2019-01-06 15:01:01 +00:00
|
|
|
__author__ = "Dennis Potter"
|
|
|
|
__copyright__ = "Copyright 2019, Dennis Potter"
|
|
|
|
__credits__ = ["Dennis Potter"]
|
|
|
|
__license__ = "GPL-3.0"
|
2019-01-12 14:13:21 +00:00
|
|
|
__version__ = "0.5.0"
|
2019-01-06 15:01:01 +00:00
|
|
|
__maintainer__ = "Dennis Potter"
|
|
|
|
__email__ = "dennis@dennispotter.eu"
|
|
|
|
|
2018-12-16 15:38:47 +00:00
|
|
|
import os
|
2019-01-14 22:47:38 +00:00
|
|
|
import hjson
|
2018-12-16 15:38:47 +00:00
|
|
|
import time
|
|
|
|
import sqlite3
|
|
|
|
import threading
|
2019-02-02 15:16:37 +00:00
|
|
|
import importlib
|
|
|
|
import sys
|
2018-12-16 15:38:47 +00:00
|
|
|
import datetime as dt
|
|
|
|
|
|
|
|
from matrix_bot_api.mregex_handler import MRegexHandler
|
|
|
|
|
2019-02-02 15:16:37 +00:00
|
|
|
sys.path.insert(0, os.path.dirname(__file__))
|
|
|
|
|
|
|
|
import admidio_python_api.admidio as admidio
|
|
|
|
import admidio_python_api.group as group
|
|
|
|
|
2019-01-14 22:47:38 +00:00
|
|
|
MESSAGES_DIR = os.path.join(os.path.dirname(__file__), 'messages')
|
2019-01-13 11:51:57 +00:00
|
|
|
DATA_DIR = os.path.join(os.path.dirname(__file__),'../../data/events')
|
2019-01-14 22:47:38 +00:00
|
|
|
CONFIG_LOCATION = os.path.join(os.path.dirname(__file__), 'config.hjson')
|
2019-01-13 11:51:57 +00:00
|
|
|
|
|
|
|
DATA_LOCATION = DATA_DIR + '/data.db'
|
2019-01-14 22:47:38 +00:00
|
|
|
HELP_LOCATION = MESSAGES_DIR + '/help'
|
|
|
|
MESSAGES_LOCATION = MESSAGES_DIR + '/messages.dutch.hjson'
|
2018-12-16 15:38:47 +00:00
|
|
|
|
|
|
|
class Plugin:
|
2019-01-12 14:13:21 +00:00
|
|
|
""" This plugin grabs events from Admidio (https://admidio.org)
|
|
|
|
and lets users interact with the data
|
|
|
|
"""
|
2018-12-16 15:38:47 +00:00
|
|
|
def __init__(self, bot):
|
|
|
|
# Load the configuration
|
2019-01-14 22:47:38 +00:00
|
|
|
with open(CONFIG_LOCATION) as hjson_data:
|
|
|
|
self.config = hjson.load(hjson_data)
|
2018-12-16 15:38:47 +00:00
|
|
|
|
2019-01-06 15:01:01 +00:00
|
|
|
# Load all messages for this plugin
|
2019-01-14 22:47:38 +00:00
|
|
|
with open(MESSAGES_LOCATION) as hjson_data:
|
|
|
|
self.messages = hjson.load(hjson_data)
|
2019-01-06 15:01:01 +00:00
|
|
|
|
2019-02-02 15:16:37 +00:00
|
|
|
self.adm = admidio.Admidio(
|
|
|
|
self.config['database_credentials']['host'],
|
|
|
|
self.config['database_credentials']['username'],
|
|
|
|
self.config['database_credentials']['password'],
|
|
|
|
self.config['database_credentials']['database'],
|
|
|
|
self.config['database_credentials']['adm_prefix'])
|
|
|
|
|
2018-12-16 15:38:47 +00:00
|
|
|
# Define sensitivity
|
2019-01-06 15:01:01 +00:00
|
|
|
self.handler = []
|
|
|
|
|
2019-02-27 18:08:09 +00:00
|
|
|
self.handler.append(MRegexHandler(
|
|
|
|
"Peter evenementen lijst",
|
|
|
|
self.list_callback,
|
|
|
|
bot))
|
|
|
|
|
|
|
|
self.handler.append(MRegexHandler(
|
|
|
|
"Peter evenementen info",
|
|
|
|
self.info_callback,
|
|
|
|
bot))
|
|
|
|
|
|
|
|
self.handler.append(MRegexHandler(
|
|
|
|
"Peter evenementen chat",
|
|
|
|
self.chat_callback,
|
|
|
|
bot))
|
|
|
|
|
|
|
|
self.handler.append(MRegexHandler(
|
|
|
|
"Peter evenementen deelnemers",
|
|
|
|
self.participants_callback,
|
|
|
|
bot))
|
2018-12-16 15:38:47 +00:00
|
|
|
|
|
|
|
# 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()
|
|
|
|
|
2019-02-03 12:35:16 +00:00
|
|
|
def ready_block(self):
|
|
|
|
while (not self.adm.ready):
|
|
|
|
time.sleep(1)
|
2019-01-06 15:01:01 +00:00
|
|
|
|
2018-12-16 15:38:47 +00:00
|
|
|
def check_new_event_thread(self):
|
|
|
|
while not self.bot.cancel:
|
|
|
|
self.check_new_event()
|
|
|
|
|
|
|
|
def check_new_event(self):
|
|
|
|
""" Check every <X> minutes for new events in the database.
|
|
|
|
|
|
|
|
Since the check will only be performed every <X> 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.
|
|
|
|
"""
|
|
|
|
|
2019-02-03 12:35:16 +00:00
|
|
|
# Refresh everything
|
|
|
|
self.adm.refresh()
|
2018-12-16 15:38:47 +00:00
|
|
|
|
|
|
|
# Open SQLite database
|
2019-01-12 14:13:21 +00:00
|
|
|
sqlite_db = sqlite3.connect(DATA_LOCATION)
|
2018-12-16 15:38:47 +00:00
|
|
|
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
|
2019-02-03 12:35:16 +00:00
|
|
|
now = dt.datetime.now()
|
|
|
|
events = (x for (k,x) in self.adm.events.items() if x.start_time > now)
|
|
|
|
|
|
|
|
for (i, event) in enumerate(events):
|
2018-12-16 15:38:47 +00:00
|
|
|
# First, check if a message on this event was already sent
|
2019-02-03 12:35:16 +00:00
|
|
|
sqlite_cursor.execute(select_sql.format(event.id))
|
2018-12-16 15:38:47 +00:00
|
|
|
|
|
|
|
if sqlite_cursor.fetchall():
|
|
|
|
# Do nothing. This event was already processed
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
# This appears to be a new event. Process it!
|
|
|
|
|
|
|
|
# Generate links
|
2019-02-03 12:35:16 +00:00
|
|
|
links = self.generate_links(event.id, event.name)
|
2018-12-16 15:38:47 +00:00
|
|
|
|
|
|
|
# First, write to SQLite database that it is processed
|
|
|
|
sqlite_cursor.execute(
|
|
|
|
insert_sql, {
|
2019-02-03 12:35:16 +00:00
|
|
|
'dat_id':event.id,
|
2018-12-16 15:38:47 +00:00
|
|
|
'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']:
|
2019-02-03 12:35:16 +00:00
|
|
|
if event.cat_id in mapping[0]:
|
2018-12-16 15:38:47 +00:00
|
|
|
# We got a winner!
|
|
|
|
|
2019-01-19 23:41:02 +00:00
|
|
|
for i, room in self.bot.client.rooms.items():
|
2018-12-16 15:38:47 +00:00
|
|
|
if room.display_name in mapping[1]:
|
|
|
|
room.send_html(
|
2019-01-06 15:01:01 +00:00
|
|
|
self.messages["new_event"].format(
|
2019-02-03 12:35:16 +00:00
|
|
|
event.start_time.strftime("%d-%m-%Y"),
|
|
|
|
event.start_time.strftime("%H:%M"),
|
|
|
|
event.name,
|
|
|
|
links['view'],
|
|
|
|
links['attend'],
|
|
|
|
links['maybe'],
|
|
|
|
links['cancel']))
|
2018-12-16 15:38:47 +00:00
|
|
|
|
|
|
|
# Commit and close queries
|
|
|
|
sqlite_db.commit()
|
|
|
|
sqlite_db.close()
|
|
|
|
|
|
|
|
# Sleep
|
2019-01-06 15:01:01 +00:00
|
|
|
time.sleep(self.config['update_time_span'] * 60)
|
|
|
|
|
2019-02-03 12:35:16 +00:00
|
|
|
def generate_links(self, event_id, event_name):
|
|
|
|
links = dict()
|
|
|
|
|
|
|
|
# Define the base URL for users to attend
|
|
|
|
base_dat_url = "{}{}".format(
|
|
|
|
self.config['base_url_adm'],
|
|
|
|
"/adm_program/modules/dates/")
|
|
|
|
|
|
|
|
links['view'] = "{}dates.php?id={}&view_mode=html&"
|
|
|
|
links['view'] += "view=detail&headline={}"
|
|
|
|
links['view'] = links['view'].format(base_dat_url, event_id, event_name)
|
|
|
|
|
|
|
|
function_link = "{}dates_function.php?mode={}&dat_id={}&"
|
|
|
|
|
|
|
|
links['attend'] = function_link.format(base_dat_url, '3', event_id)
|
|
|
|
links['maybe'] = function_link.format(base_dat_url, '7', event_id)
|
|
|
|
links['cancel'] = function_link.format(base_dat_url, '4', event_id)
|
|
|
|
|
|
|
|
return links
|
|
|
|
|
|
|
|
|
2019-01-06 15:01:01 +00:00
|
|
|
def list_callback(self, room, event):
|
2019-02-03 12:35:16 +00:00
|
|
|
self.ready_block()
|
|
|
|
|
2019-01-06 15:01:01 +00:00
|
|
|
number_events = False
|
|
|
|
|
|
|
|
for word in event['content']['body'].split():
|
|
|
|
try:
|
|
|
|
number_events = int(word)
|
|
|
|
break
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
if not number_events:
|
|
|
|
number_events = 10
|
2019-01-12 17:02:34 +00:00
|
|
|
elif number_events <= 0 or number_events > 100:
|
2019-01-06 15:01:01 +00:00
|
|
|
room.send_text(self.messages['list_event_num_err'])
|
|
|
|
number_events = 10
|
|
|
|
|
|
|
|
|
2019-02-02 15:16:37 +00:00
|
|
|
base_date_url = "{}{}".format(
|
|
|
|
self.config['base_url_adm'],
|
|
|
|
"/adm_program/modules/dates/")
|
2019-01-06 15:01:01 +00:00
|
|
|
|
2019-02-02 15:16:37 +00:00
|
|
|
function_link = "{}dates_function.php?mode={}&dat_id={}&"
|
2019-01-06 15:01:01 +00:00
|
|
|
|
2019-02-02 15:16:37 +00:00
|
|
|
now = dt.datetime.now()
|
|
|
|
events = (x for (k,x) in self.adm.events.items() if x.start_time > now)
|
2019-01-06 15:01:01 +00:00
|
|
|
|
|
|
|
# Set header
|
|
|
|
html_message = self.messages['list_events_head'].format(number_events)
|
|
|
|
|
|
|
|
# Loop through fetched events
|
|
|
|
html_message += "<br /><ul>"
|
2019-02-02 15:16:37 +00:00
|
|
|
for (i, event) in enumerate(events):
|
|
|
|
if (i >= number_events):
|
|
|
|
break;
|
2019-01-06 15:01:01 +00:00
|
|
|
|
2019-02-03 12:35:16 +00:00
|
|
|
# Generate links
|
|
|
|
links = self.generate_links(event.id, event.name)
|
2019-01-06 15:01:01 +00:00
|
|
|
|
|
|
|
html_message += "<li>"
|
|
|
|
html_message += self.messages['list_event_item'].format(
|
2019-02-02 15:16:37 +00:00
|
|
|
event.start_time.strftime("%d-%m-%Y"),
|
|
|
|
event.start_time.strftime("%H:%M"),
|
2019-02-03 12:35:16 +00:00
|
|
|
links['view'],
|
2019-02-02 15:16:37 +00:00
|
|
|
event.name,
|
2019-02-03 12:35:16 +00:00
|
|
|
event.id)
|
2019-01-06 15:01:01 +00:00
|
|
|
html_message += "</li>"
|
|
|
|
|
|
|
|
html_message += "</ul>"
|
|
|
|
|
|
|
|
# Send message
|
|
|
|
room.send_html(html_message)
|
|
|
|
|
|
|
|
def info_callback(self, room, event):
|
2019-02-03 12:35:16 +00:00
|
|
|
self.ready_block()
|
|
|
|
|
2019-01-27 16:58:24 +00:00
|
|
|
id_event = False
|
2019-01-06 15:01:01 +00:00
|
|
|
|
2019-01-27 16:58:24 +00:00
|
|
|
for word in event['content']['body'].split():
|
|
|
|
try:
|
|
|
|
id_event = int(word)
|
|
|
|
break
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
if not id_event or id_event < 0:
|
|
|
|
room.send_html(self.messages['info_event_id_err'])
|
|
|
|
return
|
|
|
|
|
2019-02-02 15:16:37 +00:00
|
|
|
try:
|
2019-02-03 12:35:16 +00:00
|
|
|
# Generate links
|
|
|
|
links = self.generate_links(
|
|
|
|
self.adm.events[id_event].id,
|
|
|
|
self.adm.events[id_event].name)
|
2019-01-27 16:58:24 +00:00
|
|
|
|
2019-02-03 12:35:16 +00:00
|
|
|
# Assemble message
|
2019-02-02 15:16:37 +00:00
|
|
|
html_message = self.messages['info_event'].format(
|
2019-02-03 12:35:16 +00:00
|
|
|
links['view'],
|
2019-02-02 15:16:37 +00:00
|
|
|
self.adm.events[id_event].name,
|
|
|
|
self.adm.events[id_event].start_time.strftime("%d-%m-%Y"),
|
|
|
|
self.adm.events[id_event].start_time.strftime("%H:%M"),
|
|
|
|
self.adm.events[id_event].end_time.strftime("%d-%m-%Y"),
|
|
|
|
self.adm.events[id_event].end_time.strftime("%H:%M"),
|
2019-02-03 12:35:16 +00:00
|
|
|
self.adm.events[id_event].description,
|
|
|
|
links['attend'],
|
|
|
|
links['maybe'],
|
|
|
|
links['cancel'])
|
2019-01-27 16:58:24 +00:00
|
|
|
|
2019-02-02 15:16:37 +00:00
|
|
|
# Send message
|
|
|
|
room.send_html(html_message)
|
2019-01-27 16:58:24 +00:00
|
|
|
|
2019-02-02 15:16:37 +00:00
|
|
|
except KeyError:
|
|
|
|
room.send_html(self.messages['unknown_event'])
|
2019-01-27 16:58:24 +00:00
|
|
|
|
|
|
|
|
2019-02-02 15:16:37 +00:00
|
|
|
def participants_callback(self, room, event):
|
2019-02-03 12:35:16 +00:00
|
|
|
self.ready_block()
|
|
|
|
|
2019-02-02 15:16:37 +00:00
|
|
|
id_event = False
|
2019-01-27 16:58:24 +00:00
|
|
|
|
2019-02-02 15:16:37 +00:00
|
|
|
for word in event['content']['body'].split():
|
|
|
|
try:
|
|
|
|
id_event = int(word)
|
|
|
|
break
|
|
|
|
except:
|
|
|
|
pass
|
2019-01-27 16:58:24 +00:00
|
|
|
|
2019-02-02 15:16:37 +00:00
|
|
|
if not id_event or id_event < 0:
|
|
|
|
room.send_html(self.messages['info_event_id_err'])
|
|
|
|
return
|
2018-12-16 15:38:47 +00:00
|
|
|
|
2019-02-02 15:25:32 +00:00
|
|
|
try:
|
|
|
|
# Set header
|
|
|
|
html_message = self.messages['event_participants_head'].format(
|
|
|
|
len(self.adm.events[id_event].getAllAttend()),
|
|
|
|
self.adm.events[id_event].number_of_guests,
|
|
|
|
self.adm.events[id_event].name)
|
2019-02-02 15:16:37 +00:00
|
|
|
|
2019-02-02 15:25:32 +00:00
|
|
|
# Attend
|
|
|
|
html_message += "<br />"
|
|
|
|
html_message += self.messages['event_participants_attend'];
|
2019-02-02 15:16:37 +00:00
|
|
|
|
2019-02-02 15:25:32 +00:00
|
|
|
# Loop through fetched participants
|
|
|
|
html_message += "<ul>"
|
2019-02-02 15:16:37 +00:00
|
|
|
|
2019-02-02 15:25:32 +00:00
|
|
|
for member in self.adm.events[id_event].getAllAttend():
|
|
|
|
html_message += "<li>"
|
|
|
|
html_message += member[1].username
|
|
|
|
html_message += "</li>"
|
2019-02-02 15:16:37 +00:00
|
|
|
|
2019-02-02 15:25:32 +00:00
|
|
|
html_message += "</ul>"
|
2019-02-02 15:16:37 +00:00
|
|
|
|
2019-02-02 15:25:32 +00:00
|
|
|
# Maybe
|
|
|
|
html_message += self.messages['event_participants_maybe'];
|
2019-02-02 15:16:37 +00:00
|
|
|
|
2019-02-02 15:25:32 +00:00
|
|
|
# Loop through fetched participants
|
|
|
|
html_message += "<ul>"
|
2019-02-02 15:16:37 +00:00
|
|
|
|
2019-02-02 15:25:32 +00:00
|
|
|
for member in self.adm.events[id_event].getAllMaybe():
|
|
|
|
html_message += "<li>"
|
|
|
|
html_message += member[1].username
|
|
|
|
html_message += "</li>"
|
2019-02-02 15:16:37 +00:00
|
|
|
|
2019-02-02 15:25:32 +00:00
|
|
|
html_message += "</ul>"
|
2019-02-02 15:16:37 +00:00
|
|
|
|
2019-02-02 15:25:32 +00:00
|
|
|
# Not attend
|
|
|
|
html_message += self.messages['event_participants_not_attend'];
|
2019-02-02 15:16:37 +00:00
|
|
|
|
2019-02-02 15:25:32 +00:00
|
|
|
# Loop through fetched participants
|
|
|
|
html_message += "<ul>"
|
2019-02-02 15:16:37 +00:00
|
|
|
|
2019-02-02 15:25:32 +00:00
|
|
|
for member in self.adm.events[id_event].getAllNotAttend():
|
|
|
|
html_message += "<li>"
|
|
|
|
html_message += member[1].username
|
|
|
|
html_message += "</li>"
|
2019-02-02 15:16:37 +00:00
|
|
|
|
2019-02-02 15:25:32 +00:00
|
|
|
html_message += "</ul>"
|
2019-02-02 15:16:37 +00:00
|
|
|
|
2019-02-02 15:25:32 +00:00
|
|
|
room.send_html(html_message)
|
|
|
|
except KeyError:
|
|
|
|
room.send_html(self.messages['unknown_event'])
|
2018-12-16 15:38:47 +00:00
|
|
|
|
2019-01-27 16:58:24 +00:00
|
|
|
def chat_callback(self, room, event):
|
|
|
|
room.send_text("Chat")
|
|
|
|
|
2018-12-16 15:38:47 +00:00
|
|
|
def help(self):
|
|
|
|
return open(HELP_LOCATION, mode="r").read()
|
2019-01-12 17:02:34 +00:00
|
|
|
|
|
|
|
def setup():
|
|
|
|
"""This function runs only, ever. It initializes the necessary
|
|
|
|
SQLite tables."""
|
|
|
|
|
|
|
|
# Try to make a new directory
|
2019-01-13 11:51:57 +00:00
|
|
|
os.mkdir(DATA_DIR)
|
2019-01-12 17:02:34 +00:00
|
|
|
|
|
|
|
# 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_LOCATION)
|
|
|
|
sqlite_cursor = sqlite_db.cursor()
|
|
|
|
sqlite_cursor.execute(sql)
|
|
|
|
sqlite_db.commit()
|
|
|
|
sqlite_db.close()
|
|
|
|
|