commit cf88a8c46f1cf601d9bca900aa0883448c1c1eed Author: Finn Christiansen Date: Sun Jun 9 19:58:05 2024 +0200 🎉 first commit, prototype-like matrix bot for islamic prayer times diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..9060eea --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +HOMESERVER="https://example.org" +USERNAME="PrayingTimesBotUsername" +PASSWORD="supersecret" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..16403b4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +# created by virtualenv automatically +bin/ +lib/ +pyvenv.cfg +.env +session.txt +tags diff --git a/bot.py b/bot.py new file mode 100644 index 0000000..110ccbc --- /dev/null +++ b/bot.py @@ -0,0 +1,124 @@ +import simplematrixbotlib as botlib +import requests +import datetime +import threading +import pytz +import os +from dotenv import load_dotenv + +load_dotenv() + +creds = botlib.Creds(os.getenv("BOT_HOMESERVER"), os.getenv("BOT_USERNAME"), os.getenv("BOT_PASSWORD")) +bot = botlib.Bot(creds) +PREFIX = '!' +utc = pytz.UTC + +user_locations: dict = {} +user_reminders: dict = {} +user_room_ids: dict = {} + + +@bot.listener.on_message_event +async def echo(room, message): + match = botlib.MessageMatch(room, message, bot, PREFIX) + + if match.is_not_from_this_bot() and match.prefix() and match.command("echo"): + + await bot.api.send_text_message( + room.room_id, " ".join(arg for arg in match.args()) + ) + + +@bot.listener.on_message_event +async def times(room, message): + match = botlib.MessageMatch(room, message, bot, PREFIX) + username = str(message).split(': ')[0] + response = "" + + if match.is_not_from_this_bot() and match.prefix() and match.command("times"): + if username not in user_locations: + response = "Please set your location first using *!set-location City, Country*" + else: + times = get_praying_times(datetime.datetime.today(), username) + + response = "Today's praying times for {}:\n\n".format(user_locations[username]) + response += "\n".join("{}: {}".format(key, value) for key, value in times.items()) + + await bot.api.send_markdown_message(room.room_id, response) + + +@bot.listener.on_message_event +async def usage(room, message): + match = botlib.MessageMatch(room, message, bot, PREFIX) + + response = """ + usage: + - **!set-location** + - **!times** + - **!set-reminder** where X is the number of minutes you want to receive the reminder before praying + """ + + if match.is_not_from_this_bot() and not match.prefix(): + await bot.api.send_markdown_message(room.room_id, response) + + +@bot.listener.on_message_event +async def set_location(room, message): + match = botlib.MessageMatch(room, message, bot, PREFIX) + + response = "" + + if match.is_not_from_this_bot() and match.prefix() and match.command("set-location"): + location = " ".join(arg for arg in match.args()) + username = str(message).split(': ')[0] + user_locations[username] = location + response = "Your location was set to: {}".format(location) + await bot.api.send_markdown_message(room.room_id, response) + + +@bot.listener.on_message_event +async def set_reminder(room, message): + match = botlib.MessageMatch(room, message, bot, PREFIX) + + response = "" + + if match.is_not_from_this_bot() and match.prefix() and match.command("set-reminder"): + minutes = int(match.args()[0]) + username = str(message).split(': ')[0] + + if username not in user_locations: + response = "You did not set your location yet." + await bot.api.send_markdown_message(room.room_id, response) + else: + user_reminders[username] = minutes + user_room_ids[username] = room.room_id + response = "Your reminder was set to {} minutes before praying.".format(minutes) + schedule_reminder(username) + await bot.api.send_markdown_message(room.room_id, response) + + +def get_praying_times(date: datetime.date, username): + day = date.day + month = date.month + year = date.year + times_api_url = 'http://api.aladhan.com/v1/timingsByAddress/{}-{}-{}?address={}&method=7&iso8601=true'.format(day, month, year, user_locations[username]) + times = requests.get(times_api_url) + times = times.json()['data']['timings'] + return times + + +def schedule_reminder(username): + times = get_praying_times(datetime.date.today(), username) + now = utc.localize(datetime.datetime.now(datetime.UTC)) + for prayer, time in times.items(): + praying_time = datetime.datetime.fromisoformat(time) + if praying_time > now: + seconds = int((praying_time - now).total_seconds()) + threading.Timer(seconds - user_reminders[username] * 60, remind, [username]).start() + + +async def remind(username, message): + await bot.api.send_markdown_message(user_room_ids[username], message) + + +bot.run() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..59a0a62 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,36 @@ +aiofiles==23.2.1 +aiohttp==3.9.5 +aiohttp-socks==0.8.4 +aiosignal==1.3.1 +async-timeout==4.0.3 +attrs==23.2.0 +certifi==2024.6.2 +cffi==1.16.0 +charset-normalizer==3.3.2 +cryptography==42.0.8 +frozenlist==1.4.1 +h11==0.14.0 +h2==4.1.0 +hpack==4.0.0 +hyperframe==6.0.1 +idna==3.7 +jsonschema==4.22.0 +jsonschema-specifications==2023.12.1 +Markdown==3.6 +matrix-nio==0.24.0 +multidict==6.0.5 +pillow==10.3.0 +pycparser==2.22 +pycryptodome==3.20.0 +python-cryptography-fernet-wrapper==1.0.4 +python-dotenv==1.0.1 +python-socks==2.4.4 +pytz==2024.1 +referencing==0.35.1 +requests==2.32.3 +rpds-py==0.18.1 +simplematrixbotlib==2.11.0 +toml==0.10.2 +unpaddedbase64==2.1.0 +urllib3==2.2.1 +yarl==1.9.4