🎨 webui优化

This commit is contained in:
HibiKier 2024-08-13 22:37:44 +08:00
parent b37e55648b
commit 2d0cee80c2
4 changed files with 123 additions and 119 deletions

View File

@ -1,6 +1,7 @@
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.message import run_postprocessor
from nonebot.plugin import PluginMetadata
@ -23,10 +24,17 @@ __plugin_meta__ = PluginMetadata(
@run_postprocessor
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:
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
if plugin_type == PluginType.NORMAL and matcher.plugin_name not in [
"update_info",

View File

@ -2,11 +2,7 @@ import asyncio
import nonebot
from fastapi import APIRouter, FastAPI
from nonebot.adapters.onebot.v11 import Bot, MessageEvent
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.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 ws_router as status_routes
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.system import router as system_router
from .auth import router as auth_router

View File

@ -1,19 +1,13 @@
import re
from typing import Literal
import nonebot
from fastapi import APIRouter
from nonebot.adapters.onebot.v11 import ActionFailed
from starlette.websockets import WebSocket, WebSocketDisconnect, WebSocketState
from tortoise.functions import Count
from zhenxun.configs.config import NICKNAME
from zhenxun.models.ban_console import BanConsole
from zhenxun.models.chat_history import ChatHistory
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_member_info import GroupInfoUser
from zhenxun.models.plugin_info import PluginInfo
from zhenxun.models.statistics import Statistics
from zhenxun.models.task_info import TaskInfo
@ -25,7 +19,6 @@ from zhenxun.utils.platform import PlatformUtils
from ....base_model import Result
from ....config import AVA_URL, GROUP_AVA_URL
from ....utils import authentication
from ...logs.log_manager import LOG_STORAGE
from .model import (
ClearRequest,
DeleteFriend,
@ -36,8 +29,6 @@ from .model import (
GroupResult,
HandleRequest,
LeaveGroup,
Message,
MessageItem,
Plugin,
ReqResult,
SendMessage,
@ -46,19 +37,8 @@ from .model import (
UserDetail,
)
ws_router = APIRouter()
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(
"/get_group_list", dependencies=[authentication()], description="获取群组列表"
@ -72,7 +52,6 @@ async def _(bot_id: str) -> Result:
return Result.warning_("指定Bot未连接...")
group_list_result = []
try:
group_info = {}
group_list = await bots[bot_id].get_group_list()
for g in group_list:
gid = g["group_id"]
@ -459,93 +438,3 @@ async def _(param: SendMessage) -> Result:
return Result.ok("发送成功!")
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

View 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())