Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a4f47da35c | |||
| 29364000e2 | |||
| ceecca44a4 | |||
| 50f62e66b0 | |||
| ab39dfd254 | |||
| 708fad18b6 | |||
| 526ba34d87 | |||
| 5d4882dee9 | |||
| 48c4361d37 |
+1
-1
@@ -1,7 +1,7 @@
|
||||
__pycache__
|
||||
botpy.log
|
||||
.vscode
|
||||
data.db
|
||||
data_v2.db
|
||||
configs/session
|
||||
configs/config.yaml
|
||||
**/.DS_Store
|
||||
|
||||
@@ -110,6 +110,7 @@ class MessageHandler():
|
||||
self.rate_limit_helper = RateLimitHelper(context)
|
||||
self.content_safety_helper = ContentSafetyHelper(context)
|
||||
self.llm_wake_prefix = self.context.config_helper.llm_settings.wake_prefix
|
||||
self.llm_identifier = self.context.config_helper.llm_settings.identifier
|
||||
if self.llm_wake_prefix:
|
||||
self.llm_wake_prefix = self.llm_wake_prefix.strip()
|
||||
self.provider = self.context.llms[0].llm_instance if len(self.context.llms) > 0 else None
|
||||
@@ -235,6 +236,13 @@ class MessageHandler():
|
||||
else:
|
||||
# normal chat
|
||||
tool_use_flag = False
|
||||
# add user info to the prompt
|
||||
if self.llm_identifier:
|
||||
user_id = message.message_obj.sender.user_id
|
||||
user_nickname = message.message_obj.sender.nickname
|
||||
user_info = f"[User ID: {user_id}, Nickname: {user_nickname}]\n"
|
||||
msg_plain = user_info + msg_plain
|
||||
|
||||
llm_result = await provider.text_chat(
|
||||
prompt=msg_plain,
|
||||
session_id=message.session_id,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import{q as e,o as a,c as t,w as o,d as s,x as n,U as r,X as c}from"./index-b50bcc8e.js";const f=e({__name:"BlankLayout",setup(p){return(u,_)=>(a(),t(r,null,{default:o(()=>[s(n(c))]),_:1}))}});export{f as default};
|
||||
@@ -1 +0,0 @@
|
||||
import{q as e,o as a,b as t,w as o,c as s,x as n,X as r,Z as c}from"./index-7e5a38e4.js";const f=e({__name:"BlankLayout",setup(p){return(u,_)=>(a(),t(r,null,{default:o(()=>[s(n(c))]),_:1}))}});export{f as default};
|
||||
@@ -1 +0,0 @@
|
||||
import{q as C,o as l,b as n,w as t,c as o,a0 as k,u as i,H as x,a as U,t as m,a1 as v,A as f,I as w,G as N,l as s,n as _,Q as S,R as B,F as r,a4 as D,M as y,a5 as T,e as $,m as F,g as b}from"./index-7e5a38e4.js";const A={class:"d-sm-flex align-center justify-space-between"},I=C({__name:"UiParentCard",props:{title:String},setup(d){const c=d;return(p,u)=>(l(),n(N,{variant:"outlined",elevation:"0",class:"withbg"},{default:t(()=>[o(k,null,{default:t(()=>[i("div",A,[o(x,null,{default:t(()=>[U(m(c.title),1)]),_:1}),v(p.$slots,"action")])]),_:3}),o(f),o(w,null,{default:t(()=>[v(p.$slots,"default")]),_:3})]),_:3}))}}),q={__name:"ConfigDetailCard",props:{config:Array},setup(d){return(c,p)=>(l(!0),s(r,null,_(d.config,u=>(l(),n(I,{key:u.name,title:u.name,style:{"margin-bottom":"16px"}},{default:t(()=>[S(i("a",null,"No data",512),[[B,d.config.length===0]]),(l(!0),s(r,null,_(u.body,e=>(l(),s(r,null,[e.config_type==="item"?(l(),s(r,{key:0},[e.val_type==="bool"?(l(),n(D,{key:0,modelValue:e.value,"onUpdate:modelValue":a=>e.value=a,label:e.name,hint:e.description,color:"primary",inset:""},null,8,["modelValue","onUpdate:modelValue","label","hint"])):e.val_type==="str"?(l(),n(y,{key:1,modelValue:e.value,"onUpdate:modelValue":a=>e.value=a,label:e.name,hint:e.description,style:{"margin-bottom":"8px"},variant:"outlined"},null,8,["modelValue","onUpdate:modelValue","label","hint"])):e.val_type==="int"?(l(),n(y,{key:2,modelValue:e.value,"onUpdate:modelValue":a=>e.value=a,label:e.name,hint:e.description,style:{"margin-bottom":"8px"},variant:"outlined"},null,8,["modelValue","onUpdate:modelValue","label","hint"])):e.val_type==="list"?(l(),s(r,{key:3},[i("span",null,m(e.name),1),o(T,{modelValue:e.value,"onUpdate:modelValue":a=>e.value=a,chips:"",clearable:"",label:"请添加",multiple:"","prepend-icon":"mdi-tag-multiple-outline"},{selection:t(({attrs:a,item:V,select:g,selected:h})=>[o($,F(a,{"model-value":h,closable:"",onClick:g,"onClick:close":P=>c.remove(V)}),{default:t(()=>[i("strong",null,m(V),1)]),_:2},1040,["model-value","onClick","onClick:close"])]),_:2},1032,["modelValue","onUpdate:modelValue"])],64)):b("",!0)],64)):e.config_type==="divider"?(l(),n(f,{key:1,style:{"margin-top":"8px","margin-bottom":"8px"}})):b("",!0)],64))),256))]),_:2},1032,["title"]))),128))}};export{q as _};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
-2
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+2
-2
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{aj as L,q as $,B as J,o as q,l as X,c as G,w as Q,Q as R,R as O,x as S,u as m,ak as Z,al as t0,am as r0,an as e0}from"./index-7e5a38e4.js";const E={Sidebar_drawer:!0,Customizer_drawer:!1,mini_sidebar:!1,fontTheme:"Roboto",inputBg:!1},i0=L({id:"customizer",state:()=>({Sidebar_drawer:E.Sidebar_drawer,Customizer_drawer:E.Customizer_drawer,mini_sidebar:E.mini_sidebar,fontTheme:"Poppins",inputBg:E.inputBg}),getters:{},actions:{SET_SIDEBAR_DRAWER(){this.Sidebar_drawer=!this.Sidebar_drawer},SET_MINI_SIDEBAR(p){this.mini_sidebar=p},SET_FONT(p){this.fontTheme=p}}}),s0={class:"logo",style:{display:"flex","align-items":"center"}},a0={style:{"font-size":"24px","font-weight":"1000"}},f0={style:{"font-size":"20px","font-weight":"1000"}},o0={style:{"font-size":"20px"}},l0=$({__name:"LogoDark",setup(p){J("rgb(var(--v-theme-primary))"),J("rgb(var(--v-theme-secondary))");const d=i0();return(M,y)=>(q(),X("div",s0,[G(S(Z),{to:"/",style:{"text-decoration":"none",color:"black"}},{default:Q(()=>[R(m("span",a0,"AstrBot 仪表盘",512),[[O,!S(d).mini_sidebar]]),R(m("span",f0,"Astr",512),[[O,S(d).mini_sidebar]]),R(m("span",o0,"Bot",512),[[O,S(d).mini_sidebar]])]),_:1})]))}});var P={exports:{}};const n0={},h0=Object.freeze(Object.defineProperty({__proto__:null,default:n0},Symbol.toStringTag,{value:"Module"})),H=t0(h0);/**
|
||||
import{aj as L,q as $,B as J,o as q,l as X,d as G,w as Z,a0 as O,a1 as R,x as S,u as m,ak as Q,al as t0,am as r0,an as e0}from"./index-b50bcc8e.js";const E={Sidebar_drawer:!0,Customizer_drawer:!1,mini_sidebar:!1,fontTheme:"Roboto",inputBg:!1},i0=L({id:"customizer",state:()=>({Sidebar_drawer:E.Sidebar_drawer,Customizer_drawer:E.Customizer_drawer,mini_sidebar:E.mini_sidebar,fontTheme:"Poppins",inputBg:E.inputBg}),getters:{},actions:{SET_SIDEBAR_DRAWER(){this.Sidebar_drawer=!this.Sidebar_drawer},SET_MINI_SIDEBAR(p){this.mini_sidebar=p},SET_FONT(p){this.fontTheme=p}}}),s0={class:"logo",style:{display:"flex","align-items":"center"}},a0={style:{"font-size":"24px","font-weight":"1000"}},f0={style:{"font-size":"20px","font-weight":"1000"}},o0={style:{"font-size":"20px"}},l0=$({__name:"LogoDark",setup(p){J("rgb(var(--v-theme-primary))"),J("rgb(var(--v-theme-secondary))");const d=i0();return(M,y)=>(q(),X("div",s0,[G(S(Q),{to:"/",style:{"text-decoration":"none",color:"black"}},{default:Z(()=>[O(m("span",a0,"AstrBot 仪表盘",512),[[R,!S(d).mini_sidebar]]),O(m("span",f0,"Astr",512),[[R,S(d).mini_sidebar]]),O(m("span",o0,"Bot",512),[[R,S(d).mini_sidebar]])]),_:1})]))}});var P={exports:{}};const n0={},h0=Object.freeze(Object.defineProperty({__proto__:null,default:n0},Symbol.toStringTag,{value:"Module"})),H=t0(h0);/**
|
||||
* [js-md5]{@link https://github.com/emn178/js-md5}
|
||||
*
|
||||
* @namespace md5
|
||||
Vendored
+2
-2
@@ -11,8 +11,8 @@
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@400;500;600;700&family=Roboto:wght@400;500;700&display=swap"
|
||||
/>
|
||||
<title>AstrBot - 仪表盘</title>
|
||||
<script type="module" crossorigin src="/assets/index-7e5a38e4.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-0f1523f3.css">
|
||||
<script type="module" crossorigin src="/assets/index-b50bcc8e.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-86dd25ba.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
@@ -5,6 +5,9 @@ from type.astrbot_message import AstrBotMessage
|
||||
from type.command import CommandResult
|
||||
from type.astrbot_message import MessageType
|
||||
|
||||
class T2IException(Exception):
|
||||
def __init__(self, message: str = "文本转图片时发生错误") -> None:
|
||||
super().__init__(message)
|
||||
|
||||
class Platform():
|
||||
def __init__(self, platform_name: str, context) -> None:
|
||||
@@ -85,6 +88,7 @@ class Platform():
|
||||
else:
|
||||
rendered_images.append(Image.fromFileSystem(p))
|
||||
return rendered_images
|
||||
return message_result
|
||||
|
||||
async def record_metrics(self):
|
||||
self.context.metrics_uploader.increment_platform_stat(self.PLATFORM_NAME)
|
||||
@@ -4,7 +4,7 @@ import traceback
|
||||
import logging
|
||||
from aiocqhttp import CQHttp, Event
|
||||
from aiocqhttp.exceptions import ActionFailed
|
||||
from . import Platform
|
||||
from . import Platform, T2IException
|
||||
from type.astrbot_message import *
|
||||
from type.message_event import *
|
||||
from type.command import *
|
||||
@@ -25,13 +25,11 @@ class AIOCQHTTP(Platform):
|
||||
assert isinstance(platform_config, AiocqhttpPlatformConfig), "aiocqhttp: 无法识别的配置类型。"
|
||||
|
||||
self.message_handler = message_handler
|
||||
self.waiting = {}
|
||||
self.context = context
|
||||
self.config = platform_config
|
||||
self.unique_session = context.config_helper.platform_settings.unique_session
|
||||
self.host = platform_config.ws_reverse_host
|
||||
self.port = platform_config.ws_reverse_port
|
||||
self.admins = context.config_helper.admins_id
|
||||
|
||||
def convert_message(self, event: Event) -> AstrBotMessage:
|
||||
|
||||
@@ -134,13 +132,6 @@ class AIOCQHTTP(Platform):
|
||||
ok, reason = await self.pre_check(message)
|
||||
if not ok:
|
||||
return
|
||||
|
||||
# 解析 role
|
||||
sender_id = str(message.sender.user_id)
|
||||
if sender_id in self.admins:
|
||||
role = 'admin'
|
||||
else:
|
||||
role = 'member'
|
||||
|
||||
# parse unified message origin
|
||||
unified_msg_origin = None
|
||||
@@ -157,7 +148,6 @@ class AIOCQHTTP(Platform):
|
||||
self.context,
|
||||
"aiocqhttp",
|
||||
message.session_id,
|
||||
role,
|
||||
unified_msg_origin,
|
||||
reason == "command") # only_command
|
||||
|
||||
@@ -169,13 +159,8 @@ class AIOCQHTTP(Platform):
|
||||
if message_result.callback:
|
||||
message_result.callback()
|
||||
|
||||
# 如果是等待回复的消息
|
||||
if message.session_id in self.waiting and self.waiting[message.session_id] == '':
|
||||
self.waiting[message.session_id] = message
|
||||
|
||||
return message_result
|
||||
|
||||
|
||||
|
||||
async def reply_msg(self,
|
||||
message: AstrBotMessage,
|
||||
result_message: list,
|
||||
@@ -183,36 +168,35 @@ class AIOCQHTTP(Platform):
|
||||
"""
|
||||
回复用户唤醒机器人的消息。(被动回复)
|
||||
"""
|
||||
res = result_message
|
||||
|
||||
if isinstance(res, str):
|
||||
res = [Plain(text=res), ]
|
||||
try:
|
||||
await self._reply(message, result_message, use_t2i)
|
||||
except T2IException as e:
|
||||
logger.error(traceback.format_exc())
|
||||
logger.warning(f"文本转图片时发生错误,将使用纯文本发送。")
|
||||
await self._reply(message, result_message, False)
|
||||
return result_message
|
||||
|
||||
# if image mode, put all Plain texts into a new picture.
|
||||
if (use_t2i or (use_t2i == None and self.context.config_helper.t2i)) and isinstance(result_message, list):
|
||||
rendered_images = await self.convert_to_t2i_chain(res)
|
||||
if rendered_images:
|
||||
try:
|
||||
await self._reply(message, rendered_images)
|
||||
return rendered_images
|
||||
except BaseException as e:
|
||||
logger.warn(traceback.format_exc())
|
||||
logger.warn(f"以文本转图片的形式回复消息时发生错误: {e},将尝试默认方式。")
|
||||
|
||||
await self._reply(message, res)
|
||||
return res
|
||||
|
||||
async def _reply(self, message: Union[AstrBotMessage, Dict], message_chain: List[BaseMessageComponent]):
|
||||
async def _reply(self, message: Union[AstrBotMessage, Dict], message_chain: List[BaseMessageComponent], use_t2i: bool = None):
|
||||
await self.record_metrics()
|
||||
if isinstance(message_chain, str):
|
||||
message_chain = [Plain(text=message_chain), ]
|
||||
|
||||
# 文转图处理
|
||||
if (use_t2i or (use_t2i == None and self.context.config_helper.t2i)) and isinstance(message_chain, list):
|
||||
try:
|
||||
message_chain = await self.convert_to_t2i_chain(message_chain)
|
||||
if not message_chain: raise T2IException()
|
||||
except BaseException as e:
|
||||
raise T2IException()
|
||||
|
||||
# log
|
||||
if isinstance(message, AstrBotMessage):
|
||||
logger.info(
|
||||
f"{message.sender.nickname}/{message.sender.user_id} <- {self.parse_message_outline(message_chain)}")
|
||||
else:
|
||||
logger.info(f"回复消息: {message_chain}")
|
||||
|
||||
|
||||
# 解析成 OneBot json 格式并发送
|
||||
ret = []
|
||||
image_idx = []
|
||||
for idx, segment in enumerate(message_chain):
|
||||
@@ -232,10 +216,11 @@ class AIOCQHTTP(Platform):
|
||||
# ENOENT
|
||||
if not image_idx:
|
||||
raise e
|
||||
logger.warn("回复失败。检测到失败原因为文件未找到,猜测用户的协议端与 AstrBot 位于不同的文件系统上。尝试采用上传图片的方式发图。")
|
||||
logger.warning("回复失败。检测到失败原因为文件未找到,猜测用户的协议端与 AstrBot 位于不同的文件系统上。尝试采用上传图片的方式发图。")
|
||||
for idx in image_idx:
|
||||
if ret[idx]['data']['file'].startswith('file://'):
|
||||
logger.info(f"正在上传图片: {ret[idx]['data']['path']}")
|
||||
# 除了上传到图床,想不到更好的办法。
|
||||
image_url = await self.context.image_uploader.upload_image(ret[idx]['data']['path'])
|
||||
logger.info(f"上传成功。")
|
||||
ret[idx]['data']['file'] = image_url
|
||||
@@ -267,8 +252,12 @@ class AIOCQHTTP(Platform):
|
||||
- 要发给某个群聊,请添加 key `group_id`,值为 int 类型的 qq 群号;
|
||||
|
||||
'''
|
||||
|
||||
await self._reply(target, result_message.message_chain)
|
||||
try:
|
||||
await self._reply(target, result_message.message_chain, result_message.is_use_t2i)
|
||||
except T2IException as e:
|
||||
logger.error(traceback.format_exc())
|
||||
logger.warning(f"文本转图片时发生错误,将使用纯文本发送。")
|
||||
await self._reply(target, result_message.message_chain, False)
|
||||
|
||||
async def send_msg_new(self, message_type: MessageType, target: str, result_message: CommandResult):
|
||||
if message_type == MessageType.GROUP_MESSAGE:
|
||||
|
||||
+37
-60
@@ -11,7 +11,7 @@ from nakuru import (
|
||||
)
|
||||
from typing import Union, List, Dict
|
||||
from type.types import Context
|
||||
from . import Platform
|
||||
from . import Platform, T2IException
|
||||
from type.astrbot_message import *
|
||||
from type.message_event import *
|
||||
from type.command import *
|
||||
@@ -40,11 +40,9 @@ class QQNakuru(Platform):
|
||||
asyncio.set_event_loop(self.loop)
|
||||
|
||||
self.message_handler = message_handler
|
||||
self.waiting = {}
|
||||
self.context = context
|
||||
self.unique_session = context.config_helper.platform_settings.unique_session
|
||||
self.config = platform_config
|
||||
self.admins = context.config_helper.admins_id
|
||||
|
||||
self.client = CQHTTP(
|
||||
host=self.config.host,
|
||||
@@ -113,13 +111,6 @@ class QQNakuru(Platform):
|
||||
session_id = message.raw_message.user_id
|
||||
|
||||
message.session_id = session_id
|
||||
|
||||
# 解析 role
|
||||
sender_id = str(message.raw_message.user_id)
|
||||
if sender_id in self.admins:
|
||||
role = 'admin'
|
||||
else:
|
||||
role = 'member'
|
||||
|
||||
# parse unified message origin
|
||||
unified_msg_origin = None
|
||||
@@ -141,7 +132,6 @@ class QQNakuru(Platform):
|
||||
self.context,
|
||||
"nakuru",
|
||||
session_id,
|
||||
role,
|
||||
unified_msg_origin,
|
||||
reason == 'command') # only_command
|
||||
|
||||
@@ -153,49 +143,47 @@ class QQNakuru(Platform):
|
||||
if message_result.callback:
|
||||
message_result.callback()
|
||||
|
||||
# 如果是等待回复的消息
|
||||
if session_id in self.waiting and self.waiting[session_id] == '':
|
||||
self.waiting[session_id] = message
|
||||
|
||||
async def reply_msg(self,
|
||||
message: AstrBotMessage,
|
||||
result_message: List[BaseMessageComponent],
|
||||
use_t2i: bool = None):
|
||||
"""
|
||||
回复用户唤醒机器人的消息。(被动回复)
|
||||
"""
|
||||
source = message.raw_message
|
||||
res = result_message
|
||||
"""
|
||||
assert isinstance(message.raw_message, (GroupMessage, FriendMessage, GuildMessage))
|
||||
|
||||
try:
|
||||
await self._reply(message, result_message, use_t2i)
|
||||
except T2IException as e:
|
||||
logger.error(traceback.format_exc())
|
||||
logger.warning(f"文本转图片时发生错误,将使用纯文本发送。")
|
||||
await self._reply(message, result_message, False)
|
||||
return result_message
|
||||
|
||||
assert isinstance(source,
|
||||
(GroupMessage, FriendMessage, GuildMessage))
|
||||
|
||||
logger.info(
|
||||
f"{message.sender.nickname}/{message.sender.user_id} <- {self.parse_message_outline(res)}")
|
||||
|
||||
if isinstance(res, str):
|
||||
res = [Plain(text=res), ]
|
||||
|
||||
# if image mode, put all Plain texts into a new picture.
|
||||
if use_t2i or (use_t2i == None and self.context.config_helper.t2i) and isinstance(result_message, list):
|
||||
rendered_images = await self.convert_to_t2i_chain(res)
|
||||
if rendered_images:
|
||||
try:
|
||||
await self._reply(source, rendered_images)
|
||||
return
|
||||
except BaseException as e:
|
||||
logger.warn(traceback.format_exc())
|
||||
logger.warn(f"以文本转图片的形式回复消息时发生错误: {e},将尝试默认方式。")
|
||||
|
||||
await self._reply(source, res)
|
||||
|
||||
async def _reply(self, source, message_chain: List[BaseMessageComponent]):
|
||||
async def _reply(self, message: Union[AstrBotMessage, Dict], message_chain: List[BaseMessageComponent], use_t2i: bool = None):
|
||||
await self.record_metrics()
|
||||
if isinstance(message_chain, str):
|
||||
message_chain = [Plain(text=message_chain), ]
|
||||
|
||||
# 文转图处理
|
||||
if (use_t2i or (use_t2i == None and self.context.config_helper.t2i)) and isinstance(message_chain, list):
|
||||
try:
|
||||
message_chain = await self.convert_to_t2i_chain(message_chain)
|
||||
if not message_chain: raise T2IException()
|
||||
except BaseException as e:
|
||||
raise T2IException()
|
||||
|
||||
# log
|
||||
if isinstance(message, AstrBotMessage):
|
||||
logger.info(
|
||||
f"{message.sender.nickname}/{message.sender.user_id} <- {self.parse_message_outline(message_chain)}")
|
||||
else:
|
||||
logger.info(f"回复消息: {message_chain}")
|
||||
|
||||
source = message.raw_message
|
||||
is_dict = isinstance(source, dict)
|
||||
|
||||
# 发消息
|
||||
typ = None
|
||||
if is_dict:
|
||||
if "group_id" in source:
|
||||
@@ -250,7 +238,13 @@ class QQNakuru(Platform):
|
||||
|
||||
guild_id 不是频道号。
|
||||
'''
|
||||
await self._reply(target, result_message.message_chain)
|
||||
try:
|
||||
await self._reply(target, result_message.message_chain, result_message.is_use_t2i)
|
||||
except T2IException as e:
|
||||
logger.error(traceback.format_exc())
|
||||
logger.warning(f"文本转图片时发生错误,将使用纯文本发送。")
|
||||
await self._reply(target, result_message.message_chain, False)
|
||||
return result_message
|
||||
|
||||
async def send_msg_new(self, message_type: MessageType, target: str, result_message: CommandResult):
|
||||
'''
|
||||
@@ -290,21 +284,4 @@ class QQNakuru(Platform):
|
||||
)
|
||||
abm.tag = "nakuru"
|
||||
abm.message = message.message
|
||||
return abm
|
||||
|
||||
def wait_for_message(self, group_id) -> Union[GroupMessage, FriendMessage, GuildMessage]:
|
||||
'''
|
||||
等待下一条消息,超时 300s 后抛出异常
|
||||
'''
|
||||
self.waiting[group_id] = ''
|
||||
cnt = 0
|
||||
while True:
|
||||
if group_id in self.waiting and self.waiting[group_id] != '':
|
||||
# 去掉
|
||||
ret = self.waiting[group_id]
|
||||
del self.waiting[group_id]
|
||||
return ret
|
||||
cnt += 1
|
||||
if cnt > 300:
|
||||
raise Exception("等待消息超时。")
|
||||
time.sleep(1)
|
||||
return abm
|
||||
@@ -63,10 +63,8 @@ class QQOfficial(Platform):
|
||||
asyncio.set_event_loop(self.loop)
|
||||
|
||||
self.message_handler = message_handler
|
||||
self.waiting: dict = {}
|
||||
self.context = context
|
||||
self.config = platform_config
|
||||
self.admins = context.config_helper.admins_id
|
||||
|
||||
self.appid = platform_config.appid
|
||||
self.secret = platform_config.secret
|
||||
@@ -201,15 +199,8 @@ class QQOfficial(Platform):
|
||||
session_id = str(message.raw_message.author.id)
|
||||
message.session_id = session_id
|
||||
|
||||
# 解析出 role
|
||||
sender_id = message.sender.user_id
|
||||
if sender_id in self.admins:
|
||||
role = 'admin'
|
||||
else:
|
||||
role = 'member'
|
||||
|
||||
# construct astrbot message event
|
||||
ame = AstrMessageEvent.from_astrbot_message(message, self.context, "qqofficial", session_id, role)
|
||||
ame = AstrMessageEvent.from_astrbot_message(message, self.context, "qqofficial", session_id)
|
||||
|
||||
message_result = await self.message_handler.handle(ame)
|
||||
if not message_result:
|
||||
@@ -219,10 +210,6 @@ class QQOfficial(Platform):
|
||||
if message_result.callback:
|
||||
message_result.callback()
|
||||
|
||||
# 如果是等待回复的消息
|
||||
if session_id in self.waiting and self.waiting[session_id] == '':
|
||||
self.waiting[session_id] = message
|
||||
|
||||
return ret
|
||||
|
||||
async def reply_msg(self,
|
||||
@@ -241,10 +228,15 @@ class QQOfficial(Platform):
|
||||
plain_text = ''
|
||||
image_path = ''
|
||||
msg_ref = None
|
||||
rendered_images = []
|
||||
rendered_images = None
|
||||
|
||||
if use_t2i or (use_t2i == None and self.context.config_helper.t2i) and isinstance(result_message, list):
|
||||
rendered_images = await self.convert_to_t2i_chain(result_message)
|
||||
try:
|
||||
rendered_images = await self.convert_to_t2i_chain(result_message)
|
||||
except BaseException as e:
|
||||
logger.warning(traceback.format_exc())
|
||||
logger.warning(f"文本转图片时发生错误: {e},将尝试默认方式。")
|
||||
rendered_images = None
|
||||
|
||||
if isinstance(result_message, list):
|
||||
plain_text, image_path = await self._parse_to_qqofficial(result_message, message.type == MessageType.GROUP_MESSAGE)
|
||||
@@ -386,20 +378,3 @@ class QQOfficial(Platform):
|
||||
|
||||
async def send_msg_new(self, message_type: MessageType, target: str, result_message: CommandResult):
|
||||
raise NotImplementedError("qqofficial 不支持此方法。")
|
||||
|
||||
def wait_for_message(self, channel_id: int) -> AstrBotMessage:
|
||||
'''
|
||||
等待指定 channel_id 的下一条信息,超时 300s 后抛出异常
|
||||
'''
|
||||
self.waiting[channel_id] = ''
|
||||
cnt = 0
|
||||
while True:
|
||||
if channel_id in self.waiting and self.waiting[channel_id] != '':
|
||||
# 去掉
|
||||
ret = self.waiting[channel_id]
|
||||
del self.waiting[channel_id]
|
||||
return ret
|
||||
cnt += 1
|
||||
if cnt > 300:
|
||||
raise Exception("等待消息超时。")
|
||||
time.sleep(1)
|
||||
|
||||
@@ -99,8 +99,6 @@ class PluginManager():
|
||||
if "no such option: --break-system-package" in err:
|
||||
self.update_plugin_dept(path, break_system_package=False)
|
||||
break
|
||||
else:
|
||||
logger.error("可能发生插件依赖安装失败导致插件无法被正常载入。请手动更新插件依赖。路径: " + path)
|
||||
if output == '' and process.poll() is not None:
|
||||
break
|
||||
if output:
|
||||
|
||||
+4
-75
@@ -1,80 +1,6 @@
|
||||
VERSION = '3.3.16'
|
||||
VERSION = '3.3.17'
|
||||
DB_PATH = 'data/data_v2.db'
|
||||
|
||||
DEFAULT_CONFIG = {
|
||||
"qqbot": {
|
||||
"enable": False,
|
||||
"appid": "",
|
||||
"token": "",
|
||||
},
|
||||
"gocqbot": {
|
||||
"enable": False,
|
||||
},
|
||||
"uniqueSessionMode": False,
|
||||
"dump_history_interval": 10,
|
||||
"limit": {
|
||||
"time": 60,
|
||||
"count": 30,
|
||||
},
|
||||
"notice": "",
|
||||
"direct_message_mode": True,
|
||||
"reply_prefix": "",
|
||||
"baidu_aip": {
|
||||
"enable": False,
|
||||
"app_id": "",
|
||||
"api_key": "",
|
||||
"secret_key": ""
|
||||
},
|
||||
"openai": {
|
||||
"key": [],
|
||||
"api_base": "",
|
||||
"chatGPTConfigs": {
|
||||
"model": "gpt-4o",
|
||||
"max_tokens": 6000,
|
||||
"temperature": 0.9,
|
||||
"top_p": 1,
|
||||
"frequency_penalty": 0,
|
||||
"presence_penalty": 0,
|
||||
},
|
||||
"total_tokens_limit": 10000,
|
||||
},
|
||||
"qq_forward_threshold": 200,
|
||||
"qq_welcome": "",
|
||||
"qq_pic_mode": True,
|
||||
"gocq_host": "127.0.0.1",
|
||||
"gocq_http_port": 5700,
|
||||
"gocq_websocket_port": 6700,
|
||||
"gocq_react_group": True,
|
||||
"gocq_react_guild": True,
|
||||
"gocq_react_friend": True,
|
||||
"gocq_react_group_increase": True,
|
||||
"other_admins": [],
|
||||
"CHATGPT_BASE_URL": "",
|
||||
"qqbot_secret": "",
|
||||
"qqofficial_enable_group_message": False,
|
||||
"admin_qq": "",
|
||||
"nick_qq": ["/", "!"],
|
||||
"admin_qqchan": "",
|
||||
"llm_env_prompt": "",
|
||||
"llm_wake_prefix": "",
|
||||
"default_personality_str": "",
|
||||
"openai_image_generate": {
|
||||
"model": "dall-e-3",
|
||||
"size": "1024x1024",
|
||||
"style": "vivid",
|
||||
"quality": "standard",
|
||||
},
|
||||
"http_proxy": "",
|
||||
"https_proxy": "",
|
||||
"dashboard_username": "",
|
||||
"dashboard_password": "",
|
||||
"aiocqhttp": {
|
||||
"enable": False,
|
||||
"ws_reverse_host": "",
|
||||
"ws_reverse_port": 0,
|
||||
}
|
||||
}
|
||||
|
||||
# 新版本配置文件,摈弃旧版本令人困惑的配置项 :D
|
||||
DEFAULT_CONFIG_VERSION_2 = {
|
||||
"config_version": 2,
|
||||
@@ -146,6 +72,7 @@ DEFAULT_CONFIG_VERSION_2 = {
|
||||
"llm_settings": {
|
||||
"wake_prefix": "",
|
||||
"web_search": False,
|
||||
"identifier": False,
|
||||
},
|
||||
"content_safety": {
|
||||
"baidu_aip": {
|
||||
@@ -231,6 +158,7 @@ MAPPINGS_1_2 = [
|
||||
[["nick_qq"], ["wake_prefix"]],
|
||||
]
|
||||
|
||||
# 配置项的中文描述、值类型
|
||||
CONFIG_METADATA_2 = {
|
||||
"config_version": {"description": "配置版本", "type": "int"},
|
||||
"platform": {
|
||||
@@ -312,6 +240,7 @@ CONFIG_METADATA_2 = {
|
||||
"items": {
|
||||
"wake_prefix": {"description": "LLM 聊天额外唤醒前缀", "type": "string"},
|
||||
"web_search": {"description": "启用网页搜索(能访问 Google 时效果最佳)", "type": "bool"},
|
||||
"identifier": {"description": "启动识别群员(略微增加token开销)", "type": "bool"},
|
||||
}
|
||||
},
|
||||
"content_safety": {
|
||||
|
||||
@@ -47,10 +47,17 @@ class AstrMessageEvent():
|
||||
context: Context,
|
||||
platform_name: str,
|
||||
session_id: str,
|
||||
role: str = "member",
|
||||
|
||||
unified_msg_origin: str = None,
|
||||
only_command: bool = False):
|
||||
|
||||
# 解析 role
|
||||
sender_id = str(message.sender.user_id)
|
||||
if sender_id in context.config_helper.admins_id:
|
||||
role = 'admin'
|
||||
else:
|
||||
role = 'member'
|
||||
|
||||
ame = AstrMessageEvent(message.message_str,
|
||||
message,
|
||||
context.find_platform(platform_name),
|
||||
|
||||
+10
-43
@@ -3,7 +3,7 @@ import json
|
||||
import shutil
|
||||
import logging
|
||||
from util.io import on_error
|
||||
from type.config import DEFAULT_CONFIG, DEFAULT_CONFIG_VERSION_2, MAPPINGS_1_2
|
||||
from type.config import DEFAULT_CONFIG_VERSION_2, MAPPINGS_1_2
|
||||
from dataclasses import dataclass, field, asdict
|
||||
from typing import List, Dict, Optional
|
||||
|
||||
@@ -90,6 +90,7 @@ class LLMConfig:
|
||||
class LLMSettings:
|
||||
wake_prefix: str = ""
|
||||
web_search: bool = False
|
||||
identifier: bool = False
|
||||
|
||||
@dataclass
|
||||
class BaiduAIPConfig:
|
||||
@@ -175,7 +176,7 @@ class AstrBotConfig():
|
||||
self.https_proxy=data.get("https_proxy", "")
|
||||
self.http_proxy=data.get("http_proxy", "")
|
||||
self.dashboard=DashboardConfig(**data.get("dashboard", {}))
|
||||
self.wake_prefix=data.get("wake_prefix", [])
|
||||
self.wake_prefix=data.get("wake_prefix", ["/"])
|
||||
self.log_level=data.get("log_level", "INFO")
|
||||
self.t2i_endpoint=data.get("t2i_endpoint", "")
|
||||
|
||||
@@ -228,22 +229,15 @@ class AstrBotConfig():
|
||||
config = self.migrate_config_1_2(config)
|
||||
self.flush_config(config)
|
||||
|
||||
_tag = False
|
||||
for key, val in DEFAULT_CONFIG_VERSION_2.items():
|
||||
if key not in config:
|
||||
config[key] = val
|
||||
_tag = True
|
||||
if _tag:
|
||||
with open(ASTRBOT_CONFIG_PATH, "w", encoding="utf-8-sig") as f:
|
||||
json.dump(config, f, indent=2, ensure_ascii=False)
|
||||
f.flush()
|
||||
|
||||
# 加载配置到对象
|
||||
self.load_from_dict(config)
|
||||
# 保存到文件
|
||||
# 这一步操作是为了保证配置文件中的字段的完整性。
|
||||
# 在版本变动新增配置项时,将对象中新增的配置项的默认值写入文件。
|
||||
self.save_config()
|
||||
|
||||
def get(self, key: str, default=None):
|
||||
'''
|
||||
从文件系统中直接获取配置
|
||||
'''
|
||||
'''从文件系统中直接获取配置'''
|
||||
with open(ASTRBOT_CONFIG_PATH, "r", encoding="utf-8-sig") as f:
|
||||
d = json.load(f)
|
||||
if key in d:
|
||||
@@ -252,9 +246,7 @@ class AstrBotConfig():
|
||||
return default
|
||||
|
||||
def get_all(self):
|
||||
'''
|
||||
从文件系统中获取所有配置
|
||||
'''
|
||||
'''从文件系统中获取所有配置'''
|
||||
with open(ASTRBOT_CONFIG_PATH, "r", encoding="utf-8-sig") as f:
|
||||
conf_str = f.read()
|
||||
if conf_str.startswith(u'/ufeff'): # remove BOM
|
||||
@@ -274,31 +266,6 @@ class AstrBotConfig():
|
||||
|
||||
def to_dict(self) -> Dict:
|
||||
return asdict(self)
|
||||
|
||||
def put_by_dot_str(self, key: str, value):
|
||||
'''根据点分割的字符串,将值写入配置文件'''
|
||||
with open(ASTRBOT_CONFIG_PATH, "r", encoding="utf-8-sig") as f:
|
||||
d = json.load(f)
|
||||
_d = d
|
||||
_ks = key.split(".")
|
||||
for i in range(len(_ks)):
|
||||
if i == len(_ks) - 1:
|
||||
_d[_ks[i]] = value
|
||||
else:
|
||||
_d = _d[_ks[i]]
|
||||
with open(ASTRBOT_CONFIG_PATH, "w", encoding="utf-8-sig") as f:
|
||||
json.dump(d, f, indent=2, ensure_ascii=False)
|
||||
f.flush()
|
||||
|
||||
def update_by_path(self, path: List):
|
||||
'''根据路径更新配置文件。
|
||||
|
||||
这个方法首先会更新缓存在内存中的配置,然后再写入文件。
|
||||
'''
|
||||
|
||||
for key in path:
|
||||
if key not in self:
|
||||
raise KeyError(f"Key {key} not found in config.")
|
||||
|
||||
def check_exist(self) -> bool:
|
||||
return os.path.exists(ASTRBOT_CONFIG_PATH)
|
||||
|
||||
@@ -58,14 +58,19 @@ class AstrBotUpdator(RepoZipUpdator):
|
||||
if self.compare_version(VERSION, latest_version) >= 0:
|
||||
raise Exception("当前已经是最新版本。")
|
||||
file_url = update_data[0]['zipball_url']
|
||||
else:
|
||||
elif str(version).startswith("v"):
|
||||
# 更新到指定版本
|
||||
print(f"请求更新到指定版本: {version}")
|
||||
logger.info(f"正在更新到指定版本: {version}")
|
||||
for data in update_data:
|
||||
if data['tag_name'] == version:
|
||||
file_url = data['zipball_url']
|
||||
if not file_url:
|
||||
raise Exception(f"未找到版本号为 {version} 的更新文件。")
|
||||
else:
|
||||
if len(str(version)) != 40:
|
||||
raise Exception("commit hash 长度不正确,应为 40")
|
||||
logger.info(f"正在尝试更新到指定 commit: {version}")
|
||||
file_url = "https://github.com/Soulter/AstrBot/archive/" + version + ".zip"
|
||||
|
||||
try:
|
||||
await download_file(file_url, "temp.zip")
|
||||
|
||||
Reference in New Issue
Block a user