mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-02 12:05:54 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86bef566c4 | ||
|
|
0983ccb61e | ||
|
|
a1d9f469c0 | ||
|
|
952124f783 | ||
|
|
6be12e8ace | ||
|
|
0799f380e1 | ||
|
|
f65270ee7e | ||
|
|
414910719c | ||
|
|
10a1e8faa6 | ||
|
|
4eea21927e | ||
|
|
48c7f659f9 | ||
|
|
b33333f4aa | ||
|
|
9edb32b081 | ||
|
|
c9b25fe806 | ||
|
|
b6ee3939be | ||
|
|
e5485cddd0 | ||
|
|
ac81597236 | ||
|
|
58d991df0a | ||
|
|
3f8e380da4 | ||
|
|
ae831a2654 | ||
|
|
ae72cf2283 | ||
|
|
8164f4b506 | ||
|
|
9617be0ca4 | ||
|
|
f079d7b9fa | ||
|
|
00afda452f | ||
|
|
70386abadd | ||
|
|
aba9d945b5 | ||
|
|
ced38490e1 | ||
|
|
ad28b69198 |
Submodule QChatGPT.wiki updated: 1e3c599c03...d0dd0c1ad3
12
README.md
12
README.md
@@ -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>
|
||||||
|
|
||||||
## 😘致谢
|
## 😘致谢
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
|
||||||
1
main.py
1
main.py
@@ -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:
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
@@ -1,2 +1 @@
|
|||||||
"""OpenAI 接口处理及会话管理相关
|
"""OpenAI 接口处理及会话管理相关"""
|
||||||
"""
|
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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})
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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]正在更新所有插件,请勿重复发起..."]
|
||||||
|
|||||||
39
pkg/qqbot/cmds/system/cmd.py
Normal file
39
pkg/qqbot/cmds/system/cmd.py
Normal 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
|
||||||
|
|
||||||
39
pkg/qqbot/cmds/system/cmds.py
Normal file
39
pkg/qqbot/cmds/system/cmds.py
Normal 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
|
||||||
|
|
||||||
@@ -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 = []
|
|
||||||
|
|
||||||
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
|
return True, reply
|
||||||
|
|
||||||
@@ -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]
|
||||||
|
|
||||||
|
|||||||
@@ -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'],
|
||||||
|
|||||||
@@ -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
@@ -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:
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
|
2023/3/31 21:35 【插件兼容性问题】若您使用了revLibs插件,并将主程序升级到了v2.3.0,请立即使用管理员账号向机器人账号发送!plugin update命令更新逆向库插件,以解决由于情景预设重构引起的兼容性问题。
|
||||||
|
|||||||
Reference in New Issue
Block a user