Просмотр исходного кода

Refactor text handling to correctly process post command

Librellium 2 месяцев назад
Родитель
Сommit
212e78f0cb

+ 6 - 1
anonflow/bot/events/event_handler.py

@@ -66,7 +66,12 @@ class EventHandler:
             else:
                 await message.answer(_("messages.user.moderation_rejected", message=message))
         elif isinstance(event, BotMessagePreparedEvent) and publication_channel_ids is not None:
-            for chat_id in publication_channel_ids + moderation_chat_ids:
+
+            chat_ids = moderation_chat_ids
+            if event.moderation_approved and event.is_post:
+                chat_ids += publication_channel_ids
+
+            for chat_id in chat_ids:
                 content = event.content
                 if isinstance(content, str):
                     await self.bot.send_message(

+ 2 - 0
anonflow/bot/events/models.py

@@ -7,6 +7,8 @@ from aiogram.types import ChatIdUnion, MediaUnion
 @dataclass
 class BotMessagePreparedEvent:
     content: Union[str, List[MediaUnion]]
+    is_post: bool
+    moderation_approved: bool
 
 @dataclass
 class ExecutorDeletionEvent:

+ 3 - 8
anonflow/bot/middleware/post_command.py

@@ -12,6 +12,8 @@ class PostCommandMiddleware(BaseMiddleware):
     async def __call__(self, handler, event, data):
         message = extract_message(event)
 
+        data["is_post"] = False
+
         if isinstance(message, Message) and message.chat.type == ChatType.PRIVATE:
             source_text = message.text if message.text is not None else message.caption
             if not source_text:
@@ -26,13 +28,6 @@ class PostCommandMiddleware(BaseMiddleware):
             if message.text is not None and not post_text:
                 return
 
-            msg = message.model_copy(
-                deep=True,
-                update={
-                    "text": post_text,
-                    "is_post": True,
-                }
-            )
-            return await handler(msg, data)
+            data["is_post"] = True
 
         return await handler(event, data)

+ 1 - 1
anonflow/bot/middleware/slowmode.py

@@ -30,7 +30,7 @@ class SlowmodeMiddleware(BaseMiddleware):
 
         if isinstance(message, Message) and message.chat.id not in self.allowed_chat_ids:
             text = message.text or message.caption
-            if text and text.startswith("/") and not text.startswith("/post"):
+            if text and not text.startswith("/post"):
                 return await handler(event, data)
 
             async with self.lock:

+ 49 - 51
anonflow/bot/routers/media.py

@@ -33,53 +33,50 @@ class MediaRouter(Router):
         self.media_groups_lock = asyncio.Lock()
 
     def setup(self):
-        @self.message(F.photo | F.video)
-        async def on_photo(message: Message):
-            if message.chat.type != ChatType.PRIVATE:
+        def can_send_media(msgs: List[Message]):
+            forwarding_types = self.config.forwarding.types
+            return any(
+                (msg.photo and "photo" in forwarding_types) or
+                (msg.video and "video" in forwarding_types)
+                for msg in msgs
+            )
+
+        def get_media(message: Message, caption: str):
+            if message.photo and "photo" in self.config.forwarding.types:
+                return InputMediaPhoto(media=message.photo[-1].file_id, caption=caption)
+            elif message.video and "video" in self.config.forwarding.types:
+                return InputMediaVideo(media=message.video.file_id, caption=caption)
+
+        async def process_messages(messages: List[Message], is_post: bool):
+            if not messages:
                 return
 
-            def can_send_media(msgs: List[Message]):
-                photos = len([msg for msg in msgs if msg.photo])
-                videos = len([msg for msg in msgs if msg.video])
-
-                return (
-                    photos and "photo" in self.config.forwarding.types
-                ) or (
-                    videos and "video" in self.config.forwarding.types
-                )
-
-            async def get_media(msg: Message):
-                _ = self.translator.get()
-
-                caption = _("messages.channel.media", message=msg)
-
-                if msg.photo and "photo" in self.config.forwarding.types:
-                    return InputMediaPhoto(media=msg.photo[-1].file_id, caption=caption)
-                elif msg.video and "video" in self.config.forwarding.types:
-                    return InputMediaVideo(media=msg.video.file_id, caption=caption)
+            _ = self.translator.get()
 
-            async def process_messages(messages: list[Message]):
-                if not messages:
-                    return
+            if can_send_media(messages):
+                moderation = self.config.moderation.enabled
+                moderation_approved = not moderation
 
-                _ = self.translator.get()
+                content = []
+                for msg in messages:
+                    if moderation and is_post and msg.caption:
+                        async for event in self.executor.process_message(msg): # type: ignore
+                            if isinstance(event, ModerationDecisionEvent):
+                                moderation_approved = moderation_approved and event.approved
+                            await self.event_handler.handle(event, msg)
 
-                if can_send_media(messages):
-                    moderation = self.config.moderation.enabled
-                    moderation_passed = not moderation
+                    caption = _("messages.channel.media", message=msg) if is_post else (msg.caption or "")
+                    content.append(get_media(msg, caption))
 
-                    media = []
-                    for msg in messages:
-                        if moderation and msg.caption:
-                            async for event in self.executor.process_message(msg):
-                                if isinstance(event, ModerationDecisionEvent):
-                                    moderation_passed = event.approved
-                                await self.event_handler.handle(event, message)
-
-                        media.append(await get_media(msg))
+                await self.event_handler.handle(
+                    BotMessagePreparedEvent(content, is_post, moderation_approved),
+                    messages[0]
+                )
 
-                    if moderation_passed:
-                        await self.event_handler.handle(BotMessagePreparedEvent(media), messages[0])
+        @self.message(F.photo | F.video)
+        async def on_photo(message: Message, is_post: bool):
+            if message.chat.type != ChatType.PRIVATE:
+                return
 
             media_group_id = message.media_group_id
 
@@ -87,22 +84,23 @@ class MediaRouter(Router):
                 try:
                     await asyncio.sleep(2)
                     async with self.media_groups_lock:
-                        messages = self.media_groups.pop(media_group_id, [])
-                        self.media_groups_tasks.pop(media_group_id, None)
-                    await process_messages(messages)
+                        messages = self.media_groups.pop(media_group_id, []) # type: ignore
+                        self.media_groups_tasks.pop(media_group_id, None) # type: ignore
+                    await process_messages(messages, is_post)
                 except CancelledError:
                     pass
 
             if media_group_id:
-                self.media_groups.setdefault(media_group_id, []).append(message)
+                async with self.media_groups_lock:
+                    self.media_groups.setdefault(media_group_id, []).append(message)
 
-                task = self.media_groups_tasks.get(media_group_id)
-                if task:
-                    task.cancel()
+                    task = self.media_groups_tasks.get(media_group_id)
+                    if task:
+                        task.cancel()
 
-                self.media_groups_tasks[media_group_id] = asyncio.create_task(
-                    await_media_group()
-                )
+                    self.media_groups_tasks[media_group_id] = asyncio.create_task(
+                        await_media_group()
+                    )
                 return
 
-            await process_messages([message])
+            await process_messages([message], is_post)

+ 16 - 10
anonflow/bot/routers/text.py

@@ -4,6 +4,7 @@ from aiogram import F, Router
 from aiogram.enums import ChatType
 from aiogram.types import Message
 
+from anonflow.bot import utils
 from anonflow.bot.events.models import BotMessagePreparedEvent
 from anonflow.bot.events.event_handler import EventHandler, ModerationDecisionEvent
 from anonflow.config import Config
@@ -28,22 +29,27 @@ class TextRouter(Router):
 
     def setup(self):
         @self.message(F.text)
-        async def on_text(message: Message):
-
+        async def on_text(message: Message, is_post: bool):
             _ = self.translator.get()
 
             moderation = self.config.moderation.enabled
-            moderation_passed = not moderation
+            moderation_approved = not moderation
 
             if (
                 message.chat.type == ChatType.PRIVATE
                 and "text" in self.config.forwarding.types
             ):
-                if moderation:
-                    async for event in self.executor.process_message(message): # type: ignore
+                msg = message.model_copy(
+                    update={"text": utils.rm_post(message.text)}
+                )
+                if moderation and is_post:
+                    async for event in self.executor.process_message(msg): # type: ignore
                         if isinstance(event, ModerationDecisionEvent):
-                            moderation_passed = event.approved
-                        await self.event_handler.handle(event, message)
-
-                if moderation_passed:
-                    await self.event_handler.handle(BotMessagePreparedEvent(_("messages.channel.text", message=message)), message)
+                            moderation_approved = event.approved
+                        await self.event_handler.handle(event, msg)
+
+                content = _("messages.channel.text", message=msg) if is_post else (msg.text or "")
+                await self.event_handler.handle(
+                    BotMessagePreparedEvent(content, is_post, moderation_approved),
+                    msg
+                )