优化智能填充和搜索功能,规范日志输出

Merge pull request #19 from x1ao4/dev
This commit is contained in:
x1ao4 2025-05-20 17:17:59 +08:00 committed by GitHub
commit cbb0e03db9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 393 additions and 81 deletions

View File

@ -263,6 +263,40 @@ def get_task_suggestions():
return jsonify({"success": False, "message": "未登录"})
query = request.args.get("q", "").lower()
deep = request.args.get("d", "").lower()
# 提取剧名,去除季数信息
def extract_show_name(task_name):
# 清理任务名称中的连续空格和特殊符号
clean_name = task_name.replace('\u3000', ' ').replace('\t', ' ')
clean_name = re.sub(r'\s+', ' ', clean_name).strip()
# 匹配常见的季数格式
# 例如:黑镜 - S07、人生若如初见 - S01、折腰.S01、音你而来-S02、快乐的大人 S02
season_patterns = [
r'^(.*?)[\s\.\-_]+S\d+$', # 黑镜 - S07、折腰.S01、音你而来-S02
r'^(.*?)[\s\.\-_]+Season\s*\d+$', # 黑镜 - Season 1
r'^(.*?)\s+S\d+$', # 快乐的大人 S02
r'^(.*?)[\s\.\-_]+S\d+E\d+$', # 处理 S01E01 格式
r'^(.*?)\s+第\s*\d+\s*季$', # 处理 第N季 格式
r'^(.*?)[\s\.\-_]+第\s*\d+\s*季$', # 处理 - 第N季 格式
r'^(.*?)\s+第[一二三四五六七八九十零]+季$', # 处理 第一季、第二季 格式
r'^(.*?)[\s\.\-_]+第[一二三四五六七八九十零]+季$', # 处理 - 第一季、- 第二季 格式
]
for pattern in season_patterns:
match = re.match(pattern, clean_name, re.IGNORECASE)
if match:
show_name = match.group(1).strip()
# 去除末尾可能残留的分隔符
show_name = re.sub(r'[\s\.\-_]+$', '', show_name)
return show_name
# 如果没有匹配到季数格式,返回原名称
return clean_name
# 处理搜索关键词,提取剧名
search_query = extract_show_name(query)
try:
cs_data = config_data.get("source", {}).get("cloudsaver", {})
if (
@ -276,23 +310,34 @@ def get_task_suggestions():
cs_data.get("password", ""),
cs_data.get("token", ""),
)
search = cs.auto_login_search(query)
# 使用处理后的搜索关键词
search = cs.auto_login_search(search_query)
if search.get("success"):
if search.get("new_token"):
cs_data["token"] = search.get("new_token")
Config.write_json(CONFIG_PATH, config_data)
search_results = cs.clean_search_results(search.get("data"))
# 在返回结果中添加实际使用的搜索关键词
return jsonify(
{"success": True, "source": "CloudSaver", "data": search_results}
{
"success": True,
"source": "CloudSaver",
"data": search_results
}
)
else:
return jsonify({"success": True, "message": search.get("message")})
else:
base_url = base64.b64decode("aHR0cHM6Ly9zLjkxNzc4OC54eXo=").decode()
url = f"{base_url}/task_suggestions?q={query}&d={deep}"
# 使用处理后的搜索关键词
url = f"{base_url}/task_suggestions?q={search_query}&d={deep}"
response = requests.get(url)
return jsonify(
{"success": True, "source": "网络公开", "data": response.json()}
{
"success": True,
"source": "网络公开",
"data": response.json()
}
)
except Exception as e:
return jsonify({"success": True, "message": f"error: {str(e)}"})

View File

@ -2137,6 +2137,12 @@ div.jsoneditor-tree button.jsoneditor-button:focus {
top: 0.5px; /* 向下微调 */
}
.bottom-links .nav-link .bi-wechat {
font-size: 1rem;
position: relative;
top: -0.5px; /* 向上微调 */
}
.bottom-links .nav-link .nav-text {
font-size: 0.85rem;
}

View File

