Compare commits

..

24 Commits

Author SHA1 Message Date
Soulter
4b158a1c89 feat: GOCQ适配QQ频道 2023-05-20 15:30:07 +08:00
Soulter
6894900e46 fix: 修复画画指令得到的图片风格像油画的问题 2023-05-20 14:27:02 +08:00
Soulter
2e11d6e007 perf: log perf 2023-05-18 22:21:29 +08:00
Soulter
348381be15 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-05-18 22:15:07 +08:00
Soulter
9024c28e70 perf: fix some logs 2023-05-18 22:15:01 +08:00
Soulter
ae1702901b Update README.md 2023-05-18 08:34:41 +08:00
Soulter
c1c0df85e6 Update README.md 2023-05-17 20:36:54 +08:00
Soulter
f3c6d9c02b fix: draw command 2023-05-16 15:06:39 +08:00
Soulter
811a885411 fix: draw command 2023-05-16 15:04:55 +08:00
Soulter
b4ec28b71c Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-05-16 11:57:04 +08:00
Soulter
cdf4a5321b perf: 1.逆向ChatGPT库支持消息等待,不会回复忙碌。
2. 优化模型加载流程
2023-05-16 11:56:59 +08:00
Soulter
d83f155f80 Update README.md 2023-05-15 20:54:19 +08:00
Soulter
4c402ed5bd perf: 优化插件鉴别 2023-05-15 20:43:42 +08:00
Soulter
ec5aff8d0b fix: update helloworld default plugin 2023-05-15 20:14:14 +08:00
Soulter
eae0d6c422 fix: 修复一些奇怪的地方 2023-05-15 20:09:01 +08:00
Soulter
9c284b84b1 perf: 升级插件协议簇 2023-05-15 20:03:17 +08:00
Soulter
9f36e5ae05 perf: 在连接到go-cqhttp之前添加连接检测 2023-05-15 18:33:07 +08:00
Soulter
7caa380e54 perf: 优化控制台输出的长度限制 2023-05-14 21:58:45 +08:00
Soulter
41d81bb60e perf: 简化控制台字数 2023-05-14 20:54:56 +08:00
Soulter
454a74f4e1 perf: 颜色日志-优化控制台显示 2023-05-14 20:51:39 +08:00
Soulter
c5bdad02e5 fix: 修复ChatGPT逆向库回答报错的问题 2023-05-14 20:39:15 +08:00
Soulter
f46de3d518 perf: 颜色日志-美化控制台显示 2023-05-14 20:38:28 +08:00
Soulter
a3e21bea1a perf: 删除不必要的控制台信息显示 2023-05-14 19:54:47 +08:00
Soulter
d7e4707d5d perf: 简化控制台输出信息 2023-05-14 19:43:12 +08:00
15 changed files with 402 additions and 139 deletions

View File

@@ -12,7 +12,7 @@ _✨教程https://github.com/Soulter/QQChannelChatGPT/wiki ✨_
_✨插件开发教程https://github.com/Soulter/QQChannelChatGPT/wiki/%E5%9B%9B%E3%80%81%E5%BC%80%E5%8F%91%E6%8F%92%E4%BB%B6 ✨_
_✨欢迎体验😊(频道名: GPT机器人 | 频道号: x42d56aki2) | QQ群号322154837✨_
_✨欢迎体验频道名: GPT机器人 | 频道号: x42d56aki2) | QQ群号322154837✨_
<!-- <img src="https://user-images.githubusercontent.com/37870767/230417115-9dd3c9d5-6b6b-4928-8fe3-82f559208aab.JPG" width="300"></img> -->
@@ -25,7 +25,7 @@ _✨欢迎体验😊频道名: GPT机器人 | 频道号: x42d56aki2) | QQ群
- 支持一键切换语言模型(使用/bing /revgpt /gpt分别可以切换newbing、逆向ChatGPT、官方ChatGPT模型
- 热更新
- 接入QQ支持在QQ上和QQ频道上同时聊天https://github.com/Soulter/QQChannelChatGPT/issues/82
- 更强大的Windows启动器,环境配置自动搞定。链接https://github.com/Soulter/QQChatGPTLauncher/releases/latest
- Windows启动器。链接https://github.com/Soulter/QQChatGPTLauncher/releases/latest
支持的AI语言模型请在`configs/config.yaml`下配置):
- 逆向ChatGPT库
@@ -102,7 +102,11 @@ _✨欢迎体验😊频道名: GPT机器人 | 频道号: x42d56aki2) | QQ群
部分好用的插件:
`HuggingChat`: https://github.com/Soulter/HuggingChatForQQBot
- `HuggingChat`: https://github.com/Soulter/HuggingChatForQQBot | HuggingChat模型接入
- `GoodPlugins`: https://github.com/Soulter/goodplugins | 随机动漫图片等等
- `sysstat`: https://github.com/Soulter/sysstatqcbot | 查看系统状态
### 指令功能

View File

