From e9d2ebca8997b96ea69d3c482529e65fd81fa31b Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sat, 17 Jun 2023 20:46:34 +0800 Subject: [PATCH] fix commands --- app/api/endpoints/site.py | 54 +++++++++++++++++++++++++--- app/chain/cookiecloud.py | 14 +++++++- app/chain/douban.py | 10 +++++- app/chain/download.py | 2 +- app/chain/message.py | 1 - app/chain/site.py | 72 ++++++++++++++++++++++++-------------- app/chain/subscribe.py | 41 +++++++++++++++++++--- app/command.py | 45 ++++++++++++------------ app/modules/slack/slack.py | 2 +- 9 files changed, 179 insertions(+), 62 deletions(-) diff --git a/app/api/endpoints/site.py b/app/api/endpoints/site.py index 4ab6dac4..5456121a 100644 --- a/app/api/endpoints/site.py +++ b/app/api/endpoints/site.py @@ -5,6 +5,7 @@ from sqlalchemy.orm import Session from app import schemas from app.chain.cookiecloud import CookieCloudChain +from app.chain.site import SiteChain from app.db import get_db from app.db.models.site import Site from app.db.models.user import User @@ -24,10 +25,10 @@ async def read_sites(db: Session = Depends(get_db), @router.put("/", response_model=schemas.Site) async def update_site( - *, - db: Session = Depends(get_db), - site_in: schemas.Site, - _: User = Depends(get_current_active_superuser), + *, + db: Session = Depends(get_db), + site_in: schemas.Site, + _: User = Depends(get_current_active_superuser), ) -> Any: """ 更新站点信息 @@ -42,6 +43,24 @@ async def update_site( return site +@router.get("/{site_id}", response_model=schemas.Site) +async def read_site( + site_id: int, + db: Session = Depends(get_db), + _: User = Depends(get_current_active_user), +) -> Any: + """ + 获取站点信息 + """ + site = Site.get(db, site_id) + if not site: + raise HTTPException( + status_code=404, + detail=f"站点 {site_id} 不存在", + ) + return site + + @router.get("/cookiecloud", response_model=schemas.Response) async def cookie_cloud_sync(_: User = Depends(get_current_active_user)) -> Any: """ @@ -51,3 +70,30 @@ async def cookie_cloud_sync(_: User = Depends(get_current_active_user)) -> Any: if not status: return {"success": False, "message": error_msg} return {"success": True, "message": error_msg} + + +@router.get("/cookie", response_model=schemas.Response) +async def update_cookie( + site_id: int, + username: str, + password: str, + db: Session = Depends(get_db), + _: User = Depends(get_current_active_user)) -> Any: + """ + 使用用户密码更新站点Cookie + """ + # 查询站点 + site_info = Site.get(db, site_id) + if not site_info: + raise HTTPException( + status_code=404, + detail=f"站点 {site_id} 不存在!", + ) + # 更新Cookie + status, msg = SiteChain().update_cookie(site_info=site_info, + username=username, + password=password) + if not status: + return {"success": False, "message": msg} + else: + return {"success": True, "message": msg} diff --git a/app/chain/cookiecloud.py b/app/chain/cookiecloud.py index f4d65086..75cdbb63 100644 --- a/app/chain/cookiecloud.py +++ b/app/chain/cookiecloud.py @@ -1,5 +1,5 @@ import base64 -from typing import Tuple, Optional +from typing import Tuple, Optional, Union from urllib.parse import urljoin from lxml import etree @@ -30,6 +30,18 @@ class CookieCloudChain(ChainBase): password=settings.COOKIECLOUD_PASSWORD ) + def remote_sync(self, userid: Union[int, str]): + """ + 远程触发同步站点,发送消息 + """ + self.post_message(title="开始同步CookieCloud站点 ...", userid=userid) + # 开始同步 + success, msg = self.process() + if success: + self.post_message(title=f"同步站点成功,{msg}", userid=userid) + else: + self.post_message(title=f"同步站点失败:{msg}", userid=userid) + def process(self) -> Tuple[bool, str]: """ 通过CookieCloud同步站点Cookie diff --git a/app/chain/douban.py b/app/chain/douban.py index c6d2ec8d..f10745c1 100644 --- a/app/chain/douban.py +++ b/app/chain/douban.py @@ -1,5 +1,5 @@ from pathlib import Path -from typing import Optional +from typing import Optional, Union from app.chain import ChainBase from app.chain.download import DownloadChain @@ -28,6 +28,14 @@ class DoubanChain(ChainBase): self.searchchain = SearchChain() self.subscribechain = SubscribeChain() + def remote_sync(self, userid: Union[int, str]): + """ + 同步豆瓣想看数据,发送消息 + """ + self.post_message(title="开始同步豆瓣想看 ...", userid=userid) + self.sync() + self.post_message(title="同步豆瓣想看数据完成!", userid=userid) + def sync(self): """ 通过用户RSS同步豆瓣想看数据 diff --git a/app/chain/download.py b/app/chain/download.py index cfca2f35..0b4893fb 100644 --- a/app/chain/download.py +++ b/app/chain/download.py @@ -509,7 +509,7 @@ class DownloadChain(ChainBase): # 全部存在 return True, no_exists - def get_downloading(self, userid: Union[str, int] = None): + def remote_downloading(self, userid: Union[str, int] = None): """ 查询正在下载的任务,并发送消息 """ diff --git a/app/chain/message.py b/app/chain/message.py index 607be133..57774640 100644 --- a/app/chain/message.py +++ b/app/chain/message.py @@ -63,7 +63,6 @@ class MessageChain(ChainBase): "user": userid } ) - self.post_message(title=f"正在运行,请稍候 ...", userid=userid) elif text.isdigit(): # 缓存 diff --git a/app/chain/site.py b/app/chain/site.py index a1639cb7..389ad52e 100644 --- a/app/chain/site.py +++ b/app/chain/site.py @@ -1,7 +1,8 @@ -from typing import Union +from typing import Union, Tuple from app.chain import ChainBase from app.core.config import settings +from app.db.models.site import Site from app.db.site_oper import SiteOper from app.helper.cookie import CookieHelper from app.log import logger @@ -20,7 +21,7 @@ class SiteChain(ChainBase): self._siteoper = SiteOper() self._cookiehelper = CookieHelper() - def list(self, userid: Union[str, int] = None): + def remote_list(self, userid: Union[str, int] = None): """ 查询所有站点,发送消息 """ @@ -44,7 +45,7 @@ class SiteChain(ChainBase): # 发送列表 self.post_message(title=title, text="\n".join(messages), userid=userid) - def disable(self, arg_str, userid: Union[str, int] = None): + def remote_disable(self, arg_str, userid: Union[str, int] = None): """ 禁用站点 """ @@ -63,9 +64,9 @@ class SiteChain(ChainBase): "is_active": False }) # 重新发送消息 - self.list() + self.remote_list() - def enable(self, arg_str, userid: Union[str, int] = None): + def remote_enable(self, arg_str, userid: Union[str, int] = None): """ 启用站点 """ @@ -84,9 +85,36 @@ class SiteChain(ChainBase): "is_active": True }) # 重新发送消息 - self.list() + self.remote_list() - def get_cookie(self, arg_str: str, userid: Union[str, int] = None): + def update_cookie(self, site_info: Site, + username: str, password: str) -> Tuple[bool, str]: + """ + 根据用户名密码更新站点Cookie + :param site_info: 站点信息 + :param username: 用户名 + :param password: 密码 + :return: (是否成功, 错误信息) + """ + # 更新站点Cookie + result = self._cookiehelper.get_site_cookie_ua( + url=site_info.url, + username=username, + password=password, + proxies=settings.PROXY_HOST if site_info.proxy else None + ) + if result: + cookie, ua, msg = result + if not cookie: + return False, msg + self._siteoper.update(site_info.id, { + "cookie": cookie, + "ua": ua + }) + return True, msg + return False, "未知错误" + + def remote_cookie(self, arg_str: str, userid: Union[str, int] = None): """ 使用用户名密码更新站点Cookie """ @@ -111,28 +139,20 @@ class SiteChain(ChainBase): if not site_info: self.post_message(title=f"站点编号 {site_id} 不存在!", userid=userid) return + self.post_message(title=f"开始更新【{site_info.name}】Cookie&UA ...", userid=userid) # 用户名 username = args[1] # 密码 password = args[2] - # 更新站点Cookie - result = self._cookiehelper.get_site_cookie_ua( - url=site_info.url, - username=username, - password=password, - proxies=settings.PROXY_HOST if site_info.proxy else None - ) - if result: - cookie, ua, msg = result - if not cookie: - logger.error(msg) - self.post_message(title=f"【{site_info.name}】 Cookie&UA更新失败!", - text=f"错误原因:{msg}", - userid=userid) - return - self._siteoper.update(site_id, { - "cookie": cookie, - "ua": ua - }) + # 更新Cookie + status, msg = self.update_cookie(site_info=site_info, + username=username, + password=password) + if not status: + logger.error(msg) + self.post_message(title=f"【{site_info.name}】 Cookie&UA更新失败!", + text=f"错误原因:{msg}", + userid=userid) + else: self.post_message(title=f"【{site_info.name}】 Cookie&UA更新成功", userid=userid) diff --git a/app/chain/subscribe.py b/app/chain/subscribe.py index ee15a2fc..0cd5a72f 100644 --- a/app/chain/subscribe.py +++ b/app/chain/subscribe.py @@ -108,6 +108,37 @@ class SubscribeChain(ChainBase): # 返回结果 return sid + def remote_refresh(self, userid: Union[str, int] = None): + """ + 远程刷新订阅,发送消息 + """ + self.post_message(title=f"开始刷新订阅 ...", userid=userid) + self.refresh() + self.post_message(title=f"订阅刷新完成!", userid=userid) + + def remote_search(self, arg_str: str, userid: Union[str, int] = None): + """ + 远程搜索订阅,发送消息 + """ + if arg_str and not str(arg_str).isdigit(): + self.post_message(title="请输入正确的命令格式:/subscribe_search [id]," + "[id]为订阅编号,不输入订阅编号时搜索所有订阅", userid=userid) + return + if arg_str: + sid = int(arg_str) + subscribe = self.subscribehelper.get(sid) + if not subscribe: + self.post_message(title=f"订阅编号 {sid} 不存在!", userid=userid) + return + self.post_message(title=f"开始搜索 {subscribe.name} ...", userid=userid) + # 搜索订阅 + self.search(sid=int(arg_str)) + self.post_message(title=f"{subscribe.name} 搜索完成!", userid=userid) + else: + self.post_message(title=f"开始搜索所有订阅 ...", userid=userid) + self.search(state='R') + self.post_message(title=f"订阅搜索完成!", userid=userid) + def search(self, sid: int = None, state: str = 'N'): """ 订阅搜索 @@ -325,7 +356,7 @@ class SubscribeChain(ChainBase): "lack_episode": len(left_episodes) }) - def list(self, userid: Union[str, int] = None): + def remote_list(self, userid: Union[str, int] = None): """ 查询订阅并发送消息 """ @@ -334,7 +365,9 @@ class SubscribeChain(ChainBase): self.post_message(title='没有任何订阅!', userid=userid) return title = f"共有 {len(subscribes)} 个订阅,回复对应指令操作: " \ - f"\n- 删除订阅:/subscribe_delete [id]" + f"\n- 删除订阅:/subscribe_delete [id]" \ + f"\n- 搜索订阅:/subscribe_search [id]" \ + f"\n- 刷新订阅:/subscribe_refresh" messages = [] for subscribe in subscribes: if subscribe.type == MediaType.MOVIE.value: @@ -349,7 +382,7 @@ class SubscribeChain(ChainBase): # 发送列表 self.post_message(title=title, text='\n'.join(messages), userid=userid) - def delete(self, arg_str: str, userid: Union[str, int] = None): + def remote_delete(self, arg_str: str, userid: Union[str, int] = None): """ 删除订阅 """ @@ -366,7 +399,7 @@ class SubscribeChain(ChainBase): # 删除订阅 self.subscribehelper.delete(subscribe_id) # 重新发送消息 - self.list() + self.remote_list() @staticmethod def __get_subscribe_no_exits(no_exists: Dict[int, Dict[int, NotExistMediaInfo]], diff --git a/app/command.py b/app/command.py index f25b60cd..532ea67c 100644 --- a/app/command.py +++ b/app/command.py @@ -42,62 +42,60 @@ class Command(metaclass=Singleton): self.eventmanager = EventManager() # 插件管理器 self.pluginmanager = PluginManager() - # 汇总插件命令 + # 内置命令 self._commands = { "/cookiecloud": { - "func": CookieCloudChain().process, + "func": CookieCloudChain().remote_sync, "description": "同步站点", "data": {} }, "/sites": { - "func": SiteChain().list, + "func": SiteChain().remote_list, "description": "查询站点", "data": {} }, "/site_cookie": { - "func": SiteChain().get_cookie, + "func": SiteChain().remote_cookie, "description": "更新站点Cookie", "data": {} }, "/site_enable": { - "func": SiteChain().enable, + "func": SiteChain().remote_enable, "description": "启用站点", "data": {} }, "/site_disable": { - "func": SiteChain().disable, + "func": SiteChain().remote_disable, "description": "禁用站点", "data": {} }, "/douban_sync": { - "func": DoubanChain().sync, + "func": DoubanChain().remote_sync, "description": "同步豆瓣想看", "data": {} }, "/subscribes": { - "func": SubscribeChain().list, + "func": SubscribeChain().remote_list, "description": "查询订阅", "data": {} }, "/subscribe_refresh": { - "func": SubscribeChain().refresh, + "func": SubscribeChain().remote_refresh, "description": "刷新订阅", "data": {} }, "/subscribe_search": { - "func": SubscribeChain().search, + "func": SubscribeChain().remote_search, "description": "搜索订阅", - "data": { - 'state': 'R', - } + "data": {} }, "/subscribe_delete": { - "func": SubscribeChain().delete, + "func": SubscribeChain().remote_delete, "description": "删除订阅", "data": {} }, "/downloading": { - "func": DownloadChain().get_downloading, + "func": DownloadChain().remote_downloading, "description": "正在下载", "data": {} }, @@ -107,6 +105,7 @@ class Command(metaclass=Singleton): "data": {} } } + # 汇总插件命令 plugin_commands = self.pluginmanager.get_plugin_commands() for command in plugin_commands: self.register( @@ -120,7 +119,7 @@ class Command(metaclass=Singleton): ) # 处理链 self.chain = CommandChian() - # 广播注册命令 + # 广播注册命令菜单 self.chain.register_commands(commands=self.get_commands()) # 消息处理线程 self._thread = Thread(target=self.__run) @@ -184,16 +183,16 @@ class Command(metaclass=Singleton): logger.info(f"用户 {userid} 开始执行:{command.get('description')} ...") cmd_data = command['data'] if command.get('data') else {} args_num = ObjectUtils.has_arguments(command['func']) - if args_num: + if args_num > 0: if cmd_data: - # 使用内置参数 + # 有内置参数直接使用内置参数 command['func'](**cmd_data) - elif args_num > 1: - # 使用用户输入参数 - command['func'](data_str, userid) - else: + elif args_num == 1: # 没有用户输入参数 - command['func'](data_str) + command['func'](userid) + else: + # 多个输入参数:用户输入、用户ID + command['func'](data_str, userid) else: # 没有参数 command['func']() diff --git a/app/modules/slack/slack.py b/app/modules/slack/slack.py index b221bd87..c060d269 100644 --- a/app/modules/slack/slack.py +++ b/app/modules/slack/slack.py @@ -112,7 +112,7 @@ class Slack: # 结构体 blocks = [] if not image: - message_text = f"*{title}*\n{text or ''}" + message_text = f"{title}\n{text or ''}" else: # 消息图片 if image: