Skip to content

Commit

Permalink
Merge pull request #48 from somakeit/11-central-db
Browse files Browse the repository at this point in the history
11 central db
  • Loading branch information
sjefferson99 authored May 8, 2024
2 parents 1448133 + 157c2d4 commit ada2a45
Show file tree
Hide file tree
Showing 21 changed files with 838 additions and 106 deletions.
31 changes: 30 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ services:
dockerfile: smib-fast.Dockerfile
ports:
- "4123:4123"
depends_on:
- smib-db
environment:
- WEBSERVER_HOST=smib-webserver
- WEBSOCKET_ALLOWED_HOSTS=smib-webserver,smib-webserver.smib-bridge-network
- MONGO_DB_HOST=smib-db

# Passed in from HOST
- SLACK_APP_TOKEN
Expand Down Expand Up @@ -36,7 +39,33 @@ services:
- smib-bridge-network
command: "python -m smib.webserver"

smib-db:

# Specific version - latest that works on a pi
image: mongo:4.4.18
container_name: smib-db
restart: always
ports:
- 27017:27017
networks:
- smib-bridge-network

smib-db-ui:
image: mongo-express
container_name: smib-db-ui
depends_on:
- smib-db
restart: always
ports:
- 8082:8081
environment:
ME_CONFIG_MONGODB_URL: mongodb://smib-db:27017/
ME_CONFIG_BASICAUTH: true

networks:
- smib-bridge-network

networks:
smib-bridge-network:
name: smib-bridge-network
driver: bridge
driver: bridge
288 changes: 203 additions & 85 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ fastapi = "^0.110.0"
uvicorn = "^0.29.0"
dataclasses-json = "^0.6.4"
aiohttp = "^3.9.5"
pymongo = "^4.7.0"
mogo = "^0.6.0"


[build-system]
Expand Down
12 changes: 6 additions & 6 deletions smib-fast.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ FROM python:3.11-buster as builder
RUN pip install poetry==1.4.2

# Install tzdata, curl, and jq.
RUN apt-get update && apt-get install -y tzdata curl jq
# RUN apt-get update && apt-get install -y tzdata curl jq

# Fetch the timezone using the API, set the TZ environment variable to the fetched timezone.
RUN TIMEZONE=$(curl -s http://worldtimeapi.org/api/ip | jq -r .timezone) && \
ln -fs /usr/share/zoneinfo/$TIMEZONE /etc/localtime && \
dpkg-reconfigure -f noninteractive tzdata && \
echo "TZ=$TIMEZONE" >> /etc/environment
#RUN TIMEZONE=$(curl -s http://worldtimeapi.org/api/ip | jq -r .timezone) && \
# ln -fs /usr/share/zoneinfo/$TIMEZONE /etc/localtime && \
# dpkg-reconfigure -f noninteractive tzdata && \
# echo "TZ=$TIMEZONE" >> /etc/environment

ENV POETRY_NO_INTERACTION=1 \
POETRY_VIRTUALENVS_IN_PROJECT=1 \
Expand Down Expand Up @@ -40,4 +40,4 @@ COPY --from=builder /etc/localtime /etc/localtime

WORKDIR /app

COPY smib ./smib
COPY smib ./smib
8 changes: 8 additions & 0 deletions smib/common/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@
WEBSOCKET_URL = urlparse(f"{WEBSOCKET_SCHEME}://{WEBSOCKET_HOST}:{WEBSOCKET_PORT}/{WEBSOCKET_PATH}")
WEBSOCKET_ALLOWED_HOSTS = config('WEBSOCKET_ALLOWED_HOSTS', default='localhost,127.0.0.1,::1', cast=Csv())

MONGO_DB_HOST = config('MONGO_DB_HOST', default='localhost')
MONGO_DB_PORT = config('MONGO_DB_PORT', default=27017, cast=int)

MONGO_DB_DEFAULT_DB = config("MONGO_DB_DEFAULT_DB", default="smib_default")
MONGO_DB_CONNECT_TIMEOUT_SECONDS = config("MONGO_DB_CONNECT_TIMEOUT_SECONDS", default=5, cast=int)

MONGO_DB_URL = f"mongodb://{MONGO_DB_HOST}:{MONGO_DB_PORT}/"

PLUGINS_DIRECTORY = config('PLUGINS_DIRECTORY', default=ROOT_DIRECTORY / 'slack' / 'plugins', cast=Path)

SPACE_OPEN_ANNOUNCE_CHANNEL_ID = config('SPACE_OPEN_ANNOUNCE_CHANNEL_ID', default='C06UDPLQRP1')
16 changes: 5 additions & 11 deletions smib/common/logging_/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import logging

from smib.common.config import ROOT_DIRECTORY
from smib.common.utils import get_module_name
from injectable import injectable_factory, load_injection_container, inject


Expand All @@ -16,21 +17,14 @@ def setup_logging(path=ROOT_DIRECTORY / 'logging.json'):
logging.config.dictConfig(read_logging_json(path))


def _get_module_name(stack_num: int = 4):
frame = inspect.stack()[stack_num]
module = inspect.getmodule(frame[0])
module_name = module.__name__
return module_name
@injectable_factory(logging.Logger, qualifier="plugin_logger")
def plugin_logger_factory():
return logging.getLogger(get_module_name(2))


@injectable_factory(logging.Logger, qualifier="logger")
def logger_factory():
return logging.getLogger(_get_module_name())


@injectable_factory(logging.Logger, qualifier="plugin_logger")
def plugin_logger_factory():
return logging.getLogger(_get_module_name(2))
return logging.getLogger(get_module_name(4))


if __name__ == '__main__':
Expand Down
23 changes: 23 additions & 0 deletions smib/common/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import inspect
import logging
import pickle
from pathlib import Path
Expand All @@ -16,6 +17,13 @@ def is_pickleable(obj):
except (pickle.PicklingError, AttributeError, TypeError):
return False

def is_json_encodable(value):
try:
json.dumps(value)
return True
except TypeError:
return False


def to_path(x):
path = Path(f"/{x.lstrip('/')}").as_posix().lstrip('/')
Expand Down Expand Up @@ -65,3 +73,18 @@ def wrapper(*args, **kwargs):
return BoltResponse(status=response[0], body=json.dumps(response[1]))

return wrapper


def get_module_name(stack_num: int = 4):
stack = inspect.stack()
frame = stack[stack_num]
module = inspect.getmodule(frame[0])
module_name = module.__name__
return module_name


def get_module_file(stack_num: int = 4) -> Path:
stack = inspect.stack()
frame = stack[stack_num]
file = inspect.getfile(frame[0])
return Path(file)
3 changes: 3 additions & 0 deletions smib/logging.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@
"tzlocal": {
"level": "WARNING",
"propagate": false
},
"pymongo": {
"level": "WARNING"
}
}
}
39 changes: 39 additions & 0 deletions smib/slack/db/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import functools
import inspect
from pathlib import Path

