Compare commits

...

9 Commits

Author SHA1 Message Date
1f14b7e9ab fix sync and task reminder 2024-06-18 11:53:06 +02:00
882f2a7982 update 2024-06-17 22:15:47 +02:00
b427531896 add tasks to commands 2024-06-17 21:58:13 +02:00
465a4c2f03 add task reminder 2024-06-17 21:56:53 +02:00
2c48fd997e add malo action day event reminder 2023-10-04 15:34:52 +02:00
3f54ab362e add bad event reminder functions 2023-02-13 16:07:35 +01:00
ea8809b7d9 add reminder functionality 2023-02-13 14:34:33 +01:00
9975f1ea08 remove invite and react callbacks 2021-08-02 22:55:26 +02:00
5235ee3169 dont print events 2021-08-02 22:48:07 +02:00
16 changed files with 217 additions and 58 deletions

19
event_reminders.json Normal file
View 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 👎🏽👍🏽."
}
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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.

View File

@@ -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):