feat(achievement): support obtain achievements
This commit is contained in:
22
app/service/load_achievements.py
Normal file
22
app/service/load_achievements.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
|
||||
from app.log import logger
|
||||
from app.models.achievement import MEDALS, Medals
|
||||
from app.path import ACHIEVEMENTS_DIR
|
||||
|
||||
|
||||
def load_achievements() -> Medals:
|
||||
for module in ACHIEVEMENTS_DIR.iterdir():
|
||||
if module.is_file() and module.suffix == ".py":
|
||||
module_name = module.stem
|
||||
module_achievements = importlib.import_module(
|
||||
f"app.achievements.{module_name}"
|
||||
)
|
||||
medals = getattr(module_achievements, "MEDALS", {})
|
||||
MEDALS.update(medals)
|
||||
logger.success(
|
||||
f"Successfully loaded {len(medals)} achievements from {module_name}.py"
|
||||
)
|
||||
return MEDALS
|
||||
@@ -35,12 +35,22 @@ class RedisSubscriber:
|
||||
ignore_subscribe_messages=True, timeout=None
|
||||
)
|
||||
if message is not None and message["type"] == "message":
|
||||
matched_handlers = []
|
||||
matched_handlers: list[Callable[[str, str], Awaitable[Any]]] = []
|
||||
|
||||
if message["channel"] in self.handlers:
|
||||
matched_handlers.extend(self.handlers[message["channel"]])
|
||||
|
||||
chan = message["channel"]
|
||||
for pattern, handlers in self.handlers.items():
|
||||
if fnmatch(message["channel"], pattern):
|
||||
matched_handlers.extend(handlers)
|
||||
if pattern == chan:
|
||||
continue
|
||||
if not any(ch in pattern for ch in "*?[]"):
|
||||
continue
|
||||
if fnmatch(chan, pattern):
|
||||
for h in handlers:
|
||||
if h not in matched_handlers:
|
||||
matched_handlers.append(h)
|
||||
|
||||
if matched_handlers:
|
||||
await asyncio.gather(
|
||||
*[
|
||||
|
||||
@@ -2,14 +2,20 @@ from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from app.log import logger
|
||||
from app.models.notification import NotificationDetails
|
||||
|
||||
from .base import RedisSubscriber
|
||||
|
||||
from pydantic import TypeAdapter
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from app.router.chat.server import ChatServer
|
||||
from app.router.notification.server import ChatServer
|
||||
|
||||
|
||||
JOIN_CHANNEL = "chat:room:joined"
|
||||
EXIT_CHANNEL = "chat:room:left"
|
||||
ON_NOTIFICATION = "chat:notification"
|
||||
|
||||
|
||||
class ChatSubscriber(RedisSubscriber):
|
||||
@@ -23,6 +29,8 @@ class ChatSubscriber(RedisSubscriber):
|
||||
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):
|
||||
@@ -36,3 +44,16 @@ class ChatSubscriber(RedisSubscriber):
|
||||
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):
|
||||
try:
|
||||
detail = TypeAdapter(NotificationDetails).validate_json(s)
|
||||
except ValueError:
|
||||
logger.exception("")
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user