From c21aed693fa76afd03adf17fe48bdb541a1239f1 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sun, 23 Jul 2023 09:42:30 +0800 Subject: [PATCH] fix plugin api --- app/api/endpoints/plugin.py | 21 +++++ app/core/plugin.py | 22 ++++- app/modules/filter/__init__.py | 2 +- app/plugins/__init__.py | 16 +++- app/plugins/autosignin/__init__.py | 116 +++++++++++++++++++++++++- app/plugins/sitestatistic/__init__.py | 91 +++++++++++++++++++- 6 files changed, 262 insertions(+), 6 deletions(-) diff --git a/app/api/endpoints/plugin.py b/app/api/endpoints/plugin.py index b8aeac52..02d64044 100644 --- a/app/api/endpoints/plugin.py +++ b/app/api/endpoints/plugin.py @@ -49,6 +49,27 @@ def install_plugin(plugin_id: str, return schemas.Response(success=True) +@router.get("/form/{plugin_id}", summary="获取插件表单页面") +def plugin_form(plugin_id: str, + _: schemas.TokenPayload = Depends(verify_token)) -> dict: + """ + 根据插件ID获取插件配置表单 + """ + conf, model = PluginManager().get_plugin_form(plugin_id) + return { + "conf": conf, + "model": model + } + + +@router.get("/page/{plugin_id}", summary="获取插件数据页面") +def plugin_page(plugin_id: str, _: schemas.TokenPayload = Depends(verify_token)) -> List[dict]: + """ + 根据插件ID获取插件配置信息 + """ + return PluginManager().get_plugin_page(plugin_id) + + @router.get("/{plugin_id}", summary="获取插件配置") def plugin_config(plugin_id: str, _: schemas.TokenPayload = Depends(verify_token)) -> dict: """ diff --git a/app/core/plugin.py b/app/core/plugin.py index 9b0e5269..4d799434 100644 --- a/app/core/plugin.py +++ b/app/core/plugin.py @@ -1,5 +1,5 @@ import traceback -from typing import List, Any, Dict +from typing import List, Any, Dict, Tuple from app.db.systemconfig_oper import SystemConfigOper from app.helper.module import ModuleHelper @@ -91,6 +91,26 @@ class PluginManager(metaclass=Singleton): return False return self.systemconfig.set(self._config_key % pid, conf) + def get_plugin_form(self, pid: str) -> Tuple[List[dict], Dict[str, Any]]: + """ + 获取插件表单 + """ + if not self._running_plugins.get(pid): + return [], {} + if hasattr(self._running_plugins[pid], "get_form"): + return self._running_plugins[pid].get_form() + return [], {} + + def get_plugin_page(self, pid: str) -> List[dict]: + """ + 获取插件页面 + """ + if not self._running_plugins.get(pid): + return [] + if hasattr(self._running_plugins[pid], "get_page"): + return self._running_plugins[pid].get_page() + return [] + def get_plugin_commands(self) -> List[Dict[str, Any]]: """ 获取插件命令 diff --git a/app/modules/filter/__init__.py b/app/modules/filter/__init__.py index 5896e676..ab8b165f 100644 --- a/app/modules/filter/__init__.py +++ b/app/modules/filter/__init__.py @@ -17,7 +17,7 @@ class FilterModule(_ModuleBase): rule_set: Dict[str, dict] = { # 蓝光 "BLU": { - "include": [r'Blu-?Ray.+VC-?1|Blu-?Ray.+AVC|UHD.+blu-?ray.+HEVC'], + "include": [r'Blu-?Ray.+VC-?1|Blu-?Ray.+AVC|UHD.+blu-?ray.+HEVC|MiniBD'], "exclude": [] }, # 4K diff --git a/app/plugins/__init__.py b/app/plugins/__init__.py index 76da7d15..1f20b8ae 100644 --- a/app/plugins/__init__.py +++ b/app/plugins/__init__.py @@ -1,6 +1,6 @@ from abc import ABCMeta, abstractmethod from pathlib import Path -from typing import Any, List, Dict +from typing import Any, List, Dict, Tuple from app.chain import ChainBase from app.core.config import settings @@ -74,6 +74,20 @@ class _PluginBase(metaclass=ABCMeta): """ pass + @abstractmethod + def get_form(self) -> Tuple[List[dict], Dict[str, Any]]: + """ + 拼装插件配置页面,需要返回两块数据:1、页面配置;2、数据结构 + """ + pass + + @abstractmethod + def get_page(self) -> List[dict]: + """ + 拼装插件详情页面,需要返回页面配置,同时附带数据 + """ + pass + @abstractmethod def stop_service(self): """ diff --git a/app/plugins/autosignin/__init__.py b/app/plugins/autosignin/__init__.py index 4c0df896..1082f0c6 100644 --- a/app/plugins/autosignin/__init__.py +++ b/app/plugins/autosignin/__init__.py @@ -31,7 +31,7 @@ class AutoSignIn(_PluginBase): # 插件名称 plugin_name = "站点自动签到" # 插件描述 - plugin_desc = "自动模拟登录站点并签到,每日 9:00-23:00 随机时间自动运行两次。" + plugin_desc = "自动模拟登录站点并签到。" # 插件图标 plugin_icon = "signin.png" # 主题色 @@ -115,6 +115,120 @@ class AutoSignIn(_PluginBase): "description": "使用站点域名签到站点", }] + def get_form(self) -> Tuple[List[dict], Dict[str, Any]]: + """ + 拼装插件配置页面,需要返回两块数据:1、页面配置;2、数据结构 + """ + return [ + { + 'component': 'VForm', + 'content': [ + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'content': [ + { + 'component': 'VSwitch', + 'model': 'enabled', + 'label': '启用插件', + }, + { + 'component': 'VSwitch', + 'model': 'notify', + 'label': '签到通知', + } + ] + } + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'content': [ + { + 'component': 'VTextField', + 'cols': 12, + 'md': 6, + 'model': 'cron', + 'label': '执行周期', + 'placeholder': '0 9,18 * * *' + }, + { + 'component': 'VTextField', + 'cols': 12, + 'md': 6, + 'model': 'queue_cnt', + 'label': '队列数量' + }, + { + 'component': 'VTextField', + 'cols': 12, + 'md': 6, + 'model': 'retry_keyword', + 'label': '重试关键字' + } + ] + } + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'content': [ + { + 'component': 'VSelect', + 'chips': True, + 'multiple': True, + 'model': 'sign_sites', + 'label': '签到站点', + 'items': [] + } + ] + } + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'content': [ + { + 'component': 'VSelect', + 'chips': True, + 'multiple': True, + 'model': 'sign_sites', + 'label': '签到站点', + 'items': [] + } + ] + } + ] + } + ] + } + ], { + "enabled": False, + "notify": False, + "cron": "1 9,18 * * *", + "queue_cnt": 5, + "retry_keyword": "", + "sign_sites": [], + "special_sites": [] + } + + def get_page(self) -> List[dict]: + """ + 拼装插件详情页面,需要返回页面配置,同时附带数据 + """ + pass + @eventmanager.register(EventType.SiteSignin) def sign_in(self, event: Event = None): """ diff --git a/app/plugins/sitestatistic/__init__.py b/app/plugins/sitestatistic/__init__.py index af9ec0b2..f57b1f2b 100644 --- a/app/plugins/sitestatistic/__init__.py +++ b/app/plugins/sitestatistic/__init__.py @@ -1,7 +1,7 @@ from datetime import datetime from multiprocessing.dummy import Pool as ThreadPool from threading import Lock -from typing import Optional, Any, List, Dict +from typing import Optional, Any, List, Dict, Tuple import requests from apscheduler.schedulers.background import BackgroundScheduler @@ -35,7 +35,7 @@ class SiteStatistic(_PluginBase): # 插件名称 plugin_name = "站点数据统计" # 插件描述 - plugin_desc = "统计和展示站点数据,每日凌晨随机时间自动运行一次。" + plugin_desc = "自动统计和展示站点数据。" # 插件图标 plugin_icon = "statistic.png" # 主题色 @@ -118,6 +118,93 @@ class SiteStatistic(_PluginBase): "description": "刷新对应域名的站点数据", }] + def get_form(self) -> Tuple[List[dict], Dict[str, Any]]: + """ + 拼装插件配置页面,需要返回两块数据:1、页面配置;2、数据结构 + """ + return [ + { + 'component': 'VForm', + 'content': [ + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'content': [ + { + 'component': 'VSwitch', + 'model': 'enabled', + 'label': '启用插件', + }, + { + 'component': 'VSwitch', + 'model': 'notify', + 'label': '发送通知', + } + ] + } + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'content': [ + { + 'component': 'VTextField', + 'cols': 12, + 'md': 6, + 'model': 'cron', + 'label': '执行周期', + 'placeholder': '0 9,18 * * *' + }, + { + 'component': 'VTextField', + 'cols': 12, + 'md': 6, + 'model': 'queue_cnt', + 'label': '队列数量' + } + ] + } + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'content': [ + { + 'component': 'VSelect', + 'chips': True, + 'multiple': True, + 'model': 'statistic_sites', + 'label': '统计站点', + 'items': [] + } + ] + } + ] + } + ] + } + ], { + "enabled": False, + "notify": False, + "cron": "5 1 * * *", + "queue_cnt": 5, + "statistic_sites": [] + } + + def get_page(self) -> List[dict]: + """ + 拼装插件详情页面,需要返回页面配置,同时附带数据 + """ + pass + def stop_service(self): pass