瀏覽代碼

Merge pull request #26 from librellium/refactor/transport-reorganization

Refactor/transport reorganization
Librellium 1 周之前
父節點
當前提交
3f7af91a2d

+ 10 - 10
anonflow/app.py

@@ -7,8 +7,14 @@ from aiogram.client.bot import DefaultBotProperties
 from aiogram.fsm.storage.memory import MemoryStorage
 
 from anonflow import __version_str__
-from anonflow.bot.builders.middlewares import build as build_middlewares
-from anonflow.bot.builders.routers import build as build_routers
+from anonflow.bot.builders import (
+    build_middlewares,
+    build_routers
+)
+from anonflow.bot.transport import (
+    DeliveryService,
+    ResponsesRouter
+)
 from anonflow.config import Config
 from anonflow.database import (
     BanRepository,
@@ -23,9 +29,7 @@ from anonflow.moderation import (
     RuleManager
 )
 from anonflow.services import (
-    DeliveryService,
     ModeratorService,
-    ResponsesRouter,
     UserService
 )
 from anonflow.translator import Translator
@@ -174,14 +178,10 @@ class Application:
             self, "_dispatcher", "_config", "_responses_router", "_user_service", "_moderator_service"
         ) as (dispatcher, config, responses_router, user_service, moderator_service):
             middlewares = build_middlewares(
+                config=config,
                 responses_router=responses_router,
                 user_service=user_service,
-                moderator_service=moderator_service,
-                subscription_requirement=config.behavior.subscription_requirement.enabled,
-                subscription_channel_ids=config.behavior.subscription_requirement.channel_ids,
-                throttling=config.behavior.throttling.enabled,
-                throttling_delay=config.behavior.throttling.delay,
-                throttling_allowed_chat_ids=config.forwarding.moderation_chat_ids
+                moderator_service=moderator_service
             )
 
             for middleware in middlewares:

+ 4 - 0
anonflow/bot/builders/__init__.py

@@ -0,0 +1,4 @@
+from .middlewares import build_middlewares
+from .routers import build_routers
+
+__all__ = ["build_middlewares", "build_routers"]

+ 27 - 35
anonflow/bot/builders/middlewares.py

