Bläddra i källkod

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

Refactor/transport reorganization
Librellium 1 vecka sedan
förälder
incheckning
3f7af91a2d

+ 10 - 10
anonflow/app.py

@@ -7,8 +7,14 @@ from aiogram.client.bot import DefaultBotProperties
 from aiogram.fsm.storage.memory import MemoryStorage
 from aiogram.fsm.storage.memory import MemoryStorage
 
 
 from anonflow import __version_str__
 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.config import Config
 from anonflow.database import (
 from anonflow.database import (
     BanRepository,
     BanRepository,
@@ -23,9 +29,7 @@ from anonflow.moderation import (
     RuleManager
     RuleManager
 )
 )
 from anonflow.services import (
 from anonflow.services import (
-    DeliveryService,
     ModeratorService,
     ModeratorService,
-    ResponsesRouter,
     UserService
     UserService
 )
 )
 from anonflow.translator import Translator
 from anonflow.translator import Translator
@@ -174,14 +178,10 @@ class Application:
             self, "_dispatcher", "_config", "_responses_router", "_user_service", "_moderator_service"
             self, "_dispatcher", "_config", "_responses_router", "_user_service", "_moderator_service"
         ) as (dispatcher, config, responses_router, user_service, moderator_service):
         ) as (dispatcher, config, responses_router, user_service, moderator_service):
             middlewares = build_middlewares(
             middlewares = build_middlewares(
+                config=config,
                 responses_router=responses_router,
                 responses_router=responses_router,
                 user_service=user_service,
                 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:
             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,
     responses_router: ResponsesRouter,
     user_service: UserService,
     user_service: UserService,
     moderator_service: ModeratorService,
     moderator_service: ModeratorService,
-
-    subscription_requirement: bool,
-    subscription_channel_ids: Tuple[ChatIdUnion],
-
-    throttling: bool,
-    throttling_delay: float,
-    throttling_allowed_chat_ids: Tuple[ChatIdUnion]
 ):
 ):
     middlewares = []
     middlewares = []
 
 
     middlewares.append(
     middlewares.append(
-        LanguageMiddleware(
+        UserContextMiddleware(
             user_service=user_service
             user_service=user_service
         )
         )
     )
     )
 
 
     middlewares.append(
     middlewares.append(
-        BannedMiddleware(
+        UserLanguageMiddleware()
+    )
+
+    middlewares.append(
+        UserBannedMiddleware(
             responses_port=responses_router,
             responses_port=responses_router,
             moderator_service=moderator_service
             moderator_service=moderator_service
         )
         )
     )
     )
 
 
