Parcourir la source

feat(transport): adapt to new API

- implement new ResponsesPorts API in ResponsesRouter
- move translator getter to dedicated method
- add delayed deletion in DeliveryService
Librellium il y a 2 jours
Parent
commit
b15cb1cdd1
2 fichiers modifiés avec 122 ajouts et 60 suppressions
  1. 33 2
      anonflow/bot/transport/delivery.py
  2. 89 58
      anonflow/bot/transport/router.py

+ 33 - 2
anonflow/bot/transport/delivery.py

@@ -1,7 +1,8 @@
-from typing import Optional, List, Union
+import asyncio
+from typing import Callable, Optional, List, Union
 
 from aiogram import Bot
-from aiogram.client.bot import Default
+from aiogram.client.default import Default
 from aiogram.types import (
     ChatIdUnion,
     InputMediaPhoto,
@@ -32,9 +33,26 @@ class DeliveryService:
         else:
             raise ValueError("Media item type is invalid.")
 
+    async def answer_callback_query(self, callback_query_id: str, text: str):
+        return await self._bot.answer_callback_query(callback_query_id, text)
+
+    async def copy(
+        self, chat_id: ChatIdUnion, from_chat_id: ChatIdUnion, message_id: int
+    ):
+        return await self._bot.copy_message(chat_id, from_chat_id, message_id)
+
     async def delete(self, chat_id: ChatIdUnion, message_id: int):
         return await self._bot.delete_message(chat_id, message_id)
 
+    async def delete_with_delay(self, chat_id: ChatIdUnion, message_id: int, delay: float):
+        await asyncio.sleep(delay)
+        return await self.delete(chat_id, message_id)
+
+    async def remove_reply_markup(self, chat_id: ChatIdUnion, message_id: int):
+        return await self._bot.edit_message_reply_markup(
+            chat_id=chat_id, message_id=message_id
+        )
+
     async def send_content(
         self,
         chat_id: ChatIdUnion,
@@ -101,3 +119,16 @@ class DeliveryService:
         return await self._bot.send_message(
             chat_id=chat_id, text=text, parse_mode=parse_mode, reply_markup=reply_markup
         )
+
+    async def send_with_delete(
+        self,
+        delay: float,
+        func: Callable,
+        *args,
+        **kwargs
+    ):
+        message = await func(*args, **kwargs)
+        asyncio.create_task(
+            self.delete_with_delay(message.chat.id, message.message_id, delay)
+        )
+        return message

+ 89 - 58
anonflow/bot/transport/router.py

@@ -1,9 +1,13 @@
-from itertools import chain
-from typing import Tuple, Union
+from typing import Optional, Tuple, Union
 
 from aiogram.types import ChatIdUnion
 
-from anonflow.interfaces import PostResponsesPort, UserResponsesPort
+from anonflow.bot.keyboards import Keyboards
+from anonflow.interfaces import (
+    ModeratorResponsesPort,
+    PostResponsesPort,
+    UserResponsesPort,
+)
 from anonflow.translator import Translator
 
 from .content import ContentGroup, ContentItem
@@ -11,50 +15,83 @@ from .delivery import DeliveryService
 from .types import RequestContext
 
 
-class ResponsesRouter(PostResponsesPort, UserResponsesPort):
+class ResponsesRouter(ModeratorResponsesPort, PostResponsesPort, UserResponsesPort):
     def __init__(
         self,
-        moderation_chat_ids: Tuple[ChatIdUnion],
+        moderation_chat_id: ChatIdUnion,
         publication_channel_ids: Tuple[ChatIdUnion],
         delivery_service: DeliveryService,
         translator: Translator,
     ):
-        self._moderation_chat_ids = moderation_chat_ids
+        self._moderation_chat_id = moderation_chat_id
         self._publication_channel_ids = publication_channel_ids
         self._delivery_service = delivery_service
         self._translator = translator
 
+    async def _get_translators(self, user_language: str, keyboards_from_user: bool = False):
+        return (
+            await self._translator.get(),
+            await self._translator.get(
+                user_language
+            ),
+            await self._translator.get(
+                user_language if keyboards_from_user else None, domain="keyboards"
+            )
+        )
+
+    async def moderator_permission_error(self, context: RequestContext, callback_query_id: Optional[str] = None):
+        t_app, t_user, t_kb = await self._get_translators(context.user_language)
+        if callback_query_id:
+            await self._delivery_service.answer_callback_query(
+                callback_query_id, t_user("moderator.permission_error")
+            )
+        else:
+            await self._delivery_service.send_text(
+                context.chat_id, t_user("moderator.permission_error")
+            )
+
+    async def post_moderators_decision(
+        self, context: RequestContext, is_approved: bool, message_id: int
+    ):
+        await self._delivery_service.remove_reply_markup(context.chat_id, message_id)
+        if is_approved:
+            for chat_id in self._publication_channel_ids:
+                await self._delivery_service.copy(chat_id, context.chat_id, message_id)
+
     async def post_moderation_decision(
         self, context: RequestContext, is_approved: bool, reason: str
     ):
-        _ = await self._translator.get(context.user_language)
-        for chat_id in self._moderation_chat_ids:
-            if is_approved:
-                await self._delivery_service.send_text(
-                    chat_id,
-                    _(
-                        "messages.staff.moderation_approved",
-                        reason=reason,
-                    ),
-                )
-            else:
-                await self._delivery_service.send_text(
-                    chat_id,
-                    _(
-                        "messages.staff.moderation_rejected",
-                        reason=reason,
-                    ),
-                )
-
-        if not is_approved:
+        t_app, t_user, t_kb = await self._get_translators(context.user_language)
+        if is_approved:
             await self._delivery_service.send_text(
-                context.chat_id, _("messages.user.moderation_rejected")
+                self._moderation_chat_id,
+                t_app(
+                    "moderator.moderation_approved",
+                    reason=reason,
+                ),
+            )
+        else:
+            await self._delivery_service.send_text(
+                self._moderation_chat_id,
+                t_app(
+                    "moderator.moderation_rejected",
+                    reason=reason,
+                ),
+            )
+
+        if is_approved:
+            await self._delivery_service.send_text(
+                context.chat_id, t_user("user.moderation_approved")
+            )
+        else:
+            await self._delivery_service.send_text(
+                context.chat_id, t_user("user.moderation_rejected")
             )
 
     async def post_moderation_started(self, context: RequestContext):
-        _ = await self._translator.get(context.user_language)
-        await self._delivery_service.send_text(
-            context.chat_id, _("messages.user.moderation_started")
+        t_app, t_user, t_kb = await self._get_translators(context.user_language)
+        await self._delivery_service.send_with_delete(
+            5, self._delivery_service.send_text, context.chat_id, t_user("user.moderation_started")
         )
 
     async def post_prepared(
@@ -63,54 +100,48 @@ class ResponsesRouter(PostResponsesPort, UserResponsesPort):
         content: Union[ContentItem, ContentGroup],
         is_approved: bool,
     ):
-        _ = await self._translator.get(context.user_language)
-
-        chat_ids = (
-            chain(self._moderation_chat_ids, self._publication_channel_ids)
-            if is_approved
-            else iter(self._moderation_chat_ids)
-        )
+        t_app, t_user, t_kb = await self._get_translators(context.user_language)
 
-        content.translate(lambda t: _("messages.channel.post", text=t))
+        content.translate(lambda t: t_app("channel.post", text=t))
 
-        for chat_id in chat_ids:
-            await self._delivery_service.send_content(chat_id, content)
+        await self._delivery_service.send_content(
+            self._moderation_chat_id,
+            content,
+            reply_markup=(
+                Keyboards.get_post_markup(t_kb) if not is_approved else None
+            ),
+        )
 
         if is_approved:
-            await self._delivery_service.send_text(
-                context.chat_id, _("messages.user.moderation_approved")
-            )
+            for chat_id in self._publication_channel_ids:
+                await self._delivery_service.send_content(chat_id, content)
 
     async def user_banned(self, context: RequestContext):
-        _ = await self._translator.get(context.user_language)
-        await self._delivery_service.send_text(
-            context.chat_id, _("messages.user.banned")
-        )
+        t_app, t_user, t_kb = await self._get_translators(context.user_language)
+        await self._delivery_service.send_text(context.chat_id, t_user("user.banned"))
 
     async def user_not_registered(self, context: RequestContext):
-        _ = await self._translator.get(context.user_language)
+        t_app, t_user, t_kb = await self._get_translators(context.user_language)
         await self._delivery_service.send_text(
-            context.chat_id, _("messages.user.not_registered")
+            context.chat_id, t_user("user.not_registered")
         )
 
     async def user_start(self, context: RequestContext):
-        _ = await self._translator.get(context.user_language)
-        await self._delivery_service.send_text(
-            context.chat_id, _("messages.user.command_start")
-        )
+        t_app, t_user, t_kb = await self._get_translators(context.user_language)
+        await self._delivery_service.send_text(context.chat_id, t_user("user.command_start"))
 
     async def user_subscription_required(self, context: RequestContext):
-        _ = await self._translator.get(context.user_language)
+        t_app, t_user, t_kb = await self._get_translators(context.user_language)
         await self._delivery_service.send_text(
-            context.chat_id, _("messages.user.subscription_required")
+            context.chat_id, t_user("user.subscription_required")
         )
 
     async def user_throttled(self, context: RequestContext, remaining_time: int):
-        _ = await self._translator.get(context.user_language)
+        t_app, t_user, t_kb = await self._get_translators(context.user_language)
         await self._delivery_service.send_text(
             context.chat_id,
-            _(
-                "messages.user.throttled",
+            t_user(
+                "user.throttled",
                 n=remaining_time,
                 remaining_time=remaining_time,
             ),