feat(bot): add recurring events
This commit is contained in:
parent
99a0a15b9c
commit
bf693dea0e
4 changed files with 64 additions and 37 deletions
|
@ -1,7 +1,5 @@
|
||||||
DISCORD_TOKEN="DISCORT_BOT_TOKEN"
|
DISCORD_TOKEN="DISCORT_BOT_TOKEN"
|
||||||
CHANNEL_ID="DISCORD_CHANNEL_ID"
|
|
||||||
GITHUB_TOKEN="GITHUB_TOKEN_TO_PUSH_TO_MAIN"
|
GITHUB_TOKEN="GITHUB_TOKEN_TO_PUSH_TO_MAIN"
|
||||||
REPO_OWNER="netz39"
|
REPO_OWNER="netz39"
|
||||||
REPO_NAME="wwww.netz39.de"
|
REPO_NAME="wwww.netz39.de"
|
||||||
BASE_BRANCH="main"
|
BASE_BRANCH="main"
|
||||||
MAINTAINERS='[DISCORD_IDS_OF_BRANCH_MAINTAINERS]'
|
|
11
Dockerfile
Normal file
11
Dockerfile
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
FROM python:3
|
||||||
|
|
||||||
|
RUN mkdir /source
|
||||||
|
|
||||||
|
COPY ./bot.py ./github_connector.py ./requirements.txt /source/
|
||||||
|
|
||||||
|
WORKDIR /source
|
||||||
|
|
||||||
|
RUN pip install -r requirements.txt
|
||||||
|
|
||||||
|
CMD [ "python3", "bot.py" ]
|
75
bot.py
75
bot.py
|
@ -1,7 +1,10 @@
|
||||||
import json
|
import json
|
||||||
import re
|
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
|
# 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)
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands, tasks
|
from discord.ext import commands, tasks
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
@ -10,10 +13,6 @@ from github_connector import create_or_update_file, delete_file, similar_exists
|
||||||
|
|
||||||
|
|
||||||
load_dotenv("./.env")
|
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")
|
DISCORD_TOKEN = getenv("DISCORD_TOKEN")
|
||||||
|
|
||||||
# Intents are required to listen to events like messages
|
# Intents are required to listen to events like messages
|
||||||
|
@ -36,44 +35,45 @@ def getFilePath(event):
|
||||||
|
|
||||||
|
|
||||||
def getEventYML(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 frequency: "{event.recurrence_rule.frequency}"\n interval: {event.recurrence_rule.interval} ---'
|
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 -->'
|
||||||
|
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 -->'
|
||||||
|
|
||||||
|
|
||||||
def addMaintainer(maintainer):
|
def getAdmins(guild):
|
||||||
MAINTAINERS.append(maintainer)
|
admins = []
|
||||||
with open(".env", "r") as fileR:
|
for member in guild.members:
|
||||||
# read a list of lines into data
|
if member.guild_permissions.administrator:
|
||||||
data = fileR.readlines()
|
admins.append(member.id)
|
||||||
data[6] = f"MAINTAINERS='{json.dumps(MAINTAINERS)}'"
|
return admins
|
||||||
with open(".env", "w") as fileW:
|
|
||||||
fileW.writelines(data)
|
|
||||||
|
|
||||||
|
|
||||||
@tasks.loop(hours=24) # Runs every 7 days
|
@tasks.loop(hours=24) # Runs every 7 days
|
||||||
async def check_events():
|
async def check_events():
|
||||||
await bot.wait_until_ready()
|
await bot.wait_until_ready()
|
||||||
guild = bot.get_guild(GUILD_ID)
|
for guild in bot.guilds:
|
||||||
channel = guild.get_channel(CHANNEL_ID)
|
scheduledEvents = await guild.fetch_scheduled_events()
|
||||||
|
for event in scheduledEvents:
|
||||||
if not channel:
|
await handleEvent(event)
|
||||||
return
|
|
||||||
|
|
||||||
scheduledEvents = await guild.fetch_scheduled_events()
|
|
||||||
for event in scheduledEvents:
|
|
||||||
await handleEvent(event)
|
|
||||||
|
|
||||||
|
|
||||||
async def handleEvent(event):
|
async def handleEvent(event):
|
||||||
|
guild = event.guild
|
||||||
|
channel = guild.system_channel
|
||||||
|
admins = getAdmins(guild)
|
||||||
|
|
||||||
eventYML = getEventYML(event)
|
eventYML = getEventYML(event)
|
||||||
file_path = getFilePath(event)
|
file_path = getFilePath(event)
|
||||||
commit_message = getCommitMessage(event)
|
commit_message = getCommitMessage(event)
|
||||||
if event.creator_id in MAINTAINERS or similar_exists(event.name):
|
if event.creator_id in admins or similar_exists(event.name):
|
||||||
create_or_update_file(
|
create_or_update_file(
|
||||||
file_path,
|
file_path,
|
||||||
eventYML,
|
eventYML,
|
||||||
f"new event: {commit_message}",
|
f"new event: {commit_message}",
|
||||||
)
|
)
|
||||||
channel = bot.get_channel(CHANNEL_ID)
|
|
||||||
await channel.send(
|
await channel.send(
|
||||||
f"📅 New event '{event.name}' on {event.start_time.strftime("%Y-%m-%d")}."
|
f"📅 New event '{event.name}' on {event.start_time.strftime("%Y-%m-%d")}."
|
||||||
)
|
)
|
||||||
|
@ -88,10 +88,10 @@ async def handleEvent(event):
|
||||||
},
|
},
|
||||||
indent=2,
|
indent=2,
|
||||||
)
|
)
|
||||||
for maintainer in MAINTAINERS:
|
for admin in admins:
|
||||||
user = await bot.fetch_user(event.creator_id)
|
user = await bot.fetch_user(event.creator_id)
|
||||||
await sendDm(
|
await sendDm(
|
||||||
maintainer,
|
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}```",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -113,14 +113,17 @@ async def hello(ctx):
|
||||||
@bot.event
|
@bot.event
|
||||||
async def on_ready():
|
async def on_ready():
|
||||||
print(f"Logged in as {bot.user}")
|
print(f"Logged in as {bot.user}")
|
||||||
channel = bot.get_channel(CHANNEL_ID)
|
for guild in bot.guilds:
|
||||||
await channel.send("Hello everyone! I'm online and ready to go! 📅")
|
system_channel = guild.system_channel
|
||||||
|
if system_channel:
|
||||||
|
await system_channel.send("Hello everyone! I'm online and ready to go! 📅")
|
||||||
await check_events()
|
await check_events()
|
||||||
|
|
||||||
|
|
||||||
@bot.event
|
@bot.event
|
||||||
async def on_scheduled_event_update(event):
|
async def on_scheduled_event_update(event):
|
||||||
await handleEvent(event)
|
if event.status != "canceled":
|
||||||
|
await handleEvent(event)
|
||||||
|
|
||||||
|
|
||||||
@bot.event
|
@bot.event
|
||||||
|
@ -135,14 +138,18 @@ async def sendDm(userID, message):
|
||||||
|
|
||||||
@bot.event
|
@bot.event
|
||||||
async def on_reaction_add(reaction, user):
|
async def on_reaction_add(reaction, user):
|
||||||
if not user.id in MAINTAINERS:
|
message = reaction.message
|
||||||
|
channel = message.channel
|
||||||
|
guild = message.guild
|
||||||
|
|
||||||
|
admins = getAdmins(guild)
|
||||||
|
if not user.id in admins:
|
||||||
return # Ignore non-maintainers
|
return # Ignore non-maintainers
|
||||||
if user.bot:
|
if user.bot:
|
||||||
return # Ignore bot reactions
|
return # Ignore bot reactions
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isinstance(reaction.message.channel, discord.DMChannel)
|
isinstance(message.channel, discord.DMChannel) and message.author.bot
|
||||||
and reaction.message.author.bot
|
|
||||||
): # Check if it's a DM and from the bot
|
): # Check if it's a DM and from the bot
|
||||||
if reaction.emoji == "👍":
|
if reaction.emoji == "👍":
|
||||||
messageJSON = json.loads(
|
messageJSON = json.loads(
|
||||||
|
@ -155,7 +162,6 @@ async def on_reaction_add(reaction, user):
|
||||||
messageJSON["yml"],
|
messageJSON["yml"],
|
||||||
f"new event: {messageJSON["fileName"]}",
|
f"new event: {messageJSON["fileName"]}",
|
||||||
)
|
)
|
||||||
channel = bot.get_channel(CHANNEL_ID)
|
|
||||||
await channel.send(
|
await channel.send(
|
||||||
f"📅 New event '{messageJSON["name"]}' on {messageJSON["date"]}."
|
f"📅 New event '{messageJSON["name"]}' on {messageJSON["date"]}."
|
||||||
)
|
)
|
||||||
|
@ -164,7 +170,8 @@ async def on_reaction_add(reaction, user):
|
||||||
@bot.event
|
@bot.event
|
||||||
async def on_scheduled_event_delete(event):
|
async def on_scheduled_event_delete(event):
|
||||||
delete_file(getFilePath(event))
|
delete_file(getFilePath(event))
|
||||||
channel = bot.get_channel(CHANNEL_ID)
|
guild = event.guild
|
||||||
|
channel = guild.system_channel
|
||||||
await channel.send(f"❌ Event has been canceled: {event.name}")
|
await channel.send(f"❌ Event has been canceled: {event.name}")
|
||||||
|
|
||||||
|
|
||||||
|
|
11
docker-compose.yml
Normal file
11
docker-compose.yml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
version: "3.5"
|
||||||
|
|
||||||
|
services:
|
||||||
|
posthorn:
|
||||||
|
image: 0ry5/posthorn:latest
|
||||||
|
environment:
|
||||||
|
- DISCORD_TOKEN=ADD_DISCORD_BOT_TOKEN_ID
|
||||||
|
- GITHUB_TOKEN=GITHUB_REPO_TOKEN
|
||||||
|
- REPO_OWNER=OrysB
|
||||||
|
- REPO_NAME=www.netz39.de
|
||||||
|
- BASE_BRANCH=main
|
Loading…
Add table
Reference in a new issue