feat(bot): add support for recurring events

This commit is contained in:
0Ry5-strato 2025-04-18 14:23:35 +00:00
parent bf693dea0e
commit c1be4e9a24
2 changed files with 71 additions and 22 deletions

2
.gitignore vendored
View file

@ -176,3 +176,5 @@ pyvenv.cfg
.venv
pip-selfcheck.json
#custom
vendor/

91
bot.py
View file

@ -1,10 +1,9 @@
import json
import re
# import sys
# needs the following version of discord.py for recurring events to work: https://github.com/DA-344/d.py/tree/recurrent_events
# sys.path.insert(1, path_to_discorpy_version)
# uncomment following lines
# import sys
# sys.path.insert(1, '/path/to/Posthorn/vendor/d.py')
import discord
from discord.ext import commands, tasks
from dotenv import load_dotenv
@ -27,20 +26,56 @@ bot = commands.Bot(command_prefix="!", intents=intents)
def getCommitMessage(event):
return f"{event.start_time.strftime("%Y-%m-%d")}_{event.name}"
return f"{event.start_time.strftime('%Y-%m-%d')}_{event.name}"
def getFilePath(event):
return f"_events/{event.start_time.strftime("%Y")}/discord-event-{event.id}.md"
return f"_events/{event.start_time.strftime('%Y')}/discord-event-{event.id}.md"
def getDay(day):
match day:
case 0:
return 'MO'
case 1:
return 'TU'
case 2:
return 'WE'
case 3:
return 'TH'
case 4:
return 'FR'
case 5:
return 'SA'
case 6:
return 'SU'
case _:
raise Exception(f'no matching day for int {day}')
def getRrule(event):
byDay = False
if hasattr(event.recurrence_rule, "n_weekdays"):
weekdays = event.recurrence_rule.n_weekdays
i = 0
for week, day in weekdays:
comma = ''
if i < len(weekdays) - 1:
comma = ','
byDay = f'{str(week)}{getDay(day)}{comma}'
i += 1
if byDay:
return f"FREQ={event.recurrence_rule.frequency.name.upper()};INTERVAL={event.recurrence_rule.interval};BYDAY={byDay}"
else:
return f"FREQ={event.recurrence_rule.frequency.name.upper()};INTERVAL={event.recurrence_rule.interval}"
def getEventYML(event):
if hasattr(event.recurrence_rule, "frequency") and hasattr(
event.recurrence_rule, "interval"
):
return f'---\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}\n---\n<!-- event imported from discord manual changes may be overwritten -->'
location = "Leibnizstraße 32, 39104 Magdeburg"
if hasattr(event, 'location'):
location = event.location
if hasattr(event, "recurrence_rule") and hasattr(event.recurrence_rule, "frequency") and hasattr(event.recurrence_rule, "interval"):
return f'---\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: "{location}"\n rrule: "{getRrule(event)}"\n---\n<!-- event imported from discord manual changes may be overwritten -->\n{event.description}'
else:
return f'---\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---\n<!-- event imported from discord manual changes may be overwritten -->'
return f'---\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: "{location}"\n---\n<!-- event imported from discord manual changes may be overwritten -->\n{event.description}'
def getAdmins(guild):
@ -57,10 +92,10 @@ async def check_events():
for guild in bot.guilds:
scheduledEvents = await guild.fetch_scheduled_events()
for event in scheduledEvents:
await handleEvent(event)
await handleEvent(event, True)
async def handleEvent(event):
async def handleEvent(event, isUpdate = False):
guild = event.guild
channel = guild.system_channel
admins = getAdmins(guild)
@ -74,9 +109,21 @@ async def handleEvent(event):
eventYML,
f"new event: {commit_message}",
)
await channel.send(
f"📅 New event '{event.name}' on {event.start_time.strftime("%Y-%m-%d")}."
)
if not isUpdate:
embed = discord.Embed(
title=f"📅 New event on {event.start_time.strftime('%Y-%m-%d')}",
description=f"### {event.name}\n\n{event.description}\n\n",
color=discord.Color.light_embed()
)
if hasattr(event, "cover_image") and event.cover_image:
embed.set_image(url=event.cover_image.url)
embed.add_field(name="📅 Time", value=event.start_time.strftime("%Y-%m-%d %HUhr"), inline=True)
if hasattr(event, 'location'):
embed.add_field(name="📍 Location", value=event.location, inline=True)
eventLink = f"[🔗 Netz39](https://www.netz39.de/events/2025/discord-event-{event.id})";
embed.add_field(value=eventLink, name="", inline=False)
embed.set_footer(text="Dont miss it! ")
await channel.send(embed=embed)
else:
eventJSON = json.dumps(
{
@ -92,7 +139,7 @@ async def handleEvent(event):
user = await bot.fetch_user(event.creator_id)
await sendDm(
admin,
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}```",
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}```",
)
@ -121,9 +168,9 @@ async def on_ready():
@bot.event
async def on_scheduled_event_update(event):
if event.status != "canceled":
await handleEvent(event)
async def on_scheduled_event_update(before, after):
if after.status != "canceled":
await handleEvent(after, True)
@bot.event
@ -160,10 +207,10 @@ async def on_reaction_add(reaction, user):
create_or_update_file(
messageJSON["path"],
messageJSON["yml"],
f"new event: {messageJSON["fileName"]}",
f"new event: {messageJSON['fileName']}",
)
await channel.send(
f"📅 New event '{messageJSON["name"]}' on {messageJSON["date"]}."
f"📅 New event '{messageJSON['name']}' on {messageJSON['date']}."
)