mirror of
https://github.com/Genshin-bots/gsuid_core.git
synced 2025-05-12 06:55:49 +08:00
✨ 使大部分功能可用、修改部分配置
This commit is contained in:
parent
706bb59abc
commit
eb8789c823
2
.gitignore
vendored
2
.gitignore
vendored
@ -663,3 +663,5 @@ FodyWeavers.xsd
|
||||
# End of https://www.toptal.com/developers/gitignore/api/visualstudio,visualstudiocode,jetbrains+all,python,data
|
||||
|
||||
config.json
|
||||
res_data
|
||||
GsData.db
|
||||
|
@ -41,7 +41,7 @@ poetry run python core.py
|
||||
import asyncio
|
||||
|
||||
from gsuid_core.sv import SL, SV
|
||||
from gsuid_core.server import Bot
|
||||
from gsuid_core.bot import Bot
|
||||
from gsuid_core.models import MessageContent
|
||||
|
||||
|
||||
@ -52,7 +52,7 @@ async def get_switch_msg(bot: Bot, msg: MessageContent):
|
||||
im = await process(name) # 自己的业务逻辑
|
||||
await bot.logger.info('正在进行[关闭/开启开关]') # 发送loger
|
||||
await bot.send(im) # 发送消息
|
||||
|
||||
|
||||
sv=SV(
|
||||
name='复杂的服务', # 定义一组服务`开关`,
|
||||
permission=3, # 权限 0为master,1为superuser,2为群的群主&管理员,3为普通
|
||||
|
49
gsuid_core/bot.py
Normal file
49
gsuid_core/bot.py
Normal file
@ -0,0 +1,49 @@
|
||||
import asyncio
|
||||
from typing import List, Union, Optional
|
||||
|
||||
from logger import logger
|
||||
from fastapi import WebSocket
|
||||
from gs_logger import GsLogger
|
||||
from segment import MessageSegment
|
||||
from msgspec import json as msgjson
|
||||
from models import Message, MessageSend
|
||||
|
||||
|
||||
class Bot:
|
||||
def __init__(self, _id: str, ws: WebSocket):
|
||||
self.bot_id = _id
|
||||
self.bot = ws
|
||||
self.logger = GsLogger(self.bot_id, ws)
|
||||
self.queue = asyncio.queues.Queue()
|
||||
self.background_tasks = set()
|
||||
self.user_id: Optional[str] = None
|
||||
self.group_id: Optional[str] = None
|
||||
self.user_type: Optional[str] = None
|
||||
|
||||
async def send(self, message: Union[Message, List[Message], str, bytes]):
|
||||
if isinstance(message, Message):
|
||||
message = [message]
|
||||
elif isinstance(message, str):
|
||||
if message.startswith('base64://'):
|
||||
message = [MessageSegment.image(message)]
|
||||
else:
|
||||
message = [MessageSegment.text(message)]
|
||||
elif isinstance(message, bytes):
|
||||
message = [MessageSegment.image(message)]
|
||||
send = MessageSend(
|
||||
content=message,
|
||||
bot_id=self.bot_id,
|
||||
target_type=self.user_type,
|
||||
target_id=self.group_id if self.group_id else self.user_id,
|
||||
)
|
||||
logger.info(f'[发送消息] {send}')
|
||||
await self.bot.send_bytes(msgjson.encode(send))
|
||||
|
||||
async def _process(self):
|
||||
while True:
|
||||
data = await self.queue.get()
|
||||
task = asyncio.create_task(data)
|
||||
self.background_tasks.add(task)
|
||||
task.add_done_callback(
|
||||
lambda _: self.background_tasks.discard(task)
|
||||
)
|
@ -36,8 +36,9 @@ class GsClient:
|
||||
intent = await self._input()
|
||||
msg = MessageReceive(
|
||||
bot_id='Nonebot',
|
||||
user_type='group',
|
||||
group_id='123456789',
|
||||
user_type='DIRECT',
|
||||
user_pm=2,
|
||||
group_id=None,
|
||||
user_id='5253123',
|
||||
content=[Message(type='text', data=intent)],
|
||||
)
|
||||
|
@ -1,7 +1,7 @@
|
||||
import asyncio
|
||||
|
||||
import uvicorn
|
||||
from server import gss
|
||||
from gss import gss
|
||||
from config import core_config
|
||||
from handler import handle_event
|
||||
from models import MessageReceive
|
||||
|
42
gsuid_core/gs_logger.py
Normal file
42
gsuid_core/gs_logger.py
Normal file
@ -0,0 +1,42 @@
|
||||
from typing import Literal
|
||||
|
||||
from fastapi import WebSocket
|
||||
from models import MessageSend
|
||||
from segment import MessageSegment
|
||||
from msgspec import json as msgjson
|
||||
|
||||
|
||||
class GsLogger:
|
||||
def __init__(self, bot_id: str, ws: WebSocket):
|
||||
self.bot_id = bot_id
|
||||
self.bot = ws
|
||||
|
||||
def get_msg_send(
|
||||
self, type: Literal['INFO', 'WARNING', 'ERROR', 'SUCCESS'], msg: str
|
||||
):
|
||||
return MessageSend(
|
||||
content=[MessageSegment.log(type, msg)],
|
||||
bot_id=self.bot_id,
|
||||
target_type=None,
|
||||
target_id=None,
|
||||
)
|
||||
|
||||
async def info(self, msg: str):
|
||||
await self.bot.send_bytes(
|
||||
msgjson.encode(self.get_msg_send('INFO', msg))
|
||||
)
|
||||
|
||||
async def warning(self, msg: str):
|
||||
await self.bot.send_bytes(
|
||||
msgjson.encode(self.get_msg_send('WARNING', msg))
|
||||
)
|
||||
|
||||
async def error(self, msg: str):
|
||||
await self.bot.send_bytes(
|
||||
msgjson.encode(self.get_msg_send('ERROR', msg))
|
||||
)
|
||||
|
||||
async def success(self, msg: str):
|
||||
await self.bot.send_bytes(
|
||||
msgjson.encode(self.get_msg_send('SUCCESS', msg))
|
||||
)
|
6
gsuid_core/gss.py
Normal file
6
gsuid_core/gss.py
Normal file
@ -0,0 +1,6 @@
|
||||
from server import GsServer
|
||||
|
||||
gss = GsServer()
|
||||
if not gss.is_load:
|
||||
gss.is_load = True
|
||||
gss.load_plugins()
|
@ -1,6 +1,6 @@
|
||||
import asyncio
|
||||
|
||||
from server import Bot
|
||||
from bot import Bot
|
||||
from trigger import Trigger
|
||||
from config import core_config
|
||||
from models import MessageContent, MessageReceive
|
||||
@ -50,6 +50,11 @@ async def handle_event(ws: Bot, msg: MessageReceive):
|
||||
SL.lst[sv].enabled
|
||||
and user_pm <= SL.lst[sv].permission
|
||||
and msg.group_id not in SL.lst[sv].black_list
|
||||
and True
|
||||
if SL.lst[sv].area == 'ALL'
|
||||
or (msg.group_id and SL.lst[sv].area == 'GROUP')
|
||||
or (not msg.group_id and SL.lst[sv].area == 'DIRECT')
|
||||
else False
|
||||
)
|
||||
]
|
||||
await asyncio.gather(*pending, return_exceptions=True)
|
||||
|
19
gsuid_core/hook.py
Normal file
19
gsuid_core/hook.py
Normal file
@ -0,0 +1,19 @@
|
||||
from functools import wraps
|
||||
from typing import Callable, Optional
|
||||
|
||||
from gsuid_core.server import gss
|
||||
from gsuid_core.logger import logger
|
||||
|
||||
|
||||
def on_bot_connect():
|
||||
def deco(func: Callable) -> Callable:
|
||||
gss.bot_connect_def.append(func)
|
||||
|
||||
@wraps(func)
|
||||
async def wrapper(*args, **kwargs) -> Optional[Callable]:
|
||||
logger.info('@on_bot_connect已成功调用...')
|
||||
return await func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
return deco
|
22
gsuid_core/logger.py
Normal file
22
gsuid_core/logger.py
Normal file
@ -0,0 +1,22 @@
|
||||
import logging
|
||||
|
||||
import rollbar
|
||||
from rollbar.logger import RollbarHandler
|
||||
|
||||
# Initialize Rollbar SDK with your server-side access token
|
||||
rollbar.init(
|
||||
'ACCESS_TOKEN',
|
||||
environment='staging',
|
||||
handler='async',
|
||||
)
|
||||
|
||||
# Set root logger to log DEBUG and above
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
# Report ERROR and above to Rollbar
|
||||
rollbar_handler = RollbarHandler()
|
||||
rollbar_handler.setLevel(logging.ERROR)
|
||||
|
||||
# Attach Rollbar handler to the root logger
|
||||
logger.addHandler(rollbar_handler)
|
@ -8,19 +8,19 @@ class Message(Struct):
|
||||
data: Optional[Any] = None
|
||||
|
||||
|
||||
class MessageReceive(Struct):
|
||||
class MessageReceive(Struct, frozen=True):
|
||||
bot_id: str = 'Bot'
|
||||
user_type: Optional[str] = None
|
||||
group_id: Optional[str] = None
|
||||
user_id: Optional[str] = None
|
||||
user_id: str = ''
|
||||
user_pm: int = 3
|
||||
content: List[Message] = []
|
||||
|
||||
|
||||
class MessageContent(Struct):
|
||||
raw: Optional[MessageReceive] = None
|
||||
raw: MessageReceive = MessageReceive()
|
||||
raw_text: str = ''
|
||||
command: Optional[str] = None
|
||||
command: str = ''
|
||||
text: str = ''
|
||||
image: Optional[str] = None
|
||||
at: Optional[str] = None
|
||||
|
@ -2,94 +2,31 @@ import sys
|
||||
import asyncio
|
||||
import importlib
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Union, Literal, Optional
|
||||
from typing import Dict, Callable
|
||||
|
||||
from bot import Bot
|
||||
from logger import logger
|
||||
from fastapi import WebSocket
|
||||
from segment import MessageSegment
|
||||
from msgspec import json as msgjson
|
||||
from models import Message, MessageSend
|
||||
|
||||
sys.path.append(str(Path(__file__).parents[1]))
|
||||
|
||||
|
||||
class Bot:
|
||||
def __init__(self, _id: str):
|
||||
self.bot_id = _id
|
||||
self.bot = gss.active_bot[_id]
|
||||
self.logger = GsLogger(self.bot_id)
|
||||
self.queue = asyncio.queues.Queue()
|
||||
self.background_tasks = set()
|
||||
self.user_id: Optional[str] = None
|
||||
self.group_id: Optional[str] = None
|
||||
self.user_type: Optional[str] = None
|
||||
|
||||
async def send(self, message: Union[Message, List[Message], str]):
|
||||
if isinstance(message, Message):
|
||||
message = [message]
|
||||
elif isinstance(message, str):
|
||||
if message.startswith('base64://'):
|
||||
message = [MessageSegment.image(message)]
|
||||
else:
|
||||
message = [MessageSegment.text(message)]
|
||||
send = MessageSend(
|
||||
content=message,
|
||||
bot_id=self.bot_id,
|
||||
target_type=self.user_type,
|
||||
target_id=self.group_id if self.group_id else self.user_id,
|
||||
)
|
||||
print(f'[发送消息] {send}')
|
||||
await self.bot.send_bytes(msgjson.encode(send))
|
||||
|
||||
async def _process(self):
|
||||
while True:
|
||||
data = await self.queue.get()
|
||||
task = asyncio.create_task(data)
|
||||
self.background_tasks.add(task)
|
||||
task.add_done_callback(
|
||||
lambda _: self.background_tasks.discard(task)
|
||||
)
|
||||
|
||||
|
||||
class GsLogger:
|
||||
def __init__(self, bot_id: str):
|
||||
self.bot_id = bot_id
|
||||
self.bot = gss.active_bot[bot_id]
|
||||
|
||||
def get_msg_send(
|
||||
self, type: Literal['INFO', 'WARNING', 'ERROR', 'SUCCESS'], msg: str
|
||||
):
|
||||
return MessageSend(
|
||||
content=[MessageSegment.log(type, msg)],
|
||||
bot_id=self.bot_id,
|
||||
target_type=None,
|
||||
target_id=None,
|
||||
)
|
||||
|
||||
async def info(self, msg: str):
|
||||
await self.bot.send_bytes(
|
||||
msgjson.encode(self.get_msg_send('INFO', msg))
|
||||
)
|
||||
|
||||
async def warning(self, msg: str):
|
||||
await self.bot.send_bytes(
|
||||
msgjson.encode(self.get_msg_send('WARNING', msg))
|
||||
)
|
||||
|
||||
async def error(self, msg: str):
|
||||
await self.bot.send_bytes(
|
||||
msgjson.encode(self.get_msg_send('ERROR', msg))
|
||||
)
|
||||
|
||||
async def success(self, msg: str):
|
||||
await self.bot.send_bytes(
|
||||
msgjson.encode(self.get_msg_send('SUCCESS', msg))
|
||||
)
|
||||
|
||||
|
||||
class GsServer:
|
||||
_instance = None
|
||||
is_initialized = False
|
||||
is_load = False
|
||||
bot_connect_def = set()
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
# 判断sv是否已经被初始化
|
||||
if cls._instance is None:
|
||||
cls._instance = super().__new__(cls)
|
||||
return cls._instance
|
||||
|
||||
def __init__(self):
|
||||
self.active_bot: Dict[str, WebSocket] = {}
|
||||
self.load_plugins()
|
||||
if not self.is_initialized:
|
||||
self.active_bot: Dict[str, WebSocket] = {}
|
||||
self.is_initialized = True
|
||||
|
||||
def load_plugins(self):
|
||||
sys.path.append(str(Path(__file__).parents[1]))
|
||||
@ -121,12 +58,14 @@ class GsServer:
|
||||
async def connect(self, websocket: WebSocket, bot_id: str) -> Bot:
|
||||
await websocket.accept()
|
||||
self.active_bot[bot_id] = websocket
|
||||
print(f'{bot_id}已连接!')
|
||||
return Bot(bot_id)
|
||||
logger.info(f'{bot_id}已连接!')
|
||||
_task = [_def() for _def in self.bot_connect_def]
|
||||
asyncio.gather(*_task)
|
||||
return Bot(bot_id, websocket)
|
||||
|
||||
def disconnect(self, bot_id: str):
|
||||
del self.active_bot[bot_id]
|
||||
print(f'{bot_id}已中断!')
|
||||
logger.warning(f'{bot_id}已中断!')
|
||||
|
||||
async def send(self, message: str, bot_id: str):
|
||||
await self.active_bot[bot_id].send_text(message)
|
||||
@ -135,5 +74,7 @@ class GsServer:
|
||||
for bot_id in self.active_bot:
|
||||
await self.send(message, bot_id)
|
||||
|
||||
|
||||
gss = GsServer()
|
||||
@classmethod
|
||||
def on_bot_connect(cls, func: Callable):
|
||||
cls.bot_connect_def.add(func)
|
||||
return func
|
||||
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
from functools import wraps
|
||||
from typing import Dict, List, Tuple, Union, Literal, Callable, Optional
|
||||
|
||||
from logger import logger
|
||||
from trigger import Trigger
|
||||
from config import core_config
|
||||
|
||||
@ -23,7 +24,7 @@ config_sv = core_config.get_config('sv')
|
||||
class SV:
|
||||
is_initialized = False
|
||||
|
||||
def __new__(cls, *args):
|
||||
def __new__(cls, *args, **kwargs):
|
||||
# 判断sv是否已经被初始化
|
||||
if args[0] in SL.lst:
|
||||
return SL.lst[args[0]]
|
||||
@ -34,14 +35,15 @@ class SV:
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
name: str = '',
|
||||
permission: int = 3,
|
||||
priority: int = 5,
|
||||
enabled: bool = True,
|
||||
area: Literal['GROUP', 'DIRECT', 'ALL'] = 'ALL',
|
||||
black_list: List = [],
|
||||
):
|
||||
if not self.is_initialized:
|
||||
print(f'【{name}】模块初始化中...')
|
||||
logger.info(f'【{name}】模块初始化中...')
|
||||
# sv名称,重复的sv名称将被并入一个sv里
|
||||
self.name: str = name
|
||||
# sv内包含的触发器
|
||||
@ -54,21 +56,25 @@ class SV:
|
||||
self.enabled = config_sv[name]['enabled']
|
||||
self.permission = config_sv[name]['permission']
|
||||
self.black_list = config_sv[name]['black_list']
|
||||
self.area = config_sv[name]['area']
|
||||
else:
|
||||
# sv优先级
|
||||
self.priority: int = priority
|
||||
self.priority = priority
|
||||
# sv是否开启
|
||||
self.enabled: bool = enabled
|
||||
self.enabled = enabled
|
||||
# 黑名单群
|
||||
self.black_list: List = black_list
|
||||
self.black_list = black_list
|
||||
# 权限 0为master,1为superuser,2为群的群主&管理员,3为普通
|
||||
self.permission: int = permission
|
||||
self.permission = permission
|
||||
# 作用范围
|
||||
self.area = area
|
||||
# 写入
|
||||
self.set(
|
||||
priority=priority,
|
||||
enabled=enabled,
|
||||
permission=permission,
|
||||
black_list=black_list,
|
||||
area=area,
|
||||
)
|
||||
|
||||
def set(self, **kwargs):
|
||||
@ -96,7 +102,7 @@ class SV:
|
||||
keyword_list = (keyword,)
|
||||
for _k in keyword_list:
|
||||
if _k not in self.TL:
|
||||
print(f'载入{type}触发器【{_k}】!')
|
||||
logger.info(f'载入{type}触发器【{_k}】!')
|
||||
self.TL[_k] = Trigger(type, _k, func)
|
||||
|
||||
@wraps(func)
|
||||
|
Loading…
x
Reference in New Issue
Block a user