60 lines
1.9 KiB
Python
60 lines
1.9 KiB
Python
from typing import TYPE_CHECKING
|
|
|
|
from app.log import log
|
|
from app.models.notification import NotificationDetails
|
|
|
|
from .base import RedisSubscriber
|
|
|
|
from pydantic import TypeAdapter
|
|
|
|
if TYPE_CHECKING:
|
|
from app.router.notification.server import ChatServer
|
|
|
|
|
|
JOIN_CHANNEL = "chat:room:joined"
|
|
EXIT_CHANNEL = "chat:room:left"
|
|
ON_NOTIFICATION = "chat:notification"
|
|
|
|
logger = log("Chat")
|
|
|
|
|
|
class ChatSubscriber(RedisSubscriber):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.room_subscriber: dict[int, list[int]] = {}
|
|
self.chat_server: "ChatServer | None" = None
|
|
|
|
async def start_subscribe(self):
|
|
await self.subscribe(JOIN_CHANNEL)
|
|
self.add_handler(JOIN_CHANNEL, self.on_join_room)
|
|
await self.subscribe(EXIT_CHANNEL)
|
|
self.add_handler(EXIT_CHANNEL, self.on_leave_room)
|
|
await self.subscribe(ON_NOTIFICATION)
|
|
self.add_handler(ON_NOTIFICATION, self.on_notification)
|
|
self.start()
|
|
|
|
async def on_join_room(self, c: str, s: str): # noqa: ARG002
|
|
channel_id, user_id = s.split(":")
|
|
if self.chat_server is None:
|
|
return
|
|
await self.chat_server.join_room_channel(int(channel_id), int(user_id))
|
|
|
|
async def on_leave_room(self, c: str, s: str): # noqa: ARG002
|
|
channel_id, user_id = s.split(":")
|
|
if self.chat_server is None:
|
|
return
|
|
await self.chat_server.leave_room_channel(int(channel_id), int(user_id))
|
|
|
|
async def on_notification(self, c: str, s: str): # noqa: ARG002
|
|
try:
|
|
detail = TypeAdapter(NotificationDetails).validate_json(s)
|
|
except ValueError:
|
|
logger.exception("Failed to parse notification detail")
|
|
return
|
|
except Exception:
|
|
logger.exception("Failed to parse notification detail")
|
|
return
|
|
if self.chat_server is None:
|
|
return
|
|
await self.chat_server.new_private_notification(detail)
|