mirror of
https://github.com/d0zingcat/MoviePilot-Plugins.git
synced 2026-05-14 07:26:51 +00:00
Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -485,6 +485,7 @@
|
||||
"author": "DzAvril",
|
||||
"level": 1,
|
||||
"history": {
|
||||
"v2.1": "联动删除历史记录",
|
||||
"v2.0": "联动删除种子,需安装插件[下载器助手]并打开监听源文件事件",
|
||||
"v1.9": "增加清理刮削文件功能(beta)",
|
||||
"v1.8": "增加清理空目录功能(beta)",
|
||||
@@ -610,11 +611,12 @@
|
||||
"name": "下载器助手",
|
||||
"description": "自动做种、站点标签、自动删种。",
|
||||
"labels": "下载管理",
|
||||
"version": "1.6",
|
||||
"version": "1.7",
|
||||
"icon": "DownloaderHelper.png",
|
||||
"author": "hotlcc",
|
||||
"level": 2,
|
||||
"history": {
|
||||
"v1.7": "优化了表单界面和一些逻辑。",
|
||||
"v1.6": "修复事件触发tr打标问题;表单界面优化。"
|
||||
}
|
||||
},
|
||||
@@ -686,8 +688,8 @@
|
||||
}
|
||||
},
|
||||
"MPServerStatus": {
|
||||
"name": "MoviePilot服务器状态",
|
||||
"description": "在仪表板中实时显示MoviePilot公共服务器状态(https://movie-pilot.org)",
|
||||
"name": "MoviePilot服务器监控",
|
||||
"description": "在仪表板中实时显示MoviePilot公共服务器状态。",
|
||||
"labels": "工具",
|
||||
"version": "1.0",
|
||||
"icon": "Duplicati_A.png",
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|定时执行周期|插件定时服务的cron表达式,仅支持5位的,缺省时不注册定时服务。|
|
||||
|排除种子标签|多个标签通过英文逗号分割,具备配置的任意标签的种子不会进行自动做种、站点标签、自动删种操作。|
|
||||
|站点标签前缀|站点标签的前缀,缺省时不添加前缀。|
|
||||
|配置Tracker映射|该开关无实际业务意义,仅用于触发展开配置Tracker映射窗口。|
|
||||
|Tracker映射|站点标签的原理是根据tracker的域名去匹配站点,但是有的PT站的tracker域名和站点域名不一致,导致匹配不到站点,因此需要对这些特殊站点的tracker做映射;每行一个映射,格式是 `tracker域名:站点域名`,tracker域名可以是完整域名或者主域名。|
|
||||
|
||||
##### 2.1.2、下载器子任务配置项
|
||||
|
||||
@@ -19,7 +19,7 @@ from app.log import logger
|
||||
from app.modules.qbittorrent.qbittorrent import Qbittorrent
|
||||
from app.modules.transmission.transmission import Transmission
|
||||
from app.plugins import _PluginBase
|
||||
from app.plugins.downloaderhelper.module import TaskContext, TaskResult
|
||||
from app.plugins.downloaderhelper.module import TaskContext, TaskResult, Downloader
|
||||
from app.schemas.types import EventType
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
@@ -32,7 +32,7 @@ class DownloaderHelper(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "DownloaderHelper.png"
|
||||
# 插件版本
|
||||
plugin_version = "1.6"
|
||||
plugin_version = "1.7"
|
||||
# 插件作者
|
||||
plugin_author = "hotlcc"
|
||||
# 作者主页
|
||||
@@ -168,7 +168,82 @@ class DownloaderHelper(_PluginBase):
|
||||
}
|
||||
# 合并默认配置
|
||||
config_suggest.update(self.__config_default)
|
||||
|
||||
# 下载器tabs
|
||||
downloader_tabs = [{
|
||||
'component': 'VTab',
|
||||
'props': {
|
||||
'value': d.id
|
||||
},
|
||||
'text': d.name_
|
||||
} for d in Downloader if d]
|
||||
# 下载器tab items
|
||||
downloader_tab_items = [{
|
||||
'component': 'VWindowItem',
|
||||
'props': {
|
||||
'value': d.id
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VRow',
|
||||
'content': [{
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12,
|
||||
'xxl': 3, 'xl': 3, 'lg': 3, 'md': 3, 'sm': 6, 'xs': 12
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VSwitch',
|
||||
'props': {
|
||||
'model': f'{d.short_id}_enable',
|
||||
'label': '任务开关',
|
||||
'hint': '该下载器子任务的开关'
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12,
|
||||
'xxl': 3, 'xl': 3, 'lg': 3, 'md': 3, 'sm': 6, 'xs': 12
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VSwitch',
|
||||
'props': {
|
||||
'model': f'{d.short_id}_enable_seeding',
|
||||
'label': '自动做种',
|
||||
'hint': '是否开启自动做种功能'
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12,
|
||||
'xxl': 3, 'xl': 3, 'lg': 3, 'md': 3, 'sm': 6, 'xs': 12
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VSwitch',
|
||||
'props': {
|
||||
'model': f'{d.short_id}_enable_tagging',
|
||||
'label': '站点标签',
|
||||
'hint': '是否开启站点标签功能'
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12,
|
||||
'xxl': 3, 'xl': 3, 'lg': 3, 'md': 3, 'sm': 6, 'xs': 12
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VSwitch',
|
||||
'props': {
|
||||
'model': f'{d.short_id}_enable_delete',
|
||||
'label': '自动删种',
|
||||
'hint': '是否开启自动删种功能'
|
||||
}
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
} for d in Downloader if d]
|
||||
# 返回form
|
||||
return [{
|
||||
'component': 'VForm',
|
||||
'content': [{ # 业务无关总控
|
||||
@@ -313,174 +388,83 @@ class DownloaderHelper(_PluginBase):
|
||||
'content': [{
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12
|
||||
'cols': 12,
|
||||
'xxl': 4, 'xl': 4, 'lg': 4, 'md': 4, 'sm': 6, 'xs': 12
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VTextarea',
|
||||
'component': 'VSwitch',
|
||||
'props': {
|
||||
'model': 'tracker_mappings',
|
||||
'label': 'Tracker映射',
|
||||
'placeholder': '格式:\n'
|
||||
'<tracker-domain>:<site-domain>\n\n'
|
||||
'例如:\n'
|
||||
'chdbits.xyz:ptchdbits.co',
|
||||
'hint': 'Tracker映射。用于在站点打标签时,指定tracker和站点域名不同的种子的域名对应关系;前面为tracker域名(完整域名或者主域名皆可),中间是英文冒号,后面是站点域名。'
|
||||
'model': '_config_tracker_mappings_dialog_closed',
|
||||
'label': '配置Tracker映射',
|
||||
'hint': '点击展开Tracker映射配置窗口。'
|
||||
}
|
||||
}]
|
||||
}]
|
||||
}, {
|
||||
'component': 'VTabs',
|
||||
'component': 'VDialog',
|
||||
'props': {
|
||||
'model': '_tabs',
|
||||
'height': 72,
|
||||
'style': {
|
||||
'margin-top': '20px',
|
||||
'margin-bottom': '20px'
|
||||
}
|
||||
'model': '_config_tracker_mappings_dialog_closed',
|
||||
'max-width': '60rem'
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VTab',
|
||||
'component': 'VCard',
|
||||
'props': {
|
||||
'value': 'qbittorrent'
|
||||
},
|
||||
'text': 'qbittorrent'
|
||||
}, {
|
||||
'component': 'VTab',
|
||||
'props': {
|
||||
'value': 'transmission'
|
||||
},
|
||||
'text': 'transmission'
|
||||
}]
|
||||
}, {
|
||||
'component': 'VWindow',
|
||||
'props': {
|
||||
'model': '_tabs'
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VWindowItem',
|
||||
'props': {
|
||||
'value': 'qbittorrent'
|
||||
'title': '配置Tracker映射',
|
||||
'style': {
|
||||
'padding': '0 20px 20px 20px'
|
||||
}
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VDialogCloseBtn',
|
||||
'props': {
|
||||
'model': '_config_tracker_mappings_dialog_closed'
|
||||
}
|
||||
}, {
|
||||
'component': 'VRow',
|
||||
'content': [{
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12,
|
||||
'xxl': 3, 'xl': 3, 'lg': 3, 'md': 3, 'sm': 6, 'xs': 12
|
||||
'cols': 12
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VSwitch',
|
||||
'component': 'VTextarea',
|
||||
'props': {
|
||||
'model': 'qb_enable',
|
||||
'label': '任务开关',
|
||||
'hint': '该下载器子任务的开关'
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12,
|
||||
'xxl': 3, 'xl': 3, 'lg': 3, 'md': 3, 'sm': 6, 'xs': 12
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VSwitch',
|
||||
'props': {
|
||||
'model': 'qb_enable_seeding',
|
||||
'label': '自动做种',
|
||||
'hint': '是否开启自动做种功能'
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12,
|
||||
'xxl': 3, 'xl': 3, 'lg': 3, 'md': 3, 'sm': 6, 'xs': 12
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VSwitch',
|
||||
'props': {
|
||||
'model': 'qb_enable_tagging',
|
||||
'label': '站点标签',
|
||||
'hint': '是否开启站点标签功能'
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12,
|
||||
'xxl': 3, 'xl': 3, 'lg': 3, 'md': 3, 'sm': 6, 'xs': 12
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VSwitch',
|
||||
'props': {
|
||||
'model': 'qb_enable_delete',
|
||||
'label': '自动删种',
|
||||
'hint': '是否开启自动删种功能'
|
||||
'model': 'tracker_mappings',
|
||||
'label': 'Tracker映射',
|
||||
'placeholder': '格式:\n'
|
||||
'<tracker-domain>:<site-domain>\n\n'
|
||||
'例如:\n'
|
||||
'chdbits.xyz:ptchdbits.co',
|
||||
'hint': 'Tracker映射。用于在站点打标签时,指定tracker和站点域名不同的种子的域名对应关系;前面为tracker域名(完整域名或者主域名皆可),中间是英文冒号,后面是站点域名。'
|
||||
}
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
}, {
|
||||
'component': 'VWindowItem',
|
||||
}]
|
||||
}, {
|
||||
'component': 'VRow',
|
||||
'content': [{
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'value': 'transmission'
|
||||
'cols': 12
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VRow',
|
||||
'content': [{
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12,
|
||||
'xxl': 3, 'xl': 3, 'lg': 3, 'md': 3, 'sm': 6, 'xs': 12
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VSwitch',
|
||||
'props': {
|
||||
'model': 'tr_enable',
|
||||
'label': '任务开关'
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12,
|
||||
'xxl': 3, 'xl': 3, 'lg': 3, 'md': 3, 'sm': 6, 'xs': 12
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VSwitch',
|
||||
'props': {
|
||||
'model': 'tr_enable_seeding',
|
||||
'label': '自动做种'
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12,
|
||||
'xxl': 3, 'xl': 3, 'lg': 3, 'md': 3, 'sm': 6, 'xs': 12
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VSwitch',
|
||||
'props': {
|
||||
'model': 'tr_enable_tagging',
|
||||
'label': '站点标签'
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12,
|
||||
'xxl': 3, 'xl': 3, 'lg': 3, 'md': 3, 'sm': 6, 'xs': 12
|
||||
},
|
||||
'content': [{
|
||||
'component': 'VSwitch',
|
||||
'props': {
|
||||
'model': 'tr_enable_delete',
|
||||
'label': '自动删种'
|
||||
}
|
||||
}]
|
||||
}]
|
||||
'component': 'VTabs',
|
||||
'props': {
|
||||
'model': '_tabs',
|
||||
'height': 72,
|
||||
'style': {
|
||||
'margin-top-': '20px',
|
||||
'margin-bottom-': '20px'
|
||||
}
|
||||
},
|
||||
'content': downloader_tabs
|
||||
}, {
|
||||
'component': 'VWindow',
|
||||
'props': {
|
||||
'model': '_tabs'
|
||||
},
|
||||
'content': downloader_tab_items
|
||||
}]
|
||||
}]
|
||||
}, {
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
from typing import Set, List, Optional
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class Constants:
|
||||
class Downloader(Enum):
|
||||
"""
|
||||
常量
|
||||
下载器枚举
|
||||
"""
|
||||
# 下载器ID
|
||||
# qb下载器id
|
||||
qb_downloader_id: str = 'qbittorrent'
|
||||
# tr下载器id
|
||||
tr_downloader_id: str = 'transmission'
|
||||
QB = ('qbittorrent', 'qBittorrent', 'qb', 'QB')
|
||||
TR = ('transmission', 'Transmission', 'tr', 'TR')
|
||||
|
||||
def __init__(self, id: str, name_: str, short_id: str, short_name: str):
|
||||
self.id: str = id
|
||||
self.name_: str = name_
|
||||
self.short_id: str = short_id
|
||||
self.short_name: str = short_name
|
||||
|
||||
|
||||
class TaskResult:
|
||||
@@ -133,14 +137,14 @@ class TaskContext:
|
||||
是否选择了qb下载器
|
||||
:return: 是否选择了qb下载器
|
||||
"""
|
||||
return self.__is_selected_the_downloader(Constants.qb_downloader_id)
|
||||
return self.__is_selected_the_downloader(Downloader.QB.id)
|
||||
|
||||
def is_selected_tr_downloader(self) -> bool:
|
||||
"""
|
||||
是否选择了tr下载器
|
||||
:return: 是否选择了tr下载器
|
||||
"""
|
||||
return self.__is_selected_the_downloader(Constants.tr_downloader_id)
|
||||
return self.__is_selected_the_downloader(Downloader.TR.id)
|
||||
|
||||
def enable_seeding(self, enable_seeding: bool = True):
|
||||
"""
|
||||
|
||||
@@ -7,7 +7,7 @@ from typing import List, Tuple, Dict, Any
|
||||
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
from watchdog.observers import Observer
|
||||
|
||||
from app.db.transferhistory_oper import TransferHistoryOper
|
||||
from app.log import logger
|
||||
from app.plugins import _PluginBase
|
||||
from app.schemas import NotificationType
|
||||
@@ -60,9 +60,16 @@ class FileMonitorHandler(FileSystemEventHandler):
|
||||
self.sync.state_set[str(file_path)] = file_path.stat().st_ino
|
||||
|
||||
def on_deleted(self, event):
|
||||
if event.is_directory:
|
||||
return
|
||||
file_path = Path(event.src_path)
|
||||
if event.is_directory:
|
||||
# 单独处理文件夹删除触发删除种子
|
||||
if self.sync._delete_torrents:
|
||||
# 发送事件
|
||||
logger.info(f"监测到删除文件夹:{file_path}")
|
||||
eventmanager.send_event(
|
||||
EventType.DownloadFileDeleted, {"src": str(file_path)}
|
||||
)
|
||||
return
|
||||
if file_path.suffix in [".!qB", ".part", ".mp"]:
|
||||
return
|
||||
logger.info(f"监测到删除文件:{file_path}")
|
||||
@@ -108,7 +115,7 @@ class RemoveLink(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "Ombi_A.png"
|
||||
# 插件版本
|
||||
plugin_version = "2.0"
|
||||
plugin_version = "2.1"
|
||||
# 插件作者
|
||||
plugin_author = "DzAvril"
|
||||
# 作者主页
|
||||
@@ -128,12 +135,15 @@ class RemoveLink(_PluginBase):
|
||||
_notify = False
|
||||
_delete_scrap_infos = False
|
||||
_delete_torrents = False
|
||||
_delete_history = False
|
||||
_transferhistory = None
|
||||
_observer = []
|
||||
# 监控目录的文件列表
|
||||
state_set: Dict[str, int] = {}
|
||||
|
||||
def init_plugin(self, config: dict = None):
|
||||
logger.info(f"Hello, RemoveLink! config {config}")
|
||||
self._transferhistory = TransferHistoryOper()
|
||||
if config:
|
||||
self._enabled = config.get("enabled")
|
||||
self._notify = config.get("notify")
|
||||
@@ -142,6 +152,7 @@ class RemoveLink(_PluginBase):
|
||||
self.exclude_keywords = config.get("exclude_keywords") or ""
|
||||
self._delete_scrap_infos = config.get("delete_scrap_infos")
|
||||
self._delete_torrents = config.get("delete_torrents")
|
||||
self._delete_history = config.get("delete_history")
|
||||
|
||||
# 停止现有任务
|
||||
self.stop_service()
|
||||
@@ -206,7 +217,7 @@ class RemoveLink(_PluginBase):
|
||||
"content": [
|
||||
{
|
||||
"component": "VCol",
|
||||
"props": {"cols": 12, "md": 6},
|
||||
"props": {"cols": 12, "md": 4},
|
||||
"content": [
|
||||
{
|
||||
"component": "VSwitch",
|
||||
@@ -219,7 +230,7 @@ class RemoveLink(_PluginBase):
|
||||
},
|
||||
{
|
||||
"component": "VCol",
|
||||
"props": {"cols": 12, "md": 6},
|
||||
"props": {"cols": 12, "md": 4},
|
||||
"content": [
|
||||
{
|
||||
"component": "VSwitch",
|
||||
@@ -237,7 +248,7 @@ class RemoveLink(_PluginBase):
|
||||
"content": [
|
||||
{
|
||||
"component": "VCol",
|
||||
"props": {"cols": 12, "md": 6},
|
||||
"props": {"cols": 12, "md": 4},
|
||||
"content": [
|
||||
{
|
||||
"component": "VSwitch",
|
||||
@@ -250,7 +261,7 @@ class RemoveLink(_PluginBase):
|
||||
},
|
||||
{
|
||||
"component": "VCol",
|
||||
"props": {"cols": 12, "md": 6},
|
||||
"props": {"cols": 12, "md": 4},
|
||||
"content": [
|
||||
{
|
||||
"component": "VSwitch",
|
||||
@@ -261,6 +272,19 @@ class RemoveLink(_PluginBase):
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"component": "VCol",
|
||||
"props": {"cols": 12, "md": 4},
|
||||
"content": [
|
||||
{
|
||||
"component": "VSwitch",
|
||||
"props": {
|
||||
"model": "delete_history",
|
||||
"label": "删除历史记录",
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -441,7 +465,7 @@ class RemoveLink(_PluginBase):
|
||||
# 文件所在目录已被删除则退出
|
||||
if not os.path.exists(path.parent):
|
||||
return
|
||||
logger.info(f"清理刮削文件: {path}")
|
||||
# logger.info(f"清理刮削文件: {path}")
|
||||
if not path.suffix.lower() in [
|
||||
".jpg",
|
||||
".nfo",
|
||||
@@ -455,11 +479,25 @@ class RemoveLink(_PluginBase):
|
||||
# 清理空目录
|
||||
self.delete_empty_folders(path)
|
||||
|
||||
def delete_history(self, path):
|
||||
"""
|
||||
清理path相关的历史记录
|
||||
"""
|
||||
if not self._delete_history:
|
||||
return
|
||||
# 查找历史记录
|
||||
transfer_history = self._transferhistory.get_by_src(path)
|
||||
if transfer_history:
|
||||
# 删除历史记录
|
||||
self._transferhistory.delete(transfer_history.id)
|
||||
logger.info(f"删除历史记录:{transfer_history.id}")
|
||||
|
||||
|
||||
def delete_empty_folders(self, path):
|
||||
"""
|
||||
从指定路径开始,逐级向上层目录检测并删除空目录,直到遇到非空目录或到达指定监控目录为止
|
||||
"""
|
||||
logger.info(f"清理空目录: {path}")
|
||||
# logger.info(f"清理空目录: {path}")
|
||||
while True:
|
||||
parent_path = path.parent
|
||||
if self.__is_excluded(parent_path):
|
||||
@@ -505,6 +543,8 @@ class RemoveLink(_PluginBase):
|
||||
eventmanager.send_event(
|
||||
EventType.DownloadFileDeleted, {"src": str(file_path)}
|
||||
)
|
||||
# 删除历史记录
|
||||
self.delete_history(str(file_path))
|
||||
# 删除的文件inode
|
||||
deleted_inode = self.state_set.get(str(file_path))
|
||||
if not deleted_inode:
|
||||
@@ -530,6 +570,8 @@ class RemoveLink(_PluginBase):
|
||||
eventmanager.send_event(
|
||||
EventType.DownloadFileDeleted, {"src": str(file_path)}
|
||||
)
|
||||
# 删除历史记录
|
||||
self.delete_history(str(file_path))
|
||||
if self._notify:
|
||||
self.post_message(
|
||||
mtype=NotificationType.SiteMessage,
|
||||
|
||||
Reference in New Issue
Block a user