171 lines
5.1 KiB
Python
171 lines
5.1 KiB
Python
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, tasks
|
|
from dotenv import load_dotenv
|
|
from os import getenv
|
|
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")
|
|
|
|
# Intents are required to listen to events like messages
|
|
intents = discord.Intents.default()
|
|
intents.message_content = True
|
|
intents.members = True
|
|
intents.reactions = True
|
|
intents.dm_messages = True
|
|
|
|
# Create an instance of the Bot
|
|
bot = commands.Bot(command_prefix="!", intents=intents)
|
|
|
|
|
|
def getCommitMessage(event):
|
|
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"
|
|
|
|
|
|
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 frequency: "{event.recurrence_rule.frequency}"\n interval: {event.recurrence_rule.interval} ---'
|
|
|
|
|
|
def addMaintainer(maintainer):
|
|
MAINTAINERS.append(maintainer)
|
|
with open(".env", "r") as fileR:
|
|
# read a list of lines into data
|
|
data = fileR.readlines()
|
|
data[6] = f"MAINTAINERS='{json.dumps(MAINTAINERS)}'"
|
|
with open(".env", "w") as fileW:
|
|
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)
|
|
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}```",
|
|
)
|
|
|
|
|
|
# Event: When the bot is ready
|
|
@bot.event
|
|
async def on_ready():
|
|
print(f"Logged in as {discord.user}")
|
|
|
|
|
|
# Command: !hello
|
|
@bot.command()
|
|
async def hello(ctx):
|
|
await ctx.send(
|
|
"Hello, I am a bot to add events from discord to the Netz39 calendar on the website!"
|
|
)
|
|
|
|
|
|
@bot.event
|
|
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
|
|
async def on_scheduled_event_update(event):
|
|
await handleEvent(event)
|
|
|
|
|
|
@bot.event
|
|
async def on_scheduled_event_create(event):
|
|
await handleEvent(event)
|
|
|
|
|
|
async def sendDm(userID, message):
|
|
user = await bot.fetch_user(userID)
|
|
await user.send(message)
|
|
|
|
|
|
@bot.event
|
|
async def on_reaction_add(reaction, user):
|
|
if not user.id in MAINTAINERS:
|
|
return # Ignore non-maintainers
|
|
if user.bot:
|
|
return # Ignore bot reactions
|
|
|
|
if (
|
|
isinstance(reaction.message.channel, discord.DMChannel)
|
|
and reaction.message.author.bot
|
|
): # Check if it's a DM and from the bot
|
|
if reaction.emoji == "👍":
|
|
messageJSON = json.loads(
|
|
re.search(
|
|
"(?s)(?<=```json).*?(?=```)", reaction.message.content
|
|
).group()
|
|
)
|
|
create_or_update_file(
|
|
messageJSON["path"],
|
|
messageJSON["yml"],
|
|
f"new event: {messageJSON["fileName"]}",
|
|
)
|
|
channel = bot.get_channel(CHANNEL_ID)
|
|
await channel.send(
|
|
f"📅 New event '{messageJSON["name"]}' on {messageJSON["date"]}."
|
|
)
|
|
|
|
|
|
@bot.event
|
|
async def on_scheduled_event_delete(event):
|
|
delete_file(getFilePath(event))
|
|
channel = bot.get_channel(CHANNEL_ID)
|
|
await channel.send(f"❌ Event has been canceled: {event.name}")
|
|
|
|
|
|
bot.run(DISCORD_TOKEN)
|