feat RSS订阅插件支持下载

This commit is contained in:
jxxghp 2023-08-19 18:54:26 +08:00
parent 236775d390
commit dac782098d

View File

@ -1,5 +1,6 @@
import datetime import datetime
import re import re
import time
from pathlib import Path from pathlib import Path
from threading import Lock from threading import Lock
from typing import Optional, Any, List, Dict, Tuple from typing import Optional, Any, List, Dict, Tuple
@ -12,11 +13,12 @@ from app.chain.download import DownloadChain
from app.chain.search import SearchChain from app.chain.search import SearchChain
from app.chain.subscribe import SubscribeChain from app.chain.subscribe import SubscribeChain
from app.core.config import settings from app.core.config import settings
from app.core.context import MediaInfo from app.core.context import MediaInfo, TorrentInfo, Context
from app.core.metainfo import MetaInfo from app.core.metainfo import MetaInfo
from app.helper.rss import RssHelper from app.helper.rss import RssHelper
from app.log import logger from app.log import logger
from app.plugins import _PluginBase from app.plugins import _PluginBase
from app.schemas.types import SystemConfigKey, MediaType
lock = Lock() lock = Lock()
@ -25,7 +27,7 @@ class RssSubscribe(_PluginBase):
# 插件名称 # 插件名称
plugin_name = "RSS订阅" plugin_name = "RSS订阅"
# 插件描述 # 插件描述
plugin_desc = "定时刷新RSS报文识别报文内容并自动添加订阅" plugin_desc = "定时刷新RSS报文识别内容后添加订阅或直接下载"
# 插件图标 # 插件图标
plugin_icon = "rss.png" plugin_icon = "rss.png"
# 主题色 # 主题色
@ -60,8 +62,11 @@ class RssSubscribe(_PluginBase):
_include: str = "" _include: str = ""
_exclude: str = "" _exclude: str = ""
_proxy: bool = False _proxy: bool = False
_filter: bool = False
_clear: bool = False _clear: bool = False
_clearflag: bool = False _clearflag: bool = False
_action: str = "subscribe"
_save_path: str = ""
def init_plugin(self, config: dict = None): def init_plugin(self, config: dict = None):
self.rsshelper = RssHelper() self.rsshelper = RssHelper()
@ -82,7 +87,10 @@ class RssSubscribe(_PluginBase):
self._include = config.get("include") self._include = config.get("include")
self._exclude = config.get("exclude") self._exclude = config.get("exclude")
self._proxy = config.get("proxy") self._proxy = config.get("proxy")
self._filter = config.get("filter")
self._clear = config.get("clear") self._clear = config.get("clear")
self._action = config.get("action")
self._save_path = config.get("save_path")
if self._enabled or self._onlyonce: if self._enabled or self._onlyonce:
@ -211,7 +219,8 @@ class RssSubscribe(_PluginBase):
{ {
'component': 'VCol', 'component': 'VCol',
'props': { 'props': {
'cols': 12 'cols': 12,
'md': 6
}, },
'content': [ 'content': [
{ {
@ -223,6 +232,26 @@ class RssSubscribe(_PluginBase):
} }
} }
] ]
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 6
},
'content': [
{
'component': 'VSelect',
'props': {
'model': 'action',
'label': '动作',
'items': [
{'title': '订阅', 'value': 'subscribe'},
{'title': '下载', 'value': 'download'}
]
}
}
]
} }
] ]
}, },
@ -240,7 +269,7 @@ class RssSubscribe(_PluginBase):
'props': { 'props': {
'model': 'address', 'model': 'address',
'label': 'RSS地址', 'label': 'RSS地址',
'rows': 5, 'rows': 3,
'placeholder': '每行一个RSS地址' 'placeholder': '每行一个RSS地址'
} }
} }
@ -287,6 +316,28 @@ class RssSubscribe(_PluginBase):
} }
] ]
}, },
{
'component': 'VRow',
'content': [
{
'component': 'VCol',
'props': {
'cols': 12
},
'content': [
{
'component': 'VTextField',
'props': {
'model': 'save_path',
'label': '保存目录',
'placeholder': '下载时有效,留空自动'
}
}
]
}
]
},
{ {
'component': 'VRow', 'component': 'VRow',
'content': [ 'content': [
@ -294,7 +345,7 @@ class RssSubscribe(_PluginBase):
'component': 'VCol', 'component': 'VCol',
'props': { 'props': {
'cols': 12, 'cols': 12,
'md': 6 'md': 4
}, },
'content': [ 'content': [
{ {
@ -305,12 +356,27 @@ class RssSubscribe(_PluginBase):
} }
} }
] ]
}, {
'component': 'VCol',
'props': {
'cols': 12,
'md': 4,
},
'content': [
{
'component': 'VSwitch',
'props': {
'model': 'filter',
'label': '使用过滤规则',
}
}
]
}, },
{ {
'component': 'VCol', 'component': 'VCol',
'props': { 'props': {
'cols': 12, 'cols': 12,
'md': 6 'md': 4
}, },
'content': [ 'content': [
{ {
@ -335,7 +401,10 @@ class RssSubscribe(_PluginBase):
"include": "", "include": "",
"exclude": "", "exclude": "",
"proxy": False, "proxy": False,
"clear": False "clear": False,
"filter": False,
"action": "subscribe",
"save_path": ""
} }
def get_page(self) -> List[dict]: def get_page(self) -> List[dict]:
@ -480,11 +549,17 @@ class RssSubscribe(_PluginBase):
if not results: if not results:
logger.error(f"未获取到RSS数据{url}") logger.error(f"未获取到RSS数据{url}")
return return
# 过滤规则
filter_rule = self.systemconfig.get(SystemConfigKey.FilterRules)
# 解析数据 # 解析数据
for result in results: for result in results:
try: try:
title = result.get("title") title = result.get("title")
description = result.get("description") description = result.get("description")
enclosure = result.get("enclosure")
link = result.get("link")
sise = result.get("sise")
pubdate = result.get("pubdate")
# 检查是否处理过 # 检查是否处理过
if not title or title in [h.get("key") for h in history]: if not title or title in [h.get("key") for h in history]:
continue continue
@ -506,25 +581,68 @@ class RssSubscribe(_PluginBase):
if not mediainfo: if not mediainfo:
logger.warn(f'未识别到媒体信息,标题:{title}') logger.warn(f'未识别到媒体信息,标题:{title}')
continue continue
# 种子
torrentinfo = TorrentInfo(
title=title,
description=description,
enclosure=enclosure,
page_url=link,
size=sise,
pubdate=time.strftime("%Y-%m-%d %H:%M:%S", pubdate) if pubdate else None,
)
# 过滤种子
if self._filter:
result = self.chain.filter_torrents(
rule_string=filter_rule,
torrent_list=[torrentinfo]
)
if not result:
logger.info(f"{title} {description} 不匹配过滤规则")
continue
# 查询缺失的媒体信息 # 查询缺失的媒体信息
exist_flag, no_exists = self.downloadchain.get_no_exists_info(meta=meta, mediainfo=mediainfo) exist_flag, no_exists = self.downloadchain.get_no_exists_info(meta=meta, mediainfo=mediainfo)
if exist_flag: if exist_flag:
logger.info(f'{mediainfo.title_year} 媒体库中已存在') logger.info(f'{mediainfo.title_year} 媒体库中已存在')
continue continue
else: else:
# 检查是否在订阅中 if self._action == "download":
subflag = self.subscribechain.exists(mediainfo=mediainfo, meta=meta) if mediainfo.type == MediaType.TV:
if subflag: if no_exists:
logger.info(f'{mediainfo.title_year} {meta.season} 正在订阅中') exist_info = no_exists.get(mediainfo.tmdb_id)
continue season_info = exist_info.get(meta.begin_season or 1)
# 添加订阅 if not season_info:
self.subscribechain.add(title=mediainfo.title, logger.info(f'{mediainfo.title_year} {meta.season} 己存在')
year=mediainfo.year, continue
mtype=mediainfo.type, if (season_info.episodes
tmdbid=mediainfo.tmdb_id, and not set(meta.episode_list).issubset(set(season_info.episodes))):
season=meta.begin_season, logger.info(f'{mediainfo.title_year} {meta.season_episode} 己存在')
exist_ok=True, continue
username="RSS订阅") # 添加下载
result = self.downloadchain.download_single(
context=Context(
meta_info=meta,
media_info=mediainfo,
torrent_info=torrentinfo,
),
save_path=self._save_path
)
if not result:
logger.error(f'{title} 下载失败')
continue
else:
# 检查是否在订阅中
subflag = self.subscribechain.exists(mediainfo=mediainfo, meta=meta)
if subflag:
logger.info(f'{mediainfo.title_year} {meta.season} 正在订阅中')
continue
# 添加订阅
self.subscribechain.add(title=mediainfo.title,
year=mediainfo.year,
mtype=mediainfo.type,
tmdbid=mediainfo.tmdb_id,
season=meta.begin_season,
exist_ok=True,
username="RSS订阅")
# 存储历史记录 # 存储历史记录
history.append({ history.append({
"title": f"{mediainfo.title} {meta.season}", "title": f"{mediainfo.title} {meta.season}",