@@ -1,69 +1,61 @@
-from typing import Tuple
-
-from aiogram.types import ChatIdUnion
-
-from anonflow.services import (
-    ModeratorService,
-    ResponsesRouter,
-    UserService
+from anonflow.bot.middlewares.user import (
+    UserBannedMiddleware,
+    UserContextMiddleware,
+    UserLanguageMiddleware,
+    UserNotRegisteredMiddleware,
+    UserSubscriptionMiddleware,
+    UserThrottlingMiddleware
 )
+from anonflow.bot.transport import ResponsesRouter
+from anonflow.config import Config
+from anonflow.services import ModeratorService, UserService
 
-from anonflow.bot.middlewares import (
-    BannedMiddleware,
-    LanguageMiddleware,
-    NotRegisteredMiddleware,
-    SubscriptionMiddleware,
-    ThrottlingMiddleware
-)
 
-def build(
+def build_middlewares(
+    config: Config,
     responses_router: ResponsesRouter,
     user_service: UserService,
     moderator_service: ModeratorService,
-
-    subscription_requirement: bool,
-    subscription_channel_ids: Tuple[ChatIdUnion],
-
-    throttling: bool,
-    throttling_delay: float,
-    throttling_allowed_chat_ids: Tuple[ChatIdUnion]
 ):
     middlewares = []
 
     middlewares.append(
-        LanguageMiddleware(
+        UserContextMiddleware(
             user_service=user_service
         )
     )
 
     middlewares.append(
-        BannedMiddleware(
+        UserLanguageMiddleware()
+    )
+
+    middlewares.append(
+        UserBannedMiddleware(
             responses_port=responses_router,
             moderator_service=moderator_service
         )
     )
 
-    if subscription_requirement:
+    if config.behavior.subscription_requirement.enabled:
         middlewares.append(
-            SubscriptionMiddleware(
+            UserSubscriptionMiddleware(
                 responses_port=responses_router,
-                channel_ids=subscription_channel_ids
+                channel_ids=config.behavior.subscription_requirement.channel_ids
             )
         )
 
     middlewares.append(
-        NotRegisteredMiddleware(
-            responses_port=responses_router,
-            user_service=user_service
+        UserNotRegisteredMiddleware(
+            responses_port=responses_router
         )
     )
 
-    if throttling:
+    if config.behavior.throttling.enabled:
         middlewares.append(
-            ThrottlingMiddleware(
+            UserThrottlingMiddleware(
                 responses_port=responses_router,
-                delay=throttling_delay,
-                allowed_chat_ids=throttling_allowed_chat_ids
+                delay=config.behavior.throttling.delay,
+                allowed_chat_ids=config.forwarding.moderation_chat_ids
             )
         )
 

+ 4 - 7
anonflow/bot/builders/routers.py

@@ -1,16 +1,13 @@
 from aiogram import Router
 
+from anonflow.bot.routers import MediaRouter, StartRouter, TextRouter
+from anonflow.bot.transport import ResponsesRouter
 from anonflow.config import Config
 from anonflow.moderation import ModerationService
-from anonflow.services import ModeratorService, ResponsesRouter, UserService
+from anonflow.services import ModeratorService, UserService
 
-from anonflow.bot.routers import (
-    MediaRouter,
-    StartRouter,
-    TextRouter
-)
 
-def build(
+def build_routers(
     config: Config,
     responses_router: ResponsesRouter,
     user_service: UserService,

+ 0 - 13
anonflow/bot/middlewares/__init__.py

@@ -1,13 +0,0 @@
-from .banned import BannedMiddleware
-from .language import LanguageMiddleware
-from .not_registered import NotRegisteredMiddleware
-from .subscription import SubscriptionMiddleware
-from .throttling import ThrottlingMiddleware
-
-__all__ = [
-    "BannedMiddleware",
-    "LanguageMiddleware",
-    "NotRegisteredMiddleware",
-    "SubscriptionMiddleware",
-    "ThrottlingMiddleware"
-]

+ 15 - 0
anonflow/bot/middlewares/user/__init__.py

@@ -0,0 +1,15 @@
+from .banned import UserBannedMiddleware
+from .context import UserContextMiddleware
+from .language import UserLanguageMiddleware
+from .not_registered import UserNotRegisteredMiddleware
+from .subscription import UserSubscriptionMiddleware
+from .throttling import UserThrottlingMiddleware
+
+__all__ = [
+    "UserBannedMiddleware",
+    "UserContextMiddleware",
+    "UserLanguageMiddleware",
+    "UserNotRegisteredMiddleware",
+    "UserSubscriptionMiddleware",
+    "UserThrottlingMiddleware"
+]

+ 2 - 2
anonflow/bot/middlewares/banned.py → anonflow/bot/middlewares/user/banned.py

@@ -1,12 +1,12 @@
 from aiogram import BaseMiddleware
 from aiogram.types import Message
 
+from anonflow.bot.transport.types import RequestContext
 from anonflow.interfaces import UserResponsesPort
 from anonflow.services import ModeratorService
-from anonflow.services.transport.types import RequestContext
 
 
-class BannedMiddleware(BaseMiddleware):
+class UserBannedMiddleware(BaseMiddleware):
     def __init__(self, responses_port: UserResponsesPort, moderator_service: ModeratorService):
         super().__init__()
 

+ 20 - 0
anonflow/bot/middlewares/user/context.py

@@ -0,0 +1,20 @@
+from aiogram import BaseMiddleware
+from aiogram.types import Message
+
+from anonflow.services import UserService
+
+
+class UserContextMiddleware(BaseMiddleware):
+    def __init__(self, user_service: UserService):
+        super().__init__()
+
+        self._user_service = user_service
+
+    async def __call__(self, handler, event, data):
+        data["user"] = None
+
+        message = getattr(event, "message", None)
+        if isinstance(message, Message) and message.from_user:
+            data["user"] = await self._user_service.get(message.from_user.id)
+
+        return await handler(event, data)

+ 3 - 7
anonflow/bot/middlewares/language.py → anonflow/bot/middlewares/user/language.py

@@ -1,21 +1,17 @@
 from aiogram import BaseMiddleware
 from aiogram.types import Message
 
-from anonflow.services import UserService
 
-
-class LanguageMiddleware(BaseMiddleware):
-    def __init__(self, user_service: UserService):
+class UserLanguageMiddleware(BaseMiddleware):
+    def __init__(self):
         super().__init__()
 
-        self._user_service = user_service
-
     async def __call__(self, handler, event, data):
         data["user_language"] = None
 
         message = getattr(event, "message", None)
         if isinstance(message, Message) and message.from_user:
-            user = await self._user_service.get(message.from_user.id)
+            user = data.get("user")
             data["user_language"] = (
                 user.language
                 if user else message.from_user.language_code

+ 4 - 6
anonflow/bot/middlewares/not_registered.py → anonflow/bot/middlewares/user/not_registered.py

@@ -2,24 +2,22 @@ from aiogram import BaseMiddleware
 from aiogram.enums import ChatType
 from aiogram.types import Message
 
+from anonflow.bot.transport.types import RequestContext
 from anonflow.interfaces import UserResponsesPort
-from anonflow.services import UserService
-from anonflow.services.transport.types import RequestContext
 
 
-class NotRegisteredMiddleware(BaseMiddleware):
-    def __init__(self, responses_port: UserResponsesPort, user_service: UserService):
+class UserNotRegisteredMiddleware(BaseMiddleware):
+    def __init__(self, responses_port: UserResponsesPort):
         super().__init__()
 
         self._responses_port = responses_port
-        self._user_service = user_service
 
     async def __call__(self, handler, event, data):
         message = getattr(event, "message", None)
         if isinstance(message, Message) and message.chat.type == ChatType.PRIVATE:
             text = message.text or message.caption or ""
 
-            is_user_exists = await self._user_service.has(message.chat.id)
+            is_user_exists = data.get("user") is not None
             if not is_user_exists and not text.startswith("/start"):
                 await self._responses_port.user_not_registered(RequestContext(message.chat.id, data["user_language"]))
                 return

+ 12 - 7
anonflow/bot/middlewares/subscription.py → anonflow/bot/middlewares/user/subscription.py

@@ -1,15 +1,15 @@
-from typing import Tuple
+from typing import Iterable
 
 from aiogram import BaseMiddleware
 from aiogram.enums import ChatMemberStatus, ChatType
 from aiogram.types import ChatIdUnion, Message
 
+from anonflow.bot.transport.types import RequestContext
 from anonflow.interfaces import UserResponsesPort
-from anonflow.services.transport.types import RequestContext
 
 
-class SubscriptionMiddleware(BaseMiddleware):
-    def __init__(self, responses_port: UserResponsesPort, channel_ids: Tuple[ChatIdUnion]):
+class UserSubscriptionMiddleware(BaseMiddleware):
+    def __init__(self, responses_port: UserResponsesPort, channel_ids: Iterable[ChatIdUnion]):
         super().__init__()
 
         self._responses_port = responses_port
@@ -17,10 +17,15 @@ class SubscriptionMiddleware(BaseMiddleware):
 
     async def __call__(self, handler, event, data):
         message = getattr(event, "message", None)
-        if isinstance(message, Message) and message.chat.type == ChatType.PRIVATE:
-            user_id = message.from_user.id # type: ignore
+        if (
+            isinstance(message, Message)
+            and message.chat.type == ChatType.PRIVATE
+            and message.from_user
+            and message.bot
+        ):
+            user_id = message.from_user.id
             for channel_id in self._channel_ids:
-                member = await message.bot.get_chat_member(channel_id, user_id) # type: ignore
+                member = await message.bot.get_chat_member(channel_id, user_id)
                 if member.status in (ChatMemberStatus.KICKED, ChatMemberStatus.LEFT):
                     await self._responses_port.user_subscription_required(RequestContext(message.chat.id, data["user_language"]))
                     return

+ 3 - 3
anonflow/bot/middlewares/throttling.py → anonflow/bot/middlewares/user/throttling.py

@@ -5,16 +5,16 @@ from typing import Dict, Iterable, Optional
 from aiogram import BaseMiddleware
 from aiogram.types import ChatIdUnion, Message
 
+from anonflow.bot.transport.types import RequestContext
 from anonflow.interfaces import UserResponsesPort
-from anonflow.services.transport.types import RequestContext
 
 
-class ThrottlingMiddleware(BaseMiddleware):
+class UserThrottlingMiddleware(BaseMiddleware):
     def __init__(
         self,
         responses_port: UserResponsesPort,
         delay: float,
-        allowed_chat_ids: Optional[Iterable[ChatIdUnion]]
+        allowed_chat_ids: Optional[Iterable[ChatIdUnion]] = None
     ):
         super().__init__()
 

+ 2 - 2
anonflow/bot/routers/media.py

@@ -12,12 +12,12 @@ from aiogram.types import Message
 from anonflow.config.models import ForwardingType
 from anonflow.interfaces import PostResponsesPort
 from anonflow.moderation import ModerationService
-from anonflow.services.transport.content import (
+from anonflow.bot.transport.content import (
     ContentGroup,
     ContentMediaItem,
     MediaType
 )
-from anonflow.services.transport.types import RequestContext
+from anonflow.bot.transport.types import RequestContext
 
 
 class MediaRouter(Router):

+ 1 - 1
anonflow/bot/routers/start.py

@@ -4,7 +4,7 @@ from aiogram.types import Message
 
 from anonflow.services import UserService
 from anonflow.interfaces import UserResponsesPort
-from anonflow.services.transport.types import RequestContext
+from anonflow.bot.transport.types import RequestContext
 
 
 class StartRouter(Router):

+ 2 - 2
anonflow/bot/routers/text.py

@@ -7,8 +7,8 @@ from aiogram.types import Message
 from anonflow.config.models import ForwardingType
 from anonflow.interfaces import PostResponsesPort
 from anonflow.moderation import ModerationService
-from anonflow.services.transport.content import ContentTextItem
-from anonflow.services.transport.types import RequestContext
+from anonflow.bot.transport.content import ContentTextItem
+from anonflow.bot.transport.types import RequestContext
 
 
 class TextRouter(Router):

+ 0 - 0
anonflow/services/transport/__init__.py → anonflow/bot/transport/__init__.py


+ 0 - 0
anonflow/services/transport/content.py → anonflow/bot/transport/content.py


+ 0 - 0
anonflow/services/transport/delivery.py → anonflow/bot/transport/delivery.py


+ 0 - 0
anonflow/services/transport/router.py → anonflow/bot/transport/router.py


+ 0 - 0
anonflow/services/transport/types.py → anonflow/bot/transport/types.py


+ 2 - 2
anonflow/interfaces/post.py

@@ -1,10 +1,10 @@
 from typing import Protocol, Union
 
-from anonflow.services.transport.content import (
+from anonflow.bot.transport.content import (
     ContentGroup,
     ContentItem
 )
-from anonflow.services.transport.types import RequestContext
+from anonflow.bot.transport.types import RequestContext
 
 
 class PostResponsesPort(Protocol):

+ 1 - 1
anonflow/interfaces/user.py

@@ -1,6 +1,6 @@
 from typing import Protocol
 
-from anonflow.services.transport.types import RequestContext
+from anonflow.bot.transport.types import RequestContext
 
 
 class UserResponsesPort(Protocol):

+ 1 - 1
anonflow/moderation/service.py

@@ -1,7 +1,7 @@
 from typing import Optional
 
 from anonflow.interfaces import PostResponsesPort
-from anonflow.services.transport.types import RequestContext
+from anonflow.bot.transport.types import RequestContext
 
 from .events import ModerationDecisionEvent, ModerationStartedEvent
 from .executor import ModerationExecutor

+ 0 - 3
anonflow/services/__init__.py

@@ -1,10 +1,7 @@
 from .moderator import ModeratorService
-from .transport import DeliveryService, ResponsesRouter
 from .user import UserService
 
 __all__ = [
     "ModeratorService",
-    "DeliveryService",
-    "ResponsesRouter",
     "UserService",
 ]