from injectable import inject
from mogo import Model, Field, connect

from smib.slack.plugin import PluginManager
from smib.common.utils import get_module_file
from smib.common.config import MONGO_DB_URL, MONGO_DB_CONNECT_TIMEOUT_SECONDS


def get_current_plugin_id() -> str:
plugin_manager: PluginManager = inject("PluginManager")
plugin_name = plugin_manager.get_plugin_from_file(get_module_file(2)).id
return plugin_name


def database(database_name: str = None):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
db_name = database_name

# If no database_name parameter name passed in, get current plugin id and use that
if db_name is None:
plugin_file = Path(inspect.getfile(func))
plugin_manager: PluginManager = inject("PluginManager")
db_name = plugin_manager.get_plugin_from_file(plugin_file).id

inject("logger").debug(f"Database name: {db_name}")

# Connect to DB and close it afterward
with connect(db_name, uri=MONGO_DB_URL, timeoutMs=1000*MONGO_DB_CONNECT_TIMEOUT_SECONDS):
return func(*args, **kwargs)

return wrapper

return decorator
5 changes: 3 additions & 2 deletions smib/slack/logging_injector.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from injectable import inject
from smib.common.logging_.setup import plugin_logger_factory



def inject_logger_to_slack_context(context, next):
context['logger'] = inject("plugin_logger", lazy=True)
next()
next()
2 changes: 1 addition & 1 deletion smib/slack/plugin/loaders/abstract_plugin_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def load_plugin(self, plugin_path: Path) -> Plugin:
self.unload_plugin(plugin)

if plugin.error:
logger.error(plugin.error)
logger.error(f"Plugin {plugin.id} failed to load: {plugin.error}")

return returned_plugin

Expand Down
22 changes: 22 additions & 0 deletions smib/slack/plugins/space/openclose/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
__author__ = "Sam Cork"

from injectable import inject

from smib.common.utils import http_bolt_response, is_json_encodable
from smib.slack.custom_app import CustomApp
from slack_sdk import WebClient
from slack_sdk.models.views import View
from slack_sdk.models.blocks import ActionsBlock, PlainTextObject, HeaderBlock, ButtonElement

from .models import Space

from smib.common.config import SPACE_OPEN_ANNOUNCE_CHANNEL_ID
from smib.slack.db import database

app: CustomApp = inject("SlackApp")

Expand Down Expand Up @@ -45,17 +50,34 @@ def app_home_opened(client: WebClient, event: dict):

@app.action('space_open')
@app.event('http_put_space_open')
@database()
def space_open(say, context, ack):

ack()
context['logger'].debug("Space Open!")
say(text='Space Open!', channel=SPACE_OPEN_ANNOUNCE_CHANNEL_ID)

space: Space = Space.single()
space.set_open()


@app.action('space_closed')
@app.event('http_put_space_closed')
@database()
def space_closed(say, context, ack):

ack()
context['logger'].debug("Space Closed!")

say(text='Space Closed!', channel=SPACE_OPEN_ANNOUNCE_CHANNEL_ID)

space: Space = Space.single()
space.set_closed()


@app.event("http_get_space_state")
@http_bolt_response
@database()
def get_space_state():
space = Space.single()
return {k: v for k, v in space.copy().items() if is_json_encodable(v)}
17 changes: 17 additions & 0 deletions smib/slack/plugins/space/openclose/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from smib.slack.db import Model, Field


class Space(Model):
open: bool = Field[bool](default=None)

@classmethod
def single(cls):
return cls.find_one() or cls()

def set_open(self):
self.open = True
self.save()

def set_closed(self):
self.open = False
self.save()
Loading

0 comments on commit ada2a45

Please sign in to comment.