From 99a0a15b9ccd3f14b59a3090f28d675dd711ba98 Mon Sep 17 00:00:00 2001 From: 0ry5 <oscar.bloch@posteo.de> Date: Sat, 12 Apr 2025 00:18:51 +0200 Subject: [PATCH] feat(bot): support recurring events --- bot.py | 102 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 50 insertions(+), 52 deletions(-) diff --git a/bot.py b/bot.py index d1457a5..d4c314e 100644 --- a/bot.py +++ b/bot.py @@ -1,20 +1,21 @@ import json import re + +# needs the following version of discord.py for recurring events to work: https://github.com/DA-344/d.py/tree/recurrent_events import discord -from discord.ext import commands +from discord.ext import commands, tasks from dotenv import load_dotenv from os import getenv -from github_connector import create_or_update_file, delete_file +from github_connector import create_or_update_file, delete_file, similar_exists load_dotenv("./.env") CHANNEL_ID = int(getenv("CHANNEL_ID")) +GUILD_ID = int(getenv("GUILD_ID")) MAINTAINERS = json.loads(getenv("MAINTAINERS")) DISCORD_TOKEN = getenv("DISCORD_TOKEN") -print(MAINTAINERS) - # Intents are required to listen to events like messages intents = discord.Intents.default() intents.message_content = True @@ -26,7 +27,7 @@ intents.dm_messages = True bot = commands.Bot(command_prefix="!", intents=intents) -def getFileName(event): +def getCommitMessage(event): return f"{event.start_time.strftime("%Y-%m-%d")}_{event.name}" @@ -35,7 +36,7 @@ def getFilePath(event): def getEventYML(event): - return f'# event imported from discord manual changes may be overwritten\n---\n \nlayout: event\ntitle: "{event.name}"\nauthor: "Netz39 e.V." \nevent:\n start: {event.start_time.strftime("%Y-%m-%d %H:%M:%S")} \n end: {event.end_time.strftime("%Y-%m-%d %H:%M:%S")} \n organizer: "Netz39 Team <kontakt@netz39.de>" \n location: "Leibnizstr. 18, 39104 Magdeburg"\n---' + return f'<!-- event imported from discord manual changes may be overwritten\n -->---\n \nlayout: event\ntitle: "{event.name}"\nauthor: "Netz39 e.V." \nevent:\n start: {event.start_time.strftime("%Y-%m-%d %H:%M:%S")} \n end: {event.end_time.strftime("%Y-%m-%d %H:%M:%S")} \n organizer: "Netz39 Team <kontakt@netz39.de>" \n location: "Leibnizstr. 18, 39104 Magdeburg"\n frequency: "{event.recurrence_rule.frequency}"\n interval: {event.recurrence_rule.interval} ---' def addMaintainer(maintainer): @@ -48,38 +49,51 @@ def addMaintainer(maintainer): fileW.writelines(data) +@tasks.loop(hours=24) # Runs every 7 days +async def check_events(): + await bot.wait_until_ready() + guild = bot.get_guild(GUILD_ID) + channel = guild.get_channel(CHANNEL_ID) + + if not channel: + return + + scheduledEvents = await guild.fetch_scheduled_events() + for event in scheduledEvents: + await handleEvent(event) + + async def handleEvent(event): eventYML = getEventYML(event) - if "netz39" in event.location.lower() or ( - "leibniz" in event.location.lower() and "18" in event.location - ): - if event.creator_id in MAINTAINERS: - create_or_update_file( - getFilePath(event), - eventYML, - f"new event: {getFileName(event)}", + file_path = getFilePath(event) + commit_message = getCommitMessage(event) + if event.creator_id in MAINTAINERS or similar_exists(event.name): + create_or_update_file( + file_path, + eventYML, + f"new event: {commit_message}", + ) + channel = bot.get_channel(CHANNEL_ID) + await channel.send( + f"📅 New event '{event.name}' on {event.start_time.strftime("%Y-%m-%d")}." + ) + else: + eventJSON = json.dumps( + { + "yml": eventYML, + "path": file_path, + "fileName": commit_message, + "name": event.name, + "date": event.start_time.strftime("%Y-%m-%d"), + }, + indent=2, + ) + for maintainer in MAINTAINERS: + user = await bot.fetch_user(event.creator_id) + await sendDm( + maintainer, + f"{user.name} added a new Event on {event.start_time.strftime("%Y")}: {event.name}. Like this message to approve.\n\n\n```json\n{eventJSON}```", ) - channel = bot.get_channel(CHANNEL_ID) - await channel.send( - f"📅 New event '{event.name}' on {event.start_time.strftime("%Y-%m-%d")}." - ) - else: - eventJSON = json.dumps( - { - "yml": eventYML, - "path": getFilePath(event), - "fileName": getFileName(event), - "name": event.name, - "date": event.start_time.strftime("%Y-%m-%d"), - }, - indent=2, - ) - for maintainer in MAINTAINERS: - user = await bot.fetch_user(event.creator_id) - await sendDm( - maintainer, - f"{user.name} added a new Event on {event.start_time.strftime("%Y")}: {event.name}. Like this message to approve.\n\n\n```json\n{eventJSON}```", - ) # Event: When the bot is ready @@ -101,6 +115,7 @@ async def on_ready(): print(f"Logged in as {bot.user}") channel = bot.get_channel(CHANNEL_ID) await channel.send("Hello everyone! I'm online and ready to go! 📅") + await check_events() @bot.event @@ -146,23 +161,6 @@ async def on_reaction_add(reaction, user): ) -@bot.event -async def on_message(message): - if isinstance(message.channel, discord.DMChannel): - global MAINTAINERS - author = message.author - if "add maintainer" in message.content.lower() and author.id in MAINTAINERS: - newMaintainer = message.content.lower().replace("add maintainer ", "") - if not newMaintainer in MAINTAINERS: - addMaintainer(int(newMaintainer)) - await sendDm( - newMaintainer, - "You are now a Maintainer for posthorn! Create an event located at 'Netz39 e.V.' and it will be added to the calendar.", - ) - await message.channel.send("Maintainer added!") - await bot.process_commands(message) - - @bot.event async def on_scheduled_event_delete(event): delete_file(getFilePath(event))