diff --git a/.env.template b/.env.template
index 28a6e9f18bd18860af253353208391ddb4967d56..3ecd2f42e570d18533e024c24d4c51d24b2e2079 100644
--- a/.env.template
+++ b/.env.template
@@ -38,6 +38,8 @@ DISCORD_CALMDOWN_ROLE=<ID of "Calmdown" role>
 DISCORD_BOTUEBUNGSPLATZ_CHANNEL=<ID of 'bot-übungsplatz' channel>
 DISCORD_ELM_STREET_CHANNEL=<ID of elm street channel>
 DISCORD_HALLOWEEN_CATEGORY=<ID of Halloween category>
+DISCORD_SEASONAL_EVENTS_CATEGORY=<ID of Seasonal Events Category>
+DISCORD_ADVENT_CALENDAR_CHANNEL_2021=<ID of advent calendar chanel for 2021>
 
 # JSON Files
 DISCORD_ROLES_FILE=<File name for roles JSON file>
@@ -51,7 +53,9 @@ DISCORD_CALMDOWN_FILE=<File name for calmdowns JSON file>
 DISCORD_MODULE_COURSE_FILE=<File name for module course JSON file>
 DISCORD_MODULE_DATA_FILE=<File name for module data JSON file>
 DISCORD_TIMER_FILE=<File name for running timers JSON file>
+DISCORD_ADVENT_CALENDAR_FILE=<File name for advent calendar JSON file>
 
 # Misc
 DISCORD_DATE_TIME_FORMAT=<Date and time format used for commands like %d.%m.%Y %H:%M>
 DISCORD_IDEE_REACT_QTY=<Amount of reactions to a submitted idea, neccessary to create a github issue (amount is including botys own reaction)>
+DISCORD_ADVENT_CALENDAR_START=<Start date and time for advent calendar. Something like "01.12.2021 00:00">
diff --git a/cogs/christmas.py b/cogs/christmas.py
index 90d67c460d3c0a4344937a0e91aa00e1537913ee..9c530f52b33cb2263233e1b1b6e85f4d1aa64d3d 100644
--- a/cogs/christmas.py
+++ b/cogs/christmas.py
@@ -1,44 +1,169 @@
+import asyncio
 import json
 import os
-from datetime import datetime
+from datetime import datetime, timedelta
 
-from disnake.ext import commands
+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.channel_id = int(os.getenv("DISCORD_ADVENT_CALENDAR_CHANNEL", "0"))
-        self.advent_calendar = []
-        self.load_advent_calendar()
-
-    def load_advent_calendar(self):
-        advent_calendar_file = open("data/advent_calendar.json", mode='r')
-        self.advent_calendar = json.load(advent_calendar_file)
-
-    @commands.Cog.listener()
-    async def on_raw_reaction_add(self, payload):
-        if payload.message_id == int(os.getenv("DISCORD_ADVENT_CALENDAR_MESSAGE")):
-            roles = {}
-            guild = await self.bot.fetch_guild(payload.guild_id)
-            member = await guild.fetch_member(payload.user_id)
-            channel = await self.bot.fetch_channel(payload.channel_id)
-            message = await channel.fetch_message(payload.message_id)
-            await message.clear_reactions()
-
-            for role in guild.roles:
-                roles[str(role.id)] = role
-
-            today = datetime.now()
-            day = today.day if today.day <= 24 else 24
-
-            if today < datetime(year=2020, month=12, day=1):
-                return
-
-            for i in range(0, day):
-                door = self.advent_calendar[i]
-                if payload.emoji.name == door["emote"]:
-                    await member.add_roles(roles[door["role"]])
-                    await utils.send_dm(member, f"Glückwunsch, du hast gerade {door['name']} geöffnet")
+        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)
diff --git a/utils.py b/utils.py
index f66beb2bd5aa74dfcc8e4bc7603619258f323d7a..0959473e7c6bd4bb32d05e686e04912e572cd2a9 100644
--- a/utils.py
+++ b/utils.py
@@ -1,12 +1,16 @@
 import os
-
-import disnake
 import re
+from datetime import datetime
 
+import disnake
 from disnake import ButtonStyle
+from dotenv import load_dotenv
 
 from views.dialog_view import DialogView
 
+load_dotenv()
+DATE_TIME_FMT = os.getenv("DISCORD_DATE_TIME_FORMAT")
+
 
 async def send_dm(user, message, embed=None):
     """ Send DM to a user/member """
@@ -55,3 +59,19 @@ async def confirm(channel, title, description, message="", custom_prefix="", cal
         {"emoji": "👍", "custom_id": f"{custom_prefix}_yes", "style": ButtonStyle.green},
         {"emoji": "👎", "custom_id": f"{custom_prefix}_no", "style": ButtonStyle.red},
     ]))
+
+
+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