diff --git a/package.json b/package.json index 1c18680..cd8990c 100644 --- a/package.json +++ b/package.json @@ -316,10 +316,13 @@ "MoviePilotUpdateNotify": { "name": "MoviePilot更新推送", "description": "MoviePilot推送release更新通知、自动重启。", - "version": "1.2", + "version": "1.3", "icon": "Moviepilot_A.png", "author": "thsrite", - "level": 1 + "level": 1, + "history": { + "v1.3": "增加前端版本更新检查,需要主程序升级至v1.8.4+版本" + } }, "CloudDiskDel": { "name": "云盘文件删除", diff --git a/plugins/moviepilotupdatenotify/__init__.py b/plugins/moviepilotupdatenotify/__init__.py index bf9eb79..e3df7f8 100644 --- a/plugins/moviepilotupdatenotify/__init__.py +++ b/plugins/moviepilotupdatenotify/__init__.py @@ -22,7 +22,7 @@ class MoviePilotUpdateNotify(_PluginBase): # 插件图标 plugin_icon = "Moviepilot_A.png" # 插件版本 - plugin_version = "1.2" + plugin_version = "1.3" # 插件作者 plugin_author = "thsrite" # 作者主页 @@ -40,6 +40,7 @@ class MoviePilotUpdateNotify(_PluginBase): _cron = None _restart = False _notify = False + _update_types = [] # 定时器 _scheduler: Optional[BackgroundScheduler] = None @@ -53,21 +54,39 @@ class MoviePilotUpdateNotify(_PluginBase): self._cron = config.get("cron") self._restart = config.get("restart") self._notify = config.get("notify") + self._update_types = config.get("update_types") or [] def __check_update(self): """ 检查MoviePilot更新 """ + # 检查后端更新 + server_update = self.__check_server_update() if self._update_types and "后端" in self._update_types else False + + # 检查前端更新 + front_update = self.__check_front_update() if self._update_types and "前端" in self._update_types else False + + # 自动重启 + if (server_update or front_update) and self._restart: + logger.info("开始执行自动重启…") + SystemUtils.restart() + + def __check_server_update(self): + """ + 检查后端更新 + """ release_version, description, update_time = self.__get_release_version() if not release_version: - logger.error("最新版本获取失败,停止运行") - return + logger.error("后端最新版本获取失败") + return False # 本地版本 - local_version = SystemChain().get_local_version() + local_version = SystemChain().get_server_local_version() if local_version and release_version <= local_version: - logger.info(f"当前版本:{local_version} 远程版本:{release_version} 停止运行") - return + logger.info(f"当前后端版本:{local_version} 远程版本:{release_version} 停止运行") + return False + + logger.info(f"发现MoviePilot后端更新:{release_version} {description} {update_time}") # 推送更新消息 if self._notify: @@ -80,17 +99,51 @@ class MoviePilotUpdateNotify(_PluginBase): update_time = dt.strftime("%Y-%m-%d %H:%M:%S") self.post_message( mtype=NotificationType.SiteMessage, - title="【MoviePilot更新通知】", + title="【MoviePilot后端更新通知】", text=f"{release_version} \n" f"\n" f"{description} \n" f"\n" f"{update_time}") - # 自动重启 - if self._restart: - logger.info("开始执行自动重启…") - SystemUtils.restart() + return True + + def __check_front_update(self): + """ + 检查前端更新 + """ + release_version, description, update_time = self.__get_front_release_version() + if not release_version: + logger.error("前端最新版本获取失败") + return False + + # 本地版本 + local_version = SystemChain().get_frontend_version() + if local_version and release_version <= local_version: + logger.info(f"当前前端版本:{local_version} 远程版本:{release_version} 停止运行") + return False + + logger.info(f"发现MoviePilot前端更新:{release_version} {description} {update_time}") + + # 推送更新消息 + if self._notify: + # 将时间字符串转为datetime对象 + dt = datetime.datetime.strptime(update_time, "%Y-%m-%dT%H:%M:%SZ") + # 设置时区 + timezone = pytz.timezone(settings.TZ) + dt = dt.replace(tzinfo=timezone) + # 将datetime对象转换为带时区的字符串 + update_time = dt.strftime("%Y-%m-%d %H:%M:%S") + self.post_message( + mtype=NotificationType.SiteMessage, + title="【MoviePilot前端更新通知】", + text=f"{release_version} \n" + f"\n" + f"{description} \n" + f"\n" + f"{update_time}") + + return True @staticmethod def __get_release_version(): @@ -108,6 +161,22 @@ class MoviePilotUpdateNotify(_PluginBase): else: return None, None, None + @staticmethod + def __get_front_release_version(): + """ + 获取前端最新版本 + """ + version_res = RequestUtils(proxies=settings.PROXY, headers=settings.GITHUB_HEADERS).get_res( + "https://api.github.com/repos/jxxghp/MoviePilot-Frontend/releases/latest") + if version_res: + ver_json = version_res.json() + version = f"{ver_json['tag_name']}" + description = f"{ver_json['body']}" + update_time = f"{ver_json['published_at']}" + return version, description, update_time + else: + return None, None, None + def get_state(self) -> bool: return self._enabled @@ -146,112 +215,142 @@ class MoviePilotUpdateNotify(_PluginBase): 拼装插件配置页面,需要返回两块数据:1、页面配置;2、数据结构 """ return [ - { - 'component': 'VForm', - 'content': [ - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ - { - 'component': 'VSwitch', - 'props': { - 'model': 'enabled', - 'label': '启用插件', - } - } - ] - }, - { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ - { - 'component': 'VSwitch', - 'props': { - 'model': 'restart', - 'label': '自动重启', - } - } - ] - }, - { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ - { - 'component': 'VSwitch', - 'props': { - 'model': 'notify', - 'label': '发送通知', - } - } - ] - } - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12, - }, - 'content': [ - { - 'component': 'VTextField', - 'props': { - 'model': 'cron', - 'label': '检查周期', - 'placeholder': '5位cron表达式' - } - } - ] - }, - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12, - }, - 'content': [ - { - 'component': 'VAlert', - 'props': { - 'type': 'info', - 'variant': 'tonal', - 'text': '如要开启自动重启,请确认MOVIEPILOT_AUTO_UPDATE设置为true,重启即更新。' - } - } - ] - } - ] - } - ] - } - ], { - "enabled": False, - "restart": False, - "notify": False, - "cron": "0 9 * * *" - } + { + 'component': 'VForm', + 'content': [ + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 4 + }, + 'content': [ + { + 'component': 'VSwitch', + 'props': { + 'model': 'enabled', + 'label': '启用插件', + } + } + ] + }, + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 4 + }, + 'content': [ + { + 'component': 'VSwitch', + 'props': { + 'model': 'restart', + 'label': '自动重启', + } + } + ] + }, + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 4 + }, + 'content': [ + { + 'component': 'VSwitch', + 'props': { + 'model': 'notify', + 'label': '发送通知', + } + } + ] + } + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 6 + }, + 'content': [ + { + 'component': 'VTextField', + 'props': { + 'model': 'cron', + 'label': '检查周期', + 'placeholder': '5位cron表达式' + } + } + ] + }, + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 6 + }, + 'content': [ + { + 'component': 'VSelect', + 'props': { + 'multiple': True, + 'chips': True, + 'model': 'update_types', + 'label': '更新类型', + 'items': [ + { + "title": "后端", + "vale": "后端" + }, + { + "title": "前端", + "vale": "前端" + } + ] + } + } + ] + }, + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + }, + 'content': [ + { + 'component': 'VAlert', + 'props': { + 'type': 'info', + 'variant': 'tonal', + 'text': '如要开启自动重启,请确认MOVIEPILOT_AUTO_UPDATE设置为true,重启即更新。' + } + } + ] + }, + ] + } + ] + } + ], { + "enabled": False, + "restart": False, + "notify": False, + "cron": "0 9 * * *", + "update_types": ["后端", "前端"] + } def get_page(self) -> List[dict]: pass