@ -192,6 +192,12 @@
<span class="nav-text"><span v-html="versionTips"></span></span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://github.com/x1ao4/quark-auto-save-x/wiki/赞赏与交流群" target="_blank">
<i class="bi bi-wechat"></i>
<span class="nav-text">WeChat Group</span>
</a>
</li>
</ul>
</div>
</div>
@ -483,7 +489,9 @@
</span>
<span v-else>正在搜索中...</span>
</div>
<div class="dropdown-item text-muted" v-else style="font-size:14px; padding-left: 8px; text-align: left;">{{ smart_param.taskSuggestions.message ? smart_param.taskSuggestions.message : smart_param.taskSuggestions.data && smart_param.taskSuggestions.data.length ? `以下资源由 ${smart_param.taskSuggestions.source} 搜索提供(仅显示有效链接),如有侵权请联系资源发布方` : "未搜索到有效资源" }}</div>
<div class="dropdown-item text-muted" v-else style="font-size:14px; padding-left: 8px; text-align: left;">
{{ smart_param.taskSuggestions.message ? smart_param.taskSuggestions.message : smart_param.taskSuggestions.data && smart_param.taskSuggestions.data.length ? `以下资源由 ${smart_param.taskSuggestions.source} 搜索提供(仅显示有效链接),如有侵权请联系资源发布方` : "未搜索到有效资源" }}
</div>
<div v-for="suggestion in smart_param.taskSuggestions.data || []" :key="suggestion.taskname" class="dropdown-item cursor-pointer" @click.prevent="selectSuggestion(index, suggestion)" style="font-size: 14px;" :title="suggestion.content">
<span v-html="suggestion.verify ? '✅': ''"></span> {{ suggestion.taskname }}
<small class="text-muted">
@ -497,7 +505,7 @@
<i v-else class="bi bi-search"></i>
</button>
<div class="input-group-text" title="谷歌搜索">
<a target="_blank" :href="`https://www.google.com/search?q=%22pan.quark.cn/s%22+${task.taskname}`"><i class="bi bi-google"></i></a>
<a target="_blank" :href="`https://www.google.com/search?q=%22pan.quark.cn/s%22+${cleanTaskNameForSearch(task.taskname)}`"><i class="bi bi-google"></i></a>
</div>
<div class="input-group-text" title="TMDB搜索">
<a target="_blank" :href="`https://www.themoviedb.org/search?query=${cleanTaskNameForSearch(task.taskname)}`"><img src="./static/TMDB.svg" class="tmdb-icon"></a>
@ -1280,14 +1288,14 @@
formatShareUrlBanMessage(message) {
if (!message) return message;
if (message.includes("分享者用户封禁链接查看受限")) {
if (message.includes("分享者用户封禁链接查看受限") ||
message.includes("文件涉及违规内容") ||
message.includes("分享地址已失效")) {
return "该分享已失效,不可访问";
} else if (message.includes("好友已取消了分享")) {
return "该分享已被取消,无法访问";
} else if (message.includes("文件已被分享者删除") || message === "文件已被分享者删除或文件夹为空") {
return "该分享已被删除,无法访问";
} else if (message.includes("分享地址已失效")) {
return "该分享已失效,不可访问";
}
return message;
@ -1340,12 +1348,39 @@
},
cleanTaskNameForSearch(taskName) {
if (!taskName) return '';
// 移除 Sxx 格式(包括 S01、S01E01 等)
let cleanedName = taskName.replace(/\s*[-—_]\s*S\d+(\w\d+)?/i, '');
// 清理任务名称中的连续空格和特殊符号
let cleanedName = taskName.replace(/\u3000/g, ' ').replace(/\t/g, ' ');
cleanedName = cleanedName.replace(/\s+/g, ' ').trim();
// 匹配常见的季数格式
const seasonPatterns = [
/^(.*?)[\s\.\-_]+S\d+$/i, // 黑镜 - S07、折腰.S01、音你而来-S02
/^(.*?)[\s\.\-_]+Season\s*\d+$/i, // 黑镜 - Season 1
/^(.*?)\s+S\d+$/i, // 快乐的大人 S02
/^(.*?)[\s\.\-_]+S\d+E\d+$/i, // 处理 S01E01 格式
/^(.*?)\s+第\s*\d+\s*季$/i, // 处理 第N季 格式
/^(.*?)[\s\.\-_]+第\s*\d+\s*季$/i, // 处理 - 第N季 格式
/^(.*?)\s+第[一二三四五六七八九十零]+季$/i, // 处理 第一季、第二季 格式
/^(.*?)[\s\.\-_]+第[一二三四五六七八九十零]+季$/i, // 处理 - 第一季、- 第二季 格式
];
for (const pattern of seasonPatterns) {
const match = cleanedName.match(pattern);
if (match) {
let showName = match[1].trim();
// 去除末尾可能残留的分隔符
showName = showName.replace(/[\s\.\-_]+$/, '');
return encodeURIComponent(showName);
}
}
// 如果没有匹配到季数格式,执行原有的清理逻辑
// 移除孤立的特殊符号
cleanedName = cleanedName.replace(/\s*[-—_]\s*$/, '');
// 移除开头和结尾的特殊符号
cleanedName = cleanedName.trim().replace(/^[-—_\s]+|[-—_\s]+$/g, '');
return encodeURIComponent(cleanedName);
},
changeTab(tab) {
@ -1529,7 +1564,22 @@
addTask() {
if (!this.formData.tasklist)
this.formData.tasklist = [];
newTask = { ...this.newTask }
let newTask = { ...this.newTask };
// 如果有上一个任务,继承保存路径和命名规则
if (this.formData.tasklist.length > 0) {
const lastTask = this.formData.tasklist[this.formData.tasklist.length - 1];
newTask.savepath = lastTask.savepath || "";
newTask.pattern = lastTask.pattern || "";
// 继承命名规则选择模式
newTask.use_sequence_naming = lastTask.use_sequence_naming || false;
newTask.use_episode_naming = lastTask.use_episode_naming || false;
newTask.sequence_naming = lastTask.sequence_naming || "";
newTask.episode_naming = lastTask.episode_naming || "";
newTask.replace = lastTask.replace || "";
}
this.formData.tasklist.push(newTask)
const index = this.formData.tasklist.length - 1;
@ -1573,8 +1623,217 @@
this.smart_param.searchTimer = setTimeout(() => {
this.searchSuggestions(index, task.taskname, 0);
}, 1000);
if (this.smart_param.savepath)
task.savepath = this.smart_param.savepath.replace('TASKNAME', task.taskname);
// 清理任务名称中的连续空格和特殊符号
const cleanTaskName = task.taskname.replace(/\s+/g, ' ').trim();
// 提取任务名称中的分隔符格式
// 使用与cleanTaskNameForSearch相同的季数格式匹配模式
let showName, seasonNumber, nameSeparator = ' - '; // 默认分隔符
let isTVShow = false; // 标记是否为电视节目
let separatorMatch = null;
// 匹配常见的季数格式
const seasonPatterns = [
/^(.*?)([\s\.\-_]+)S(\d+)$/i, // 黑镜 - S07、折腰.S01、音你而来-S02
/^(.*?)([\s\.\-_]+)Season\s*(\d+)$/i, // 黑镜 - Season 1
/^(.*?)(\s+)S(\d+)$/i, // 快乐的大人 S02
/^(.*?)([\s\.\-_]+)S(\d+)E\d+$/i, // 处理 S01E01 格式
/^(.*?)(\s+)第\s*(\d+)\s*季$/i, // 处理 第N季 格式
/^(.*?)([\s\.\-_]+)第\s*(\d+)\s*季$/i, // 处理 - 第N季 格式
/^(.*?)(\s+)第([一二三四五六七八九十零]+)季$/i, // 处理 第一季、第二季 格式
/^(.*?)([\s\.\-_]+)第([一二三四五六七八九十零]+)季$/i, // 处理 - 第一季、- 第二季 格式
];
// 尝试匹配各种格式
for (const pattern of seasonPatterns) {
const match = cleanTaskName.match(pattern);
if (match) {
separatorMatch = match;
// 根据不同的格式,确定季序号的位置
if (match[3] && match[3].match(/[一二三四五六七八九十零]/)) {
// 将中文数字转换为阿拉伯数字
const chineseToNumber = {
'零': '0', '一': '1', '二': '2', '三': '3', '四': '4',
'五': '5', '六': '6', '七': '7', '八': '8', '九': '9', '十': '10'
};
seasonNumber = chineseToNumber[match[3]] || '01';
} else {
seasonNumber = match[3] || '01';
}
break;
}
}
// 判断保存路径是否包含电视节目相关的关键词
if (task.savepath) {
const tvKeywords = ["电视", "节目", "剧", "动漫", "动画", "番", "综艺", "真人秀", "TV", "Tv", "tv", "Series", "series", "Show", "show"];
isTVShow = tvKeywords.some(keyword => task.savepath.includes(keyword));
}
// 当任务名称包含季信息或保存路径有电视剧关键词时,按电视节目处理
const hasSeason = separatorMatch !== null;
isTVShow = isTVShow || hasSeason;
if (separatorMatch) {
// 提取剧名(去除末尾空格和特殊符号)
showName = separatorMatch[1].trim().replace(/[\s\.\-_]+$/, '');
// 季序号已在上面的循环中提取
// 提取实际使用的分隔符
const rawSeparator = separatorMatch[2];
// 处理特殊情况:如果是"黑镜 - 第五季"这种格式,需要保留完整的" - "分隔符
// 检查原始字符串中剧名后面的分隔符
const fullSeparator = cleanTaskName.substring(showName.length, cleanTaskName.length - (separatorMatch[3] ? separatorMatch[3].length + 1 : 0)).match(/^([\s\.\-_]+)/);
if (fullSeparator && fullSeparator[1]) {
// 使用完整的分隔符
nameSeparator = fullSeparator[1];
} else {
// 规范化分隔符(如果是连续的空格,转为单个空格)
nameSeparator = rawSeparator.replace(/\s+/g, ' ');
// 如果只有一个点号,保留点号
if (rawSeparator === '.') {
nameSeparator = '.';
}
// 如果是单个空格,保留单个空格
else if (rawSeparator === ' ') {
nameSeparator = ' ';
}
}
// 其他情况保持原样
} else {
// 如果没有匹配到季序号格式默认使用整个任务名作为剧名季序号为01
showName = cleanTaskName;
seasonNumber = '01';
}
// 更新保存路径 - 无论是否使用智能路径,都确保倒数第二级目录更新
if (task.savepath) {
// 分割保存路径为各级目录
const pathParts = task.savepath.split('/');
if (pathParts.length >= 2) {
// 如果智能路径已设置,使用原有逻辑更新最后一级
if (this.smart_param.savepath) {
// 更新最后一级目录,但保留前面的路径结构
const newPath = this.smart_param.savepath.replace('TASKNAME', task.taskname);
const newPathParts = newPath.split('/');
pathParts[pathParts.length - 1] = newPathParts[newPathParts.length - 1];
} else {
// 根据是否为电视节目决定处理方式
if (isTVShow) {
// 电视节目格式:剧名 + 分隔符 + S季序号
pathParts[pathParts.length - 1] = showName + nameSeparator + 'S' + seasonNumber.padStart(2, '0');
} else {
// 非电视节目直接使用任务名称
pathParts[pathParts.length - 1] = cleanTaskName;
}
}
// 处理倒数第二级目录(剧名+年份)- 无论是否使用智能路径,都更新
if (pathParts.length >= 3 && isTVShow) {
// 只有电视节目才更新倒数第二级目录
const parentDir = pathParts[pathParts.length - 2];
// 提取年份信息
const yearMatch = parentDir.match(/\((\d{4})\)|\(\d{4})\|[\s\-_]+(\d{4})(?:[\s\-_]+|$)/);
const year = yearMatch ? (yearMatch[1] || yearMatch[2] || yearMatch[3] || '2025') : '2025';
// 重建倒数第二级目录,使用新的剧名和原有的年份
pathParts[pathParts.length - 2] = showName + ' (' + year + ')';
}
// 更新保存路径
task.savepath = pathParts.join('/');
}
}
// 额外处理:检查保存路径最末级是否包含中文季序号,如果包含则转换为标准格式
if (task.savepath) {
const pathParts = task.savepath.split('/');
if (pathParts.length > 0) {
const lastPart = pathParts[pathParts.length - 1];
// 匹配中文季序号格式
const chineseSeasonMatch = lastPart.match(/^(.*?)([\s\.\-_]+)第([一二三四五六七八九十零]+)季$/);
if (chineseSeasonMatch) {
const showName = chineseSeasonMatch[1].trim();
const separator = chineseSeasonMatch[2];
const chineseSeason = chineseSeasonMatch[3];
// 将中文数字转换为阿拉伯数字
const chineseToNumber = {
'零': '0', '一': '1', '二': '2', '三': '3', '四': '4',
'五': '5', '六': '6', '七': '7', '八': '8', '九': '9', '十': '10'
};
const seasonNumber = chineseToNumber[chineseSeason] || '1';
// 更新最末级目录为标准格式
pathParts[pathParts.length - 1] = showName + separator + 'S' + seasonNumber.padStart(2, '0');
task.savepath = pathParts.join('/');
}
// 匹配阿拉伯数字季序号格式
const arabicSeasonMatch = lastPart.match(/^(.*?)([\s\.\-_]+)第(\d+)季$/);
if (arabicSeasonMatch) {
const showName = arabicSeasonMatch[1].trim();
const separator = arabicSeasonMatch[2];
const seasonNumber = arabicSeasonMatch[3];
// 更新最末级目录为标准格式
pathParts[pathParts.length - 1] = showName + separator + 'S' + seasonNumber.padStart(2, '0');
task.savepath = pathParts.join('/');
}
}
}
// 更新命名规则 - 始终使用当前任务名称中的信息
if (task.pattern) {
// 根据是否为电视节目决定处理方式
if (isTVShow) {
// 处理剧集命名模式
if (task.use_episode_naming) {
// 直接使用任务名称中提取的信息构建命名规则
task.pattern = showName + nameSeparator + 'S' + seasonNumber.padStart(2, '0') + 'E[]';
task.episode_naming = task.pattern;
}
// 处理顺序命名模式
else if (task.use_sequence_naming) {
// 直接使用任务名称中提取的信息构建命名规则
task.pattern = showName + nameSeparator + 'S' + seasonNumber.padStart(2, '0') + 'E{}';
task.sequence_naming = task.pattern;
}
} else {
// 非电视节目,仅在使用剧集或顺序命名时更新
if (task.use_episode_naming) {
// 如果原模式是纯E[],直接使用任务名称
if (task.pattern.trim() === 'E[]') {
task.pattern = cleanTaskName + 'E[]';
} else if (task.pattern.includes('[]')) {
// 尝试保留原有格式,但更新剧名部分
const patternParts = task.pattern.split(/E\[\]/i);
if (patternParts.length > 0) {
task.pattern = cleanTaskName + 'E[]' + (patternParts[1] || '');
} else {
task.pattern = cleanTaskName + 'E[]';
}
}
task.episode_naming = task.pattern;
} else if (task.use_sequence_naming) {
// 同样处理顺序命名
if (task.pattern.trim() === 'E{}' || task.pattern.trim() === '{}') {
task.pattern = cleanTaskName + 'E{}';
} else if (task.pattern.includes('{}')) {
const patternParts = task.pattern.split(/E\{\}/i);
if (patternParts.length > 0) {
task.pattern = cleanTaskName + 'E{}' + (patternParts[1] || '');
} else {
task.pattern = cleanTaskName + 'E{}';
}
}
task.sequence_naming = task.pattern;
}
}
}
},
removeTask(index) {
if (confirm("确认删除任务 [#" + (index + 1) + ": " + this.formData.tasklist[index].taskname + "] 吗?"))
@ -1776,7 +2035,8 @@
"好友已取消了分享",
"文件已被分享者删除",
"文件夹为空",
"分享地址已失效"
"分享地址已失效",
"文件涉及违规内容"
];
// 如果没有搜索结果,直接返回

View File

@ -52,13 +52,13 @@ class Alist:
response = response.json()
if response.get("code") == 200:
print(
f"Alist刷新: {response.get('data',[])[1].get('value','')} {response.get('data',[])[0].get('value','')}"
f"AList 刷新: {response.get('data',[])[1].get('value','')} {response.get('data',[])[0].get('value','')}"
)
return True
else:
print(f"Alist刷新: 连接失败{response.get('message')}")
print(f"AList 刷新: 连接失败 {response.get('message')}")
except requests.exceptions.RequestException as e:
print(f"获取Alist信息出错: {e}")
print(f"获取 AList 信息出错: {e}")
return False
def storage_id_to_path(self, storage_id):
@ -69,7 +69,7 @@ class Alist:
storage_mount_path, quark_root_dir = match.group(1), match.group(2)
file_list = self.get_file_list(storage_mount_path)
if file_list.get("code") != 200:
print(f"Alist刷新: 获取挂载路径失败{file_list.get('message')}")
print(f"AList 刷新: 获取挂载路径失败 {file_list.get('message')}")
return False, (None, None)
# 2. 检查是否数字,调用 Alist API 获取存储信息
elif re.match(r"^\d+$", storage_id):
@ -84,12 +84,12 @@ class Alist:
)
elif storage_info["driver"] == "QuarkTV":
print(
f"Alist刷新: [QuarkTV]驱动⚠️ storage_id请手动填入 /Alist挂载路径:/Quark目录路径"
f"AList 刷新: [QuarkTV] 驱动 ⚠️ storage_id 请手动填入 /Alist挂载路径:/Quark目录路径"
)
else:
print(f"Alist刷新: 不支持[{storage_info['driver']}]驱动 ❌")
print(f"AList 刷新: 不支持 [{storage_info['driver']}] 驱动 ❌")
else:
print(f"Alist刷新: storage_id[{storage_id}]格式错误")
print(f"AList 刷新: storage_id [{storage_id}] 格式错误 ")
# 返回结果
if storage_mount_path and quark_root_dir:
return True, (storage_mount_path, quark_root_dir)
@ -107,28 +107,28 @@ class Alist:
if data.get("code") == 200:
return data.get("data", [])
else:
print(f"Alist刷新: 存储{storage_id}连接失败{data.get('message')}")
print(f"AList 刷新: 存储 {storage_id} 连接失败 {data.get('message')}")
except Exception as e:
print(f"Alist刷新: 获取Alist存储出错 {e}")
print(f"AList 刷新: 获取 AList 存储出错 {e}")
return []
def refresh(self, path):
data = self.get_file_list(path, True)
if data.get("code") == 200:
print(f"📁 Alist刷新目录[{path}] 成功")
print(f"📁 AList 刷新: 目录 [{path}] 成功 ")
return data.get("data")
elif "object not found" in data.get("message", ""):
# 如果是根目录就不再往上查找
if path == "/" or path == self.storage_mount_path:
print(f"📁 Alist刷新根目录不存在请检查 Alist 配置")
print(f"📁 AList 刷新: 根目录不存在,请检查 AList 配置")
return False
# 获取父目录
parent_path = os.path.dirname(path)
print(f"📁 Alist刷新[{path}] 不存在,转父目录 [{parent_path}]")
print(f"📁 AList 刷新: [{path}] 不存在,转父目录 [{parent_path}]")
# 递归刷新父目录
return self.refresh(parent_path)
else:
print(f"📁 Alist刷新失败{data.get('message')}")
print(f"📁 AList 刷新: 失败 {data.get('message')}")
def get_file_list(self, path, force_refresh=False):
url = f"{self.url}/api/fs/list"
@ -145,7 +145,7 @@ class Alist:
response.raise_for_status()
return response.json()
except Exception as e:
print(f"📁 Alist刷新: 获取文件列表出错{e}")
print(f"📁 AList 刷新: 获取文件列表出错 {e}")
return {}
def get_root_folder_full_path(self, cookie, pdir_fid):
@ -178,5 +178,5 @@ class Alist:
path = f"{path}/{item['file_name']}"
return path
except Exception as e:
print(f"Alist刷新: 获取Quark路径出错 {e}")
print(f"AList 刷新: 获取 Quark 路径出错 {e}")
return ""

View File

@ -2,7 +2,7 @@ import re
import requests
"""
配合 alist-strm 项目触发特定配置运行
配合 Alist-Strm 项目触发特定配置运行
https://github.com/tefuirZ/alist-strm
"""
@ -47,12 +47,12 @@ class Alist_strm:
for item in matchs
if item[0] in config_id_str.split(",")
]
print(f"alist-strm配置运行: {config_name}")
print(f"Alist-Strm 配置运行: {config_name}")
return True
else:
print(f"alist-strm配置运行: 匹配失败❌,请检查网络连通和cookie有效性")
print(f"Alist-Strm 配置运行: 匹配失败 ❌ 请检查网络连通和cookie有效性")
except Exception as e:
print(f"获取alist-strm配置信息出错: {e}")
print(f"获取 Alist-Strm 配置信息出错: {e}")
return False
def run_selected_configs(self, selected_configs_str):
@ -61,7 +61,7 @@ class Alist_strm:
try:
selected_configs = [int(x.strip()) for x in selected_configs_str.split(",")]
except ValueError:
print("🔗 alist-strm配置运行: 出错❌ id应以,分割")
print("🔗 Alist-Strm 配置运行: 出错 ❌ ID 应以 , 分割")
return False
data = [("selected_configs", config_id) for config_id in selected_configs]
data.append(("action", "run_selected"))
@ -73,10 +73,10 @@ class Alist_strm:
match = re.search(r'role="alert">\s*([^<]+)\s*<button', html_content)
if match:
alert = match.group(1).strip()
print(f"🔗 alist-strm配置运行: {alert}")
print(f"🔗 Alist-Strm 配置运行: {alert} ")
return True
else:
print(f"🔗 alist-strm配置运行: 失败")
print(f"🔗 Alist-Strm 配置运行: 失败 ")
except Exception as e:
print(f"Error: {e}")
return False

