mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-04 21:06:03 +00:00
Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fed6f61ba | ||
|
|
59b2cd26d2 | ||
|
|
f7b87e99d2 | ||
|
|
70bc985145 | ||
|
|
070dbe9108 | ||
|
|
a63fa6d955 | ||
|
|
c7703809b0 | ||
|
|
37eb74338f | ||
|
|
77d5585b7c | ||
|
|
6cab3ef029 | ||
|
|
820a7b78fc | ||
|
|
c51dffef3a | ||
|
|
983bc3da3c | ||
|
|
09be956a58 | ||
|
|
5eded50c53 | ||
|
|
6d8eebd314 | ||
|
|
19a0572b5f | ||
|
|
6272e98474 | ||
|
|
45042fe7d4 | ||
|
|
d85e840126 | ||
|
|
804889f1de | ||
|
|
919c996434 | ||
|
|
00823b3d62 | ||
|
|
af54efd24a | ||
|
|
b1c9b121f6 | ||
|
|
7b5649d153 | ||
|
|
52bf716d84 | ||
|
|
c149dd7b66 | ||
|
|
65d5a1ed63 | ||
|
|
5516754bbb | ||
|
|
08082f2ee3 | ||
|
|
8489266080 | ||
|
|
51c7e0b235 | ||
|
|
628b6b0bb4 | ||
|
|
7e024d860d | ||
|
|
c2f6273f70 | ||
|
|
96e401ec7b | ||
|
|
ae8ac65447 | ||
|
|
2d4f59f36e | ||
|
|
0e85467e02 | ||
|
|
eb41cf5481 | ||
|
|
b970a42d07 | ||
|
|
8c9d123e1c | ||
|
|
ab2a95e347 | ||
|
|
2184c558a4 | ||
|
|
83cb8588fd | ||
|
|
007e82c533 | ||
|
|
499f8580a7 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -22,4 +22,6 @@ cmdpriv.json
|
|||||||
tips.py
|
tips.py
|
||||||
.venv
|
.venv
|
||||||
bin/
|
bin/
|
||||||
.vscode
|
.vscode
|
||||||
|
test_*
|
||||||
|
venv/
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
[](https://github.com/RockChinQ/QChatGPT/releases/latest)
|
[](https://github.com/RockChinQ/QChatGPT/releases/latest)
|
||||||
|
|
||||||
|
> 2023/4/27 正在对纯Python实现的QQ登录框架、YAML配置文件、异步编程等功能进行概念验证,欢迎体验[LightQChat](https://github.com/RockChinQ/LightQChat)项目
|
||||||
> 2023/4/24 支持使用go-cqhttp登录QQ,请查看[此文档](https://github.com/RockChinQ/QChatGPT/wiki/go-cqhttp%E9%85%8D%E7%BD%AE)
|
> 2023/4/24 支持使用go-cqhttp登录QQ,请查看[此文档](https://github.com/RockChinQ/QChatGPT/wiki/go-cqhttp%E9%85%8D%E7%BD%AE)
|
||||||
> 2023/3/18 现已支持GPT-4 API(内测),请查看`config-template.py`中的`completion_api_params`
|
> 2023/3/18 现已支持GPT-4 API(内测),请查看`config-template.py`中的`completion_api_params`
|
||||||
> 2023/3/15 逆向库已支持New Bing,使用方法查看[插件文档](https://github.com/RockChinQ/revLibs)
|
> 2023/3/15 逆向库已支持New Bing,使用方法查看[插件文档](https://github.com/RockChinQ/revLibs)
|
||||||
@@ -32,6 +33,7 @@
|
|||||||
- ChatGPT网页版GPT-3.5模型, 由[插件](https://github.com/RockChinQ/revLibs)接入
|
- ChatGPT网页版GPT-3.5模型, 由[插件](https://github.com/RockChinQ/revLibs)接入
|
||||||
- ChatGPT网页版GPT-4模型, 目前需要ChatGPT Plus订阅, 由[插件](https://github.com/RockChinQ/revLibs)接入
|
- ChatGPT网页版GPT-4模型, 目前需要ChatGPT Plus订阅, 由[插件](https://github.com/RockChinQ/revLibs)接入
|
||||||
- New Bing逆向库, 由[插件](https://github.com/RockChinQ/revLibs)接入
|
- New Bing逆向库, 由[插件](https://github.com/RockChinQ/revLibs)接入
|
||||||
|
- HuggingChat, 由[插件](https://github.com/RockChinQ/revLibs)接入, 无需账号,仅支持英文
|
||||||
|
|
||||||
### 故事续写
|
### 故事续写
|
||||||
|
|
||||||
@@ -176,6 +178,8 @@
|
|||||||
|
|
||||||
#### Docker方式
|
#### Docker方式
|
||||||
|
|
||||||
|
> docker方式目前仅支持使用mirai登录,若您不**熟悉**docker的操作及相关知识,强烈建议您使用其他方式部署,我们**不会且难以**解决您主机上多个容器的连接问题。
|
||||||
|
|
||||||
请查看[此文档](res/docs/docker_deploy.md)
|
请查看[此文档](res/docs/docker_deploy.md)
|
||||||
由[@mikumifa](https://github.com/mikumifa)贡献
|
由[@mikumifa](https://github.com/mikumifa)贡献
|
||||||
|
|
||||||
@@ -292,6 +296,7 @@ python3 main.py
|
|||||||
- [chordfish-k/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/)上的机器人
|
- [oliverkirk-sudo/ChatPoeBot](https://github.com/oliverkirk-sudo/ChatPoeBot) - 接入[Poe](https://poe.com/)上的机器人
|
||||||
- [lieyanqzu/WeatherPlugin](https://github.com/lieyanqzu/WeatherPlugin) - 天气查询插件
|
- [lieyanqzu/WeatherPlugin](https://github.com/lieyanqzu/WeatherPlugin) - 天气查询插件
|
||||||
|
- [SysStatPlugin](https://github.com/RockChinQ/SysStatPlugin) - 查看系统状态
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## 😘致谢
|
## 😘致谢
|
||||||
@@ -304,6 +309,6 @@ python3 main.py
|
|||||||
|
|
||||||
以及所有[贡献者](https://github.com/RockChinQ/QChatGPT/graphs/contributors)和其他为本项目提供支持的朋友们。
|
以及所有[贡献者](https://github.com/RockChinQ/QChatGPT/graphs/contributors)和其他为本项目提供支持的朋友们。
|
||||||
|
|
||||||
<!-- ## 👍赞赏
|
## 👍赞赏
|
||||||
|
|
||||||
<img alt="赞赏码" src="res/mm_reward_qrcode_1672840549070.png" width="400" height="400"/> -->
|
<img alt="赞赏码" src="res/mm_reward_qrcode_1672840549070.png" width="400" height="400"/>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ English | [简体中文](README.md)
|
|||||||
- ChatGPT website edition (GPT-3.5), see [revLibs plugin](https://github.com/RockChinQ/revLibs)
|
- ChatGPT website edition (GPT-3.5), see [revLibs plugin](https://github.com/RockChinQ/revLibs)
|
||||||
- ChatGPT website edition (GPT-4), ChatGPT plus subscription required, see [revLibs plugin](https://github.com/RockChinQ/revLibs)
|
- ChatGPT website edition (GPT-4), ChatGPT plus subscription required, see [revLibs plugin](https://github.com/RockChinQ/revLibs)
|
||||||
- New Bing, see [revLibs plugin](https://github.com/RockChinQ/revLibs)
|
- New Bing, see [revLibs plugin](https://github.com/RockChinQ/revLibs)
|
||||||
|
- HuggingChat, see [revLibs plugin](https://github.com/RockChinQ/revLibs), no accounts required, English only
|
||||||
|
|
||||||
### Story
|
### Story
|
||||||
|
|
||||||
|
|||||||
@@ -123,13 +123,36 @@ preset_mode = "normal"
|
|||||||
# 注意:由消息前缀(prefix)匹配的消息中将会删除此前缀,正则表达式(regexp)匹配的消息不会删除匹配的部分
|
# 注意:由消息前缀(prefix)匹配的消息中将会删除此前缀,正则表达式(regexp)匹配的消息不会删除匹配的部分
|
||||||
# 前缀匹配优先级高于正则表达式匹配
|
# 前缀匹配优先级高于正则表达式匹配
|
||||||
# 正则表达式简明教程:https://www.runoob.com/regexp/regexp-tutorial.html
|
# 正则表达式简明教程:https://www.runoob.com/regexp/regexp-tutorial.html
|
||||||
|
#
|
||||||
|
# 支持针对不同群设置不同的响应规则,例如:
|
||||||
|
# response_rules = {
|
||||||
|
# "default": {
|
||||||
|
# "at": True,
|
||||||
|
# "prefix": ["/ai", "!ai", "!ai", "ai"],
|
||||||
|
# "regexp": [],
|
||||||
|
# "random_rate": 0.0,
|
||||||
|
# },
|
||||||
|
# "12345678": {
|
||||||
|
# "at": False,
|
||||||
|
# "prefix": ["/ai", "!ai", "!ai", "ai"],
|
||||||
|
# "regexp": [],
|
||||||
|
# "random_rate": 0.0,
|
||||||
|
# },
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# 以上设置将会在群号为12345678的群中关闭at响应
|
||||||
|
# 未单独设置的群将使用default规则
|
||||||
response_rules = {
|
response_rules = {
|
||||||
"at": True, # 是否响应at机器人的消息
|
"default": {
|
||||||
"prefix": ["/ai", "!ai", "!ai", "ai"],
|
"at": True, # 是否响应at机器人的消息
|
||||||
"regexp": [], # "为什么.*", "怎么?样.*", "怎么.*", "如何.*", "[Hh]ow to.*", "[Ww]hy not.*", "[Ww]hat is.*", ".*怎么办", ".*咋办"
|
"prefix": ["/ai", "!ai", "!ai", "ai"],
|
||||||
"random_rate": 0.0, # 随机响应概率,0.0-1.0,0.0为不随机响应,1.0为响应所有消息, 仅在前几项判断不通过时生效
|
"regexp": [], # "为什么.*", "怎么?样.*", "怎么.*", "如何.*", "[Hh]ow to.*", "[Ww]hy not.*", "[Ww]hat is.*", ".*怎么办", ".*咋办"
|
||||||
|
"random_rate": 0.0, # 随机响应概率,0.0-1.0,0.0为不随机响应,1.0为响应所有消息, 仅在前几项判断不通过时生效
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 消息忽略规则
|
# 消息忽略规则
|
||||||
# 适用于私聊及群聊
|
# 适用于私聊及群聊
|
||||||
# 符合此规则的消息将不会被响应
|
# 符合此规则的消息将不会被响应
|
||||||
@@ -218,6 +241,14 @@ process_message_timeout = 30
|
|||||||
# 回复消息时是否显示[GPT]前缀
|
# 回复消息时是否显示[GPT]前缀
|
||||||
show_prefix = False
|
show_prefix = False
|
||||||
|
|
||||||
|
# 回复前的强制延迟时间,降低机器人被腾讯风控概率
|
||||||
|
# *此机制对命令和消息、私聊及群聊均生效
|
||||||
|
# 每次处理时从以下的范围取一个随机秒数,
|
||||||
|
# 当此次消息处理时间低于此秒数时,将会强制延迟至此秒数
|
||||||
|
# 例如:[1.5, 3],则每次处理时会随机取一个1.5-3秒的随机数,若处理时间低于此随机数,则强制延迟至此随机秒数
|
||||||
|
# 若您不需要此功能,请将force_delay_range设置为[0, 0]
|
||||||
|
force_delay_range = [1.5, 3]
|
||||||
|
|
||||||
# 应用长消息处理策略的阈值
|
# 应用长消息处理策略的阈值
|
||||||
# 当回复消息长度超过此值时,将使用长消息处理策略
|
# 当回复消息长度超过此值时,将使用长消息处理策略
|
||||||
blob_message_threshold = 256
|
blob_message_threshold = 256
|
||||||
|
|||||||
6
main.py
6
main.py
@@ -48,8 +48,8 @@ def init_db():
|
|||||||
def ensure_dependencies():
|
def ensure_dependencies():
|
||||||
import pkg.utils.pkgmgr as pkgmgr
|
import pkg.utils.pkgmgr as pkgmgr
|
||||||
pkgmgr.run_pip(["install", "openai", "Pillow", "nakuru-project-idk", "--upgrade",
|
pkgmgr.run_pip(["install", "openai", "Pillow", "nakuru-project-idk", "--upgrade",
|
||||||
"-i", "https://pypi.douban.com/simple/",
|
"-i", "https://pypi.tuna.tsinghua.edu.cn/simple",
|
||||||
"--trusted-host", "pypi.douban.com"])
|
"--trusted-host", "pypi.tuna.tsinghua.edu.cn"])
|
||||||
|
|
||||||
|
|
||||||
known_exception_caught = False
|
known_exception_caught = False
|
||||||
@@ -268,7 +268,7 @@ def start(first_time_init=False):
|
|||||||
import config
|
import config
|
||||||
if config.msg_source_adapter == "yirimirai":
|
if config.msg_source_adapter == "yirimirai":
|
||||||
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("QQ: {}, MAH: {}".format(config.mirai_http_api_config['qq'], config.mirai_http_api_config['host']+":"+str(config.mirai_http_api_config['port'])))
|
||||||
logging.critical('程序启动完成,如长时间未显示 "成功登录到账号xxxxx" ,并且不回复消息,请查看 '
|
logging.critical('程序启动完成,如长时间未显示 "成功登录到账号xxxxx" ,并且不回复消息,解决办法(请勿到群里问): '
|
||||||
'https://github.com/RockChinQ/QChatGPT/issues/37')
|
'https://github.com/RockChinQ/QChatGPT/issues/37')
|
||||||
elif config.msg_source_adapter == 'nakuru':
|
elif config.msg_source_adapter == 'nakuru':
|
||||||
logging.info("host: {}, port: {}, http_port: {}".format(config.nakuru_config['host'], config.nakuru_config['port'], config.nakuru_config['http_port']))
|
logging.info("host: {}, port: {}, http_port: {}".format(config.nakuru_config['host'], config.nakuru_config['port'], config.nakuru_config['http_port']))
|
||||||
|
|||||||
@@ -27,15 +27,17 @@
|
|||||||
},
|
},
|
||||||
"preset_mode": "normal",
|
"preset_mode": "normal",
|
||||||
"response_rules": {
|
"response_rules": {
|
||||||
"at": true,
|
"default": {
|
||||||
"prefix": [
|
"at": true,
|
||||||
"/ai",
|
"prefix": [
|
||||||
"!ai",
|
"/ai",
|
||||||
"!ai",
|
"!ai",
|
||||||
"ai"
|
"!ai",
|
||||||
],
|
"ai"
|
||||||
"regexp": [],
|
],
|
||||||
"random_rate": 0.0
|
"regexp": [],
|
||||||
|
"random_rate": 0.0
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"ignore_rules": {
|
"ignore_rules": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
@@ -65,6 +67,10 @@
|
|||||||
"include_image_description": true,
|
"include_image_description": true,
|
||||||
"process_message_timeout": 30,
|
"process_message_timeout": 30,
|
||||||
"show_prefix": false,
|
"show_prefix": false,
|
||||||
|
"force_delay_range": [
|
||||||
|
1.5,
|
||||||
|
3
|
||||||
|
],
|
||||||
"blob_message_threshold": 256,
|
"blob_message_threshold": 256,
|
||||||
"blob_message_strategy": "forward",
|
"blob_message_strategy": "forward",
|
||||||
"wait_last_done": true,
|
"wait_last_done": true,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import sys
|
|||||||
import shutil
|
import shutil
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
import pkg.utils.updater as updater
|
||||||
import pkg.utils.context as context
|
import pkg.utils.context as context
|
||||||
import pkg.plugin.switch as switch
|
import pkg.plugin.switch as switch
|
||||||
import pkg.plugin.settings as settings
|
import pkg.plugin.settings as settings
|
||||||
@@ -79,7 +80,7 @@ def walk_plugin_path(module, prefix='', path_prefix=''):
|
|||||||
__current_module_path__ = "plugins/"+path_prefix + item.name + '.py'
|
__current_module_path__ = "plugins/"+path_prefix + item.name + '.py'
|
||||||
|
|
||||||
importlib.import_module(module.__name__ + '.' + item.name)
|
importlib.import_module(module.__name__ + '.' + item.name)
|
||||||
logging.info('加载模块: plugins/{} 成功'.format(path_prefix + item.name + '.py'))
|
logging.debug('加载模块: plugins/{} 成功'.format(path_prefix + item.name + '.py'))
|
||||||
except:
|
except:
|
||||||
logging.error('加载模块: plugins/{} 失败: {}'.format(path_prefix + item.name + '.py', sys.exc_info()))
|
logging.error('加载模块: plugins/{} 失败: {}'.format(path_prefix + item.name + '.py', sys.exc_info()))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
@@ -177,6 +178,43 @@ def uninstall_plugin(plugin_name: str) -> str:
|
|||||||
return "plugins/"+plugin_path
|
return "plugins/"+plugin_path
|
||||||
|
|
||||||
|
|
||||||
|
def update_plugin(plugin_name: str):
|
||||||
|
"""更新插件"""
|
||||||
|
# 检查是否有远程地址记录
|
||||||
|
target_plugin_dir = "plugins/" + __plugins__[plugin_name]['path'].replace("\\", "/").split("plugins/")[1].split("/")[0]
|
||||||
|
|
||||||
|
remote_url = updater.get_remote_url(target_plugin_dir)
|
||||||
|
if remote_url == "https://github.com/RockChinQ/QChatGPT" or remote_url == "https://gitee.com/RockChin/QChatGPT" \
|
||||||
|
or remote_url == "" or remote_url is None or remote_url == "http://github.com/RockChinQ/QChatGPT" or remote_url == "http://gitee.com/RockChin/QChatGPT":
|
||||||
|
raise Exception("插件没有远程地址记录,无法更新")
|
||||||
|
|
||||||
|
# 把远程clone到temp/plugins/update/插件名
|
||||||
|
logging.info("克隆插件储存库: {}".format(remote_url))
|
||||||
|
|
||||||
|
from dulwich import porcelain
|
||||||
|
clone_target_dir = "temp/plugins/update/"+target_plugin_dir.split("/")[-1]+"/"
|
||||||
|
|
||||||
|
if os.path.exists(clone_target_dir):
|
||||||
|
shutil.rmtree(clone_target_dir)
|
||||||
|
|
||||||
|
if not os.path.exists(clone_target_dir):
|
||||||
|
os.makedirs(clone_target_dir)
|
||||||
|
repo = porcelain.clone(remote_url, clone_target_dir, checkout=True)
|
||||||
|
|
||||||
|
# 检查此目录是否包含requirements.txt
|
||||||
|
if os.path.exists(clone_target_dir+"requirements.txt"):
|
||||||
|
logging.info("检测到requirements.txt,正在安装依赖")
|
||||||
|
import pkg.utils.pkgmgr
|
||||||
|
pkg.utils.pkgmgr.install_requirements(clone_target_dir+"requirements.txt")
|
||||||
|
|
||||||
|
import pkg.utils.log as log
|
||||||
|
log.reset_logging()
|
||||||
|
|
||||||
|
# 将temp/plugins/update/插件名 覆盖到 plugins/插件名
|
||||||
|
shutil.rmtree(target_plugin_dir)
|
||||||
|
|
||||||
|
shutil.copytree(clone_target_dir, target_plugin_dir)
|
||||||
|
|
||||||
class EventContext:
|
class EventContext:
|
||||||
"""事件上下文"""
|
"""事件上下文"""
|
||||||
eid = 0
|
eid = 0
|
||||||
@@ -283,11 +321,11 @@ class PluginHost:
|
|||||||
|
|
||||||
def send_person_message(self, person, message):
|
def send_person_message(self, person, message):
|
||||||
"""发送私聊消息"""
|
"""发送私聊消息"""
|
||||||
asyncio.run(self.get_bot().send_friend_message(person, message))
|
self.get_bot_adapter().send_message("person", person, message)
|
||||||
|
|
||||||
def send_group_message(self, group, message):
|
def send_group_message(self, group, message):
|
||||||
"""发送群消息"""
|
"""发送群消息"""
|
||||||
asyncio.run(self.get_bot().send_group_message(group, message))
|
self.get_bot_adapter().send_message("group", group, message)
|
||||||
|
|
||||||
def notify_admin(self, message):
|
def notify_admin(self, message):
|
||||||
"""通知管理员"""
|
"""通知管理员"""
|
||||||
@@ -344,3 +382,6 @@ class PluginHost:
|
|||||||
event_context.__return_value__))
|
event_context.__return_value__))
|
||||||
|
|
||||||
return event_context
|
return event_context
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
pass
|
||||||
|
|||||||
@@ -260,8 +260,8 @@ def execute(context: Context) -> list:
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
logging.debug('执行指令: {}'.format(path))
|
|
||||||
node = __command_list__[path]
|
node = __command_list__[path]
|
||||||
|
logging.debug('执行指令: {}'.format(path))
|
||||||
|
|
||||||
# 检查权限
|
# 检查权限
|
||||||
if ctx.privilege < node['privilege']:
|
if ctx.privilege < node['privilege']:
|
||||||
|
|||||||
@@ -97,37 +97,34 @@ class PluginUpdateCommand(AbstractCommandNode):
|
|||||||
plugin_list = plugin_host.__plugins__
|
plugin_list = plugin_host.__plugins__
|
||||||
|
|
||||||
reply = []
|
reply = []
|
||||||
def closure():
|
|
||||||
try:
|
|
||||||
import pkg.utils.context
|
|
||||||
updated = []
|
|
||||||
for key in plugin_list:
|
|
||||||
plugin = plugin_list[key]
|
|
||||||
if updater.is_repo("/".join(plugin['path'].split('/')[:-1])):
|
|
||||||
success = updater.pull_latest("/".join(plugin['path'].split('/')[:-1]))
|
|
||||||
if success:
|
|
||||||
updated.append(plugin['name'])
|
|
||||||
|
|
||||||
# 检查是否有requirements.txt
|
if len(ctx.crt_params) > 0:
|
||||||
pkg.utils.context.get_qqbot_manager().notify_admin("正在安装依赖...")
|
def closure():
|
||||||
for key in plugin_list:
|
try:
|
||||||
plugin = plugin_list[key]
|
import pkg.utils.context
|
||||||
if os.path.exists("/".join(plugin['path'].split('/')[:-1])+"/requirements.txt"):
|
|
||||||
logging.info("{}检测到requirements.txt,安装依赖".format(plugin['name']))
|
updated = []
|
||||||
import pkg.utils.pkgmgr
|
|
||||||
pkg.utils.pkgmgr.install_requirements("/".join(plugin['path'].split('/')[:-1])+"/requirements.txt")
|
|
||||||
|
|
||||||
import pkg.utils.log as log
|
if ctx.crt_params[0] == 'all':
|
||||||
log.reset_logging()
|
for key in plugin_list:
|
||||||
|
plugin_host.update_plugin(key)
|
||||||
|
updated.append(key)
|
||||||
|
else:
|
||||||
|
if ctx.crt_params[0] in plugin_list:
|
||||||
|
plugin_host.update_plugin(ctx.crt_params[0])
|
||||||
|
updated.append(ctx.crt_params[0])
|
||||||
|
else:
|
||||||
|
raise Exception("未找到插件: {}".format(ctx.crt_params[0]))
|
||||||
|
|
||||||
pkg.utils.context.get_qqbot_manager().notify_admin("已更新插件: {}".format(", ".join(updated)))
|
pkg.utils.context.get_qqbot_manager().notify_admin("已更新插件: {}, 请发送 !reload 重载插件".format(", ".join(updated)))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error("插件更新失败:{}".format(e))
|
logging.error("插件更新失败:{}".format(e))
|
||||||
pkg.utils.context.get_qqbot_manager().notify_admin("插件更新失败:{} 请尝试手动更新插件".format(e))
|
pkg.utils.context.get_qqbot_manager().notify_admin("插件更新失败:{} 请尝试手动更新插件".format(e))
|
||||||
|
|
||||||
|
reply = ["[bot]正在更新插件,请勿重复发起..."]
|
||||||
threading.Thread(target=closure).start()
|
threading.Thread(target=closure).start()
|
||||||
reply = ["[bot]正在更新所有插件,请勿重复发起..."]
|
else:
|
||||||
|
reply = ["[bot]请指定要更新的插件, 或使用 !plugin update all 更新所有插件"]
|
||||||
return True, reply
|
return True, reply
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,10 +25,18 @@ import pkg.qqbot.adapter as msadapter
|
|||||||
|
|
||||||
|
|
||||||
# 检查消息是否符合泛响应匹配机制
|
# 检查消息是否符合泛响应匹配机制
|
||||||
def check_response_rule(text: str):
|
def check_response_rule(group_id:int, text: str):
|
||||||
config = pkg.utils.context.get_config()
|
config = pkg.utils.context.get_config()
|
||||||
|
|
||||||
rules = config.response_rules
|
rules = config.response_rules
|
||||||
|
|
||||||
|
# 检查是否有特定规则
|
||||||
|
if 'prefix' not in config.response_rules:
|
||||||
|
if str(group_id) in config.response_rules:
|
||||||
|
rules = config.response_rules[str(group_id)]
|
||||||
|
else:
|
||||||
|
rules = config.response_rules['default']
|
||||||
|
|
||||||
# 检查前缀匹配
|
# 检查前缀匹配
|
||||||
if 'prefix' in rules:
|
if 'prefix' in rules:
|
||||||
for rule in rules['prefix']:
|
for rule in rules['prefix']:
|
||||||
@@ -46,19 +54,39 @@ def check_response_rule(text: str):
|
|||||||
return False, ""
|
return False, ""
|
||||||
|
|
||||||
|
|
||||||
def response_at():
|
def response_at(group_id: int):
|
||||||
config = pkg.utils.context.get_config()
|
config = pkg.utils.context.get_config()
|
||||||
if 'at' not in config.response_rules:
|
|
||||||
|
use_response_rule = config.response_rules
|
||||||
|
|
||||||
|
# 检查是否有特定规则
|
||||||
|
if 'prefix' not in config.response_rules:
|
||||||
|
if str(group_id) in config.response_rules:
|
||||||
|
use_response_rule = config.response_rules[str(group_id)]
|
||||||
|
else:
|
||||||
|
use_response_rule = config.response_rules['default']
|
||||||
|
|
||||||
|
if 'at' not in use_response_rule:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return config.response_rules['at']
|
return use_response_rule['at']
|
||||||
|
|
||||||
|
|
||||||
def random_responding():
|
def random_responding(group_id):
|
||||||
config = pkg.utils.context.get_config()
|
config = pkg.utils.context.get_config()
|
||||||
if 'random_rate' in config.response_rules:
|
|
||||||
|
use_response_rule = config.response_rules
|
||||||
|
|
||||||
|
# 检查是否有特定规则
|
||||||
|
if 'prefix' not in config.response_rules:
|
||||||
|
if str(group_id) in config.response_rules:
|
||||||
|
use_response_rule = config.response_rules[str(group_id)]
|
||||||
|
else:
|
||||||
|
use_response_rule = config.response_rules['default']
|
||||||
|
|
||||||
|
if 'random_rate' in use_response_rule:
|
||||||
import random
|
import random
|
||||||
return random.random() < config.response_rules['random_rate']
|
return random.random() < use_response_rule['random_rate']
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@@ -100,6 +128,7 @@ class QQBotManager:
|
|||||||
self.bot_account_id = self.adapter.bot_account_id
|
self.bot_account_id = self.adapter.bot_account_id
|
||||||
else:
|
else:
|
||||||
self.adapter = pkg.utils.context.get_qqbot_manager().adapter
|
self.adapter = pkg.utils.context.get_qqbot_manager().adapter
|
||||||
|
self.bot_account_id = pkg.utils.context.get_qqbot_manager().bot_account_id
|
||||||
|
|
||||||
pkg.utils.context.set_qqbot_manager(self)
|
pkg.utils.context.set_qqbot_manager(self)
|
||||||
|
|
||||||
@@ -317,16 +346,16 @@ class QQBotManager:
|
|||||||
if Image in event.message_chain:
|
if Image in event.message_chain:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
if At(self.bot_account_id) in event.message_chain and response_at():
|
if At(self.bot_account_id) in event.message_chain and response_at(event.group.id):
|
||||||
# 直接调用
|
# 直接调用
|
||||||
reply = process()
|
reply = process()
|
||||||
else:
|
else:
|
||||||
check, result = check_response_rule(str(event.message_chain).strip())
|
check, result = check_response_rule(event.group.id, str(event.message_chain).strip())
|
||||||
|
|
||||||
if check:
|
if check:
|
||||||
reply = process(result.strip())
|
reply = process(result.strip())
|
||||||
# 检查是否随机响应
|
# 检查是否随机响应
|
||||||
elif random_responding():
|
elif random_responding(event.group.id):
|
||||||
logging.info("随机响应group_{}消息".format(event.group.id))
|
logging.info("随机响应group_{}消息".format(event.group.id))
|
||||||
reply = process()
|
reply = process()
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,10 @@ def process_message(launcher_type: str, launcher_id: int, text_message: str, mes
|
|||||||
|
|
||||||
text_message = text_message.strip()
|
text_message = text_message.strip()
|
||||||
|
|
||||||
|
|
||||||
|
# 为强制消息延迟计时
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
# 处理消息
|
# 处理消息
|
||||||
try:
|
try:
|
||||||
|
|
||||||
@@ -168,4 +172,23 @@ def process_message(launcher_type: str, launcher_id: int, text_message: str, mes
|
|||||||
finally:
|
finally:
|
||||||
pkg.openai.session.get_session(session_name).release_response_lock()
|
pkg.openai.session.get_session(session_name).release_response_lock()
|
||||||
|
|
||||||
|
# 检查延迟时间
|
||||||
|
if config.force_delay_range[1] == 0:
|
||||||
|
delay_time = 0
|
||||||
|
else:
|
||||||
|
import random
|
||||||
|
|
||||||
|
# 从延迟范围中随机取一个值(浮点)
|
||||||
|
rdm = random.uniform(config.force_delay_range[0], config.force_delay_range[1])
|
||||||
|
|
||||||
|
spent = time.time() - start_time
|
||||||
|
|
||||||
|
# 如果花费时间小于延迟时间,则延迟
|
||||||
|
delay_time = rdm - spent if rdm - spent > 0 else 0
|
||||||
|
|
||||||
|
# 延迟
|
||||||
|
if delay_time > 0:
|
||||||
|
logging.info("[风控] 强制延迟{:.2f}秒(如需关闭,请到config.py修改force_delay_range字段)".format(delay_time))
|
||||||
|
time.sleep(delay_time)
|
||||||
|
|
||||||
return MessageChain(reply)
|
return MessageChain(reply)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class NakuruProjectMessageConverter(MessageConverter):
|
|||||||
elif type(message_chain) is list:
|
elif type(message_chain) is list:
|
||||||
msg_list = message_chain
|
msg_list = message_chain
|
||||||
else:
|
else:
|
||||||
raise Exception("Unknown message type: " + str(message_chain) + type(message_chain))
|
raise Exception("Unknown message type: " + str(message_chain) + str(type(message_chain)))
|
||||||
|
|
||||||
nakuru_msg_list = []
|
nakuru_msg_list = []
|
||||||
|
|
||||||
@@ -157,7 +157,6 @@ class NakuruProjectEventConverter(EventConverter):
|
|||||||
raise Exception("未支持转换的事件类型: " + str(event))
|
raise Exception("未支持转换的事件类型: " + str(event))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class NakuruProjectAdapter(MessageSourceAdapter):
|
class NakuruProjectAdapter(MessageSourceAdapter):
|
||||||
"""nakuru-project适配器"""
|
"""nakuru-project适配器"""
|
||||||
bot: nakuru.CQHTTP
|
bot: nakuru.CQHTTP
|
||||||
@@ -183,6 +182,9 @@ class NakuruProjectAdapter(MessageSourceAdapter):
|
|||||||
},
|
},
|
||||||
timeout=5
|
timeout=5
|
||||||
)
|
)
|
||||||
|
if resp.status_code == 403:
|
||||||
|
logging.error("go-cqhttp拒绝访问,请检查config.py中nakuru_config的token是否与go-cqhttp设置的access-token匹配")
|
||||||
|
raise Exception("go-cqhttp拒绝访问,请检查config.py中nakuru_config的token是否与go-cqhttp设置的access-token匹配")
|
||||||
self.bot_account_id = int(resp.json()['data']['user_id'])
|
self.bot_account_id = int(resp.json()['data']['user_id'])
|
||||||
|
|
||||||
def send_message(
|
def send_message(
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,8 +1,8 @@
|
|||||||
requests~=2.28.1
|
requests~=2.28.1
|
||||||
openai~=0.27.4
|
openai~=0.27.6
|
||||||
dulwich~=0.21.3
|
dulwich~=0.21.5
|
||||||
colorlog~=6.6.0
|
colorlog~=6.6.0
|
||||||
yiri-mirai~=0.2.6.1
|
yiri-mirai~=0.2.7
|
||||||
websockets
|
websockets
|
||||||
urllib3~=1.26.10
|
urllib3~=1.26.10
|
||||||
func_timeout~=4.3.5
|
func_timeout~=4.3.5
|
||||||
|
|||||||
@@ -5,24 +5,27 @@
|
|||||||
## 步骤
|
## 步骤
|
||||||
|
|
||||||
1. 从[go-cqhttp的Release](https://github.com/Mrs4s/go-cqhttp/releases/latest)下载最新的go-cqhttp可执行文件(建议直接下载可执行文件压缩包,而不是安装器)
|
1. 从[go-cqhttp的Release](https://github.com/Mrs4s/go-cqhttp/releases/latest)下载最新的go-cqhttp可执行文件(建议直接下载可执行文件压缩包,而不是安装器)
|
||||||
2. 解压并运行,首次运行会询问需要开放的网络协议,**请填入`02`并回车**
|
2. 解压并运行,首次运行会询问需要开放的网络协议,**请填入`02`并回车,必须输入`02`❗❗❗❗❗❗❗**
|
||||||
|
|
||||||
```
|
<h1> 你这里必须得输入`02`,你懂么,`0`必须得输入,看好了,看好下面输入什么了吗?别他妈的搁那就输个`2`完了启动连不上还跑群里问,问一个我踢一个。 </h1>
|
||||||
C:\Softwares\go-cqhttp.old> .\go-cqhttp.exe
|
|
||||||
未找到配置文件,正在为您生成配置文件中!
|
```
|
||||||
请选择你需要的通信方式:
|
C:\Softwares\go-cqhttp.old> .\go-cqhttp.exe
|
||||||
> 0: HTTP通信
|
未找到配置文件,正在为您生成配置文件中!
|
||||||
> 1: 云函数服务
|
请选择你需要的通信方式:
|
||||||
> 2: 正向 Websocket 通信
|
> 0: HTTP通信
|
||||||
> 3: 反向 Websocket 通信
|
> 1: 云函数服务
|
||||||
请输入你需要的编号(0-9),可输入多个,同一编号也可输入多个(如: 233)
|
> 2: 正向 Websocket 通信
|
||||||
您的选择是:02
|
> 3: 反向 Websocket 通信
|
||||||
```
|
请输入你需要的编号(0-9),可输入多个,同一编号也可输入多个(如: 233)
|
||||||
提示已生成`config.yml`文件,关闭go-cqhttp。
|
您的选择是:02
|
||||||
|
```
|
||||||
|
|
||||||
|
提示已生成`config.yml`文件,关闭go-cqhttp。
|
||||||
|
|
||||||
3. 打开go-cqhttp同目录的`config.yml`
|
3. 打开go-cqhttp同目录的`config.yml`
|
||||||
|
|
||||||
1. 编辑账号登录信息(可选)
|
1. 编辑账号登录信息
|
||||||
|
|
||||||
只需要修改下方`uin`和`password`为你要登录的机器人账号的QQ号和密码即可。
|
只需要修改下方`uin`和`password`为你要登录的机器人账号的QQ号和密码即可。
|
||||||
**若您不填写,将会在启动时请求扫码登录。**
|
**若您不填写,将会在启动时请求扫码登录。**
|
||||||
@@ -39,7 +42,7 @@
|
|||||||
max-times: 0 # 最大重连次数, 0为无限制
|
max-times: 0 # 最大重连次数, 0为无限制
|
||||||
```
|
```
|
||||||
|
|
||||||
2. 修改websocket端口(必需)
|
2. 修改websocket端口
|
||||||
|
|
||||||
在`config.yml`下方找到以下内容
|
在`config.yml`下方找到以下内容
|
||||||
|
|
||||||
@@ -64,4 +67,4 @@
|
|||||||
|
|
||||||
4. 配置完成,重新启动go-cqhttp
|
4. 配置完成,重新启动go-cqhttp
|
||||||
|
|
||||||
> 若启动后登录不成功,请尝试根据[此文档](https://docs.go-cqhttp.org/guide/config.html#%E8%AE%BE%E5%A4%87%E4%BF%A1%E6%81%AF)修改`device.json`的协议编号。
|
> 若启动后登录不成功,请尝试根据[此文档](https://docs.go-cqhttp.org/guide/config.html#%E8%AE%BE%E5%A4%87%E4%BF%A1%E6%81%AF)修改`device.json`的协议编号。
|
||||||
|
|||||||
@@ -23,15 +23,16 @@ QChatGPT 插件使用Wiki
|
|||||||
|
|
||||||
## 管理
|
## 管理
|
||||||
|
|
||||||
### !plugin 指令
|
### !plugin 命令
|
||||||
|
|
||||||
```
|
```
|
||||||
!plugin 列出所有已安装的插件
|
!plugin 列出所有已安装的插件
|
||||||
!plugin get <储存库地址> 从Git储存库安装插件(需要管理员权限)
|
!plugin get <储存库地址> 从Git储存库安装插件(需要管理员权限)
|
||||||
!plugin update 更新所有插件(需要管理员权限,仅支持从储存库安装的插件)
|
!plugin update all 更新所有插件(需要管理员权限,仅支持从储存库安装的插件)
|
||||||
!plugin del <插件名> 删除插件(需要管理员权限)
|
!plugin update <插件名> 更新指定插件
|
||||||
!plugin on <插件名> 启用插件(需要管理员权限)
|
!plugin del <插件名> 删除插件(需要管理员权限)
|
||||||
!plugin off <插件名> 禁用插件(需要管理员权限)
|
!plugin on <插件名> 启用插件(需要管理员权限)
|
||||||
|
!plugin off <插件名> 禁用插件(需要管理员权限)
|
||||||
```
|
```
|
||||||
|
|
||||||
### 控制插件执行顺序
|
### 控制插件执行顺序
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ replys_message = "[bot]err:请求超时"
|
|||||||
# 指令权限不足提示
|
# 指令权限不足提示
|
||||||
command_admin_message = "[bot]err:权限不足: "
|
command_admin_message = "[bot]err:权限不足: "
|
||||||
# 指令无效提示
|
# 指令无效提示
|
||||||
command_err_message = "[bot]err:指令执行出错:"
|
command_err_message = "[bot]err:指令不存在:"
|
||||||
|
|
||||||
# 会话重置提示
|
# 会话重置提示
|
||||||
command_reset_message = "[bot]:会话已重置"
|
command_reset_message = "[bot]:会话已重置"
|
||||||
|
|||||||
Reference in New Issue
Block a user