diff --git a/.pylintrc b/.pylintrc index 5d12340..149e62f 100644 --- a/.pylintrc +++ b/.pylintrc @@ -1,3 +1,3 @@ [pylint] good-names = id -min-public-methods = 1 +min-public-methods = 0 diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/app_client.py b/app/app_client.py new file mode 100644 index 0000000..ad99363 --- /dev/null +++ b/app/app_client.py @@ -0,0 +1,20 @@ +from domain.event.message_received_event import MessageReceivedEvent + + +class AppClient(): + def __init__(self, bot_client, event_bus): + self._bot_client = bot_client + self.event_bus = event_bus + + self.event_bus.subscribe(self) + + def start(self): + self._bot_client.run() + + async def on_receive_event(self, event): + if isinstance(event, MessageReceivedEvent): + print("yolo") + + @staticmethod + def subscribed_to(): + return [MessageReceivedEvent] diff --git a/app/discord_client.py b/app/discord_client.py index 3def8d7..2cef4e8 100644 --- a/app/discord_client.py +++ b/app/discord_client.py @@ -1,10 +1,17 @@ import discord +from domain.event.message_received_event import MessageReceivedEvent class DiscordClient(): - def __init__(self, bot_secret_key): + def __init__(self, bot_secret_key, event_bus): self._client = discord.Client() self._bot_secret_key = bot_secret_key + self.event_bus = event_bus + + self._client.on_message = self.on_message def run(self): self._client.run(self._bot_secret_key) + + async def on_message(self, _message): + await self.event_bus.publish(MessageReceivedEvent()) diff --git a/app/domain/event/message_received_event.py b/app/domain/event/message_received_event.py new file mode 100644 index 0000000..5fdde99 --- /dev/null +++ b/app/domain/event/message_received_event.py @@ -0,0 +1,5 @@ +from shared.event.event import Event + + +class MessageReceivedEvent(Event): + pass diff --git a/app/shared/event/event.py b/app/shared/event/event.py new file mode 100644 index 0000000..4ddf6dc --- /dev/null +++ b/app/shared/event/event.py @@ -0,0 +1,3 @@ +class Event(): + def __init__(self, payload=None): + self.payload = payload diff --git a/app/shared/event/event_bus.py b/app/shared/event/event_bus.py new file mode 100644 index 0000000..d8b0e84 --- /dev/null +++ b/app/shared/event/event_bus.py @@ -0,0 +1,29 @@ +class EventBus(): + def __init__(self): + self._subscribers = {} + + async def publish(self, event): + event_classes = [x for x in list( + map(lambda x: x.__name__, type(event).mro())) if x != 'object'] + + subscribers = [] + for event_class in event_classes: + if not event_class in self._subscribers.keys(): + continue + subscribers += self._subscribers[event_class] + + if not subscribers: + return + + for subscriber in subscribers: + await subscriber.on_receive_event(event) + + def subscribe(self, subscriber): + subscribed_events = list( + map(lambda event_class: event_class.__name__, subscriber.subscribed_to())) + + for event_class_name in subscribed_events: + if not event_class_name in self._subscribers.keys(): + self._subscribers[event_class_name] = [] + + self._subscribers[event_class_name].append(subscriber) diff --git a/app/shared/event/event_logger.py b/app/shared/event/event_logger.py new file mode 100644 index 0000000..f7fb92a --- /dev/null +++ b/app/shared/event/event_logger.py @@ -0,0 +1,13 @@ +from event import Event + + +class EventLogger(): + def __init__(self): + pass + + async def on_receive_event(self, event): + print("Received event", type(event).__name__) + + @staticmethod + def subscribed_to(): + return [Event] diff --git a/main.py b/main.py index af72152..aafe444 100644 --- a/main.py +++ b/main.py @@ -1,12 +1,19 @@ from os import environ, path from dotenv import load_dotenv from app.discord_client import DiscordClient - +from app.app_client import AppClient +from app.shared.event.event_bus import EventBus +from app.shared.event.event_logger import EventLogger if environ.get("BOT_ENV") == "development": basedir = path.dirname(__file__) load_dotenv(path.join(basedir, '.env.development')) +event_bus = EventBus() +event_logger = EventLogger() +event_bus.subscribe(event_logger) -client = DiscordClient(environ.get("DISCORD_BOT_SECRET_KEY")) -client.run() +discord_client = DiscordClient( + environ.get("DISCORD_BOT_SECRET_KEY"), event_bus) +app = AppClient(discord_client, event_bus) +app.start() diff --git a/requirements.txt b/requirements.txt index 2d7c18c..9ff6af8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,6 +24,7 @@ pylama==7.7.1 pylint==2.6.2 pyparsing==2.4.7 pytest==6.2.2 +pytest-asyncio==0.14.0 pytest-mock==3.5.1 python-dateutil==2.8.1 python-dotenv==0.15.0 diff --git a/tests/discord_app_test.py b/tests/discord_app_test.py new file mode 100644 index 0000000..95d29fd --- /dev/null +++ b/tests/discord_app_test.py @@ -0,0 +1,29 @@ +from app.app_client import AppClient +from stubs.discord_client_stub import DiscordClientStub +from app.shared.event.event_bus import EventBus +from app.domain.event.message_received_event import MessageReceivedEvent +from stubs.in_memory_event_logger import InMemoryEventLogger + + +import pytest + + +def test_app_run_bot_client_on_start(): + event_bus = EventBus() + discord_client_stub = DiscordClientStub(event_bus) + app = AppClient(discord_client_stub, event_bus) + app.start() + assert discord_client_stub.is_start == True + + +@pytest.mark.asyncio +async def test_app_receive_event_from_bot_client(): + event_bus = EventBus() + discord_client_stub = DiscordClientStub(event_bus) + event_logger = InMemoryEventLogger() + event_bus.subscribe(event_logger) + app = AppClient(discord_client_stub, event_bus) + app.start() + + await discord_client_stub.trigger_event(MessageReceivedEvent()) + assert len(event_logger.events), 1 diff --git a/tests/stubs/discord_client_stub.py b/tests/stubs/discord_client_stub.py new file mode 100644 index 0000000..78d2b5d --- /dev/null +++ b/tests/stubs/discord_client_stub.py @@ -0,0 +1,10 @@ +class DiscordClientStub(): + def __init__(self, event_bus): + self.is_start = False + self._event_bus = event_bus + + def run(self): + self.is_start = True + + async def trigger_event(self, event): + await self._event_bus.publish(event) diff --git a/tests/stubs/in_memory_event_logger.py b/tests/stubs/in_memory_event_logger.py new file mode 100644 index 0000000..4dae9d3 --- /dev/null +++ b/tests/stubs/in_memory_event_logger.py @@ -0,0 +1,13 @@ +from app.shared.event.event import Event + + +class InMemoryEventLogger(): + def __init__(self): + self.events = [] + + async def on_receive_event(self, event): + self.events.append(event) + + @staticmethod + def subscribed_to(): + return [Event]