import os import json import time import sqlite3 import threading import datetime as dt import MySQLdb as mysql from matrix_bot_api.mregex_handler import MRegexHandler CONFIG_LOCATION = os.path.join(os.path.dirname(__file__), 'config.json') HELP_LOCATION = os.path.join(os.path.dirname(__file__), 'help') NEW_EVENT_LOCATION = os.path.join(os.path.dirname(__file__), 'new_event') class Plugin: """ Description of event plugin """ def __init__(self, bot): # Load the configuration with open(CONFIG_LOCATION) as json_data: self.config = json.load(json_data) # Define sensitivity self.handler = MRegexHandler("Peter evenementen", self.callback) # Save parent bot self.bot = bot # Start thread to check events self.event_thread = threading.Thread(target=self.check_new_event_thread) self.event_thread.start() self.setup() def setup(self): """This function only runs once, ever. It initializes the necessary SQLite tables.""" try: # Define query to INSERT event table to SQLite DB sql = """CREATE TABLE 'events' ( 'dat_id' integer, 'datetime_posted' datetime);""" # Open, execute, commit, and close SQLite database sqlite_db = sqlite3.connect('data/bot.db') sqlite_cursor = sqlite_db.cursor() sqlite_cursor.execute(sql) sqlite_db.commit() sqlite_db.close() except sqlite3.OperationalError: # Table already exists, do nothing pass def check_new_event_thread(self): while not self.bot.cancel: self.check_new_event() def check_new_event(self): """ Check every minutes for new events in the database. Since the check will only be performed every minutes, the connection to the database will not be kept open. As soon as an event is posted to the defined room, its ID is saved in an SQLite database. """ # Connect to database mysql_db = mysql.connect( user = self.config['database_credentials']['username'], password = self.config['database_credentials']['password'], database = self.config['database_credentials']['database']) mysql_cursor = mysql_db.cursor() # Grab all events from database that start in the future select_sql = """SELECT dat_id, dat_cat_id, dat_headline, dat_begin, dat_end FROM adm_dates WHERE dat_begin >'{}'""".format( dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) mysql_cursor.execute(select_sql) # Fetch events results = mysql_cursor.fetchall() mysql_db.close() # Open SQLite database sqlite_db = sqlite3.connect('data/bot.db') sqlite_cursor = sqlite_db.cursor() # Define query to SELECT event from SQLite DB select_sql = """SELECT dat_id FROM events WHERE dat_id = {}""" insert_sql = """INSERT INTO events(dat_id, datetime_posted) VALUES(:dat_id, :datetime_posted)""" # Loop through event for row in results: # First, check if a message on this event was already sent sqlite_cursor.execute(select_sql.format(row[0])) if sqlite_cursor.fetchall(): # Do nothing. This event was already processed pass else: # This appears to be a new event. Process it! # Generate links base_date_url = "{}{}".format( self.config['base_url_adm'], "/adm_program/modules/dates/") view_link = "{}dates.php?id={}&view_mode=html&" view_link += "view=detail&headline={}" view_link = view_link.format(base_date_url, row[0], row[2]) function_link = "{}dates_function.php?mode={}&dat_id={}&" attend_link = function_link.format(base_date_url, '3', row[0]) maybe_link = function_link.format(base_date_url, '7', row[0]) cancel_link = function_link.format(base_date_url, '4', row[0]) new_event = open(NEW_EVENT_LOCATION, mode="r").read() # First, write to SQLite database that it is processed sqlite_cursor.execute( insert_sql, { 'dat_id':row[0], 'datetime_posted': dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}) # Check role ID of event and check if config defines # where it should be shared. for mapping in self.config['cat_id_room_mapping']: if row[1] in mapping[0]: # We got a winner! for i, room in self.bot.client.get_rooms().items(): if room.display_name in mapping[1]: room.send_html( new_event.format( row[3].strftime("%d-%m-%Y"), row[3].strftime("%H:%M"), row[2], view_link, attend_link, maybe_link, cancel_link)) # Commit and close queries sqlite_db.commit() sqlite_db.close() # Sleep #time.sleep(self.config['update_time_span'] * 60) time.sleep(1) def callback(self, room, event): room.send_text("Information ") def help(self): return open(HELP_LOCATION, mode="r").read()