View File

@ -82,7 +82,7 @@ class Alist_strm_gen:
storage_mount_path, quark_root_dir = match.group(1), match.group(2)
file_list = self.get_file_list(storage_mount_path)
if file_list.get("code") != 200:
print(f"Alist-Strm生成: 获取挂载路径失败❌ {file_list.get('message')}")
print(f"Alist-Strm 生成: 获取挂载路径失败 {file_list.get('message')}")
return False, (None, None)
# 2. 检查是否数字,调用 Alist API 获取存储信息
elif re.match(r"^\d+$", storage_id):
@ -97,15 +97,15 @@ class Alist_strm_gen:
)
elif storage_info["driver"] == "QuarkTV":
print(
f"Alist-Strm生成: [QuarkTV]驱动⚠️ storage_id请手动填入 /Alist挂载路径:/Quark目录路径"
f"Alist-Strm 生成: [QuarkTV] 驱动 ⚠️ storage_id 请手动填入 /Alist挂载路径:/Quark目录路径"
)
else:
print(f"Alist-Strm生成: 不支持[{storage_info['driver']}]驱动 ❌")
print(f"Alist-Strm 生成: 不支持 [{storage_info['driver']}] 驱动 ❌")
else:
print(f"Alist-Strm生成: storage_id[{storage_id}]格式错误❌")
print(f"Alist-Strm 生成: storage_id [{storage_id}] 格式错误❌")
# 返回结果
if storage_mount_path and quark_root_dir:
print(f"Alist-Strm生成: [{storage_mount_path}:{quark_root_dir}]")
print(f"Alist-Strm 生成: [{storage_mount_path}:{quark_root_dir}]")
return True, (storage_mount_path, quark_root_dir)
else:
return False, (None, None)
@ -121,15 +121,15 @@ class Alist_strm_gen:
if data.get("code") == 200:
return data.get("data", [])
else:
print(f"Alist-Strm生成: 获取存储失败❌ {data.get('message')}")
print(f"Alist-Strm 生成: 获取存储失败 {data.get('message')}")
except Exception as e:
print(f"Alist-Strm生成: 获取存储出错 {e}")
print(f"Alist-Strm 生成: 获取存储出错 {e}")
return []
def check_dir(self, path):
data = self.get_file_list(path)
if data.get("code") != 200:
print(f"📺 Alist-Strm生成: 获取文件列表失败❌{data.get('message')}")
print(f"📺 Alist-Strm 生成: 获取文件列表失败 {data.get('message')}")
return
elif files := data.get("data", {}).get("content"):
for item in files:
@ -154,7 +154,7 @@ class Alist_strm_gen:
response.raise_for_status()
return response.json()
except Exception as e:
print(f"📺 Alist-Strm生成: 获取文件列表出错❌ {e}")
print(f"📺 Alist-Strm 生成: 获取文件列表出错 {e}")
return {}
def generate_strm(self, file_path):
@ -171,7 +171,7 @@ class Alist_strm_gen:
os.makedirs(os.path.dirname(strm_path))
with open(strm_path, "w", encoding="utf-8") as strm_file:
strm_file.write(f"{self.strm_server}{file_path}")
print(f"📺 生成STRM文件 {strm_path} 成功")
print(f"📺 生成 STRM 文件 {strm_path} 成功 ")
def get_root_folder_full_path(self, cookie, pdir_fid):
if pdir_fid == "0":
@ -203,5 +203,5 @@ class Alist_strm_gen:
path = f"{path}/{item['file_name']}"
return path
except Exception as e:
print(f"Alist-Strm生成: 获取Quark路径出错 {e}")
print(f"Alist-Strm 生成: 获取 Quark 路径出错 {e}")
return ""