@@ -4,24 +4,28 @@ from nakuru import (
FriendMessage
)
from botpy.message import Message, DirectMessage
from model.platform.qq import QQ
import time
import threading
class HelloWorldPlugin:
"""
初始化函数, 可以选择直接pass
"""
def __init__(self) -> None:
self.myThread = None # 线程对象如果要使用线程需要在此处定义。在run处定义会被释放掉
print("这是HelloWorld测试插件, 发送 helloworld 即可触发此插件。")
"""
入口函数,机器人会调用此函数。
参数规范: message: 消息文本; role: 身份; platform: 消息平台; message_obj: 消息对象
参数规范: message: 消息文本; role: 身份; platform: 消息平台; message_obj: 消息对象; qq_platform: QQ平台对象可以通过调用qq_platform.send()直接发送消息。详见Helloworld插件示例
参数详情: role为admin或者member; platform为qqchan或者gocq; message_obj为nakuru的GroupMessage对象或者FriendMessage对象或者频道的Message, DirectMessage对象。
返回规范: bool: 是否hit到此插件(所有的消息均会调用每一个载入的插件, 如果没有hit到, 则应返回False)
Tuple: None或者长度为3的元组。当没有hit到时, 返回None. hit到时, 第1个参数为指令是否调用成功, 第2个参数为返回的消息文本或者gocq的消息链列表, 第3个参数为指令名称
例子:做一个名为"yuanshen"的插件;当接收到消息为“原神 可莉”, 如果不想要处理此消息则返回False, None如果想要处理但是执行失败了返回True, tuple([False, "请求失败啦~", "yuanshen"])
执行成功了返回True, tuple([True, "结果文本", "yuanshen"])
"""
def run(self, message: str, role: str, platform: str, message_obj):
def run(self, message: str, role: str, platform: str, message_obj, qq_platform: QQ):
if platform == "gocq":
"""
@@ -30,6 +34,11 @@ class HelloWorldPlugin:
img_url = "https://gchat.qpic.cn/gchatpic_new/905617992/720871955-2246763964-C6EE1A52CC668EC982453065C4FA8747/0?term=2&amp;is_origin=0"
if message == "helloworld":
return True, tuple([True, [Plain("Hello World!!"), Image.fromURL(url=img_url)], "helloworld"])
elif message == "hiloop":
if self.myThread is None:
self.myThread = threading.Thread(target=self.helloworldThread, args=(message_obj, qq_platform))
self.myThread.start()
return True, tuple([True, [Plain("A lot of Helloworlds!!"), Image.fromURL(url=img_url)], "helloworld"])
else:
return False, None
elif platform == "qqchan":
@@ -58,7 +67,12 @@ class HelloWorldPlugin:
"version": "v1.0.1 beta",
"author": "Soulter"
}
def helloworldThread(self, meseage_obj, qq_platform: QQ):
while True:
qq_platform.send(meseage_obj, [Plain("Hello World!!")]) # 第一个参数可以是message_obj, 也可以是qq群号
time.sleep(3) # 睡眠3秒。 用while True一定要记得sleep不然会卡死
# 热知识:检测消息开头指令,使用以下方法
# if message.startswith("原神"):

View File

@@ -18,10 +18,12 @@ from nakuru import (
CQHTTP,
GroupMessage,
GroupMemberIncrease,
FriendMessage
FriendMessage,
GuildMessage
)
from nakuru.entities.components import Plain,At
from model.command.command import Command
from util import general_utils as gu
# QQBotClient实例
client = ''
@@ -91,7 +93,11 @@ qqchan_loop = None
# QQ机器人
gocq_bot = None
PLATFORM_GOCQ = 'gocq'
gocq_app = None
gocq_app = CQHTTP(
host="127.0.0.1",
port=6700,
http_port=5700,
)
admin_qq = "123456"
gocq_loop = None
@@ -103,23 +109,6 @@ bing_cache_loop = None
cached_plugins = {}
def gocq_runner():
global gocq_app
ok = False
while not ok:
try:
gocq_app = CQHTTP(
host="127.0.0.1",
port=6700,
http_port=5700,
)
ok = True
except BaseException as e:
print("[System-err] 连接到go-cqhttp异常, 5秒后重试。"+str(e))
threading.Thread(target=gocq_runner, daemon=True).start()
def new_sub_thread(func, args=()):
thread = threading.Thread(target=func, args=args, daemon=True)
thread.start()
@@ -169,7 +158,6 @@ def upload():
d = json.dumps(d).encode("utf-8")
res = requests.put(f'https://uqfxtww1.lc-cn-n1-shared.com/1.1/classes/bot_record/{object_id}', headers = headers, data = d)
if json.loads(res.text)['code'] == 1:
print("[System] New User.")
res = requests.post(f'https://uqfxtww1.lc-cn-n1-shared.com/1.1/classes/bot_record', headers = headers, data = d)
object_id = json.loads(res.text)['objectId']
object_id_file = open(abs_path+"configs/object_id", 'w+', encoding='utf-8')
@@ -194,9 +182,9 @@ def initBot(cfg, prov):
reply_prefix = cfg['reply_prefix']
# 语言模型提供商
print("--------------------加载语言模型--------------------")
gu.log("--------加载语言模型--------", gu.LEVEL_INFO, fg=gu.FG_COLORS['yellow'])
if REV_CHATGPT in prov:
print("- 逆向ChatGPT库 -")
gu.log("- 逆向ChatGPT库 -", gu.LEVEL_INFO)
if cfg['rev_ChatGPT']['enable']:
if 'account' in cfg['rev_ChatGPT']:
from model.provider.provider_rev_chatgpt import ProviderRevChatGPT
@@ -208,7 +196,8 @@ def initBot(cfg, prov):
input("[System-err] 请退出本程序, 然后在配置文件中填写rev_ChatGPT相关配置")
if REV_EDGEGPT in prov:
print("- New Bing -")
gu.log("- New Bing -", gu.LEVEL_INFO)
if not os.path.exists('./cookies.json'):
input("[System-err] 导入Bing模型时发生错误, 没有找到cookies文件或者cookies文件放置位置错误。windows启动器启动的用户请把cookies.json文件放到和启动器相同的目录下。\n如何获取请看https://github.com/Soulter/QQChannelChatGPT仓库介绍。")
else:
@@ -219,7 +208,7 @@ def initBot(cfg, prov):
command_rev_edgegpt = CommandRevEdgeGPT(rev_edgegpt)
chosen_provider = REV_EDGEGPT
if OPENAI_OFFICIAL in prov:
print("- OpenAI ChatGPT官方API -")
gu.log("- OpenAI官方 -", gu.LEVEL_INFO)
if cfg['openai']['key'] is not None:
from model.provider.provider_openai_official import ProviderOpenAIOfficial
from model.command.command_openai_official import CommandOpenAIOfficial
@@ -227,7 +216,7 @@ def initBot(cfg, prov):
command_openai_official = CommandOpenAIOfficial(chatgpt)
chosen_provider = OPENAI_OFFICIAL
print("--------------------加载个性化配置--------------------")
gu.log("--------加载个性化配置--------", gu.LEVEL_INFO, fg=gu.FG_COLORS['yellow'])
# 得到关键词
if os.path.exists("keyword.json"):
with open("keyword.json", 'r', encoding='utf-8') as f:
@@ -244,10 +233,9 @@ def initBot(cfg, prov):
if 'baidu_aip' in cfg and 'enable' in cfg['baidu_aip'] and cfg['baidu_aip']['enable']:
try:
baidu_judge = BaiduJudge(cfg['baidu_aip'])
print("[System] 百度内容审核初始化成功")
gu.log("百度内容审核初始化成功", gu.LEVEL_INFO)
except BaseException as e:
input("[System] 百度内容审核初始化失败: " + str(e))
exit()
gu.log("百度内容审核初始化失败", gu.LEVEL_ERROR)
# 统计上传
if is_upload_log:
@@ -265,11 +253,11 @@ def initBot(cfg, prov):
# 得到私聊模式配置
if 'direct_message_mode' in cfg:
direct_message_mode = cfg['direct_message_mode']
print("[System] 私聊功能: "+str(direct_message_mode))
gu.log("私聊功能: "+str(direct_message_mode), gu.LEVEL_INFO)
# 得到发言频率配置
if 'limit' in cfg:
print('[System] 发言频率配置: '+str(cfg['limit']))
gu.log("发言频率配置: "+str(cfg['limit']), gu.LEVEL_INFO)
if 'count' in cfg['limit']:
frequency_count = cfg['limit']['count']
if 'time' in cfg['limit']:
@@ -277,26 +265,24 @@ def initBot(cfg, prov):
# 得到公告配置
if 'notice' in cfg:
print('[System] 公告配置: '+cfg['notice'])
gu.log("公告配置: "+cfg['notice'], gu.LEVEL_INFO)
announcement += cfg['notice']
try:
if 'uniqueSessionMode' in cfg and cfg['uniqueSessionMode']:
uniqueSession = True
else:
uniqueSession = False
print("[System] 独立会话: " + str(uniqueSession))
gu.log("独立会话: "+str(uniqueSession), gu.LEVEL_INFO)
if 'dump_history_interval' in cfg:
print("[System] 历史记录转储时间周期: " + cfg['dump_history_interval'] + "分钟")
gu.log("历史记录保存间隔: "+str(cfg['dump_history_interval']), gu.LEVEL_INFO)
except BaseException:
pass
print(f"[System] QQ开放平台AppID: {cfg['qqbot']['appid']} 令牌: {cfg['qqbot']['token']}")
print("\n[System] 如果有任何问题, 请在 https://github.com/Soulter/QQChannelChatGPT 上提交issue说明问题或者添加QQ905617992")
print("[System] 请给 https://github.com/Soulter/QQChannelChatGPT 点个star!")
gu.log(f"QQ开放平台AppID: {cfg['qqbot']['appid']} 令牌: {cfg['qqbot']['token']}")
if chosen_provider is None:
print("[System-Warning] 检测到没有启动任何一个语言模型。请至少在配置文件中启用一个语言模型。")
gu.log("检测到没有启动任何一个语言模型。请至少在配置文件中启用一个语言模型。", gu.LEVEL_CRITICAL)
# 得到指令设置(cmd_config.json)
if os.path.exists("cmd_config.json"):
@@ -310,42 +296,65 @@ def initBot(cfg, prov):
thread_inst = None
print("--------------------加载插件--------------------")
gu.log("--------加载插件--------", gu.LEVEL_INFO, fg=gu.FG_COLORS['yellow'])
# 加载插件
_command = Command(None)
ok, err = _command.plugin_reload(cached_plugins)
if ok:
print("加载插件完成")
gu.log("加载插件完成", gu.LEVEL_INFO)
else:
print(err)
gu.log(err, gu.LEVEL_ERROR)
print("--------------------加载平台--------------------")
gu.log("--------加载平台--------", gu.LEVEL_INFO, fg=gu.FG_COLORS['yellow'])
# GOCQ
global gocq_bot
if 'gocqbot' in cfg and cfg['gocqbot']['enable']:
print("- 启用QQ机器人 -")
gu.log("- 启用QQ机器人 -", gu.LEVEL_INFO)
if os.path.exists("cmd_config.json"):
with open("cmd_config.json", 'r', encoding='utf-8') as f:
cmd_config = json.load(f)
global admin_qq
global admin_qq, admin_qqchan
if "admin_qq" in cmd_config:
admin_qq = cmd_config['admin_qq']
print("[System] 管理者QQ号: " + admin_qq)
gu.log("管理者QQ号: " + admin_qq, gu.LEVEL_INFO)
else:
admin_qq = input("[System] 请输入管理者QQ号(管理者QQ号才能使用update/plugin等指令): ")
print("[System] 管理者QQ号设置: " + admin_qq)
gu.log("未设置管理者QQ号(管理者才能使用update/plugin等指令)", gu.LEVEL_WARNING)
admin_qq = input("请输入管理者QQ号(必须设置): ")
gu.log("管理者QQ号设置为: " + admin_qq, gu.LEVEL_INFO, fg=gu.FG_COLORS['yellow'])
cmd_config['admin_qq'] = admin_qq
with open("cmd_config.json", 'w', encoding='utf-8') as f:
json.dump(cmd_config, f, indent=4)
f.flush()
global gocq_app, gocq_bot, gocq_loop
gocq_bot = QQ()
if "admin_qqchan" in cmd_config:
admin_qqchan = cmd_config['admin_qqchan']
gu.log("管理者频道用户号: " + admin_qqchan, gu.LEVEL_INFO)
else:
gu.log("未设置管理者QQ频道用户号(管理者才能使用update/plugin等指令)", gu.LEVEL_WARNING)
admin_qqchan = input("请输入管理者频道用户号(不是QQ号, 可以先回车跳过然后在频道发送指令!myid获取): ")
if admin_qqchan == "":
gu.log("跳过设置管理者频道用户号", gu.LEVEL_INFO, fg=gu.FG_COLORS['yellow'])
else:
gu.log("管理者频道用户号设置为: " + admin_qqchan, gu.LEVEL_INFO, fg=gu.FG_COLORS['yellow'])
cmd_config['admin_qqchan'] = admin_qqchan
with open("cmd_config.json", 'w', encoding='utf-8') as f:
json.dump(cmd_config, f, indent=4)
f.flush()
global gocq_app, gocq_loop
gocq_loop = asyncio.new_event_loop()
gocq_bot = QQ(True, gocq_loop)
thread_inst = threading.Thread(target=run_gocq_bot, args=(gocq_loop, gocq_bot, gocq_app), daemon=False)
thread_inst.start()
else:
gocq_bot = QQ(False)
gu.log("机器人部署教程: https://github.com/Soulter/QQChannelChatGPT/wiki/", gu.LEVEL_INFO, fg=gu.FG_COLORS['yellow'])
gu.log("如果有任何问题, 请在 https://github.com/Soulter/QQChannelChatGPT 上提交issue说明问题", gu.LEVEL_INFO, fg=gu.FG_COLORS['yellow'])
gu.log("请给 https://github.com/Soulter/QQChannelChatGPT 点个star!", gu.LEVEL_INFO, fg=gu.FG_COLORS['yellow'])
# QQ频道
if 'qqbot' in cfg and cfg['qqbot']['enable']:
print("- 启用QQ频道机器人 -")
gu.log("- 启用QQ频道机器人 -", gu.LEVEL_INFO)
global qqchannel_bot, qqchan_loop
qqchannel_bot = QQChan()
qqchan_loop = asyncio.new_event_loop()
@@ -371,6 +380,16 @@ def run_qqchan_bot(cfg, loop, qqchannel_bot):
def run_gocq_bot(loop, gocq_bot, gocq_app):
asyncio.set_event_loop(loop)
gu.log("正在检查本地GO-CQHTTP连接...端口5700, 6700", tag="QQ")
while True:
if not gu.port_checker(5700) or not gu.port_checker(6700):
gu.log("与GO-CQHTTP通信失败, 请检查GO-CQHTTP是否启动并正确配置。5秒后自动重试。", gu.LEVEL_CRITICAL, tag="QQ")
time.sleep(5)
else:
gu.log("检查完毕,未发现问题。", tag="QQ")
break
global gocq_client
gocq_client = gocqClient()
try:
@@ -438,18 +457,18 @@ def oper_msg(message,
role = "member" # 角色
hit = False # 是否命中指令
command_result = () # 调用指令返回的结果
global admin_qq, cached_plugins
global admin_qq, admin_qqchan, cached_plugins, gocq_bot
if platform == PLATFORM_QQCHAN:
print("[QQCHAN-BOT] 接收到消息:"+ str(message.content))
gu.log(f"接收到消息:{message.content}", gu.LEVEL_INFO, tag="QQ频道")
user_id = message.author.id
user_name = message.author.username
global qqchan_loop
if platform == PLATFORM_GOCQ:
if isinstance(message.message[0], Plain):
print("[GOCQ-BOT] 接收到消息:"+ str(message.message[0].text))
gu.log(f"接收到消息:{message.message[0].text}", gu.LEVEL_INFO, tag="GOCQ")
elif isinstance(message.message[0], At):
print("[GOCQ-BOT] 接收到消息:"+ str(message.message[1].text))
gu.log(f"接收到消息:{message.message[1].text}", gu.LEVEL_INFO, tag="GOCQ")
user_id = message.user_id
user_name = message.user_id
@@ -478,7 +497,7 @@ def oper_msg(message,
session_id = message.channel_id
# 得到身份
if "2" in message.member.roles or "4" in message.member.roles or "5" in message.member.roles:
print("[QQCHAN-BOT] 检测到管理员身份")
gu.log(f"检测到管理员身份", gu.LEVEL_INFO, tag="QQ频道")
role = "admin"
else:
role = "member"
@@ -495,20 +514,24 @@ def oper_msg(message,
qq_msg = str(message.message[1].text).strip()
else:
return
session_id = message.group_id
# 适配GO-CQHTTP的频道功能
if message.type == "GuildMessage":
session_id = message.channel_id
else:
session_id = message.group_id
else:
qq_msg = message.message[0].text
session_id = message.user_id
role = "member"
if str(message.sender.user_id) == admin_qq:
print("[GOCQ-BOT] 检测到管理员身份")
if str(message.sender.user_id) == admin_qq or str(message.sender.tiny_id) == admin_qqchan:
gu.log("检测到管理员身份", gu.LEVEL_INFO, tag="GOCQ")
role = "admin"
if qq_msg == "":
send_message(platform, message, f"Hi~", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
return
logf.write("[QQBOT] "+ qq_msg+'\n')
logf.write("[GOCQBOT] "+ qq_msg+'\n')
logf.flush()
# 关键词回复
@@ -557,7 +580,10 @@ def oper_msg(message,
chatgpt_res = ""
if chosen_provider == OPENAI_OFFICIAL:
hit, command_result = command_openai_official.check_command(qq_msg, session_id, user_name, role, platform=platform, message_obj=message, cached_plugins=cached_plugins)
if chatgpt == None:
send_message(platform, message, f"管理员未启动此模型或者此模型初始化时失败。", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
return
hit, command_result = command_openai_official.check_command(qq_msg, session_id, user_name, role, platform=platform, message_obj=message, cached_plugins=cached_plugins, qq_platform=gocq_bot)
# hit: 是否触发了指令
if not hit:
# 请求ChatGPT获得结果
@@ -566,27 +592,35 @@ def oper_msg(message,
if OPENAI_OFFICIAL in reply_prefix:
chatgpt_res = reply_prefix[OPENAI_OFFICIAL] + chatgpt_res
except (BaseException) as e:
print("[System-Err] OpenAI API请求错误, 原因: "+str(e))
gu.log("OpenAI API请求错误, 原因: "+str(e), gu.LEVEL_ERROR)
send_message(platform, message, f"OpenAI API错误, 原因: {str(e)}", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
elif chosen_provider == REV_CHATGPT:
hit, command_result = command_rev_chatgpt.check_command(qq_msg, role, platform=platform, message=message, cached_plugins=cached_plugins)
if rev_chatgpt == None:
send_message(platform, message, f"管理员未启动此模型或者此模型初始化时失败。", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
return
hit, command_result = command_rev_chatgpt.check_command(qq_msg, role, platform=platform, message_obj=message, cached_plugins=cached_plugins, qq_platform=gocq_bot)
if not hit:
try:
while rev_chatgpt.is_all_busy():
time.sleep(1)
chatgpt_res = str(rev_chatgpt.text_chat(qq_msg))
if REV_CHATGPT in reply_prefix:
chatgpt_res = reply_prefix[REV_CHATGPT] + chatgpt_res
except BaseException as e:
print("[System-Err] RevChatGPT请求错误, 原因: "+str(e))
gu.log("逆向ChatGPT请求错误, 原因: "+str(e), gu.LEVEL_ERROR)
send_message(platform, message, f"RevChatGPT错误, 原因: \n{str(e)}", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
elif chosen_provider == REV_EDGEGPT:
if rev_edgegpt == None:
send_message(platform, message, f"管理员未启动此模型或者此模型初始化时失败。", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
return
if bing_cache_loop == None:
if platform == PLATFORM_GOCQ:
bing_cache_loop = gocq_loop
elif platform == PLATFORM_QQCHAN:
bing_cache_loop = qqchan_loop
hit, command_result = command_rev_edgegpt.check_command(qq_msg, bing_cache_loop, role, platform=platform, message_obj=message, cached_plugins=cached_plugins)
hit, command_result = command_rev_edgegpt.check_command(qq_msg, bing_cache_loop, role, platform=platform, message_obj=message, cached_plugins=cached_plugins, qq_platform=gocq_bot)
if not hit:
try:
while rev_edgegpt.is_busy():
@@ -605,7 +639,7 @@ def oper_msg(message,
if REV_EDGEGPT in reply_prefix:
chatgpt_res = reply_prefix[REV_EDGEGPT] + chatgpt_res
except BaseException as e:
print("[System-Err] Rev NewBing API错误。原因如下:\n"+str(e))
gu.log("NewBing请求错误, 原因: "+str(e), gu.LEVEL_ERROR)
send_message(platform, message, f"Rev NewBing API错误。原因如下\n{str(e)} \n前往官方频道反馈~", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
# 切换回原来的语言模型
@@ -622,7 +656,7 @@ def oper_msg(message,
with open("keyword.json", "r", encoding="utf-8") as f:
keywords = json.load(f)
# QQ昵称
# 昵称
if command == "nick":
with open("cmd_config.json", "r", encoding="utf-8") as f:
global nick_qq
@@ -630,7 +664,7 @@ def oper_msg(message,
if command_result[0]:
# 是否是画图指令
if isinstance(command_result, list) and len(command_result) == 3 and command_result[2] == 'draw':
if isinstance(command_result[1], list) and len(command_result) == 3 and command_result[2] == 'draw':
for i in command_result[1]:
send_message(platform, message, i, msg_ref=msg_ref, image=i, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
else:
@@ -666,7 +700,7 @@ def oper_msg(message,
try:
send_message(platform, message, chatgpt_res, msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
except BaseException as e:
print("回复消息错误: \n"+str(e))
gu.log("回复消息错误: \n"+str(e), gu.LEVEL_ERROR)
'''
获取统计信息
@@ -719,7 +753,7 @@ class gocqClient():
global nick_qq
# 将nick_qq转换为元组
if nick_qq == None:
nick_qq = ("ai",)
nick_qq = ("ai","!","")
if isinstance(nick_qq, str):
nick_qq = (nick_qq,)
if isinstance(nick_qq, list):
@@ -751,4 +785,29 @@ class gocqClient():
global nick_qq
await app.sendGroupMessage(source.group_id, [
Plain(text=f"欢迎加入本群!\n欢迎给https://github.com/Soulter/QQChannelChatGPT项目一个Star😊~\n@我输入help查看帮助~\n我叫{nick_qq}, 你也可以以【{nick_qq}+问题】的格式来提醒我并问我问题哦~\n")
])
])
@gocq_app.receiver("GuildMessage")
async def _(app: CQHTTP, source: GuildMessage):
# gu.log(str(source), gu.LEVEL_INFO, max_len=9999)
global nick_qq
if nick_qq == None:
nick_qq = ("ai","!","")
if isinstance(nick_qq, str):
nick_qq = (nick_qq,)
if isinstance(nick_qq, list):
nick_qq = tuple(nick_qq)
if isinstance(source.message[0], Plain):
if source.message[0].text.startswith(nick_qq):
_len = 0
for i in nick_qq:
if source.message[0].text.startswith(i):
_len = len(i)
source.message[0].text = source.message[0].text[_len:].strip()
new_sub_thread(oper_msg, (source, True, None, PLATFORM_GOCQ))
if isinstance(source.message[0], At):
if source.message[0].tiny_id == source.self_tiny_id:
new_sub_thread(oper_msg, (source, True, None, PLATFORM_GOCQ))
else:
return

18
main.py
View File

@@ -1,11 +1,10 @@
import threading
import asyncio
import os, sys
from pip._internal import main as pipmain
import util.general_utils as gu
abs_path = os.path.dirname(os.path.realpath(sys.argv[0])) + '/'
def main(loop, event):
def main():
try:
import cores.qqbot.core as qqBot
import yaml
@@ -13,7 +12,7 @@ def main(loop, event):
cfg = yaml.safe_load(ymlfile)
except BaseException as e:
print(e)
input("yaml库未导入或者配置文件格式错误,请退出程序重试。")
input("第三方依赖库未完全安装完毕,请退出程序重试。")
exit()
if 'http_proxy' in cfg:
@@ -22,7 +21,11 @@ def main(loop, event):
os.environ['HTTPS_PROXY'] = cfg['https_proxy']
provider = privider_chooser(cfg)
print('[System] 当前语言模型提供商: ' + str(provider))
if len(provider) == 0:
gu.log("未开启任何语言模型, 请在configs/config.yaml下选择开启相应语言模型。", gu.LEVEL_CRITICAL)
input("按任意键退出...")
exit()
print('[System] 开启的语言模型: ' + str(provider))
# 执行Bot
qqBot.initBot(cfg, provider)
@@ -116,7 +119,4 @@ if __name__ == "__main__":
except BaseException as e:
print(e)
print(f"[System-err] Replit Web保活服务启动失败:{str(e)}")
bot_event = threading.Event()
loop = asyncio.get_event_loop()
main(loop, bot_event)
main()

View File

@@ -9,6 +9,8 @@ import json
import util.plugin_util as putil
import shutil
import importlib
from util import general_utils as gu
from model.platform.qq import QQ
PLATFORM_QQCHAN = 'qqchan'
PLATFORM_GOCQ = 'gocq'
@@ -32,16 +34,16 @@ class Command:
except BaseException as e:
raise e
def check_command(self, message, role, platform, message_obj, cached_plugins: dict):
def check_command(self, message, role, platform, message_obj, cached_plugins: dict, qq_platform: QQ):
# 插件
for k, v in cached_plugins.items():
try:
hit, res = v["clsobj"].run(message, role, platform, message_obj)
hit, res = v["clsobj"].run(message, role, platform, message_obj, qq_platform)
if hit:
return True, res
except BaseException as e:
print(f"[Debug] {k}插件加载出现问题,原因: {str(e)}\n已安装插件: {cached_plugins.keys}\n如果你没有相关装插件的想法, 请直接忽略此报错, 不影响其他功能的运行。")
gu.log(f"{k}插件加载出现问题,原因: {str(e)}\n已安装插件: {cached_plugins.keys}\n如果你没有相关装插件的想法, 请直接忽略此报错, 不影响其他功能的运行。", level=gu.LEVEL_WARNING)
if self.command_start_with(message, "nick"):
return True, self.set_nick(message, platform)
@@ -49,8 +51,19 @@ class Command:
if self.command_start_with(message, "plugin"):
return True, self.plugin_oper(message, role, cached_plugins)
if self.command_start_with(message, "myid"):
return True, self.get_my_id(message_obj, platform)
return False, None
def get_my_id(self, message_obj, platform):
if platform == "gocq":
if message_obj.type == "GuildMessage":
return True, f"你的频道id是{str(message_obj.sender.tiny_id)}", "plugin"
else:
return True, f"你的QQ是{str(message_obj.sender.user_id)}", "plugin"
def plugin_reload(self, cached_plugins: dict, target: str = None, all: bool = False):
plugins = self.get_plugin_modules()
fail_rec = ""
@@ -272,7 +285,6 @@ class Command:
del_mode = False
if l[1] == "d":
print("删除关键词: "+l[2])
del_mode = True
try:
@@ -291,7 +303,6 @@ class Command:
return False, "该关键词不存在", "keyword"
keyword = {l[1]: l[2]}
with open("keyword.json", "w", encoding="utf-8") as f:
print("设置指令: "+l[1]+" -> "+l[2])
json.dump(keyword, f, ensure_ascii=False, indent=4)
f.flush()
if del_mode:

View File

@@ -1,6 +1,7 @@
from model.command.command import Command
from model.provider.provider_openai_official import ProviderOpenAIOfficial
from cores.qqbot.personality import personalities
from model.platform.qq import QQ
class CommandOpenAIOfficial(Command):
def __init__(self, provider: ProviderOpenAIOfficial):
@@ -14,8 +15,9 @@ class CommandOpenAIOfficial(Command):
role: str,
platform: str,
message_obj,
cached_plugins: dict):
hit, res = super().check_command(message, role, platform, message_obj=message_obj, cached_plugins=cached_plugins)
cached_plugins: dict,
qq_platform: QQ):
hit, res = super().check_command(message, role, platform, message_obj=message_obj, cached_plugins=cached_plugins, qq_platform=qq_platform)
if hit:
return True, res
if self.command_start_with(message, "reset", "重置"):
@@ -187,6 +189,10 @@ class CommandOpenAIOfficial(Command):
return True, f"自定义人格已设置。 \n人格信息: {ps}", "set"
def draw(self, message):
if message.startswith("/画"):
message = message[2:]
elif message.startswith(""):
message = message[1:]
try:
# 画图模式传回3个参数
img_url = self.provider.image_chat(message)

View File

@@ -1,5 +1,6 @@
from model.command.command import Command
from model.provider.provider_rev_chatgpt import ProviderRevChatGPT
from model.platform.qq import QQ
class CommandRevChatGPT(Command):
def __init__(self, provider: ProviderRevChatGPT):
@@ -11,8 +12,9 @@ class CommandRevChatGPT(Command):
role: str,
platform: str,
message_obj,
cached_plugins: dict):
hit, res = super().check_command(message, role, platform, message_obj=message_obj, cached_plugins=cached_plugins)
cached_plugins: dict,
qq_platform: QQ):
hit, res = super().check_command(message, role, platform, message_obj=message_obj, cached_plugins=cached_plugins, qq_platform=qq_platform)
if hit:
return True, res
if self.command_start_with(message, "help", "帮助"):

View File

@@ -1,6 +1,8 @@
from model.command.command import Command
from model.provider.provider_rev_edgegpt import ProviderRevEdgeGPT
import asyncio
from model.platform.qq import QQ
class CommandRevEdgeGPT(Command):
def __init__(self, provider: ProviderRevEdgeGPT):
self.provider = provider
@@ -13,8 +15,9 @@ class CommandRevEdgeGPT(Command):
role: str,
platform: str,
message_obj,
cached_plugins: dict):
hit, res = super().check_command(message, role, platform, message_obj=message_obj, cached_plugins=cached_plugins)
cached_plugins: dict,
qq_platform: QQ):
hit, res = super().check_command(message, role, platform, message_obj=message_obj, cached_plugins=cached_plugins, qq_platform=qq_platform)
if hit:
return True, res
if self.command_start_with(message, "reset"):

View File

@@ -1,24 +1,49 @@
from nakuru.entities.components import Plain, At, Image
from util import general_utils as gu
import asyncio
from nakuru import (
CQHTTP,
GuildMessage
)
class QQ:
def __init__(self, is_start: bool, gocq_loop = None) -> None:
self.is_start = is_start
self.gocq_loop = gocq_loop
def run_bot(self, gocq):
self.client = gocq
self.client: CQHTTP = gocq
self.client.run()
def get_msg_loop(self):
return self.gocq_loop
async def send_qq_msg(self,
source,
res,
image_mode: bool = False):
if not self.is_start:
raise Exception("管理员未启动GOCQ平台")
"""
res可以是一个数组也就是gocq的消息链.
res可以是一个数组, 也就是gocq的消息链
插件开发者请使用send方法, 可以不用直接调用这个方法。
"""
gu.log("回复GOCQ消息: "+str(res), level=gu.LEVEL_INFO, tag="GOCQ", max_len=40)
# print(res)
print("[System-Info] 回复QQ消息中..."+str(res))
if isinstance(source, int):
source = {
"type": "GroupMessage",
"group_id": source
}
# 回复消息链
if isinstance(res, list) and len(res) > 0:
await self.client.sendGroupMessage(source.group_id, res)
return
if source.type == "GuildMessage":
await self.client.sendGuildChannelMessage(source.guild_id, source.channel_id, res)
return
else:
await self.client.sendGroupMessage(source.group_id, res)
return
# 通过消息链处理
if not image_mode:
if source.type == "GroupMessage":
@@ -30,6 +55,10 @@ class QQ:
await self.client.sendFriendMessage(source.user_id, [
Plain(text=res)
])
elif source.type == "GuildMessage":
await self.client.sendGuildChannelMessage(source.guild_id, source.channel_id, [
Plain(text=res)
])
else:
if source.type == "GroupMessage":
await self.client.sendGroupMessage(source.group_id, [
@@ -41,4 +70,35 @@ class QQ:
await self.client.sendFriendMessage(source.user_id, [
Plain(text="好的,我根据你的需要为你生成了一张图片😊"),
Image.fromURL(url=res)
])
])
elif source.type == "GuildMessage":
await self.client.sendGuildChannelMessage(source.guild_id, source.channel_id, [
Plain(text="好的,我根据你的需要为你生成了一张图片😊"),
Image.fromURL(url=res)
])
def send(self,
to,
res,
):
'''
提供给插件的发送QQ消息接口, 不用在外部await。
参数说明第一个参数可以是消息对象也可以是QQ群号。第二个参数是消息内容消息内容可以是消息链列表也可以是纯文字信息
'''
try:
asyncio.run_coroutine_threadsafe(self.send_qq_msg(to, res), self.gocq_loop).result()
except BaseException as e:
raise e
def send_guild(self,
message_obj,
res,
):
'''
提供给插件的发送GOCQ QQ频道消息接口, 不用在外部await。
参数说明:第一个参数必须是消息对象, 第二个参数是消息内容(消息内容可以是消息链列表,也可以是纯文字信息)。
'''
try:
asyncio.run_coroutine_threadsafe(self.send_qq_msg(message_obj, res), self.gocq_loop).result()
except BaseException as e:
raise e

View File

@@ -6,7 +6,7 @@ import re
import asyncio
import requests
from cores.qqbot.personality import personalities
from util import general_utils as gu
class QQChan():
@@ -16,7 +16,8 @@ class QQChan():
self.client.run(appid=appid, token=token)
def send_qq_msg(self, message, res, image_mode=False, msg_ref = None):
print("[System-Info] 回复QQ频道消息中..."+str(res))
gu.log("回复QQ频道消息: "+str(res), level=gu.LEVEL_INFO, tag="QQ频道", max_len=30)
if not image_mode:
try:
if msg_ref is not None:

View File

@@ -6,6 +6,7 @@ import sys
from cores.database.conn import dbConn
from model.provider.provider import Provider
import threading
from util import general_utils as gu
abs_path = os.path.dirname(os.path.realpath(sys.argv[0])) + '/'
key_record_path = abs_path+'chatgpt_key_record'
@@ -16,7 +17,7 @@ class ProviderOpenAIOfficial(Provider):
if 'api_base' in cfg and cfg['api_base'] != 'none' and cfg['api_base'] != '':
openai.api_base = cfg['api_base']
if cfg['key'] != '' and cfg['key'] != None:
print("[System] 读取ChatGPT Key成功")
gu.log("读取ChatGPT Key成功")
self.key_list = cfg['key']
else:
input("[System] 请先去完善ChatGPT的Key。详情请前往https://beta.openai.com/account/api-keys")
@@ -25,7 +26,7 @@ class ProviderOpenAIOfficial(Provider):
self.init_key_record()
self.chatGPT_configs = cfg['chatGPTConfigs']
print(f'[System] 加载ChatGPTConfigs: {self.chatGPT_configs}')
gu.log(f'加载ChatGPTConfigs: {self.chatGPT_configs}')
self.openai_configs = cfg
# 会话缓存
self.session_dict = {}
@@ -39,9 +40,10 @@ class ProviderOpenAIOfficial(Provider):
db1 = dbConn()
for session in db1.get_all_session():
self.session_dict[session[0]] = json.loads(session[1])['data']
print("[System] 历史记录读取成功喵")
gu.log("历史记录读取成功喵")
except BaseException as e:
print("[System] 历史记录读取失败: " + str(e))
gu.log("历史记录读取失败", level=gu.LEVEL_ERROR)
# 读取统计信息
if not os.path.exists(abs_path+"configs/stat"):
@@ -118,9 +120,8 @@ class ProviderOpenAIOfficial(Provider):
)
break
except Exception as e:
print(e)
if 'You exceeded' in str(e) or 'Billing hard limit has been reached' in str(e) or 'No API key provided' in str(e) or 'Incorrect API key provided' in str(e):
print("[System] 当前Key已超额或者不正常,正在切换")
gu.log("当前Key已超额或者不正常,正在切换", level=gu.LEVEL_WARNING)
self.key_stat[openai.api_key]['exceed'] = True
self.save_key_record()
@@ -130,17 +131,20 @@ class ProviderOpenAIOfficial(Provider):
raise e
else:
break
if 'maximum context length' in str(e):
print("token超限, 清空对应缓存")
elif 'maximum context length' in str(e):
gu.log("token超限, 清空对应缓存")
self.session_dict[session_id] = []
cache_data_list, new_record, req = self.wrap(prompt, session_id)
else:
gu.log(str(e), level=gu.LEVEL_ERROR)
retry+=1
if retry >= 5:
raise BaseException("连接超时")
gu.log(r"如果报错, 且您的机器在中国大陆内, 请确保您的电脑已经设置好代理软件(梯子), 并在配置文件设置了系统代理地址。详见https://github.com/Soulter/QQChannelChatGPT/wiki/%E4%BA%8C%E3%80%81%E9%A1%B9%E7%9B%AE%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E9%85%8D%E7%BD%AE", max_len=999)
raise BaseException("连接出错")
self.key_stat[openai.api_key]['used'] += response['usage']['total_tokens']
self.save_key_record()
print("[ChatGPT] "+str(response["choices"][0]["message"]["content"]))
# print("[ChatGPT] "+str(response["choices"][0]["message"]["content"]))
chatgpt_res = str(response["choices"][0]["message"]["content"]).strip()
current_usage_tokens = response['usage']['total_tokens']
@@ -192,13 +196,12 @@ class ProviderOpenAIOfficial(Provider):
image_url = []
for i in range(img_num):
image_url.append(response['data'][i]['url'])
print(image_url)
break
except Exception as e:
print(e)
gu.log(str(e), level=gu.LEVEL_ERROR)
if 'You exceeded' in str(e) or 'Billing hard limit has been reached' in str(
e) or 'No API key provided' in str(e) or 'Incorrect API key provided' in str(e):
print("[System] 当前Key已超额或者不正常,正在切换")
gu.log("当前Key已超额或者不正常, 正在切换", level=gu.LEVEL_WARNING)
self.key_stat[openai.api_key]['exceed'] = True
self.save_key_record()
@@ -305,7 +308,7 @@ class ProviderOpenAIOfficial(Provider):
if not self.key_stat[key]['exceed']:
is_all_exceed = False
openai.api_key = key
print(f"[System] 切换到Key: {key}, 已使用token: {self.key_stat[key]['used']}")
gu.log(f"切换到Key: {key}, 已使用token: {self.key_stat[key]['used']}", level=gu.LEVEL_INFO)
if len(req) > 0:
try:
response = openai.ChatCompletion.create(
@@ -314,20 +317,21 @@ class ProviderOpenAIOfficial(Provider):
)
return response, True
except Exception as e:
print(e)
if 'You exceeded' in str(e):
print("[System] 当前Key已超额,正在切换")
gu.log("当前Key已超额, 正在切换")
self.key_stat[openai.api_key]['exceed'] = True
self.save_key_record()
time.sleep(1)
continue
else:
gu.log(str(e), level=gu.LEVEL_ERROR)
else:
return True
if is_all_exceed:
print("[System] 所有Key已超额")
gu.log("所有Key已超额", level=gu.LEVEL_CRITICAL)
return None, False
else:
print("[System] 在切换key时程序异常。")
gu.log("在切换key时程序异常。", level=gu.LEVEL_ERROR)
return None, False
def getConfigs(self):
@@ -375,7 +379,7 @@ class ProviderOpenAIOfficial(Provider):
try:
self.key_stat = json.load(keyfile)
except Exception as e:
print(e)
gu.log(str(e), level=gu.LEVEL_ERROR)
self.key_stat = {}
finally:
for key in self.key_list:

View File

@@ -1,13 +1,16 @@
from revChatGPT.V1 import Chatbot
from revChatGPT import typings
from model.provider.provider import Provider
from util import general_utils as gu
class ProviderRevChatGPT(Provider):
def __init__(self, config):
self.rev_chatgpt = []
for i in range(0, len(config['account'])):
try:
print(f"[System] 创建rev_ChatGPT负载{str(i)}中...")
gu.log(f"创建rev_ChatGPT负载{str(i)}中...", level=gu.LEVEL_INFO, tag="RevChatGPT")
if 'password' in config['account'][i]:
config['account'][i]['password'] = str(config['account'][i]['password'])
revstat = {
@@ -16,7 +19,7 @@ class ProviderRevChatGPT(Provider):
}
self.rev_chatgpt.append(revstat)
except BaseException as e:
print(f"[System] 创建rev_ChatGPT负载失败: {str(e)}")
gu.log(f"创建rev_ChatGPT负载{str(i)}失败: {str(e)}", level=gu.LEVEL_ERROR, tag="RevChatGPT")
def forget(self) -> bool:
return False
@@ -42,21 +45,22 @@ class ProviderRevChatGPT(Provider):
raise e
err_count += 1
print(f"[RevChatGPT] 请求出现问题: {str(e)} | 正在重试: {str(err_count)}")
gu.log(f"请求出现问题: {str(e)} | 正在重试: {str(err_count)}", level=gu.LEVEL_WARNING, tag="RevChatGPT")
if err_count >= retry_count:
raise e
except BaseException as e:
err_count += 1
print(f"[RevChatGPT] 请求出现问题: {str(e)} | 正在重试: {str(err_count)}")
gu.log(f"请求出现问题: {str(e)} | 正在重试: {str(err_count)}", level=gu.LEVEL_WARNING, tag="RevChatGPT")
if err_count >= retry_count:
raise e
if resp == '':
resp = "RevChatGPT出现故障."
print("[RevChatGPT] "+str(resp))
# print("[RevChatGPT] "+str(resp))
return resp
def text_chat(self, prompt):
def text_chat(self, prompt) -> str:
res = ''
print("[Debug] "+str(self.rev_chatgpt))
err_msg = ''
cursor = 0
for revstat in self.rev_chatgpt:
@@ -70,11 +74,17 @@ class ProviderRevChatGPT(Provider):
# todo: 细化错误管理
except BaseException as e:
revstat['busy'] = False
print(f"请求出现问题: {str(e)}")
gu.log(f"请求出现问题: {str(e)}", level=gu.LEVEL_WARNING, tag="RevChatGPT")
err_msg += f"账号{cursor} - 错误原因: {str(e)}"
continue
else:
err_msg += f"账号{cursor} - 错误原因: 忙碌"
continue
res = f'回复失败。错误跟踪:{err_msg}'
return res
return res
def is_all_busy(self) -> bool:
for revstat in self.rev_chatgpt:
if not revstat['busy']:
return False
return True

View File

@@ -2,6 +2,8 @@ from model.provider.provider import Provider
from EdgeGPT import Chatbot, ConversationStyle
import json
import os
from util import general_utils as gu
class ProviderRevEdgeGPT(Provider):
def __init__(self):
@@ -76,15 +78,15 @@ class ProviderRevEdgeGPT(Provider):
reply_msg += f"\n{throttling['numUserMessagesInConversation']}/{throttling['maxNumUserMessagesInConversation']}"
break
except BaseException as e:
# raise e
print(e)
gu.log(str(e), level=gu.LEVEL_WARNING, tag="RevEdgeGPT")
err_count += 1
if err_count >= retry_count:
gu.log(r"如果报错, 且您的机器在中国大陆内, 请确保您的电脑已经设置好代理软件(梯子), 并在配置文件设置了系统代理地址。详见https://github.com/Soulter/QQChannelChatGPT/wiki/%E4%BA%8C%E3%80%81%E9%A1%B9%E7%9B%AE%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E9%85%8D%E7%BD%AE", max_len=999)
self.busy = False
raise e
print("[RevEdgeGPT] 请求出现了一些问题, 正在重试。次数"+str(err_count))
gu.log("请求出现了一些问题, 正在重试。次数"+str(err_count), level=gu.LEVEL_WARNING, tag="RevEdgeGPT")
self.busy = False
print("[RevEdgeGPT] "+str(reply_msg))
# print("[RevEdgeGPT] "+str(reply_msg))
return reply_msg, 1

87
util/general_utils.py Normal file
View File

@@ -0,0 +1,87 @@
import datetime
import socket
FG_COLORS = {
"black": "30",
"red": "31",
"green": "32",
"yellow": "33",
"blue": "34",
"purple": "35",
"cyan": "36",
"white": "37",
"default": "39",
}
BG_COLORS = {
"black": "40",
"red": "41",
"green": "42",
"yellow": "43",
"blue": "44",
"purple": "45",
"cyan": "46",
"white": "47",
"default": "49",
}
LEVEL_INFO = "INFO"
LEVEL_WARNING = "WARNING"
LEVEL_ERROR = "ERROR"
LEVEL_CRITICAL = "CRITICAL"
level_colors = {
"INFO": "green",
"WARNING": "yellow",
"ERROR": "red",
"CRITICAL": "purple",
}
def log(
msg: str,
level: str = "INFO",
tag: str = "System",
fg: str = None,
bg: str = None,
max_len: int = 100):
"""
日志记录函数
"""
if len(msg) > max_len:
msg = msg[:max_len] + "..."
now = datetime.datetime.now().strftime("%m-%d %H:%M:%S")
pre = f"[{now}] [{level}] [{tag}]: {msg}"
if level == "INFO":
if fg is None:
fg = FG_COLORS["green"]
if bg is None:
bg = BG_COLORS["default"]
elif level == "WARNING":
if fg is None:
fg = FG_COLORS["yellow"]
if bg is None:
bg = BG_COLORS["default"]
elif level == "ERROR":
if fg is None:
fg = FG_COLORS["red"]
if bg is None:
bg = BG_COLORS["default"]
elif level == "CRITICAL":
if fg is None:
fg = FG_COLORS["purple"]
if bg is None:
bg = BG_COLORS["default"]
print(f"\033[{fg};{bg}m{pre}\033[0m")
def port_checker(port: int, host: str = "localhost"):
sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sk.settimeout(1)
try:
sk.connect((host, port))
sk.close()
return True
except Exception:
sk.close()
return False

View File

@@ -7,7 +7,7 @@ def get_classes(p_name, arg):
clsmembers = inspect.getmembers(arg, inspect.isclass)
for (name, _) in clsmembers:
# print(name, p_name)
if p_name.lower() == name.lower().replace("plugin", ""):
if p_name.lower() == name.lower()[:-6]:
classes.append(name)
break
return classes