-    if subscription_requirement:
+    if config.behavior.subscription_requirement.enabled:
         middlewares.append(
         middlewares.append(
-            SubscriptionMiddleware(
+            UserSubscriptionMiddleware(
                 responses_port=responses_router,
                 responses_port=responses_router,
-                channel_ids=subscription_channel_ids
+                channel_ids=config.behavior.subscription_requirement.channel_ids
             )
             )
         )
         )
 
 
     middlewares.append(
     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(
         middlewares.append(
-            ThrottlingMiddleware(
+            UserThrottlingMiddleware(
                 responses_port=responses_router,
                 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 aiogram import Router
 
 
+from anonflow.bot.routers import MediaRouter, StartRouter, TextRouter
+from anonflow.bot.transport import ResponsesRouter
 from anonflow.config import Config
 from anonflow.config import Config
 from anonflow.moderation import ModerationService
 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,
     config: Config,
     responses_router: ResponsesRouter,
     responses_router: ResponsesRouter,
     user_service: UserService,
     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 import BaseMiddleware
 from aiogram.types import Message
 from aiogram.types import Message
 
 
+from anonflow.bot.transport.types import RequestContext
 from anonflow.interfaces import UserResponsesPort
 from anonflow.interfaces import UserResponsesPort
 from anonflow.services import ModeratorService
 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):
     def __init__(self, responses_port: UserResponsesPort, moderator_service: ModeratorService):
         super().__init__()
         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 import BaseMiddleware
 from aiogram.types import Message
 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__()
         super().__init__()
 
 
-        self._user_service = user_service
-
     async def __call__(self, handler, event, data):
     async def __call__(self, handler, event, data):
         data["user_language"] = None
         data["user_language"] = None
 
 
         message = getattr(event, "message", None)
         message = getattr(event, "message", None)
         if isinstance(message, Message) and message.from_user:
         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"] = (
             data["user_language"] = (
                 user.language
                 user.language
                 if user else message.from_user.language_code
                 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.enums import ChatType
 from aiogram.types import Message
 from aiogram.types import Message
 
 
+from anonflow.bot.transport.types import RequestContext
 from anonflow.interfaces import UserResponsesPort
 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__()
         super().__init__()
 
 
         self._responses_port = responses_port
         self._responses_port = responses_port
-        self._user_service = user_service
 
 
     async def __call__(self, handler, event, data):
     async def __call__(self, handler, event, data):
         message = getattr(event, "message", None)
         message = getattr(event, "message", None)
         if isinstance(message, Message) and message.chat.type == ChatType.PRIVATE:
         if isinstance(message, Message) and message.chat.type == ChatType.PRIVATE:
             text = message.text or message.caption or ""
             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"):
             if not is_user_exists and not text.startswith("/start"):
                 await self._responses_port.user_not_registered(RequestContext(message.chat.id, data["user_language"]))
                 await self._responses_port.user_not_registered(RequestContext(message.chat.id, data["user_language"]))
                 return
                 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 import BaseMiddleware
 from aiogram.enums import ChatMemberStatus, ChatType
 from aiogram.enums import ChatMemberStatus, ChatType
 from aiogram.types import ChatIdUnion, Message
 from aiogram.types import ChatIdUnion, Message
 
 
+from anonflow.bot.transport.types import RequestContext
 from anonflow.interfaces import UserResponsesPort
 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__()
         super().__init__()
 
 
         self._responses_port = responses_port
         self._responses_port = responses_port
@@ -17,10 +17,15 @@ class SubscriptionMiddleware(BaseMiddleware):
 
 
     async def __call__(self, handler, event, data):
     async def __call__(self, handler, event, data):
         message = getattr(event, "message", None)
         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:
             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):
                 if member.status in (ChatMemberStatus.KICKED, ChatMemberStatus.LEFT):
                     await self._responses_port.user_subscription_required(RequestContext(message.chat.id, data["user_language"]))
                     await self._responses_port.user_subscription_required(RequestContext(message.chat.id, data["user_language"]))
                     return
                     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 import BaseMiddleware
 from aiogram.types import ChatIdUnion, Message
 from aiogram.types import ChatIdUnion, Message
 
 
+from anonflow.bot.transport.types import RequestContext
 from anonflow.interfaces import UserResponsesPort
 from anonflow.interfaces import UserResponsesPort
-from anonflow.services.transport.types import RequestContext
 
 
 
 
-class ThrottlingMiddleware(BaseMiddleware):
+class UserThrottlingMiddleware(BaseMiddleware):
     def __init__(
     def __init__(
         self,
         self,
         responses_port: UserResponsesPort,
         responses_port: UserResponsesPort,
         delay: float,
         delay: float,
-        allowed_chat_ids: Optional[Iterable[ChatIdUnion]]
+        allowed_chat_ids: Optional[Iterable[ChatIdUnion]] = None
     ):
     ):
         super().__init__()
         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.config.models import ForwardingType
 from anonflow.interfaces import PostResponsesPort
 from anonflow.interfaces import PostResponsesPort
 from anonflow.moderation import ModerationService
 from anonflow.moderation import ModerationService
-from anonflow.services.transport.content import (
+from anonflow.bot.transport.content import (
     ContentGroup,
     ContentGroup,
     ContentMediaItem,
     ContentMediaItem,
     MediaType
     MediaType
 )
 )
-from anonflow.services.transport.types import RequestContext
+from anonflow.bot.transport.types import RequestContext
 
 
 
 
 class MediaRouter(Router):
 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.services import UserService
 from anonflow.interfaces import UserResponsesPort
 from anonflow.interfaces import UserResponsesPort
-from anonflow.services.transport.types import RequestContext
+from anonflow.bot.transport.types import RequestContext
 
 
 
 
 class StartRouter(Router):
 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.config.models import ForwardingType
 from anonflow.interfaces import PostResponsesPort
 from anonflow.interfaces import PostResponsesPort
 from anonflow.moderation import ModerationService
 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):
 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 typing import Protocol, Union
 
 
-from anonflow.services.transport.content import (
+from anonflow.bot.transport.content import (
     ContentGroup,
     ContentGroup,
     ContentItem
     ContentItem
 )
 )
-from anonflow.services.transport.types import RequestContext
+from anonflow.bot.transport.types import RequestContext
 
 
 
 
 class PostResponsesPort(Protocol):
 class PostResponsesPort(Protocol):

+ 1 - 1
anonflow/interfaces/user.py

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

+ 1 - 1
anonflow/moderation/service.py

@@ -1,7 +1,7 @@
 from typing import Optional
 from typing import Optional
 
 
 from anonflow.interfaces import PostResponsesPort
 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 .events import ModerationDecisionEvent, ModerationStartedEvent
 from .executor import ModerationExecutor
 from .executor import ModerationExecutor

+ 0 - 3
anonflow/services/__init__.py

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