Compare commits
9 Commits
7b3498bd27
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 1f14b7e9ab | |||
| 882f2a7982 | |||
| b427531896 | |||
| 465a4c2f03 | |||
| 2c48fd997e | |||
| 3f54ab362e | |||
| ea8809b7d9 | |||
| 9975f1ea08 | |||
| 5235ee3169 |
19
event_reminders.json
Normal file
19
event_reminders.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"Orga & Finanzen Plenum": {
|
||||||
|
"days": 1,
|
||||||
|
"message": "hey there everyone🦓 hope you are all. okay💖 who is able to attend plenary tomorrow? please give thumbs up or down to know 👎🏽👍🏽"
|
||||||
|
},
|
||||||
|
"Open Library": {
|
||||||
|
"days": 1,
|
||||||
|
"message": "Who is able to attend open library on tuesday? please give thumbs up or down to know 👎🏽👍🏽. Also fill out the pad please <3"
|
||||||
|
},
|
||||||
|
"Malo Gesamtplenum": {
|
||||||
|
"days": 3,
|
||||||
|
"message": "Who is able to attend Gesamtplenum?? please give thumbs up or down to know 👎🏽👍🏽."
|
||||||
|
},
|
||||||
|
"malo (A)ction Day + Socializing": {
|
||||||
|
"days": 5,
|
||||||
|
"message": "This week is malo actionday! Saturday at 3pm. Are you able to come?? please give thumbs up or down to know 👎🏽👍🏽."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -17,4 +17,6 @@ my_project_name.egg-info/PKG-INFO
|
|||||||
my_project_name.egg-info/SOURCES.txt
|
my_project_name.egg-info/SOURCES.txt
|
||||||
my_project_name.egg-info/dependency_links.txt
|
my_project_name.egg-info/dependency_links.txt
|
||||||
my_project_name.egg-info/requires.txt
|
my_project_name.egg-info/requires.txt
|
||||||
my_project_name.egg-info/top_level.txt
|
my_project_name.egg-info/top_level.txt
|
||||||
|
tests/test_callbacks.py
|
||||||
|
tests/test_config.py
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -4,7 +4,23 @@ from my_project_name.chat_functions import react_to_event, send_text_to_room
|
|||||||
from my_project_name.config import Config
|
from my_project_name.config import Config
|
||||||
from my_project_name.storage import Storage
|
from my_project_name.storage import Storage
|
||||||
from my_project_name.caldav_handler import CaldavHandler
|
from my_project_name.caldav_handler import CaldavHandler
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
|
|
||||||
|
def task_help():
|
||||||
|
api_url = "https://tasklist.malobeo.org/api/next"
|
||||||
|
response = requests.get(api_url)
|
||||||
|
|
||||||
|
if response.status_code != 200:
|
||||||
|
return "Error requesting " + api_url + " Status Code: " + str(response.status_code)
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
message = "# Tasks for this week\n"
|
||||||
|
for task in data:
|
||||||
|
message += "- **{}** (*{}*): {}\n".format(task["Name"], task["Value"], task["Description"])
|
||||||
|
|
||||||
|
return message
|
||||||
|
|
||||||
class Command:
|
class Command:
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -53,6 +69,8 @@ class Command:
|
|||||||
await self._show_week()
|
await self._show_week()
|
||||||
elif self.command.startswith("month"):
|
elif self.command.startswith("month"):
|
||||||
await self._show_month()
|
await self._show_month()
|
||||||
|
elif self.command.startswith("tasks"):
|
||||||
|
await self._show_tasks()
|
||||||
#else:
|
#else:
|
||||||
# await self._unknown_command()
|
# await self._unknown_command()
|
||||||
|
|
||||||
@@ -73,6 +91,10 @@ class Command:
|
|||||||
response = handler.print_month()
|
response = handler.print_month()
|
||||||
await send_text_to_room(self.client, self.room.room_id, response, markdown_convert=True)
|
await send_text_to_room(self.client, self.room.room_id, response, markdown_convert=True)
|
||||||
|
|
||||||
|
async def _show_tasks(self):
|
||||||
|
response = task_help()
|
||||||
|
await send_text_to_room(self.client, self.room.room_id, response, markdown_convert=True)
|
||||||
|
|
||||||
async def _echo(self):
|
async def _echo(self):
|
||||||
"""Echo back the command's arguments"""
|
"""Echo back the command's arguments"""
|
||||||
response = " ".join(self.args)
|
response = " ".join(self.args)
|
||||||
@@ -107,7 +129,7 @@ class Command:
|
|||||||
if topic == "rules":
|
if topic == "rules":
|
||||||
text = "be nice to each other."
|
text = "be nice to each other."
|
||||||
elif topic == "commands":
|
elif topic == "commands":
|
||||||
text = "Available commands: today, week, month"
|
text = "Available commands: today, week, month, tasks"
|
||||||
else:
|
else:
|
||||||
text = "I dont know what you are talking about.."
|
text = "I dont know what you are talking about.."
|
||||||
await send_text_to_room(self.client, self.room.room_id, text)
|
await send_text_to_room(self.client, self.room.room_id, text)
|
||||||
|
|||||||
@@ -15,16 +15,18 @@ import caldav
|
|||||||
|
|
||||||
class CaldavHandler:
|
class CaldavHandler:
|
||||||
def get_config(self, path):
|
def get_config(self, path):
|
||||||
with open("./config.json") as f:
|
with open(path) as f:
|
||||||
return json.load(f)
|
return json.load(f)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._config_path = "./config.json"
|
self._config_path = "./config.json"
|
||||||
|
self._event_reminder_path = "./event_reminders.json"
|
||||||
|
|
||||||
if not exists(self._config_path):
|
if not exists(self._config_path):
|
||||||
print("No config file found. Aborting.")
|
print("No config file found. Aborting.")
|
||||||
|
|
||||||
self._config = self.get_config(self._config_path)
|
self._config = self.get_config(self._config_path)
|
||||||
|
self._event_reminder_config = self.get_config(self._event_reminder_path)
|
||||||
self._caldavclient = caldav.DAVClient(self._config["caldav"]["url"],
|
self._caldavclient = caldav.DAVClient(self._config["caldav"]["url"],
|
||||||
username=self._config["caldav"]["username"],
|
username=self._config["caldav"]["username"],
|
||||||
password=self._config["caldav"]["password"])
|
password=self._config["caldav"]["password"])
|
||||||
@@ -74,7 +76,6 @@ class CaldavHandler:
|
|||||||
for event in v:
|
for event in v:
|
||||||
result += "* " + event + "\n"
|
result += "* " + event + "\n"
|
||||||
|
|
||||||
print(result)
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def event_to_string(self, event):
|
def event_to_string(self, event):
|
||||||
@@ -100,6 +101,50 @@ class CaldavHandler:
|
|||||||
events = self.get_events(datetime.date.today(), datetime.date.today() + datetime.timedelta(days=7))
|
events = self.get_events(datetime.date.today(), datetime.date.today() + datetime.timedelta(days=7))
|
||||||
return self.send_events(events, 7)
|
return self.send_events(events, 7)
|
||||||
|
|
||||||
|
def time_to_remind(self, event_name, days_to_remind):
|
||||||
|
events = self.get_events(datetime.date.today(), datetime.date.today() + datetime.timedelta(days=days_to_remind + 1))
|
||||||
|
datetime_to_remind = datetime.date.today() + datetime.timedelta(days=days_to_remind)
|
||||||
|
|
||||||
|
datetime_to_remind = datetime_to_remind.strftime("%x")
|
||||||
|
print(datetime_to_remind)
|
||||||
|
|
||||||
|
#create a map where each day is a key and list of events are the values
|
||||||
|
event_map = self.get_event_map(events, days_to_remind + 1)
|
||||||
|
|
||||||
|
print(datetime_to_remind)
|
||||||
|
print(event_map)
|
||||||
|
if datetime_to_remind not in event_map:
|
||||||
|
return False
|
||||||
|
|
||||||
|
for real_event_name in event_map[datetime_to_remind]:
|
||||||
|
print("real_ev_name:")
|
||||||
|
print(real_event_name)
|
||||||
|
print("ev_name")
|
||||||
|
print(event_name)
|
||||||
|
if event_name in real_event_name:
|
||||||
|
print("found event!")
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def send_reminders(self):
|
||||||
|
print(self._event_reminder_config)
|
||||||
|
|
||||||
|
result = []
|
||||||
|
for event_name in self._event_reminder_config:
|
||||||
|
print("iterating event configs")
|
||||||
|
print(event_name)
|
||||||
|
days = self._event_reminder_config[event_name]["days"]
|
||||||
|
print(days)
|
||||||
|
if not self.time_to_remind(event_name, days):
|
||||||
|
continue
|
||||||
|
reminder_message = self._event_reminder_config[event_name]["message"]
|
||||||
|
result.append(reminder_message)
|
||||||
|
print(reminder_message)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def print_today(self):
|
def print_today(self):
|
||||||
events = self.get_events(datetime.date.today(), datetime.date.today() + datetime.timedelta(days=1))
|
events = self.get_events(datetime.date.today(), datetime.date.today() + datetime.timedelta(days=1))
|
||||||
|
#self.send_reminders()
|
||||||
return self.send_events(events, 1)
|
return self.send_events(events, 1)
|
||||||
|
|||||||
@@ -78,73 +78,75 @@ class Callbacks:
|
|||||||
await command.process()
|
await command.process()
|
||||||
|
|
||||||
async def invite(self, room: MatrixRoom, event: InviteMemberEvent) -> None:
|
async def invite(self, room: MatrixRoom, event: InviteMemberEvent) -> None:
|
||||||
"""Callback for when an invite is received. Join the room specified in the invite.
|
#"""Callback for when an invite is received. Join the room specified in the invite.
|
||||||
|
|
||||||
Args:
|
#Args:
|
||||||
room: The room that we are invited to.
|
# room: The room that we are invited to.
|
||||||
|
|
||||||
event: The invite event.
|
# event: The invite event.
|
||||||
"""
|
#"""
|
||||||
logger.debug(f"Got invite to {room.room_id} from {event.sender}.")
|
#logger.debug(f"Got invite to {room.room_id} from {event.sender}.")
|
||||||
|
|
||||||
# Attempt to join 3 times before giving up
|
## Attempt to join 3 times before giving up
|
||||||
for attempt in range(3):
|
#for attempt in range(3):
|
||||||
result = await self.client.join(room.room_id)
|
# result = await self.client.join(room.room_id)
|
||||||
if type(result) == JoinError:
|
# if type(result) == JoinError:
|
||||||
logger.error(
|
# logger.error(
|
||||||
f"Error joining room {room.room_id} (attempt %d): %s",
|
# f"Error joining room {room.room_id} (attempt %d): %s",
|
||||||
attempt,
|
# attempt,
|
||||||
result.message,
|
# result.message,
|
||||||
)
|
# )
|
||||||
else:
|
# else:
|
||||||
break
|
# break
|
||||||
else:
|
#else:
|
||||||
logger.error("Unable to join room: %s", room.room_id)
|
# logger.error("Unable to join room: %s", room.room_id)
|
||||||
|
|
||||||
# Successfully joined room
|
## Successfully joined room
|
||||||
logger.info(f"Joined {room.room_id}")
|
#logger.info(f"Joined {room.room_id}")
|
||||||
|
return
|
||||||
|
|
||||||
async def _reaction(
|
async def _reaction(
|
||||||
self, room: MatrixRoom, event: UnknownEvent, reacted_to_id: str
|
self, room: MatrixRoom, event: UnknownEvent, reacted_to_id: str
|
||||||
) -> None:
|
) -> None:
|
||||||
"""A reaction was sent to one of our messages. Let's send a reply acknowledging it.
|
#"""A reaction was sent to one of our messages. Let's send a reply acknowledging it.
|
||||||
|
|
||||||
Args:
|
#Args:
|
||||||
room: The room the reaction was sent in.
|
# room: The room the reaction was sent in.
|
||||||
|
|
||||||
event: The reaction event.
|
# event: The reaction event.
|
||||||
|
|
||||||
reacted_to_id: The event ID that the reaction points to.
|
# reacted_to_id: The event ID that the reaction points to.
|
||||||
"""
|
#"""
|
||||||
logger.debug(f"Got reaction to {room.room_id} from {event.sender}.")
|
#logger.debug(f"Got reaction to {room.room_id} from {event.sender}.")
|
||||||
|
|
||||||
# Get the original event that was reacted to
|
## Get the original event that was reacted to
|
||||||
event_response = await self.client.room_get_event(room.room_id, reacted_to_id)
|
#event_response = await self.client.room_get_event(room.room_id, reacted_to_id)
|
||||||
if isinstance(event_response, RoomGetEventError):
|
#if isinstance(event_response, RoomGetEventError):
|
||||||
logger.warning(
|
# logger.warning(
|
||||||
"Error getting event that was reacted to (%s)", reacted_to_id
|
# "Error getting event that was reacted to (%s)", reacted_to_id
|
||||||
)
|
# )
|
||||||
return
|
# return
|
||||||
reacted_to_event = event_response.event
|
#reacted_to_event = event_response.event
|
||||||
|
|
||||||
# Only acknowledge reactions to events that we sent
|
## Only acknowledge reactions to events that we sent
|
||||||
if reacted_to_event.sender != self.config.user_id:
|
#if reacted_to_event.sender != self.config.user_id:
|
||||||
return
|
# return
|
||||||
|
|
||||||
# Send a message acknowledging the reaction
|
## Send a message acknowledging the reaction
|
||||||
reaction_sender_pill = make_pill(event.sender)
|
#reaction_sender_pill = make_pill(event.sender)
|
||||||
reaction_content = (
|
#reaction_content = (
|
||||||
event.source.get("content", {}).get("m.relates_to", {}).get("key")
|
# event.source.get("content", {}).get("m.relates_to", {}).get("key")
|
||||||
)
|
#)
|
||||||
message = (
|
#message = (
|
||||||
f"{reaction_sender_pill} reacted to this event with `{reaction_content}`!"
|
# f"{reaction_sender_pill} reacted to this event with `{reaction_content}`!"
|
||||||
)
|
#)
|
||||||
await send_text_to_room(
|
#await send_text_to_room(
|
||||||
self.client,
|
# self.client,
|
||||||
room.room_id,
|
# room.room_id,
|
||||||
message,
|
# message,
|
||||||
reply_to_event_id=reacted_to_id,
|
# reply_to_event_id=reacted_to_id,
|
||||||
)
|
#)
|
||||||
|
return
|
||||||
|
|
||||||
async def decryption_failure(self, room: MatrixRoom, event: MegolmEvent) -> None:
|
async def decryption_failure(self, room: MatrixRoom, event: MegolmEvent) -> None:
|
||||||
"""Callback for when an event fails to decrypt. Inform the user.
|
"""Callback for when an event fails to decrypt. Inform the user.
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
import threading
|
||||||
import sys
|
import sys
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
import datetime
|
||||||
|
import requests
|
||||||
|
|
||||||
from aiohttp import ClientConnectionError, ServerDisconnectedError
|
from aiohttp import ClientConnectionError, ServerDisconnectedError
|
||||||
from nio import (
|
from nio import (
|
||||||
@@ -16,12 +19,63 @@ from nio import (
|
|||||||
UnknownEvent,
|
UnknownEvent,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from my_project_name.chat_functions import react_to_event, send_text_to_room
|
||||||
|
from my_project_name.caldav_handler import CaldavHandler
|
||||||
|
|
||||||
from my_project_name.callbacks import Callbacks
|
from my_project_name.callbacks import Callbacks
|
||||||
from my_project_name.config import Config
|
from my_project_name.config import Config
|
||||||
from my_project_name.storage import Storage
|
from my_project_name.storage import Storage
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
from datetime import datetime, time
|
||||||
|
|
||||||
|
def weekly_task_reminder():
|
||||||
|
api_url = "https://tasklist.malobeo.org/api/next"
|
||||||
|
response = requests.get(api_url)
|
||||||
|
|
||||||
|
if response.status_code != 200:
|
||||||
|
return "Error requesting " + api_url + " Status Code: " + str(response.status_code)
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
message = "# Weekly Task Reminder\n"
|
||||||
|
for task in data:
|
||||||
|
message += "- {}: **{}**\n".format(task["Name"], task["Value"])
|
||||||
|
|
||||||
|
message += "\n*Write* ```!c tasks``` *to get details about the tasks*"
|
||||||
|
return message
|
||||||
|
|
||||||
|
def is_time_between(begin_time, end_time, check_time=None):
|
||||||
|
# If check time is not given, default to current UTC time
|
||||||
|
check_time = check_time or datetime.utcnow().time()
|
||||||
|
if begin_time < end_time:
|
||||||
|
return check_time >= begin_time and check_time <= end_time
|
||||||
|
else: # crosses midnight
|
||||||
|
return check_time >= begin_time or check_time <= end_time
|
||||||
|
|
||||||
|
async def foo(client):
|
||||||
|
ShouldSendReminder = True
|
||||||
|
while True:
|
||||||
|
print(datetime.today().weekday())
|
||||||
|
await client.sync()
|
||||||
|
if is_time_between(time(9,00), time(10,10)):
|
||||||
|
print("Ist Time to check")
|
||||||
|
if ShouldSendReminder:
|
||||||
|
handler = CaldavHandler()
|
||||||
|
messages = handler.send_reminders()
|
||||||
|
for message in messages:
|
||||||
|
await send_text_to_room(client, "!aRFGSGKGeaBxiEfDMC:matrix.org", message)
|
||||||
|
|
||||||
|
print("Check if its tuesday")
|
||||||
|
if datetime.today().weekday() == 1: #check if its tuesday
|
||||||
|
await send_text_to_room(client, "!aRFGSGKGeaBxiEfDMC:matrix.org", weekly_task_reminder())
|
||||||
|
|
||||||
|
ShouldSendReminder = False
|
||||||
|
else:
|
||||||
|
ShouldSendReminder = True
|
||||||
|
sleep(20)
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
"""The first function that is run when starting the bot"""
|
"""The first function that is run when starting the bot"""
|
||||||
@@ -102,7 +156,22 @@ async def main():
|
|||||||
|
|
||||||
# Login succeeded!
|
# Login succeeded!
|
||||||
|
|
||||||
logger.info(f"Logged in as {config.user_id}")
|
#logger.info(f"Logged in as {config.user_id}")
|
||||||
|
await client.join("!aRFGSGKGeaBxiEfDMC:matrix.org")
|
||||||
|
print("joined room")
|
||||||
|
sleep(5)
|
||||||
|
await client.sync(full_state=True)
|
||||||
|
print(client.rooms)
|
||||||
|
|
||||||
|
#await client.room_send(
|
||||||
|
# # Watch out! If you join an old room you'll see lots of old messages
|
||||||
|
# room_id="!zKwFlsxXpmVhBMdOBa:matrix.org",
|
||||||
|
# message_type="m.room.message",
|
||||||
|
# content={"msgtype": "m.text", "body": "Hello world!"},
|
||||||
|
# )
|
||||||
|
#t = threading.Thread(target = foo, args =(client, ))
|
||||||
|
#t.start()
|
||||||
|
await foo(client)
|
||||||
await client.sync_forever(timeout=30000, full_state=True)
|
await client.sync_forever(timeout=30000, full_state=True)
|
||||||
|
|
||||||
except (ClientConnectionError, ServerDisconnectedError):
|
except (ClientConnectionError, ServerDisconnectedError):
|
||||||
|
|||||||
Reference in New Issue
Block a user