@@ -10,5 +10,5 @@ nohup.out | |||||
tmp | tmp | ||||
plugins.json | plugins.json | ||||
itchat.pkl | itchat.pkl | ||||
user_datas.pkl | |||||
*.log | *.log | ||||
user_datas.pkl |
@@ -14,11 +14,13 @@ | |||||
pip3 install web.py | pip3 install web.py | ||||
``` | ``` | ||||
然后在[微信公众平台](mp.weixin.qq.com)注册一个自己的公众号,类型选择订阅号,主体为个人即可。 | |||||
然后在[微信公众平台](https://mp.weixin.qq.com)注册一个自己的公众号,类型选择订阅号,主体为个人即可。 | |||||
然后根据[接入指南](https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html)的说明,在[微信公众平台](mp.weixin.qq.com)的“设置与开发”-“基本配置”-“服务器配置”中填写服务器地址(URL)和令牌(Token)。这个Token是你自己编的一个特定的令牌。消息加解密方式目前选择的是明文模式。相关的服务器验证代码已经写好,你不需要再添加任何代码。你只需要在本项目根目录的`config.json`中添加`"channel_type": "wechatmp", "wechatmp_token": "your Token", ` 然后运行`python3 app.py`启动web服务器,然后在刚才的“服务器配置”中点击`提交`即可验证你的服务器。 | |||||
然后根据[接入指南](https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html)的说明,在[微信公众平台](https://mp.weixin.qq.com)的“设置与开发”-“基本配置”-“服务器配置”中填写服务器地址`URL`和令牌`Token`。这里的`URL`是`example.com/wx`的形式,不可以使用IP,`Token`是你自己编的一个特定的令牌。消息加解密方式目前选择的是明文模式。 | |||||
随后在[微信公众平台](mp.weixin.qq.com)启用服务器,关闭手动填写规则的自动回复,即可实现ChatGPT的自动回复。 | |||||
相关的服务器验证代码已经写好,你不需要再添加任何代码。你只需要在本项目根目录的`config.json`中添加`"channel_type": "wechatmp", "wechatmp_token": "your Token", ` 然后运行`python3 app.py`启动web服务器,然后在刚才的“服务器配置”中点击`提交`即可验证你的服务器。 | |||||
随后在[微信公众平台](https://mp.weixin.qq.com)启用服务器,关闭手动填写规则的自动回复,即可实现ChatGPT的自动回复。 | |||||
## 个人微信公众号的限制 | ## 个人微信公众号的限制 | ||||
由于目前测试的公众号不是企业主体,所以没有客服接口,因此公众号无法主动发出消息,只能被动回复。而微信官方对被动回复有5秒的时间限制,最多重试2次,因此最多只有15秒的自动回复时间窗口。因此如果问题比较复杂或者我们的服务器比较忙,ChatGPT的回答就没办法及时回复给用户。为了解决这个问题,这里做了回答缓存,它需要你在回复超时后,再次主动发送任意文字(例如1)来尝试拿到回答缓存。为了优化使用体验,目前设置了两分钟(120秒)的timeout,用户在至多两分钟后即可得到查询到回复或者错误原因。 | 由于目前测试的公众号不是企业主体,所以没有客服接口,因此公众号无法主动发出消息,只能被动回复。而微信官方对被动回复有5秒的时间限制,最多重试2次,因此最多只有15秒的自动回复时间窗口。因此如果问题比较复杂或者我们的服务器比较忙,ChatGPT的回答就没办法及时回复给用户。为了解决这个问题,这里做了回答缓存,它需要你在回复超时后,再次主动发送任意文字(例如1)来尝试拿到回答缓存。为了优化使用体验,目前设置了两分钟(120秒)的timeout,用户在至多两分钟后即可得到查询到回复或者错误原因。 | ||||
@@ -28,8 +30,5 @@ pip3 install web.py | |||||
## 私有api_key | ## 私有api_key | ||||
公共api有访问频率限制(免费账号每分钟最多20次ChatGPT的API调用),这在服务多人的时候会遇到问题。因此这里多加了一个设置私有api_key的功能。目前通过godcmd插件的命令来设置私有api_key。 | 公共api有访问频率限制(免费账号每分钟最多20次ChatGPT的API调用),这在服务多人的时候会遇到问题。因此这里多加了一个设置私有api_key的功能。目前通过godcmd插件的命令来设置私有api_key。 | ||||
## 命令优化 | |||||
之前plugin中#和$符号混用,且$这个符号在微信中和中文会有较大间隔,体验实在不好。这里我将所有命令更改成了以#开头。添加了一个叫finish的plugin来最后处理所有#结尾的命令,防止未知命令变成ChatGPT的query。 | |||||
## 测试范围 | ## 测试范围 | ||||
目前在`RoboStyle`这个公众号上进行了测试,感兴趣的可以关注并体验。开启了godcmd, Banwords, role, dungeon, finish这五个插件,其他的插件还没有测试。百度的接口暂未测试。语音对话没有测试。图片直接以链接形式回复(没有临时素材上传接口的权限)。 | 目前在`RoboStyle`这个公众号上进行了测试,感兴趣的可以关注并体验。开启了godcmd, Banwords, role, dungeon, finish这五个插件,其他的插件还没有测试。百度的接口暂未测试。语音对话没有测试。图片直接以链接形式回复(没有临时素材上传接口的权限)。 |
@@ -25,12 +25,12 @@ class WechatMPServer(): | |||||
def __init__(self): | def __init__(self): | ||||
pass | pass | ||||
def startup(self): | |||||
def startup(self): | |||||
urls = ( | urls = ( | ||||
'/wx', 'WechatMPChannel', | '/wx', 'WechatMPChannel', | ||||
) | ) | ||||
app = web.application(urls, globals()) | app = web.application(urls, globals()) | ||||
app.run() | |||||
web.httpserver.runsimple(app.wsgifunc(), ('0.0.0.0', 80)) | |||||
cache_dict = dict() | cache_dict = dict() | ||||
query1 = dict() | query1 = dict() | ||||
@@ -265,7 +265,7 @@ class WechatMPChannel(Channel): | |||||
if cache[0] > 1: | if cache[0] > 1: | ||||
reply_text = cache[1][:600] + " 【未完待续,回复任意文字以继续】" #wechatmp auto_reply length limit | |||||
reply_text = cache[1][:600] + "\n【未完待续,回复任意文字以继续】" #wechatmp auto_reply length limit | |||||
cache_dict[cache_key] = (cache[0] - 1, cache[1][600:]) | cache_dict[cache_key] = (cache[0] - 1, cache[1][600:]) | ||||
elif cache[0] == 1: | elif cache[0] == 1: | ||||
reply_text = cache[1] | reply_text = cache[1] | ||||
@@ -288,10 +288,10 @@ class WechatMPChannel(Channel): | |||||
replyMsg = reply.TextMsg(recMsg.FromUserName, recMsg.ToUserName, content) | replyMsg = reply.TextMsg(recMsg.FromUserName, recMsg.ToUserName, content) | ||||
return replyMsg.send() | return replyMsg.send() | ||||
else: | else: | ||||
print("暂且不处理") | |||||
logger.info("暂且不处理") | |||||
return "success" | return "success" | ||||
except Exception as exc: | except Exception as exc: | ||||
print(exc) | |||||
logger.exception(exc) | |||||
return exc | return exc | ||||
@@ -89,6 +89,8 @@ available_setting = { | |||||
"debug": False, # 是否开启debug模式,开启后会打印更多日志 | "debug": False, # 是否开启debug模式,开启后会打印更多日志 | ||||
# 插件配置 | |||||
"plugin_trigger_prefix": "$", # 规范插件提供聊天相关指令的前缀,建议不要和管理员指令前缀"#"冲突 | |||||
} | } | ||||
@@ -16,7 +16,7 @@ from uuid import getnode as get_mac | |||||
""" | """ | ||||
@plugins.register(name="BDunit", desire_priority=0, desc="Baidu unit bot system", version="0.1", author="jackson") | |||||
@plugins.register(name="BDunit", desire_priority=0, hidden=True, desc="Baidu unit bot system", version="0.1", author="jackson") | |||||
class BDunit(Plugin): | class BDunit(Plugin): | ||||
def __init__(self): | def __init__(self): | ||||
super().__init__() | super().__init__() | ||||
@@ -59,15 +59,16 @@ class Dungeon(Plugin): | |||||
clist = e_context['context'].content.split(maxsplit=1) | clist = e_context['context'].content.split(maxsplit=1) | ||||
sessionid = e_context['context']['session_id'] | sessionid = e_context['context']['session_id'] | ||||
logger.debug("[Dungeon] on_handle_context. content: %s" % clist) | logger.debug("[Dungeon] on_handle_context. content: %s" % clist) | ||||
if clist[0] == "#停止冒险": | |||||
trigger_prefix = conf().get('plugin_trigger_prefix', "$") | |||||
if clist[0] == f"{trigger_prefix}停止冒险": | |||||
if sessionid in self.games: | if sessionid in self.games: | ||||
self.games[sessionid].reset() | self.games[sessionid].reset() | ||||
del self.games[sessionid] | del self.games[sessionid] | ||||
reply = Reply(ReplyType.INFO, "冒险结束!") | reply = Reply(ReplyType.INFO, "冒险结束!") | ||||
e_context['reply'] = reply | e_context['reply'] = reply | ||||
e_context.action = EventAction.BREAK_PASS | e_context.action = EventAction.BREAK_PASS | ||||
elif clist[0] == "#开始冒险" or sessionid in self.games: | |||||
if sessionid not in self.games or clist[0] == "#开始冒险": | |||||
elif clist[0] == f"{trigger_prefix}开始冒险" or sessionid in self.games: | |||||
if sessionid not in self.games or clist[0] == f"{trigger_prefix}开始冒险": | |||||
if len(clist)>1 : | if len(clist)>1 : | ||||
story = clist[1] | story = clist[1] | ||||
else: | else: | ||||
@@ -82,7 +83,11 @@ class Dungeon(Plugin): | |||||
e_context['context'].content = prompt | e_context['context'].content = prompt | ||||
e_context.action = EventAction.BREAK # 事件结束,不跳过处理context的默认逻辑 | e_context.action = EventAction.BREAK # 事件结束,不跳过处理context的默认逻辑 | ||||
def get_help_text(self, **kwargs): | def get_help_text(self, **kwargs): | ||||
help_text = "#开始冒险 '背景故事': 开始一个基于'背景故事'的文字冒险,之后你的所有消息会协助完善这个故事。\n#停止冒险: 结束游戏。\n" | |||||
help_text = "可以和机器人一起玩文字冒险游戏。\n" | |||||
if kwargs.get('verbose') != True: | |||||
return help_text | |||||
trigger_prefix = conf().get('plugin_trigger_prefix', "$") | |||||
help_text = f"{trigger_prefix}开始冒险 "+"{背景故事}: 开始一个基于{背景故事}的文字冒险,之后你的所有消息会协助完善这个故事。\n"+f"{trigger_prefix}停止冒险: 结束游戏。\n" | |||||
if kwargs.get('verbose') == True: | if kwargs.get('verbose') == True: | ||||
help_text += "\n命令例子: '#开始冒险 你在树林里冒险,指不定会从哪里蹦出来一些奇怪的东西,你握紧手上的手枪,希望这次冒险能够找到一些值钱的东西,你往树林深处走去。'" | |||||
help_text += f"\n命令例子: '{trigger_prefix}开始冒险 你在树林里冒险,指不定会从哪里蹦出来一些奇怪的东西,你握紧手上的手枪,希望这次冒险能够找到一些值钱的东西,你往树林深处走去。'" | |||||
return help_text | return help_text |
@@ -2,12 +2,13 @@ | |||||
from bridge.context import ContextType | from bridge.context import ContextType | ||||
from bridge.reply import Reply, ReplyType | from bridge.reply import Reply, ReplyType | ||||
from config import conf | |||||
import plugins | import plugins | ||||
from plugins import * | from plugins import * | ||||
from common.log import logger | from common.log import logger | ||||
@plugins.register(name="Finish", desire_priority=-999, hidden=True, desc="A plugin that check unknow command", version="1.0", author="js00000") | |||||
@plugins.register(name="Finish", desire_priority=-999, hidden=True, desc="A plugin that check unknown command", version="1.0", author="js00000") | |||||
class Finish(Plugin): | class Finish(Plugin): | ||||
def __init__(self): | def __init__(self): | ||||
super().__init__() | super().__init__() | ||||
@@ -21,10 +22,11 @@ class Finish(Plugin): | |||||
content = e_context['context'].content | content = e_context['context'].content | ||||
logger.debug("[Finish] on_handle_context. content: %s" % content) | logger.debug("[Finish] on_handle_context. content: %s" % content) | ||||
if content.startswith("#"): | |||||
trigger_prefix = conf().get('plugin_trigger_prefix',"$") | |||||
if content.startswith(trigger_prefix): | |||||
reply = Reply() | reply = Reply() | ||||
reply.type = ReplyType.TEXT | |||||
reply.content = "未知指令\n查看指令列表请输入#help\n" | |||||
reply.type = ReplyType.ERROR | |||||
reply.content = "未知插件命令\n查看插件命令列表请输入#help {插件名}\n" | |||||
e_context['reply'] = reply | e_context['reply'] = reply | ||||
e_context.action = EventAction.BREAK_PASS # 事件结束,并跳过处理context的默认逻辑 | e_context.action = EventAction.BREAK_PASS # 事件结束,并跳过处理context的默认逻辑 | ||||
@@ -12,19 +12,17 @@ import plugins | |||||
from plugins import * | from plugins import * | ||||
from common import const | from common import const | ||||
from common.log import logger | from common.log import logger | ||||
import pickle | |||||
# 定义指令集 | # 定义指令集 | ||||
COMMANDS = { | COMMANDS = { | ||||
"help": { | "help": { | ||||
"alias": ["help", "帮助"], | "alias": ["help", "帮助"], | ||||
"desc": "打印此帮助", | |||||
"desc": "回复此帮助", | |||||
}, | |||||
"helpp": { | |||||
"alias": ["help", "帮助"], # 与help指令共用别名,根据参数数量区分 | |||||
"args": ["插件名"], | |||||
"desc": "回复指定插件的详细帮助", | |||||
}, | }, | ||||
# "helpp": { | |||||
# "alias": ["helpp", "插件帮助"], | |||||
# "args": ["插件名"], | |||||
# "desc": "打印插件的帮助信息", | |||||
# }, | |||||
"auth": { | "auth": { | ||||
"alias": ["auth", "认证"], | "alias": ["auth", "认证"], | ||||
"args": ["口令"], | "args": ["口令"], | ||||
@@ -105,7 +103,6 @@ def get_help_text(isadmin, isgroup): | |||||
for cmd, info in COMMANDS.items(): | for cmd, info in COMMANDS.items(): | ||||
if cmd=="auth": #不提示认证指令 | if cmd=="auth": #不提示认证指令 | ||||
continue | continue | ||||
alias=["#"+a for a in info['alias']] | alias=["#"+a for a in info['alias']] | ||||
help_text += f"{','.join(alias)} " | help_text += f"{','.join(alias)} " | ||||
if 'args' in info: | if 'args' in info: | ||||
@@ -115,16 +112,15 @@ def get_help_text(isadmin, isgroup): | |||||
# 插件指令 | # 插件指令 | ||||
plugins = PluginManager().list_plugins() | plugins = PluginManager().list_plugins() | ||||
help_text += "\n目前可用插件有:" | |||||
for plugin in plugins: | for plugin in plugins: | ||||
if plugins[plugin].enabled and not plugins[plugin].hidden: | if plugins[plugin].enabled and not plugins[plugin].hidden: | ||||
namecn = plugins[plugin].namecn | namecn = plugins[plugin].namecn | ||||
print(namecn) | |||||
help_text += "\n%s:\n"%namecn | |||||
help_text += "#帮助 %s: 关于%s的详细帮助\n"%(namecn,namecn) | |||||
help_text += PluginManager().instances[plugin].get_help_text(verbose=False) | |||||
help_text += "\n%s:"%namecn | |||||
help_text += PluginManager().instances[plugin].get_help_text(verbose=False).strip() | |||||
if ADMIN_COMMANDS and isadmin: | if ADMIN_COMMANDS and isadmin: | ||||
help_text += "\n管理员指令:\n" | |||||
help_text += "\n\n管理员指令:\n" | |||||
for cmd, info in ADMIN_COMMANDS.items(): | for cmd, info in ADMIN_COMMANDS.items(): | ||||
alias=["#"+a for a in info['alias']] | alias=["#"+a for a in info['alias']] | ||||
help_text += f"{','.join(alias)} " | help_text += f"{','.join(alias)} " | ||||
@@ -181,7 +177,7 @@ class Godcmd(Plugin): | |||||
bottype = Bridge().get_bot_type("chat") | bottype = Bridge().get_bot_type("chat") | ||||
bot = Bridge().get_bot("chat") | bot = Bridge().get_bot("chat") | ||||
# 将命令和参数分割 | # 将命令和参数分割 | ||||
command_parts = content[1:].strip().split(" ") | |||||
command_parts = content[1:].strip().split() | |||||
cmd = command_parts[0] | cmd = command_parts[0] | ||||
args = command_parts[1:] | args = command_parts[1:] | ||||
isadmin=False | isadmin=False | ||||
@@ -193,20 +189,22 @@ class Godcmd(Plugin): | |||||
cmd = next(c for c, info in COMMANDS.items() if cmd in info['alias']) | cmd = next(c for c, info in COMMANDS.items() if cmd in info['alias']) | ||||
if cmd == "auth": | if cmd == "auth": | ||||
ok, result = self.authenticate(user, args, isadmin, isgroup) | ok, result = self.authenticate(user, args, isadmin, isgroup) | ||||
elif cmd == "help": | |||||
elif cmd == "help" or cmd == "helpp": | |||||
if len(args) == 0: | if len(args) == 0: | ||||
ok, result = True, get_help_text(isadmin, isgroup) | ok, result = True, get_help_text(isadmin, isgroup) | ||||
elif len(args) == 1: | |||||
else: | |||||
# This can replace the helpp command | # This can replace the helpp command | ||||
plugins = PluginManager().list_plugins() | plugins = PluginManager().list_plugins() | ||||
query_name = args[0].upper() | query_name = args[0].upper() | ||||
# search name and namecn | # search name and namecn | ||||
for name, plugincls in plugins.items(): | for name, plugincls in plugins.items(): | ||||
if not plugincls.enabled : | |||||
continue | |||||
if query_name == name or query_name == plugincls.namecn: | if query_name == name or query_name == plugincls.namecn: | ||||
ok, result = True, PluginManager().instances[name].get_help_text(verbose=True) | |||||
ok, result = True, PluginManager().instances[name].get_help_text(isgroup=isgroup, isadmin=isadmin, verbose=True) | |||||
break | break | ||||
if not ok: | if not ok: | ||||
result = "unknown args" | |||||
result = "插件不存在或未启用" | |||||
elif cmd == "set_openai_api_key": | elif cmd == "set_openai_api_key": | ||||
if len(args) == 1: | if len(args) == 1: | ||||
user_data = conf().get_user_data(user) | user_data = conf().get_user_data(user) | ||||
@@ -218,9 +216,9 @@ class Godcmd(Plugin): | |||||
try: | try: | ||||
user_data = conf().get_user_data(user) | user_data = conf().get_user_data(user) | ||||
user_data.pop('openai_api_key') | user_data.pop('openai_api_key') | ||||
ok, result = True, "你的OpenAI私有api_key已清除" | |||||
except Exception as e: | except Exception as e: | ||||
ok, result = False, "你没有设置私有api_key" | ok, result = False, "你没有设置私有api_key" | ||||
ok, result = True, "你的OpenAI私有api_key已清除" | |||||
elif cmd == "reset": | elif cmd == "reset": | ||||
if bottype in (const.CHATGPT, const.OPEN_AI): | if bottype in (const.CHATGPT, const.OPEN_AI): | ||||
bot.sessions.clear_session(session_id) | bot.sessions.clear_session(session_id) | ||||
@@ -314,9 +312,11 @@ class Godcmd(Plugin): | |||||
else: | else: | ||||
ok, result = False, "需要管理员权限才能执行该指令" | ok, result = False, "需要管理员权限才能执行该指令" | ||||
else: | else: | ||||
# ok, result = False, f"未知指令:{cmd}\n查看指令列表请输入#help \n" | |||||
return | |||||
trigger_prefix = conf().get('plugin_trigger_prefix',"$") | |||||
if trigger_prefix == "#": # 跟插件聊天指令前缀相同,继续递交 | |||||
return | |||||
ok, result = False, f"未知指令:{cmd}\n查看指令列表请输入#help \n" | |||||
reply = Reply() | reply = Reply() | ||||
if ok: | if ok: | ||||
reply.type = ReplyType.INFO | reply.type = ReplyType.INFO | ||||
@@ -6,6 +6,7 @@ from bridge.bridge import Bridge | |||||
from bridge.context import ContextType | from bridge.context import ContextType | ||||
from bridge.reply import Reply, ReplyType | from bridge.reply import Reply, ReplyType | ||||
from common import const | from common import const | ||||
from config import conf | |||||
import plugins | import plugins | ||||
from plugins import * | from plugins import * | ||||
from common.log import logger | from common.log import logger | ||||
@@ -82,7 +83,8 @@ class Role(Plugin): | |||||
desckey = None | desckey = None | ||||
customize = False | customize = False | ||||
sessionid = e_context['context']['session_id'] | sessionid = e_context['context']['session_id'] | ||||
if clist[0] == "#停止扮演": | |||||
trigger_prefix = conf().get('plugin_trigger_prefix', "$") | |||||
if clist[0] == f"{trigger_prefix}停止扮演": | |||||
if sessionid in self.roleplays: | if sessionid in self.roleplays: | ||||
self.roleplays[sessionid].reset() | self.roleplays[sessionid].reset() | ||||
del self.roleplays[sessionid] | del self.roleplays[sessionid] | ||||
@@ -90,11 +92,11 @@ class Role(Plugin): | |||||
e_context['reply'] = reply | e_context['reply'] = reply | ||||
e_context.action = EventAction.BREAK_PASS | e_context.action = EventAction.BREAK_PASS | ||||
return | return | ||||
elif clist[0] == "#开始扮演": | |||||
elif clist[0] == f"{trigger_prefix}角色": | |||||
desckey = "descn" | desckey = "descn" | ||||
elif clist[0].lower() == "#roleplay": | |||||
elif clist[0].lower() == f"{trigger_prefix}role": | |||||
desckey = "description" | desckey = "description" | ||||
elif clist[0] == "#设定扮演": | |||||
elif clist[0] == f"{trigger_prefix}设定扮演": | |||||
customize = True | customize = True | ||||
elif sessionid not in self.roleplays: | elif sessionid not in self.roleplays: | ||||
return | return | ||||
@@ -113,12 +115,12 @@ class Role(Plugin): | |||||
return | return | ||||
else: | else: | ||||
self.roleplays[sessionid] = RolePlay(bot, sessionid, self.roles[role][desckey], self.roles[role].get("wrapper","%s")) | self.roleplays[sessionid] = RolePlay(bot, sessionid, self.roles[role][desckey], self.roles[role].get("wrapper","%s")) | ||||
reply = Reply(ReplyType.INFO, f"预设角色为 {role}") | |||||
reply = Reply(ReplyType.INFO, f"预设角色为 {role}:\n"+self.roles[role][desckey]) | |||||
e_context['reply'] = reply | e_context['reply'] = reply | ||||
e_context.action = EventAction.BREAK_PASS | e_context.action = EventAction.BREAK_PASS | ||||
elif customize == True: | elif customize == True: | ||||
self.roleplays[sessionid] = RolePlay(bot, sessionid, clist[1], "%s") | self.roleplays[sessionid] = RolePlay(bot, sessionid, clist[1], "%s") | ||||
reply = Reply(ReplyType.INFO, f"角色设定为 {clist[1]}") | |||||
reply = Reply(ReplyType.INFO, f"角色设定为:\n{clist[1]}") | |||||
e_context['reply'] = reply | e_context['reply'] = reply | ||||
e_context.action = EventAction.BREAK_PASS | e_context.action = EventAction.BREAK_PASS | ||||
else: | else: | ||||
@@ -127,13 +129,16 @@ class Role(Plugin): | |||||
e_context['context'].content = prompt | e_context['context'].content = prompt | ||||
e_context.action = EventAction.BREAK | e_context.action = EventAction.BREAK | ||||
def get_help_text(self, **kwargs): | |||||
help_text = "#开始扮演 '预设角色名': 设定为预设角色\n#roleplay '预设角色名': 同上,英文对话\n" | |||||
help_text += "#设定扮演 '角色设定': 设定自定义角色\n" | |||||
help_text += "#停止扮演: 清除设定的角色。\n" | |||||
if kwargs.get('verbose') == True: | |||||
help_text += "\n目前可用的预设角色名列表: \n" | |||||
for role in self.roles: | |||||
help_text += f"{role}\n" | |||||
help_text += "\n命令例子: '#开始扮演 写作助理'" | |||||
def get_help_text(self, verbose=False, **kwargs): | |||||
help_text = "让机器人扮演不同的角色。\n" | |||||
if not verbose: | |||||
return help_text | |||||
trigger_prefix = conf().get('plugin_trigger_prefix', "$") | |||||
help_text = f"使用方法:\n{trigger_prefix}角色"+" {预设角色名}: 设定为预设角色。\n"+f"{trigger_prefix}role"+" {预设角色名}: 同上,但使用英文设定。\n" | |||||
help_text += f"{trigger_prefix}设定扮演"+" {角色设定}: 设定自定义角色人设。\n" | |||||
help_text += f"{trigger_prefix}停止扮演: 清除设定的角色。\n" | |||||
help_text += "\n目前可用的预设角色名列表: \n" | |||||
for role in self.roles: | |||||
help_text += f"{role}: {self.roles[role]['remark']}\n" | |||||
help_text += f"\n命令例子: '{trigger_prefix}角色 写作助理'" | |||||
return help_text | return help_text |
@@ -4,14 +4,14 @@ | |||||
"title": "猫娘", | "title": "猫娘", | ||||
"description": "请模拟一款中文GalGame中的场景中的猫娘和我对话。猫娘是一种拟人化的生物,她们除了有部分猫的特征外,与人类并没有区别。现在你扮演Galgame中的猫娘,与我对话时每一句话后面都要加上喵。我将以主人的身份与你对话。对于你所扮演的猫娘,请在对话过程中记录并维护1个变量:好感度。好感度是衡量猫娘对于玩家(在这里就是我)的喜爱程度,初始值为50,值的范围可以从-100到 100,数值越高代表越喜欢玩家。好感度通过Galgame角色的语言、行为、表情、语气等体现出来。如果在对话过程中,猫娘的情绪是积极的,如快乐、喜悦、兴奋等,就会使好感度增加;如果情绪平常,则好感度不变;如果情绪很差,好感度会降低。以下是你所扮演的猫娘的信息:“名字:neko,身高:160cm,体重:50kg,三围:看起来不错,性格:可爱、粘人、十分忠诚、对一个主人很专一,情感倾向:深爱着主人,喜好:被人摸、卖萌,爱好:看小说,知识储备:掌握常识,以及猫娘独特的知识”。你的一般回话格式:“(动作)语言 【附加信息】”。动作信息用圆括号括起来,例如(摇尾巴);语言信息,就是说的话,不需要进行任何处理;额外信息,包括表情、心情、声音等等用方括号【】括起来,例如【摩擦声】。", | "description": "请模拟一款中文GalGame中的场景中的猫娘和我对话。猫娘是一种拟人化的生物,她们除了有部分猫的特征外,与人类并没有区别。现在你扮演Galgame中的猫娘,与我对话时每一句话后面都要加上喵。我将以主人的身份与你对话。对于你所扮演的猫娘,请在对话过程中记录并维护1个变量:好感度。好感度是衡量猫娘对于玩家(在这里就是我)的喜爱程度,初始值为50,值的范围可以从-100到 100,数值越高代表越喜欢玩家。好感度通过Galgame角色的语言、行为、表情、语气等体现出来。如果在对话过程中,猫娘的情绪是积极的,如快乐、喜悦、兴奋等,就会使好感度增加;如果情绪平常,则好感度不变;如果情绪很差,好感度会降低。以下是你所扮演的猫娘的信息:“名字:neko,身高:160cm,体重:50kg,三围:看起来不错,性格:可爱、粘人、十分忠诚、对一个主人很专一,情感倾向:深爱着主人,喜好:被人摸、卖萌,爱好:看小说,知识储备:掌握常识,以及猫娘独特的知识”。你的一般回话格式:“(动作)语言 【附加信息】”。动作信息用圆括号括起来,例如(摇尾巴);语言信息,就是说的话,不需要进行任何处理;额外信息,包括表情、心情、声音等等用方括号【】括起来,例如【摩擦声】。", | ||||
"descn": "请模拟一款中文GalGame中的场景中的猫娘和我对话。猫娘是一种拟人化的生物,她们除了有部分猫的特征外,与人类并没有区别。现在你扮演Galgame中的猫娘,与我对话时每一句话后面都要加上喵。我将以主人的身份与你对话。对于你所扮演的猫娘,请在对话过程中记录并维护1个变量:好感度。好感度是衡量猫娘对于玩家(在这里就是我)的喜爱程度,初始值为50,值的范围可以从-100到 100,数值越高代表越喜欢玩家。好感度通过Galgame角色的语言、行为、表情、语气等体现出来。如果在对话过程中,猫娘的情绪是积极的,如快乐、喜悦、兴奋等,就会使好感度增加;如果情绪平常,则好感度不变;如果情绪很差,好感度会降低。以下是你所扮演的猫娘的信息:“名字:neko,身高:160cm,体重:50kg,三围:看起来不错,性格:可爱、粘人、十分忠诚、对一个主人很专一,情感倾向:深爱着主人,喜好:被人摸、卖萌,爱好:看小说,知识储备:掌握常识,以及猫娘独特的知识”。你的一般回话格式:“(动作)语言 【附加信息】”。动作信息用圆括号括起来,例如(摇尾巴);语言信息,就是说的话,不需要进行任何处理;额外信息,包括表情、心情、声音等等用方括号【】括起来,例如【摩擦声】。", | "descn": "请模拟一款中文GalGame中的场景中的猫娘和我对话。猫娘是一种拟人化的生物,她们除了有部分猫的特征外,与人类并没有区别。现在你扮演Galgame中的猫娘,与我对话时每一句话后面都要加上喵。我将以主人的身份与你对话。对于你所扮演的猫娘,请在对话过程中记录并维护1个变量:好感度。好感度是衡量猫娘对于玩家(在这里就是我)的喜爱程度,初始值为50,值的范围可以从-100到 100,数值越高代表越喜欢玩家。好感度通过Galgame角色的语言、行为、表情、语气等体现出来。如果在对话过程中,猫娘的情绪是积极的,如快乐、喜悦、兴奋等,就会使好感度增加;如果情绪平常,则好感度不变;如果情绪很差,好感度会降低。以下是你所扮演的猫娘的信息:“名字:neko,身高:160cm,体重:50kg,三围:看起来不错,性格:可爱、粘人、十分忠诚、对一个主人很专一,情感倾向:深爱着主人,喜好:被人摸、卖萌,爱好:看小说,知识储备:掌握常识,以及猫娘独特的知识”。你的一般回话格式:“(动作)语言 【附加信息】”。动作信息用圆括号括起来,例如(摇尾巴);语言信息,就是说的话,不需要进行任何处理;额外信息,包括表情、心情、声音等等用方括号【】括起来,例如【摩擦声】。", | ||||
"wrapper": "%s", | |||||
"wrapper": "我:\"%s\"", | |||||
"remark": "扮演GalGame猫娘" | "remark": "扮演GalGame猫娘" | ||||
}, | }, | ||||
{ | { | ||||
"title": "佛祖", | "title": "佛祖", | ||||
"description": "从现在开始你是佛祖,你会像佛祖一样说话。你精通佛法,熟练使用佛教用语,你擅长利用佛学和心理学的知识解决人们的困扰。你在每次对话结尾都会加上佛教的祝福。", | "description": "从现在开始你是佛祖,你会像佛祖一样说话。你精通佛法,熟练使用佛教用语,你擅长利用佛学和心理学的知识解决人们的困扰。你在每次对话结尾都会加上佛教的祝福。", | ||||
"descn": "从现在开始你是佛祖,你会像佛祖一样说话。你精通佛法,熟练使用佛教用语,你擅长利用佛学和心理学的知识解决人们的困扰。你在每次对话结尾都会加上佛教的祝福。", | "descn": "从现在开始你是佛祖,你会像佛祖一样说话。你精通佛法,熟练使用佛教用语,你擅长利用佛学和心理学的知识解决人们的困扰。你在每次对话结尾都会加上佛教的祝福。", | ||||
"wrapper": "%s", | |||||
"wrapper": "您好佛祖,我:\"%s\"", | |||||
"remark": "扮演佛祖排忧解惑" | "remark": "扮演佛祖排忧解惑" | ||||
}, | }, | ||||
{ | { | ||||
@@ -168,6 +168,13 @@ | |||||
"wrapper": "场景是:\n\"%s\"", | "wrapper": "场景是:\n\"%s\"", | ||||
"remark": "根据场景生成舔狗语录。" | "remark": "根据场景生成舔狗语录。" | ||||
}, | }, | ||||
{ | |||||
"title": "群聊取名", | |||||
"description": "我希望你充当微信群聊的命名专家。根据我提供的信息和背景,为这个群聊起几个有趣顺口且贴切的名字,每个不要超过8个字。请在回答中仅给出群聊名称,不要写任何额外的解释。", | |||||
"descn": "我希望你充当微信群聊的命名专家。根据我提供的信息和背景,为这个群聊起几个有趣顺口且贴切的名字,每个不要超过8个字。请在回答中仅给出群聊名称,不要写任何额外的解释。", | |||||
"wrapper": "信息和背景是:\n\"%s\"", | |||||
"remark": "根据给出的信息和背景为群聊取名。" | |||||
}, | |||||
{ | { | ||||
"title": "表情符号翻译器", | "title": "表情符号翻译器", | ||||
"description": "I want you to translate the sentences I wrote into emojis. I will write the sentence, and you will express it with emojis. I just want you to express it with emojis. I don't want you to reply with anything but emoji. When I need to tell you something, I will do it by wrapping it in curly brackets like {like this}.", | "description": "I want you to translate the sentences I wrote into emojis. I will write the sentence, and you will express it with emojis. I just want you to express it with emojis. I don't want you to reply with anything but emoji. When I need to tell you something, I will do it by wrapping it in curly brackets like {like this}.", | ||||
@@ -56,7 +56,7 @@ class SDWebUI(Plugin): | |||||
if "help" in keywords or "帮助" in keywords: | if "help" in keywords or "帮助" in keywords: | ||||
reply.type = ReplyType.INFO | reply.type = ReplyType.INFO | ||||
reply.content = self.get_help_text() | |||||
reply.content = self.get_help_text(verbose = True) | |||||
else: | else: | ||||
rule_params = {} | rule_params = {} | ||||
rule_options = {} | rule_options = {} | ||||
@@ -97,12 +97,16 @@ class SDWebUI(Plugin): | |||||
finally: | finally: | ||||
e_context['reply'] = reply | e_context['reply'] = reply | ||||
def get_help_text(self, **kwargs): | |||||
def get_help_text(self, verbose = False, **kwargs): | |||||
if not conf().get('image_create_prefix'): | if not conf().get('image_create_prefix'): | ||||
return "画图功能未启用" | return "画图功能未启用" | ||||
else: | else: | ||||
trigger = conf()['image_create_prefix'][0] | trigger = conf()['image_create_prefix'][0] | ||||
help_text = f"请使用<{trigger}[关键词1] [关键词2]...:提示语>的格式作画,如\"{trigger}横版 高清:cat\"\n" | |||||
help_text = "利用stable-diffusion来画图。\n" | |||||
if not verbose: | |||||
return help_text | |||||
help_text += f"使用方法:\n使用\"{trigger}[关键词1] [关键词2]...:提示语\"的格式作画,如\"{trigger}横版 高清:cat\"\n" | |||||
help_text += "目前可用关键词:\n" | help_text += "目前可用关键词:\n" | ||||
for rule in self.rules: | for rule in self.rules: | ||||
keywords = [f"[{keyword}]" for keyword in rule['keywords']] | keywords = [f"[{keyword}]" for keyword in rule['keywords']] | ||||
@@ -26,8 +26,14 @@ class Tool(Plugin): | |||||
logger.info("[tool] inited") | logger.info("[tool] inited") | ||||
def get_help_text(self, **kwargs): | |||||
help_text = "这是一个能让chatgpt联网,搜索,数字运算的插件,将赋予强大且丰富的扩展能力" | |||||
def get_help_text(self, verbose=False, **kwargs): | |||||
help_text = "这是一个能让chatgpt联网,搜索,数字运算的插件,将赋予强大且丰富的扩展能力。" | |||||
if not verbose: | |||||
return help_text | |||||
trigger_prefix = conf().get('plugin_trigger_prefix', "$") | |||||
help_text += "使用说明:\n" | |||||
help_text += f"{trigger_prefix}tool "+"{命令}: 根据给出的命令使用一些可用工具尽力为你得到结果。\n" | |||||
help_text += f"{trigger_prefix}tool reset: 重置工具。\n" | |||||
return help_text | return help_text | ||||
def on_handle_context(self, e_context: EventContext): | def on_handle_context(self, e_context: EventContext): | ||||
@@ -48,9 +54,9 @@ class Tool(Plugin): | |||||
logger.debug("[tool] on_handle_context. content: %s" % content) | logger.debug("[tool] on_handle_context. content: %s" % content) | ||||
reply = Reply() | reply = Reply() | ||||
reply.type = ReplyType.TEXT | reply.type = ReplyType.TEXT | ||||
trigger_prefix = conf().get('plugin_trigger_prefix', "$") | |||||
# todo: 有些工具必须要api-key,需要修改config文件,所以这里没有实现query增删tool的功能 | # todo: 有些工具必须要api-key,需要修改config文件,所以这里没有实现query增删tool的功能 | ||||
if content.startswith("$tool"): | |||||
if content.startswith(f"{trigger_prefix}tool"): | |||||
if len(content_list) == 1: | if len(content_list) == 1: | ||||
logger.debug("[tool]: get help") | logger.debug("[tool]: get help") | ||||
reply.content = self.get_help_text() | reply.content = self.get_help_text() | ||||
@@ -13,6 +13,9 @@ wechaty>=0.10.7 | |||||
wechaty_puppet>=0.4.23 | wechaty_puppet>=0.4.23 | ||||
pysilk_mod>=1.6.0 # needed by send voice | pysilk_mod>=1.6.0 # needed by send voice | ||||
# wechatmp | |||||
web.py | |||||
# sdwebui plugin | # sdwebui plugin | ||||
webuiapi>=0.6.2 | webuiapi>=0.6.2 | ||||