3 Commits

8 changed files with 67 additions and 10 deletions

View File

@@ -1 +1 @@
0.4.0 0.4.5

View File

@@ -4,7 +4,7 @@ cd "$(dirname "$0")/source_clean"
VERSION=$(cat ../VERSION) VERSION=$(cat ../VERSION)
echo "🔨 Building CloudSearch v${VERSION}..." echo "🔨 Building CloudSearch v${VERSION}..."
cp ../VERSION ./VERSION
docker build -t cloudsearch-app:v${VERSION} -t cloudsearch-app:latest . docker build -t cloudsearch-app:v${VERSION} -t cloudsearch-app:latest .
echo "✅ Built: cloudsearch-app:v${VERSION} + cloudsearch-app:latest" echo "✅ Built: cloudsearch-app:v${VERSION} + cloudsearch-app:latest"

View File

@@ -1 +1 @@
0.4.0 0.4.5

11
source_clean/build.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/bin/bash
set -e
cd "$(dirname "$0")/source_clean"
VERSION=$(cat ../VERSION)
echo "🔨 Building CloudSearch v${VERSION}..."
docker build -t cloudsearch-app:v${VERSION} -t cloudsearch-app:latest .
echo "✅ Built: cloudsearch-app:v${VERSION} + cloudsearch-app:latest"
echo " Run: docker-compose up -d app"

View File

@@ -7,7 +7,10 @@ cd "$SCRIPT_DIR"
# 如果 docker-compose.yml 不存在,自动下载 # 如果 docker-compose.yml 不存在,自动下载
if [ ! -f docker-compose.yml ]; then if [ ! -f docker-compose.yml ]; then
echo "📥 下载 docker-compose.yml..." echo "📥 下载 docker-compose.yml..."
wget -q https://gitea.timxx.cn/admin/CloudSearch/raw/branch/master/source_clean/docker-compose.yml wget -q https://gitea.timxx.cn/admin/CloudSearch/raw/branch/master/source_clean/docker-compose.yml || {
echo "❌ 下载失败,请检查网络"
exit 1
}
fi fi
echo "🔍 检测 Redis..." echo "🔍 检测 Redis..."
@@ -23,11 +26,43 @@ if [ -n "$EXISTING_REDIS" ]; then
echo " ✅ 已加入 cloudsearch-net" echo " ✅ 已加入 cloudsearch-net"
fi fi
# 检测 Redis 密码 # 检测 Redis 密码 (多种来源)
REDIS_PASS=$(docker inspect "$EXISTING_REDIS" --format '{{range .Config.Cmd}}{{println .}}{{end}}' 2>/dev/null | grep -A1 'requirepass' | tail -1 || true) REDIS_PASS=""
# 方法1: 从命令行参数 --requirepass
PASS_FROM_CMD=$(docker inspect "$EXISTING_REDIS" --format '{{range .Config.Cmd}}{{println .}}{{end}}' 2>/dev/null | grep -A1 'requirepass' | tail -1 | tr -d '[:space:]' || true)
if [ -n "$PASS_FROM_CMD" ] && [ "$PASS_FROM_CMD" != "redis-server" ] && [ "$PASS_FROM_CMD" != "/etc/redis/redis.conf" ]; then
REDIS_PASS="$PASS_FROM_CMD"
echo " 🔑 从启动参数检测到 Redis 密码"
fi
# 方法2: 从 redis.conf 读取 (1Panel 常见配置方式)
if [ -z "$REDIS_PASS" ]; then
PASS_FROM_CONF=$(docker exec "$EXISTING_REDIS" cat /etc/redis/redis.conf 2>/dev/null | grep '^requirepass ' | awk '{print $2}' | tr -d '"' || true)
if [ -n "$PASS_FROM_CONF" ]; then
REDIS_PASS="$PASS_FROM_CONF"
echo " 🔑 从 redis.conf 检测到 Redis 密码"
fi
fi
# 方法3: 尝试无密码连接测试
if [ -z "$REDIS_PASS" ]; then
if docker exec "$EXISTING_REDIS" redis-cli ping 2>/dev/null | grep -q PONG; then
echo " Redis 无密码(已通过连接测试验证)"
else
# 有密码但检测不到 — 尝试从 redis-cli 的错误消息中提取
AUTH_ERR=$(docker exec "$EXISTING_REDIS" redis-cli ping 2>&1 || true)
if echo "$AUTH_ERR" | grep -q "NOAUTH\|AUTH"; then
echo " ⚠️ Redis 需要密码但无法自动检测,请手动设置 REDIS_URL"
echo " 提示: 在 .env 中设置 REDIS_URL=redis://:密码@${EXISTING_REDIS}:6379"
fi
fi
fi
if [ -n "$REDIS_PASS" ]; then if [ -n "$REDIS_PASS" ]; then
REDIS_URL="redis://:${REDIS_PASS}@${EXISTING_REDIS}:6379" # 对密码中的特殊字符进行URL编码
echo " 🔑 检测到 Redis 密码,已自动配置" ENCODED_PASS=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$REDIS_PASS', safe=''))" 2>/dev/null || echo "$REDIS_PASS")
REDIS_URL="redis://:${ENCODED_PASS}@${EXISTING_REDIS}:6379"
else else
REDIS_URL="redis://${EXISTING_REDIS}:6379" REDIS_URL="redis://${EXISTING_REDIS}:6379"
fi fi

