mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-07-28 00:31:14 +00:00
connect driver-adapter-matcher
This commit is contained in:
@ -1,8 +1,47 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from nonebot.config import Config
|
||||
|
||||
|
||||
class BaseBot(object):
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, type: str, config: Config, *, websocket=None):
|
||||
raise NotImplementedError
|
||||
|
||||
async def handle_message(self, message: dict):
|
||||
raise NotImplementedError
|
||||
|
||||
async def call_api(self, api: str, data: dict):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class BaseMessageSegment(dict):
|
||||
|
||||
def __init__(self,
|
||||
d: Optional[Dict[str, Any]] = None,
|
||||
*,
|
||||
type_: Optional[str] = None,
|
||||
data: Optional[Dict[str, str]] = None):
|
||||
super().__init__()
|
||||
if isinstance(d, dict) and d.get('type'):
|
||||
self.update(d)
|
||||
elif type_:
|
||||
self.type = type_
|
||||
self.data = data
|
||||
else:
|
||||
raise ValueError('the "type" field cannot be None or empty')
|
||||
|
||||
def __str__(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class BaseMessage(list):
|
||||
|
||||
def __init__(self, message: str = None):
|
||||
raise NotImplementedError
|
||||
|
||||
def __str__(self):
|
||||
return ''.join((str(seg) for seg in self))
|
||||
|
@ -1,10 +1,40 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from nonebot.adapters import BaseBot
|
||||
import httpx
|
||||
|
||||
from nonebot.event import Event
|
||||
from nonebot.config import Config
|
||||
from nonebot.adapters import BaseBot, BaseMessage, BaseMessageSegment
|
||||
from nonebot.message import handle_event
|
||||
|
||||
|
||||
class Bot(BaseBot):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
def __init__(self, type_: str, config: Config, *, websocket=None):
|
||||
if type_ not in ["http", "websocket"]:
|
||||
raise ValueError("Unsupported connection type")
|
||||
self.type = type_
|
||||
self.config = config
|
||||
self.websocket = websocket
|
||||
|
||||
async def handle_message(self, message: dict):
|
||||
# TODO: convert message into event
|
||||
event = Event.from_payload(message)
|
||||
|
||||
# TODO: Handle Meta Event
|
||||
await handle_event(self, event)
|
||||
|
||||
async def call_api(self, api: str, data: dict):
|
||||
if self.type == "websocket":
|
||||
pass
|
||||
elif self.type == "http":
|
||||
pass
|
||||
|
||||
|
||||
class MessageSegment(BaseMessageSegment):
|
||||
pass
|
||||
|
||||
|
||||
class Message(BaseMessage):
|
||||
pass
|
||||
|
@ -4,10 +4,12 @@
|
||||
from typing import Optional
|
||||
from ipaddress import IPv4Address
|
||||
|
||||
from nonebot.config import Config
|
||||
|
||||
|
||||
class BaseDriver(object):
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, config: Config):
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@ -34,3 +36,6 @@ class BaseDriver(object):
|
||||
|
||||
async def _handle_ws_reverse(self):
|
||||
raise NotImplementedError
|
||||
|
||||
async def _handle_http_api(self):
|
||||
raise NotImplementedError
|
||||
|
@ -7,15 +7,18 @@ from typing import Optional
|
||||
from ipaddress import IPv4Address
|
||||
|
||||
import uvicorn
|
||||
from starlette.websockets import WebSocketDisconnect
|
||||
from fastapi import Body, FastAPI, WebSocket
|
||||
|
||||
from nonebot.log import logger
|
||||
from nonebot.config import Config
|
||||
from nonebot.drivers import BaseDriver
|
||||
from nonebot.adapters.coolq import Bot as CoolQBot
|
||||
|
||||
|
||||
class Driver(BaseDriver):
|
||||
|
||||
def __init__(self, config):
|
||||
def __init__(self, config: Config):
|
||||
self._server_app = FastAPI(
|
||||
debug=config.debug,
|
||||
openapi_url=None,
|
||||
@ -25,8 +28,10 @@ class Driver(BaseDriver):
|
||||
|
||||
self.config = config
|
||||
|
||||
self._server_app.post("/coolq/")(self._handle_http)
|
||||
self._server_app.websocket("/coolq/ws")(self._handle_ws_reverse)
|
||||
self._server_app.post("/{adapter}/")(self._handle_http)
|
||||
self._server_app.post("/{adapter}/http")(self._handle_http)
|
||||
self._server_app.websocket("/{adapter}/ws")(self._handle_ws_reverse)
|
||||
self._server_app.websocket("/{adapter}/ws/")(self._handle_ws_reverse)
|
||||
|
||||
@property
|
||||
def server_app(self):
|
||||
@ -81,11 +86,16 @@ class Driver(BaseDriver):
|
||||
log_config=LOGGING_CONFIG,
|
||||
**kwargs)
|
||||
|
||||
async def _handle_http(self, data: dict = Body(...)):
|
||||
async def _handle_http(self, adapter: str, data: dict = Body(...)):
|
||||
# TODO: Check authorization
|
||||
logger.debug(f"Received message: {data}")
|
||||
if adapter == "coolq":
|
||||
bot = CoolQBot("http", self.config)
|
||||
await bot.handle_message(data)
|
||||
return {"status": 200, "message": "success"}
|
||||
|
||||
async def _handle_ws_reverse(self, websocket: WebSocket):
|
||||
async def _handle_ws_reverse(self, adapter: str, websocket: WebSocket):
|
||||
# TODO: Check authorization
|
||||
await websocket.accept()
|
||||
while True:
|
||||
try:
|
||||
@ -93,5 +103,11 @@ class Driver(BaseDriver):
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
logger.exception(e)
|
||||
continue
|
||||
except WebSocketDisconnect:
|
||||
logger.error("WebSocket Disconnect")
|
||||
return
|
||||
|
||||
logger.debug(f"Received message: {data}")
|
||||
if adapter == "coolq":
|
||||
bot = CoolQBot("websocket", self.config, websocket=websocket)
|
||||
await bot.handle_message(data)
|
||||
|
@ -94,7 +94,6 @@ class Matcher:
|
||||
|
||||
def _decorator(func: Handler) -> Handler:
|
||||
|
||||
@wraps(func)
|
||||
async def _handler(bot, event: Event, state: dict):
|
||||
raise PausedException
|
||||
|
||||
|
@ -6,13 +6,19 @@ from nonebot.event import Event
|
||||
from nonebot.matcher import matchers
|
||||
|
||||
|
||||
async def handle_message(bot, event: Event):
|
||||
async def handle_event(bot, event: Event):
|
||||
# TODO: PreProcess
|
||||
|
||||
for priority in sorted(matchers.keys()):
|
||||
for index in range(len(matchers[priority])):
|
||||
Matcher = matchers[priority][index]
|
||||
if not Matcher.check_rule(event):
|
||||
try:
|
||||
if not Matcher.check_rule(event):
|
||||
continue
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"Rule check failed for matcher {Matcher}. Ignored.")
|
||||
logger.exception(e)
|
||||
continue
|
||||
|
||||
matcher = Matcher()
|
||||
@ -22,5 +28,6 @@ async def handle_message(bot, event: Event):
|
||||
try:
|
||||
await matcher.run(bot, event)
|
||||
except Exception as e:
|
||||
logger.error(f"Running matcher {matcher} failed.")
|
||||
logger.exception(e)
|
||||
return
|
||||
|
Reference in New Issue
Block a user