mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2026-09-29 00:32:06 +08:00
perf👌: webui完善好友群组管理api,添加部分数据库管理接口
This commit is contained in:
@@ -17,7 +17,7 @@ from ....utils import authentication
|
|||||||
from .models.model import SqlModel, SqlText
|
from .models.model import SqlModel, SqlText
|
||||||
from .models.sql_log import SqlLog
|
from .models.sql_log import SqlLog
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter(prefix="/database")
|
||||||
|
|
||||||
|
|
||||||
driver: Driver = nonebot.get_driver()
|
driver: Driver = nonebot.get_driver()
|
||||||
@@ -26,6 +26,18 @@ driver: Driver = nonebot.get_driver()
|
|||||||
SQL_DICT = {}
|
SQL_DICT = {}
|
||||||
|
|
||||||
|
|
||||||
|
SELECT_TABLE_SQL = """
|
||||||
|
select a.tablename as name,d.description as desc from pg_tables a
|
||||||
|
left join pg_class c on relname=tablename
|
||||||
|
left join pg_description d on oid=objoid and objsubid=0 where a.schemaname = 'public'
|
||||||
|
"""
|
||||||
|
|
||||||
|
SELECT_TABLE_COLUMN_SQL = """
|
||||||
|
SELECT column_name, data_type, character_maximum_length as max_length, is_nullable
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_name = '{}';
|
||||||
|
"""
|
||||||
|
|
||||||
@driver.on_startup
|
@driver.on_startup
|
||||||
async def _():
|
async def _():
|
||||||
for matcher in get_matchers(True):
|
for matcher in get_matchers(True):
|
||||||
@@ -45,6 +57,18 @@ async def _():
|
|||||||
)
|
)
|
||||||
SQL_DICT[plugin_name] = SqlModel
|
SQL_DICT[plugin_name] = SqlModel
|
||||||
|
|
||||||
|
@router.get("/get_table_list", dependencies=[authentication()], description="获取数据库表")
|
||||||
|
async def _() -> Result:
|
||||||
|
db = Tortoise.get_connection("default")
|
||||||
|
query = await db.execute_query_dict(SELECT_TABLE_SQL)
|
||||||
|
return Result.ok(query)
|
||||||
|
|
||||||
|
@router.get("/get_table_column", dependencies=[authentication()], description="获取表字段")
|
||||||
|
async def _(table_name: str) -> Result:
|
||||||
|
db = Tortoise.get_connection("default")
|
||||||
|
print(SELECT_TABLE_COLUMN_SQL.format(table_name))
|
||||||
|
query = await db.execute_query_dict(SELECT_TABLE_COLUMN_SQL.format(table_name))
|
||||||
|
return Result.ok(query)
|
||||||
|
|
||||||
@router.post("/exec_sql", dependencies=[authentication()], description="执行sql")
|
@router.post("/exec_sql", dependencies=[authentication()], description="执行sql")
|
||||||
async def _(sql: SqlText, request: Request) -> Result:
|
async def _(sql: SqlText, request: Request) -> Result:
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ from .model import ActiveGroup, BaseInfo, ChatHistoryCount, HotPlugin
|
|||||||
run_time = time.time()
|
run_time = time.time()
|
||||||
|
|
||||||
ws_router = APIRouter()
|
ws_router = APIRouter()
|
||||||
router = APIRouter()
|
router = APIRouter(prefix="/main")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ async def _(date_type: Optional[QueryDateType] = None) -> Result:
|
|||||||
if date_type == QueryDateType.YEAR:
|
if date_type == QueryDateType.YEAR:
|
||||||
query = ChatHistory.filter(create_time__gte=now - timedelta(days=365))
|
query = ChatHistory.filter(create_time__gte=now - timedelta(days=365))
|
||||||
data_list = (
|
data_list = (
|
||||||
await query.annotate(count=Count("id"))
|
await query.annotate(count=Count("id")).filter(group_id__not_isnull=True)
|
||||||
.group_by("group_id").order_by("-count").limit(5)
|
.group_by("group_id").order_by("-count").limit(5)
|
||||||
.values_list("group_id", "count")
|
.values_list("group_id", "count")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ from .model import (
|
|||||||
HandleRequest,
|
HandleRequest,
|
||||||
LeaveGroup,
|
LeaveGroup,
|
||||||
Message,
|
Message,
|
||||||
|
MessageItem,
|
||||||
Plugin,
|
Plugin,
|
||||||
ReqResult,
|
ReqResult,
|
||||||
SendMessage,
|
SendMessage,
|
||||||
@@ -42,7 +43,7 @@ from .model import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
ws_router = APIRouter()
|
ws_router = APIRouter()
|
||||||
router = APIRouter()
|
router = APIRouter(prefix="/manage")
|
||||||
|
|
||||||
SUB_PATTERN = r"\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))"
|
SUB_PATTERN = r"\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))"
|
||||||
|
|
||||||
@@ -50,6 +51,8 @@ GROUP_PATTERN = r'.*?Message (-?\d*) from (\d*)@\[群:(\d*)] "(.*)"'
|
|||||||
|
|
||||||
PRIVATE_PATTERN = r'.*?Message (-?\d*) from (\d*) "(.*)"'
|
PRIVATE_PATTERN = r'.*?Message (-?\d*) from (\d*) "(.*)"'
|
||||||
|
|
||||||
|
IMAGE_PATTERN = r'\[CQ:image,.*,url=(.*);.*?\]'
|
||||||
|
|
||||||
@router.get("/get_group_list", dependencies=[authentication()], description="获取群组列表")
|
@router.get("/get_group_list", dependencies=[authentication()], description="获取群组列表")
|
||||||
async def _(bot_id: str) -> Result:
|
async def _(bot_id: str) -> Result:
|
||||||
"""
|
"""
|
||||||
@@ -323,8 +326,10 @@ async def _(bot_id: str, group_id: str) -> Result:
|
|||||||
like_plugin[name] = data[1]
|
like_plugin[name] = data[1]
|
||||||
close_plugins = []
|
close_plugins = []
|
||||||
for module in g.close_plugins:
|
for module in g.close_plugins:
|
||||||
plugin = Plugin(module=module, plugin_name=module)
|
module_ = module.replace(":super", "")
|
||||||
if plugin_data := plugin_data_manager.get(module):
|
is_super_block = module.endswith(":super")
|
||||||
|
plugin = Plugin(module=module_, plugin_name=module, is_super_block=is_super_block)
|
||||||
|
if plugin_data := plugin_data_manager.get(module_):
|
||||||
plugin.plugin_name = plugin_data.name
|
plugin.plugin_name = plugin_data.name
|
||||||
close_plugins.append(plugin)
|
close_plugins.append(plugin)
|
||||||
task_list = []
|
task_list = []
|
||||||
@@ -374,48 +379,71 @@ async def _(param: SendMessage) -> Result:
|
|||||||
|
|
||||||
MSG_LIST = []
|
MSG_LIST = []
|
||||||
|
|
||||||
|
ID2NAME = {}
|
||||||
|
|
||||||
|
|
||||||
|
async def message_handle(sub_log: str, type: Literal["private", "group"]):
|
||||||
|
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:
|
||||||
|
user = await FriendUser.filter(user_id=uid).first()
|
||||||
|
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:
|
||||||
|
user = await GroupInfoUser.filter(user_id=uid, group_id=gid).first()
|
||||||
|
ID2NAME[gid] = user.user_name or user.nickname
|
||||||
|
if msg_id in MSG_LIST:
|
||||||
|
return
|
||||||
|
MSG_LIST.append(msg_id)
|
||||||
|
messages = []
|
||||||
|
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,
|
||||||
|
user_id=uid,
|
||||||
|
group_id=gid,
|
||||||
|
message=messages,
|
||||||
|
name=ID2NAME[uid],
|
||||||
|
ava_url=AVA_URL.format(uid),
|
||||||
|
)
|
||||||
|
|
||||||
@ws_router.websocket("/chat")
|
@ws_router.websocket("/chat")
|
||||||
async def _(websocket: WebSocket, group_id: Optional[str] = None, user_id: Optional[str] = None):
|
async def _(websocket: WebSocket):
|
||||||
global MSG_LIST
|
|
||||||
await websocket.accept()
|
await websocket.accept()
|
||||||
|
|
||||||
async def log_listener(log: str):
|
async def log_listener(log: str):
|
||||||
|
global MSG_LIST, ID2NAME
|
||||||
sub_log = re.sub(SUB_PATTERN, "", log)
|
sub_log = re.sub(SUB_PATTERN, "", log)
|
||||||
|
img_list = re.findall(IMAGE_PATTERN, sub_log)
|
||||||
if "message.private.friend" in log:
|
if "message.private.friend" in log:
|
||||||
if r := re.search(PRIVATE_PATTERN, sub_log):
|
if message := await message_handle(sub_log, 'private'):
|
||||||
msg_id = r.group(1)
|
await websocket.send_json(message.dict())
|
||||||
uid = r.group(2)
|
|
||||||
msg = r.group(3)
|
|
||||||
user = await FriendUser.filter(user_id=user_id).first()
|
|
||||||
name = user.user_name
|
|
||||||
if uid and uid == user_id and msg_id not in MSG_LIST:
|
|
||||||
MSG_LIST.append(msg_id)
|
|
||||||
message = Message(
|
|
||||||
user_id=uid,
|
|
||||||
message=msg,
|
|
||||||
name=name,
|
|
||||||
ava_url=AVA_URL.format(uid)
|
|
||||||
)
|
|
||||||
await websocket.send_json(message.dict())
|
|
||||||
else:
|
else:
|
||||||
if r := re.search(GROUP_PATTERN, sub_log):
|
if r := re.search(GROUP_PATTERN, sub_log):
|
||||||
msg_id = r.group(1)
|
if message := await message_handle(sub_log, 'group'):
|
||||||
uid = r.group(2)
|
|
||||||
gid = r.group(3)
|
|
||||||
msg = r.group(4)
|
|
||||||
user = await GroupInfoUser.filter(user_id=uid, group_id=gid).first()
|
|
||||||
name = user.user_name or user.nickname
|
|
||||||
if gid and gid == group_id and msg_id not in MSG_LIST:
|
|
||||||
MSG_LIST.append(msg_id)
|
|
||||||
message = Message(
|
|
||||||
user_id=uid,
|
|
||||||
group_id=gid,
|
|
||||||
message=msg,
|
|
||||||
name=name,
|
|
||||||
ava_url=AVA_URL.format(uid)
|
|
||||||
)
|
|
||||||
await websocket.send_json(message.dict())
|
await websocket.send_json(message.dict())
|
||||||
|
if len(MSG_LIST) > 30:
|
||||||
|
MSG_LIST = MSG_LIST[-1:]
|
||||||
LOG_STORAGE.listeners.add(log_listener)
|
LOG_STORAGE.listeners.add(log_listener)
|
||||||
try:
|
try:
|
||||||
while websocket.client_state == WebSocketState.CONNECTED:
|
while websocket.client_state == WebSocketState.CONNECTED:
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ class Plugin(BaseModel):
|
|||||||
"""模块名"""
|
"""模块名"""
|
||||||
plugin_name: str
|
plugin_name: str
|
||||||
"""中文名"""
|
"""中文名"""
|
||||||
|
is_super_block: bool
|
||||||
|
"""是否超级用户禁用"""
|
||||||
|
|
||||||
|
|
||||||
class GroupResult(BaseModel):
|
class GroupResult(BaseModel):
|
||||||
@@ -227,23 +229,33 @@ class GroupDetail(BaseModel):
|
|||||||
task: List[Task]
|
task: List[Task]
|
||||||
"""被动列表"""
|
"""被动列表"""
|
||||||
|
|
||||||
|
class MessageItem(BaseModel):
|
||||||
|
|
||||||
|
type: str
|
||||||
|
"""消息类型"""
|
||||||
|
msg: str
|
||||||
|
"""内容"""
|
||||||
|
|
||||||
class Message(BaseModel):
|
class Message(BaseModel):
|
||||||
"""
|
"""
|
||||||
消息
|
消息
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
object_id: str
|
||||||
|
"""主体id user_id 或 group_id"""
|
||||||
user_id: str
|
user_id: str
|
||||||
"""用户id"""
|
"""用户id"""
|
||||||
group_id: Optional[str] = None
|
group_id: Optional[str] = None
|
||||||
"""群组id"""
|
"""群组id"""
|
||||||
message: str
|
message: List[MessageItem]
|
||||||
"""消息"""
|
"""消息"""
|
||||||
name: str
|
name: str
|
||||||
"""用户名称"""
|
"""用户名称"""
|
||||||
ava_url: str
|
ava_url: str
|
||||||
"""用户头像"""
|
"""用户头像"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SendMessage(BaseModel):
|
class SendMessage(BaseModel):
|
||||||
"""
|
"""
|
||||||
发送消息
|
发送消息
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import re
|
|||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
import cattrs
|
import cattrs
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter, Query
|
||||||
|
|
||||||
from configs.config import Config
|
from configs.config import Config
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
@@ -17,26 +17,26 @@ from .model import (
|
|||||||
PluginDetail,
|
PluginDetail,
|
||||||
PluginInfo,
|
PluginInfo,
|
||||||
PluginSwitch,
|
PluginSwitch,
|
||||||
UpdateConfig,
|
|
||||||
UpdatePlugin,
|
UpdatePlugin,
|
||||||
)
|
)
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter(prefix="/plugin")
|
||||||
|
|
||||||
|
|
||||||
@router.get("/get_plugin_list", dependencies=[authentication()], deprecated="获取插件列表")
|
@router.get("/get_plugin_list", dependencies=[authentication()], deprecated="获取插件列表")
|
||||||
def _(
|
def _(
|
||||||
plugin_type: PluginType, menu_type: Optional[str] = None
|
plugin_type: List[PluginType] = Query(None), menu_type: Optional[str] = None
|
||||||
) -> Result:
|
) -> Result:
|
||||||
"""
|
"""
|
||||||
获取插件列表
|
获取插件列表
|
||||||
:param plugin_type: 类型 normal, superuser, hidden, admin
|
:param plugin_type: 类型 normal, superuser, hidden, admin
|
||||||
|
:param menu_type: 菜单类型
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
plugin_list: List[PluginInfo] = []
|
plugin_list: List[PluginInfo] = []
|
||||||
for module in plugin_data_manager.keys():
|
for module in plugin_data_manager.keys():
|
||||||
plugin_data: Optional[PluginData] = plugin_data_manager[module]
|
plugin_data: Optional[PluginData] = plugin_data_manager[module]
|
||||||
if plugin_data and plugin_data.plugin_type == plugin_type:
|
if plugin_data and plugin_data.plugin_type in plugin_type:
|
||||||
setting = plugin_data.plugin_setting or PluginSetting()
|
setting = plugin_data.plugin_setting or PluginSetting()
|
||||||
plugin = plugin_data.plugin_status
|
plugin = plugin_data.plugin_status
|
||||||
menu_type_ = getattr(setting, "plugin_type", ["无"])[0]
|
menu_type_ = getattr(setting, "plugin_type", ["无"])[0]
|
||||||
|
|||||||
Reference in New Issue
Block a user