diff --git a/butterrobot/app.py b/butterrobot/app.py index 42b1161..8301a5d 100644 --- a/butterrobot/app.py +++ b/butterrobot/app.py @@ -11,29 +11,13 @@ from butterrobot.queue import q from butterrobot.db import ChannelQuery from butterrobot.config import SECRET_KEY, HOSTNAME from butterrobot.objects import Message, Channel +from butterrobot.http import ExternalProxyFix from butterrobot.plugins import get_available_plugins from butterrobot.platforms import PLATFORMS, get_available_platforms from butterrobot.platforms.base import Platform from butterrobot.admin.blueprint import admin as admin_bp -class ExternalProxyFix(object): - """ - Custom proxy helper to get the external hostname from the `X-External-Host` header - used by one of the reverse proxies in front of this in production. - It does nothing if the header is not present. - """ - - def __init__(self, app): - self.app = app - - def __call__(self, environ, start_response): - host = environ.get("HTTP_X_EXTERNAL_HOST", "") - if host: - environ["HTTP_HOST"] = host - return self.app(environ, start_response) - - loop = asyncio.get_event_loop() logger = structlog.get_logger(__name__) app = Flask(__name__) diff --git a/butterrobot/http.py b/butterrobot/http.py new file mode 100644 index 0000000..9086155 --- /dev/null +++ b/butterrobot/http.py @@ -0,0 +1,15 @@ +class ExternalProxyFix(object): + """ + Custom proxy helper to get the external hostname from the `X-External-Host` header + used by one of the reverse proxies in front of this in production. + It does nothing if the header is not present. + """ + + def __init__(self, app): + self.app = app + + def __call__(self, environ, start_response): + host = environ.get("HTTP_X_EXTERNAL_HOST", "") + if host: + environ["HTTP_HOST"] = host + return self.app(environ, start_response) diff --git a/butterrobot/platforms/base.py b/butterrobot/platforms/base.py index b7dd352..f92d665 100644 --- a/butterrobot/platforms/base.py +++ b/butterrobot/platforms/base.py @@ -1,4 +1,4 @@ -from abc import abstractclassmethod +from abc import abstractmethod from dataclasses import dataclass @@ -23,14 +23,45 @@ class Platform: @classmethod def init(cls, app): + """ + Initialises the platform. + + Used at the application launch to prepare anything required for + the platform to work.. + + It receives the flask application via parameter in case the platform + requires for custom webservice endpoints or configuration. + """ + pass + + @classmethod + @abstractmethod + def parse_incoming_message(cls, request) -> 'Message': + """ + Parses the incoming request and returns a :class:`butterrobot.objects.Message` instance. + """ + pass + + @classmethod + @abstractmethod + def parse_channel_name_from_raw(cls, channel_raw) -> str: + """ + Extracts the Channel name from :class:`butterrobot.objects.Channel.channel_raw`. + """ + pass + + @classmethod + @abstractmethod + def parse_channel_from_message(cls, channel_raw) -> 'Channel': + """ + Extracts the Channel raw data from the message received in the incoming webhook. + """ pass class PlatformMethods: - @abstractclassmethod - def send_message(cls, message): - pass - - @abstractclassmethod - def reply_message(cls, message, reply_to): + @classmethod + @abstractmethod + def send_message(cls, message: 'Message'): + """Method used to send a message via the platform""" pass diff --git a/tests/test_objects.py b/tests/test_objects.py new file mode 100644 index 0000000..1388dbd --- /dev/null +++ b/tests/test_objects.py @@ -0,0 +1,16 @@ +from butterrobot.objects import Channel, ChannelPlugin + + +def test_channel_has_enabled_plugin_ok(): + channel = Channel( + platform="debug", + platform_channel_id="debug", + channel_raw={}, + plugins={ + "enabled": ChannelPlugin(id=1, channel_id="test", plugin_id="enabled", enabled=True), + "existant": ChannelPlugin(id=2, channel_id="test", plugin_id="existant"), + } + ) + assert not channel.has_enabled_plugin("non.existant") + assert not channel.has_enabled_plugin("existant") + assert channel.has_enabled_plugin("enabled")