View File

@ -174,7 +174,7 @@ class Aria2:
# print(f"📥 Aria2下载: {file_path} (已存在,跳过)")
continue
print(f"📥 Aria2下载: {file_path}")
print(f"📥 Aria2 下载: {file_path}")
# 确保目录存在
os.makedirs(os.path.dirname(local_path), exist_ok=True)
@ -194,7 +194,7 @@ class Aria2:
try:
self.add_uri(aria2_params)
except Exception as e:
print(f"📥 Aria2添加下载任务失败: {e}")
print(f"📥 Aria2 添加下载任务失败: {e}")
def _make_rpc_request(self, method, params=None):
"""发出 JSON-RPC 请求."""
@ -211,17 +211,17 @@ class Aria2:
response.raise_for_status()
return response.json()
except Exception as e:
print(f"Aria2下载: 错误{e}")
print(f"Aria2 下载: 错误{e}")
return {}
def get_version(self):
"""检查与 Aria2 的连接."""
response = self._make_rpc_request("aria2.getVersion")
if response.get("result"):
print(f"Aria2下载: v{response['result']['version']}")
print(f"Aria2 下载: v{response['result']['version']}")
return True
else:
print(f"Aria2下载: 连接失败{response.get('error')}")
print(f"Aria2 下载: 连接失败{response.get('error')}")
return False
def add_uri(self, params=None):

