mirror of
https://github.com/Cp0204/quark-auto-save.git
synced 2026-01-17 01:40:44 +08:00
新增字幕命名规则功能,支持在全局设置字幕文件的语言代码后缀
- 添加字幕文件语言代码后缀自动添加功能 - 支持 .srt/.ass/.ssa/.vtt/.sup 等常见字幕格式 - 在系统配置中提供语言代码设置和启用开关 - 覆盖所有重命名场景:预览界面、任务执行、文件整理 - 支持顺序命名、剧集命名、正则表达式命名模式 - 避免重复添加语言代码后缀 - 默认语言代码为 "zh",默认禁用状态 功能说明: - 用户可在系统配置中设置字幕文件的语言代码(如 "zh") - 启用后,所有字幕文件重命名时自动添加语言代码后缀 - 例如:`movie.srt` → `movie.zh.srt` - 支持所有命名模式和预览功能 - 向后兼容,不影响现有功能
This commit is contained in:
parent
be5773fb84
commit
1f99f66ce5
17
app/run.py
17
app/run.py
@ -44,7 +44,7 @@ from quark_auto_save import Config, format_bytes
|
|||||||
|
|
||||||
# 添加导入全局extract_episode_number和sort_file_by_name函数
|
# 添加导入全局extract_episode_number和sort_file_by_name函数
|
||||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
from quark_auto_save import extract_episode_number, sort_file_by_name, chinese_to_arabic, is_date_format
|
from quark_auto_save import extract_episode_number, sort_file_by_name, chinese_to_arabic, is_date_format, apply_subtitle_naming_rule
|
||||||
|
|
||||||
# 导入豆瓣服务
|
# 导入豆瓣服务
|
||||||
from sdk.douban_service import douban_service
|
from sdk.douban_service import douban_service
|
||||||
@ -2105,6 +2105,9 @@ def get_share_detail():
|
|||||||
else:
|
else:
|
||||||
# 替换所有的{}为当前序号
|
# 替换所有的{}为当前序号
|
||||||
file["file_name_re"] = sequence_pattern.replace("{}", f"{current_sequence:02d}") + file_ext
|
file["file_name_re"] = sequence_pattern.replace("{}", f"{current_sequence:02d}") + file_ext
|
||||||
|
|
||||||
|
# 应用字幕命名规则
|
||||||
|
file["file_name_re"] = apply_subtitle_naming_rule(file["file_name_re"], config_data["task_settings"])
|
||||||
current_sequence += 1
|
current_sequence += 1
|
||||||
|
|
||||||
return share_detail
|
return share_detail
|
||||||
@ -2143,6 +2146,8 @@ def get_share_detail():
|
|||||||
|
|
||||||
if episode_num is not None:
|
if episode_num is not None:
|
||||||
file["file_name_re"] = episode_pattern.replace("[]", f"{episode_num:02d}") + extension
|
file["file_name_re"] = episode_pattern.replace("[]", f"{episode_num:02d}") + extension
|
||||||
|
# 应用字幕命名规则
|
||||||
|
file["file_name_re"] = apply_subtitle_naming_rule(file["file_name_re"], config_data["task_settings"])
|
||||||
# 添加episode_number字段用于前端排序
|
# 添加episode_number字段用于前端排序
|
||||||
file["episode_number"] = episode_num
|
file["episode_number"] = episode_num
|
||||||
else:
|
else:
|
||||||
@ -2177,6 +2182,8 @@ def get_share_detail():
|
|||||||
item["file_name_re"] = (
|
item["file_name_re"] = (
|
||||||
re.sub(pattern, replace, file_name) if replace != "" else file_name
|
re.sub(pattern, replace, file_name) if replace != "" else file_name
|
||||||
)
|
)
|
||||||
|
# 应用字幕命名规则
|
||||||
|
item["file_name_re"] = apply_subtitle_naming_rule(item["file_name_re"], config_data["task_settings"])
|
||||||
return share_detail
|
return share_detail
|
||||||
|
|
||||||
share_detail = preview_regex(share_detail)
|
share_detail = preview_regex(share_detail)
|
||||||
@ -3383,6 +3390,8 @@ def preview_rename():
|
|||||||
for file in filtered_files:
|
for file in filtered_files:
|
||||||
extension = os.path.splitext(file["file_name"])[1] if not file["dir"] else ""
|
extension = os.path.splitext(file["file_name"])[1] if not file["dir"] else ""
|
||||||
new_name = pattern.replace("{}", f"{sequence:02d}") + extension
|
new_name = pattern.replace("{}", f"{sequence:02d}") + extension
|
||||||
|
# 应用字幕命名规则
|
||||||
|
new_name = apply_subtitle_naming_rule(new_name, config_data["task_settings"])
|
||||||
preview_results.append({
|
preview_results.append({
|
||||||
"original_name": file["file_name"],
|
"original_name": file["file_name"],
|
||||||
"new_name": new_name,
|
"new_name": new_name,
|
||||||
@ -3420,6 +3429,8 @@ def preview_rename():
|
|||||||
|
|
||||||
if episode_num is not None:
|
if episode_num is not None:
|
||||||
new_name = pattern.replace("[]", f"{episode_num:02d}") + extension
|
new_name = pattern.replace("[]", f"{episode_num:02d}") + extension
|
||||||
|
# 应用字幕命名规则
|
||||||
|
new_name = apply_subtitle_naming_rule(new_name, config_data["task_settings"])
|
||||||
preview_results.append({
|
preview_results.append({
|
||||||
"original_name": file["file_name"],
|
"original_name": file["file_name"],
|
||||||
"new_name": new_name,
|
"new_name": new_name,
|
||||||
@ -3439,10 +3450,14 @@ def preview_rename():
|
|||||||
# 应用正则表达式
|
# 应用正则表达式
|
||||||
if replace:
|
if replace:
|
||||||
new_name = re.sub(pattern, replace, file["file_name"])
|
new_name = re.sub(pattern, replace, file["file_name"])
|
||||||
|
# 应用字幕命名规则
|
||||||
|
new_name = apply_subtitle_naming_rule(new_name, config_data["task_settings"])
|
||||||
else:
|
else:
|
||||||
# 如果没有提供替换表达式,则检查是否匹配
|
# 如果没有提供替换表达式,则检查是否匹配
|
||||||
if re.search(pattern, file["file_name"]):
|
if re.search(pattern, file["file_name"]):
|
||||||
new_name = file["file_name"] # 匹配但不替换
|
new_name = file["file_name"] # 匹配但不替换
|
||||||
|
# 应用字幕命名规则
|
||||||
|
new_name = apply_subtitle_naming_rule(new_name, config_data["task_settings"])
|
||||||
else:
|
else:
|
||||||
new_name = "" # 表示不匹配
|
new_name = "" # 表示不匹配
|
||||||
|
|
||||||
|
|||||||
@ -788,6 +788,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">字幕命名规则</span>
|
||||||
|
</div>
|
||||||
|
<input type="text" class="form-control" v-model="formData.task_settings.subtitle_naming_rule" placeholder="zh" title="设置字幕文件的语言代码,在重命名字幕文件时会在文件名末尾添加此代码">
|
||||||
|
<div class="input-group-append" title="启用后,重命名字幕文件时会在文件名末尾添加语言代码后缀">
|
||||||
|
<div class="input-group-text">
|
||||||
|
<input type="checkbox" v-model="formData.task_settings.subtitle_add_language_code"> 添加语言代码
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
@ -2831,7 +2845,9 @@
|
|||||||
movie_naming_pattern: "^(.*)\\.([^.]+)",
|
movie_naming_pattern: "^(.*)\\.([^.]+)",
|
||||||
movie_naming_replace: "片名 (年份).\\2",
|
movie_naming_replace: "片名 (年份).\\2",
|
||||||
tv_naming_rule: "剧名 - S季数E[]",
|
tv_naming_rule: "剧名 - S季数E[]",
|
||||||
tv_ignore_extension: true
|
tv_ignore_extension: true,
|
||||||
|
subtitle_naming_rule: "zh",
|
||||||
|
subtitle_add_language_code: false
|
||||||
},
|
},
|
||||||
source: {
|
source: {
|
||||||
cloudsaver: {
|
cloudsaver: {
|
||||||
@ -6935,6 +6951,8 @@
|
|||||||
movie_naming_replace: "片名 (年份).\\2",
|
movie_naming_replace: "片名 (年份).\\2",
|
||||||
tv_naming_rule: "剧名 - S季数E[]",
|
tv_naming_rule: "剧名 - S季数E[]",
|
||||||
tv_ignore_extension: true,
|
tv_ignore_extension: true,
|
||||||
|
subtitle_naming_rule: "zh",
|
||||||
|
subtitle_add_language_code: false,
|
||||||
auto_search_resources: "enabled"
|
auto_search_resources: "enabled"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1083,7 +1083,7 @@ def get_file_icon(file_name, is_dir=False):
|
|||||||
return "📝"
|
return "📝"
|
||||||
|
|
||||||
# 字幕文件
|
# 字幕文件
|
||||||
if any(lower_name.endswith(ext) for ext in ['.srt', '.ass', '.ssa', '.vtt']):
|
if any(lower_name.endswith(ext) for ext in ['.srt', '.ass', '.ssa', '.vtt', '.sup']):
|
||||||
return "💬"
|
return "💬"
|
||||||
|
|
||||||
# 歌词文件
|
# 歌词文件
|
||||||
@ -1108,6 +1108,54 @@ def remove_file_icons(filename):
|
|||||||
|
|
||||||
return clean_name
|
return clean_name
|
||||||
|
|
||||||
|
# 定义一个函数来检测字幕文件并应用语言代码后缀
|
||||||
|
def apply_subtitle_naming_rule(filename, task_settings):
|
||||||
|
"""
|
||||||
|
检测字幕文件并应用语言代码后缀
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filename: 原始文件名
|
||||||
|
task_settings: 任务设置,包含字幕命名规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的文件名
|
||||||
|
"""
|
||||||
|
# 从任务设置中获取字幕命名规则配置
|
||||||
|
subtitle_add_language_code = task_settings.get("subtitle_add_language_code", False)
|
||||||
|
subtitle_naming_rule = task_settings.get("subtitle_naming_rule", "zh")
|
||||||
|
|
||||||
|
# 如果任务设置中没有配置,尝试从全局配置中获取
|
||||||
|
if not subtitle_add_language_code:
|
||||||
|
try:
|
||||||
|
if 'CONFIG_DATA' in globals() and CONFIG_DATA:
|
||||||
|
global_task_settings = CONFIG_DATA.get("task_settings", {})
|
||||||
|
subtitle_add_language_code = global_task_settings.get("subtitle_add_language_code", False)
|
||||||
|
subtitle_naming_rule = global_task_settings.get("subtitle_naming_rule", "zh")
|
||||||
|
except (KeyError, AttributeError, TypeError):
|
||||||
|
# 配置获取失败,使用默认值
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 检查是否启用了字幕命名规则
|
||||||
|
if not subtitle_add_language_code or not subtitle_naming_rule:
|
||||||
|
return filename
|
||||||
|
|
||||||
|
# 检测是否为字幕文件
|
||||||
|
lower_name = filename.lower()
|
||||||
|
subtitle_extensions = ['.srt', '.ass', '.ssa', '.vtt', '.sup']
|
||||||
|
|
||||||
|
if not any(lower_name.endswith(ext) for ext in subtitle_extensions):
|
||||||
|
return filename
|
||||||
|
|
||||||
|
# 分离文件名和扩展名
|
||||||
|
name_without_ext, ext = os.path.splitext(filename)
|
||||||
|
|
||||||
|
# 检查是否已经包含语言代码后缀,避免重复添加
|
||||||
|
if f".{subtitle_naming_rule}" in name_without_ext:
|
||||||
|
return filename
|
||||||
|
|
||||||
|
# 添加语言代码后缀
|
||||||
|
return f"{name_without_ext}.{subtitle_naming_rule}{ext}"
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
# 下载配置
|
# 下载配置
|
||||||
@ -2561,6 +2609,9 @@ class Quark:
|
|||||||
# 生成新文件名
|
# 生成新文件名
|
||||||
save_name = sequence_pattern.replace("{}", f"{current_sequence:02d}") + file_ext
|
save_name = sequence_pattern.replace("{}", f"{current_sequence:02d}") + file_ext
|
||||||
|
|
||||||
|
# 应用字幕命名规则
|
||||||
|
save_name = apply_subtitle_naming_rule(save_name, task)
|
||||||
|
|
||||||
# 检查目标目录是否已存在此文件,支持忽略后缀选项
|
# 检查目标目录是否已存在此文件,支持忽略后缀选项
|
||||||
if task.get("ignore_extension", False):
|
if task.get("ignore_extension", False):
|
||||||
# 忽略后缀模式:只比较文件名部分,不比较扩展名
|
# 忽略后缀模式:只比较文件名部分,不比较扩展名
|
||||||
@ -2764,6 +2815,9 @@ class Quark:
|
|||||||
else:
|
else:
|
||||||
target_name = episode_pattern.replace("[]", f"{episode_num:02d}") + file_ext
|
target_name = episode_pattern.replace("[]", f"{episode_num:02d}") + file_ext
|
||||||
|
|
||||||
|
# 应用字幕命名规则
|
||||||
|
target_name = apply_subtitle_naming_rule(target_name, task)
|
||||||
|
|
||||||
# 检查目标文件名是否已存在,支持忽略后缀选项
|
# 检查目标文件名是否已存在,支持忽略后缀选项
|
||||||
if task.get("ignore_extension", False):
|
if task.get("ignore_extension", False):
|
||||||
# 忽略后缀模式:只比较文件名部分,不比较扩展名
|
# 忽略后缀模式:只比较文件名部分,不比较扩展名
|
||||||
@ -2904,6 +2958,8 @@ class Quark:
|
|||||||
# 尝试应用正则替换
|
# 尝试应用正则替换
|
||||||
if re.search(pattern, original_file_name):
|
if re.search(pattern, original_file_name):
|
||||||
renamed_file = re.sub(pattern, replace, original_file_name)
|
renamed_file = re.sub(pattern, replace, original_file_name)
|
||||||
|
# 应用字幕命名规则
|
||||||
|
renamed_file = apply_subtitle_naming_rule(renamed_file, task)
|
||||||
renamed_base = os.path.splitext(renamed_file)[0]
|
renamed_base = os.path.splitext(renamed_file)[0]
|
||||||
else:
|
else:
|
||||||
renamed_file = None
|
renamed_file = None
|
||||||
@ -3058,6 +3114,9 @@ class Quark:
|
|||||||
else share_file["file_name"]
|
else share_file["file_name"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 应用字幕命名规则
|
||||||
|
save_name = apply_subtitle_naming_rule(save_name, task)
|
||||||
|
|
||||||
# 检查新名称是否存在重复的前缀
|
# 检查新名称是否存在重复的前缀
|
||||||
if replace and " - " in save_name:
|
if replace and " - " in save_name:
|
||||||
parts = save_name.split(" - ")
|
parts = save_name.split(" - ")
|
||||||
@ -3509,6 +3568,9 @@ class Quark:
|
|||||||
else:
|
else:
|
||||||
save_name = sequence_pattern.replace("{}", f"{current_sequence:02d}") + file_ext
|
save_name = sequence_pattern.replace("{}", f"{current_sequence:02d}") + file_ext
|
||||||
|
|
||||||
|
# 应用字幕命名规则
|
||||||
|
save_name = apply_subtitle_naming_rule(save_name, task)
|
||||||
|
|
||||||
# 检查是否需要重命名,支持忽略后缀选项
|
# 检查是否需要重命名,支持忽略后缀选项
|
||||||
name_conflict = False
|
name_conflict = False
|
||||||
if task.get("ignore_extension", False):
|
if task.get("ignore_extension", False):
|
||||||
@ -3701,6 +3763,8 @@ class Quark:
|
|||||||
new_name = f"{episode_num:02d}{file_ext}"
|
new_name = f"{episode_num:02d}{file_ext}"
|
||||||
else:
|
else:
|
||||||
new_name = episode_pattern.replace("[]", f"{episode_num:02d}") + file_ext
|
new_name = episode_pattern.replace("[]", f"{episode_num:02d}") + file_ext
|
||||||
|
# 应用字幕命名规则
|
||||||
|
new_name = apply_subtitle_naming_rule(new_name, task)
|
||||||
else:
|
else:
|
||||||
new_name = None
|
new_name = None
|
||||||
|
|
||||||
@ -3775,6 +3839,9 @@ class Quark:
|
|||||||
else:
|
else:
|
||||||
save_name = episode_pattern.replace("[]", f"{episode_num:02d}") + file_ext
|
save_name = episode_pattern.replace("[]", f"{episode_num:02d}") + file_ext
|
||||||
|
|
||||||
|
# 应用字幕命名规则
|
||||||
|
save_name = apply_subtitle_naming_rule(save_name, task)
|
||||||
|
|
||||||
# 检查过滤词
|
# 检查过滤词
|
||||||
should_filter = False
|
should_filter = False
|
||||||
if task.get("filterwords"):
|
if task.get("filterwords"):
|
||||||
@ -3987,12 +4054,16 @@ class Quark:
|
|||||||
# 使用完整的剧集号识别逻辑,而不是简单的纯数字判断
|
# 使用完整的剧集号识别逻辑,而不是简单的纯数字判断
|
||||||
# 生成新文件名
|
# 生成新文件名
|
||||||
new_name = f"{episode_num:02d}{file_ext}"
|
new_name = f"{episode_num:02d}{file_ext}"
|
||||||
|
# 应用字幕命名规则
|
||||||
|
new_name = apply_subtitle_naming_rule(new_name, task)
|
||||||
# 只有当当前文件名与目标文件名不同时才重命名
|
# 只有当当前文件名与目标文件名不同时才重命名
|
||||||
if dir_file["file_name"] != new_name:
|
if dir_file["file_name"] != new_name:
|
||||||
rename_operations.append((dir_file, new_name, episode_num))
|
rename_operations.append((dir_file, new_name, episode_num))
|
||||||
else:
|
else:
|
||||||
# 生成目标文件名
|
# 生成目标文件名
|
||||||
new_name = episode_pattern.replace("[]", f"{episode_num:02d}") + file_ext
|
new_name = episode_pattern.replace("[]", f"{episode_num:02d}") + file_ext
|
||||||
|
# 应用字幕命名规则
|
||||||
|
new_name = apply_subtitle_naming_rule(new_name, task)
|
||||||
# 检查文件名是否已经符合目标格式
|
# 检查文件名是否已经符合目标格式
|
||||||
if dir_file["file_name"] != new_name:
|
if dir_file["file_name"] != new_name:
|
||||||
rename_operations.append((dir_file, new_name, episode_num))
|
rename_operations.append((dir_file, new_name, episode_num))
|
||||||
@ -4140,6 +4211,9 @@ class Quark:
|
|||||||
# 应用正则表达式获取目标文件名
|
# 应用正则表达式获取目标文件名
|
||||||
new_name = re.sub(pattern, replace, orig_name)
|
new_name = re.sub(pattern, replace, orig_name)
|
||||||
|
|
||||||
|
# 应用字幕命名规则
|
||||||
|
new_name = apply_subtitle_naming_rule(new_name, task)
|
||||||
|
|
||||||
# 如果替换后的文件名没有变化,跳过
|
# 如果替换后的文件名没有变化,跳过
|
||||||
if new_name == orig_name:
|
if new_name == orig_name:
|
||||||
continue
|
continue
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user