Compare commits

...

29 Commits

Author SHA1 Message Date
Rock Chin
86bef566c4 Release v2.3.4 2023-04-05 17:13:05 +08:00
Rock Chin
0983ccb61e doc: 添加模型切换器插件 2023-04-05 16:59:06 +08:00
Rock Chin
a1d9f469c0 doc: 添加模型切换器插件 2023-04-05 16:58:15 +08:00
Rock Chin
952124f783 feat: 禁用的插件仍进行初始化 2023-04-05 16:50:35 +08:00
GitHub Actions
6be12e8ace Update override-all.json 2023-04-05 07:48:46 +00:00
Rock Chin
0799f380e1 feat: 更改默认help_message 2023-04-05 15:48:21 +08:00
Rock Chin
f65270ee7e feat: 启动时输出mah相关配置项 2023-04-05 15:46:49 +08:00
Rock Chin
414910719c Release v2.3.3 2023-04-05 09:57:21 +08:00
Rock Chin
10a1e8faa6 fix: 回复内容不完整问题 (#208) 2023-04-05 09:56:27 +08:00
Rock Chin
4eea21927e doc: 补充手动部署中缺失的requests库 (#375) 2023-04-04 16:49:59 +08:00
Rock Chin
48c7f659f9 Release v2.3.2 2023-04-04 03:22:19 +00:00
Rock Chin
b33333f4aa Merge pull request #372 from RockChinQ/363-bug-helpmessage-creditapi
[Fix] help_message问题、额度检测接口问题
2023-04-04 11:20:34 +08:00
Rock Chin
9edb32b081 feat: usage命令不再显示额度 2023-04-04 03:15:07 +00:00
Rock Chin
c9b25fe806 doc: cmds指令的说明 2023-04-03 14:55:01 +00:00
GitHub Actions Bot
b6ee3939be Update cmdpriv-template.json 2023-04-03 14:41:25 +00:00
Rock Chin
e5485cddd0 feat: 更改使用!cmd指令查看指令列表 2023-04-03 14:40:27 +00:00
Rock Chin
ac81597236 feat: 插件更新异常处理 2023-04-03 14:09:30 +00:00
Rock Chin
58d991df0a Merge pull request #368 from zyckk4/docstring-improvements
[Chore] 统一docstring格式
2023-04-03 22:02:11 +08:00
Rock Chin
3f8e380da4 Merge pull request #369 from zyckk4/fix-type-hint
[Fix] 修复一处类型注解的错误
2023-04-03 13:39:56 +08:00
zyckk4
ae831a2654 [Fix] 修复一处类型注解的错误 2023-04-03 10:13:20 +08:00
zyckk4
ae72cf2283 chore: 统一docstring格式 2023-04-03 00:19:28 +08:00
Rock Chin
8164f4b506 Release v2.3.1 2023-04-02 16:32:52 +08:00
Rock Chin
9617be0ca4 fix: 未指定utf-8保存已输出的公告 2023-04-02 16:30:42 +08:00
Rock Chin
f079d7b9fa fix: Windows上无法读取和应用命令权限配置的问题 2023-04-02 16:24:30 +08:00
Rock Chin
00afda452f Merge pull request #365 from zyckk4/style-improvements
去除行尾空格
2023-04-02 16:04:52 +08:00
zyckk4
70386abadd 去除行尾空格 2023-04-02 14:43:34 +08:00
Rock Chin
aba9d945b5 doc: 收起功能概述 2023-04-01 09:59:33 +08:00
Rock Chin
ced38490e1 chore: 兼容性问题公告 2023-03-31 21:37:35 +08:00
Rock Chin
ad28b69198 doc: 添加ChatPoeBot插件链接 (#352) 2023-03-31 21:31:40 +08:00
25 changed files with 182 additions and 130 deletions

View File

@@ -45,8 +45,13 @@
</details> </details>
安装[此插件](https://github.com/RockChinQ/Switcher),即可在使用中切换文字模型。
## ✅功能 ## ✅功能
<details>
<summary>点击此处展开概述</summary>
<details> <details>
<summary>✅支持敏感词过滤,避免账号风险</summary> <summary>✅支持敏感词过滤,避免账号风险</summary>
@@ -124,6 +129,7 @@
- 目前已支持正向代理访问接口 - 目前已支持正向代理访问接口
- 详细请查看config.py中的`openai_config`的说明 - 详细请查看config.py中的`openai_config`的说明
</details> </details>
</details>
详情请查看[Wiki功能使用页](https://github.com/RockChinQ/QChatGPT/wiki/%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8#%E5%8A%9F%E8%83%BD%E7%82%B9%E5%88%97%E4%B8%BE) 详情请查看[Wiki功能使用页](https://github.com/RockChinQ/QChatGPT/wiki/%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8#%E5%8A%9F%E8%83%BD%E7%82%B9%E5%88%97%E4%B8%BE)
@@ -184,7 +190,7 @@ cd QChatGPT
2. 安装依赖 2. 安装依赖
```bash ```bash
pip3 install yiri-mirai openai colorlog func_timeout dulwich Pillow pip3 install requests yiri-mirai openai colorlog func_timeout dulwich Pillow
``` ```
3. 运行一次主程序,生成配置文件 3. 运行一次主程序,生成配置文件
@@ -240,12 +246,14 @@ python3 main.py
欢迎提交新的插件 欢迎提交新的插件
- [revLibs](https://github.com/RockChinQ/revLibs) - 将ChatGPT网页版接入此项目关于[官方接口和网页版有什么区别](https://github.com/RockChinQ/QChatGPT/wiki/%E5%AE%98%E6%96%B9%E6%8E%A5%E5%8F%A3%E4%B8%8EChatGPT%E7%BD%91%E9%A1%B5%E7%89%88) - [revLibs](https://github.com/RockChinQ/revLibs) - 将ChatGPT网页版接入此项目关于[官方接口和网页版有什么区别](https://github.com/RockChinQ/QChatGPT/wiki/%E5%AE%98%E6%96%B9%E6%8E%A5%E5%8F%A3%E4%B8%8EChatGPT%E7%BD%91%E9%A1%B5%E7%89%88)
- [Switcher](https://github.com/RockChinQ/Switcher) - 支持通过指令切换使用的模型
- [hello_plugin](https://github.com/RockChinQ/hello_plugin) - `hello_plugin` 的储存库形式,插件开发模板 - [hello_plugin](https://github.com/RockChinQ/hello_plugin) - `hello_plugin` 的储存库形式,插件开发模板
- [dominoar/QChatPlugins](https://github.com/dominoar/QchatPlugins) - dominoar编写的诸多新功能插件语音输出、Ranimg、屏蔽词规则等 - [dominoar/QChatPlugins](https://github.com/dominoar/QchatPlugins) - dominoar编写的诸多新功能插件语音输出、Ranimg、屏蔽词规则等
- [dominoar/QCP-NovelAi](https://github.com/dominoar/QCP-NovelAi) - NovelAI 故事叙述与绘画 - [dominoar/QCP-NovelAi](https://github.com/dominoar/QCP-NovelAi) - NovelAI 故事叙述与绘画
- [oliverkirk-sudo/chat_voice](https://github.com/oliverkirk-sudo/chat_voice) - 文字转语音输出使用HuggingFace上的[VITS-Umamusume-voice-synthesizer模型](https://huggingface.co/spaces/Plachta/VITS-Umamusume-voice-synthesizer) - [oliverkirk-sudo/chat_voice](https://github.com/oliverkirk-sudo/chat_voice) - 文字转语音输出使用HuggingFace上的[VITS-Umamusume-voice-synthesizer模型](https://huggingface.co/spaces/Plachta/VITS-Umamusume-voice-synthesizer)
- [RockChinQ/WaitYiYan](https://github.com/RockChinQ/WaitYiYan) - 实时获取百度`文心一言`等待列表人数 - [RockChinQ/WaitYiYan](https://github.com/RockChinQ/WaitYiYan) - 实时获取百度`文心一言`等待列表人数
- [QChartGPT_Emoticon_Plugin](https://github.com/chordfish-k/QChartGPT_Emoticon_Plugin) - 使机器人根据回复内容发送表情包 - [chordfish-k/QChartGPT_Emoticon_Plugin](https://github.com/chordfish-k/QChartGPT_Emoticon_Plugin) - 使机器人根据回复内容发送表情包
- [oliverkirk-sudo/ChatPoeBot](https://github.com/oliverkirk-sudo/ChatPoeBot) - 接入[Poe](https://poe.com/)上的机器人
</details> </details>
## 😘致谢 ## 😘致谢

View File

@@ -19,6 +19,7 @@
"prompt": 1, "prompt": 1,
"resend": 1, "resend": 1,
"reset": 1, "reset": 1,
"cmd": 1,
"help": 1, "help": 1,
"reload": 2, "reload": 2,
"update": 2, "update": 2,

View File

@@ -33,9 +33,9 @@ mirai_http_api_config = {
# }, # },
# "http_proxy": "http://127.0.0.1:12345" # "http_proxy": "http://127.0.0.1:12345"
# } # }
# #
# 现已支持反向代理可以添加reverse_proxy字段以使用反向代理 # 现已支持反向代理可以添加reverse_proxy字段以使用反向代理
# 使用反向代理可以在国内使用OpenAI的API反向代理的配置请参考 # 使用反向代理可以在国内使用OpenAI的API反向代理的配置请参考
# https://github.com/Ice-Hazymoon/openai-scf-proxy # https://github.com/Ice-Hazymoon/openai-scf-proxy
# #
# 反向代理填写示例: # 反向代理填写示例:
@@ -63,7 +63,7 @@ admin_qq = 0
# 情景预设(机器人人格) # 情景预设(机器人人格)
# 每个会话的预设信息,影响所有会话,无视指令重置 # 每个会话的预设信息,影响所有会话,无视指令重置
# 可以通过这个字段指定某些情况的回复,可直接用自然语言描述指令 # 可以通过这个字段指定某些情况的回复,可直接用自然语言描述指令
# 例如: # 例如:
# default_prompt = "如果我之后想获取帮助,请你说“输入!help获取帮助”" # default_prompt = "如果我之后想获取帮助,请你说“输入!help获取帮助”"
# 这样用户在不知所措的时候机器人就会提示其输入!help获取帮助 # 这样用户在不知所措的时候机器人就会提示其输入!help获取帮助
# 可参考 https://github.com/PlexPt/awesome-chatgpt-prompts-zh # 可参考 https://github.com/PlexPt/awesome-chatgpt-prompts-zh
@@ -81,14 +81,14 @@ admin_qq = 0
# 例如: # 例如:
# !reset linux-terminal # !reset linux-terminal
# 若不指定名称,则使用默认情景预设 # 若不指定名称,则使用默认情景预设
# #
# 也可以使用指令: # 也可以使用指令:
# !default <名称> # !default <名称>
# 将指定的情景预设设置为默认情景预设 # 将指定的情景预设设置为默认情景预设
# 例如: # 例如:
# !default linux-terminal # !default linux-terminal
# 之后的会话重置时若不指定名称则使用linux-terminal情景预设 # 之后的会话重置时若不指定名称则使用linux-terminal情景预设
# #
# 还可以加载文件中的预设文字使用方法请查看https://github.com/RockChinQ/QChatGPT/wiki/%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8#%E9%A2%84%E8%AE%BE%E6%96%87%E5%AD%97 # 还可以加载文件中的预设文字使用方法请查看https://github.com/RockChinQ/QChatGPT/wiki/%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8#%E9%A2%84%E8%AE%BE%E6%96%87%E5%AD%97
default_prompt = { default_prompt = {
"default": "如果我之后想获取帮助,请你说“输入!help获取帮助”", "default": "如果我之后想获取帮助,请你说“输入!help获取帮助”",
@@ -160,7 +160,7 @@ prompt_submit_length = 2048
# OpenAI补全API的参数 # OpenAI补全API的参数
# 请在下方填写模型,程序自动选择接口 # 请在下方填写模型,程序自动选择接口
# 现已支持的模型有: # 现已支持的模型有:
# #
# 'gpt-4' # 'gpt-4'
# 'gpt-4-0314' # 'gpt-4-0314'
# 'gpt-4-32k' # 'gpt-4-32k'
@@ -276,11 +276,6 @@ report_usage = True
logging_level = logging.INFO logging_level = logging.INFO
# 定制帮助消息 # 定制帮助消息
help_message = """此机器人通过调用OpenAI的GPT-3大型语言模型生成回复,不具有情感。 help_message = """此机器人通过调用大型语言模型生成回复,不具有情感。
你可以用自然语言与其交流,回复的消息中[GPT]开头的为模型生成的语言,[bot]开头的为程序提示。 你可以用自然语言与其交流,回复的消息中[GPT]开头的为模型生成的语言,[bot]开头的为程序提示。
了解此项目请找QQ 1010553892 联系作者 欢迎到github.com/RockChinQ/QChatGPT 给个star"""
请不要用其生成整篇文章或大段代码,因为每次只会向模型提交少部分文字,生成大部分文字会产生偏题、前后矛盾等问题
每次会话最后一次交互后{}分钟后会自动结束,结束后将开启新会话,如需继续前一次会话请发送 !last 重新开启
欢迎到github.com/RockChinQ/QChatGPT 给个star
指令帮助信息请查看: https://github.com/RockChinQ/QChatGPT/wiki/%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8#%E6%9C%BA%E5%99%A8%E4%BA%BA%E6%8C%87%E4%BB%A4""".format(session_expire_time // 60)

View File

@@ -290,6 +290,7 @@ def start(first_time_init=False):
if first_time_init: if first_time_init:
if not known_exception_caught: if not known_exception_caught:
logging.info("QQ: {}, MAH: {}".format(config.mirai_http_api_config['qq'], config.mirai_http_api_config['host']+":"+str(config.mirai_http_api_config['port'])))
logging.info('程序启动完成,如长时间未显示 ”成功登录到账号xxxxx“ ,并且不回复消息,请查看 ' logging.info('程序启动完成,如长时间未显示 ”成功登录到账号xxxxx“ ,并且不回复消息,请查看 '
'https://github.com/RockChinQ/QChatGPT/issues/37') 'https://github.com/RockChinQ/QChatGPT/issues/37')
else: else:

View File

@@ -74,5 +74,5 @@
"upgrade_dependencies": true, "upgrade_dependencies": true,
"report_usage": true, "report_usage": true,
"logging_level": 20, "logging_level": 20,
"help_message": "此机器人通过调用OpenAI的GPT-3大型语言模型生成回复,不具有情感。\n你可以用自然语言与其交流回复的消息中[GPT]开头的为模型生成的语言,[bot]开头的为程序提示。\n了解此项目请找QQ 1010553892 联系作者\n请不要用其生成整篇文章或大段代码因为每次只会向模型提交少部分文字生成大部分文字会产生偏题、前后矛盾等问题\n每次会话最后一次交互后20分钟后会自动结束结束后将开启新会话如需继续前一次会话请发送 !last 重新开启\n欢迎到github.com/RockChinQ/QChatGPT 给个star\n\n指令帮助信息请查看: https://github.com/RockChinQ/QChatGPT/wiki/%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8#%E6%9C%BA%E5%99%A8%E4%BA%BA%E6%8C%87%E4%BB%A4" "help_message": "此机器人通过调用大型语言模型生成回复,不具有情感。\n你可以用自然语言与其交流回复的消息中[GPT]开头的为模型生成的语言,[bot]开头的为程序提示。\n欢迎到github.com/RockChinQ/QChatGPT 给个star"
} }

View File

@@ -1,2 +1 @@
"""OpenAI 接口处理及会话管理相关 """OpenAI 接口处理及会话管理相关"""
"""

View File

@@ -11,8 +11,7 @@ class KeysManager:
"""所有api-key""" """所有api-key"""
using_key = "" using_key = ""
"""当前使用的api-key """当前使用的api-key"""
"""
alerted = [] alerted = []
"""已提示过超额的key """已提示过超额的key
@@ -48,7 +47,7 @@ class KeysManager:
self.auto_switch() self.auto_switch()
def auto_switch(self) -> (bool, str): def auto_switch(self) -> tuple[bool, str]:
"""尝试切换api-key """尝试切换api-key
Returns: Returns:
@@ -79,8 +78,7 @@ class KeysManager:
self.api_key[key_name] = key self.api_key[key_name] = key
def set_current_exceeded(self): def set_current_exceeded(self):
"""设置当前使用的api-key使用量超限 """设置当前使用的api-key使用量超限"""
"""
self.exceeded.append(self.using_key) self.exceeded.append(self.using_key)
def get_key_name(self, api_key): def get_key_name(self, api_key):

View File

@@ -48,8 +48,8 @@ class OpenAIInteract:
# 根据模型选择使用的接口 # 根据模型选择使用的接口
ai: ModelRequest = create_openai_model_request( ai: ModelRequest = create_openai_model_request(
config.completion_api_params['model'], config.completion_api_params['model'],
'user', 'user',
config.openai_config["http_proxy"] if "http_proxy" in config.openai_config else None config.openai_config["http_proxy"] if "http_proxy" in config.openai_config else None
) )
ai.request( ai.request(

View File

@@ -229,13 +229,7 @@ class Session:
# 成功获取,处理回复 # 成功获取,处理回复
res_test = message res_test = message
res_ans = res_test res_ans = res_test.strip()
# 去除开头可能的提示
res_ans_spt = res_test.split("\n\n")
if len(res_ans_spt) > 1:
del (res_ans_spt[0])
res_ans = '\n\n'.join(res_ans_spt)
# 将此次对话的双方内容加入到prompt中 # 将此次对话的双方内容加入到prompt中
self.prompt.append({'role': 'user', 'content': text}) self.prompt.append({'role': 'user', 'content': text})

View File

@@ -15,8 +15,7 @@ import pkg.plugin.settings as settings
from mirai import Mirai from mirai import Mirai
__plugins__ = {} __plugins__ = {}
""" """插件列表
插件列表
示例: 示例:
{ {
@@ -35,14 +34,15 @@ __plugins__ = {}
}, },
"instance": None "instance": None
} }
}""" }
"""
__plugins_order__ = [] __plugins_order__ = []
"""插件顺序""" """插件顺序"""
def generate_plugin_order(): def generate_plugin_order():
""" 根据__plugin__生成插件初始顺序无视是否启用 """ """根据__plugin__生成插件初始顺序无视是否启用"""
global __plugins_order__ global __plugins_order__
__plugins_order__ = [] __plugins_order__ = []
for plugin_name in __plugins__: for plugin_name in __plugins__:
@@ -50,13 +50,13 @@ def generate_plugin_order():
def iter_plugins(): def iter_plugins():
""" 按照顺序迭代插件 """ """按照顺序迭代插件"""
for plugin_name in __plugins_order__: for plugin_name in __plugins_order__:
yield __plugins__[plugin_name] yield __plugins__[plugin_name]
def iter_plugins_name(): def iter_plugins_name():
""" 迭代插件名 """ """迭代插件名"""
for plugin_name in __plugins_order__: for plugin_name in __plugins_order__:
yield plugin_name yield plugin_name
@@ -85,7 +85,7 @@ def walk_plugin_path(module, prefix='', path_prefix=''):
def load_plugins(): def load_plugins():
""" 加载插件 """ """加载插件"""
logging.info("加载插件") logging.info("加载插件")
PluginHost() PluginHost()
walk_plugin_path(__import__('plugins')) walk_plugin_path(__import__('plugins'))
@@ -102,12 +102,12 @@ def load_plugins():
def initialize_plugins(): def initialize_plugins():
""" 初始化插件 """ """初始化插件"""
logging.info("初始化插件") logging.info("初始化插件")
import pkg.plugin.models as models import pkg.plugin.models as models
for plugin in iter_plugins(): for plugin in iter_plugins():
if not plugin['enabled']: # if not plugin['enabled']:
continue # continue
try: try:
models.__current_registering_plugin__ = plugin['name'] models.__current_registering_plugin__ = plugin['name']
plugin['instance'] = plugin["class"](plugin_host=context.get_plugin_host()) plugin['instance'] = plugin["class"](plugin_host=context.get_plugin_host())
@@ -117,8 +117,7 @@ def initialize_plugins():
def unload_plugins(): def unload_plugins():
""" 卸载插件 """卸载插件"""
"""
# 不再显式卸载插件,因为当程序结束时,插件的析构函数会被系统执行 # 不再显式卸载插件,因为当程序结束时,插件的析构函数会被系统执行
# for plugin in __plugins__.values(): # for plugin in __plugins__.values():
# if plugin['enabled'] and plugin['instance'] is not None: # if plugin['enabled'] and plugin['instance'] is not None:
@@ -134,7 +133,7 @@ def unload_plugins():
def install_plugin(repo_url: str): def install_plugin(repo_url: str):
""" 安装插件从git储存库获取并解决依赖 """ """安装插件从git储存库获取并解决依赖"""
try: try:
import pkg.utils.pkgmgr import pkg.utils.pkgmgr
pkg.utils.pkgmgr.ensure_dulwich() pkg.utils.pkgmgr.ensure_dulwich()
@@ -162,7 +161,7 @@ def install_plugin(repo_url: str):
def uninstall_plugin(plugin_name: str) -> str: def uninstall_plugin(plugin_name: str) -> str:
""" 卸载插件 """ """卸载插件"""
if plugin_name not in __plugins__: if plugin_name not in __plugins__:
raise Exception("插件不存在") raise Exception("插件不存在")
@@ -178,17 +177,17 @@ def uninstall_plugin(plugin_name: str) -> str:
class EventContext: class EventContext:
""" 事件上下文 """ """事件上下文"""
eid = 0 eid = 0
"""事件编号""" """事件编号"""
name = "" name = ""
__prevent_default__ = False __prevent_default__ = False
""" 是否阻止默认行为 """ """是否阻止默认行为"""
__prevent_postorder__ = False __prevent_postorder__ = False
""" 是否阻止后续插件的执行 """ """是否阻止后续插件的执行"""
__return_value__ = {} __return_value__ = {}
""" 返回值 """ 返回值
@@ -251,7 +250,7 @@ class EventContext:
def emit(event_name: str, **kwargs) -> EventContext: def emit(event_name: str, **kwargs) -> EventContext:
""" 触发事件 """ """触发事件"""
import pkg.utils.context as context import pkg.utils.context as context
if context.get_plugin_host() is None: if context.get_plugin_host() is None:
return None return None
@@ -290,7 +289,7 @@ class PluginHost:
context.get_qqbot_manager().notify_admin(message) context.get_qqbot_manager().notify_admin(message)
def emit(self, event_name: str, **kwargs) -> EventContext: def emit(self, event_name: str, **kwargs) -> EventContext:
""" 触发事件 """ """触发事件"""
import json import json
event_context = EventContext(event_name) event_context = EventContext(event_name)

View File

@@ -7,7 +7,7 @@ import pkg.plugin.host as host
def wrapper_dict_from_plugin_list() -> dict: def wrapper_dict_from_plugin_list() -> dict:
""" 将插件列表转换为开关json """ """将插件列表转换为开关json"""
switch = {} switch = {}
for plugin_name in host.__plugins__: for plugin_name in host.__plugins__:
@@ -30,7 +30,7 @@ def apply_switch(switch: dict):
def dump_switch(): def dump_switch():
""" 保存开关数据 """ """保存开关数据"""
logging.debug("保存开关数据") logging.debug("保存开关数据")
# 将开关数据写入plugins/switch.json # 将开关数据写入plugins/switch.json
@@ -41,7 +41,7 @@ def dump_switch():
def load_switch(): def load_switch():
""" 加载开关数据 """ """加载开关数据"""
logging.debug("加载开关数据") logging.debug("加载开关数据")
# 读取plugins/switch.json # 读取plugins/switch.json

View File

@@ -315,12 +315,16 @@ def register_all():
def apply_privileges(): def apply_privileges():
"""读取cmdpriv.json并应用指令权限""" """读取cmdpriv.json并应用指令权限"""
with open('cmdpriv.json', 'r') as f: # 读取内容
data = json.load(f) json_str = ""
for path, priv in data.items(): with open('cmdpriv.json', 'r', encoding="utf-8") as f:
if path == 'comment': json_str = f.read()
continue
if __command_list__[path]['privilege'] != priv:
logging.debug('应用权限: {} -> {}(default: {})'.format(path, priv, __command_list__[path]['privilege']))
__command_list__[path]['privilege'] = priv data = json.loads(json_str)
for path, priv in data.items():
if path == 'comment':
continue
if __command_list__[path]['privilege'] != priv:
logging.debug('应用权限: {} -> {}(default: {})'.format(path, priv, __command_list__[path]['privilege']))
__command_list__[path]['privilege'] = priv

View File

@@ -98,28 +98,33 @@ class PluginUpdateCommand(AbstractCommandNode):
reply = [] reply = []
def closure(): def closure():
import pkg.utils.context try:
updated = [] import pkg.utils.context
for key in plugin_list: updated = []
plugin = plugin_list[key] for key in plugin_list:
if updater.is_repo("/".join(plugin['path'].split('/')[:-1])): plugin = plugin_list[key]
success = updater.pull_latest("/".join(plugin['path'].split('/')[:-1])) if updater.is_repo("/".join(plugin['path'].split('/')[:-1])):
if success: success = updater.pull_latest("/".join(plugin['path'].split('/')[:-1]))
updated.append(plugin['name']) if success:
updated.append(plugin['name'])
# 检查是否有requirements.txt # 检查是否有requirements.txt
pkg.utils.context.get_qqbot_manager().notify_admin("正在安装依赖...") pkg.utils.context.get_qqbot_manager().notify_admin("正在安装依赖...")
for key in plugin_list: for key in plugin_list:
plugin = plugin_list[key] plugin = plugin_list[key]
if os.path.exists("/".join(plugin['path'].split('/')[:-1])+"/requirements.txt"): if os.path.exists("/".join(plugin['path'].split('/')[:-1])+"/requirements.txt"):
logging.info("{}检测到requirements.txt安装依赖".format(plugin['name'])) logging.info("{}检测到requirements.txt安装依赖".format(plugin['name']))
import pkg.utils.pkgmgr import pkg.utils.pkgmgr
pkg.utils.pkgmgr.install_requirements("/".join(plugin['path'].split('/')[:-1])+"/requirements.txt") pkg.utils.pkgmgr.install_requirements("/".join(plugin['path'].split('/')[:-1])+"/requirements.txt")
import main import main
main.reset_logging() main.reset_logging()
pkg.utils.context.get_qqbot_manager().notify_admin("已更新插件: {}".format(", ".join(updated)))
except Exception as e:
logging.error("插件更新失败:{}".format(e))
pkg.utils.context.get_qqbot_manager().notify_admin("插件更新失败:{} 请尝试手动更新插件".format(e))
pkg.utils.context.get_qqbot_manager().notify_admin("已更新插件: {}".format(", ".join(updated)))
threading.Thread(target=closure).start() threading.Thread(target=closure).start()
reply = ["[bot]正在更新所有插件,请勿重复发起..."] reply = ["[bot]正在更新所有插件,请勿重复发起..."]

View File

@@ -0,0 +1,39 @@
from ..mgr import AbstractCommandNode, Context, __command_list__
@AbstractCommandNode.register(
parent=None,
name="cmd",
description="显示指令列表",
usage="!cmd\n!cmd <指令名称>",
aliases=[],
privilege=1
)
class CmdCommand(AbstractCommandNode):
@classmethod
def process(cls, ctx: Context) -> tuple[bool, list]:
command_list = __command_list__
reply = []
if len(ctx.params) == 0:
reply_str = "[bot]当前所有指令:\n\n"
# 遍历顶级指令
for key in command_list:
command = command_list[key]
if command['parent'] is None:
reply_str += "!{} - {}\n".format(key, command['description'])
reply_str += "\n请使用 !cmd <指令名称> 来查看指令的详细信息"
reply = [reply_str]
else:
command_name = ctx.params[0]
if command_name in command_list:
reply = [command_list[command_name]['cls'].help()]
else:
reply = ["[bot]指令 {} 不存在".format(command_name)]
return True, reply

View File

@@ -0,0 +1,39 @@
from ..mgr import AbstractCommandNode, Context, __command_list__
@AbstractCommandNode.register(
parent=None,
name="cmd",
description="显示指令列表",
usage="!help\n!help <指令名称>",
aliases=[],
privilege=1
)
class CmdCommand(AbstractCommandNode):
@classmethod
def process(cls, ctx: Context) -> tuple[bool, list]:
command_list = __command_list__
reply = []
if len(ctx.params) == 0:
reply_str = "[bot]当前所有指令:\n\n"
# 遍历顶级指令
for key in command_list:
command = command_list[key]
if command['parent'] is None:
reply_str += "!{} - {}\n".format(key, command['description'])
reply_str += "\n请使用 !cmd <指令名称> 来查看指令的详细信息"
reply = [reply_str]
else:
command_name = ctx.params[0]
if command_name in command_list:
reply = [command_list[command_name]['cls'].help()]
else:
reply = ["[bot]指令 {} 不存在".format(command_name)]
return True, reply

View File

@@ -1,38 +1,19 @@
from ..mgr import AbstractCommandNode, Context, __command_list__ from ..mgr import AbstractCommandNode, Context
@AbstractCommandNode.register( @AbstractCommandNode.register(
parent=None, parent=None,
name="help", name="help",
description="显示帮助信息", description="显示自定义的帮助信息",
usage="!help\n!help <指令名称>", usage="!help",
aliases=[], aliases=[],
privilege=1 privilege=1
) )
class HelpCommand(AbstractCommandNode): class HelpCommand(AbstractCommandNode):
@classmethod @classmethod
def process(cls, ctx: Context) -> tuple[bool, list]: def process(cls, ctx: Context) -> tuple[bool, list]:
command_list = __command_list__ import config
reply = [(config.help_message if hasattr(config, 'help_message') else "") + "\n请输入 !cmds 查看指令列表"]
reply = [] return True, reply
if len(ctx.params) == 0:
reply_str = "[bot]当前所有指令:\n\n"
# 遍历顶级指令
for key in command_list:
command = command_list[key]
if command['parent'] is None:
reply_str += "!{} - {}\n".format(key, command['description'])
reply_str += "\n请使用 !help <指令名称> 来查看指令的详细信息"
reply = [reply_str]
else:
command_name = ctx.params[0]
if command_name in command_list:
reply = [command_list[command_name]['cls'].help()]
else:
reply = ["[bot]指令 {} 不存在".format(command_name)]
return True, reply

View File

@@ -29,13 +29,6 @@ class UsageCommand(AbstractCommandNode):
.get_image_count_of_key(api_keys[key_name]) .get_image_count_of_key(api_keys[key_name])
reply_str += "{}:\n - 文本长度:{}\n - 图片数量:{}\n".format(key_name, int(text_length), reply_str += "{}:\n - 文本长度:{}\n - 图片数量:{}\n".format(key_name, int(text_length),
int(image_count)) int(image_count))
# 获取此key的额度
try:
http_proxy = config.openai_config["http_proxy"] if "http_proxy" in config.openai_config else None
credit_data = credit.fetch_credit_data(api_keys[key_name], http_proxy)
reply_str += " - 使用额度:{:.2f}/{:.2f}\n".format(credit_data['total_used'],credit_data['total_granted'])
except Exception as e:
logging.warning("获取额度失败:{}".format(e))
reply = [reply_str] reply = [reply_str]

View File

@@ -32,7 +32,7 @@ def process_command(session_name: str, text_message: str, mgr, config,
params = text_message[1:].strip().split(' ')[1:] params = text_message[1:].strip().split(' ')[1:]
# 把!~开头的转换成!cfg # 把!~开头的转换成!cfg
if cmd.startswith('~'): if cmd.startswith('~'):
params = [cmd[1:]] + params params = [cmd[1:]] + params
cmd = 'cfg' cmd = 'cfg'

View File

@@ -50,8 +50,8 @@ class ReplyFilter:
# 百度云审核URL # 百度云审核URL
baidu_url = "https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined?access_token=" + \ baidu_url = "https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined?access_token=" + \
str(requests.post("https://aip.baidubce.com/oauth/2.0/token", str(requests.post("https://aip.baidubce.com/oauth/2.0/token",
params={"grant_type": "client_credentials", params={"grant_type": "client_credentials",
"client_id": self.baidu_api_key, "client_id": self.baidu_api_key,
"client_secret": self.baidu_secret_key}).json().get("access_token")) "client_secret": self.baidu_secret_key}).json().get("access_token"))

View File

@@ -201,7 +201,6 @@ class QQBotManager:
def first_time_init(self, mirai_http_api_config: dict): def first_time_init(self, mirai_http_api_config: dict):
"""热重载后不再运行此函数""" """热重载后不再运行此函数"""
if 'adapter' not in mirai_http_api_config or mirai_http_api_config['adapter'] == "WebSocketAdapter": if 'adapter' not in mirai_http_api_config or mirai_http_api_config['adapter'] == "WebSocketAdapter":
bot = Mirai( bot = Mirai(
qq=mirai_http_api_config['qq'], qq=mirai_http_api_config['qq'],

View File

@@ -22,10 +22,10 @@ def read_saved() -> str:
# 已保存的在res/announcement_saved # 已保存的在res/announcement_saved
# 检查是否存在 # 检查是否存在
if not os.path.exists("res/announcement_saved"): if not os.path.exists("res/announcement_saved"):
with open("res/announcement_saved", "w") as f: with open("res/announcement_saved", "w", encoding="utf-8") as f:
f.write("") f.write("")
with open("res/announcement_saved", "r") as f: with open("res/announcement_saved", "r", encoding="utf-8") as f:
content = f.read() content = f.read()
return content return content
@@ -33,7 +33,7 @@ def read_saved() -> str:
def write_saved(content: str): def write_saved(content: str):
# 已保存的在res/announcement_saved # 已保存的在res/announcement_saved
with open("res/announcement_saved", "w") as f: with open("res/announcement_saved", "w", encoding="utf-8") as f:
f.write(content) f.write(content)

File diff suppressed because one or more lines are too long

View File

@@ -4,9 +4,7 @@ from concurrent.futures import ThreadPoolExecutor
class Pool: class Pool:
''' """线程池结构"""
线程池结构
'''
pool_num:int = None pool_num:int = None
ctl:ThreadPoolExecutor = None ctl:ThreadPoolExecutor = None
task_list:list = None task_list:list = None
@@ -33,12 +31,11 @@ class Pool:
class ThreadCtl: class ThreadCtl:
def __init__(self, sys_pool_num, admin_pool_num, user_pool_num): def __init__(self, sys_pool_num, admin_pool_num, user_pool_num):
''' """线程池控制类
线程池控制类
sys_pool_num分配系统使用的线程池数量(>=8) sys_pool_num分配系统使用的线程池数量(>=8)
admin_pool_num用于处理管理员消息的线程池数量(>=1) admin_pool_num用于处理管理员消息的线程池数量(>=1)
user_pool_num分配用于处理用户消息的线程池的数量(>=1) user_pool_num分配用于处理用户消息的线程池的数量(>=1)
''' """
if sys_pool_num < 5: if sys_pool_num < 5:
raise Exception("Too few system threads(sys_pool_num needs >= 8, but received {})".format(sys_pool_num)) raise Exception("Too few system threads(sys_pool_num needs >= 8, but received {})".format(sys_pool_num))
if admin_pool_num < 1: if admin_pool_num < 1:

View File

@@ -1 +1 @@
2023/3/31 21:35 【插件兼容性问题】若您使用了revLibs插件并将主程序升级到了v2.3.0,请立即使用管理员账号向机器人账号发送!plugin update命令更新逆向库插件以解决由于情景预设重构引起的兼容性问题。