Skip to content

Commit

Permalink
Add DataStore and DataStore Interactions
Browse files Browse the repository at this point in the history
DataStoreInteractions are data that is related to a message or interaction that needs to be retrieved when a user responds to a message.

Notes:
DataStoreInteractions will auto be retrieved using the original channel and ts of the message the user is responding to.

In most cases the response from the plugin is the json response from slack of sending a message. This data will be autolinked to the new_interaction object in the request. If there is no new_interaction set by the plugin, it will be skipped. It can also be skipped by setting request.auto_link to False.

You can create more than one interaction entry per request, it will just have to be done manually using the functions added to the request module.

TODO:
Need to add in a function to look for all interactions that have not been followed up and that the followup_ts has passed. In these cases it should take the bot and followup_action and execute them.

Also we may need to purge old interactions in the datastore every once in a while
  • Loading branch information
zpriddy committed Apr 16, 2020
2 parents ad7bd75 + 0c6431e commit 0f09a3b
Show file tree
Hide file tree
Showing 11 changed files with 666 additions and 5 deletions.
7 changes: 7 additions & 0 deletions docs-src/glados.db.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
glados.db module
=================

.. automodule:: glados.db
:members:
:no-undoc-members:
:show-inheritance:
1 change: 1 addition & 0 deletions docs-src/glados.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Submodules
glados.bot
glados.configs
glados.core
glados.db
glados.errors
glados.message_blocks
glados.plugin
Expand Down
1 change: 1 addition & 0 deletions docs-src/modules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ glados
glados.bot
glados.configs
glados.core
glados.db
glados.errors
glados.message_blocks
glados.plugin
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ install_requires =
slackclient==2.5.0 # fixes bug with LinkButtonElement
pyyaml
requests
sqlalchemy[postgresql]

[options.packages.find]
where=src
Expand Down
2 changes: 2 additions & 0 deletions src/glados/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
from .utils import PyJSON, get_var, get_enc_var

from .db import DataStore, DataStoreInteraction
from .route_type import RouteType, EventRoutes, BOT_ROUTES, VERIFY_ROUTES
from .request import GladosRequest, SlackVerification
from .errors import (
Expand All @@ -17,6 +18,7 @@
from .configs import GladosConfig
from .utils import read_config


from .core import Glados

# LOGGING_FORMAT = "%(asctime)s :: %(levelname)-8s :: [%(filename)s:%(lineno)s :: %(funcName)s() ] %(message)s"
Expand Down
82 changes: 80 additions & 2 deletions src/glados/core.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List, Dict, TYPE_CHECKING
from typing import List, Dict, TYPE_CHECKING, Optional
import yaml
import logging

Expand All @@ -10,6 +10,7 @@
BotImporter,
PluginImporter,
read_config,
DataStore,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -37,6 +38,8 @@ def __init__(
self.logging_level = logging.getLevelName("DEBUG")
self.logging_format = "%(asctime)s :: %(levelname)-8s :: [%(filename)s:%(lineno)s :: %(funcName)s() ] %(message)s"
self.global_config = None
self.enable_datastore = False
self.datastore = None # type: Optional[DataStore]

def read_config(self, bot_name=None):
# TODO: Fix logging setup
Expand Down Expand Up @@ -73,6 +76,43 @@ def read_config(self, bot_name=None):
if import_plugins == "limited":
self.import_plugins(bot_name=bot_name)

# Config datastore
if "datastore" in self.global_config.sections:
ds_config = self.global_config.config.datastore
ds_enabled = ds_config.get("enabled", False)
ds_host = ds_config.get("host")
ds_port = ds_config.get("port", 5432)
ds_username = ds_config.get("username")
ds_password = ds_config.get("password")
ds_database = ds_config.get("database", "glados")
ds_recreate = ds_config.get("recreate", False)
if None in [
ds_enabled,
ds_host,
ds_port,
ds_username,
ds_password,
ds_database,
]:
logging.warning(
"missing datastore config item(s) or datastore disabled. disabling datastore."
)
self.enable_datastore = False
else:
self.enable_datastore = ds_enabled
if ds_enabled:
self.datastore = DataStore(
host=ds_host,
port=ds_port,
username=ds_username,
password=ds_password,
database=ds_database,
)
self.datastore.create_table(force=ds_recreate)
else:
logging.warning("datastore section not found in config file")
self.enable_datastore = False

def import_bots(self):
"""Import all discovered bots"""
logging.info("importing bots...")
Expand Down Expand Up @@ -136,9 +176,18 @@ def add_bot(self, bot: GladosBot):
"""
self.bots[bot.name] = bot

def has_datastore(self):
return (
True
if self.enable_datastore is True and self.datastore is not None
else False
)

def request(self, request: GladosRequest):
"""Send a request to GLaDOS.
This function will also set the datastore session for the request, try to find the interaction in the datastore and fetch it. This info is available in the request.
Parameters
----------
request : GladosRequest
Expand All @@ -148,4 +197,33 @@ def request(self, request: GladosRequest):
-------
"""
return self.router.exec_route(request)
# DataStore actions if enabled
if self.has_datastore():
try:
request.set_datastore(self.datastore)
request.set_interaction_from_datastore()
except Exception as e:
logging.error(
f"error setting up datastore or retrieving interaction : {e} for request: {request}"
)

response = self.router.exec_route(request)

if self.has_datastore() and request.auto_link and request.new_interaction:
try:
request.link_interaction_to_message_response(
request.new_interaction, response
)
except Exception as e:
logging.error(
f"error linking response to interaction: {e} response: {response}"
)
request._session.rollback()
finally:
request.close_session()
return response

elif self.has_datastore():
request.close_session()

return response

0 comments on commit 0f09a3b

Please sign in to comment.