diff --git a/src/snek/service/forum.py b/src/snek/service/forum.py index 6e241c2..253e719 100644 --- a/src/snek/service/forum.py +++ b/src/snek/service/forum.py @@ -1,23 +1,25 @@ # services/forum.py from snek.system.service import BaseService import re - +import uuid from collections import defaultdict from typing import Any, Awaitable, Callable, Dict, List EventListener = Callable[[str, Any], Awaitable[None]] | Callable[[str, Any], None] - - class BaseForumService(BaseService): """ - Base mix-in that gives a service `add_notification_listener` - and an internal `_dispatch_event` helper. + Base mix-in that gives a service `add_notification_listener`, + an internal `_dispatch_event` helper, and a public `notify` method. """ - def __init__(self,*args, **kwargs) -> None: + def generate_uid(self): + return str(uuid.uuid4()) + + def __init__(self, *args, **kwargs) -> None: # Map event name -> list of listener callables self._listeners: Dict[str, List[EventListener]] = defaultdict(list) super().__init__(*args, **kwargs) + def add_notification_listener( self, event_name: str, listener: EventListener ) -> None: @@ -36,11 +38,6 @@ class BaseForumService(BaseService): self._listeners[event_name].append(listener) - # ----------------------------------------------------------------- - # The piece below is optional but makes the service fully usable. - # Call `_dispatch_event` whenever the service actually performs an - # action that should notify listeners. - # ----------------------------------------------------------------- async def _dispatch_event(self, event_name: str, data: Any) -> None: """Invoke every listener for the given event.""" for listener in self._listeners.get(event_name, []): @@ -49,7 +46,18 @@ class BaseForumService(BaseService): else: # plain sync function listener(event_name, data) + async def notify(self, event_name: str, data: Any) -> None: + """ + Public method to trigger notification to all listeners of an event. + Parameters + ---------- + event_name : str + The name of the event to notify listeners about. + data : Any + The data to pass to the listeners. + """ + await self._dispatch_event(event_name, data) class ForumService(BaseForumService): @@ -60,7 +68,7 @@ class ForumService(BaseForumService): slug = self.generate_slug(name) # Check if slug exists - existing = await self.find_one(slug=slug) + existing = await self.get(slug=slug) if existing: slug = f"{slug}-{self.generate_uid()[:8]}" @@ -105,7 +113,7 @@ class ThreadService(BaseForumService): slug = self.services.forum.generate_slug(title) # Check if slug exists in this forum - existing = await self.find_one(forum_uid=forum_uid, slug=slug) + existing = await self.get(forum_uid=forum_uid, slug=slug) if existing: slug = f"{slug}-{self.generate_uid()[:8]}" @@ -255,7 +263,7 @@ class PostLikeService(BaseForumService): async def toggle_like(self, post_uid, user_uid): # Check if already liked - existing = await self.find_one(post_uid=post_uid, user_uid=user_uid) + existing = await self.get(post_uid=post_uid, user_uid=user_uid) if existing: # Unlike diff --git a/src/snek/view/forum.py b/src/snek/view/forum.py index fd0c462..870f9b1 100644 --- a/src/snek/view/forum.py +++ b/src/snek/view/forum.py @@ -439,12 +439,12 @@ class ForumView(BaseView): class ForumWebSocketView(BaseView): """WebSocket view for real-time forum updates""" - async def websocket_handler(self): + async def get(self): ws = web.WebSocketResponse() await ws.prepare(self.request) # Store WebSocket connection - ws_id = self.services.generate_uid() + ws_id = self.services.forum.generate_uid() if not hasattr(self.app, 'forum_websockets'): self.app.forum_websockets = {}