View File

@@ -222,7 +222,8 @@ export async function testCloudConnection(id: number): Promise<{
return { success: false, message: 'Cookie not configured' }; return { success: false, message: 'Cookie not configured' };
} }
const cookie = decryptCookie(config.cookie); // config.cookie is already decrypted by getCloudConfigById
const cookie = config.cookie;
try { try {
let valid = false; let valid = false;

View File

@@ -39,6 +39,7 @@ function runMigrations(db: Database.Database): void {
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
cloud_type TEXT NOT NULL, cloud_type TEXT NOT NULL,
cookie TEXT, cookie TEXT,
cloud_type_uid TEXT DEFAULT NULL,
nickname TEXT, nickname TEXT,
is_active INTEGER NOT NULL DEFAULT 1, is_active INTEGER NOT NULL DEFAULT 1,
storage_used TEXT, storage_used TEXT,
@@ -204,6 +205,7 @@ function migrateCloudConfigs(db: Database.Database): void {
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
cloud_type TEXT NOT NULL, cloud_type TEXT NOT NULL,
cookie TEXT, cookie TEXT,
cloud_type_uid TEXT DEFAULT NULL,
nickname TEXT, nickname TEXT,
is_active INTEGER NOT NULL DEFAULT 1, is_active INTEGER NOT NULL DEFAULT 1,
storage_used TEXT, storage_used TEXT,
@@ -251,6 +253,13 @@ function migrateCloudConfigs(db: Database.Database): void {
db.exec("ALTER TABLE cloud_configs ADD COLUMN notify_config TEXT DEFAULT NULL"); db.exec("ALTER TABLE cloud_configs ADD COLUMN notify_config TEXT DEFAULT NULL");
console.log('[DB] cloud_configs migration: notify_config column added'); console.log('[DB] cloud_configs migration: notify_config column added');
} }
// Migration 6: Add cloud_type_uid column
const hasCloudTypeUid = db.prepare("SELECT sql FROM sqlite_master WHERE name='cloud_configs' AND sql LIKE '%cloud_type_uid%'").get();
if (!hasCloudTypeUid) {
db.exec("ALTER TABLE cloud_configs ADD COLUMN cloud_type_uid TEXT DEFAULT NULL");
console.log('[DB] cloud_configs migration: cloud_type_uid column added');
}
} }
} }
@@ -300,6 +309,7 @@ function seedSystemConfigs(db: Database.Database): void {
{ key: 'site_marquee', value: '📢 欢迎使用CloudSearch所有资源仅供学习交流请于下载后24小时内删除', description: '搜索栏下方滚动通知文字(从右往左滚动显示)' }, { key: 'site_marquee', value: '📢 欢迎使用CloudSearch所有资源仅供学习交流请于下载后24小时内删除', description: '搜索栏下方滚动通知文字(从右往左滚动显示)' },
{ key: 'tmdb_api_token', value: '', description: 'TMDB API 读取令牌(用于增强豆瓣内容信息)' }, { key: 'tmdb_api_token', value: '', description: 'TMDB API 读取令牌(用于增强豆瓣内容信息)' },
{ key: 'ip_geo_api_url', value: '', description: 'IP 归属地查询接口({ip} 会被替换为实际IP留空则禁用' }, { key: 'ip_geo_api_url', value: '', description: 'IP 归属地查询接口({ip} 会被替换为实际IP留空则禁用' },
{ key: 'ip_geo_api_id', value: '', description: 'IP 归属地 API IDapihz.cn 接口)' },
{ key: 'ip_geo_api_key', value: '', description: 'IP 归属地备用 API Key留空使用默认' }, { key: 'ip_geo_api_key', value: '', description: 'IP 归属地备用 API Key留空使用默认' },
{ key: 'title_filter_rules', value: '', description: '搜索结果标题过滤规则(一行一条:纯文本直接移除 / 正则用/包围/' }, { key: 'title_filter_rules', value: '', description: '搜索结果标题过滤规则(一行一条:纯文本直接移除 / 正则用/包围/' },
{ key: 'timezone', value: 'Asia/Shanghai', description: '系统时区(如 Asia/Shanghai、America/New_York、UTC' }, { key: 'timezone', value: 'Asia/Shanghai', description: '系统时区(如 Asia/Shanghai、America/New_York、UTC' },

View File

@@ -508,7 +508,7 @@ router.post('/admin/test-external-service', async (req: Request, res: Response)
break; break;
} }
case 'tmdb': { case 'tmdb': {
const tmdbToken = token || getSystemConfig('tmdb_api_key') || ''; const tmdbToken = token || getSystemConfig('tmdb_api_token') || '';
if (!tmdbToken) { if (!tmdbToken) {
res.json({ ok: false, info: 'TMDB API Key not configured' }); res.json({ ok: false, info: 'TMDB API Key not configured' });
return; return;