Skip to content
Snippets Groups Projects
Unverified Commit b9ba0ed0 authored by dnns01's avatar dnns01 Committed by GitHub
Browse files

Merge pull request #18 from FU-Hagen-Discord/advent-calendar

Add advent calendar functionality
parents b1cd8f42 497edf2d
Branches campusstandort-auswahl
No related tags found
1 merge request!15Aktualisierung von News-Branch
...@@ -17,6 +17,8 @@ DISCORD_ROLE_MSG=<ID of role assignment message> ...@@ -17,6 +17,8 @@ DISCORD_ROLE_MSG=<ID of role assignment message>
DISCORD_SUPPORT_CHANNEL=<ID of channel where modmail & user news should be forwarded> DISCORD_SUPPORT_CHANNEL=<ID of channel where modmail & user news should be forwarded>
DISCORD_WELCOME_CHANNEL=<ID of welcome channel> DISCORD_WELCOME_CHANNEL=<ID of welcome channel>
DISCORD_WELCOME_MSG=<ID of welcome message> DISCORD_WELCOME_MSG=<ID of welcome message>
DISCORD_SEASONAL_EVENTS_CATEGORY=<ID of Seasonal Events Category>
DISCORD_ADVENT_CALENDAR_CHANNEL_2021=<ID of advent calendar chanel for 2021>
# JSON Files # JSON Files
DISCORD_CALMDOWN_FILE=<File name for calmdowns JSON file> DISCORD_CALMDOWN_FILE=<File name for calmdowns JSON file>
...@@ -25,6 +27,8 @@ DISCORD_ROLES_FILE=<File name for roles JSON file> ...@@ -25,6 +27,8 @@ DISCORD_ROLES_FILE=<File name for roles JSON file>
DISCORD_TEXT_COMMANDS_FILE=<File name for text commands JSON file> DISCORD_TEXT_COMMANDS_FILE=<File name for text commands JSON file>
DISCORD_TIMER_FILE=<File name for running timers JSON file> DISCORD_TIMER_FILE=<File name for running timers JSON file>
DISCORD_APPOINTMENTS_FILE=<File name for running appointments JSON file> DISCORD_APPOINTMENTS_FILE=<File name for running appointments JSON file>
DISCORD_ADVENT_CALENDAR_FILE=<File name for advent calendar JSON file>
# Misc # Misc
DISCORD_DATE_TIME_FORMAT=<Date and time format used for commands like %d.%m.%Y %H:%M> DISCORD_DATE_TIME_FORMAT=<Date and time format used for commands like %d.%m.%Y %H:%M>
DISCORD_ADVENT_CALENDAR_START=<Start date and time for advent calendar. Something like "01.12.2021 00:00">
import asyncio
import json
import os
from datetime import datetime, timedelta
from disnake import ApplicationCommandInteraction, Member
from disnake.ext import commands, tasks
from dotenv import load_dotenv
import utils
load_dotenv()
def create_advent_calendar():
advent_calendar = []
startdate = utils.date_from_string(os.getenv("DISCORD_ADVENT_CALENDAR_START")).astimezone()
for i in range(0, 24):
advent_calendar.append({
"number": i + 1,
"date": utils.date_to_string(startdate + timedelta(days=i)),
"assigned": False,
"opened": False
})
return advent_calendar
class Christmas(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.seasonal_events_category = int(os.getenv("DISCORD_SEASONAL_EVENTS_CATEGORY"))
self.advent_calendar_channel = int(os.getenv("DISCORD_ADVENT_CALENDAR_CHANNEL_2021"))
self.file_name = os.getenv("DISCORD_ADVENT_CALENDAR_FILE")
self.advent_calendar = self.load()
self.advent_calendar_loop.start()
def load(self):
with open(self.file_name, mode='r') as f:
advent_calendar = json.load(f)
if len(advent_calendar) == 0:
advent_calendar = create_advent_calendar()
return advent_calendar
def save(self):
with open(self.file_name, mode='w') as f:
json.dump(self.advent_calendar, f)
@commands.slash_command(name="advent", guild_ids=[int(os.getenv('DISCORD_GUILD'))])
async def cmd_advent(self, interaction: ApplicationCommandInteraction):
pass
@cmd_advent.sub_command(name="list", description="Erhalte die Liste aller Türchen mit Zuordnung und Thema")
@commands.check(utils.is_mod)
async def cmd_advent_list(self, interaction: ApplicationCommandInteraction):
message = f"__**Adventskalender 2021**__\n\n"
for day in self.advent_calendar:
message += f"{day['number']}. "
if day["assigned"]:
message += f"<@!{day['assignee']}>: \"{day['name']}\""
else:
message += f"noch nicht zugewiesen"
message += "\n"
await interaction.response.send_message(message, ephemeral=True)
@cmd_advent.sub_command(name="assign", description="Einer Person ein Türchen zuweisen",
guild_ids=[int(os.getenv('DISCORD_GUILD'))])
@commands.check(utils.is_mod)
async def cmd_advent_assign(self, interaction: ApplicationCommandInteraction, day: int, member: Member, name: str):
if self.advent_calendar[day - 1]["assigned"]:
await interaction.response.send_message("Das gewählte Türchen ist bereits vergeben. \n"
"Wenn du das Türchen an jemand anderen vergeben möchtest, oder das "
"Thema ändern möchtest, verwende `/advent reassign`.",
ephemeral=True)
else:
await interaction.response.defer(ephemeral=True)
await self.assign_day(day, member, name)
await interaction.edit_original_message(content="Das gewählte Türchen wurde vergeben.")
@cmd_advent.sub_command(name="reassign", description="Ein Türchen neu zuweisen",
guild_ids=[int(os.getenv('DISCORD_GUILD'))])
@commands.check(utils.is_mod)
async def cmd_advent_reassign(self, interaction: ApplicationCommandInteraction, day: int, member: Member,
name: str):
if not self.advent_calendar[day - 1]["assigned"]:
await interaction.response.send_message("Das gewählte Türchen ist noch nicht vergeben. \n"
"Bitte verwende `/advent assign` um das Türchen an "
"jemanden zu vergeben.", ephemeral=True)
else:
await interaction.response.defer(ephemeral=True)
channel = await self.bot.fetch_channel(self.advent_calendar[day - 1]["channel"])
old_member = await self.bot.fetch_user(self.advent_calendar[day - 1]["assignee"])
await channel.set_permissions(old_member, overwrite=None)
await self.assign_day(day, member, name)
await interaction.edit_original_message(content="Das gewählte Türchen wurde neu vergeben.")
@cmd_advent.sub_command(name="remaining", description="Noch nicht zugewiesene Türchen ausgeben lassen.",
guild_ids=[int(os.getenv('DISCORD_GUILD'))])
@commands.check(utils.is_mod)
async def cmd_advent_remaining(self, interaction: ApplicationCommandInteraction):
message = f"Noch verfügbare Türchen: "
for day in self.advent_calendar:
if not day["assigned"]:
message += f"{day['number']}, "
await interaction.response.send_message(message[:-2], ephemeral=True)
async def assign_day(self, day: int, member: Member, name: str):
category = await self.bot.fetch_channel(self.seasonal_events_category)
channel = await category.create_text_channel(f"{day}-{name}")
await channel.set_permissions(member.roles[0], view_channel=False)
await channel.set_permissions(member, view_channel=True)
await channel.send(f"Vielen Dank {member.mention}, dass du für das {day}. Türchen etwas zum Thema {name} "
f"vorbereiten möchtest. Dieser Channel ist für dich gedacht. Du kannst hier deinen Beitrag "
f"vorbereiten.\n\n"
f"Am {day}.12.2021 um 00:00 werden alle Nachrichten von dir, die in diesem Channel bis "
f"dahin geschrieben wurden, in einen eigenen Thread für diesen Tag übernommen.\n\n"
f"Beachte bitte, dass Sticker nicht verwendet werden können. Das gleiche gilt für Emojis, "
f"die nicht von diesem Server sind.\n\n"
f"Das Mod-Team wünscht dir viel Spaß bei der Vorbereitung.")
self.advent_calendar[day - 1]["channel"] = channel.id
self.advent_calendar[day - 1]["assigned"] = True
self.advent_calendar[day - 1]["assignee"] = member.id
self.advent_calendar[day - 1]["name"] = name
self.save()
async def open(self, day):
source_channel = await self.bot.fetch_channel(day["channel"])
assignee = await self.bot.fetch_user(day["assignee"])
target_channel = await self.bot.fetch_channel(self.advent_calendar_channel)
thread_name = f"{day['number']}. {day['name']}"
message = await target_channel.send(f"{day['number']}. \"{day['name']}\", ein Beitrag von {assignee.mention}:")
thread = await message.create_thread(name=thread_name, auto_archive_duration=1440)
day["thread"] = thread.id
day["opened"] = True
async for msg in source_channel.history(limit=None, oldest_first=True):
if msg.author == assignee:
if len(msg.stickers) > 0:
continue
files = await utils.files_from_attachments(msg.attachments)
await thread.send(content=msg.content, embeds=msg.embeds, files=files)
await thread.send("--------------------------\nBeginn der Diskussion\n--------------------------")
self.save()
@tasks.loop(seconds=10)
async def advent_calendar_loop(self):
now = datetime.now()
for day in self.advent_calendar:
if not day["opened"]:
due_date = utils.date_from_string(day["date"])
if due_date <= now:
await self.open(day)
else:
return
@advent_calendar_loop.before_loop
async def before_advent_calendar_loop(self):
await asyncio.sleep(10 - datetime.now().second % 10)
...@@ -4,7 +4,7 @@ import disnake ...@@ -4,7 +4,7 @@ import disnake
from disnake.ext import commands from disnake.ext import commands
from dotenv import load_dotenv from dotenv import load_dotenv
from cogs import appointments, calmdown, help, links, polls, roles, support, text_commands, timer, welcome from cogs import appointments, calmdown, help, links, polls, roles, support, text_commands, timer, welcome, christmas
# .env file is necessary in the same directory, that contains several strings. # .env file is necessary in the same directory, that contains several strings.
load_dotenv() load_dotenv()
...@@ -38,6 +38,7 @@ class Root(commands.Bot): ...@@ -38,6 +38,7 @@ class Root(commands.Bot):
self.add_cog(text_commands.TextCommands(self)) self.add_cog(text_commands.TextCommands(self))
self.add_cog(timer.Timer(self)) self.add_cog(timer.Timer(self))
self.add_cog(welcome.Welcome(self)) self.add_cog(welcome.Welcome(self))
self.add_cog(christmas.Christmas(self))
bot = Root() bot = Root()
......
import os import os
import re import re
from datetime import datetime
import disnake import disnake
from dotenv import load_dotenv
load_dotenv()
DATE_TIME_FMT = os.getenv("DISCORD_DATE_TIME_FORMAT")
async def send_dm(user, message, embed=None): async def send_dm(user, message, embed=None):
...@@ -41,3 +46,19 @@ def to_minutes(time): ...@@ -41,3 +46,19 @@ def to_minutes(time):
return h * 60 return h * 60
return int(time) return int(time)
def date_to_string(date: datetime):
return date.strftime(DATE_TIME_FMT)
def date_from_string(date: str):
return datetime.strptime(date, DATE_TIME_FMT)
async def files_from_attachments(attachments):
files = []
for attachment in attachments:
files.append(await attachment.to_file(spoiler=attachment.is_spoiler()))
return files
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment