def test_nested_logs(self): log = Log('main', log_to_file=True) c_log = None for i in range(10): if c_log is None: c_log = Log(log, child_name=f'child_{i}') else: c_log = Log(c_log, child_name=f'child_{i}')
def test_child_log(self): parent = Log('parent', log_level_str='DEBUG') # Regular child - should inherit level child_1 = Log(parent, child_name='child_1') # Child 2 should have a different log leve child_2 = Log(parent, child_name='child_2', log_level_str='WARN') # Child of a child test child_child = Log(child_1, child_name='child^2') self.assertTrue(not parent.is_child) self.assertTrue(child_1.log_level_int == parent.log_level_int) self.assertTrue(child_2.log_level_int != parent.log_level_int) child_child.close() child_2.close() child_1.close() parent.close()
def test_filehandler(self): log = Log('test-filehandler', log_to_file=True) log2 = Log(log, child_name='child') self.assertTrue(log2.log_to_file) self.assertTrue(log.log_path == log2.log_path) self.assertTrue(len(log.log_obj.handlers) == 2) self.assertTrue(len(log2.log_obj.handlers) == 0) log.error('Test exception') log2.info('test') log3 = Log(log2, child_name='child of child') log2.warning('Hello!') log3.info('HI!') log3.close() log2.close() log.close()
def test_orphan(self): """Test that handlers are still made in the instance of an orphaned child log""" log = Log(None, child_name='child', log_to_file=True) log.info('Test') with self.assertRaises(ValueError) as err: raise ValueError('Test') log.close()
def __init__(self, credstore: SecretStore, slack_cred_name: str, parent_log: Log): """ Args: creds: dict, contains tokens & other secrets for connecting & interacting with Slack required keys: team: str, the Slack workspace name xoxp-token: str, the user token xoxb-token: str, the bot token optional keys: cookie: str, cookie used for special processes outside the realm of common API calls e.g., emoji uploads parent_log: the parent log to attach to. """ self.log = Log(parent_log, child_name=self.__class__.__name__) slack_creds = credstore.get_key_and_make_ns(slack_cred_name) self.gsr = GSheetReader(sec_store=credstore, sheet_key=slack_creds.spreadsheet_key) self.team = slack_creds.team # Grab tokens self.xoxp_token = slack_creds.xoxp_token self.xoxb_token = slack_creds.xoxb_token self.cookie = slack_creds.cookie self.bkb = BlockKitBuilder() self.user = WebClient(self.xoxp_token) self.bot = WebClient(self.xoxb_token) # Test API calls to the bot self.bot_id = self.bot.auth_test() self.session = self._init_session() if self.cookie != '' else None
def setUp(self, bot='viktor') -> None: # Read in the kdbx secret for unlocking the database secretprops = {} with open(os.path.abspath('../secretprops.properties'), 'r') as f: contents = f.read().split('\n') for item in contents: key, value = item.split('=', 1) secretprops[key] = value.strip() slacktools_secret = secretprops['slacktools_secret'] credstore = SecretStore('secretprops-bobdev.kdbx', slacktools_secret) _log = Log('slacktools-test', log_level_str='DEBUG') self.st = SlackTools(credstore=credstore, slack_cred_name=bot, parent_log=_log) bot_dict = keys[bot] self.test_channel = bot_dict['test_channel'] self.test_user = bot_dict['test_user'] self.bkb = BlockKitBuilder()
def test_none_log(self): log = Log() self.assertTrue(isinstance(log.log_name, str)) self.assertTrue(isinstance(log.name, str)) log.error('Test') log.close()
def __init__(self, log_name: str, slack_cred_name: str, triggers: List[str], credstore: SecretStore, test_channel: str, commands: dict, cmd_categories: List[str], debug: bool = False): """ Args: log_name: str, log name of kavalkilu.Log object for logging special events triggers: list of str, any specific text trigger to kick off the bot's processing of commands default: None. (i.e., will only trigger on @mentions) credstore: SimpleNamespace, contains tokens & other secrets for connecting & interacting with Slack required keys: team: str, the Slack workspace name xoxp-token: str, the user token xoxb-token: str, the bot token optional keys: cookie: str, cookie used for special processes outside the realm of common API calls e.g., emoji uploads test_channel: str, the channel to send messages by default commands: dict, all the commands the bot recognizes (to be built into help text) expected keys: cat: str, the category of the command (for grouping purposes) - must match with categories list desc: str, description of the command value: str or list of func & str, the object to return / command to run optional keys: pattern: str, the human-readable match pattern to show end users flags: list of dict, shows optional flags to include int he command and what they do expected keys: pattern: str, the flag pattern desc: str, the description of this flag cmd_categories: list of str, the categories to group the above commands in to debug: bool, if True, will provide additional info into exceptions """ self._log = Log(log_name) super().__init__(credstore=credstore, slack_cred_name=slack_cred_name, parent_log=self._log) self.debug = debug self.dt = DateTools() # Enforce lowercase triggers (regex will be indifferent to case anyway if triggers is not None: triggers = list(map(str.lower, triggers)) # Set triggers to @bot and any custom text trigger_formatted = '|{}'.format( '|'.join(triggers)) if triggers is not None else '' self.MENTION_REGEX = r'^(<@(|[WU].+?)>{})([.\s\S ]*)'.format( trigger_formatted) self.test_channel = test_channel self.bkb = BlockKitBuilder() self.commands = commands self.cmd_categories = cmd_categories auth_test = self.bot.auth_test() self.bot_id = auth_test['bot_id'] self.user_id = auth_test['user_id'] self.triggers = [f'{self.user_id}'] # User ids are formatted in a different way, so just # break this out into a variable for displaying in help text self.triggers_txt = [f'<@{self.user_id}>'] if triggers is not None: # Add in custom text triggers, if any self.triggers += triggers self.triggers_txt += triggers # This is a data store of handled past message hashes to help enforce only one action per command issued # This was mainly built as a response to occasional duplicate responses # due to delay in Slack receiving a response. I've yet to figure out how to improve response time self.message_events = []
import os import json import requests import signal from typing import Dict from flask import Flask, request, make_response from slacktools import SlackEventAdapter, SecretStore from easylogger import Log from kavalkilu import Path from .utils import CAHBot bot_name = 'wizzy' DEBUG = os.environ['CAH_DEBUG'] == '1' kpath = Path() logg = Log(bot_name) def read_props() -> Dict[str, str]: props = {} with open(os.path.abspath('./secretprops.properties'), 'r') as f: contents = f.read().split('\n') for item in contents: if item != '': key, value = item.split('=', 1) props[key] = value.strip() return props secretprops = read_props() credstore = SecretStore('secretprops-bobdev.kdbx', secretprops['slacktools_secret'])