diff --git a/pkg/persistence/migrations/dbm001_migrate_v3_config.py b/pkg/persistence/migrations/dbm001_migrate_v3_config.py index 58f05e04..6d53718d 100644 --- a/pkg/persistence/migrations/dbm001_migrate_v3_config.py +++ b/pkg/persistence/migrations/dbm001_migrate_v3_config.py @@ -212,6 +212,7 @@ class DBMigrateV3Config(migration.DBMigration): self.ap.instance_config.data['api']['port'] = self.ap.system_cfg.data['http-api']['port'] self.ap.instance_config.data['command'] = { 'prefix': self.ap.command_cfg.data['command-prefix'], + 'enable': self.ap.command_cfg.data['command-enable'], 'privilege': self.ap.command_cfg.data['privilege'], } self.ap.instance_config.data['concurrency']['pipeline'] = self.ap.system_cfg.data['pipeline-concurrency'] diff --git a/pkg/pipeline/bansess/bansess.py b/pkg/pipeline/bansess/bansess.py index c88a1aa2..ed6ddf74 100644 --- a/pkg/pipeline/bansess/bansess.py +++ b/pkg/pipeline/bansess/bansess.py @@ -30,6 +30,10 @@ class BanSessionCheckStage(stage.PipelineStage): if sess == f'{query.launcher_type.value}_{query.launcher_id}': found = True break + # 使用 *_id 来表示加白/拉黑某用户的私聊和群聊场景 + if sess.startswith('*_') and (sess[2:] == query.launcher_id or sess[2:] == query.sender_id): + found = True + break ctn = False diff --git a/pkg/pipeline/process/handlers/chat.py b/pkg/pipeline/process/handlers/chat.py index e913bbc2..fee54427 100644 --- a/pkg/pipeline/process/handlers/chat.py +++ b/pkg/pipeline/process/handlers/chat.py @@ -43,7 +43,7 @@ class ChatMessageHandler(handler.MessageHandler): query=query, ) ) - + is_create_card = False # 判断下是否需要创建流式卡片 if event_ctx.is_prevented_default(): if event_ctx.event.reply is not None: mc = platform_message.MessageChain(event_ctx.event.reply) @@ -72,14 +72,17 @@ class ChatMessageHandler(handler.MessageHandler): raise ValueError(f'未找到请求运行器: {query.pipeline_config["ai"]["runner"]["runner"]}') if is_stream: resp_message_id = uuid.uuid4() - await query.adapter.create_message_card(str(resp_message_id), query.message_event) + async for result in runner.run(query): result.resp_message_id = str(resp_message_id) if query.resp_messages: query.resp_messages.pop() if query.resp_message_chain: query.resp_message_chain.pop() - + # 此时连接外部 AI 服务正常,创建卡片 + if not is_create_card: # 只有不是第一次才创建卡片 + await query.adapter.create_message_card(str(resp_message_id), query.message_event) + is_create_card = True query.resp_messages.append(result) self.ap.logger.info(f'对话({query.query_id})流式响应: {self.cut_str(result.readable_str())}') diff --git a/pkg/pipeline/process/process.py b/pkg/pipeline/process/process.py index db66135c..a08b8c08 100644 --- a/pkg/pipeline/process/process.py +++ b/pkg/pipeline/process/process.py @@ -42,12 +42,14 @@ class Processor(stage.PipelineStage): async def generator(): cmd_prefix = self.ap.instance_config.data['command']['prefix'] + cmd_enable = self.ap.instance_config.data['command'].get('enable', True) - if any(message_text.startswith(prefix) for prefix in cmd_prefix): - async for result in self.cmd_handler.handle(query): - yield result + if cmd_enable and any(message_text.startswith(prefix) for prefix in cmd_prefix): + handler_to_use = self.cmd_handler else: - async for result in self.chat_handler.handle(query): - yield result + handler_to_use = self.chat_handler + + async for result in handler_to_use.handle(query): + yield result return generator() diff --git a/pkg/utils/announce.py b/pkg/utils/announce.py index a6b8539a..69d19368 100644 --- a/pkg/utils/announce.py +++ b/pkg/utils/announce.py @@ -45,17 +45,23 @@ class AnnouncementManager: async def fetch_all(self) -> list[Announcement]: """获取所有公告""" - resp = requests.get( - url='https://api.github.com/repos/langbot-app/LangBot/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') + try: + resp = requests.get( + url='https://api.github.com/repos/langbot-app/LangBot/contents/res/announcement.json', + proxies=self.ap.proxy_mgr.get_forward_proxies(), + timeout=5, + ) + resp.raise_for_status() # 检查请求是否成功 + 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)] + return [Announcement(**item) for item in json.loads(content)] + except (requests.RequestException, json.JSONDecodeError, KeyError) as e: + self.ap.logger.warning(f"获取公告失败: {e}") + pass + return [] # 请求失败时返回空列表 async def fetch_saved(self) -> list[Announcement]: if not os.path.exists('data/labels/announcement_saved.json'): diff --git a/pkg/utils/version.py b/pkg/utils/version.py index b26b1e33..3a2748fc 100644 --- a/pkg/utils/version.py +++ b/pkg/utils/version.py @@ -28,15 +28,19 @@ class VersionManager: async def get_release_list(self) -> list: """获取发行列表""" - rls_list_resp = requests.get( - url='https://api.github.com/repos/langbot-app/LangBot/releases', - proxies=self.ap.proxy_mgr.get_forward_proxies(), - timeout=5, - ) - - rls_list = rls_list_resp.json() - - return rls_list + try: + rls_list_resp = requests.get( + url='https://api.github.com/repos/langbot-app/LangBot/releases', + proxies=self.ap.proxy_mgr.get_forward_proxies(), + timeout=5, + ) + rls_list_resp.raise_for_status() # 检查请求是否成功 + rls_list = rls_list_resp.json() + return rls_list + except Exception as e: + self.ap.logger.warning(f"获取发行列表失败: {e}") + pass + return [] async def update_all(self): """检查更新并下载源码""" diff --git a/templates/config.yaml b/templates/config.yaml index d347af77..3faa2fd7 100644 --- a/templates/config.yaml +++ b/templates/config.yaml @@ -2,6 +2,7 @@ admins: [] api: port: 5300 command: + enable: true prefix: - '!' - ! diff --git a/templates/metadata/pipeline/trigger.yaml b/templates/metadata/pipeline/trigger.yaml index 949b2698..cecfc59d 100644 --- a/templates/metadata/pipeline/trigger.yaml +++ b/templates/metadata/pipeline/trigger.yaml @@ -79,6 +79,9 @@ stages: label: en_US: Blacklist zh_Hans: 黑名单 + description: + en_US: Sessions in the blacklist will be ignored, the format is `{launcher_type}_{launcher_id}`(remove quotes), for example `person_123` matches private chat, `group_456` matches group chat, `person_*` matches all private chats, `group_*` matches all group chats, `*_123` matches private and group chats with user ID 123 + zh_Hans: 黑名单中的会话将被忽略;会话格式:`{launcher_type}_{launcher_id}`(删除引号),例如 `person_123` 匹配私聊会话,`group_456` 匹配群聊会话;`person_*` 匹配所有私聊会话,`group_*` 匹配所有群聊会话;`*_123` 匹配用户 ID 为 123 的私聊和群聊消息 type: array[string] required: true default: [] @@ -86,6 +89,9 @@ stages: label: en_US: Whitelist zh_Hans: 白名单 + description: + en_US: Only respond to sessions in the whitelist, the format is `{launcher_type}_{launcher_id}`(remove quotes), for example `person_123` matches private chat, `group_456` matches group chat, `person_*` matches all private chats, `group_*` matches all group chats, `*_123` matches private and group chats with user ID 123 + zh_Hans: 仅响应白名单中的会话;会话格式:`{launcher_type}_{launcher_id}`(删除引号),例如 `person_123` 匹配私聊会话,`group_456` 匹配群聊会话;`person_*` 匹配所有私聊会话,`group_*` 匹配所有群聊会话;`*_123` 匹配用户 ID 为 123 的私聊和群聊消息 type: array[string] required: true default: []