From d7c6c2767961324b792a13a627203f326195f053 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 19 Feb 2024 17:47:20 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E6=B6=88=E6=81=AF=E4=BA=A4?= =?UTF-8?q?=E4=BA=92=E6=94=AF=E6=8C=81=E6=B4=97=E7=89=88=E8=AE=A2=E9=98=85?= =?UTF-8?q?=E5=8F=8A=E5=85=A8=E9=87=8F=E9=87=8D=E6=96=B0=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=20fix=20#1202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/chain/message.py | 148 +++++++++++++++++++++++++++++++------------ 1 file changed, 109 insertions(+), 39 deletions(-) diff --git a/app/chain/message.py b/app/chain/message.py index fcf0039e..8da5e404 100644 --- a/app/chain/message.py +++ b/app/chain/message.py @@ -1,7 +1,7 @@ import copy import json import re -from typing import Any, Optional, Dict +from typing import Any, Optional, Dict, Union from app.chain import ChainBase from app.chain.download import DownloadChain @@ -14,7 +14,7 @@ from app.core.event import EventManager from app.core.meta import MetaBase from app.helper.torrent import TorrentHelper from app.log import logger -from app.schemas import Notification +from app.schemas import Notification, NotExistMediaInfo from app.schemas.types import EventType, MessageChannel, MediaType from app.utils.string import StringUtils @@ -40,10 +40,47 @@ class MessageChain(ChainBase): self.downloadchain = DownloadChain() self.subscribechain = SubscribeChain() self.searchchain = SearchChain() - self.medtachain = MediaChain() + self.mediachain = MediaChain() self.eventmanager = EventManager() self.torrenthelper = TorrentHelper() + @staticmethod + def __get_noexits_info( + _meta: MetaBase, + _mediainfo: MediaInfo) -> Dict[Union[int, str], Dict[int, NotExistMediaInfo]]: + """ + 获取缺失的媒体信息 + """ + if _mediainfo.type == MediaType.TV: + _mediakey = _mediainfo.tmdb_id or _mediainfo.douban_id + _no_exists = { + _mediakey: {} + } + if _meta.begin_season: + episodes = _mediainfo.seasons.get(_meta.begin_season) + if not episodes: + return {} + _no_exists[_mediakey][_meta.begin_season] = NotExistMediaInfo( + season=_meta.begin_season, + episodes=[], + total_episode=len(episodes), + start_episode=episodes[0] + ) + else: + for sea, eps in _mediainfo.seasons.items(): + if not eps: + continue + _no_exists[_mediakey][sea] = NotExistMediaInfo( + season=sea, + episodes=[], + total_episode=len(eps), + start_episode=eps[0] + ) + else: + _no_exists = {} + + return _no_exists + def process(self, body: Any, form: Any, args: Any) -> None: """ 识别消息内容,执行操作 @@ -84,6 +121,7 @@ class MessageChain(ChainBase): ) elif text.isdigit(): + # 用户选择了具体的条目 # 缓存 cache_data: dict = user_cache.get(userid) # 选择项目 @@ -100,31 +138,44 @@ class MessageChain(ChainBase): # 缓存列表 cache_list: list = copy.deepcopy(cache_data.get('items')) # 选择 - if cache_type == "Search": + if cache_type in ["Search", "ReSearch"]: + # 当前媒体信息 mediainfo: MediaInfo = cache_list[_choice] _current_media = mediainfo # 查询缺失的媒体信息 exist_flag, no_exists = self.downloadchain.get_no_exists_info(meta=_current_meta, mediainfo=_current_media) - if exist_flag: + if exist_flag and cache_type == "Search": + # 媒体库中已存在 self.post_message( Notification(channel=channel, title=f"{_current_media.title_year}" - f"{_current_meta.sea} 媒体库中已存在", + f"{_current_meta.sea} 媒体库中已存在,如需重新下载请发送:搜索 XXX 或 下载 XXX", userid=userid)) return + elif exist_flag: + # 没有缺失,但要全量重新搜索和下载 + no_exists = self.__get_noexits_info(_current_meta, _current_media) # 发送缺失的媒体信息 - if no_exists: - # 发送消息 + messages = [] + if no_exists and cache_type == "Search": + # 发送缺失消息 mediakey = mediainfo.tmdb_id or mediainfo.douban_id messages = [ f"第 {sea} 季缺失 {StringUtils.str_series(no_exist.episodes) if no_exist.episodes else no_exist.total_episode} 集" for sea, no_exist in no_exists.get(mediakey).items()] + elif no_exists: + # 发送总集数的消息 + mediakey = mediainfo.tmdb_id or mediainfo.douban_id + messages = [ + f"第 {sea} 季总 {no_exist.total_episode} 集" + for sea, no_exist in no_exists.get(mediakey).items()] + if messages: self.post_message(Notification(channel=channel, title=f"{mediainfo.title_year}:\n" + "\n".join(messages), userid=userid)) # 搜索种子,过滤掉不需要的剧集,以便选择 - logger.info(f"{mediainfo.title_year} 媒体库中不存在,开始搜索 ...") + logger.info(f"开始搜索 {mediainfo.title_year} ...") self.post_message( Notification(channel=channel, title=f"开始搜索 {mediainfo.type.value} {mediainfo.title_year} ...", @@ -144,13 +195,16 @@ class MessageChain(ChainBase): # 判断是否设置自动下载 auto_download_user = settings.AUTO_DOWNLOAD_USER # 匹配到自动下载用户 - if auto_download_user and (auto_download_user == "all" or any(userid == user for user in auto_download_user.split(","))): - logger.info(f"用户 {userid} 在自动下载用户中,开始自动择优下载") + if auto_download_user \ + and (auto_download_user == "all" + or any(userid == user for user in auto_download_user.split(","))): + logger.info(f"用户 {userid} 在自动下载用户中,开始自动择优下载 ...") # 自动选择下载 self.__auto_download(channel=channel, cache_list=contexts, userid=userid, - username=username) + username=username, + no_exists=no_exists) else: # 更新缓存 user_cache[userid] = { @@ -165,19 +219,24 @@ class MessageChain(ChainBase): userid=userid, total=len(contexts)) - elif cache_type == "Subscribe": - # 订阅媒体 + elif cache_type in ["Subscribe", "ReSubscribe"]: + # 订阅或洗版媒体 mediainfo: MediaInfo = cache_list[_choice] + # 洗版标识 + best_version = False # 查询缺失的媒体信息 - exist_flag, _ = self.downloadchain.get_no_exists_info(meta=_current_meta, - mediainfo=mediainfo) - if exist_flag: - self.post_message(Notification( - channel=channel, - title=f"{mediainfo.title_year}" - f"{_current_meta.sea} 媒体库中已存在", - userid=userid)) - return + if cache_type == "Subscribe": + exist_flag, _ = self.downloadchain.get_no_exists_info(meta=_current_meta, + mediainfo=mediainfo) + if exist_flag: + self.post_message(Notification( + channel=channel, + title=f"{mediainfo.title_year}" + f"{_current_meta.sea} 媒体库中已存在,如需洗版请发送:洗版 XXX", + userid=userid)) + return + else: + best_version = True # 添加订阅,状态为N self.subscribechain.add(title=mediainfo.title, year=mediainfo.year, @@ -186,10 +245,11 @@ class MessageChain(ChainBase): season=_current_meta.begin_season, channel=channel, userid=userid, - username=username) + username=username, + best_version=best_version) elif cache_type == "Torrent": if int(text) == 0: - # 自动选择下载 + # 自动选择下载,强制下载模式 self.__auto_download(channel=channel, cache_list=cache_list, userid=userid, @@ -280,6 +340,14 @@ class MessageChain(ChainBase): # 订阅 content = re.sub(r"订阅[::\s]*", "", text) action = "Subscribe" + elif text.startswith("洗版"): + # 洗版 + content = re.sub(r"洗版[::\s]*", "", text) + action = "ReSubscribe" + elif text.startswith("搜索") or text.startswith("下载"): + # 重新搜索/下载 + content = re.sub(r"(搜索|下载)[::\s]*", "", text) + action = "ReSearch" elif text.startswith("#") \ or re.search(r"^请[问帮你]", text) \ or re.search(r"[??]$", text) \ @@ -290,12 +358,12 @@ class MessageChain(ChainBase): action = "chat" else: # 搜索 - content = re.sub(r"(搜索|下载)[::\s]*", "", text) + content = text action = "Search" - if action in ["Subscribe", "Search"]: + if action != "chat": # 搜索 - meta, medias = self.medtachain.search(content) + meta, medias = self.mediachain.search(content) # 识别 if not meta.name: self.post_message(Notification( @@ -334,20 +402,22 @@ class MessageChain(ChainBase): # 保存缓存 self.save_cache(user_cache, self._cache_file) - def __auto_download(self, channel, cache_list, userid, username): + def __auto_download(self, channel: MessageChannel, cache_list: list[Context], + userid: Union[str, int], username: str, + no_exists: Optional[Dict[Union[int, str], Dict[int, NotExistMediaInfo]]] = None): """ 自动择优下载 """ - # 查询缺失的媒体信息 - exist_flag, no_exists = self.downloadchain.get_no_exists_info(meta=_current_meta, - mediainfo=_current_media) - if exist_flag: - self.post_message(Notification( - channel=channel, - title=f"{_current_media.title_year}" - f"{_current_meta.sea} 媒体库中已存在", - userid=userid)) - return + if no_exists is None: + # 查询缺失的媒体信息 + exist_flag, no_exists = self.downloadchain.get_no_exists_info( + meta=_current_meta, + mediainfo=_current_media + ) + if exist_flag: + # 媒体库中已存在,查询全量 + no_exists = self.__get_noexits_info(_current_meta, _current_media) + # 批量下载 downloads, lefts = self.downloadchain.batch_download(contexts=cache_list, no_exists=no_exists,