View File

@ -48,13 +48,13 @@ class Emby:
if "application/json" in response.headers["Content-Type"]:
response = response.json()
print(
f"Emby媒体库: {response.get('ServerName','')} v{response.get('Version','')}"
f"Emby 媒体库: {response.get('ServerName','')} v{response.get('Version','')}"
)
return True
else:
print(f"Emby媒体库: 连接失败❌ {response.text}")
print(f"Emby 媒体库: 连接失败 {response.text}")
except Exception as e:
print(f"获取Emby媒体库信息出错: {e}")
print(f"获取 Emby 媒体库信息出错: {e}")
return False
def refresh(self, emby_id):
@ -74,12 +74,12 @@ class Emby:
"POST", url, headers=headers, params=querystring
)
if response.text == "":
print(f"🎞️ 刷新Emby媒体库成功")
print(f"🎞️ 刷新 Emby 媒体库: 成功 ")
return True
else:
print(f"🎞️ 刷新Emby媒体库{response.text}")
print(f"🎞️ 刷新 Emby 媒体库: {response.text} ")
except Exception as e:
print(f"刷新Emby媒体库出错: {e}")
print(f"刷新 Emby 媒体库出错: {e}")
return False
def search(self, media_name):
@ -106,11 +106,11 @@ class Emby:
for item in response["Items"]:
if item["IsFolder"]:
print(
f"🎞️ 《{item['Name']}》匹配到Emby媒体库ID{item['Id']}"
f"🎞️ 《{item['Name']}》匹配到 Emby 媒体库 ID: {item['Id']}"
)
return item["Id"]
else:
print(f"🎞️ 搜索Emby媒体库{response.text}")
print(f"🎞️ 搜索 Emby 媒体库: {response.text}")
except Exception as e:
print(f"搜索Emby媒体库出错: {e}")
print(f"搜索 Emby 媒体库出错: {e}")
return ""

