mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-15 14:22:55 +08:00
commit
c7e073baea
@ -122,7 +122,7 @@ PS: **ARM平台** 请使用全量版 同时 **如果你的机器 RAM < 1G 可
|
|||||||
|
|
||||||
```
|
```
|
||||||
# 获取代码
|
# 获取代码
|
||||||
git clone https://github.com/HibiKier/zhenxun.git
|
git clone https://github.com/HibiKier/zhenxun_bot.git
|
||||||
|
|
||||||
# 进入目录
|
# 进入目录
|
||||||
cd zhenxun_bot
|
cd zhenxun_bot
|
||||||
@ -135,6 +135,9 @@ poetry install # 安装依赖
|
|||||||
poetry shell # 进入虚拟环境
|
poetry shell # 进入虚拟环境
|
||||||
python bot.py
|
python bot.py
|
||||||
|
|
||||||
|
# 在Linux系统,你可能还需要运行此命令安装playwright依赖
|
||||||
|
playwright install-deps
|
||||||
|
|
||||||
# 首次后会在data目录下生成database.json和config.yaml文件
|
# 首次后会在data目录下生成database.json和config.yaml文件
|
||||||
# database.json用户配置数据库信息
|
# database.json用户配置数据库信息
|
||||||
# config.yaml用户配置插件
|
# config.yaml用户配置插件
|
||||||
@ -387,9 +390,9 @@ python bot.py
|
|||||||
|
|
||||||
<!-- ### 2024/1/25
|
<!-- ### 2024/1/25
|
||||||
|
|
||||||
* 重构webui -->
|
* 重构webui
|
||||||
|
|
||||||
<!-- ### 2023/12/28
|
### 2023/12/28
|
||||||
|
|
||||||
* 修复B站动态获取失败的时候,会发送空消息
|
* 修复B站动态获取失败的时候,会发送空消息
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
from nonebot.adapters import Bot
|
from nonebot.adapters import Bot, Event
|
||||||
|
from nonebot.adapters.onebot.v11 import PokeNotifyEvent
|
||||||
from nonebot.exception import IgnoredException
|
from nonebot.exception import IgnoredException
|
||||||
from nonebot.matcher import Matcher
|
from nonebot.matcher import Matcher
|
||||||
from nonebot_plugin_alconna import At, UniMsg
|
from nonebot_plugin_alconna import At, UniMsg
|
||||||
@ -183,6 +184,7 @@ class AuthChecker:
|
|||||||
async def auth(
|
async def auth(
|
||||||
self,
|
self,
|
||||||
matcher: Matcher,
|
matcher: Matcher,
|
||||||
|
event: Event,
|
||||||
bot: Bot,
|
bot: Bot,
|
||||||
session: EventSession,
|
session: EventSession,
|
||||||
message: UniMsg,
|
message: UniMsg,
|
||||||
@ -203,6 +205,9 @@ class AuthChecker:
|
|||||||
if not group_id:
|
if not group_id:
|
||||||
group_id = channel_id
|
group_id = channel_id
|
||||||
channel_id = None
|
channel_id = None
|
||||||
|
if matcher.type == "notice" and not isinstance(event, PokeNotifyEvent):
|
||||||
|
"""过滤除poke外的notice"""
|
||||||
|
return
|
||||||
if user_id and matcher.plugin and (module_path := matcher.plugin.module_name):
|
if user_id and matcher.plugin and (module_path := matcher.plugin.module_name):
|
||||||
try:
|
try:
|
||||||
user = await UserConsole.get_user(user_id, session.platform)
|
user = await UserConsole.get_user(user_id, session.platform)
|
||||||
@ -225,7 +230,7 @@ class AuthChecker:
|
|||||||
raise IsSuperuserException()
|
raise IsSuperuserException()
|
||||||
await self.auth_group(plugin, session, message)
|
await self.auth_group(plugin, session, message)
|
||||||
await self.auth_admin(plugin, session)
|
await self.auth_admin(plugin, session)
|
||||||
await self.auth_plugin(plugin, session)
|
await self.auth_plugin(plugin, session, event)
|
||||||
await self.auth_limit(plugin, session)
|
await self.auth_limit(plugin, session)
|
||||||
except IsSuperuserException:
|
except IsSuperuserException:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
@ -278,7 +283,9 @@ class AuthChecker:
|
|||||||
plugin.module, user_id, group_id, channel_id, session
|
plugin.module, user_id, group_id, channel_id, session
|
||||||
)
|
)
|
||||||
|
|
||||||
async def auth_plugin(self, plugin: PluginInfo, session: EventSession):
|
async def auth_plugin(
|
||||||
|
self, plugin: PluginInfo, session: EventSession, event: Event
|
||||||
|
):
|
||||||
"""插件状态
|
"""插件状态
|
||||||
|
|
||||||
参数:
|
参数:
|
||||||
@ -288,6 +295,7 @@ class AuthChecker:
|
|||||||
user_id = session.id1
|
user_id = session.id1
|
||||||
group_id = session.id3
|
group_id = session.id3
|
||||||
channel_id = session.id2
|
channel_id = session.id2
|
||||||
|
is_poke = isinstance(event, PokeNotifyEvent)
|
||||||
if not group_id:
|
if not group_id:
|
||||||
group_id = channel_id
|
group_id = channel_id
|
||||||
channel_id = None
|
channel_id = None
|
||||||
@ -297,7 +305,7 @@ class AuthChecker:
|
|||||||
group_id, plugin.module, channel_id
|
group_id, plugin.module, channel_id
|
||||||
):
|
):
|
||||||
"""超级用户群组插件状态"""
|
"""超级用户群组插件状态"""
|
||||||
if self._flmt_s.check(group_id or user_id):
|
if self._flmt_s.check(group_id or user_id) and not is_poke:
|
||||||
self._flmt_s.start_cd(group_id or user_id)
|
self._flmt_s.start_cd(group_id or user_id)
|
||||||
await MessageUtils.build_message(
|
await MessageUtils.build_message(
|
||||||
"超级管理员禁用了该群此功能..."
|
"超级管理员禁用了该群此功能..."
|
||||||
@ -312,7 +320,7 @@ class AuthChecker:
|
|||||||
group_id, plugin.module, channel_id
|
group_id, plugin.module, channel_id
|
||||||
):
|
):
|
||||||
"""群组插件状态"""
|
"""群组插件状态"""
|
||||||
if self._flmt_s.check(group_id or user_id):
|
if self._flmt_s.check(group_id or user_id) and not is_poke:
|
||||||
self._flmt_s.start_cd(group_id or user_id)
|
self._flmt_s.start_cd(group_id or user_id)
|
||||||
await MessageUtils.build_message("该群未开启此功能...").send(
|
await MessageUtils.build_message("该群未开启此功能...").send(
|
||||||
reply_to=True
|
reply_to=True
|
||||||
@ -326,7 +334,7 @@ class AuthChecker:
|
|||||||
if not plugin.status and plugin.block_type == BlockType.GROUP:
|
if not plugin.status and plugin.block_type == BlockType.GROUP:
|
||||||
"""全局群组禁用"""
|
"""全局群组禁用"""
|
||||||
try:
|
try:
|
||||||
if self._flmt_c.check(group_id):
|
if self._flmt_c.check(group_id) and not is_poke:
|
||||||
self._flmt_c.start_cd(group_id)
|
self._flmt_c.start_cd(group_id)
|
||||||
await MessageUtils.build_message(
|
await MessageUtils.build_message(
|
||||||
"该功能在群组中已被禁用..."
|
"该功能在群组中已被禁用..."
|
||||||
@ -345,7 +353,7 @@ class AuthChecker:
|
|||||||
if not plugin.status and plugin.block_type == BlockType.PRIVATE:
|
if not plugin.status and plugin.block_type == BlockType.PRIVATE:
|
||||||
"""全局私聊禁用"""
|
"""全局私聊禁用"""
|
||||||
try:
|
try:
|
||||||
if self._flmt_c.check(user_id):
|
if self._flmt_c.check(user_id) and not is_poke:
|
||||||
self._flmt_c.start_cd(user_id)
|
self._flmt_c.start_cd(user_id)
|
||||||
await MessageUtils.build_message(
|
await MessageUtils.build_message(
|
||||||
"该功能在私聊中已被禁用..."
|
"该功能在私聊中已被禁用..."
|
||||||
@ -365,14 +373,14 @@ class AuthChecker:
|
|||||||
if group_id:
|
if group_id:
|
||||||
if await GroupConsole.is_super_group(group_id, channel_id):
|
if await GroupConsole.is_super_group(group_id, channel_id):
|
||||||
raise IsSuperuserException()
|
raise IsSuperuserException()
|
||||||
if self._flmt_s.check(group_id or user_id):
|
|
||||||
self._flmt_s.start_cd(group_id or user_id)
|
|
||||||
await MessageUtils.build_message("全局未开启此功能...").send()
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"{plugin.name}({plugin.module}) 全局未开启此功能...",
|
f"{plugin.name}({plugin.module}) 全局未开启此功能...",
|
||||||
"HOOK",
|
"HOOK",
|
||||||
session=session,
|
session=session,
|
||||||
)
|
)
|
||||||
|
if self._flmt_s.check(group_id or user_id) and not is_poke:
|
||||||
|
self._flmt_s.start_cd(group_id or user_id)
|
||||||
|
await MessageUtils.build_message("全局未开启此功能...").send()
|
||||||
raise IgnoredException("全局未开启此功能...")
|
raise IgnoredException("全局未开启此功能...")
|
||||||
|
|
||||||
async def auth_admin(self, plugin: PluginInfo, session: EventSession):
|
async def auth_admin(self, plugin: PluginInfo, session: EventSession):
|
||||||
|
|||||||
@ -11,8 +11,16 @@ from ._auth_checker import LimitManage, checker
|
|||||||
|
|
||||||
# # 权限检测
|
# # 权限检测
|
||||||
@run_preprocessor
|
@run_preprocessor
|
||||||
async def _(matcher: Matcher, bot: Bot, session: EventSession, message: UniMsg):
|
async def _(
|
||||||
await checker.auth(matcher, bot, session, message)
|
matcher: Matcher, event: Event, bot: Bot, session: EventSession, message: UniMsg
|
||||||
|
):
|
||||||
|
await checker.auth(
|
||||||
|
matcher,
|
||||||
|
event,
|
||||||
|
bot,
|
||||||
|
session,
|
||||||
|
message,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# 解除命令block阻塞
|
# 解除命令block阻塞
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from nonebot.adapters import Bot
|
from nonebot.adapters import Bot, Event
|
||||||
|
from nonebot.adapters.onebot.v11 import PokeNotifyEvent
|
||||||
from nonebot.matcher import Matcher
|
from nonebot.matcher import Matcher
|
||||||
from nonebot.message import run_postprocessor
|
from nonebot.message import run_postprocessor
|
||||||
from nonebot.plugin import PluginMetadata
|
from nonebot.plugin import PluginMetadata
|
||||||
@ -23,10 +24,17 @@ __plugin_meta__ = PluginMetadata(
|
|||||||
|
|
||||||
@run_postprocessor
|
@run_postprocessor
|
||||||
async def _(
|
async def _(
|
||||||
matcher: Matcher, exception: Exception | None, bot: Bot, session: EventSession
|
matcher: Matcher,
|
||||||
|
exception: Exception | None,
|
||||||
|
bot: Bot,
|
||||||
|
session: EventSession,
|
||||||
|
event: Event,
|
||||||
):
|
):
|
||||||
|
if matcher.type == "notice" and not isinstance(event, PokeNotifyEvent):
|
||||||
|
"""过滤除poke外的notice"""
|
||||||
|
return
|
||||||
if session.id1:
|
if session.id1:
|
||||||
plugin = await PluginInfo.get_or_none(module=matcher.plugin_name)
|
plugin = await PluginInfo.get_or_none(module=matcher.module_name)
|
||||||
plugin_type = plugin.plugin_type if plugin else None
|
plugin_type = plugin.plugin_type if plugin else None
|
||||||
if plugin_type == PluginType.NORMAL and matcher.plugin_name not in [
|
if plugin_type == PluginType.NORMAL and matcher.plugin_name not in [
|
||||||
"update_info",
|
"update_info",
|
||||||
|
|||||||
@ -2,11 +2,7 @@ import asyncio
|
|||||||
|
|
||||||
import nonebot
|
import nonebot
|
||||||
from fastapi import APIRouter, FastAPI
|
from fastapi import APIRouter, FastAPI
|
||||||
from nonebot.adapters.onebot.v11 import Bot, MessageEvent
|
|
||||||
from nonebot.log import default_filter, default_format
|
from nonebot.log import default_filter, default_format
|
||||||
from nonebot.matcher import Matcher
|
|
||||||
from nonebot.message import run_preprocessor
|
|
||||||
from nonebot.typing import T_State
|
|
||||||
|
|
||||||
from zhenxun.configs.config import Config as gConfig
|
from zhenxun.configs.config import Config as gConfig
|
||||||
from zhenxun.services.log import logger, logger_
|
from zhenxun.services.log import logger, logger_
|
||||||
@ -17,7 +13,7 @@ from .api.tabs.database import router as database_router
|
|||||||
from .api.tabs.main import router as main_router
|
from .api.tabs.main import router as main_router
|
||||||
from .api.tabs.main import ws_router as status_routes
|
from .api.tabs.main import ws_router as status_routes
|
||||||
from .api.tabs.manage import router as manage_router
|
from .api.tabs.manage import router as manage_router
|
||||||
from .api.tabs.manage import ws_router as chat_routes
|
from .api.tabs.manage.chat import ws_router as chat_routes
|
||||||
from .api.tabs.plugin_manage import router as plugin_router
|
from .api.tabs.plugin_manage import router as plugin_router
|
||||||
from .api.tabs.system import router as system_router
|
from .api.tabs.system import router as system_router
|
||||||
from .auth import router as auth_router
|
from .auth import router as auth_router
|
||||||
|
|||||||
@ -1,19 +1,13 @@
|
|||||||
import re
|
|
||||||
from typing import Literal
|
|
||||||
|
|
||||||
import nonebot
|
import nonebot
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
from nonebot.adapters.onebot.v11 import ActionFailed
|
from nonebot.adapters.onebot.v11 import ActionFailed
|
||||||
from starlette.websockets import WebSocket, WebSocketDisconnect, WebSocketState
|
|
||||||
from tortoise.functions import Count
|
from tortoise.functions import Count
|
||||||
|
|
||||||
from zhenxun.configs.config import NICKNAME
|
from zhenxun.configs.config import NICKNAME
|
||||||
from zhenxun.models.ban_console import BanConsole
|
from zhenxun.models.ban_console import BanConsole
|
||||||
from zhenxun.models.chat_history import ChatHistory
|
from zhenxun.models.chat_history import ChatHistory
|
||||||
from zhenxun.models.fg_request import FgRequest
|
from zhenxun.models.fg_request import FgRequest
|
||||||
from zhenxun.models.friend_user import FriendUser
|
|
||||||
from zhenxun.models.group_console import GroupConsole
|
from zhenxun.models.group_console import GroupConsole
|
||||||
from zhenxun.models.group_member_info import GroupInfoUser
|
|
||||||
from zhenxun.models.plugin_info import PluginInfo
|
from zhenxun.models.plugin_info import PluginInfo
|
||||||
from zhenxun.models.statistics import Statistics
|
from zhenxun.models.statistics import Statistics
|
||||||
from zhenxun.models.task_info import TaskInfo
|
from zhenxun.models.task_info import TaskInfo
|
||||||
@ -25,7 +19,6 @@ from zhenxun.utils.platform import PlatformUtils
|
|||||||
from ....base_model import Result
|
from ....base_model import Result
|
||||||
from ....config import AVA_URL, GROUP_AVA_URL
|
from ....config import AVA_URL, GROUP_AVA_URL
|
||||||
from ....utils import authentication
|
from ....utils import authentication
|
||||||
from ...logs.log_manager import LOG_STORAGE
|
|
||||||
from .model import (
|
from .model import (
|
||||||
ClearRequest,
|
ClearRequest,
|
||||||
DeleteFriend,
|
DeleteFriend,
|
||||||
@ -36,8 +29,6 @@ from .model import (
|
|||||||
GroupResult,
|
GroupResult,
|
||||||
HandleRequest,
|
HandleRequest,
|
||||||
LeaveGroup,
|
LeaveGroup,
|
||||||
Message,
|
|
||||||
MessageItem,
|
|
||||||
Plugin,
|
Plugin,
|
||||||
ReqResult,
|
ReqResult,
|
||||||
SendMessage,
|
SendMessage,
|
||||||
@ -46,19 +37,8 @@ from .model import (
|
|||||||
UserDetail,
|
UserDetail,
|
||||||
)
|
)
|
||||||
|
|
||||||
ws_router = APIRouter()
|
|
||||||
router = APIRouter(prefix="/manage")
|
router = APIRouter(prefix="/manage")
|
||||||
|
|
||||||
SUB_PATTERN = r"\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))"
|
|
||||||
|
|
||||||
GROUP_PATTERN = r".*?Message (-?\d*) from (\d*)@\[群:(\d*)] '(.*)'"
|
|
||||||
|
|
||||||
PRIVATE_PATTERN = r".*?Message (-?\d*) from (\d*) '(.*)'"
|
|
||||||
|
|
||||||
AT_PATTERN = r"\[CQ:at,qq=(.*)\]"
|
|
||||||
|
|
||||||
IMAGE_PATTERN = r"\[image:file=.*,url=(.*);.*?\]"
|
|
||||||
|
|
||||||
|
|
||||||
@router.get(
|
@router.get(
|
||||||
"/get_group_list", dependencies=[authentication()], description="获取群组列表"
|
"/get_group_list", dependencies=[authentication()], description="获取群组列表"
|
||||||
@ -72,7 +52,6 @@ async def _(bot_id: str) -> Result:
|
|||||||
return Result.warning_("指定Bot未连接...")
|
return Result.warning_("指定Bot未连接...")
|
||||||
group_list_result = []
|
group_list_result = []
|
||||||
try:
|
try:
|
||||||
group_info = {}
|
|
||||||
group_list = await bots[bot_id].get_group_list()
|
group_list = await bots[bot_id].get_group_list()
|
||||||
for g in group_list:
|
for g in group_list:
|
||||||
gid = g["group_id"]
|
gid = g["group_id"]
|
||||||
@ -459,93 +438,3 @@ async def _(param: SendMessage) -> Result:
|
|||||||
return Result.ok("发送成功!")
|
return Result.ok("发送成功!")
|
||||||
return Result.warning_("指定Bot未连接...")
|
return Result.warning_("指定Bot未连接...")
|
||||||
return Result.warning_("无Bot连接...")
|
return Result.warning_("无Bot连接...")
|
||||||
|
|
||||||
|
|
||||||
MSG_LIST = []
|
|
||||||
|
|
||||||
ID2NAME = {}
|
|
||||||
|
|
||||||
|
|
||||||
async def message_handle(
|
|
||||||
sub_log: str, type: Literal["private", "group"]
|
|
||||||
) -> Message | None:
|
|
||||||
global MSG_LIST, ID2NAME
|
|
||||||
pattern = PRIVATE_PATTERN if type == "private" else GROUP_PATTERN
|
|
||||||
msg_id = None
|
|
||||||
uid = None
|
|
||||||
gid = None
|
|
||||||
msg = None
|
|
||||||
img_list = re.findall(IMAGE_PATTERN, sub_log)
|
|
||||||
if r := re.search(pattern, sub_log):
|
|
||||||
if type == "private":
|
|
||||||
msg_id = r.group(1)
|
|
||||||
uid = r.group(2)
|
|
||||||
msg = r.group(3)
|
|
||||||
if uid not in ID2NAME:
|
|
||||||
if user := await FriendUser.get_or_none(user_id=uid):
|
|
||||||
ID2NAME[uid] = user.user_name or user.nickname
|
|
||||||
else:
|
|
||||||
msg_id = r.group(1)
|
|
||||||
uid = r.group(2)
|
|
||||||
gid = r.group(3)
|
|
||||||
msg = r.group(4)
|
|
||||||
if gid not in ID2NAME:
|
|
||||||
if user := await GroupInfoUser.get_or_none(user_id=uid, group_id=gid):
|
|
||||||
ID2NAME[uid] = user.user_name or user.nickname
|
|
||||||
if at_list := re.findall(AT_PATTERN, msg):
|
|
||||||
user_list = await GroupInfoUser.filter(
|
|
||||||
user_id__in=at_list, group_id=gid
|
|
||||||
).all()
|
|
||||||
id2name = {u.user_id: (u.user_name or u.nickname) for u in user_list}
|
|
||||||
for qq in at_list:
|
|
||||||
msg = re.sub(rf"\[CQ:at,qq={qq}\]", f"@{id2name[qq] or ''}", msg)
|
|
||||||
if msg_id in MSG_LIST:
|
|
||||||
return
|
|
||||||
MSG_LIST.append(msg_id)
|
|
||||||
messages = []
|
|
||||||
if msg and uid:
|
|
||||||
rep = re.split(r"\[CQ:image.*\]", msg)
|
|
||||||
if img_list:
|
|
||||||
for i in range(len(rep)):
|
|
||||||
messages.append(MessageItem(type="text", msg=rep[i]))
|
|
||||||
if i < len(img_list):
|
|
||||||
messages.append(MessageItem(type="img", msg=img_list[i]))
|
|
||||||
else:
|
|
||||||
messages = [MessageItem(type="text", msg=x) for x in rep]
|
|
||||||
return Message(
|
|
||||||
object_id=uid if type == "private" else gid, # type: ignore
|
|
||||||
user_id=uid,
|
|
||||||
group_id=gid,
|
|
||||||
message=messages,
|
|
||||||
name=ID2NAME.get(uid) or "",
|
|
||||||
ava_url=AVA_URL.format(uid),
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
@ws_router.websocket("/chat")
|
|
||||||
async def _(websocket: WebSocket):
|
|
||||||
await websocket.accept()
|
|
||||||
|
|
||||||
async def log_listener(log: str):
|
|
||||||
global MSG_LIST, ID2NAME
|
|
||||||
sub_log = re.sub(SUB_PATTERN, "", log)
|
|
||||||
if "message.private.friend" in log:
|
|
||||||
if message := await message_handle(sub_log, "private"):
|
|
||||||
await websocket.send_json(message.dict())
|
|
||||||
else:
|
|
||||||
if r := re.search(GROUP_PATTERN, sub_log):
|
|
||||||
if message := await message_handle(sub_log, "group"):
|
|
||||||
await websocket.send_json(message.dict())
|
|
||||||
if len(MSG_LIST) > 30:
|
|
||||||
MSG_LIST = MSG_LIST[-1:]
|
|
||||||
|
|
||||||
LOG_STORAGE.listeners.add(log_listener)
|
|
||||||
try:
|
|
||||||
while websocket.client_state == WebSocketState.CONNECTED:
|
|
||||||
recv = await websocket.receive()
|
|
||||||
except WebSocketDisconnect:
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
LOG_STORAGE.listeners.remove(log_listener)
|
|
||||||
return
|
|
||||||
|
|||||||
111
zhenxun/plugins/web_ui/api/tabs/manage/chat.py
Normal file
111
zhenxun/plugins/web_ui/api/tabs/manage/chat.py
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import re
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
|
import nonebot
|
||||||
|
from fastapi import APIRouter
|
||||||
|
from nonebot import on_message
|
||||||
|
from nonebot.adapters.onebot.v11 import MessageEvent
|
||||||
|
from nonebot_plugin_alconna import At, Emoji, Hyper, Image, Text, UniMessage, UniMsg
|
||||||
|
from nonebot_plugin_session import EventSession
|
||||||
|
from starlette.websockets import WebSocket, WebSocketDisconnect, WebSocketState
|
||||||
|
|
||||||
|
from zhenxun.models.friend_user import FriendUser
|
||||||
|
from zhenxun.models.group_console import GroupConsole
|
||||||
|
from zhenxun.models.group_member_info import GroupInfoUser
|
||||||
|
from zhenxun.utils.depends import UserName
|
||||||
|
|
||||||
|
from ....config import AVA_URL, GROUP_AVA_URL
|
||||||
|
from .model import Message, MessageItem
|
||||||
|
|
||||||
|
driver = nonebot.get_driver()
|
||||||
|
|
||||||
|
ws_conn: WebSocket | None = None
|
||||||
|
|
||||||
|
ID2NAME = {}
|
||||||
|
|
||||||
|
ID_LIST = []
|
||||||
|
|
||||||
|
ws_router = APIRouter()
|
||||||
|
|
||||||
|
matcher = on_message(block=False, priority=1)
|
||||||
|
|
||||||
|
|
||||||
|
@driver.on_shutdown
|
||||||
|
async def _():
|
||||||
|
if ws_conn:
|
||||||
|
await ws_conn.close()
|
||||||
|
|
||||||
|
|
||||||
|
@ws_router.websocket("/chat")
|
||||||
|
async def _(websocket: WebSocket):
|
||||||
|
global ws_conn
|
||||||
|
await websocket.accept()
|
||||||
|
if not ws_conn:
|
||||||
|
ws_conn = websocket
|
||||||
|
try:
|
||||||
|
while websocket.client_state == WebSocketState.CONNECTED:
|
||||||
|
recv = await websocket.receive()
|
||||||
|
except WebSocketDisconnect:
|
||||||
|
ws_conn = None
|
||||||
|
|
||||||
|
|
||||||
|
async def message_handle(
|
||||||
|
message: UniMsg,
|
||||||
|
group_id: str | None,
|
||||||
|
):
|
||||||
|
messages = []
|
||||||
|
for m in message:
|
||||||
|
if isinstance(m, (Text, str)):
|
||||||
|
messages.append(MessageItem(type="text", msg=str(m)))
|
||||||
|
elif isinstance(m, Image):
|
||||||
|
if m.url:
|
||||||
|
messages.append(MessageItem(type="img", msg=m.url))
|
||||||
|
elif isinstance(m, At):
|
||||||
|
if group_id:
|
||||||
|
if m.target == "0":
|
||||||
|
uname = "全体成员"
|
||||||
|
else:
|
||||||
|
uname = m.target
|
||||||
|
if group_id not in ID2NAME:
|
||||||
|
ID2NAME[group_id] = {}
|
||||||
|
if m.target in ID2NAME[group_id]:
|
||||||
|
uname = ID2NAME[group_id][m.target]
|
||||||
|
else:
|
||||||
|
if group_user := await GroupInfoUser.get_or_none(
|
||||||
|
user_id=m.target, group_id=group_id
|
||||||
|
):
|
||||||
|
uname = group_user.user_name
|
||||||
|
if m.target not in ID2NAME[group_id]:
|
||||||
|
ID2NAME[group_id][m.target] = uname
|
||||||
|
messages.append(MessageItem(type="at", msg=f"@{uname}"))
|
||||||
|
# elif isinstance(m, Emoji):
|
||||||
|
# messages.append(MessageItem(type="text", msg=f"[emoji]"))
|
||||||
|
elif isinstance(m, Hyper):
|
||||||
|
messages.append(MessageItem(type="text", msg=f"[分享消息]"))
|
||||||
|
return messages
|
||||||
|
|
||||||
|
|
||||||
|
@matcher.handle()
|
||||||
|
async def _(
|
||||||
|
message: UniMsg, event: MessageEvent, session: EventSession, uname: str = UserName()
|
||||||
|
):
|
||||||
|
global ws_conn, ID2NAME, ID_LIST
|
||||||
|
uid = session.id1
|
||||||
|
gid = session.id3 or session.id2
|
||||||
|
if ws_conn and uid:
|
||||||
|
msg_id = event.message_id
|
||||||
|
if msg_id in ID_LIST:
|
||||||
|
return
|
||||||
|
ID_LIST.append(msg_id)
|
||||||
|
if len(ID_LIST) > 50:
|
||||||
|
ID_LIST = ID_LIST[40:]
|
||||||
|
messages = await message_handle(message, gid)
|
||||||
|
data = Message(
|
||||||
|
object_id=gid or uid,
|
||||||
|
user_id=uid,
|
||||||
|
group_id=gid,
|
||||||
|
message=messages,
|
||||||
|
name=uname,
|
||||||
|
ava_url=AVA_URL.format(uid),
|
||||||
|
)
|
||||||
|
await ws_conn.send_json(data.dict())
|
||||||
Loading…
Reference in New Issue
Block a user