diff --git a/addons/plugins/helloworld/helloworld.py b/addons/plugins/helloworld/helloworld.py index c76d4a9f9..5e8dccb98 100644 --- a/addons/plugins/helloworld/helloworld.py +++ b/addons/plugins/helloworld/helloworld.py @@ -50,6 +50,11 @@ class HelloWorldPlugin: return True, tuple([True, "Hello World!!", "helloworld"]) else: return False, None + else: + """ + 其他平台处理逻辑 + """ + return False, None """ 帮助函数,当用户输入 plugin v 插件名称 时,会调用此函数,返回帮助信息 返回参数要求(必填):dict{ diff --git a/cores/qqbot/core.py b/cores/qqbot/core.py index 0c8345f81..e4f39f7bb 100644 --- a/cores/qqbot/core.py +++ b/cores/qqbot/core.py @@ -96,28 +96,32 @@ client = None # QQ群机器人 PLATFROM_QQBOT = 'qqbot' -# 配置 -cc.init_attributes(["qq_forward_threshold"], 200) -cc.init_attributes(["qq_welcome"], "欢迎加入本群!\n欢迎给https://github.com/Soulter/QQChannelChatGPT项目一个Star😊~\n输入help查看帮助~\n") -cc.init_attributes(["bing_proxy"], "") -cc.init_attributes(["qq_pic_mode"], False) -cc.init_attributes(["rev_chatgpt_model"], "") -cc.init_attributes(["rev_chatgpt_plugin_ids"], []) -cc.init_attributes(["rev_chatgpt_PUID"], "") -cc.init_attributes(["rev_chatgpt_unverified_plugin_domains"], []) -cc.init_attributes(["gocq_host"], "127.0.0.1") -cc.init_attributes(["gocq_http_port"], 5700) -cc.init_attributes(["gocq_websocket_port"], 6700) -cc.init_attributes(["gocq_react_group"], True) -cc.init_attributes(["gocq_react_guild"], True) -cc.init_attributes(["gocq_react_friend"], True) -cc.init_attributes(["gocq_react_group_increase"], True) -cc.init_attributes(["gocq_qqchan_admin"], "") -cc.init_attributes(["other_admins"], []) -cc.init_attributes(["CHATGPT_BASE_URL"], "") -cc.init_attributes(["qqbot_appid"], "") -cc.init_attributes(["qqbot_secret"], "") -cc.init_attributes(["llm_env_prompt"], "> hint: 末尾根据内容和心情添加 1-2 个emoji") +# CLI +PLATFORM_CLI = 'cli' + +# 加载默认配置 +cc.init_attributes("qq_forward_threshold", 200) +cc.init_attributes("qq_welcome", "欢迎加入本群!\n欢迎给https://github.com/Soulter/QQChannelChatGPT项目一个Star😊~\n输入help查看帮助~\n") +cc.init_attributes("bing_proxy", "") +cc.init_attributes("qq_pic_mode", False) +cc.init_attributes("rev_chatgpt_model", "") +cc.init_attributes("rev_chatgpt_plugin_ids", []) +cc.init_attributes("rev_chatgpt_PUID", "") +cc.init_attributes("rev_chatgpt_unverified_plugin_domains", []) +cc.init_attributes("gocq_host", "127.0.0.1") +cc.init_attributes("gocq_http_port", 5700) +cc.init_attributes("gocq_websocket_port", 6700) +cc.init_attributes("gocq_react_group", True) +cc.init_attributes("gocq_react_guild", True) +cc.init_attributes("gocq_react_friend", True) +cc.init_attributes("gocq_react_group_increase", True) +cc.init_attributes("gocq_qqchan_admin", "") +cc.init_attributes("other_admins", []) +cc.init_attributes("CHATGPT_BASE_URL", "") +cc.init_attributes("qqbot_appid", "") +cc.init_attributes("qqbot_secret", "") +cc.init_attributes("llm_env_prompt", "> hint: 末尾根据内容和心情添加 1-2 个emoji") +cc.init_attributes("default_personality_name", "") # cc.init_attributes(["qq_forward_mode"], False) # QQ机器人 @@ -219,6 +223,9 @@ def initBot(cfg, prov): global frequency_count, frequency_time, announcement, direct_message_mode, version global keywords, _global_object + _event_loop = asyncio.new_event_loop() + asyncio.set_event_loop(_event_loop) + # 初始化 global_object _global_object = GlobalObject() _global_object.base_config = cfg @@ -374,7 +381,7 @@ def initBot(cfg, prov): qqbot_loop = asyncio.new_event_loop() if cc.get("qqbot_appid", '') != '' and cc.get("qqbot_secret", '') != '': gu.log("- 启用QQ群机器人 -", gu.LEVEL_INFO) - thread_inst = threading.Thread(target=run_qqbot, args=(qqbot_loop, qq_bot,), daemon=False) + thread_inst = threading.Thread(target=run_qqbot, args=(qqbot_loop, qq_bot,), daemon=True) thread_inst.start() @@ -386,7 +393,7 @@ def initBot(cfg, prov): global gocq_app, gocq_loop gocq_loop = asyncio.new_event_loop() gocq_bot = QQ(True, cc, gocq_loop) - thread_inst = threading.Thread(target=run_gocq_bot, args=(gocq_loop, gocq_bot, gocq_app), daemon=False) + thread_inst = threading.Thread(target=run_gocq_bot, args=(gocq_loop, gocq_bot, gocq_app), daemon=True) thread_inst.start() else: gocq_bot = QQ(False) @@ -404,7 +411,7 @@ def initBot(cfg, prov): qqchannel_bot = QQChan() qqchan_loop = asyncio.new_event_loop() _global_object.platform_qqchan = qqchannel_bot - thread_inst = threading.Thread(target=run_qqchan_bot, args=(cfg, qqchan_loop, qqchannel_bot), daemon=False) + thread_inst = threading.Thread(target=run_qqchan_bot, args=(cfg, qqchan_loop, qqchannel_bot), daemon=True) thread_inst.start() # thread.join() @@ -412,7 +419,31 @@ def initBot(cfg, prov): input("[System-Error] 没有启用/成功启用任何机器人,程序退出") exit() - thread_inst.join() + gu.log("🎉 项目启动完成。") + + # thread_inst.join() + asyncio.get_event_loop().run_until_complete(cli()) + +async def cli(): + time.sleep(1) + while True: + prompt = input(">>> ") + if prompt == "": + continue + ngm = NakuruGuildMessage() + ngm.channel_id = 6180 + ngm.user_id = 6180 + ngm.message = [Plain(prompt)] + ngm.type = "GuildMessage" + ngm.self_id = 6180 + ngm.self_tiny_id = 6180 + ngm.guild_id = 6180 + ngm.sender = NakuruGuildMember() + ngm.sender.tiny_id = 6180 + ngm.sender.user_id = 6180 + ngm.sender.nickname = "CLI" + ngm.sender.role = 0 + await oper_msg(ngm, True, PLATFORM_CLI) ''' 运行QQ频道机器人 @@ -443,9 +474,12 @@ def run_qqchan_bot(cfg, loop, qqchannel_bot: QQChan): def run_gocq_bot(loop, gocq_bot, gocq_app): asyncio.set_event_loop(loop) gu.log("正在检查本地GO-CQHTTP连接...端口5700, 6700", tag="QQ") + noticed = False while True: if not gu.port_checker(5700, cc.get("gocq_host", "127.0.0.1")) or not gu.port_checker(6700, cc.get("gocq_host", "127.0.0.1")): - gu.log("与GO-CQHTTP通信失败, 请检查GO-CQHTTP是否启动并正确配置。5秒后自动重试。", gu.LEVEL_CRITICAL, tag="QQ") + if not noticed: + noticed = True + gu.log("与GO-CQHTTP通信失败, 请检查GO-CQHTTP是否启动并正确配置。程序会每隔 5s 自动重试。", gu.LEVEL_CRITICAL, tag="QQ") time.sleep(5) else: gu.log("检查完毕,未发现问题。", tag="QQ") @@ -509,6 +543,8 @@ async def send_message(platform, message, res, session_id = None): message_chain = MessageChain() message_chain.parse_from_nakuru(res) await qq_bot.send(message, message_chain) + if platform == PLATFORM_CLI: + print(res) async def oper_msg(message: Union[GroupMessage, FriendMessage, GuildMessage, NakuruGuildMessage], group: bool=False, @@ -533,59 +569,59 @@ async def oper_msg(message: Union[GroupMessage, FriendMessage, GuildMessage, Nak with_tag = False # 是否带有昵称 - if platform == PLATFORM_QQCHAN or platform == PLATFROM_QQBOT: + if platform == PLATFORM_QQCHAN or platform == PLATFROM_QQBOT or platform == PLATFORM_CLI: with_tag = True - if platform == PLATFORM_GOCQ or platform == PLATFORM_QQCHAN or platform == PLATFROM_QQBOT: - _len = 0 - for i in message.message: - if isinstance(i, Plain) or isinstance(i, PlainText): - qq_msg += str(i.text).strip() - if isinstance(i, At): - if message.type == "GuildMessage": - if i.qq == message.user_id or i.qq == message.self_tiny_id: - with_tag = True - if message.type == "FriendMessage": - if i.qq == message.self_id: - with_tag = True - if message.type == "GroupMessage": - if i.qq == message.self_id: - with_tag = True - - for i in _global_object.nick: - if i != '' and qq_msg.startswith(i): - _len = len(i) - with_tag = True - break - qq_msg = qq_msg[_len:].strip() - - gu.log(f"收到消息:{qq_msg}", gu.LEVEL_INFO, tag="QQ") - user_id = message.user_id - - if group: - # 适配GO-CQHTTP的频道功能 + _len = 0 + for i in message.message: + if isinstance(i, Plain) or isinstance(i, PlainText): + qq_msg += str(i.text).strip() + if isinstance(i, At): if message.type == "GuildMessage": - session_id = message.channel_id - else: - session_id = message.group_id - else: + if i.qq == message.user_id or i.qq == message.self_tiny_id: + with_tag = True + if message.type == "FriendMessage": + if i.qq == message.self_id: + with_tag = True + if message.type == "GroupMessage": + if i.qq == message.self_id: + with_tag = True + + for i in _global_object.nick: + if i != '' and qq_msg.startswith(i): + _len = len(i) with_tag = True - session_id = message.user_id - role = "member" + break + qq_msg = qq_msg[_len:].strip() + gu.log(f"收到消息:{qq_msg}", gu.LEVEL_INFO, tag="QQ") + user_id = message.user_id + + if group: + # 适配GO-CQHTTP的频道功能 if message.type == "GuildMessage": - sender_id = str(message.sender.tiny_id) + session_id = message.channel_id else: - sender_id = str(message.sender.user_id) - if sender_id == _global_object.admin_qq or \ - sender_id == _global_object.admin_qqchan or \ - sender_id in cc.get("other_admins", []) or \ - sender_id == cc.get("gocq_qqchan_admin", ""): - # gu.log("检测到管理员身份", gu.LEVEL_INFO, tag="GOCQ") - role = "admin" - if _global_object.uniqueSession: - # 独立会话时,一个用户一个session - session_id = sender_id + session_id = message.group_id + else: + with_tag = True + session_id = message.user_id + + if message.type == "GuildMessage": + sender_id = str(message.sender.tiny_id) + else: + sender_id = str(message.sender.user_id) + if sender_id == _global_object.admin_qq or \ + sender_id == _global_object.admin_qqchan or \ + sender_id in cc.get("other_admins", []) or \ + sender_id == cc.get("gocq_qqchan_admin", "") or \ + platform == PLATFORM_CLI: + role = "admin" + + if _global_object.uniqueSession: + # 独立会话时,一个用户一个 session + session_id = sender_id + if qq_msg == "": await send_message(platform, message, f"Hi~", session_id=session_id) diff --git a/main.py b/main.py index 635205e0a..082d835cb 100644 --- a/main.py +++ b/main.py @@ -2,6 +2,7 @@ import os, sys from pip._internal import main as pipmain import warnings import traceback +import threading warnings.filterwarnings("ignore") abs_path = os.path.dirname(os.path.realpath(sys.argv[0])) + '/' @@ -128,4 +129,7 @@ if __name__ == "__main__": except BaseException as e: print(e) print(f"[System-err] Replit Web保活服务启动失败:{str(e)}") - main() + + t = threading.Thread(target=main, daemon=False) + t.start() + t.join() diff --git a/model/command/command.py b/model/command/command.py index 7fc068c61..3a3689d5e 100644 --- a/model/command/command.py +++ b/model/command/command.py @@ -126,8 +126,6 @@ class Command: fail_rec = "" if plugins is None: return False, "未找到任何插件模块" - - print(plugins) for plugin in plugins: try: diff --git a/model/provider/openai_official.py b/model/provider/openai_official.py index 405fa930b..2e0b36a95 100644 --- a/model/provider/openai_official.py +++ b/model/provider/openai_official.py @@ -35,7 +35,7 @@ class ProviderOpenAIOfficial(Provider): self.api_base = None if 'api_base' in cfg and cfg['api_base'] != 'none' and cfg['api_base'] != '': self.api_base = cfg['api_base'] - print(f"设置 api_base 为: {self.api_base}") + gu.log(f"设置 api_base 为: {self.api_base}") # openai client self.client = OpenAI( api_key=self.key_list[0], diff --git a/model/provider/rev_edgegpt.py b/model/provider/rev_edgegpt.py index ce122f28d..aadb81179 100644 --- a/model/provider/rev_edgegpt.py +++ b/model/provider/rev_edgegpt.py @@ -1,15 +1,15 @@ from model.provider.provider import Provider -# from EdgeGPT import Chatbot, ConversationStyle +from EdgeGPT import Chatbot, ConversationStyle import json import os from util import general_utils as gu from util.cmd_config import CmdConfig as cc import time -from EdgeGPT.EdgeUtils import Query, Cookie -from EdgeGPT.EdgeGPT import Chatbot as EdgeChatbot, ConversationStyle, NotAllowedToAccess class ProviderRevEdgeGPT(Provider): def __init__(self): + raise Exception("Bing 逆向已停止维护,不可用,请使用 ChatGPT 官方 API。") + self.busy = False self.wait_stack = [] with open('./cookies.json', 'r') as f: diff --git a/util/cmd_config.py b/util/cmd_config.py index 03d81c43c..396ad721f 100644 --- a/util/cmd_config.py +++ b/util/cmd_config.py @@ -1,5 +1,6 @@ import os import json +from typing import Union cpath = "cmd_config.json" @@ -38,7 +39,7 @@ class CmdConfig(): f.flush() @staticmethod - def init_attributes(keys: list, init_val = ""): + def init_attributes(key: Union[str, list], init_val = ""): check_exist() conf_str = '' with open(cpath, "r", encoding="utf-8-sig") as f: @@ -47,10 +48,15 @@ class CmdConfig(): conf_str = conf_str.encode('utf8')[3:].decode('utf8') d = json.loads(conf_str) _tag = False - for k in keys: - if k not in d: - d[k] = init_val - _tag = True + + if isinstance(key, str): + d[key] = init_val + _tag = True + elif isinstance(key, list): + for k in key: + if k not in d: + d[k] = init_val + _tag = True if _tag: with open(cpath, "w", encoding="utf-8-sig") as f: json.dump(d, f, indent=4, ensure_ascii=False)