View File

@ -42,13 +42,13 @@ class Plex:
if response.status_code == 200:
info = response.json()["MediaContainer"]
print(
f"Plex媒体库: {info.get('friendlyName','')} v{info.get('version','')}"
f"Plex 媒体库: {info.get('friendlyName','')} v{info.get('version','')}"
)
return True
else:
print(f"Plex媒体库: 连接失败❌ 状态码:{response.status_code}")
print(f"Plex 媒体库: 连接失败 ❌ 状态码: {response.status_code}")
except Exception as e:
print(f"获取Plex媒体库信息出错: {e}")
print(f"获取 Plex 媒体库信息出错: {e}")
return False
def refresh(self, folder_path):
@ -67,16 +67,16 @@ class Plex:
refresh_response = requests.get(refresh_url, headers=headers)
if refresh_response.status_code == 200:
print(
f"🎞️ 刷新Plex媒体库{library['title']} [{folder_path}] 成功"
f"🎞️ 刷新 Plex 媒体库: {library['title']} [{folder_path}] 成功 "
)
return True
else:
print(
f"🎞️ 刷新Plex媒体库刷新请求失败❌ 状态码:{refresh_response.status_code}"
f"🎞️ 刷新 Plex 媒体库: 刷新请求失败 ❌ 状态码: {refresh_response.status_code}"
)
print(f"🎞️ 刷新Plex媒体库{folder_path} 未找到匹配的媒体库")
print(f"🎞️ 刷新 Plex 媒体库: {folder_path} 未找到匹配的媒体库 ")
except Exception as e:
print(f"刷新Plex媒体库出错: {e}")
print(f"刷新 Plex 媒体库出错: {e}")
return False
def _get_libraries(self):
@ -89,7 +89,7 @@ class Plex:
libraries = response.json()["MediaContainer"].get("Directory", [])
return libraries
else:
print(f"🎞️ 获取Plex媒体库信息失败❌ 状态码:{response.status_code}")
print(f"🎞️ 获取 Plex 媒体库信息失败 ❌ 状态码: {response.status_code}")
except Exception as e:
print(f"获取Plex媒体库信息出错: {e}")
print(f"获取 Plex 媒体库信息出错: {e}")
return []

