fix: 修复一些指令的bug

This commit is contained in:
Soulter
2024-07-25 10:44:17 -04:00
parent c57f711c48
commit 618f8aa7d2
8 changed files with 85 additions and 32 deletions

View File

@@ -19,7 +19,7 @@ class InternalCommandHandler:
self.plugin_manager = plugin_manager
self.manager.register("help", "查看帮助", 10, self.help)
self.manager.register("nick", "设置机器人昵称", 10, self.set_nick)
self.manager.register("wake", "设置机器人唤醒词", 10, self.set_nick)
self.manager.register("update", "更新 AstrBot", 10, self.update)
self.manager.register("plugin", "插件管理", 10, self.plugin)
self.manager.register("reboot", "重启 AstrBot", 10, self.reboot)
@@ -33,14 +33,14 @@ class InternalCommandHandler:
return CommandResult().message("你没有权限使用该指令。")
l = message_str.split(" ")
if len(l) == 1:
return CommandResult().message("设置机器人昵称】示例:\n支持多昵称\nnick 昵称1 昵称2 昵称3")
return CommandResult().message("设置机器人唤醒词,支持多唤醒词。以唤醒词开头的消息会唤醒机器人处理,起到 @ 的效果。\n示例wake 昵称1 昵称2 昵称3")
nick = l[1:]
context.config_helper.put("nick_qq", nick)
context.nick = tuple(nick)
return CommandResult(
hit=True,
success=True,
message_chain=f"已经成功将昵称设定为 {nick}",
message_chain=f"已经成功将唤醒词设定为 {nick}",
)
def update(self, message: AstrMessageEvent, context: Context):
@@ -51,13 +51,13 @@ class InternalCommandHandler:
success=False,
message_chain="你没有权限使用该指令",
)
update_info = context.updator.check_update(None, None)
if tokens.len == 1:
update_info = context.updator.check_update(None, None)
ret = ""
if not update_info:
ret = f"当前已经是最新版本 v{VERSION}"
else:
ret = f"发现新版本 v{update_info['version']}\n- 使用 /update latest 更新到最新版本。\n- 使用 /update vX.X.X 更新到指定版本。"
ret = f"发现新版本 {update_info.version},更新内容如下:\n---\n{update_info.body}\n---\n- 使用 /update latest 更新到最新版本。\n- 使用 /update vX.X.X 更新到指定版本。"
return CommandResult(
hit=True,
success=False,
@@ -67,7 +67,7 @@ class InternalCommandHandler:
if tokens.get(1) == "latest":
try:
context.updator.update()
return CommandResult().message(f"已经成功更新到最新版本 v{update_info['version']}。要应用更新,请重启 AstrBot。输入 /reboot 即可重启")
return CommandResult().message(f"已经成功更新到最新版本 v{update_info.version}。要应用更新,请重启 AstrBot。输入 /reboot 即可重启")
except BaseException as e:
return CommandResult().message(f"更新失败。原因:{str(e)}")
elif tokens.get(1).startswith("v"):
@@ -157,13 +157,13 @@ class InternalCommandHandler:
msg = "# Help Center\n## 指令列表\n"
for key, value in self.manager.commands_handler.items():
if value.plugin_metadata:
msg += f"`{key}` ({value.plugin_metadata.plugin_name}) - {value.description}\n"
else: msg += f"`{key}` - {value.description}\n"
msg += f"- `{key}` ({value.plugin_metadata.plugin_name}): {value.description}\n"
else: msg += f"- `{key}`: {value.description}\n"
# plugins
if context.cached_plugins != None:
plugin_list_info = ""
for plugin in context.cached_plugins:
plugin_list_info += f"`{plugin.metadata.plugin_name}` {plugin.metadata.desc}\n"
plugin_list_info += f"- `{plugin.metadata.plugin_name}` {plugin.metadata.desc}\n"
if plugin_list_info.strip() != "":
msg += "\n## 插件列表\n> 使用plugin v 插件名 查看插件帮助\n"
msg += plugin_list_info

View File

@@ -25,6 +25,7 @@ class OpenAIOfficialCommandHandler():
self.manager.register("unset", "清除个性化人格设置", 10, self.unset)
self.manager.register("set", "设置个性化人格", 10, self.set)
self.manager.register("draw", "调用 DallE 模型画图", 10, self.draw)
self.manager.register("model", "切换模型", 10, self.model)
self.manager.register("", "调用 DallE 模型画图", 10, self.draw)
def set_provider(self, provider):
@@ -37,6 +38,41 @@ class OpenAIOfficialCommandHandler():
return CommandResult().message("重置成功")
elif tokens.get(1) == 'p':
await self.provider.forget(message.session_id)
async def model(self, message: AstrMessageEvent, context: Context):
tokens = self.manager.command_parser.parse(message.message_str)
if tokens.len == 1:
ret = await self._print_models()
return CommandResult().message(ret)
model = tokens.get(1)
if model.isdigit():
try:
models = await self.provider.get_models()
except BaseException as e:
logger.error(f"获取模型列表失败: {str(e)}")
return CommandResult().message("获取模型列表失败,无法使用编号切换模型。可以尝试直接输入模型名来切换,如 gpt-4o。")
models = list(models)
if int(model) <= len(models) and int(model) >= 1:
model = models[int(model)-1]
self.provider.set_model(model.id)
return CommandResult().message(f"模型已设置为 {model.id}")
else:
self.provider.set_model(model)
return CommandResult().message(f"模型已设置为 {model} (自定义)")
async def _print_models(self):
try:
models = await self.provider.get_models()
except BaseException as e:
return "获取模型列表失败: " + str(e)
i = 1
ret = "OpenAI GPT 类可用模型"
for model in models:
ret += f"\n{i}. {model.id}"
i += 1
ret += "\nTips: 使用 /model 模型名/编号,即可实时更换模型。如目标模型不存在于上表,请输入模型名。"
logger.debug(ret)
return ret
def his(self, message: AstrMessageEvent, context: Context):
tokens = self.manager.command_parser.parse(message.message_str)
@@ -108,12 +144,12 @@ class OpenAIOfficialCommandHandler():
def set(self, message: AstrMessageEvent, context: Context):
l = message.message_str.split(" ")
if len(l) == 1:
return CommandResult().message("【人格文本由PlexPt开源项目awesome-chatgpt-prompts-zh提供】\n设置人格: \n/set 人格名。例如/set 编剧\n人格列表: /set list\n人格详细信息: /set view 人格名\n自定义人格: /set 人格文本\n重置会话(清除人格): /reset\n重置会话(保留人格): /reset p\n【当前人格】: " + str(self.provider.curr_personality))
return CommandResult().message("- 设置人格: \nset 人格名。例如 set 编剧\n- 人格列表: set list\n- 人格详细信息: set view 人格名\n- 自定义人格: set 人格文本\n- 重置会话(清除人格): reset\n- 重置会话(保留人格): reset p\n\n【当前人格】: " + str(self.provider.curr_personality['prompt']))
elif l[1] == "list":
msg = "人格列表:\n"
for key in personalities.keys():
msg += f" |-{key}\n"
msg += '\n\n*输入/set view 人格名查看人格详细信息'
msg += f"- {key}\n"
msg += '\n\n*输入 set view 人格名 查看人格详细信息'
return CommandResult().message(msg)
elif l[1] == "view":
if len(l) == 2:
@@ -126,20 +162,20 @@ class OpenAIOfficialCommandHandler():
msg = f"人格{ps}不存在"
return CommandResult().message(msg)
else:
ps = l[1].strip()
ps = "".join(l[1:]).strip()
if ps in personalities:
self.provider.curr_personality = {
'name': ps,
'prompt': personalities[ps]
}
self.provider.personality_set(ps, message.session_id)
self.provider.personality_set(self.provider.curr_personality, message.session_id)
return CommandResult().message(f"人格已设置。 \n人格信息: {ps}")
else:
self.provider.curr_personality = {
'name': '自定义人格',
'prompt': ps
}
self.provider.personality_set(ps, message.session_id)
self.provider.personality_set(self.provider.curr_personality, message.session_id)
return CommandResult().message(f"人格已设置。 \n人格信息: {ps}")
async def draw(self, message: AstrMessageEvent, context: Context):

View File

@@ -9,7 +9,7 @@ import botpy.types.message
from botpy.types.message import Reference, Media
from botpy import Client
from util.io import save_temp_img
from util.io import save_temp_img, download_image_by_url
from . import Platform
from type.astrbot_message import *
from type.message_event import *
@@ -80,7 +80,7 @@ class QQOfficial(Platform):
self.client.set_platform(self)
def _parse_to_qqofficial(self, message: List[BaseMessageComponent]):
async def _parse_to_qqofficial(self, message: List[BaseMessageComponent], is_group: bool = False):
plain_text = ""
image_path = None # only one img supported
for i in message:
@@ -92,8 +92,9 @@ class QQOfficial(Platform):
elif i.file and i.file.startswith("base64://"):
img_data = base64.b64decode(i.file[9:])
image_path = save_temp_img(img_data)
else:
image_path = save_temp_img(i.file)
elif i.file and i.file.startswith("http"):
# 如果是群消息,不需要下载
image_path = await download_image_by_url(i.file) if not is_group else i.file
return plain_text, image_path
def _parse_from_qqofficial(self, message: Union[botpy.message.Message, botpy.message.GroupMessage],
@@ -237,7 +238,7 @@ class QQOfficial(Platform):
rendered_images = await self.convert_to_t2i_chain(result_message)
if isinstance(result_message, list):
plain_text, image_path = self._parse_to_qqofficial(result_message)
plain_text, image_path = await self._parse_to_qqofficial(result_message, message.type == MessageType.GROUP_MESSAGE)
else:
plain_text = result_message
@@ -319,17 +320,23 @@ class QQOfficial(Platform):
media = await self.client.api.post_group_file(kwargs['group_openid'], 1, image_url)
del kwargs['file_image']
kwargs['media'] = media
logger.debug(f"发送群图片: {media}")
kwargs['msg_type'] = 7 # 富媒体
await self.client.api.post_group_message(**kwargs)
elif 'channel_id' in kwargs:
# 频道消息
if 'file_image' in kwargs:
kwargs['file_image'] = kwargs['file_image'].replace("file:///", "")
# 频道消息发图只支持本地
if kwargs['file_image'].startswith("http"):
kwargs['file_image'] = await download_image_by_url(kwargs['file_image'])
await self.client.api.post_message(**kwargs)
else:
# 频道私聊消息
if 'file_image' in kwargs:
kwargs['file_image'] = kwargs['file_image'].replace("file:///", "")
if kwargs['file_image'].startswith("http"):
kwargs['file_image'] = await download_image_by_url(kwargs['file_image'])
await self.client.api.post_dms(**kwargs)
async def send_msg(self, target: Dict[str, str], result_message: Union[List[BaseMessageComponent], str]):
@@ -343,7 +350,7 @@ class QQOfficial(Platform):
- 如果目标是 频道私聊,请添加 key `guild_id`。
'''
if isinstance(result_message, list):
plain_text, image_path = self._parse_to_qqofficial(result_message)
plain_text, image_path = await self._parse_to_qqofficial(result_message)
else:
plain_text = result_message

View File

@@ -188,12 +188,14 @@ class ProviderOpenAIOfficial(Provider):
return self.model_configs['model'].startswith("gpt-4")
async def get_models(self):
'''
获取所有模型
'''
models = await self.client.models.list()
logger.info(f"OpenAI 模型列表:{models}")
return models
try:
models = await self.client.models.list()
except NotFoundError as e:
bu = str(self.client.base_url)
self.client.base_url = bu + "/v1"
models = await self.client.models.list()
finally:
return filter(lambda x: x.id.startswith("gpt"), models.data)
async def assemble_context(self, session_id: str, prompt: str, image_url: str = None):
'''
@@ -376,7 +378,8 @@ class ProviderOpenAIOfficial(Provider):
if "maximum context length" in str(e):
logger.warn(f"OpenAI 请求失败:{e}。上下文长度超过限制。尝试弹出最早的记录然后重试。")
self.pop_record(session_id)
logger.warning(traceback.format_exc())
logger.warning(f"OpenAI 请求失败:{e}。重试第 {retry} 次。")
time.sleep(1)

View File

@@ -11,7 +11,7 @@ def init_configs():
cc.init_attributes("qq_forward_threshold", 200)
cc.init_attributes("qq_welcome", "")
cc.init_attributes("qq_pic_mode", False)
cc.init_attributes("qq_pic_mode", True)
cc.init_attributes("gocq_host", "127.0.0.1")
cc.init_attributes("gocq_http_port", 5700)
cc.init_attributes("gocq_websocket_port", 6700)
@@ -104,6 +104,6 @@ def inject_to_context(context: Context):
if isinstance(nick_qq, list):
nick_qq = tuple(nick_qq)
context.nick = nick_qq
context.t2i_mode = cc.get("qq_pic_mode", False)
context.t2i_mode = cc.get("qq_pic_mode", True)
return cfg

View File

@@ -17,7 +17,7 @@ class LocalRenderStrategy(RenderStrategy):
except Exception as e:
pass
async def render(self, text: str, **kwargs):
async def render(self, text: str, return_url: bool=False) -> str:
font_size = 26
image_width = 800
image_height = 600

View File

@@ -30,7 +30,9 @@ class NetworkRenderStrategy(RenderStrategy):
"version": f"v{VERSION}",
},
"options": {
"full_page": True
"full_page": True,
"type": "jpeg",
"quality": 25,
}
}

View File

@@ -10,6 +10,11 @@ class ReleaseInfo():
published_at: str
body: str
def __init__(self, version: str = '', published_at: str = '', body: str = '') -> None:
self.version = version
self.published_at = published_at
self.body = body
def __str__(self) -> str:
return f"新版本: {self.version}, 发布于: {self.published_at}, 详细内容: {self.body}"