Fix #347: 支持自定义分类和tag

This commit is contained in:
zuijin
2024-07-31 04:11:39 +08:00
committed by Yuukiy
parent 31bbb9a7a0
commit bd6f621e27
6 changed files with 72 additions and 22 deletions
+1
View File
@@ -133,3 +133,4 @@ ver_hook.py
*.cache.json
.idea
.vscode
+2 -16
View File
@@ -263,32 +263,18 @@ def info_summary(movie: Movie, all_info: Dict[str, MovieInfo]):
movie.info = final_info
return True
def generate_names(movie: Movie):
"""按照模板生成相关文件的文件名"""
info = movie.info
# 准备用来填充命名模板的字典
d = {}
d['num'] = info.dvdid or info.cid
d['title'] = info.title or cfg.NamingRule.null_for_title
d['rawtitle'] = info.ori_title or d['title']
d = info.get_info_dic(cfg)
if info.actress and len(info.actress) > cfg.NamingRule.max_actress_count:
logging.debug('女优人数过多,按配置保留了其中的前n个: ' + ','.join(info.actress))
actress = info.actress[:cfg.NamingRule.max_actress_count] + ['…']
else:
actress = info.actress
d['actress'] = ','.join(actress) if actress else cfg.NamingRule.null_for_actress
d['score'] = info.score or '0'
d['censor'] = cfg.NamingRule.censorship_names[info.uncensored]
d['serial'] = info.serial or cfg.NamingRule.null_for_serial
d['director'] = info.director or cfg.NamingRule.null_for_director
d['producer'] = info.producer or cfg.NamingRule.null_for_producer
d['publisher'] = info.publisher or cfg.NamingRule.null_for_publisher
d['date'] = info.publish_date or '0000-00-00'
d['year'] = d['date'].split('-')[0]
# cid中不会出现'-',可以直接从d['num']拆分出label
num_items = d['num'].split('-')
d['label'] = num_items[0] if len(num_items) > 1 else '---'
# 保存label供后面判断裁剪图片的方式使用
setattr(info, 'label', d['label'].upper())
# 处理字段:替换不能作为文件名的字符,移除首尾的空字符
+9 -1
View File
@@ -133,10 +133,18 @@ claude_key =
groq_key =
[NFO]
# 同时将genre写入到tag?
# 同时将genre写入到tag? (这个选项可以通过新选项 add_custom_tags_rule = $genre 来代替了)
add_genre_to_tag = yes
# 是否开启艺名固定。如果允许,对于存在多个艺名的女优,会固定使用一个艺名
fix_actress_name = yes
# 是否添加自定义分类
add_custom_genres = no
# 自定义分类规则,多个用逗号隔开,可以使用变量
add_custom_genres_rule =
# 是否添加自定义tag
add_custom_tags = no
# 自定义tag规则,多个用逗号隔开,可以使用变量
add_custom_tags_rule = $genre,$censor
[Other]
# 是否允许检查更新。如果允许,在有新版本时会显示提示信息和新版功能
+8
View File
@@ -213,6 +213,7 @@ class Config(configparser.ConfigParser):
check_proxy_free_url(self)
validate_media_servers(self)
validate_ai_config(self)
convert_nfo_config(self)
def is_url(url: str):
@@ -266,6 +267,8 @@ def norm_boolean(cfg: Config):
('Picture', 'use_ai_crop'),
('Picture', 'add_label_to_cover'),
('NFO', 'add_genre_to_tag'),
('NFO', 'add_custom_tags'),
('NFO', 'add_custom_genres'),
('Other', 'check_update'),
('Other', 'auto_update'),
('File', 'enable_file_move'),
@@ -395,6 +398,11 @@ def check_proxy_free_url(cfg: Config):
url = 'http://' + url
sec[site] = url if is_url(url) else ''
def convert_nfo_config(cfg: Config):
"""NFO: 转换为字符串Template"""
cfg.NFO.add_custom_tags_rule = Template(cfg.NFO.add_custom_tags_rule)
cfg.NFO.add_custom_genres_rule = Template(cfg.NFO.add_custom_genres_rule)
def parse_args():
"""解析从命令行传入的参数并进行有效性验证"""
+25 -1
View File
@@ -8,6 +8,7 @@ import logging
from functools import cached_property
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from core.config import Config
from core.lib import mei_path, detect_special_attr
@@ -98,6 +99,29 @@ class MovieInfo:
if k in attrs:
self.__setattr__(k, v)
def get_info_dic(self, cfg: Config):
"""生成用来填充模板的字典"""
info = self
d = {}
d['num'] = info.dvdid or info.cid
d['title'] = info.title or cfg.NamingRule.null_for_title
d['rawtitle'] = info.ori_title or d['title']
d['actress'] = ','.join(info.actress) if info.actress else cfg.NamingRule.null_for_actress
d['score'] = info.score or '0'
d['censor'] = cfg.NamingRule.censorship_names[info.uncensored]
d['serial'] = info.serial or cfg.NamingRule.null_for_serial
d['director'] = info.director or cfg.NamingRule.null_for_director
d['producer'] = info.producer or cfg.NamingRule.null_for_producer
d['publisher'] = info.publisher or cfg.NamingRule.null_for_publisher
d['date'] = info.publish_date or '0000-00-00'
d['year'] = d['date'].split('-')[0]
# cid中不会出现'-',可以直接从d['num']拆分出label
num_items = d['num'].split('-')
d['label'] = num_items[0] if len(num_items) > 1 else '---'
d['genre'] = ','.join(info.genre_norm if info.genre_norm else info.genre if info.genre else [])
return d
class Movie:
"""用于关联影片文件的类"""
@@ -110,7 +134,7 @@ class Movie:
self.cid = cid # DMM Content ID
self.files = [] # 关联到此番号的所有影片文件的列表(用于管理带有多个分片的影片)
self.data_src = 'normal' # 数据源:不同的数据源将使用不同的爬虫
self.info = None # 抓取到的影片信息
self.info: MovieInfo = None # 抓取到的影片信息
self.save_dir = None # 存放影片、封面、NFO的文件夹路径
self.basename = None # 按照命名模板生成的不包含路径和扩展名的basename
self.nfo_file = None # nfo文件的路径
+27 -4
View File
@@ -14,6 +14,8 @@ def write_nfo(info: MovieInfo, nfo_file):
"""将存储了影片信息的'info'写入到nfo文件中"""
# NFO spec: https://kodi.wiki/view/NFO_files/Movies
nfo = E.movie()
dic = info.get_info_dic(cfg)
if info.nfo_title:
nfo.append(E.title(info.nfo_title))
else:
@@ -53,16 +55,37 @@ def write_nfo(info: MovieInfo, nfo_file):
nfo.append(E.uniqueid(info.cid, type='cid'))
# 选择要写入的genre数据源字段:将[]作为后备结果,以确保genre结果为None时后续不会抛出异常
for genre in (info.genre_norm, info.genre, []):
if genre:
for genre_item in (info.genre_norm, info.genre, []):
if genre_item:
break
genre = genre_item.copy()
# 添加自定义分类
if cfg.NFO.add_custom_genres:
custom_genres = cfg.NFO.add_custom_genres_rule.substitute(**dic)
if custom_genres:
genre += custom_genres.split(',')
# 分类去重
genre = list(set(genre))
# 写入genre分类:优先使用genre_norm。在Jellyfin上,只有genre可以直接跳转,tag不可以
# 也同时写入tag。TODO: 还没有研究tag和genre在Kodi上的区别
for i in genre:
nfo.append(E.genre(i))
tags = []
# 将genre写入到tag
if cfg.NFO.add_genre_to_tag:
for i in genre:
nfo.append(E.tag(i))
tags += genre_item
# 添加自定义tag
if cfg.NFO.add_custom_tags:
custom_tags = cfg.NFO.add_custom_tags_rule.substitute(**dic)
if custom_tags:
tags += custom_tags.split(',')
# 去重
tags = list(set(tags))
# 写入tag
for i in tags:
nfo.append(E.tag(i))
# Kodi上的country字段没说必须使用国家的代码(比如JP),所以目前暂定直接使用国家名
nfo.append(E.country('日本'))