View File

@ -1048,9 +1048,10 @@ class Quark:
dir_paths_exist_arr.append(
{"file_path": dir_path, "fid": new_dir["fid"]}
)
print(f"创建文件夹:{dir_path}")
# print(f"创建文件夹:{dir_path}")
else:
print(f"创建文件夹:{dir_path} 失败, {mkdir_return['message']}")
# print(f"创建文件夹:{dir_path} 失败, {mkdir_return['message']}")
pass
# 储存目标目录的fid
for dir_path in dir_paths_exist_arr:
self.savepath_fid[dir_path["file_path"]] = dir_path["fid"]
@ -3001,17 +3002,17 @@ class Quark:
def verify_account(account):
# 验证账号
print(f"▶️ 验证第{account.index}个账号")
print(f"▶️ 验证第 {account.index} 个账号")
if "__uid" not in account.cookie:
print(f"💡 不存在cookie必要参数判断为仅签到")
print(f"💡 不存在 cookie 必要参数,判断为仅签到")
return False
else:
account_info = account.init()
if not account_info:
add_notify(f"👤 第{account.index}个账号登录失败cookie无效❌")
add_notify(f"👤 第 {account.index} 个账号登录失败cookie 无效 ")
return False
else:
print(f"👤 账号昵称: {account_info['nickname']}")
print(f"👤 账号昵称: {account_info['nickname']} ")
return True
@ -3021,7 +3022,7 @@ def format_bytes(size_bytes: int) -> str:
while size_bytes >= 1024 and i < len(units) - 1:
size_bytes /= 1024
i += 1
return f"{size_bytes:.2f} {units[i]}"
return f"{size_bytes:.2f}{units[i]}"
def do_sign(account):
@ -3032,15 +3033,15 @@ def do_sign(account):
# 每日领空间
growth_info = account.get_growth_info()
if growth_info:
growth_message = f"💾 {'88VIP' if growth_info['88VIP'] else '普通用户'} 总空间:{format_bytes(growth_info['total_capacity'])},签到累计获得{format_bytes(growth_info['cap_composition'].get('sign_reward', 0))}"
growth_message = f"💾 {'88VIP' if growth_info['88VIP'] else '普通用户'}: 总空间 {format_bytes(growth_info['total_capacity'])},签到累计获得 {format_bytes(growth_info['cap_composition'].get('sign_reward', 0))}"
if growth_info["cap_sign"]["sign_daily"]:
sign_message = f"📅 签到记录: 今日已签到+{int(growth_info['cap_sign']['sign_daily_reward']/1024/1024)}MB连签进度({growth_info['cap_sign']['sign_progress']}/{growth_info['cap_sign']['sign_target']})"
sign_message = f"📅 签到记录: 今日已签到 +{int(growth_info['cap_sign']['sign_daily_reward']/1024/1024)}MB连签进度{growth_info['cap_sign']['sign_progress']}/{growth_info['cap_sign']['sign_target']}"
message = f"{sign_message}\n{growth_message}"
print(message)
else:
sign, sign_return = account.get_growth_sign()
if sign:
sign_message = f"📅 执行签到: 今日签到+{int(sign_return/1024/1024)}MB连签进度({growth_info['cap_sign']['sign_progress']+1}/{growth_info['cap_sign']['sign_target']})"
sign_message = f"📅 执行签到: 今日签到 +{int(sign_return/1024/1024)}MB连签进度{growth_info['cap_sign']['sign_progress']+1}/{growth_info['cap_sign']['sign_target']}"
message = f"{sign_message}\n{growth_message}"
if (
str(