mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-07-28 08:41:29 +00:00
@ -1,8 +1,8 @@
|
||||
"""
|
||||
r"""
|
||||
Mirai-API-HTTP 协议适配
|
||||
============================
|
||||
|
||||
协议详情请看: `mirai-api-http 文档`_
|
||||
协议详情请看: `mirai-api-http 文档`_
|
||||
|
||||
\:\:\: tip
|
||||
该Adapter目前仍然处在早期实验性阶段, 并未经过充分测试
|
||||
|
@ -5,11 +5,11 @@ from typing import Any, Dict, List, NoReturn, Optional, Tuple, Union
|
||||
|
||||
import httpx
|
||||
|
||||
from nonebot.adapters import Bot as BaseBot
|
||||
from nonebot.config import Config
|
||||
from nonebot.drivers import Driver, WebSocket
|
||||
from nonebot.exception import ApiNotAvailable, RequestDenied
|
||||
from nonebot.typing import overrides
|
||||
from nonebot.adapters import Bot as BaseBot
|
||||
from nonebot.exception import ApiNotAvailable
|
||||
from nonebot.drivers import Driver, HTTPConnection, HTTPResponse, WebSocket
|
||||
|
||||
from .config import Config as MiraiConfig
|
||||
from .event import Event, FriendMessage, GroupMessage, TempMessage
|
||||
@ -140,7 +140,7 @@ class SessionManager:
|
||||
|
||||
|
||||
class Bot(BaseBot):
|
||||
"""
|
||||
r"""
|
||||
mirai-api-http 协议 Bot 适配。
|
||||
|
||||
\:\:\: warning
|
||||
@ -151,14 +151,6 @@ class Bot(BaseBot):
|
||||
|
||||
"""
|
||||
|
||||
@overrides(BaseBot)
|
||||
def __init__(self,
|
||||
connection_type: str,
|
||||
self_id: str,
|
||||
*,
|
||||
websocket: Optional[WebSocket] = None):
|
||||
super().__init__(connection_type, self_id, websocket=websocket)
|
||||
|
||||
@property
|
||||
@overrides(BaseBot)
|
||||
def type(self) -> str:
|
||||
@ -166,7 +158,8 @@ class Bot(BaseBot):
|
||||
|
||||
@property
|
||||
def alive(self) -> bool:
|
||||
return not self.websocket.closed
|
||||
assert isinstance(self.request, WebSocket)
|
||||
return not self.request.closed
|
||||
|
||||
@property
|
||||
def api(self) -> SessionManager:
|
||||
@ -177,27 +170,26 @@ class Bot(BaseBot):
|
||||
|
||||
@classmethod
|
||||
@overrides(BaseBot)
|
||||
async def check_permission(cls, driver: "Driver", connection_type: str,
|
||||
headers: dict, body: Optional[bytes]) -> str:
|
||||
if connection_type == 'ws':
|
||||
raise RequestDenied(
|
||||
status_code=501,
|
||||
reason='Websocket connection is not implemented')
|
||||
self_id: Optional[str] = headers.get('bot')
|
||||
async def check_permission(
|
||||
cls, driver: Driver,
|
||||
request: HTTPConnection) -> Tuple[Optional[str], HTTPResponse]:
|
||||
if isinstance(request, WebSocket):
|
||||
return None, HTTPResponse(
|
||||
501, b'Websocket connection is not implemented')
|
||||
self_id: Optional[str] = request.headers.get('bot')
|
||||
if self_id is None:
|
||||
raise RequestDenied(status_code=400,
|
||||
reason='Header `Bot` is required.')
|
||||
return None, HTTPResponse(400, b'Header `Bot` is required.')
|
||||
self_id = str(self_id).strip()
|
||||
await SessionManager.new(
|
||||
int(self_id),
|
||||
host=cls.mirai_config.host, # type: ignore
|
||||
port=cls.mirai_config.port, #type: ignore
|
||||
auth_key=cls.mirai_config.auth_key) # type: ignore
|
||||
return self_id
|
||||
return self_id, HTTPResponse(204, b'')
|
||||
|
||||
@classmethod
|
||||
@overrides(BaseBot)
|
||||
def register(cls, driver: "Driver", config: "Config"):
|
||||
def register(cls, driver: Driver, config: "Config"):
|
||||
cls.mirai_config = MiraiConfig(**config.dict())
|
||||
if (cls.mirai_config.auth_key and cls.mirai_config.host and
|
||||
cls.mirai_config.port) is None:
|
||||
@ -224,7 +216,7 @@ class Bot(BaseBot):
|
||||
|
||||
@overrides(BaseBot)
|
||||
async def call_api(self, api: str, **data) -> NoReturn:
|
||||
"""
|
||||
r"""
|
||||
\:\:\: danger
|
||||
由于Mirai的HTTP API特殊性, 该API暂时无法实现
|
||||
\:\:\:
|
||||
|
@ -1,18 +1,16 @@
|
||||
import asyncio
|
||||
import json
|
||||
import asyncio
|
||||
from dataclasses import dataclass
|
||||
from ipaddress import IPv4Address
|
||||
from typing import (Any, Callable, Coroutine, Dict, NoReturn, Optional, Set,
|
||||
TypeVar)
|
||||
from typing import Any, Set, Dict, Tuple, TypeVar, Optional, Callable, Coroutine
|
||||
|
||||
import httpx
|
||||
import websockets
|
||||
|
||||
from nonebot.config import Config
|
||||
from nonebot.drivers import Driver
|
||||
from nonebot.drivers import WebSocket as BaseWebSocket
|
||||
from nonebot.exception import RequestDenied
|
||||
from nonebot.log import logger
|
||||
from nonebot.config import Config
|
||||
from nonebot.typing import overrides
|
||||
from nonebot.drivers import Driver, HTTPConnection, HTTPResponse, WebSocket as BaseWebSocket
|
||||
|
||||
from .bot import SessionManager, Bot
|
||||
|
||||
@ -21,7 +19,9 @@ WebsocketHandler_T = TypeVar('WebsocketHandler_T',
|
||||
bound=WebsocketHandlerFunction)
|
||||
|
||||
|
||||
@dataclass
|
||||
class WebSocket(BaseWebSocket):
|
||||
websocket: websockets.WebSocketClientProtocol = None # type: ignore
|
||||
|
||||
@classmethod
|
||||
async def new(cls, *, host: IPv4Address, port: int,
|
||||
@ -37,24 +37,26 @@ class WebSocket(BaseWebSocket):
|
||||
self.event_handlers: Set[WebsocketHandlerFunction] = set()
|
||||
super().__init__(websocket)
|
||||
|
||||
@property
|
||||
@overrides(BaseWebSocket)
|
||||
def websocket(self) -> websockets.WebSocketClientProtocol:
|
||||
return self._websocket
|
||||
|
||||
@property
|
||||
@overrides(BaseWebSocket)
|
||||
def closed(self) -> bool:
|
||||
return self.websocket.closed
|
||||
|
||||
@overrides(BaseWebSocket)
|
||||
async def send(self, data: Dict[str, Any]):
|
||||
return await self.websocket.send(json.dumps(data))
|
||||
async def send(self, data: str):
|
||||
return await self.websocket.send(data)
|
||||
|
||||
@overrides(BaseWebSocket)
|
||||
async def receive(self) -> Dict[str, Any]:
|
||||
received = await self.websocket.recv()
|
||||
return json.loads(received)
|
||||
async def send_bytes(self, data: str):
|
||||
return await self.websocket.send(data)
|
||||
|
||||
@overrides(BaseWebSocket)
|
||||
async def receive(self) -> str:
|
||||
return await self.websocket.recv() # type: ignore
|
||||
|
||||
@overrides(BaseWebSocket)
|
||||
async def receive_bytes(self) -> bytes:
|
||||
return await self.websocket.recv() # type: ignore
|
||||
|
||||
async def _dispatcher(self):
|
||||
while not self.closed:
|
||||
@ -93,11 +95,6 @@ class WebsocketBot(Bot):
|
||||
mirai-api-http 正向 Websocket 协议 Bot 适配。
|
||||
"""
|
||||
|
||||
@overrides(Bot)
|
||||
def __init__(self, connection_type: str, self_id: str, *,
|
||||
websocket: WebSocket):
|
||||
super().__init__(connection_type, self_id, websocket=websocket)
|
||||
|
||||
@property
|
||||
@overrides(Bot)
|
||||
def type(self) -> str:
|
||||
@ -105,7 +102,8 @@ class WebsocketBot(Bot):
|
||||
|
||||
@property
|
||||
def alive(self) -> bool:
|
||||
return not self.websocket.closed
|
||||
assert isinstance(self.request, WebSocket)
|
||||
return not self.request.closed
|
||||
|
||||
@property
|
||||
def api(self) -> SessionManager:
|
||||
@ -115,16 +113,14 @@ class WebsocketBot(Bot):
|
||||
|
||||
@classmethod
|
||||
@overrides(Bot)
|
||||
async def check_permission(cls, driver: "Driver", connection_type: str,
|
||||
headers: dict,
|
||||
body: Optional[bytes]) -> NoReturn:
|
||||
raise RequestDenied(
|
||||
status_code=501,
|
||||
reason=f'Connection {connection_type} not implented')
|
||||
async def check_permission(
|
||||
cls, driver: Driver,
|
||||
request: HTTPConnection) -> Tuple[None, HTTPResponse]:
|
||||
return None, HTTPResponse(501, b'Connection not implented')
|
||||
|
||||
@classmethod
|
||||
@overrides(Bot)
|
||||
def register(cls, driver: "Driver", config: "Config", qq: int):
|
||||
def register(cls, driver: Driver, config: "Config", qq: int):
|
||||
"""
|
||||
:说明:
|
||||
|
||||
|
Reference in New Issue
Block a user