diff --git a/pkg/audit/center/apigroup.py b/pkg/audit/center/apigroup.py index 61d02901..ce9ed76f 100644 --- a/pkg/audit/center/apigroup.py +++ b/pkg/audit/center/apigroup.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import abc import uuid import json diff --git a/pkg/core/app.py b/pkg/core/app.py index cc36d4b3..3ce86d3f 100644 --- a/pkg/core/app.py +++ b/pkg/core/app.py @@ -10,7 +10,7 @@ from ..provider.requester import modelmgr as llm_model_mgr from ..provider.sysprompt import sysprompt as llm_prompt_mgr from ..provider.tools import toolmgr as llm_tool_mgr from ..config import manager as config_mgr -# from ..utils.center import v2 as center_mgr +from ..audit.center import v2 as center_mgr from ..command import cmdmgr from ..plugin import manager as plugin_mgr from . import pool, controller @@ -35,7 +35,7 @@ class Application: tips_mgr: config_mgr.ConfigManager = None - # ctr_mgr: center_mgr.V2CenterAPI = None + ctr_mgr: center_mgr.V2CenterAPI = None plugin_mgr: plugin_mgr.PluginManager = None @@ -61,13 +61,11 @@ class Application: await self.plugin_mgr.load_plugins() await self.plugin_mgr.initialize_plugins() - tasks = [ - asyncio.create_task(self.im_mgr.run()), - asyncio.create_task(self.ctrl.run()) - ] - try: - + tasks = [ + asyncio.create_task(self.im_mgr.run()), + asyncio.create_task(self.ctrl.run()) + ] await asyncio.wait(tasks) except asyncio.CancelledError: diff --git a/pkg/core/boot.py b/pkg/core/boot.py index 9c58785c..fedb1e23 100644 --- a/pkg/core/boot.py +++ b/pkg/core/boot.py @@ -21,7 +21,7 @@ from ..platform import manager as im_mgr from ..command import cmdmgr from ..plugin import manager as plugin_mgr from ..audit.center import v2 as center_v2 -from ..utils import version, proxy +from ..utils import version, proxy, announce use_override = False @@ -82,16 +82,26 @@ async def make_app() -> app.Application: ap.cfg_mgr = cfg_mgr ap.tips_mgr = tips_mgr - ap.query_pool = pool.QueryPool() - proxy_mgr = proxy.ProxyManager(ap) await proxy_mgr.initialize() ap.proxy_mgr = proxy_mgr + # 发送公告 + ann_mgr = announce.AnnouncementManager(ap) + announcements = await ann_mgr.fetch_new() + + for ann in announcements: + ap.logger.info(f'[公告] {ann.time}: {ann.content}') + + ap.query_pool = pool.QueryPool() + ver_mgr = version.VersionManager(ap) await ver_mgr.initialize() ap.ver_mgr = ver_mgr + if await ap.ver_mgr.is_new_version_available(): + ap.logger.info("有新版本可用,请使用 !update 命令更新") + plugin_mgr_inst = plugin_mgr.PluginManager(ap) await plugin_mgr_inst.initialize() ap.plugin_mgr = plugin_mgr_inst @@ -109,7 +119,7 @@ async def make_app() -> app.Application: "msg_source": cfg['msg_source_adapter'], } ) - # ap.ctr_mgr = center_v2_api + ap.ctr_mgr = center_v2_api cmd_mgr_inst = cmdmgr.CommandManager(ap) await cmd_mgr_inst.initialize() diff --git a/pkg/utils/announce.py b/pkg/utils/announce.py new file mode 100644 index 00000000..c304caad --- /dev/null +++ b/pkg/utils/announce.py @@ -0,0 +1,106 @@ +from __future__ import annotations + +import json +import typing +import os +import base64 + +import pydantic +import requests + +from ..core import app + + +class Announcement(pydantic.BaseModel): + """公告""" + + id: int + + time: str + + timestamp: int + + content: str + + enabled: typing.Optional[bool] = True + + def to_dict(self) -> dict: + return { + "id": self.id, + "time": self.time, + "timestamp": self.timestamp, + "content": self.content, + "enabled": self.enabled + } + + +class AnnouncementManager: + """公告管理器""" + + ap: app.Application = None + + def __init__(self, ap: app.Application): + self.ap = ap + + async def fetch_all( + self + ) -> list[Announcement]: + """获取所有公告""" + resp = requests.get( + url="https://api.github.com/repos/RockChinQ/QChatGPT/contents/res/announcement.json", + proxies=self.ap.proxy_mgr.get_forward_proxies(), + timeout=5 + ) + obj_json = resp.json() + b64_content = obj_json["content"] + # 解码 + content = base64.b64decode(b64_content).decode("utf-8") + + return [Announcement(**item) for item in json.loads(content)] + + async def fetch_saved( + self + ) -> list[Announcement]: + if not os.path.exists("res/announcement_saved.json"): + with open("res/announcement_saved.json", "w", encoding="utf-8") as f: + f.write("[]") + + with open("res/announcement_saved.json", "r", encoding="utf-8") as f: + content = f.read() + + if not content: + content = '[]' + + return [Announcement(**item) for item in json.loads(content)] + + async def write_saved( + self, + content: list[Announcement] + ): + + with open("res/announcement_saved.json", "w", encoding="utf-8") as f: + f.write(json.dumps([ + item.to_dict() for item in content + ], indent=4, ensure_ascii=False)) + + async def fetch_new( + self + ) -> list[Announcement]: + """获取新公告""" + all = await self.fetch_all() + saved = await self.fetch_saved() + + to_show: list[Announcement] = [] + + for item in all: + # 遍历saved检查是否有相同id的公告 + for saved_item in saved: + if saved_item.id == item.id: + break + else: + if item.enabled: + # 没有相同id的公告 + to_show.append(item) + + await self.write_saved(all) + return to_show diff --git a/pkg/utils/announcement.py b/pkg/utils/announcement.py deleted file mode 100644 index 4bff412d..00000000 --- a/pkg/utils/announcement.py +++ /dev/null @@ -1,68 +0,0 @@ -import base64 -import os -import json - -import requests - - -def read_latest() -> list: - import pkg.utils.network as network - resp = requests.get( - url="https://api.github.com/repos/RockChinQ/QChatGPT/contents/res/announcement.json", - proxies=network.wrapper_proxies() - ) - obj_json = resp.json() - b64_content = obj_json["content"] - # 解码 - content = base64.b64decode(b64_content).decode("utf-8") - return json.loads(content) - - -def read_saved() -> list: - # 已保存的在res/announcement_saved - # 检查是否存在 - if not os.path.exists("res/announcement_saved.json"): - with open("res/announcement_saved.json", "w", encoding="utf-8") as f: - f.write("[]") - - with open("res/announcement_saved.json", "r", encoding="utf-8") as f: - content = f.read() - - return json.loads(content) - - -def write_saved(content: list): - # 已保存的在res/announcement_saved - with open("res/announcement_saved.json", "w", encoding="utf-8") as f: - f.write(json.dumps(content, indent=4, ensure_ascii=False)) - - -def fetch_new() -> list: - latest = read_latest() - saved = read_saved() - - to_show: list = [] - - for item in latest: - # 遍历saved检查是否有相同id的公告 - for saved_item in saved: - if saved_item["id"] == item["id"]: - break - else: - # 没有相同id的公告 - to_show.append(item) - - write_saved(latest) - return to_show - - -if __name__ == '__main__': - - resp = requests.get( - url="https://api.github.com/repos/RockChinQ/QChatGPT/contents/res/announcement.json", - ) - obj_json = resp.json() - b64_content = obj_json["content"] - # 解码 - content = base64.b64decode(b64_content).decode("utf-8") - print(json.dumps(json.loads(content), indent=4, ensure_ascii=False)) diff --git a/pkg/utils/version.py b/pkg/utils/version.py index 7427ce9f..49c67668 100644 --- a/pkg/utils/version.py +++ b/pkg/utils/version.py @@ -49,7 +49,8 @@ class VersionManager: """获取发行列表""" rls_list_resp = requests.get( url="https://api.github.com/repos/RockChinQ/QChatGPT/releases", - proxies=self.ap.proxy_mgr.get_forward_proxies() + proxies=self.ap.proxy_mgr.get_forward_proxies(), + timeout=5 ) rls_list = rls_list_resp.json()