diff --git a/package.json b/package.json index 9518254..1e04909 100644 --- a/package.json +++ b/package.json @@ -1,782 +1,783 @@ { - "CloudStrm": { - "name": "云盘Strm生成", - "description": "监控文件创建,生成Strm文件。", - "labels": "云盘", - "version": "4.4", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/create.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v4.4": "修复bug", - "v4.3": "回滚自定义媒体类型", - "v4.2": "扩展名转小写", - "v4.1": "支持自定义媒体类型", - "v4.0": "回归老版本", - "v3.8": "支持增量路径、支持自定义媒体类型(注:本次更新需修改配置使用)", - "v3.7": "api模式支持启用https", - "v3.6": "支持重建索引周期运行", - "v3.4": "交互命令", - "v3.1": "注册交互命令、注册公共服务", - "v3.0": "实现改为定时扫描" + "CloudStrm": { + "name": "云盘Strm生成", + "description": "监控文件创建,生成Strm文件。", + "labels": "云盘", + "version": "4.4", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/create.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v4.4": "修复bug", + "v4.3": "回滚自定义媒体类型", + "v4.2": "扩展名转小写", + "v4.1": "支持自定义媒体类型", + "v4.0": "回归老版本", + "v3.8": "支持增量路径、支持自定义媒体类型(注:本次更新需修改配置使用)", + "v3.7": "api模式支持启用https", + "v3.6": "支持重建索引周期运行", + "v3.4": "交互命令", + "v3.1": "注册交互命令、注册公共服务", + "v3.0": "实现改为定时扫描" + } + }, + "CloudStrmIncrement": { + "name": "云盘Strm生成(增量版)", + "description": "监控文件创建,生成Strm文件(增量版)。", + "labels": "云盘", + "version": "1.1.2", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/create.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.1.2": "增量文件可选择是否保留", + "v1.1.1": "写入strm使用utf-8编码", + "v1.1": "某种场景下可能出现卡死,修复bug", + "v1.0": "增量监控" + } + }, + "StrmConvert": { + "name": "Strm文件模式转换", + "description": "Strm文件内容转为本地路径或者cd2/alist API路径。", + "labels": "云盘", + "version": "1.0", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/convert.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.0": "Strm文件内容转为本地路径或者cd2/alist API路径" + } + }, + "SiteUnreadMsg": { + "name": "站点未读消息", + "description": "发送站点未读消息。", + "labels": "站点", + "version": "1.9", + "icon": "Synomail_A.png", + "author": "thsrite", + "level": 2, + "history": { + "v1.9": "同步主仓库", + "v1.8": "自定义保留消息天数", + "v1.7": "删除重复代码、依赖于[站点数据统计]插件", + "v1.6": "增加解析失败日志", + "v1.5": "修复馒头未读消息1", + "v1.4": "sync主仓库", + "v1.3": "feat mtorrent", + "v1.2": "站点消息历史存库", + "v1.1": "防止同一消息重复发送", + "v1.0": "定时获取站点消息" + } + }, + "SubscribeClear": { + "name": "清理订阅缓存", + "description": "清理订阅已下载集数。", + "labels": "订阅", + "version": "1.0", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/broom.png", + "author": "thsrite", + "level": 2, + "v2": true, + "history": { + "v1.0": "清理订阅已下载集数" + } + }, + "DownloadTorrent": { + "name": "添加种子下载", + "description": "选择下载器,添加种子任务。", + "labels": "站点", + "version": "1.1", + "icon": "download.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.1": "支持选择MoviePilot配置的下载路径", + "v1.0": "删除下载器中该站点辅种,保留该站点没有辅种的种子" + } + }, + "RemoveTorrent": { + "name": "删除站点种子", + "description": "删除下载器中某站点种子。", + "labels": "站点", + "version": "1.2", + "icon": "delete.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.2": "修复删除种子bug", + "v1.1": "可选择删除有无辅种", + "v1.0": "选择下载器,添加种子任务" + } + }, + "PluginAutoUpdate": { + "name": "插件更新管理", + "description": "监测已安装插件,推送更新提醒,可配置自动更新。", + "labels": "自动更新,插件管理", + "version": "2.0", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/pluginupdate.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v2.0": "修复插件显示版本问题", + "v1.9.2": "修复获取本地插件版本None,重新更新问题", + "v1.9.1": "修复bug", + "v1.9": "过滤相同ID插件,保留最新版本检查更新", + "v1.8": "修复已安装插件列表", + "v1.7": "插件API立即生效", + "v1.6": "插件重载,插件自动更新注册成为服务、命令", + "v1.5": "自动更新增加排除列表", + "v1.4": "正在运行的插件跳过更新,可选更新插件列表", + "v1.3": "配置更新提醒", + "v1.2": "重启后立即执行一遍更新插件", + "v1.1": "修复插件重载", + "v1.0": "监测已安装插件,自动更新最新版本" + } + }, + "PluginReInstall": { + "name": "插件强制重装", + "description": "卸载当前插件,强制重装。", + "labels": "插件管理", + "version": "1.8", + "icon": "refresh.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.8": "修复插件显示版本问题", + "v1.7": "使用主程序GITHUB_PROXY代理", + "v1.6": "插件API立即生效", + "v1.5": "支持插件热重载", + "v1.4": "支持代理地址", + "v1.3": "插件重载", + "v1.2": "支持指定插件仓库地址", + "v1.1": "修复插件重载", + "v1.0": "卸载当前插件,强制重装" + } + }, + "SynologyNotify": { + "name": "群辉Webhook通知", + "description": "接收群辉webhook通知并推送。", + "labels": "消息通知", + "version": "1.1", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/synology.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.1": "修复bug", + "v1.0": "接收群辉webhook通知并推送" + } + }, + "SyncCookieCloud": { + "name": "同步CookieCloud", + "description": "同步MoviePilot站点Cookie到本地CookieCloud。", + "labels": "站点", + "version": "1.3", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/cookiecloud.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.3": "感谢MidnightShake共享代码(同步时保留MoviePilot不匹配站点的cookie)", + "v1.2": "同步到本地CookieCloud", + "v1.1": "修复CookieCloud覆盖到浏览器", + "v1.0": "同步MoviePilot站点Cookie到CookieCloud" + } + }, + "ScheduleReminder": { + "name": "日程提醒", + "description": "自定义提醒事项、提醒时间。", + "labels": "消息通知", + "version": "1.0", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/reminder.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.0": "自定义提醒事项、提醒时间" + } + }, + "SubscribeReminder": { + "name": "订阅提醒", + "description": "推送当天订阅更新内容。", + "labels": "订阅", + "version": "1.3", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/subscribe_reminder.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.3": "修复消息类型不生效", + "v1.2": "可选订阅类型、推送类型,随机获取订阅图片", + "v1.1": "fix icon", + "v1.0": "推送当天订阅更新内容" + } + }, + "EmbyReporter": { + "name": "Emby观影报告", + "description": "推送Emby观影报告,需Emby安装Playback Report 插件。", + "labels": "Emby", + "version": "1.9.1", + "icon": "Pydiocells_A.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.9.1": "修复媒体库黑名单设置", + "v1.9": "支持媒体库黑名单设置", + "v1.8": "推送微信增加时间戳,防止使用缓存", + "v1.7": "分块发送,兼容微信推送", + "v1.6": "fix #67", + "v1.5": "按观影市场排序", + "v1.4": "支持自定义emby && 支持每日一言", + "v1.3": "修复bug", + "v1.2": "过滤已删除媒体", + "v1.1": "修复推送", + "v1.0": "推送Emby观影报告" + } + }, + "ActorSubscribe": { + "name": "演员订阅", + "description": "自动订阅指定演员热映电影、电视剧。", + "labels": "订阅", + "version": "2.1.1", + "icon": "Mdcng_A.png", + "author": "thsrite", + "level": 2, + "v2": true, + "history": { + "v2.1.1": "尝试修复未匹配到演员的bug", + "v2.1": "逻辑优化", + "v2.0": "修复订阅", + "v1.8": "支持自定义订阅username,默认`演员订阅`", + "v1.7": "修复bug", + "v1.6": "增加历史删除按钮", + "v1.5": "rename", + "v1.4": "支持多个订阅源", + "v1.3": "修复bug", + "v1.2": "修复订阅重复处理的bug", + "v1.1": "支持自定义分辨率、质量、特效", + "v1.0": "自动订阅豆瓣演员最新电影" + } + }, + "ShortPlayMonitor": { + "name": "短剧刮削", + "description": "监控视频短剧创建,刮削。", + "labels": "刮削", + "version": "3.2", + "icon": "Amule_B.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v3.2": "支持消息发送", + "v3.1": "支持自定义转移方式", + "v3.0": "默认从tmdb刮削,刮削失败则从pt站刮削" + } + }, + "CloudLinkMonitor": { + "name": "云盘实时监控", + "description": "监控云盘目录文件变化,自动转移链接。", + "labels": "云盘", + "version": "2.4.6", + "icon": "Linkease_A.png", + "author": "thsrite", + "level": 1, + "history": { + "v2.4.6": "修复bug", + "v2.4.5": "联动实时软连接插件(近媒体文件)", + "v2.4.4": "修复刷新媒体库", + "v2.4.3": "可选转移完刷新媒体库", + "v2.4.2": "fix #65", + "v2.4.1": "增加log", + "v2.4": "修复二级目录", + "v2.3": "去除无效变量", + "v2.2": "优化配置一二级分类流程", + "v2.1": "可配置是否存储转移记录", + "v2.0": "修复不刮削不生效bug", + "v1.8": "fix S00转移", + "v1.7": "fix 刮削", + "v1.6": "可配置是否刮削", + "v1.5": "fix 消息推送", + "v1.4": "fix 转移后路径", + "v1.3": "修复bug", + "v1.2": "修复订阅重复处理的bug", + "v1.1": "自动转移链接(不刮削)", + "v1.0": "监控云盘目录文件变化,按原文件名软连接" + } + }, + "LinkToSrc": { + "name": "源文件恢复", + "description": "根据MoviePilot的转移记录中的硬链文件恢复源文件。", + "labels": "媒体库", + "version": "1.2", + "icon": "Time_machine_A.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.2": "fix 路径", + "v1.1": "支持指定需要恢复的硬链接目录", + "v1.0": "根据MoviePilot的转移记录中的硬链文件恢复源文件" + } + }, + "WeChatForward": { + "name": "微信消息转发", + "description": "根据正则转发通知到其他WeChat应用。", + "labels": "消息通知", + "version": "2.7", + "icon": "Wechat_A.png", + "author": "thsrite", + "level": 1, + "history": { + "v2.7": "特殊消息指定用户支持title匹配", + "v2.6": "已完成订阅额外消息查询订阅历史订阅用户", + "v2.5.1": "修复token过期重发未存储userid问题", + "v2.5": "增强额外消息发送", + "v2.4": "修复配置修改后不重建缓存bug", + "v2.3": "增加重建缓存,丰富转发历史", + "v2.2": "增加消息发送历史", + "v2.1": "微信配置持久化存库", + "v2.0": "优化微信配置,兼容旧版本配置", + "v1.6": "修改获取指定用户订阅列表方法", + "v1.5": "丰富日志", + "v1.4": "特定消息强制指定userid", + "v1.3": "防重复发送额外消息", + "v1.2": "fix规则", + "v1.1": "自定义发送额外消息", + "v1.0": "根据正则转发通知到其他WeChat应用" + } + }, + "SubscribeStatistic": { + "name": "订阅下载统计", + "description": "统计指定时间内各站点订阅及下载情况。", + "labels": "订阅", + "version": "1.6", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/subscribestatistic.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.6": "调整page页及消息", + "v1.5": "增加消息推送", + "v1.4": "无订阅站点也统计数量", + "v1.3": "fix 数据统计", + "v1.2": "fix 订阅数量", + "v1.1": "站点去重", + "v1.0": "统计指定时间内各站点订阅及下载情况" + } + }, + "CustomCommand": { + "name": "自定义命令", + "description": "自定义执行周期执行命令并推送结果。", + "labels": "自定义命令", + "version": "1.7", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/code.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.7": "自定义通知关键词", + "v1.6": "自定义保留消息天数", + "v1.5": "修复多个任务立即运行一次", + "v1.4": "fix icon", + "v1.3": "清除历史记录", + "v1.2": "增加执行历史", + "v1.1": "打印命令日志", + "v1.0": "自定义执行周期执行命令并推送结果" + } + }, + "DockerManager": { + "name": "docker自定义任务", + "description": "管理宿主机docker,自定义容器定时任务。", + "labels": "自定义命令", + "version": "1.3", + "icon": "Docker_F.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.3": "自定义保留消息天数", + "v1.2": "多个容器名,拼接", + "v1.1": "修复多个任务立即运行一次", + "v1.0": "init" + } + }, + "PluginUnInstall": { + "name": "插件彻底卸载", + "description": "删除数据库中已安装插件记录、清理插件文件。", + "labels": "插件管理", + "version": "1.2", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/uninstall.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.2": "卸载时先停止注册服务", + "v1.1": "可选删除插件配置及数据", + "v1.0": "init" + } + }, + "FileSoftLink": { + "name": "实时软连接", + "description": "监控目录文件变化,媒体文件软连接,其他文件可选复制。", + "labels": "文件管理", + "version": "2.0.2", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/softlink.png", + "author": "thsrite", + "level": 1, + "history": { + "v2.0.2": "增加同步间隔", + "v2.0.1": "不重要的更新", + "v2.0": "修复交互命令", + "v1.9.9": "交互命令更多玩法", + "v1.9.8": "新增模糊匹配交互命令", + "v1.9.7": "接收云盘实时监控处理单文件", + "v1.9.6": "优化log", + "v1.9.5": "增强交互命令", + "v1.9.4": "监控目录自定义监控模式", + "v1.9.3": "增强交互命令模糊匹配", + "v1.9.2": "增强交互命令模糊匹配", + "v1.9.1": "增强交互命令", + "v1.9": "交互命令定向软连接", + "v1.8": "修复bug", + "v1.6": "bug修复", + "v1.5": "优化性能,提高处理速度", + "v1.4": "支持自定义视频格式", + "v1.3": "异步启动" + } + }, + "SubscribeGroup": { + "name": "订阅规则自动填充", + "description": "电视剧下载后自动添加官组等信息到订阅;添加订阅后根据二级分类名称自定义订阅规则。", + "labels": "订阅", + "version": "2.7", + "icon": "teamwork.png", + "author": "thsrite", + "level": 2, + "history": { + "v2.7": "下载填充判断当前站点是否在已选订阅站点范围内", + "v2.6": "兼容属性值包含:号", + "v2.5": "操作历史Unicode编码转中文", + "v2.4": "保存路径支持变量{name} (订阅名称 (年份))", + "v2.3": "二级分类自定义填充支持保存路径", + "v2.1": "站点与官组分开,修复质量无填充", + "v2.0": "种子下载自定义填充支持自定义占位符", + "v1.8": "修复种子下载不填充bug", + "v1.7": "操作历史Unicode编码转中文", + "v1.6": "支持一行配置多个二级分类名称", + "v1.5": "支持操作历史", + "v1.4": "支持根据二级分类名称自定义订阅规则", + "v1.3": "增加质量、分辨率、特效信息填充", + "v1.2": "修复订阅已存在包含关键词和订阅站点" + } + }, + "EmbyMetaRefresh": { + "name": "Emby元数据刷新", + "description": "定时刷新Emby媒体库元数据,演职人员中文。", + "labels": "Emby", + "version": "1.7.4", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/emby-icon.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.7.4": "获取tmdb图片使用PROXY_HOST代理", + "v1.7.3": "优化剧集演员刮削", + "v1.7.2": "优化剧集演员刮削", + "v1.7.1": "修复演员刮削", + "v1.7": "精细化刷新,最新入库支持刷新单集演职人员中文", + "v1.6": "修复豆瓣查询bug,丰富日志", + "v1.5": "支持刷新演员中文路径关键词(多个英文逗号分隔)。建议覆盖元数据修改为False,防止演员中文被刷新覆盖", + "v1.4": "支持刷新演员中文", + "v1.3": "支持自定义覆盖元数据、图片", + "v1.2": "支持获取Emby最新媒体刷新", + "v1.1": "添加远程交互命令", + "v1.0": "定时刷新Emby媒体库元数据" + } + }, + "EmbyMetaTag": { + "name": "Emby媒体标签", + "description": "自动给媒体库媒体添加标签。", + "labels": "Emby", + "version": "1.2", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/tag.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.2": "支持指定特殊媒体名称添加标签", + "v1.1": "添加远程交互命令", + "v1.0": "自动给媒体库媒体添加标签" + } + }, + "PopularSubscribe": { + "name": "热门媒体订阅", + "description": "自动添加热门电影、电视剧、动漫到订阅。", + "labels": "订阅", + "version": "1.7", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/popular.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.7": "调整订阅用户名,默认:热门订阅", + "v1.6": "调整历史unique唯一索引(可删除本次更新后的历史)", + "v1.5": "修复电视剧订阅、订阅历史展示", + "v1.4": "动漫单独订阅(本子佬启动!)", + "v1.3": "增加立即运行、历史删除按钮", + "v1.2": "增加历史删除按钮", + "v1.1": "修正流行度校验", + "v1.0": "自动添加热门媒体到订阅" + } + }, + "HomePage": { + "name": "HomePage", + "description": "HomePage自定义API。", + "labels": "工具", + "version": "1.2", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/homepage.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.2": "适配v1.9.1-beta(不生效就重启)", + "v1.1": "支持更多返回值、插件展示数据", + "v1.0": "HomePage自定义API" + } + }, + "DirMonitorEnhanced": { + "name": "目录监控", + "description": "监控目录文件发生变化时实时整理到媒体库。(统一入库消息增强版)(测试中-.-)", + "labels": "文件整理", + "version": "1.0", + "icon": "directory.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.0": "同步merge主仓库[目录监控]插件,增加统一发送消息逻辑(Testing…)" + } + }, + "SqlExecute": { + "name": "Sql执行器", + "description": "自定义MoviePilot数据库Sql执行。", + "labels": "工具", + "version": "1.3", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/sqlite.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.3": "修复执行delete锁表失败的bug", + "v1.2": "调整交互命令返回信息", + "v1.1": "支持交互命令/sql [command]执行,需主程序1.9.4+", + "v1.0": "自定义MoviePilot数据库Sql执行" + } + }, + "CommandExecute": { + "name": "命令执行器", + "description": "自定义容器命令执行。", + "labels": "工具", + "version": "1.2", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/command.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.2": "调整交互命令返回信息", + "v1.1": "支持交互命令/cmd [sql]执行,需主程序1.9.4+", + "v1.0": "自定义容器命令执行" + } + }, + "Cd2Assistant": { + "name": "CloudDrive2助手", + "description": "监控上传任务,检测是否有异常,发送通知。", + "labels": "云盘", + "version": "1.8.4", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/clouddrive.png", + "author": "thsrite", + "level": 2, + "history": { + "v1.8.4": "添加115 429消息通知", + "v1.8.3": "添加异常处理,解决cd2上本地目录获取存储空间失败的问题", + "v1.8.2": "插件页面密码类型设置为pasword", + "v1.8.1": "云下载支持自定义路径 /cd /cd2路径 磁链", + "v1.8": "修复插件依赖安装问题", + "v1.7": "增加HomePage自定义API(详见插件说明)", + "v1.6": "支持交互命令云下载", + "v1.5": "增加云盘同步黑名单(排序挂载本地目录)", + "v1.4": "增加云盘存储空间展示", + "v1.3": "增加云盘Cookie失效检测", + "v1.2": "实时速率显示", + "v1.1": "交互命令重启cd2、获取cd2系统信息,支持仪表盘", + "v1.0": "监控上传任务,检测是否有异常,发送通知" + } + }, + "SoftLinkRedirect": { + "name": "软连接重定向", + "description": "重定向软连接指向。", + "labels": "云盘", + "version": "1.2", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/softlinkredirect.png", + "author": "thsrite", + "level": 2, + "v2": true, + "history": { + "v1.2": "修复重定向", + "v1.1": "不删除软连接,强制更新重定向", + "v1.0": "重定向软连接指向" + } + }, + "CloudSyncDel": { + "name": "云盘同步删除", + "description": "媒体库删除软连接文件后,同步删除云盘文件。", + "labels": "云盘", + "version": "1.5.5", + "icon": "clouddisk.png", + "author": "thsrite", + "level": 2, + "v2": true, + "history": { + "v1.5.5": "兼容strm删除", + "v1.5.4": "fix插件历史ui", + "v1.5.3": "修复删除文件夹包含本地+云盘的场景", + "v1.5.2": "修复直接删除本地文件夹的场景", + "v1.5.1": "不重要的更新", + "v1.5": "支持软连接指向本地路径的同步删除", + "v1.4": "插件删除历史", + "v1.3.1": "添加log", + "v1.3": "同步删除thumb图片", + "v1.2": "修复删除bug", + "v1.1": "增加测试模式按钮(不删除文件)", + "v1.0": "媒体库删除软连接文件后,同步删除云盘文件" + } + }, + "LibraryDuplicateCheck": { + "name": "媒体库重复媒体检测", + "description": "媒体库重复媒体检查,可选保留规则保留其一。", + "labels": "云盘,媒体库", + "version": "1.9", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/libraryduplicate.png", + "author": "thsrite", + "level": 2, + "history": { + "v1.9": "修复删除软连接", + "v1.8": "仅检查模式下,预览操作不会删除任何文件。", + "v1.7": "修复特殊场景下删除问题", + "v1.6": "同步删除thumb图片等刮削文件", + "v1.5": "删除重复文件时再刷新媒体库逻辑", + "v1.4": "修复删除时文件不存在bug", + "v1.3": "各路径支持自定义保留规则", + "v1.2": "支持通知推送", + "v1.1": "支持自动刷新媒体库", + "v1.0": "媒体库重复媒体检查,可选择保留规则保留其一" + } + }, + "ActorSubscribePlus": { + "name": "演员作品订阅", + "description": "获取TMDB演员作品,并自动添加到订阅。", + "labels": "订阅", + "version": "1.1", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/actorsubscribeplus.png", + "author": "thsrite", + "level": 2, + "v2": true, + "history": { + "v1.1": "无评分默认评分0", + "v1.0": "获取TMDB演员作品,并自动添加到订阅" + } + }, + "FileCopy": { + "name": "文件复制", + "description": "自定义文件类型从源目录复制到目的目录。", + "labels": "工具", + "version": "1.1", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/copy_files.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.1": "增加log显示", + "v1.0": "自定义文件类型从源目录复制到目的目录" + } + }, + "EmbyCollectionSort": { + "name": "Emby合集媒体排序", + "description": "Emby保留按照加入时间倒序的前提下,把合集中的媒体按照发布日期排序,修改加入时间已到达顺序排列的目的。", + "labels": "媒体库", + "version": "1.1", + "icon": "Element_A.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.1": "优化处理逻辑", + "v1.0": "保留按照加入时间倒序的前提下,把合集中的媒体放一块,不用到处找。" + } + }, + "MediaRelease": { + "name": "影视将映订阅", + "description": "监控未上线影视作品,自动添加订阅。", + "labels": "订阅", + "version": "1.1", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/mediarelease.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.1": "bug修复", + "v1.0": "监控未上线影视作品,自动添加订阅。" + } + }, + "EmbyExtendType": { + "name": "Emby视频类型检查", + "description": "定期检查Emby媒体库中是否包含指定的视频类型,发送通知。", + "labels": "Emby,媒体库", + "version": "1.0", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/extendtype.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.0": "定期检查Emby媒体库中是否包含指定的视频类型,发送通知。" + } + }, + "EmbyAudioBook": { + "name": "Emby有声书整理", + "description": "还在为Emby有声书整理烦恼吗?入库存在很多单集?", + "labels": "Emby,媒体库", + "version": "1.1", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/audiobook.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.1": "整理完锁定,防止数据被刷新", + "v1.0": "还在为Emby有声书整理烦恼吗?入库存在很多单集。" + } + }, + "EmbyDanmu": { + "name": "Emby弹幕下载", + "description": "通知Emby Danmu插件下载弹幕。", + "labels": "Emby,媒体库", + "version": "1.2", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/danmu.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.2": "检查本地弹幕文件是否已存在,避免重复下载。", + "v1.1": "解析Emby日志,判断已配置弹幕源是否全部匹配失败。", + "v1.0": "通知Emby Danmu插件下载弹幕。" + } + }, + "EmbyActorSync": { + "name": "Emby剧集演员同步", + "description": "同步剧演员信息到集演员信息。", + "labels": "Emby,媒体库", + "version": "1.3", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/embyactorsync.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.3": "剧集优先使用季演员。", + "v1.2": "交互命令返回处理完成信息。", + "v1.1": "支持交互命令手动同步单个剧集 /as 媒体库名 剧集名。", + "v1.0": "同步剧演员信息到集演员信息。" + } } - }, - "CloudStrmIncrement": { - "name": "云盘Strm生成(增量版)", - "description": "监控文件创建,生成Strm文件(增量版)。", - "labels": "云盘", - "version": "1.1.2", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/create.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.1.2": "增量文件可选择是否保留", - "v1.1.1": "写入strm使用utf-8编码", - "v1.1": "某种场景下可能出现卡死,修复bug", - "v1.0": "增量监控" - } - }, - "StrmConvert": { - "name": "Strm文件模式转换", - "description": "Strm文件内容转为本地路径或者cd2/alist API路径。", - "labels": "云盘", - "version": "1.0", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/convert.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.0": "Strm文件内容转为本地路径或者cd2/alist API路径" - } - }, - "SiteUnreadMsg": { - "name": "站点未读消息", - "description": "发送站点未读消息。", - "labels": "站点", - "version": "1.9", - "icon": "Synomail_A.png", - "author": "thsrite", - "level": 2, - "history": { - "v1.9": "同步主仓库", - "v1.8": "自定义保留消息天数", - "v1.7": "删除重复代码、依赖于[站点数据统计]插件", - "v1.6": "增加解析失败日志", - "v1.5": "修复馒头未读消息1", - "v1.4": "sync主仓库", - "v1.3": "feat mtorrent", - "v1.2": "站点消息历史存库", - "v1.1": "防止同一消息重复发送", - "v1.0": "定时获取站点消息" - } - }, - "SubscribeClear": { - "name": "清理订阅缓存", - "description": "清理订阅已下载集数。", - "labels": "订阅", - "version": "1.0", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/broom.png", - "author": "thsrite", - "level": 2, - "v2": true, - "history": { - "v1.0": "清理订阅已下载集数" - } - }, - "DownloadTorrent": { - "name": "添加种子下载", - "description": "选择下载器,添加种子任务。", - "labels": "站点", - "version": "1.1", - "icon": "download.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.1": "支持选择MoviePilot配置的下载路径", - "v1.0": "删除下载器中该站点辅种,保留该站点没有辅种的种子" - } - }, - "RemoveTorrent": { - "name": "删除站点种子", - "description": "删除下载器中某站点种子。", - "labels": "站点", - "version": "1.2", - "icon": "delete.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.2": "修复删除种子bug", - "v1.1": "可选择删除有无辅种", - "v1.0": "选择下载器,添加种子任务" - } - }, - "PluginAutoUpdate": { - "name": "插件更新管理", - "description": "监测已安装插件,推送更新提醒,可配置自动更新。", - "labels": "自动更新,插件管理", - "version": "2.0", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/pluginupdate.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v2.0": "修复插件显示版本问题", - "v1.9.2": "修复获取本地插件版本None,重新更新问题", - "v1.9.1": "修复bug", - "v1.9": "过滤相同ID插件,保留最新版本检查更新", - "v1.8": "修复已安装插件列表", - "v1.7": "插件API立即生效", - "v1.6": "插件重载,插件自动更新注册成为服务、命令", - "v1.5": "自动更新增加排除列表", - "v1.4": "正在运行的插件跳过更新,可选更新插件列表", - "v1.3": "配置更新提醒", - "v1.2": "重启后立即执行一遍更新插件", - "v1.1": "修复插件重载", - "v1.0": "监测已安装插件,自动更新最新版本" - } - }, - "PluginReInstall": { - "name": "插件强制重装", - "description": "卸载当前插件,强制重装。", - "labels": "插件管理", - "version": "1.8", - "icon": "refresh.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.8": "修复插件显示版本问题", - "v1.7": "使用主程序GITHUB_PROXY代理", - "v1.6": "插件API立即生效", - "v1.5": "支持插件热重载", - "v1.4": "支持代理地址", - "v1.3": "插件重载", - "v1.2": "支持指定插件仓库地址", - "v1.1": "修复插件重载", - "v1.0": "卸载当前插件,强制重装" - } - }, - "SynologyNotify": { - "name": "群辉Webhook通知", - "description": "接收群辉webhook通知并推送。", - "labels": "消息通知", - "version": "1.1", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/synology.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.1": "修复bug", - "v1.0": "接收群辉webhook通知并推送" - } - }, - "SyncCookieCloud": { - "name": "同步CookieCloud", - "description": "同步MoviePilot站点Cookie到本地CookieCloud。", - "labels": "站点", - "version": "1.3", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/cookiecloud.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.3": "感谢MidnightShake共享代码(同步时保留MoviePilot不匹配站点的cookie)", - "v1.2": "同步到本地CookieCloud", - "v1.1": "修复CookieCloud覆盖到浏览器", - "v1.0": "同步MoviePilot站点Cookie到CookieCloud" - } - }, - "ScheduleReminder": { - "name": "日程提醒", - "description": "自定义提醒事项、提醒时间。", - "labels": "消息通知", - "version": "1.0", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/reminder.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.0": "自定义提醒事项、提醒时间" - } - }, - "SubscribeReminder": { - "name": "订阅提醒", - "description": "推送当天订阅更新内容。", - "labels": "订阅", - "version": "1.3", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/subscribe_reminder.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.3": "修复消息类型不生效", - "v1.2": "可选订阅类型、推送类型,随机获取订阅图片", - "v1.1": "fix icon", - "v1.0": "推送当天订阅更新内容" - } - }, - "EmbyReporter": { - "name": "Emby观影报告", - "description": "推送Emby观影报告,需Emby安装Playback Report 插件。", - "labels": "Emby", - "version": "1.9.1", - "icon": "Pydiocells_A.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.9.1": "修复媒体库黑名单设置", - "v1.9": "支持媒体库黑名单设置", - "v1.8": "推送微信增加时间戳,防止使用缓存", - "v1.7": "分块发送,兼容微信推送", - "v1.6": "fix #67", - "v1.5": "按观影市场排序", - "v1.4": "支持自定义emby && 支持每日一言", - "v1.3": "修复bug", - "v1.2": "过滤已删除媒体", - "v1.1": "修复推送", - "v1.0": "推送Emby观影报告" - } - }, - "ActorSubscribe": { - "name": "演员订阅", - "description": "自动订阅指定演员热映电影、电视剧。", - "labels": "订阅", - "version": "2.1.1", - "icon": "Mdcng_A.png", - "author": "thsrite", - "level": 2, - "v2": true, - "history": { - "v2.1.1": "尝试修复未匹配到演员的bug", - "v2.1": "逻辑优化", - "v2.0": "修复订阅", - "v1.8": "支持自定义订阅username,默认`演员订阅`", - "v1.7": "修复bug", - "v1.6": "增加历史删除按钮", - "v1.5": "rename", - "v1.4": "支持多个订阅源", - "v1.3": "修复bug", - "v1.2": "修复订阅重复处理的bug", - "v1.1": "支持自定义分辨率、质量、特效", - "v1.0": "自动订阅豆瓣演员最新电影" - } - }, - "ShortPlayMonitor": { - "name": "短剧刮削", - "description": "监控视频短剧创建,刮削。", - "labels": "刮削", - "version": "3.2", - "icon": "Amule_B.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v3.2": "支持消息发送", - "v3.1": "支持自定义转移方式", - "v3.0": "默认从tmdb刮削,刮削失败则从pt站刮削" - } - }, - "CloudLinkMonitor": { - "name": "云盘实时监控", - "description": "监控云盘目录文件变化,自动转移链接。", - "labels": "云盘", - "version": "2.4.6", - "icon": "Linkease_A.png", - "author": "thsrite", - "level": 1, - "history": { - "v2.4.6": "修复bug", - "v2.4.5": "联动实时软连接插件(近媒体文件)", - "v2.4.4": "修复刷新媒体库", - "v2.4.3": "可选转移完刷新媒体库", - "v2.4.2": "fix #65", - "v2.4.1": "增加log", - "v2.4": "修复二级目录", - "v2.3": "去除无效变量", - "v2.2": "优化配置一二级分类流程", - "v2.1": "可配置是否存储转移记录", - "v2.0": "修复不刮削不生效bug", - "v1.8": "fix S00转移", - "v1.7": "fix 刮削", - "v1.6": "可配置是否刮削", - "v1.5": "fix 消息推送", - "v1.4": "fix 转移后路径", - "v1.3": "修复bug", - "v1.2": "修复订阅重复处理的bug", - "v1.1": "自动转移链接(不刮削)", - "v1.0": "监控云盘目录文件变化,按原文件名软连接" - } - }, - "LinkToSrc": { - "name": "源文件恢复", - "description": "根据MoviePilot的转移记录中的硬链文件恢复源文件。", - "labels": "媒体库", - "version": "1.2", - "icon": "Time_machine_A.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.2": "fix 路径", - "v1.1": "支持指定需要恢复的硬链接目录", - "v1.0": "根据MoviePilot的转移记录中的硬链文件恢复源文件" - } - }, - "WeChatForward": { - "name": "微信消息转发", - "description": "根据正则转发通知到其他WeChat应用。", - "labels": "消息通知", - "version": "2.7", - "icon": "Wechat_A.png", - "author": "thsrite", - "level": 1, - "history": { - "v2.7": "特殊消息指定用户支持title匹配", - "v2.6": "已完成订阅额外消息查询订阅历史订阅用户", - "v2.5.1": "修复token过期重发未存储userid问题", - "v2.5": "增强额外消息发送", - "v2.4": "修复配置修改后不重建缓存bug", - "v2.3": "增加重建缓存,丰富转发历史", - "v2.2": "增加消息发送历史", - "v2.1": "微信配置持久化存库", - "v2.0": "优化微信配置,兼容旧版本配置", - "v1.6": "修改获取指定用户订阅列表方法", - "v1.5": "丰富日志", - "v1.4": "特定消息强制指定userid", - "v1.3": "防重复发送额外消息", - "v1.2": "fix规则", - "v1.1": "自定义发送额外消息", - "v1.0": "根据正则转发通知到其他WeChat应用" - } - }, - "SubscribeStatistic": { - "name": "订阅下载统计", - "description": "统计指定时间内各站点订阅及下载情况。", - "labels": "订阅", - "version": "1.6", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/subscribestatistic.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.6": "调整page页及消息", - "v1.5": "增加消息推送", - "v1.4": "无订阅站点也统计数量", - "v1.3": "fix 数据统计", - "v1.2": "fix 订阅数量", - "v1.1": "站点去重", - "v1.0": "统计指定时间内各站点订阅及下载情况" - } - }, - "CustomCommand": { - "name": "自定义命令", - "description": "自定义执行周期执行命令并推送结果。", - "labels": "自定义命令", - "version": "1.7", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/code.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.7": "自定义通知关键词", - "v1.6": "自定义保留消息天数", - "v1.5": "修复多个任务立即运行一次", - "v1.4": "fix icon", - "v1.3": "清除历史记录", - "v1.2": "增加执行历史", - "v1.1": "打印命令日志", - "v1.0": "自定义执行周期执行命令并推送结果" - } - }, - "DockerManager": { - "name": "docker自定义任务", - "description": "管理宿主机docker,自定义容器定时任务。", - "labels": "自定义命令", - "version": "1.3", - "icon": "Docker_F.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.3": "自定义保留消息天数", - "v1.2": "多个容器名,拼接", - "v1.1": "修复多个任务立即运行一次", - "v1.0": "init" - } - }, - "PluginUnInstall": { - "name": "插件彻底卸载", - "description": "删除数据库中已安装插件记录、清理插件文件。", - "labels": "插件管理", - "version": "1.2", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/uninstall.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.2": "卸载时先停止注册服务", - "v1.1": "可选删除插件配置及数据", - "v1.0": "init" - } - }, - "FileSoftLink": { - "name": "实时软连接", - "description": "监控目录文件变化,媒体文件软连接,其他文件可选复制。", - "labels": "文件管理", - "version": "2.0.1", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/softlink.png", - "author": "thsrite", - "level": 1, - "history": { - "v2.0.1": "不重要的更新", - "v2.0": "修复交互命令", - "v1.9.9": "交互命令更多玩法", - "v1.9.8": "新增模糊匹配交互命令", - "v1.9.7": "接收云盘实时监控处理单文件", - "v1.9.6": "优化log", - "v1.9.5": "增强交互命令", - "v1.9.4": "监控目录自定义监控模式", - "v1.9.3": "增强交互命令模糊匹配", - "v1.9.2": "增强交互命令模糊匹配", - "v1.9.1": "增强交互命令", - "v1.9": "交互命令定向软连接", - "v1.8": "修复bug", - "v1.6": "bug修复", - "v1.5": "优化性能,提高处理速度", - "v1.4": "支持自定义视频格式", - "v1.3": "异步启动" - } - }, - "SubscribeGroup": { - "name": "订阅规则自动填充", - "description": "电视剧下载后自动添加官组等信息到订阅;添加订阅后根据二级分类名称自定义订阅规则。", - "labels": "订阅", - "version": "2.7", - "icon": "teamwork.png", - "author": "thsrite", - "level": 2, - "history": { - "v2.7": "下载填充判断当前站点是否在已选订阅站点范围内", - "v2.6": "兼容属性值包含:号", - "v2.5": "操作历史Unicode编码转中文", - "v2.4": "保存路径支持变量{name} (订阅名称 (年份))", - "v2.3": "二级分类自定义填充支持保存路径", - "v2.1": "站点与官组分开,修复质量无填充", - "v2.0": "种子下载自定义填充支持自定义占位符", - "v1.8": "修复种子下载不填充bug", - "v1.7": "操作历史Unicode编码转中文", - "v1.6": "支持一行配置多个二级分类名称", - "v1.5": "支持操作历史", - "v1.4": "支持根据二级分类名称自定义订阅规则", - "v1.3": "增加质量、分辨率、特效信息填充", - "v1.2": "修复订阅已存在包含关键词和订阅站点" - } - }, - "EmbyMetaRefresh": { - "name": "Emby元数据刷新", - "description": "定时刷新Emby媒体库元数据,演职人员中文。", - "labels": "Emby", - "version": "1.7.4", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/emby-icon.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.7.4": "获取tmdb图片使用PROXY_HOST代理", - "v1.7.3": "优化剧集演员刮削", - "v1.7.2": "优化剧集演员刮削", - "v1.7.1": "修复演员刮削", - "v1.7": "精细化刷新,最新入库支持刷新单集演职人员中文", - "v1.6": "修复豆瓣查询bug,丰富日志", - "v1.5": "支持刷新演员中文路径关键词(多个英文逗号分隔)。建议覆盖元数据修改为False,防止演员中文被刷新覆盖", - "v1.4": "支持刷新演员中文", - "v1.3": "支持自定义覆盖元数据、图片", - "v1.2": "支持获取Emby最新媒体刷新", - "v1.1": "添加远程交互命令", - "v1.0": "定时刷新Emby媒体库元数据" - } - }, - "EmbyMetaTag": { - "name": "Emby媒体标签", - "description": "自动给媒体库媒体添加标签。", - "labels": "Emby", - "version": "1.2", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/tag.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.2": "支持指定特殊媒体名称添加标签", - "v1.1": "添加远程交互命令", - "v1.0": "自动给媒体库媒体添加标签" - } - }, - "PopularSubscribe": { - "name": "热门媒体订阅", - "description": "自动添加热门电影、电视剧、动漫到订阅。", - "labels": "订阅", - "version": "1.7", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/popular.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.7": "调整订阅用户名,默认:热门订阅", - "v1.6": "调整历史unique唯一索引(可删除本次更新后的历史)", - "v1.5": "修复电视剧订阅、订阅历史展示", - "v1.4": "动漫单独订阅(本子佬启动!)", - "v1.3": "增加立即运行、历史删除按钮", - "v1.2": "增加历史删除按钮", - "v1.1": "修正流行度校验", - "v1.0": "自动添加热门媒体到订阅" - } - }, - "HomePage": { - "name": "HomePage", - "description": "HomePage自定义API。", - "labels": "工具", - "version": "1.2", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/homepage.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.2": "适配v1.9.1-beta(不生效就重启)", - "v1.1": "支持更多返回值、插件展示数据", - "v1.0": "HomePage自定义API" - } - }, - "DirMonitorEnhanced": { - "name": "目录监控", - "description": "监控目录文件发生变化时实时整理到媒体库。(统一入库消息增强版)(测试中-.-)", - "labels": "文件整理", - "version": "1.0", - "icon": "directory.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.0": "同步merge主仓库[目录监控]插件,增加统一发送消息逻辑(Testing…)" - } - }, - "SqlExecute": { - "name": "Sql执行器", - "description": "自定义MoviePilot数据库Sql执行。", - "labels": "工具", - "version": "1.3", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/sqlite.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.3": "修复执行delete锁表失败的bug", - "v1.2": "调整交互命令返回信息", - "v1.1": "支持交互命令/sql [command]执行,需主程序1.9.4+", - "v1.0": "自定义MoviePilot数据库Sql执行" - } - }, - "CommandExecute": { - "name": "命令执行器", - "description": "自定义容器命令执行。", - "labels": "工具", - "version": "1.2", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/command.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.2": "调整交互命令返回信息", - "v1.1": "支持交互命令/cmd [sql]执行,需主程序1.9.4+", - "v1.0": "自定义容器命令执行" - } - }, - "Cd2Assistant": { - "name": "CloudDrive2助手", - "description": "监控上传任务,检测是否有异常,发送通知。", - "labels": "云盘", - "version": "1.8.4", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/clouddrive.png", - "author": "thsrite", - "level": 2, - "history": { - "v1.8.4": "添加115 429消息通知", - "v1.8.3": "添加异常处理,解决cd2上本地目录获取存储空间失败的问题", - "v1.8.2": "插件页面密码类型设置为pasword", - "v1.8.1": "云下载支持自定义路径 /cd /cd2路径 磁链", - "v1.8": "修复插件依赖安装问题", - "v1.7": "增加HomePage自定义API(详见插件说明)", - "v1.6": "支持交互命令云下载", - "v1.5": "增加云盘同步黑名单(排序挂载本地目录)", - "v1.4": "增加云盘存储空间展示", - "v1.3": "增加云盘Cookie失效检测", - "v1.2": "实时速率显示", - "v1.1": "交互命令重启cd2、获取cd2系统信息,支持仪表盘", - "v1.0": "监控上传任务,检测是否有异常,发送通知" - } - }, - "SoftLinkRedirect": { - "name": "软连接重定向", - "description": "重定向软连接指向。", - "labels": "云盘", - "version": "1.2", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/softlinkredirect.png", - "author": "thsrite", - "level": 2, - "v2": true, - "history": { - "v1.2": "修复重定向", - "v1.1": "不删除软连接,强制更新重定向", - "v1.0": "重定向软连接指向" - } - }, - "CloudSyncDel": { - "name": "云盘同步删除", - "description": "媒体库删除软连接文件后,同步删除云盘文件。", - "labels": "云盘", - "version": "1.5.5", - "icon": "clouddisk.png", - "author": "thsrite", - "level": 2, - "v2": true, - "history": { - "v1.5.5": "兼容strm删除", - "v1.5.4": "fix插件历史ui", - "v1.5.3": "修复删除文件夹包含本地+云盘的场景", - "v1.5.2": "修复直接删除本地文件夹的场景", - "v1.5.1": "不重要的更新", - "v1.5": "支持软连接指向本地路径的同步删除", - "v1.4": "插件删除历史", - "v1.3.1": "添加log", - "v1.3": "同步删除thumb图片", - "v1.2": "修复删除bug", - "v1.1": "增加测试模式按钮(不删除文件)", - "v1.0": "媒体库删除软连接文件后,同步删除云盘文件" - } - }, - "LibraryDuplicateCheck": { - "name": "媒体库重复媒体检测", - "description": "媒体库重复媒体检查,可选保留规则保留其一。", - "labels": "云盘,媒体库", - "version": "1.9", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/libraryduplicate.png", - "author": "thsrite", - "level": 2, - "history": { - "v1.9": "修复删除软连接", - "v1.8": "仅检查模式下,预览操作不会删除任何文件。", - "v1.7": "修复特殊场景下删除问题", - "v1.6": "同步删除thumb图片等刮削文件", - "v1.5": "删除重复文件时再刷新媒体库逻辑", - "v1.4": "修复删除时文件不存在bug", - "v1.3": "各路径支持自定义保留规则", - "v1.2": "支持通知推送", - "v1.1": "支持自动刷新媒体库", - "v1.0": "媒体库重复媒体检查,可选择保留规则保留其一" - } - }, - "ActorSubscribePlus": { - "name": "演员作品订阅", - "description": "获取TMDB演员作品,并自动添加到订阅。", - "labels": "订阅", - "version": "1.1", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/actorsubscribeplus.png", - "author": "thsrite", - "level": 2, - "v2": true, - "history": { - "v1.1": "无评分默认评分0", - "v1.0": "获取TMDB演员作品,并自动添加到订阅" - } - }, - "FileCopy": { - "name": "文件复制", - "description": "自定义文件类型从源目录复制到目的目录。", - "labels": "工具", - "version": "1.1", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/copy_files.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.1": "增加log显示", - "v1.0": "自定义文件类型从源目录复制到目的目录" - } - }, - "EmbyCollectionSort": { - "name": "Emby合集媒体排序", - "description": "Emby保留按照加入时间倒序的前提下,把合集中的媒体按照发布日期排序,修改加入时间已到达顺序排列的目的。", - "labels": "媒体库", - "version": "1.1", - "icon": "Element_A.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.1": "优化处理逻辑", - "v1.0": "保留按照加入时间倒序的前提下,把合集中的媒体放一块,不用到处找。" - } - }, - "MediaRelease": { - "name": "影视将映订阅", - "description": "监控未上线影视作品,自动添加订阅。", - "labels": "订阅", - "version": "1.1", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/mediarelease.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.1": "bug修复", - "v1.0": "监控未上线影视作品,自动添加订阅。" - } - }, - "EmbyExtendType": { - "name": "Emby视频类型检查", - "description": "定期检查Emby媒体库中是否包含指定的视频类型,发送通知。", - "labels": "Emby,媒体库", - "version": "1.0", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/extendtype.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.0": "定期检查Emby媒体库中是否包含指定的视频类型,发送通知。" - } - }, - "EmbyAudioBook": { - "name": "Emby有声书整理", - "description": "还在为Emby有声书整理烦恼吗?入库存在很多单集?", - "labels": "Emby,媒体库", - "version": "1.1", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/audiobook.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.1": "整理完锁定,防止数据被刷新", - "v1.0": "还在为Emby有声书整理烦恼吗?入库存在很多单集。" - } - }, - "EmbyDanmu": { - "name": "Emby弹幕下载", - "description": "通知Emby Danmu插件下载弹幕。", - "labels": "Emby,媒体库", - "version": "1.2", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/danmu.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.2": "检查本地弹幕文件是否已存在,避免重复下载。", - "v1.1": "解析Emby日志,判断已配置弹幕源是否全部匹配失败。", - "v1.0": "通知Emby Danmu插件下载弹幕。" - } - }, - "EmbyActorSync": { - "name": "Emby剧集演员同步", - "description": "同步剧演员信息到集演员信息。", - "labels": "Emby,媒体库", - "version": "1.3", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/embyactorsync.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.3": "剧集优先使用季演员。", - "v1.2": "交互命令返回处理完成信息。", - "v1.1": "支持交互命令手动同步单个剧集 /as 媒体库名 剧集名。", - "v1.0": "同步剧演员信息到集演员信息。" - } - } } diff --git a/package.v2.json b/package.v2.json index b38cdcd..a4bc72e 100644 --- a/package.v2.json +++ b/package.v2.json @@ -1,446 +1,447 @@ { - "EmbyMetaRefresh": { - "name": "Emby元数据刷新", - "description": "定时刷新Emby媒体库元数据,演职人员中文。", - "labels": "Emby", - "version": "2.1.3", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/emby-icon.png", - "author": "thsrite", - "level": 1, - "history": { - "v2.1.3": "增加自定义延迟", - "v2.1.1": "优化刷新逻辑,过滤掉信息全的媒体", - "v2.0.1": "获取tmdb图片时使用PROXY_HOST代理", - "v2.0": "适配v2", - "v1.8": "适配v2多媒体服务器", - "v1.7.3": "优化剧集演员刮削", - "v1.7.2": "优化剧集演员刮削", - "v1.7.1": "修复演员刮削", - "v1.7": "精细化刷新,最新入库支持刷新单集演职人员中文", - "v1.6": "修复豆瓣查询bug,丰富日志", - "v1.5": "支持刷新演员中文路径关键词(多个英文逗号分隔)。建议覆盖元数据修改为False,防止演员中文被刷新覆盖", - "v1.4": "支持刷新演员中文", - "v1.3": "支持自定义覆盖元数据、图片", - "v1.2": "支持获取Emby最新媒体刷新", - "v1.1": "添加远程交互命令", - "v1.0": "定时刷新Emby媒体库元数据" + "EmbyMetaRefresh": { + "name": "Emby元数据刷新", + "description": "定时刷新Emby媒体库元数据,演职人员中文。", + "labels": "Emby", + "version": "2.1.3", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/emby-icon.png", + "author": "thsrite", + "level": 1, + "history": { + "v2.1.3": "增加自定义延迟", + "v2.1.1": "优化刷新逻辑,过滤掉信息全的媒体", + "v2.0.1": "获取tmdb图片时使用PROXY_HOST代理", + "v2.0": "适配v2", + "v1.8": "适配v2多媒体服务器", + "v1.7.3": "优化剧集演员刮削", + "v1.7.2": "优化剧集演员刮削", + "v1.7.1": "修复演员刮削", + "v1.7": "精细化刷新,最新入库支持刷新单集演职人员中文", + "v1.6": "修复豆瓣查询bug,丰富日志", + "v1.5": "支持刷新演员中文路径关键词(多个英文逗号分隔)。建议覆盖元数据修改为False,防止演员中文被刷新覆盖", + "v1.4": "支持刷新演员中文", + "v1.3": "支持自定义覆盖元数据、图片", + "v1.2": "支持获取Emby最新媒体刷新", + "v1.1": "添加远程交互命令", + "v1.0": "定时刷新Emby媒体库元数据" + } + }, + "EmbyMetaTag": { + "name": "Emby媒体标签", + "description": "自动给媒体库媒体添加标签。", + "labels": "Emby", + "version": "1.3", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/tag.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.3": "适配v2多媒体服务器", + "v1.2": "支持指定特殊媒体名称添加标签", + "v1.1": "添加远程交互命令", + "v1.0": "自动给媒体库媒体添加标签" + } + }, + "EmbyReporter": { + "name": "Emby观影报告", + "description": "推送Emby观影报告,需Emby安装Playback Report 插件。", + "labels": "Emby", + "version": "2.1.1", + "icon": "Pydiocells_A.png", + "author": "thsrite", + "level": 1, + "history": { + "v2.1.1": "修复媒体库黑名单设置", + "v2.1": "支持媒体库黑名单设置", + "v2.0": "修复获取媒体服务器配置", + "v1.9": "适配v2多媒体服务器", + "v1.8": "推送微信增加时间戳,防止使用缓存", + "v1.7": "分块发送,兼容微信推送", + "v1.6": "fix #67", + "v1.5": "按观影市场排序", + "v1.4": "支持自定义emby && 支持每日一言", + "v1.3": "修复bug", + "v1.2": "过滤已删除媒体", + "v1.1": "修复推送", + "v1.0": "推送Emby观影报告" + } + }, + "WeChatForward": { + "name": "微信消息转发", + "description": "根据正则转发通知到其他WeChat应用。", + "labels": "消息通知", + "version": "2.8", + "icon": "Wechat_A.png", + "author": "thsrite", + "level": 1, + "history": { + "v2.8": "兼容v2", + "v2.7": "特殊消息指定用户支持title匹配", + "v2.6": "已完成订阅额外消息查询订阅历史订阅用户", + "v2.5.1": "修复token过期重发未存储userid问题", + "v2.5": "增强额外消息发送", + "v2.4": "修复配置修改后不重建缓存bug", + "v2.3": "增加重建缓存,丰富转发历史", + "v2.2": "增加消息发送历史", + "v2.1": "微信配置持久化存库", + "v2.0": "优化微信配置,兼容旧版本配置", + "v1.6": "修改获取指定用户订阅列表方法", + "v1.5": "丰富日志", + "v1.4": "特定消息强制指定userid", + "v1.3": "防重复发送额外消息", + "v1.2": "fix规则", + "v1.1": "自定义发送额外消息", + "v1.0": "根据正则转发通知到其他WeChat应用" + } + }, + "EmbyDanmu": { + "name": "Emby弹幕下载", + "description": "通知Emby Danmu插件下载弹幕。", + "labels": "Emby,媒体库", + "version": "1.6", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/danmu.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.6": "增加Emby、MoviePilot目录映射(相同可不填)", + "v1.5.1": "Emby4.8.8 Items API修改", + "v1.5": "修复获取弹幕源", + "v1.4": "修复自定义参数", + "v1.3": "适配v2多媒体服务器", + "v1.2": "检查本地弹幕文件是否已存在,避免重复下载。", + "v1.1": "解析Emby日志,判断已配置弹幕源是否全部匹配失败。", + "v1.0": "通知Emby Danmu插件下载弹幕。" + } + }, + "EmbyExtendType": { + "name": "Emby视频类型检查", + "description": "定期检查Emby媒体库中是否包含指定的视频类型,发送通知。", + "labels": "Emby,媒体库", + "version": "1.1", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/extendtype.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.1": "适配v2多媒体服务器", + "v1.0": "定期检查Emby媒体库中是否包含指定的视频类型,发送通知。" + } + }, + "EmbyAudioBook": { + "name": "Emby有声书整理", + "description": "还在为Emby有声书整理烦恼吗?入库存在很多单集?", + "labels": "Emby,媒体库", + "version": "1.4", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/audiobook.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.4": "交互命令支持多媒体库", + "v1.3": "修复自定义参数", + "v1.2": "适配v2多媒体服务器", + "v1.1": "整理完锁定,防止数据被刷新", + "v1.0": "还在为Emby有声书整理烦恼吗?入库存在很多单集。" + } + }, + "EmbyCollectionSort": { + "name": "Emby合集媒体排序", + "description": "Emby保留按照加入时间倒序的前提下,把合集中的媒体按照发布日期排序,修改加入时间已到达顺序排列的目的。", + "labels": "媒体库", + "version": "1.2", + "icon": "Element_A.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.2": "适配v2多媒体服务器", + "v1.1": "优化处理逻辑", + "v1.0": "保留按照加入时间倒序的前提下,把合集中的媒体放一块,不用到处找。" + } + }, + "EmbyActorSync": { + "name": "Emby剧集演员同步", + "description": "同步剧演员信息到集演员信息。", + "labels": "Emby,媒体库", + "version": "1.5", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/embyactorsync.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.5": "修复自定义参数", + "v1.4": "适配v2多媒体服务器", + "v1.3": "剧集优先使用季演员。", + "v1.2": "交互命令返回处理完成信息。", + "v1.1": "支持交互命令手动同步单个剧集 /as 媒体库名 剧集名。", + "v1.0": "同步剧演员信息到集演员信息。" + } + }, + "LibraryDuplicateCheck": { + "name": "Emby媒体库重复媒体检测", + "description": "媒体库重复媒体检查,可选保留规则保留其一。", + "labels": "Emby,云盘,媒体库", + "version": "2.0.1", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/libraryduplicate.png", + "author": "thsrite", + "level": 2, + "history": { + "v2.0.1": "适配v2多媒体服务器", + "v1.9": "修复删除软连接", + "v1.8": "仅检查模式下,预览操作不会删除任何文件。", + "v1.7": "修复特殊场景下删除问题", + "v1.6": "同步删除thumb图片等刮削文件", + "v1.5": "删除重复文件时再刷新媒体库逻辑", + "v1.4": "修复删除时文件不存在bug", + "v1.3": "各路径支持自定义保留规则", + "v1.2": "支持通知推送", + "v1.1": "支持自动刷新媒体库", + "v1.0": "媒体库重复媒体检查,可选择保留规则保留其一" + } + }, + "MediaSyncDel": { + "name": "媒体文件同步删除", + "description": "同步删除历史记录、源文件和下载任务。", + "labels": "媒体库,文件整理", + "version": "1.8.4", + "icon": "mediasyncdel.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.8.4": "修复暂停种子失败", + "v1.8.3": "修复源文件删除", + "v1.8.1": "适配v2多媒体服务器,移除日志方式", + "v1.7": "修复重新整理被一并删除问题", + "v1.6": "修复删除辅种", + "v1.5": "支持手动删除订阅历史记录(本次更新之后的历史)" + } + }, + "SyncDownloadFiles": { + "name": "下载器文件同步", + "description": "同步下载器的文件信息到数据库,删除文件时联动删除下载任务。", + "labels": "下载管理", + "version": "1.1.3", + "icon": "Youtube-dl_A.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.1.3": "支持v2", + "v1.1.1": "修复时区问题导致的上次同步后8h内的种子不同步的问题" + } + }, + "HomePage": { + "name": "HomePage", + "description": "HomePage自定义API。", + "labels": "工具", + "version": "1.3", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/homepage.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.3": "兼容v2", + "v1.2": "适配v1.9.1-beta(不生效就重启)", + "v1.1": "支持更多返回值、插件展示数据", + "v1.0": "HomePage自定义API" + } + }, + "FileSoftLink": { + "name": "实时软连接", + "description": "监控目录文件变化,媒体文件软连接,其他文件可选复制。", + "labels": "文件管理", + "version": "2.0.4", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/softlink.png", + "author": "thsrite", + "level": 1, + "history": { + "v2.0.4": "增加同步遍历文件间隔", + "v2.0.3": "增加强制覆盖选项", + "v2.0.2": "兼容v2", + "v2.0.1": "不重要的更新", + "v2.0": "修复交互命令", + "v1.9.9": "交互命令更多玩法", + "v1.9.8": "新增模糊匹配交互命令", + "v1.9.7": "接收云盘实时监控处理单文件", + "v1.9.6": "优化log", + "v1.9.5": "增强交互命令", + "v1.9.4": "监控目录自定义监控模式", + "v1.9.3": "增强交互命令模糊匹配", + "v1.9.2": "增强交互命令模糊匹配", + "v1.9.1": "增强交互命令", + "v1.9": "交互命令定向软连接", + "v1.8": "修复bug", + "v1.6": "bug修复", + "v1.5": "优化性能,提高处理速度", + "v1.4": "支持自定义视频格式", + "v1.3": "异步启动" + } + }, + "Cd2Assistant": { + "name": "CloudDrive2助手", + "description": "监控上传任务,检测是否有异常,发送通知。", + "labels": "云盘", + "version": "1.8.5", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/clouddrive.png", + "author": "thsrite", + "level": 2, + "history": { + "v1.8.5": "兼容v2", + "v1.8.4": "添加115 429消息通知", + "v1.8.3": "添加异常处理,解决cd2上本地目录获取存储空间失败的问题", + "v1.8.2": "插件页面密码类型设置为pasword", + "v1.8.1": "云下载支持自定义路径 /cd /cd2路径 磁链", + "v1.8": "修复插件依赖安装问题", + "v1.7": "增加HomePage自定义API(详见插件说明)", + "v1.6": "支持交互命令云下载", + "v1.5": "增加云盘同步黑名单(排序挂载本地目录)", + "v1.4": "增加云盘存储空间展示", + "v1.3": "增加云盘Cookie失效检测", + "v1.2": "实时速率显示", + "v1.1": "交互命令重启cd2、获取cd2系统信息,支持仪表盘", + "v1.0": "监控上传任务,检测是否有异常,发送通知" + } + }, + "MediaRelease": { + "name": "影视将映订阅", + "description": "监控未上线影视作品,自动添加订阅。", + "labels": "订阅", + "version": "1.2", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/mediarelease.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.2": "兼容v2", + "v1.1": "bug修复", + "v1.0": "监控未上线影视作品,自动添加订阅。" + } + }, + "SubscribeGroup": { + "name": "订阅规则自动填充", + "description": "电视剧下载后自动添加官组等信息到订阅;添加订阅后根据二级分类名称自定义订阅规则。", + "labels": "订阅", + "version": "2.8.2", + "icon": "teamwork.png", + "author": "thsrite", + "level": 2, + "history": { + "v2.8.2": "订阅填充规则支持优先级规则组", + "v2.8.1": "修复种子下载自定义填充站点后订阅无法打开问题", + "v2.8": "兼容v2", + "v2.7": "下载填充判断当前站点是否在已选订阅站点范围内", + "v2.6": "兼容属性值包含:号", + "v2.5": "操作历史Unicode编码转中文", + "v2.4": "保存路径支持变量{name} (订阅名称 (年份))", + "v2.3": "二级分类自定义填充支持保存路径", + "v2.1": "站点与官组分开,修复质量无填充", + "v2.0": "种子下载自定义填充支持自定义占位符", + "v1.8": "修复种子下载不填充bug", + "v1.7": "操作历史Unicode编码转中文", + "v1.6": "支持一行配置多个二级分类名称", + "v1.5": "支持操作历史", + "v1.4": "支持根据二级分类名称自定义订阅规则", + "v1.3": "增加质量、分辨率、特效信息填充", + "v1.2": "修复订阅已存在包含关键词和订阅站点" + } + }, + "SqlExecute": { + "name": "Sql执行器", + "description": "自定义MoviePilot数据库Sql执行。", + "labels": "工具", + "version": "1.4", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/sqlite.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.4": "兼容v2", + "v1.3": "修复执行delete锁表失败的bug", + "v1.2": "调整交互命令返回信息", + "v1.1": "支持交互命令/sql [command]执行,需主程序1.9.4+", + "v1.0": "自定义MoviePilot数据库Sql执行" + } + }, + "CommandExecute": { + "name": "命令执行器", + "description": "自定义容器命令执行。", + "labels": "工具", + "version": "1.3", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/command.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.3": "兼容v2", + "v1.2": "调整交互命令返回信息", + "v1.1": "支持交互命令/cmd [sql]执行,需主程序1.9.4+", + "v1.0": "自定义容器命令执行" + } + }, + "AutoBackup": { + "name": "自动备份", + "description": "自动备份数据和配置文件。", + "labels": "系统设置", + "version": "2.0.1", + "icon": "Time_machine_B.png", + "author": "thsrite", + "level": 1, + "history": { + "v2.0.1": "修复cookies文件夹备份失败", + "v2.0": "支持备份app.env及cookies,支持自定义保存路径", + "v1.3": "去除已废弃的环境变量引用", + "v1.2": "增强API安全性" + } + }, + "CloudLinkMonitor": { + "name": "目录实时监控", + "description": "监控云盘目录文件变化,自动转移媒体文件。", + "labels": "云盘,工具", + "version": "2.5.1", + "icon": "Linkease_A.png", + "author": "thsrite", + "level": 1, + "history": { + "v2.5.1": "修复媒体刮削", + "v2.5": "兼容v2", + "v2.4.5": "联动实时软连接插件(近媒体文件)", + "v2.4.4": "修复刷新媒体库", + "v2.4.3": "可选转移完刷新媒体库", + "v2.4.2": "fix #65", + "v2.4.1": "增加log", + "v2.4": "修复二级目录", + "v2.3": "去除无效变量", + "v2.2": "优化配置一二级分类流程", + "v2.1": "可配置是否存储转移记录", + "v2.0": "修复不刮削不生效bug", + "v1.8": "fix S00转移", + "v1.7": "fix 刮削", + "v1.6": "可配置是否刮削", + "v1.5": "fix 消息推送", + "v1.4": "fix 转移后路径", + "v1.3": "修复bug", + "v1.2": "修复订阅重复处理的bug", + "v1.1": "自动转移链接(不刮削)", + "v1.0": "监控云盘目录文件变化,按原文件名软连接" + } + }, + "CloudStrmCompanion": { + "name": "云盘Strm助手", + "description": "实时监控、定时全量增量生成strm文件。", + "labels": "云盘", + "version": "1.0.5", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/cloudcompanion.png", + "author": "thsrite", + "level": 1, + "history": { + "v1.0.5": "增加复制非媒体文件选项", + "v1.0.4": "修复实时监控,只处理指定类型的文件", + "v1.0.3": "修复重建索引缓存", + "v1.0.2": "增加可玩性交互命令", + "v1.0": "实时监控、定时全量增量生成strm文件" + } + }, + "StrmRedirect": { + "name": "Strm重定向", + "description": "重写Strm文件内容。", + "labels": "云盘", + "version": "1.0", + "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/softlinkredirect.png", + "author": "thsrite", + "level": 1, + "v2": true, + "history": { + "v1.0": "重写Strm文件内容" + } } - }, - "EmbyMetaTag": { - "name": "Emby媒体标签", - "description": "自动给媒体库媒体添加标签。", - "labels": "Emby", - "version": "1.3", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/tag.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.3": "适配v2多媒体服务器", - "v1.2": "支持指定特殊媒体名称添加标签", - "v1.1": "添加远程交互命令", - "v1.0": "自动给媒体库媒体添加标签" - } - }, - "EmbyReporter": { - "name": "Emby观影报告", - "description": "推送Emby观影报告,需Emby安装Playback Report 插件。", - "labels": "Emby", - "version": "2.1.1", - "icon": "Pydiocells_A.png", - "author": "thsrite", - "level": 1, - "history": { - "v2.1.1": "修复媒体库黑名单设置", - "v2.1": "支持媒体库黑名单设置", - "v2.0": "修复获取媒体服务器配置", - "v1.9": "适配v2多媒体服务器", - "v1.8": "推送微信增加时间戳,防止使用缓存", - "v1.7": "分块发送,兼容微信推送", - "v1.6": "fix #67", - "v1.5": "按观影市场排序", - "v1.4": "支持自定义emby && 支持每日一言", - "v1.3": "修复bug", - "v1.2": "过滤已删除媒体", - "v1.1": "修复推送", - "v1.0": "推送Emby观影报告" - } - }, - "WeChatForward": { - "name": "微信消息转发", - "description": "根据正则转发通知到其他WeChat应用。", - "labels": "消息通知", - "version": "2.8", - "icon": "Wechat_A.png", - "author": "thsrite", - "level": 1, - "history": { - "v2.8": "兼容v2", - "v2.7": "特殊消息指定用户支持title匹配", - "v2.6": "已完成订阅额外消息查询订阅历史订阅用户", - "v2.5.1": "修复token过期重发未存储userid问题", - "v2.5": "增强额外消息发送", - "v2.4": "修复配置修改后不重建缓存bug", - "v2.3": "增加重建缓存,丰富转发历史", - "v2.2": "增加消息发送历史", - "v2.1": "微信配置持久化存库", - "v2.0": "优化微信配置,兼容旧版本配置", - "v1.6": "修改获取指定用户订阅列表方法", - "v1.5": "丰富日志", - "v1.4": "特定消息强制指定userid", - "v1.3": "防重复发送额外消息", - "v1.2": "fix规则", - "v1.1": "自定义发送额外消息", - "v1.0": "根据正则转发通知到其他WeChat应用" - } - }, - "EmbyDanmu": { - "name": "Emby弹幕下载", - "description": "通知Emby Danmu插件下载弹幕。", - "labels": "Emby,媒体库", - "version": "1.6", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/danmu.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.6": "增加Emby、MoviePilot目录映射(相同可不填)", - "v1.5.1": "Emby4.8.8 Items API修改", - "v1.5": "修复获取弹幕源", - "v1.4": "修复自定义参数", - "v1.3": "适配v2多媒体服务器", - "v1.2": "检查本地弹幕文件是否已存在,避免重复下载。", - "v1.1": "解析Emby日志,判断已配置弹幕源是否全部匹配失败。", - "v1.0": "通知Emby Danmu插件下载弹幕。" - } - }, - "EmbyExtendType": { - "name": "Emby视频类型检查", - "description": "定期检查Emby媒体库中是否包含指定的视频类型,发送通知。", - "labels": "Emby,媒体库", - "version": "1.1", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/extendtype.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.1": "适配v2多媒体服务器", - "v1.0": "定期检查Emby媒体库中是否包含指定的视频类型,发送通知。" - } - }, - "EmbyAudioBook": { - "name": "Emby有声书整理", - "description": "还在为Emby有声书整理烦恼吗?入库存在很多单集?", - "labels": "Emby,媒体库", - "version": "1.4", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/audiobook.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.4": "交互命令支持多媒体库", - "v1.3": "修复自定义参数", - "v1.2": "适配v2多媒体服务器", - "v1.1": "整理完锁定,防止数据被刷新", - "v1.0": "还在为Emby有声书整理烦恼吗?入库存在很多单集。" - } - }, - "EmbyCollectionSort": { - "name": "Emby合集媒体排序", - "description": "Emby保留按照加入时间倒序的前提下,把合集中的媒体按照发布日期排序,修改加入时间已到达顺序排列的目的。", - "labels": "媒体库", - "version": "1.2", - "icon": "Element_A.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.2": "适配v2多媒体服务器", - "v1.1": "优化处理逻辑", - "v1.0": "保留按照加入时间倒序的前提下,把合集中的媒体放一块,不用到处找。" - } - }, - "EmbyActorSync": { - "name": "Emby剧集演员同步", - "description": "同步剧演员信息到集演员信息。", - "labels": "Emby,媒体库", - "version": "1.5", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/embyactorsync.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.5": "修复自定义参数", - "v1.4": "适配v2多媒体服务器", - "v1.3": "剧集优先使用季演员。", - "v1.2": "交互命令返回处理完成信息。", - "v1.1": "支持交互命令手动同步单个剧集 /as 媒体库名 剧集名。", - "v1.0": "同步剧演员信息到集演员信息。" - } - }, - "LibraryDuplicateCheck": { - "name": "Emby媒体库重复媒体检测", - "description": "媒体库重复媒体检查,可选保留规则保留其一。", - "labels": "Emby,云盘,媒体库", - "version": "2.0.1", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/libraryduplicate.png", - "author": "thsrite", - "level": 2, - "history": { - "v2.0.1": "适配v2多媒体服务器", - "v1.9": "修复删除软连接", - "v1.8": "仅检查模式下,预览操作不会删除任何文件。", - "v1.7": "修复特殊场景下删除问题", - "v1.6": "同步删除thumb图片等刮削文件", - "v1.5": "删除重复文件时再刷新媒体库逻辑", - "v1.4": "修复删除时文件不存在bug", - "v1.3": "各路径支持自定义保留规则", - "v1.2": "支持通知推送", - "v1.1": "支持自动刷新媒体库", - "v1.0": "媒体库重复媒体检查,可选择保留规则保留其一" - } - }, - "MediaSyncDel": { - "name": "媒体文件同步删除", - "description": "同步删除历史记录、源文件和下载任务。", - "labels": "媒体库,文件整理", - "version": "1.8.4", - "icon": "mediasyncdel.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.8.4": "修复暂停种子失败", - "v1.8.3": "修复源文件删除", - "v1.8.1": "适配v2多媒体服务器,移除日志方式", - "v1.7": "修复重新整理被一并删除问题", - "v1.6": "修复删除辅种", - "v1.5": "支持手动删除订阅历史记录(本次更新之后的历史)" - } - }, - "SyncDownloadFiles": { - "name": "下载器文件同步", - "description": "同步下载器的文件信息到数据库,删除文件时联动删除下载任务。", - "labels": "下载管理", - "version": "1.1.3", - "icon": "Youtube-dl_A.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.1.3": "支持v2", - "v1.1.1": "修复时区问题导致的上次同步后8h内的种子不同步的问题" - } - }, - "HomePage": { - "name": "HomePage", - "description": "HomePage自定义API。", - "labels": "工具", - "version": "1.3", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/homepage.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.3": "兼容v2", - "v1.2": "适配v1.9.1-beta(不生效就重启)", - "v1.1": "支持更多返回值、插件展示数据", - "v1.0": "HomePage自定义API" - } - }, - "FileSoftLink": { - "name": "实时软连接", - "description": "监控目录文件变化,媒体文件软连接,其他文件可选复制。", - "labels": "文件管理", - "version": "2.0.3", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/softlink.png", - "author": "thsrite", - "level": 1, - "history": { - "v2.0.3": "增加强制覆盖选项", - "v2.0.2": "兼容v2", - "v2.0.1": "不重要的更新", - "v2.0": "修复交互命令", - "v1.9.9": "交互命令更多玩法", - "v1.9.8": "新增模糊匹配交互命令", - "v1.9.7": "接收云盘实时监控处理单文件", - "v1.9.6": "优化log", - "v1.9.5": "增强交互命令", - "v1.9.4": "监控目录自定义监控模式", - "v1.9.3": "增强交互命令模糊匹配", - "v1.9.2": "增强交互命令模糊匹配", - "v1.9.1": "增强交互命令", - "v1.9": "交互命令定向软连接", - "v1.8": "修复bug", - "v1.6": "bug修复", - "v1.5": "优化性能,提高处理速度", - "v1.4": "支持自定义视频格式", - "v1.3": "异步启动" - } - }, - "Cd2Assistant": { - "name": "CloudDrive2助手", - "description": "监控上传任务,检测是否有异常,发送通知。", - "labels": "云盘", - "version": "1.8.5", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/clouddrive.png", - "author": "thsrite", - "level": 2, - "history": { - "v1.8.5": "兼容v2", - "v1.8.4": "添加115 429消息通知", - "v1.8.3": "添加异常处理,解决cd2上本地目录获取存储空间失败的问题", - "v1.8.2": "插件页面密码类型设置为pasword", - "v1.8.1": "云下载支持自定义路径 /cd /cd2路径 磁链", - "v1.8": "修复插件依赖安装问题", - "v1.7": "增加HomePage自定义API(详见插件说明)", - "v1.6": "支持交互命令云下载", - "v1.5": "增加云盘同步黑名单(排序挂载本地目录)", - "v1.4": "增加云盘存储空间展示", - "v1.3": "增加云盘Cookie失效检测", - "v1.2": "实时速率显示", - "v1.1": "交互命令重启cd2、获取cd2系统信息,支持仪表盘", - "v1.0": "监控上传任务,检测是否有异常,发送通知" - } - }, - "MediaRelease": { - "name": "影视将映订阅", - "description": "监控未上线影视作品,自动添加订阅。", - "labels": "订阅", - "version": "1.2", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/mediarelease.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.2": "兼容v2", - "v1.1": "bug修复", - "v1.0": "监控未上线影视作品,自动添加订阅。" - } - }, - "SubscribeGroup": { - "name": "订阅规则自动填充", - "description": "电视剧下载后自动添加官组等信息到订阅;添加订阅后根据二级分类名称自定义订阅规则。", - "labels": "订阅", - "version": "2.8.2", - "icon": "teamwork.png", - "author": "thsrite", - "level": 2, - "history": { - "v2.8.2": "订阅填充规则支持优先级规则组", - "v2.8.1": "修复种子下载自定义填充站点后订阅无法打开问题", - "v2.8": "兼容v2", - "v2.7": "下载填充判断当前站点是否在已选订阅站点范围内", - "v2.6": "兼容属性值包含:号", - "v2.5": "操作历史Unicode编码转中文", - "v2.4": "保存路径支持变量{name} (订阅名称 (年份))", - "v2.3": "二级分类自定义填充支持保存路径", - "v2.1": "站点与官组分开,修复质量无填充", - "v2.0": "种子下载自定义填充支持自定义占位符", - "v1.8": "修复种子下载不填充bug", - "v1.7": "操作历史Unicode编码转中文", - "v1.6": "支持一行配置多个二级分类名称", - "v1.5": "支持操作历史", - "v1.4": "支持根据二级分类名称自定义订阅规则", - "v1.3": "增加质量、分辨率、特效信息填充", - "v1.2": "修复订阅已存在包含关键词和订阅站点" - } - }, - "SqlExecute": { - "name": "Sql执行器", - "description": "自定义MoviePilot数据库Sql执行。", - "labels": "工具", - "version": "1.4", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/sqlite.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.4": "兼容v2", - "v1.3": "修复执行delete锁表失败的bug", - "v1.2": "调整交互命令返回信息", - "v1.1": "支持交互命令/sql [command]执行,需主程序1.9.4+", - "v1.0": "自定义MoviePilot数据库Sql执行" - } - }, - "CommandExecute": { - "name": "命令执行器", - "description": "自定义容器命令执行。", - "labels": "工具", - "version": "1.3", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/command.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.3": "兼容v2", - "v1.2": "调整交互命令返回信息", - "v1.1": "支持交互命令/cmd [sql]执行,需主程序1.9.4+", - "v1.0": "自定义容器命令执行" - } - }, - "AutoBackup": { - "name": "自动备份", - "description": "自动备份数据和配置文件。", - "labels": "系统设置", - "version": "2.0.1", - "icon": "Time_machine_B.png", - "author": "thsrite", - "level": 1, - "history": { - "v2.0.1": "修复cookies文件夹备份失败", - "v2.0": "支持备份app.env及cookies,支持自定义保存路径", - "v1.3": "去除已废弃的环境变量引用", - "v1.2": "增强API安全性" - } - }, - "CloudLinkMonitor": { - "name": "目录实时监控", - "description": "监控云盘目录文件变化,自动转移媒体文件。", - "labels": "云盘,工具", - "version": "2.5.1", - "icon": "Linkease_A.png", - "author": "thsrite", - "level": 1, - "history": { - "v2.5.1": "修复媒体刮削", - "v2.5": "兼容v2", - "v2.4.5": "联动实时软连接插件(近媒体文件)", - "v2.4.4": "修复刷新媒体库", - "v2.4.3": "可选转移完刷新媒体库", - "v2.4.2": "fix #65", - "v2.4.1": "增加log", - "v2.4": "修复二级目录", - "v2.3": "去除无效变量", - "v2.2": "优化配置一二级分类流程", - "v2.1": "可配置是否存储转移记录", - "v2.0": "修复不刮削不生效bug", - "v1.8": "fix S00转移", - "v1.7": "fix 刮削", - "v1.6": "可配置是否刮削", - "v1.5": "fix 消息推送", - "v1.4": "fix 转移后路径", - "v1.3": "修复bug", - "v1.2": "修复订阅重复处理的bug", - "v1.1": "自动转移链接(不刮削)", - "v1.0": "监控云盘目录文件变化,按原文件名软连接" - } - }, - "CloudStrmCompanion": { - "name": "云盘Strm助手", - "description": "实时监控、定时全量增量生成strm文件。", - "labels": "云盘", - "version": "1.0.5", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/cloudcompanion.png", - "author": "thsrite", - "level": 1, - "history": { - "v1.0.5": "增加复制非媒体文件选项", - "v1.0.4": "修复实时监控,只处理指定类型的文件", - "v1.0.3": "修复重建索引缓存", - "v1.0.2": "增加可玩性交互命令", - "v1.0": "实时监控、定时全量增量生成strm文件" - } - }, - "StrmRedirect": { - "name": "Strm重定向", - "description": "重写Strm文件内容。", - "labels": "云盘", - "version": "1.0", - "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/softlinkredirect.png", - "author": "thsrite", - "level": 1, - "v2": true, - "history": { - "v1.0": "重写Strm文件内容" - } - } } diff --git a/plugins.v2/filesoftlink/__init__.py b/plugins.v2/filesoftlink/__init__.py index 3e2a0b6..bd00115 100644 --- a/plugins.v2/filesoftlink/__init__.py +++ b/plugins.v2/filesoftlink/__init__.py @@ -4,6 +4,7 @@ import re import shutil import threading import traceback +import time from pathlib import Path from typing import List, Tuple, Dict, Any, Optional @@ -37,12 +38,20 @@ class FileMonitorHandler(FileSystemEventHandler): self.sync = sync def on_created(self, event): - self.sync.event_handler(event=event, text="创建", - mon_path=self._watch_path, event_path=event.src_path) + self.sync.event_handler( + event=event, + text="创建", + mon_path=self._watch_path, + event_path=event.src_path, + ) def on_moved(self, event): - self.sync.event_handler(event=event, text="移动", - mon_path=self._watch_path, event_path=event.dest_path) + self.sync.event_handler( + event=event, + text="移动", + mon_path=self._watch_path, + event_path=event.dest_path, + ) class FileSoftLink(_PluginBase): @@ -53,7 +62,7 @@ class FileSoftLink(_PluginBase): # 插件图标 plugin_icon = "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/softlink.png" # 插件版本 - plugin_version = "2.0.3" + plugin_version = "2.0.4" # 插件作者 plugin_author = "thsrite" # 作者主页 @@ -75,6 +84,7 @@ class FileSoftLink(_PluginBase): _url = None _force = None _size = 0 + _sync_interval = 0 # 模式 compatibility/fast _mode = "compatibility" _monitor_dirs = "" @@ -105,8 +115,11 @@ class FileSoftLink(_PluginBase): self._url = config.get("url") self._force = config.get("force") self._size = config.get("size") or 0 - self._rmt_mediaext = config.get( - "rmt_mediaext") or ".mp4, .mkv, .ts, .iso,.rmvb, .avi, .mov, .mpeg,.mpg, .wmv, .3gp, .asf, .m4v, .flv, .m2ts, .strm,.tp, .f4v" + self._sync_interval = float(config.get("sync_interval")) + self._rmt_mediaext = ( + config.get("rmt_mediaext") + or ".mp4, .mkv, .ts, .iso,.rmvb, .avi, .mov, .mpeg,.mpg, .wmv, .3gp, .asf, .m4v, .flv, .m2ts, .strm,.tp, .f4v" + ) # 停止现有任务 self.stop_service() @@ -137,8 +150,10 @@ class FileSoftLink(_PluginBase): # 存储目的目录 if SystemUtils.is_windows(): if mon_path.count(":") > 1: - paths = [mon_path.split(":")[0] + ":" + mon_path.split(":")[1], - mon_path.split(":")[2] + ":" + mon_path.split(":")[3]] + paths = [ + mon_path.split(":")[0] + ":" + mon_path.split(":")[1], + mon_path.split(":")[2] + ":" + mon_path.split(":")[3], + ] else: paths = [mon_path] else: @@ -160,8 +175,12 @@ class FileSoftLink(_PluginBase): # 检查媒体库目录是不是下载目录的子目录 try: if target_path and target_path.is_relative_to(Path(mon_path)): - logger.warn(f"{target_path} 是监控目录 {mon_path} 的子目录,无法监控") - self.systemmessage.put(f"{target_path} 是下载目录 {mon_path} 的子目录,无法监控") + logger.warn( + f"{target_path} 是监控目录 {mon_path} 的子目录,无法监控" + ) + self.systemmessage.put( + f"{target_path} 是下载目录 {mon_path} 的子目录,无法监控" + ) continue except Exception as e: logger.debug(str(e)) @@ -170,23 +189,31 @@ class FileSoftLink(_PluginBase): # 异步开启云盘监控 self._mode = monitor or self._mode if str(self._mode) != "nomonitor": - logger.info(f"异步开启实时软连接链接 {mon_path} {self._mode},延迟3s启动") - self._scheduler.add_job(func=self.start_monitor, trigger='date', - run_date=datetime.datetime.now( - tz=pytz.timezone(settings.TZ)) + datetime.timedelta(seconds=3), - name=f"实时软连接 {mon_path}", - kwargs={ - "source_dir": mon_path - }) + logger.info( + f"异步开启实时软连接链接 {mon_path} {self._mode},延迟3s启动" + ) + self._scheduler.add_job( + func=self.start_monitor, + trigger="date", + run_date=datetime.datetime.now( + tz=pytz.timezone(settings.TZ) + ) + + datetime.timedelta(seconds=3), + name=f"实时软连接 {mon_path}", + kwargs={"source_dir": mon_path}, + ) else: logger.info(f"{mon_path} 实时软链接服务已关闭") # 运行一次定时服务 if self._onlyonce: logger.info("实时软连接服务启动,立即运行一次") - self._scheduler.add_job(name="实时软连接", func=self.sync_all, trigger='date', - run_date=datetime.datetime.now( - tz=pytz.timezone(settings.TZ)) + datetime.timedelta(seconds=3) - ) + self._scheduler.add_job( + name="实时软连接", + func=self.sync_all, + trigger="date", + run_date=datetime.datetime.now(tz=pytz.timezone(settings.TZ)) + + datetime.timedelta(seconds=3), + ) # 关闭一次性开关 self._onlyonce = False # 保存配置 @@ -209,7 +236,9 @@ class FileSoftLink(_PluginBase): # 内部处理系统操作类型选择最优解 observer = Observer(timeout=10) self._observer.append(observer) - observer.schedule(FileMonitorHandler(source_dir, self), path=source_dir, recursive=True) + observer.schedule( + FileMonitorHandler(source_dir, self), path=source_dir, recursive=True + ) observer.daemon = True observer.start() logger.info(f"{source_dir} 的实时软链接服务启动") @@ -222,7 +251,8 @@ class FileSoftLink(_PluginBase): echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf echo fs.inotify.max_user_instances=524288 | sudo tee -a /etc/sysctl.conf sudo sysctl -p - """) + """ + ) else: logger.error(f"{source_dir} 启动云盘监控失败:{err_msg}") self.systemmessage.put(f"{source_dir} 启动云盘监控失败:{err_msg}") @@ -231,19 +261,22 @@ class FileSoftLink(_PluginBase): """ 更新配置 """ - self.update_config({ - "enabled": self._enabled, - "onlyonce": self._onlyonce, - "copy_files": self._copy_files, - "mode": self._mode, - "monitor_dirs": self._monitor_dirs, - "exclude_keywords": self._exclude_keywords, - "cron": self._cron, - "url": self._url, - "force": self._force, - "size": self._size, - "rmt_mediaext": self._rmt_mediaext - }) + self.update_config( + { + "enabled": self._enabled, + "onlyonce": self._onlyonce, + "copy_files": self._copy_files, + "mode": self._mode, + "monitor_dirs": self._monitor_dirs, + "exclude_keywords": self._exclude_keywords, + "cron": self._cron, + "url": self._url, + "force": self._force, + "size": self._size, + "sync_interval": self._sync_interval, + "rmt_mediaext": self._rmt_mediaext, + } + ) @eventmanager.register(EventType.PluginAction) def remote_sync(self, event: Event): @@ -254,13 +287,18 @@ class FileSoftLink(_PluginBase): event_data = event.event_data if not event_data or event_data.get("action") != "softlink_sync": return - self.post_message(channel=event.event_data.get("channel"), - title="开始同步监控目录 ...", - userid=event.event_data.get("user")) + self.post_message( + channel=event.event_data.get("channel"), + title="开始同步监控目录 ...", + userid=event.event_data.get("user"), + ) self.sync_all() if event: - self.post_message(channel=event.event_data.get("channel"), - title="监控目录同步完成!", userid=event.event_data.get("user")) + self.post_message( + channel=event.event_data.get("channel"), + title="监控目录同步完成!", + userid=event.event_data.get("user"), + ) @eventmanager.register(EventType.PluginAction) def softlink_file(self, event: Event = None): @@ -292,7 +330,9 @@ class FileSoftLink(_PluginBase): if event: event_data = event.event_data if not event_data or ( - event_data.get("action") != "softlink_one" and event_data.get("action") != "softlink_all"): + event_data.get("action") != "softlink_one" + and event_data.get("action") != "softlink_all" + ): return args = event_data.get("arg_str") if not args: @@ -312,7 +352,11 @@ class FileSoftLink(_PluginBase): if category: # 判断是不是目录 - if Path(category).is_dir() and Path(category).exists() and limit is not None: + if ( + Path(category).is_dir() + and Path(category).exists() + and limit is not None + ): # 遍历所有监控目录 mon_path = None for mon in self._dirconf.keys(): @@ -323,12 +367,16 @@ class FileSoftLink(_PluginBase): # 指定路径软连接 if not mon_path: logger.error(f"未找到 {category} 对应的监控目录") - self.post_message(channel=event.event_data.get("channel"), - title=f"未找到 {category} 对应的监控目录", - userid=event.event_data.get("user")) + self.post_message( + channel=event.event_data.get("channel"), + title=f"未找到 {category} 对应的监控目录", + userid=event.event_data.get("user"), + ) return - self.__handle_limit(path=category, mon_path=mon_path, limit=limit, event=event) + self.__handle_limit( + path=category, mon_path=mon_path, limit=limit, event=event + ) return else: for mon_path in self._categoryconf.keys(): @@ -337,18 +385,33 @@ class FileSoftLink(_PluginBase): if mon_category and str(category) in mon_category: parent_path = os.path.join(mon_path, category) if limit: - logger.info(f"获取到 {category} 对应的监控目录 {parent_path}") - self.__handle_limit(path=parent_path, mon_path=mon_path, limit=limit, event=event) + logger.info( + f"获取到 {category} 对应的监控目录 {parent_path}" + ) + self.__handle_limit( + path=parent_path, + mon_path=mon_path, + limit=limit, + event=event, + ) else: - logger.info(f"获取到 {category} {args} 对应的监控目录 {parent_path}") + logger.info( + f"获取到 {category} {args} 对应的监控目录 {parent_path}" + ) target_path = os.path.join(str(parent_path), args) logger.info(f"开始处理 {target_path}") - target_paths = self.__find_related_paths(os.path.join(str(parent_path), args)) + target_paths = self.__find_related_paths( + os.path.join(str(parent_path), args) + ) if not target_paths: - logger.error(f"未查找到 {category} {args} 对应的具体目录") - self.post_message(channel=event.event_data.get("channel"), - title=f"未查找到 {category} {args} 对应的具体目录", - userid=event.event_data.get("user")) + logger.error( + f"未查找到 {category} {args} 对应的具体目录" + ) + self.post_message( + channel=event.event_data.get("channel"), + title=f"未查找到 {category} {args} 对应的具体目录", + userid=event.event_data.get("user"), + ) return for target_path in target_paths: logger.info(f"开始定向处理文件夹 ...{target_path}") @@ -356,14 +419,24 @@ class FileSoftLink(_PluginBase): for file_name in sdirs + sfiles: src_file = os.path.join(sroot, file_name) if Path(src_file).is_file(): - self.__handle_file(event_path=str(src_file), mon_path=mon_path) + self.__handle_file( + event_path=str(src_file), + mon_path=mon_path, + ) + time.sleep(self._sync_interval) if event.event_data.get("user"): - self.post_message(channel=event.event_data.get("channel"), - title=f"{target_path} 软连接完成!", - userid=event.event_data.get("user")) + self.post_message( + channel=event.event_data.get("channel"), + title=f"{target_path} 软连接完成!", + userid=event.event_data.get("user"), + ) - if limit is None and event_data and event_data.get("action") == "softlink_one": + if ( + limit is None + and event_data + and event_data.get("action") == "softlink_one" + ): return return else: @@ -392,10 +465,17 @@ class FileSoftLink(_PluginBase): for file_name in sdirs + sfiles: src_file = os.path.join(sroot, file_name) if Path(str(src_file)).is_file(): - self.__handle_file(event_path=str(src_file), mon_path=mon_path) + self.__handle_file( + event_path=str(src_file), mon_path=mon_path + ) + logger.info(f"等待 {self._sync_interval} 秒") + time.sleep(self._sync_interval) if event.event_data.get("user"): - self.post_message(channel=event.event_data.get("channel"), - title=f"{all_args} 软连接完成!", userid=event.event_data.get("user")) + self.post_message( + channel=event.event_data.get("channel"), + title=f"{all_args} 软连接完成!", + userid=event.event_data.get("user"), + ) return else: for mon_path in self._categoryconf.keys(): @@ -408,16 +488,24 @@ class FileSoftLink(_PluginBase): for file_name in sdirs + sfiles: src_file = os.path.join(sroot, file_name) if Path(str(src_file)).is_file(): - self.__handle_file(event_path=str(src_file), mon_path=mon_path) + self.__handle_file( + event_path=str(src_file), mon_path=mon_path + ) + logger.info(f"等待 {self._sync_interval} 秒") + time.sleep(self._sync_interval) if event.event_data.get("user"): - self.post_message(channel=event.event_data.get("channel"), - title=f"{all_args} 软连接完成!", - userid=event.event_data.get("user")) + self.post_message( + channel=event.event_data.get("channel"), + title=f"{all_args} 软连接完成!", + userid=event.event_data.get("user"), + ) return if event.event_data.get("user"): - self.post_message(channel=event.event_data.get("channel"), - title=f"{all_args} 未检索到,请检查输入是否正确!", - userid=event.event_data.get("user")) + self.post_message( + channel=event.event_data.get("channel"), + title=f"{all_args} 未检索到,请检查输入是否正确!", + userid=event.event_data.get("user"), + ) def __handle_limit(self, path, limit, mon_path, event): """ @@ -443,9 +531,14 @@ class FileSoftLink(_PluginBase): src_file = os.path.join(sroot, file_name) if Path(src_file).is_file(): self.__handle_file(event_path=str(src_file), mon_path=mon_path) + logger.info(f"等待 {self._sync_interval} 秒") + time.sleep(self._sync_interval) if event.event_data.get("user"): - self.post_message(channel=event.event_data.get("channel"), - title=f"{sub_path} 软连接完成!", userid=event.event_data.get("user")) + self.post_message( + channel=event.event_data.get("channel"), + title=f"{sub_path} 软连接完成!", + userid=event.event_data.get("user"), + ) @staticmethod def __find_related_paths(base_path): @@ -468,16 +561,21 @@ class FileSoftLink(_PluginBase): """ 立即运行一次,全量同步目录中所有文件 """ - logger.info("开始全量同步监控目录 ...") - # 遍历所有监控目录 - for mon_path in self._dirconf.keys(): - # 遍历目录下所有文件 - for root, dirs, files in os.walk(mon_path): - for name in dirs + files: - path = os.path.join(root, name) - if Path(path).is_file(): - self.__handle_file(event_path=str(path), mon_path=mon_path) - logger.info("全量同步监控目录完成!") + try: + logger.info("开始全量同步监控目录 ...") + # 遍历所有监控目录 + for mon_path in self._dirconf.keys(): + # 遍历目录下所有文件 + for root, dirs, files in os.walk(mon_path): + for name in dirs + files: + path = os.path.join(root, name) + if Path(path).is_file(): + self.__handle_file(event_path=str(path), mon_path=mon_path) + logger.info(f"等待 {self._sync_interval} 秒") + time.sleep(self._sync_interval) + logger.info("全量同步监控目录完成!") + except Exception as result: + logger.error(f"全量同步监控目录失败:{result}") def event_handler(self, event, mon_path: str, text: str, event_path: str): """ @@ -505,10 +603,12 @@ class FileSoftLink(_PluginBase): # 全程加锁 with lock: # 回收站及隐藏的文件不处理 - if event_path.find('/@Recycle/') != -1 \ - or event_path.find('/#recycle/') != -1 \ - or event_path.find('/.') != -1 \ - or event_path.find('/@eaDir') != -1: + if ( + event_path.find("/@Recycle/") != -1 + or event_path.find("/#recycle/") != -1 + or event_path.find("/.") != -1 + or event_path.find("/@eaDir") != -1 + ): logger.debug(f"{event_path} 是回收站或隐藏的文件") return @@ -516,28 +616,42 @@ class FileSoftLink(_PluginBase): if self._exclude_keywords: for keyword in self._exclude_keywords.split("\n"): if keyword and re.findall(keyword, event_path): - logger.info(f"{event_path} 命中过滤关键字 {keyword},不处理") + logger.info( + f"{event_path} 命中过滤关键字 {keyword},不处理" + ) return # 整理屏蔽词不处理 - transfer_exclude_words = self.systemconfig.get(SystemConfigKey.TransferExcludeWords) + transfer_exclude_words = self.systemconfig.get( + SystemConfigKey.TransferExcludeWords + ) if transfer_exclude_words: for keyword in transfer_exclude_words: if not keyword: continue - if keyword and re.search(r"%s" % keyword, event_path, re.IGNORECASE): - logger.info(f"{event_path} 命中整理屏蔽词 {keyword},不处理") + if keyword and re.search( + r"%s" % keyword, event_path, re.IGNORECASE + ): + logger.info( + f"{event_path} 命中整理屏蔽词 {keyword},不处理" + ) return # 判断是不是蓝光目录 if re.search(r"BDMV[/\\]STREAM", event_path, re.IGNORECASE): # 截取BDMV前面的路径 - blurray_dir = event_path[:event_path.find("BDMV")] + blurray_dir = event_path[: event_path.find("BDMV")] file_path = Path(blurray_dir) - logger.info(f"{event_path} 是蓝光目录,更正文件路径为:{str(file_path)}") + logger.info( + f"{event_path} 是蓝光目录,更正文件路径为:{str(file_path)}" + ) # 判断文件大小 - if self._size and float(self._size) > 0 and file_path.stat().st_size < float(self._size) * 1024 ** 3: + if ( + self._size + and float(self._size) > 0 + and file_path.stat().st_size < float(self._size) * 1024**3 + ): logger.info(f"{file_path} 文件大小小于监控文件大小,不处理") return @@ -570,20 +684,27 @@ class FileSoftLink(_PluginBase): os.makedirs(Path(target_file).parent) # 媒体文件软连接 - if Path(target_file).suffix.lower() in [ext.strip() for ext in - self._rmt_mediaext.split(",")]: - retcode, retmsg = SystemUtils.softlink(file_path, Path(target_file)) - logger.info(f"创建媒体文件软连接 {str(file_path)} 到 {target_file} {retcode} {retmsg}") + if Path(target_file).suffix.lower() in [ + ext.strip() for ext in self._rmt_mediaext.split(",") + ]: + retcode, retmsg = SystemUtils.softlink( + file_path, Path(target_file) + ) + logger.info( + f"创建媒体文件软连接 {str(file_path)} 到 {target_file} {retcode} {retmsg}" + ) if self._url and file_path.suffix in settings.RMT_MEDIAEXT: - RequestUtils(content_type="application/json").post(url=self._url, json={ - "path": str(file_path), - "type": "add" - }) + RequestUtils(content_type="application/json").post( + url=self._url, + json={"path": str(file_path), "type": "add"}, + ) else: if self._copy_files: # 其他nfo、jpg等复制文件 shutil.copy2(str(file_path), target_file) - logger.info(f"复制其他文件 {str(file_path)} 到 {target_file}") + logger.info( + f"复制其他文件 {str(file_path)} 到 {target_file}" + ) except Exception as e: logger.error("软连接发生错误:%s - %s" % (str(e), traceback.format_exc())) @@ -602,38 +723,34 @@ class FileSoftLink(_PluginBase): "event": EventType.PluginAction, "desc": "文件软连接同步", "category": "", - "data": { - "action": "softlink_sync" - } + "data": {"action": "softlink_sync"}, }, { "cmd": "/soft", "event": EventType.PluginAction, "desc": "定向软连接处理", "category": "", - "data": { - "action": "softlink_one" - } + "data": {"action": "softlink_one"}, }, { "cmd": "/softall", "event": EventType.PluginAction, "desc": "定向软连接处理", "category": "", - "data": { - "action": "softlink_all" - } - } + "data": {"action": "softlink_all"}, + }, ] def get_api(self) -> List[Dict[str, Any]]: - return [{ - "path": "/softlink_sync", - "endpoint": self.sync, - "methods": ["GET"], - "summary": "实时软连接同步", - "description": "实时软连接同步", - }] + return [ + { + "path": "/softlink_sync", + "endpoint": self.sync, + "methods": ["GET"], + "summary": "实时软连接同步", + "description": "实时软连接同步", + } + ] def get_service(self) -> List[Dict[str, Any]]: """ @@ -647,13 +764,15 @@ class FileSoftLink(_PluginBase): }] """ if self._enabled and self._cron: - return [{ - "id": "FileSoftLink", - "name": "实时软连接全量同步服务", - "trigger": CronTrigger.from_crontab(self._cron), - "func": self.sync_all, - "kwargs": {} - }] + return [ + { + "id": "FileSoftLink", + "name": "实时软连接全量同步服务", + "trigger": CronTrigger.from_crontab(self._cron), + "func": self.sync_all, + "kwargs": {}, + } + ] return [] def sync(self) -> schemas.Response: @@ -666,251 +785,246 @@ class FileSoftLink(_PluginBase): def get_form(self) -> Tuple[List[dict], Dict[str, Any]]: return [ { - 'component': 'VForm', - 'content': [ + "component": "VForm", + "content": [ { - 'component': 'VRow', - 'content': [ + "component": "VRow", + "content": [ { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ + "component": "VCol", + "props": {"cols": 12, "md": 4}, + "content": [ { - 'component': 'VSwitch', - 'props': { - 'model': 'enabled', - 'label': '启用插件', - } + "component": "VSwitch", + "props": { + "model": "enabled", + "label": "启用插件", + }, } - ] + ], }, { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ + "component": "VCol", + "props": {"cols": 12, "md": 4}, + "content": [ { - 'component': 'VSwitch', - 'props': { - 'model': 'onlyonce', - 'label': '立即运行一次', - } + "component": "VSwitch", + "props": { + "model": "onlyonce", + "label": "立即运行一次", + }, } - ] + ], }, { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ + "component": "VCol", + "props": {"cols": 12, "md": 4}, + "content": [ { - 'component': 'VSwitch', - 'props': { - 'model': 'copy_files', - 'label': '复制非媒体文件', - } + "component": "VSwitch", + "props": { + "model": "copy_files", + "label": "复制非媒体文件", + }, } - ] - } - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ - { - 'component': 'VSwitch', - 'props': { - 'model': 'force', - 'label': '强制覆盖', - } - } - ] + ], }, - ] + ], }, { - 'component': 'VRow', - 'content': [ + "component": "VRow", + "content": [ { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ + "component": "VCol", + "props": {"cols": 12, "md": 4}, + "content": [ { - 'component': 'VSelect', - 'props': { - 'model': 'mode', - 'label': '监控模式', - 'items': [ - {'title': '兼容模式', 'value': 'compatibility'}, - {'title': '性能模式', 'value': 'fast'}, - {'title': '不监控', 'value': 'nomonitor'}, - ] - } + "component": "VSwitch", + "props": { + "model": "force", + "label": "强制覆盖", + }, } - ] + ], + }, + ], + }, + { + "component": "VRow", + "content": [ + { + "component": "VCol", + "props": {"cols": 12, "md": 4}, + "content": [ + { + "component": "VSelect", + "props": { + "model": "mode", + "label": "监控模式", + "items": [ + { + "title": "兼容模式", + "value": "compatibility", + }, + {"title": "性能模式", "value": "fast"}, + { + "title": "不监控", + "value": "nomonitor", + }, + ], + }, + } + ], }, { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ + "component": "VCol", + "props": {"cols": 12, "md": 4}, + "content": [ { - 'component': 'VTextField', - 'props': { - 'model': 'cron', - 'label': '定时全量同步周期', - 'placeholder': '5位cron表达式,留空关闭' - } + "component": "VTextField", + "props": { + "model": "cron", + "label": "定时全量同步周期", + "placeholder": "5位cron表达式,留空关闭", + }, } - ] + ], }, { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ + "component": "VCol", + "props": {"cols": 12, "md": 4}, + "content": [ { - 'component': 'VTextField', - 'props': { - 'model': 'size', - 'label': '监控文件大小(GB)', - 'placeholder': '0' - } + "component": "VTextField", + "props": { + "model": "size", + "label": "监控文件大小(GB)", + "placeholder": "0", + }, } - ] - } - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12 - }, - 'content': [ - { - 'component': 'VTextarea', - 'props': { - 'model': 'monitor_dirs', - 'label': '监控目录', - 'rows': 5, - 'placeholder': '监控目录:转移目的目录' - } - } - ] - } - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12, - }, - 'content': [ - { - 'component': 'VTextarea', - 'props': { - 'model': 'exclude_keywords', - 'label': '排除关键词', - 'rows': 2, - 'placeholder': '每一行一个关键词' - } - } - ] - } - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12 - }, - 'content': [ - { - 'component': 'VTextarea', - 'props': { - 'model': 'rmt_mediaext', - 'label': '视频格式', - 'rows': 2, - 'placeholder': ".mp4, .mkv, .ts, .iso,.rmvb, .avi, .mov, .mpeg,.mpg, .wmv, .3gp, .asf, .m4v, .flv, .m2ts, .strm,.tp, .f4v" - } - } - ] - } - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12, - }, - 'content': [ - { - 'component': 'VTextField', - 'props': { - 'model': 'url', - 'label': '任务推送url', - 'placeholder': 'post请求json方式推送path和type(add)字段' - } - } - ] + ], }, - ] + { + "component": "VCol", + "props": {"cols": 12, "md": 4}, + "content": [ + { + "component": "VTextField", + "props": { + "model": "sync_interval", + "label": "同步遍历文件间隔(s)", + "placeholder": "0", + }, + } + ], + }, + ], }, { - 'component': 'VRow', - 'content': [ + "component": "VRow", + "content": [ { - 'component': 'VCol', - 'props': { - 'cols': 12, - }, - 'content': [ + "component": "VCol", + "props": {"cols": 12}, + "content": [ { - 'component': 'VAlert', - 'props': { - 'type': 'info', - 'variant': 'tonal', - 'text': '监控文件大小:单位GB,0为不开启,低于监控文件大小的文件不会被监控转移。' - } + "component": "VTextarea", + "props": { + "model": "monitor_dirs", + "label": "监控目录", + "rows": 5, + "placeholder": "监控目录:转移目的目录", + }, } - ] + ], } - ] - } - ] + ], + }, + { + "component": "VRow", + "content": [ + { + "component": "VCol", + "props": { + "cols": 12, + }, + "content": [ + { + "component": "VTextarea", + "props": { + "model": "exclude_keywords", + "label": "排除关键词", + "rows": 2, + "placeholder": "每一行一个关键词", + }, + } + ], + } + ], + }, + { + "component": "VRow", + "content": [ + { + "component": "VCol", + "props": {"cols": 12}, + "content": [ + { + "component": "VTextarea", + "props": { + "model": "rmt_mediaext", + "label": "视频格式", + "rows": 2, + "placeholder": ".mp4, .mkv, .ts, .iso,.rmvb, .avi, .mov, .mpeg,.mpg, .wmv, .3gp, .asf, .m4v, .flv, .m2ts, .strm,.tp, .f4v", + }, + } + ], + } + ], + }, + { + "component": "VRow", + "content": [ + { + "component": "VCol", + "props": { + "cols": 12, + }, + "content": [ + { + "component": "VTextField", + "props": { + "model": "url", + "label": "任务推送url", + "placeholder": "post请求json方式推送path和type(add)字段", + }, + } + ], + }, + ], + }, + { + "component": "VRow", + "content": [ + { + "component": "VCol", + "props": { + "cols": 12, + }, + "content": [ + { + "component": "VAlert", + "props": { + "type": "info", + "variant": "tonal", + "text": "监控文件大小:单位GB,0为不开启,低于监控文件大小的文件不会被监控转移。", + }, + } + ], + } + ], + }, + ], } ], { "enabled": False, @@ -922,8 +1036,9 @@ class FileSoftLink(_PluginBase): "exclude_keywords": "", "cron": "", "size": 0, + "sync_interval": 0, "url": "", - "rmt_mediaext": ".mp4, .mkv, .ts, .iso,.rmvb, .avi, .mov, .mpeg,.mpg, .wmv, .3gp, .asf, .m4v, .flv, .m2ts, .strm,.tp, .f4v" + "rmt_mediaext": ".mp4, .mkv, .ts, .iso,.rmvb, .avi, .mov, .mpeg,.mpg, .wmv, .3gp, .asf, .m4v, .flv, .m2ts, .strm,.tp, .f4v", } def get_page(self) -> List[dict]: diff --git a/plugins/filesoftlink/__init__.py b/plugins/filesoftlink/__init__.py index 89cadbe..afd10d2 100644 --- a/plugins/filesoftlink/__init__.py +++ b/plugins/filesoftlink/__init__.py @@ -4,6 +4,7 @@ import re import shutil import threading import traceback +import time from pathlib import Path from typing import List, Tuple, Dict, Any, Optional @@ -37,12 +38,20 @@ class FileMonitorHandler(FileSystemEventHandler): self.sync = sync def on_created(self, event): - self.sync.event_handler(event=event, text="创建", - mon_path=self._watch_path, event_path=event.src_path) + self.sync.event_handler( + event=event, + text="创建", + mon_path=self._watch_path, + event_path=event.src_path, + ) def on_moved(self, event): - self.sync.event_handler(event=event, text="移动", - mon_path=self._watch_path, event_path=event.dest_path) + self.sync.event_handler( + event=event, + text="移动", + mon_path=self._watch_path, + event_path=event.dest_path, + ) class FileSoftLink(_PluginBase): @@ -53,7 +62,7 @@ class FileSoftLink(_PluginBase): # 插件图标 plugin_icon = "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/softlink.png" # 插件版本 - plugin_version = "2.0.1" + plugin_version = "2.0.2" # 插件作者 plugin_author = "thsrite" # 作者主页 @@ -71,6 +80,7 @@ class FileSoftLink(_PluginBase): _enabled = False _onlyonce = False _copy_files = False + _sync_interval = 0 _cron = None _url = None _size = 0 @@ -97,14 +107,17 @@ class FileSoftLink(_PluginBase): self._enabled = config.get("enabled") self._onlyonce = config.get("onlyonce") self._copy_files = config.get("copy_files") + self._sync_interval = float(config.get("sync_interval")) self._mode = config.get("mode") self._monitor_dirs = config.get("monitor_dirs") or "" self._exclude_keywords = config.get("exclude_keywords") or "" self._cron = config.get("cron") self._url = config.get("url") self._size = config.get("size") or 0 - self._rmt_mediaext = config.get( - "rmt_mediaext") or ".mp4, .mkv, .ts, .iso,.rmvb, .avi, .mov, .mpeg,.mpg, .wmv, .3gp, .asf, .m4v, .flv, .m2ts, .strm,.tp, .f4v" + self._rmt_mediaext = ( + config.get("rmt_mediaext") + or ".mp4, .mkv, .ts, .iso,.rmvb, .avi, .mov, .mpeg,.mpg, .wmv, .3gp, .asf, .m4v, .flv, .m2ts, .strm,.tp, .f4v" + ) # 停止现有任务 self.stop_service() @@ -135,8 +148,10 @@ class FileSoftLink(_PluginBase): # 存储目的目录 if SystemUtils.is_windows(): if mon_path.count(":") > 1: - paths = [mon_path.split(":")[0] + ":" + mon_path.split(":")[1], - mon_path.split(":")[2] + ":" + mon_path.split(":")[3]] + paths = [ + mon_path.split(":")[0] + ":" + mon_path.split(":")[1], + mon_path.split(":")[2] + ":" + mon_path.split(":")[3], + ] else: paths = [mon_path] else: @@ -158,8 +173,12 @@ class FileSoftLink(_PluginBase): # 检查媒体库目录是不是下载目录的子目录 try: if target_path and target_path.is_relative_to(Path(mon_path)): - logger.warn(f"{target_path} 是监控目录 {mon_path} 的子目录,无法监控") - self.systemmessage.put(f"{target_path} 是下载目录 {mon_path} 的子目录,无法监控") + logger.warn( + f"{target_path} 是监控目录 {mon_path} 的子目录,无法监控" + ) + self.systemmessage.put( + f"{target_path} 是下载目录 {mon_path} 的子目录,无法监控" + ) continue except Exception as e: logger.debug(str(e)) @@ -168,23 +187,31 @@ class FileSoftLink(_PluginBase): # 异步开启云盘监控 self._mode = monitor or self._mode if str(self._mode) != "nomonitor": - logger.info(f"异步开启实时软连接链接 {mon_path} {self._mode},延迟3s启动") - self._scheduler.add_job(func=self.start_monitor, trigger='date', - run_date=datetime.datetime.now( - tz=pytz.timezone(settings.TZ)) + datetime.timedelta(seconds=3), - name=f"实时软连接 {mon_path}", - kwargs={ - "source_dir": mon_path - }) + logger.info( + f"异步开启实时软连接链接 {mon_path} {self._mode},延迟3s启动" + ) + self._scheduler.add_job( + func=self.start_monitor, + trigger="date", + run_date=datetime.datetime.now( + tz=pytz.timezone(settings.TZ) + ) + + datetime.timedelta(seconds=3), + name=f"实时软连接 {mon_path}", + kwargs={"source_dir": mon_path}, + ) else: logger.info(f"{mon_path} 实时软链接服务已关闭") # 运行一次定时服务 if self._onlyonce: logger.info("实时软连接服务启动,立即运行一次") - self._scheduler.add_job(name="实时软连接", func=self.sync_all, trigger='date', - run_date=datetime.datetime.now( - tz=pytz.timezone(settings.TZ)) + datetime.timedelta(seconds=3) - ) + self._scheduler.add_job( + name="实时软连接", + func=self.sync_all, + trigger="date", + run_date=datetime.datetime.now(tz=pytz.timezone(settings.TZ)) + + datetime.timedelta(seconds=3), + ) # 关闭一次性开关 self._onlyonce = False # 保存配置 @@ -207,7 +234,9 @@ class FileSoftLink(_PluginBase): # 内部处理系统操作类型选择最优解 observer = Observer(timeout=10) self._observer.append(observer) - observer.schedule(FileMonitorHandler(source_dir, self), path=source_dir, recursive=True) + observer.schedule( + FileMonitorHandler(source_dir, self), path=source_dir, recursive=True + ) observer.daemon = True observer.start() logger.info(f"{source_dir} 的实时软链接服务启动") @@ -220,7 +249,8 @@ class FileSoftLink(_PluginBase): echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf echo fs.inotify.max_user_instances=524288 | sudo tee -a /etc/sysctl.conf sudo sysctl -p - """) + """ + ) else: logger.error(f"{source_dir} 启动云盘监控失败:{err_msg}") self.systemmessage.put(f"{source_dir} 启动云盘监控失败:{err_msg}") @@ -229,18 +259,21 @@ class FileSoftLink(_PluginBase): """ 更新配置 """ - self.update_config({ - "enabled": self._enabled, - "onlyonce": self._onlyonce, - "copy_files": self._copy_files, - "mode": self._mode, - "monitor_dirs": self._monitor_dirs, - "exclude_keywords": self._exclude_keywords, - "cron": self._cron, - "url": self._url, - "size": self._size, - "rmt_mediaext": self._rmt_mediaext - }) + self.update_config( + { + "enabled": self._enabled, + "onlyonce": self._onlyonce, + "copy_files": self._copy_files, + "sync_interval": self._sync_interval, + "mode": self._mode, + "monitor_dirs": self._monitor_dirs, + "exclude_keywords": self._exclude_keywords, + "cron": self._cron, + "url": self._url, + "size": self._size, + "rmt_mediaext": self._rmt_mediaext, + } + ) @eventmanager.register(EventType.PluginAction) def remote_sync(self, event: Event): @@ -251,13 +284,18 @@ class FileSoftLink(_PluginBase): event_data = event.event_data if not event_data or event_data.get("action") != "softlink_sync": return - self.post_message(channel=event.event_data.get("channel"), - title="开始同步监控目录 ...", - userid=event.event_data.get("user")) + self.post_message( + channel=event.event_data.get("channel"), + title="开始同步监控目录 ...", + userid=event.event_data.get("user"), + ) self.sync_all() if event: - self.post_message(channel=event.event_data.get("channel"), - title="监控目录同步完成!", userid=event.event_data.get("user")) + self.post_message( + channel=event.event_data.get("channel"), + title="监控目录同步完成!", + userid=event.event_data.get("user"), + ) @eventmanager.register(EventType.PluginAction) def softlink_file(self, event: Event = None): @@ -289,7 +327,9 @@ class FileSoftLink(_PluginBase): if event: event_data = event.event_data if not event_data or ( - event_data.get("action") != "softlink_one" and event_data.get("action") != "softlink_all"): + event_data.get("action") != "softlink_one" + and event_data.get("action") != "softlink_all" + ): return args = event_data.get("args") if not args: @@ -309,7 +349,11 @@ class FileSoftLink(_PluginBase): if category: # 判断是不是目录 - if Path(category).is_dir() and Path(category).exists() and limit is not None: + if ( + Path(category).is_dir() + and Path(category).exists() + and limit is not None + ): # 遍历所有监控目录 mon_path = None for mon in self._dirconf.keys(): @@ -322,7 +366,9 @@ class FileSoftLink(_PluginBase): logger.error(f"未找到 {category} 对应的监控目录") return - self.__handle_limit(path=category, mon_path=mon_path, limit=limit, event=event) + self.__handle_limit( + path=category, mon_path=mon_path, limit=limit, event=event + ) return else: for mon_path in self._categoryconf.keys(): @@ -331,13 +377,26 @@ class FileSoftLink(_PluginBase): if mon_category and str(category) in mon_category: parent_path = os.path.join(mon_path, category) if limit: - logger.info(f"获取到 {category} 对应的监控目录 {parent_path}") - self.__handle_limit(path=parent_path, mon_path=mon_path, limit=limit, event=event) + logger.info( + f"获取到 {category} 对应的监控目录 {parent_path}" + ) + self.__handle_limit( + path=parent_path, + mon_path=mon_path, + limit=limit, + event=event, + ) else: - logger.info(f"获取到 {category} {args} 对应的监控目录 {parent_path}") - target_paths = self.__find_related_paths(os.path.join(str(parent_path), args)) + logger.info( + f"获取到 {category} {args} 对应的监控目录 {parent_path}" + ) + target_paths = self.__find_related_paths( + os.path.join(str(parent_path), args) + ) if not target_paths: - logger.error(f"未查找到 {category} {args} 对应的具体目录") + logger.error( + f"未查找到 {category} {args} 对应的具体目录" + ) return for target_path in target_paths: logger.info(f"开始定向处理文件夹 ...{target_path}") @@ -345,14 +404,27 @@ class FileSoftLink(_PluginBase): for file_name in sdirs + sfiles: src_file = os.path.join(sroot, file_name) if Path(src_file).is_file(): - self.__handle_file(event_path=str(src_file), mon_path=mon_path) + self.__handle_file( + event_path=str(src_file), + mon_path=mon_path, + ) + logger.info( + f"等待 {self._sync_interval} 秒" + ) + time.sleep(self._sync_interval) if event.event_data.get("user"): - self.post_message(channel=event.event_data.get("channel"), - title=f"{target_path} 软连接完成!", - userid=event.event_data.get("user")) + self.post_message( + channel=event.event_data.get("channel"), + title=f"{target_path} 软连接完成!", + userid=event.event_data.get("user"), + ) - if limit is None and event_data and event_data.get("action") == "softlink_one": + if ( + limit is None + and event_data + and event_data.get("action") == "softlink_one" + ): return return else: @@ -381,10 +453,17 @@ class FileSoftLink(_PluginBase): for file_name in sdirs + sfiles: src_file = os.path.join(sroot, file_name) if Path(str(src_file)).is_file(): - self.__handle_file(event_path=str(src_file), mon_path=mon_path) + self.__handle_file( + event_path=str(src_file), mon_path=mon_path + ) + logger.info(f"等待 {self._sync_interval} 秒") + time.sleep(self._sync_interval) if event.event_data.get("user"): - self.post_message(channel=event.event_data.get("channel"), - title=f"{all_args} 软连接完成!", userid=event.event_data.get("user")) + self.post_message( + channel=event.event_data.get("channel"), + title=f"{all_args} 软连接完成!", + userid=event.event_data.get("user"), + ) return else: for mon_path in self._categoryconf.keys(): @@ -397,16 +476,24 @@ class FileSoftLink(_PluginBase): for file_name in sdirs + sfiles: src_file = os.path.join(sroot, file_name) if Path(str(src_file)).is_file(): - self.__handle_file(event_path=str(src_file), mon_path=mon_path) + self.__handle_file( + event_path=str(src_file), mon_path=mon_path + ) + logger.info(f"等待 {self._sync_interval} 秒") + time.sleep(self._sync_interval) if event.event_data.get("user"): - self.post_message(channel=event.event_data.get("channel"), - title=f"{all_args} 软连接完成!", - userid=event.event_data.get("user")) + self.post_message( + channel=event.event_data.get("channel"), + title=f"{all_args} 软连接完成!", + userid=event.event_data.get("user"), + ) return if event.event_data.get("user"): - self.post_message(channel=event.event_data.get("channel"), - title=f"{all_args} 未检索到,请检查输入是否正确!", - userid=event.event_data.get("user")) + self.post_message( + channel=event.event_data.get("channel"), + title=f"{all_args} 未检索到,请检查输入是否正确!", + userid=event.event_data.get("user"), + ) def __handle_limit(self, path, limit, mon_path, event): """ @@ -432,9 +519,14 @@ class FileSoftLink(_PluginBase): src_file = os.path.join(sroot, file_name) if Path(src_file).is_file(): self.__handle_file(event_path=str(src_file), mon_path=mon_path) + logger.info(f"等待 {self._sync_interval} 秒") + time.sleep(self._sync_interval) if event.event_data.get("user"): - self.post_message(channel=event.event_data.get("channel"), - title=f"{sub_path} 软连接完成!", userid=event.event_data.get("user")) + self.post_message( + channel=event.event_data.get("channel"), + title=f"{sub_path} 软连接完成!", + userid=event.event_data.get("user"), + ) @staticmethod def __find_related_paths(base_path): @@ -466,6 +558,8 @@ class FileSoftLink(_PluginBase): path = os.path.join(root, name) if Path(path).is_file(): self.__handle_file(event_path=str(path), mon_path=mon_path) + logger.info(f"等待 {self._sync_interval} 秒") + time.sleep(self._sync_interval) logger.info("全量同步监控目录完成!") def event_handler(self, event, mon_path: str, text: str, event_path: str): @@ -494,10 +588,12 @@ class FileSoftLink(_PluginBase): # 全程加锁 with lock: # 回收站及隐藏的文件不处理 - if event_path.find('/@Recycle/') != -1 \ - or event_path.find('/#recycle/') != -1 \ - or event_path.find('/.') != -1 \ - or event_path.find('/@eaDir') != -1: + if ( + event_path.find("/@Recycle/") != -1 + or event_path.find("/#recycle/") != -1 + or event_path.find("/.") != -1 + or event_path.find("/@eaDir") != -1 + ): logger.debug(f"{event_path} 是回收站或隐藏的文件") return @@ -505,28 +601,42 @@ class FileSoftLink(_PluginBase): if self._exclude_keywords: for keyword in self._exclude_keywords.split("\n"): if keyword and re.findall(keyword, event_path): - logger.info(f"{event_path} 命中过滤关键字 {keyword},不处理") + logger.info( + f"{event_path} 命中过滤关键字 {keyword},不处理" + ) return # 整理屏蔽词不处理 - transfer_exclude_words = self.systemconfig.get(SystemConfigKey.TransferExcludeWords) + transfer_exclude_words = self.systemconfig.get( + SystemConfigKey.TransferExcludeWords + ) if transfer_exclude_words: for keyword in transfer_exclude_words: if not keyword: continue - if keyword and re.search(r"%s" % keyword, event_path, re.IGNORECASE): - logger.info(f"{event_path} 命中整理屏蔽词 {keyword},不处理") + if keyword and re.search( + r"%s" % keyword, event_path, re.IGNORECASE + ): + logger.info( + f"{event_path} 命中整理屏蔽词 {keyword},不处理" + ) return # 判断是不是蓝光目录 if re.search(r"BDMV[/\\]STREAM", event_path, re.IGNORECASE): # 截取BDMV前面的路径 - blurray_dir = event_path[:event_path.find("BDMV")] + blurray_dir = event_path[: event_path.find("BDMV")] file_path = Path(blurray_dir) - logger.info(f"{event_path} 是蓝光目录,更正文件路径为:{str(file_path)}") + logger.info( + f"{event_path} 是蓝光目录,更正文件路径为:{str(file_path)}" + ) # 判断文件大小 - if self._size and float(self._size) > 0 and file_path.stat().st_size < float(self._size) * 1024 ** 3: + if ( + self._size + and float(self._size) > 0 + and file_path.stat().st_size < float(self._size) * 1024**3 + ): logger.info(f"{file_path} 文件大小小于监控文件大小,不处理") return @@ -555,20 +665,27 @@ class FileSoftLink(_PluginBase): os.makedirs(Path(target_file).parent) # 媒体文件软连接 - if Path(target_file).suffix.lower() in [ext.strip() for ext in - self._rmt_mediaext.split(",")]: - retcode, retmsg = SystemUtils.softlink(file_path, Path(target_file)) - logger.info(f"创建媒体文件软连接 {str(file_path)} 到 {target_file} {retcode} {retmsg}") + if Path(target_file).suffix.lower() in [ + ext.strip() for ext in self._rmt_mediaext.split(",") + ]: + retcode, retmsg = SystemUtils.softlink( + file_path, Path(target_file) + ) + logger.info( + f"创建媒体文件软连接 {str(file_path)} 到 {target_file} {retcode} {retmsg}" + ) if self._url and file_path.suffix in settings.RMT_MEDIAEXT: - RequestUtils(content_type="application/json").post(url=self._url, json={ - "path": str(file_path), - "type": "add" - }) + RequestUtils(content_type="application/json").post( + url=self._url, + json={"path": str(file_path), "type": "add"}, + ) else: if self._copy_files: # 其他nfo、jpg等复制文件 shutil.copy2(str(file_path), target_file) - logger.info(f"复制其他文件 {str(file_path)} 到 {target_file}") + logger.info( + f"复制其他文件 {str(file_path)} 到 {target_file}" + ) except Exception as e: logger.error("软连接发生错误:%s - %s" % (str(e), traceback.format_exc())) @@ -587,38 +704,34 @@ class FileSoftLink(_PluginBase): "event": EventType.PluginAction, "desc": "文件软连接同步", "category": "", - "data": { - "action": "softlink_sync" - } + "data": {"action": "softlink_sync"}, }, { "cmd": "/soft", "event": EventType.PluginAction, "desc": "定向软连接处理", "category": "", - "data": { - "action": "softlink_one" - } + "data": {"action": "softlink_one"}, }, { "cmd": "/softall", "event": EventType.PluginAction, "desc": "定向软连接处理", "category": "", - "data": { - "action": "softlink_all" - } - } + "data": {"action": "softlink_all"}, + }, ] def get_api(self) -> List[Dict[str, Any]]: - return [{ - "path": "/softlink_sync", - "endpoint": self.sync, - "methods": ["GET"], - "summary": "实时软连接同步", - "description": "实时软连接同步", - }] + return [ + { + "path": "/softlink_sync", + "endpoint": self.sync, + "methods": ["GET"], + "summary": "实时软连接同步", + "description": "实时软连接同步", + } + ] def get_service(self) -> List[Dict[str, Any]]: """ @@ -632,13 +745,15 @@ class FileSoftLink(_PluginBase): }] """ if self._enabled and self._cron: - return [{ - "id": "FileSoftLink", - "name": "实时软连接全量同步服务", - "trigger": CronTrigger.from_crontab(self._cron), - "func": self.sync_all, - "kwargs": {} - }] + return [ + { + "id": "FileSoftLink", + "name": "实时软连接全量同步服务", + "trigger": CronTrigger.from_crontab(self._cron), + "func": self.sync_all, + "kwargs": {}, + } + ] return [] def sync(self) -> schemas.Response: @@ -651,242 +766,241 @@ class FileSoftLink(_PluginBase): def get_form(self) -> Tuple[List[dict], Dict[str, Any]]: return [ { - 'component': 'VForm', - 'content': [ + "component": "VForm", + "content": [ { - 'component': 'VRow', - 'content': [ + "component": "VRow", + "content": [ { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ + "component": "VCol", + "props": {"cols": 12, "md": 4}, + "content": [ { - 'component': 'VSwitch', - 'props': { - 'model': 'enabled', - 'label': '启用插件', - } + "component": "VSwitch", + "props": { + "model": "enabled", + "label": "启用插件", + }, } - ] + ], }, { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ + "component": "VCol", + "props": {"cols": 12, "md": 4}, + "content": [ { - 'component': 'VSwitch', - 'props': { - 'model': 'onlyonce', - 'label': '立即运行一次', - } + "component": "VSwitch", + "props": { + "model": "onlyonce", + "label": "立即运行一次", + }, } - ] + ], }, { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ + "component": "VCol", + "props": {"cols": 12, "md": 4}, + "content": [ { - 'component': 'VSwitch', - 'props': { - 'model': 'copy_files', - 'label': '复制非媒体文件', - } + "component": "VSwitch", + "props": { + "model": "copy_files", + "label": "复制非媒体文件", + }, } - ] - } - ] + ], + }, + ], }, { - 'component': 'VRow', - 'content': [ + "component": "VRow", + "content": [ { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ + "component": "VCol", + "props": {"cols": 12, "md": 4}, + "content": [ { - 'component': 'VSelect', - 'props': { - 'model': 'mode', - 'label': '监控模式', - 'items': [ - {'title': '兼容模式', 'value': 'compatibility'}, - {'title': '性能模式', 'value': 'fast'}, - {'title': '不监控', 'value': 'nomonitor'}, - ] - } + "component": "VSelect", + "props": { + "model": "mode", + "label": "监控模式", + "items": [ + { + "title": "兼容模式", + "value": "compatibility", + }, + {"title": "性能模式", "value": "fast"}, + { + "title": "不监控", + "value": "nomonitor", + }, + ], + }, } - ] + ], }, { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ + "component": "VCol", + "props": {"cols": 12, "md": 4}, + "content": [ { - 'component': 'VTextField', - 'props': { - 'model': 'cron', - 'label': '定时全量同步周期', - 'placeholder': '5位cron表达式,留空关闭' - } + "component": "VTextField", + "props": { + "model": "cron", + "label": "定时全量同步周期", + "placeholder": "5位cron表达式,留空关闭", + }, } - ] + ], }, { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ + "component": "VCol", + "props": {"cols": 12, "md": 4}, + "content": [ { - 'component': 'VTextField', - 'props': { - 'model': 'size', - 'label': '监控文件大小(GB)', - 'placeholder': '0' - } + "component": "VTextField", + "props": { + "model": "size", + "label": "监控文件大小(GB)", + "placeholder": "0", + }, } - ] - } - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12 - }, - 'content': [ - { - 'component': 'VTextarea', - 'props': { - 'model': 'monitor_dirs', - 'label': '监控目录', - 'rows': 5, - 'placeholder': '监控目录:转移目的目录' - } - } - ] - } - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12, - }, - 'content': [ - { - 'component': 'VTextarea', - 'props': { - 'model': 'exclude_keywords', - 'label': '排除关键词', - 'rows': 2, - 'placeholder': '每一行一个关键词' - } - } - ] - } - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12 - }, - 'content': [ - { - 'component': 'VTextarea', - 'props': { - 'model': 'rmt_mediaext', - 'label': '视频格式', - 'rows': 2, - 'placeholder': ".mp4, .mkv, .ts, .iso,.rmvb, .avi, .mov, .mpeg,.mpg, .wmv, .3gp, .asf, .m4v, .flv, .m2ts, .strm,.tp, .f4v" - } - } - ] - } - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12, - }, - 'content': [ - { - 'component': 'VTextField', - 'props': { - 'model': 'url', - 'label': '任务推送url', - 'placeholder': 'post请求json方式推送path和type(add)字段' - } - } - ] + ], }, - ] + { + "component": "VCol", + "props": {"cols": 12, "md": 4}, + "content": [ + { + "component": "VTextField", + "props": { + "model": "sync_interval", + "label": "同步间隔(秒)", + "placeholder": "0", + }, + } + ], + }, + ], }, { - 'component': 'VRow', - 'content': [ + "component": "VRow", + "content": [ { - 'component': 'VCol', - 'props': { - 'cols': 12, - }, - 'content': [ + "component": "VCol", + "props": {"cols": 12}, + "content": [ { - 'component': 'VAlert', - 'props': { - 'type': 'info', - 'variant': 'tonal', - 'text': '监控文件大小:单位GB,0为不开启,低于监控文件大小的文件不会被监控转移。' - } + "component": "VTextarea", + "props": { + "model": "monitor_dirs", + "label": "监控目录", + "rows": 5, + "placeholder": "监控目录:转移目的目录", + }, } - ] + ], } - ] - } - ] + ], + }, + { + "component": "VRow", + "content": [ + { + "component": "VCol", + "props": { + "cols": 12, + }, + "content": [ + { + "component": "VTextarea", + "props": { + "model": "exclude_keywords", + "label": "排除关键词", + "rows": 2, + "placeholder": "每一行一个关键词", + }, + } + ], + } + ], + }, + { + "component": "VRow", + "content": [ + { + "component": "VCol", + "props": {"cols": 12}, + "content": [ + { + "component": "VTextarea", + "props": { + "model": "rmt_mediaext", + "label": "视频格式", + "rows": 2, + "placeholder": ".mp4, .mkv, .ts, .iso,.rmvb, .avi, .mov, .mpeg,.mpg, .wmv, .3gp, .asf, .m4v, .flv, .m2ts, .strm,.tp, .f4v", + }, + } + ], + } + ], + }, + { + "component": "VRow", + "content": [ + { + "component": "VCol", + "props": { + "cols": 12, + }, + "content": [ + { + "component": "VTextField", + "props": { + "model": "url", + "label": "任务推送url", + "placeholder": "post请求json方式推送path和type(add)字段", + }, + } + ], + }, + ], + }, + { + "component": "VRow", + "content": [ + { + "component": "VCol", + "props": { + "cols": 12, + }, + "content": [ + { + "component": "VAlert", + "props": { + "type": "info", + "variant": "tonal", + "text": "监控文件大小:单位GB,0为不开启,低于监控文件大小的文件不会被监控转移。", + }, + } + ], + } + ], + }, + ], } ], { "enabled": False, "onlyonce": False, "copy_files": True, + "sync_interval": 0, "mode": "compatibility", "monitor_dirs": "", "exclude_keywords": "", "cron": "", "size": 0, "url": "", - "rmt_mediaext": ".mp4, .mkv, .ts, .iso,.rmvb, .avi, .mov, .mpeg,.mpg, .wmv, .3gp, .asf, .m4v, .flv, .m2ts, .strm,.tp, .f4v" + "rmt_mediaext": ".mp4, .mkv, .ts, .iso,.rmvb, .avi, .mov, .mpeg,.mpg, .wmv, .3gp, .asf, .m4v, .flv, .m2ts, .strm,.tp, .f4v", } def get_page(self) -> List[dict]: