Compare commits

...

8 Commits

Author SHA1 Message Date
Junyan Qin (Chin)
629ebae0e9 chore: release v3.4.11.1 (#1244) 2025-03-28 23:48:09 +08:00
Junyan Qin (Chin)
394d4b3c1b fix: static_file sent with wrong mimetype (#1243) 2025-03-28 23:46:24 +08:00
Junyan Qin (Chin)
a0fd152d19 doc(README): add 3.13 in python version badge (#1232) 2025-03-24 15:43:46 +08:00
Junyan Qin (Chin)
1a62e08bab chore: update gitignore (#1231) 2025-03-24 15:40:51 +08:00
Junyan Qin (Chin)
edbc59c117 perf: use source_platform_object to pass source event in aiocqhttp (#1230) 2025-03-24 14:03:44 +08:00
WangCham
cfdd0f8cb2 fix: Format the code in a standardized way (#1222) 2025-03-21 14:04:13 +08:00
Junyan Qin (Chin)
808f30675d doc(README): contributors (#1223) 2025-03-21 10:47:32 +08:00
Junyan Qin (Chin)
46072abb41 doc(README): add planning platforms comments (#1219) 2025-03-19 23:23:56 +08:00
9 changed files with 105 additions and 111 deletions

2
.gitignore vendored
View File

@@ -19,7 +19,7 @@ cookies.json
data/labels/announcement_saved.json
cmdpriv.json
tips.py
.venv
venv*
bin/
.vscode
test_*

View File

@@ -26,7 +26,7 @@
[![QQ Group](https://img.shields.io/badge/%E7%A4%BE%E5%8C%BAQQ%E7%BE%A4-966235608-blue)](https://qm.qq.com/q/JLi38whHum)
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/RockChinQ/LangBot)](https://github.com/RockChinQ/LangBot/releases/latest)
![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.qchatgpt.rockchin.top%2Fapi%2Fv2%2Fview%2Frealtime%2Fcount_query%3Fminute%3D10080&query=%24.data.count&label=%E4%BD%BF%E7%94%A8%E9%87%8F%EF%BC%887%E6%97%A5%EF%BC%89)
<img src="https://img.shields.io/badge/python-3.10 | 3.11 | 3.12-blue.svg" alt="python">
<img src="https://img.shields.io/badge/python-3.10 ~ 3.13 -blue.svg" alt="python">
[![star](https://gitcode.com/RockChinQ/LangBot/star/badge.svg)](https://gitcode.com/RockChinQ/LangBot)
[简体中文](README.md) / [English](README_EN.md) / [日本語](README_JP.md)
@@ -93,6 +93,8 @@
| 钉钉 | ✅ | |
| Discord | ✅ | |
| Telegram | ✅ | |
| Slack | 🚧 | |
| LINE | 🚧 | |
| WhatsApp | 🚧 | |
🚧: 正在开发中
@@ -115,6 +117,7 @@
| [阿里云百炼](https://bailian.console.aliyun.com/) | ✅ | 大模型聚合平台, LLMOps 平台 |
| [火山方舟](https://console.volcengine.com/ark/region:ark+cn-beijing/model?vendor=Bytedance&view=LIST_VIEW) | ✅ | 大模型聚合平台, LLMOps 平台 |
| [MCP](https://modelcontextprotocol.io/) | ✅ | 支持通过 MCP 协议获取工具 |
### TTS
| 平台/模型 | 备注 |
@@ -131,9 +134,15 @@
## 😘 社区贡献
LangBot 离不开以下贡献者和社区内所有人的贡献,我们欢迎任何形式的贡献和反馈。
感谢以下[代码贡献者](https://github.com/RockChinQ/LangBot/graphs/contributors)和社区里其他成员对 LangBot 的贡献:
<a href="https://github.com/RockChinQ/LangBot/graphs/contributors">
<img src="https://contrib.rocks/image?repo=RockChinQ/LangBot" />
</a>
以及 LangBot 核心团队成员:
- [RockChinQ](https://github.com/RockChinQ)
- [the-lazy-me](https://github.com/the-lazy-me)
- [wangcham](https://github.com/wangcham)
- [KaedeSAMA](https://github.com/KaedeSAMA)

View File

@@ -24,7 +24,7 @@
[![Discord](https://img.shields.io/discord/1335141740050649118?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb)](https://discord.gg/wdNEHETs87)
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/RockChinQ/LangBot)](https://github.com/RockChinQ/LangBot/releases/latest)
![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.qchatgpt.rockchin.top%2Fapi%2Fv2%2Fview%2Frealtime%2Fcount_query%3Fminute%3D10080&query=%24.data.count&label=Usage(7days))
<img src="https://img.shields.io/badge/python-3.10 | 3.11 | 3.12-blue.svg" alt="python">
<img src="https://img.shields.io/badge/python-3.10 ~ 3.13 -blue.svg" alt="python">
[简体中文](README.md) / [English](README_EN.md) / [日本語](README_JP.md)
@@ -90,6 +90,8 @@ Directly use the released version to run, see the [Manual Deployment](https://do
| DingTalk | ✅ | |
| Discord | ✅ | |
| Telegram | ✅ | |
| Slack | 🚧 | |
| LINE | 🚧 | |
| WhatsApp | 🚧 | |
🚧: In development
@@ -115,11 +117,15 @@ Directly use the released version to run, see the [Manual Deployment](https://do
## 🤝 Community Contribution
Thanks to the following contributors and everyone in the community for their contributions.
Thank you for the following [code contributors](https://github.com/RockChinQ/LangBot/graphs/contributors) and other members in the community for their contributions to LangBot:
<a href="https://github.com/RockChinQ/LangBot/graphs/contributors">
<img src="https://contrib.rocks/image?repo=RockChinQ/LangBot" />
</a>
And the core team members of LangBot:
- [RockChinQ](https://github.com/RockChinQ)
- [the-lazy-me](https://github.com/the-lazy-me)
- [wangcham](https://github.com/wangcham)
- [KaedeSAMA](https://github.com/KaedeSAMA)

View File

@@ -23,7 +23,7 @@
[![Discord](https://img.shields.io/discord/1335141740050649118?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb)](https://discord.gg/wdNEHETs87)
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/RockChinQ/LangBot)](https://github.com/RockChinQ/LangBot/releases/latest)
![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.qchatgpt.rockchin.top%2Fapi%2Fv2%2Fview%2Frealtime%2Fcount_query%3Fminute%3D10080&query=%24.data.count&label=Usage(7days))
<img src="https://img.shields.io/badge/python-3.10 | 3.11 | 3.12-blue.svg" alt="python">
<img src="https://img.shields.io/badge/python-3.10 ~ 3.13 -blue.svg" alt="python">
[简体中文](README.md) / [English](README_EN.md) / [日本語](README_JP.md)
@@ -89,6 +89,8 @@ LangBotはBTPanelにリストされています。BTPanelをインストール
| DingTalk | ✅ | |
| Discord | ✅ | |
| Telegram | ✅ | |
| Slack | 🚧 | |
| LINE | 🚧 | |
| WhatsApp | 🚧 | |
🚧: 開発中
@@ -114,11 +116,15 @@ LangBotはBTPanelにリストされています。BTPanelをインストール
## 🤝 コミュニティ貢献
以下の貢献者とコミュニティの皆さんの貢献に感謝します。
LangBot への貢献に対して、以下の [コード貢献者](https://github.com/RockChinQ/LangBot/graphs/contributors) とコミュニティの他のメンバーに感謝します。
<a href="https://github.com/RockChinQ/LangBot/graphs/contributors">
<img src="https://contrib.rocks/image?repo=RockChinQ/LangBot" />
</a>
LangBot の核心チームメンバー:
- [RockChinQ](https://github.com/RockChinQ)
- [the-lazy-me](https://github.com/the-lazy-me)
- [wangcham](https://github.com/wangcham)
- [KaedeSAMA](https://github.com/KaedeSAMA)

View File

@@ -27,7 +27,6 @@ xml_template = """
</xml>
"""
user_msg_queue = {}
class OAClient():
@@ -45,6 +44,7 @@ class OAClient():
}
self.access_token_expiry_time = None
self.msg_id_map = {}
self.generated_content = {}
async def handle_callback_request(self):
@@ -87,12 +87,10 @@ class OAClient():
from_user = root.find("FromUserName").text # 发送者
to_user = root.find("ToUserName").text # 机器人
from pkg.platform.sources import officialaccount
timeout = 4.80
interval = 0.1
while True:
content = officialaccount.generated_content.pop(message_data["MsgId"], None)
content = self.generated_content.pop(message_data["MsgId"], None)
if content:
response_xml = xml_template.format(
to_user=from_user,
@@ -172,6 +170,9 @@ class OAClient():
for handler in self._message_handlers[msg_type]:
await handler(event)
async def set_message(self,msg_id:int,content:str):
self.generated_content[msg_id] = content
class OAClientForLongerResponse():
@@ -190,6 +191,8 @@ class OAClientForLongerResponse():
}
self.access_token_expiry_time = None
self.loading_message = LoadingMessage
self.msg_queue = {}
self.user_msg_queue = {}
async def handle_callback_request(self):
try:
@@ -222,17 +225,15 @@ class OAClientForLongerResponse():
from_user = root.find("FromUserName").text
to_user = root.find("ToUserName").text
from pkg.platform.sources import officialaccount as oa
if oa.msg_queue.get(from_user) and oa.msg_queue[from_user][0]["content"]:
queue_top = oa.msg_queue[from_user].pop(0)
if self.msg_queue.get(from_user) and self.msg_queue[from_user][0]["content"]:
queue_top = self.msg_queue[from_user].pop(0)
queue_content = queue_top["content"]
# 弹出用户消息
if user_msg_queue.get(from_user) and user_msg_queue[from_user]:
user_msg_queue[from_user].pop(0)
if self.user_msg_queue.get(from_user) and self.user_msg_queue[from_user]:
self.user_msg_queue[from_user].pop(0)
response_xml = xml_template.format(
to_user=from_user,
@@ -250,7 +251,7 @@ class OAClientForLongerResponse():
content=self.loading_message
)
if user_msg_queue.get(from_user) and user_msg_queue[from_user][0]["content"]:
if self.user_msg_queue.get(from_user) and self.user_msg_queue[from_user][0]["content"]:
return response_xml
else:
message_data = await self.get_message(xml_msg)
@@ -258,7 +259,7 @@ class OAClientForLongerResponse():
if message_data:
event = OAEvent.from_payload(message_data)
if event:
user_msg_queue.setdefault(from_user,[]).append(
self.user_msg_queue.setdefault(from_user,[]).append(
{
"content":event.message,
}
@@ -318,6 +319,18 @@ class OAClientForLongerResponse():
for handler in self._message_handlers[msg_type]:
await handler(event)
async def set_message(self,from_user:int,message_id:int,content:str):
if from_user not in self.msg_queue:
self.msg_queue[from_user] = []
self.msg_queue[from_user].append(
{
"msg_id":message_id,
"content":content,
}
)

View File

@@ -66,8 +66,42 @@ class HTTPController:
@self.quart_app.route("/")
async def index():
return await quart.send_from_directory(frontend_path, "index.html")
return await quart.send_from_directory(
frontend_path,
"index.html",
mimetype="text/html"
)
@self.quart_app.route("/<path:path>")
async def static_file(path: str):
return await quart.send_from_directory(frontend_path, path)
mimetype = None
if path.endswith(".html"):
mimetype = "text/html"
elif path.endswith(".js"):
mimetype = "application/javascript"
elif path.endswith(".css"):
mimetype = "text/css"
elif path.endswith(".png"):
mimetype = "image/png"
elif path.endswith(".jpg"):
mimetype = "image/jpeg"
elif path.endswith(".jpeg"):
mimetype = "image/jpeg"
elif path.endswith(".gif"):
mimetype = "image/gif"
elif path.endswith(".svg"):
mimetype = "image/svg+xml"
elif path.endswith(".ico"):
mimetype = "image/x-icon"
elif path.endswith(".json"):
mimetype = "application/json"
elif path.endswith(".txt"):
mimetype = "text/plain"
return await quart.send_from_directory(
frontend_path,
path,
mimetype=mimetype
)

View File

@@ -57,7 +57,7 @@ class AiocqhttpMessageConverter(adapter.MessageConverter):
elif msg.path:
arg = msg.path
msg_list.append(aiocqhttp.MessageSegment.record(msg.path))
elif type(msg) is forward.Forward:
elif type(msg) is platform_message.Forward:
for node in msg.node_list:
msg_list.extend((await AiocqhttpMessageConverter.yiri2target(node.message_chain))[0])
@@ -101,69 +101,8 @@ class AiocqhttpMessageConverter(adapter.MessageConverter):
class AiocqhttpEventConverter(adapter.EventConverter):
@staticmethod
async def yiri2target(event: platform_events.Event, bot_account_id: int):
msg, msg_id, msg_time = await AiocqhttpMessageConverter.yiri2target(event.message_chain)
if type(event) is platform_events.GroupMessage:
role = "member"
if event.sender.permission == "ADMINISTRATOR":
role = "admin"
elif event.sender.permission == "OWNER":
role = "owner"
payload = {
"post_type": "message",
"message_type": "group",
"time": int(msg_time.timestamp()),
"self_id": bot_account_id,
"sub_type": "normal",
"anonymous": None,
"font": 0,
"message": str(msg),
"raw_message": str(msg),
"sender": {
"age": 0,
"area": "",
"card": "",
"level": "",
"nickname": event.sender.member_name,
"role": role,
"sex": "unknown",
"title": "",
"user_id": event.sender.id,
},
"user_id": event.sender.id,
"message_id": msg_id,
"group_id": event.group.id,
"message_seq": 0,
}
return aiocqhttp.Event.from_payload(payload)
elif type(event) is platform_events.FriendMessage:
payload = {
"post_type": "message",
"message_type": "private",
"time": int(msg_time.timestamp()),
"self_id": bot_account_id,
"sub_type": "friend",
"target_id": bot_account_id,
"message": str(msg),
"raw_message": str(msg),
"font": 0,
"sender": {
"age": 0,
"nickname": event.sender.nickname,
"sex": "unknown",
"user_id": event.sender.id,
},
"message_id": msg_id,
"user_id": event.sender.id,
}
return aiocqhttp.Event.from_payload(payload)
async def yiri2target(event: platform_events.MessageEvent, bot_account_id: int):
return event.source_platform_object
@staticmethod
async def target2yiri(event: aiocqhttp.Event):
@@ -196,6 +135,7 @@ class AiocqhttpEventConverter(adapter.EventConverter):
),
message_chain=yiri_chain,
time=event.time,
source_platform_object=event
)
return converted_event
elif event.message_type == "private":
@@ -207,6 +147,7 @@ class AiocqhttpEventConverter(adapter.EventConverter):
),
message_chain=yiri_chain,
time=event.time,
source_platform_object=event
)

View File

@@ -22,10 +22,6 @@ from ..types import entities as platform_entities
from ...command.errors import ParamNotEnoughError
# 生成的ai回答
generated_content = {}
msg_queue = {}
class OAMessageConverter(adapter.MessageConverter):
@staticmethod
async def yiri2target(message_chain: platform_message.MessageChain):
@@ -69,7 +65,7 @@ class OAEventConverter(adapter.EventConverter):
class OfficialAccountAdapter(adapter.MessagePlatformAdapter):
bot : OAClient
bot : OAClient | OAClientForLongerResponse
ap : app.Application
bot_account_id: str
message_converter: OAMessageConverter = OAMessageConverter()
@@ -114,26 +110,15 @@ class OfficialAccountAdapter(adapter.MessagePlatformAdapter):
async def reply_message(self, message_source: platform_events.FriendMessage, message: platform_message.MessageChain, quote_origin: bool = False):
global generated_content
content = await OAMessageConverter.yiri2target(
message
)
generated_content[message_source.message_chain.message_id] = content
from_user = message_source.sender.id
if from_user not in msg_queue:
msg_queue[from_user] = []
msg_queue[from_user].append(
{
"msg_id":message_source.message_chain.message_id,
"content":content,
}
)
if type(self.bot) == OAClient:
await self.bot.set_message(message_source.message_chain.message_id,content)
if type(self.bot) == OAClientForLongerResponse:
from_user = message_source.sender.id
await self.bot.set_message(from_user,message_source.message_chain.message_id,content)
async def send_message(

View File

@@ -1,4 +1,4 @@
semantic_version = "v3.4.11"
semantic_version = "v3.4.11.1"
debug_mode = False