diff --git a/.env.template b/.env.template
deleted file mode 100644
index e0ed7b7599035e927ab80d67dd0e7d4ea4a2777f..0000000000000000000000000000000000000000
--- a/.env.template
+++ /dev/null
@@ -1,9 +0,0 @@
-# General
-DISCORD_TOKEN=<Bot Token>
-DISCORD_ACTIVITY=<What should be shown, Bot is playing right now>
-DISCORD_PROD=<True, if running in an productive environment, otherwise False (neccessary for a couple of features like private threads, that are only available on our productive environment)>
-
-# IDs
-DISCORD_ELM_STREET_CHANNEL=<ID of elm street channel>
-DISCORD_HALLOWEEN_CATEGORY=<ID of Halloween category>
-
diff --git a/.gitignore b/.gitignore
index 4ac064f1cd7569e5a87fe9cab128d1881f3e7cbf..438cdf0832136ed56299f6bb586abd9266caad9e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -117,3 +117,4 @@ GitHub.sublime-settings
 .history
 /data/*.json
 !/data/story.json
+/config.json
diff --git a/extensions/elm_street.py b/deprecated/extensions/elm_street.py
similarity index 100%
rename from extensions/elm_street.py
rename to deprecated/extensions/elm_street.py
diff --git a/images/20220928_142617.jpg b/deprecated/images/20220928_142617.jpg
similarity index 100%
rename from images/20220928_142617.jpg
rename to deprecated/images/20220928_142617.jpg
diff --git a/images/20220928_143119.jpg b/deprecated/images/20220928_143119.jpg
similarity index 100%
rename from images/20220928_143119.jpg
rename to deprecated/images/20220928_143119.jpg
diff --git a/images/20220928_143134.jpg b/deprecated/images/20220928_143134.jpg
similarity index 100%
rename from images/20220928_143134.jpg
rename to deprecated/images/20220928_143134.jpg
diff --git a/images/20220928_151142.jpg b/deprecated/images/20220928_151142.jpg
similarity index 100%
rename from images/20220928_151142.jpg
rename to deprecated/images/20220928_151142.jpg
diff --git a/images/20220928_151227.jpg b/deprecated/images/20220928_151227.jpg
similarity index 100%
rename from images/20220928_151227.jpg
rename to deprecated/images/20220928_151227.jpg
diff --git a/images/20220928_151233.jpg b/deprecated/images/20220928_151233.jpg
similarity index 100%
rename from images/20220928_151233.jpg
rename to deprecated/images/20220928_151233.jpg
diff --git a/images/20220928_151251.jpg b/deprecated/images/20220928_151251.jpg
similarity index 100%
rename from images/20220928_151251.jpg
rename to deprecated/images/20220928_151251.jpg
diff --git a/images/20220928_151535.jpg b/deprecated/images/20220928_151535.jpg
similarity index 100%
rename from images/20220928_151535.jpg
rename to deprecated/images/20220928_151535.jpg
diff --git a/images/20220928_152325.jpg b/deprecated/images/20220928_152325.jpg
similarity index 100%
rename from images/20220928_152325.jpg
rename to deprecated/images/20220928_152325.jpg
diff --git a/images/20220928_152359.jpg b/deprecated/images/20220928_152359.jpg
similarity index 100%
rename from images/20220928_152359.jpg
rename to deprecated/images/20220928_152359.jpg
diff --git a/images/20220928_152754.jpg b/deprecated/images/20220928_152754.jpg
similarity index 100%
rename from images/20220928_152754.jpg
rename to deprecated/images/20220928_152754.jpg
diff --git a/images/20220928_152812.jpg b/deprecated/images/20220928_152812.jpg
similarity index 100%
rename from images/20220928_152812.jpg
rename to deprecated/images/20220928_152812.jpg
diff --git a/images/20220928_152925.jpg b/deprecated/images/20220928_152925.jpg
similarity index 100%
rename from images/20220928_152925.jpg
rename to deprecated/images/20220928_152925.jpg
diff --git a/images/20220928_153911.jpg b/deprecated/images/20220928_153911.jpg
similarity index 100%
rename from images/20220928_153911.jpg
rename to deprecated/images/20220928_153911.jpg
diff --git a/images/20220928_154705.jpg b/deprecated/images/20220928_154705.jpg
similarity index 100%
rename from images/20220928_154705.jpg
rename to deprecated/images/20220928_154705.jpg
diff --git a/images/20220928_155339.jpg b/deprecated/images/20220928_155339.jpg
similarity index 100%
rename from images/20220928_155339.jpg
rename to deprecated/images/20220928_155339.jpg
diff --git a/images/20220928_160658.jpg b/deprecated/images/20220928_160658.jpg
similarity index 100%
rename from images/20220928_160658.jpg
rename to deprecated/images/20220928_160658.jpg
diff --git a/images/20220928_184010.jpg b/deprecated/images/20220928_184010.jpg
similarity index 100%
rename from images/20220928_184010.jpg
rename to deprecated/images/20220928_184010.jpg
diff --git a/images/Felskapelle.jpg b/deprecated/images/Felskapelle.jpg
similarity index 100%
rename from images/Felskapelle.jpg
rename to deprecated/images/Felskapelle.jpg
diff --git a/images/Midjourney-Herbsthaus1_.png b/deprecated/images/Midjourney-Herbsthaus1_.png
similarity index 100%
rename from images/Midjourney-Herbsthaus1_.png
rename to deprecated/images/Midjourney-Herbsthaus1_.png
diff --git a/images/Midjourney-Herbsthaus2.png b/deprecated/images/Midjourney-Herbsthaus2.png
similarity index 100%
rename from images/Midjourney-Herbsthaus2.png
rename to deprecated/images/Midjourney-Herbsthaus2.png
diff --git a/images/Midjourney-Herbsthaus3.png b/deprecated/images/Midjourney-Herbsthaus3.png
similarity index 100%
rename from images/Midjourney-Herbsthaus3.png
rename to deprecated/images/Midjourney-Herbsthaus3.png
diff --git a/images/Midjourney-Tuergesicht.png b/deprecated/images/Midjourney-Tuergesicht.png
similarity index 100%
rename from images/Midjourney-Tuergesicht.png
rename to deprecated/images/Midjourney-Tuergesicht.png
diff --git a/images/wildeGestallten.jpg b/deprecated/images/wildeGestallten.jpg
similarity index 100%
rename from images/wildeGestallten.jpg
rename to deprecated/images/wildeGestallten.jpg
diff --git a/extensions/click_game.py b/extensions/click_game.py
new file mode 100644
index 0000000000000000000000000000000000000000..e7aa064c17b72f31c72dbc1e962ffabbb722bea9
--- /dev/null
+++ b/extensions/click_game.py
@@ -0,0 +1,167 @@
+import json
+import os
+import random
+from asyncio import sleep
+from copy import deepcopy
+from os.path import exists
+from random import SystemRandom
+from typing import Union, Dict
+from datetime import datetime, timedelta
+
+import discord
+from discord import app_commands, Guild, Interaction, ButtonStyle, File, Message, Embed
+from discord.app_commands import Choice
+from discord.ext import commands, tasks
+from discord.utils import escape_markdown
+from dotenv import load_dotenv
+
+from utils import send_dm
+
+load_dotenv()
+
+
+@app_commands.guild_only()
+class ClickGame(commands.Cog):
+    def __init__(self, bot):
+        self.bot = bot
+        self.config: Dict = bot.config["extensions"][__name__.split(".")[-1]]
+        self.bot.view_manager.register("on_click", self.on_click)
+        self.msg_count: int = 0
+        self.last_sent: datetime = datetime(1970, 1, 1)
+
+    @commands.Cog.listener()
+    async def on_message(self, message: Message):
+        if message.author == self.bot.user:
+            return
+
+        if message.channel.id not in self.config["channels"]:
+            return
+
+        self.msg_count += 1
+        if self.msg_count < self.config["min_msg_count"]:
+            print("Too few messages sent.")
+            return
+
+        if self.last_sent + timedelta(minutes=self.config["cooldown"]) > datetime.now():
+            print("Too early, sorry.")
+            return
+
+        if random.random() > self.config["probability"]:
+            print("Nope, better luck next time!")
+            return
+
+        await self.send_message(message.channel)
+
+    async def send_message(self, channel) -> None:
+        img = self.get_random_image()
+        plus_emoji, minus_emoji = self.get_random_emojis()
+        file = discord.File(f"images/{img}", filename=img)
+        embed = Embed(title="Vorsicht!", description=self.get_random_description(plus_emoji, minus_emoji))
+        embed.set_image(url=f"attachment://{img}")
+        await channel.send(file=file, embed=embed, view=self.get_view(plus_emoji, minus_emoji))
+
+        self.last_sent = datetime.now()
+        self.msg_count = 0
+
+    def get_random_image(self) -> str:
+        images = os.listdir("images/")
+        return random.choice(images)
+
+    def get_random_emojis(self):
+        plus_emoji = random.choice(self.config["emojis"])
+        while True:
+            minus_emoji = random.choice(self.config["emojis"])
+            if plus_emoji != minus_emoji:
+                return plus_emoji, minus_emoji
+
+    def get_random_description(self, plus_emoji, minus_emoji):
+        texts = [
+            f"Oh nein, pass auf! Klicke auf {plus_emoji}, um das Monster in die Flucht zu schlagen! Klicke auf {minus_emoji} um das Monster zu stärken!",
+            f"Oh nein, pass auf! Klicke auf {minus_emoji} um das Monster zu stärken! Klicke auf {plus_emoji}, um das Monster in die Flucht zu schlagen!"]
+        return random.choice(texts)
+
+    @app_commands.command(name="leaderboard",
+                          description="Zeigt das Leaderboard der Elm Street Sammlerinnen-Gemeinschaft an.")
+    @app_commands.choices(show=[Choice(name='10', value=10), Choice(name='all', value=0)])
+    @app_commands.guild_only()
+    async def cmd_leaderboard(self, interaction: Interaction, show: int = 10):
+        await interaction.response.defer(ephemeral=True)
+        leaderboard = await self.get_leaderboard(interaction.guild, max_entries=show)
+        await interaction.followup.send(content=leaderboard, ephemeral=True)
+
+    async def on_click(self, button: discord.ui.Button, interaction: Interaction, value=None):
+        if value > 0:
+            await interaction.response.send_message(
+                f"Super! Du hast das Monster geschwächt und erhältst zur Belohnung {value} Punkte.", ephemeral=True)
+            button.value -= 1
+        elif value < 0:
+            await interaction.response.send_message(
+                f"Oh nein! Du hast das Monster gestärkt. Es greift dich an und du bekommst {value} Punkte abgezogen.",
+                ephemeral=True)
+            button.value += 1
+        else:
+            interaction.response.send_message("Du warst zu spät. Glücklicherweise wurde das Monster bereits besiegt.",
+                                              ephemeral=True)
+
+        if button.value == 0 and interaction.message:
+            await interaction.message.delete()
+
+    def get_view(self, plus_emoji, minus_emoji):
+        buttons = [
+            {"style": ButtonStyle.gray, "value": 5, "custom_id": "click_game:plus", "emoji": plus_emoji},
+            {"style": ButtonStyle.gray, "value": -5, "custom_id": "click_game:minus", "emoji": minus_emoji}
+        ]
+        return self.bot.view_manager.view(buttons, "on_click")
+
+    async def get_leaderboard(self, guild: Guild, max_entries: int = 10):
+        message = f"**__Elm-Street Leaderboard__**\n\n" \
+                  f"Wie süß bist du wirklich??\n" \
+                  f"{':jack_o_lantern: ' * 8}\n\n" \
+                  f"```md\n" \
+                  f"Rank. | Items | User\n" \
+                  f"==================================================\n"
+
+        place = 0
+
+        ready = False
+        last_score = -1
+        for player_id, player_data in sorted(self.players.items(), key=lambda item: item[1]["sweets"], reverse=True):
+            value = player_data["sweets"]
+            member = await guild.fetch_member(int(player_id))
+            try:
+                if last_score != value:
+                    place += 1
+                last_score = value
+                if 0 < max_entries < place:
+                    if ready:
+                        break
+                message += f"{str(place).rjust(4)}. | {str(value).rjust(5)} | "
+                message += f"{member.display_name}#{member.discriminator}\n"
+            except:
+                pass
+
+        message += f"```"
+
+        return message
+
+    @tasks.loop(minutes=5)
+    async def increase_courage(self):
+        pass
+
+    @increase_courage.before_loop
+    async def before_increase(self):
+        pass
+        # await sleep(10)
+
+    # @commands.Cog.listener(name="on_voice_state_update")
+    # async def voice_state_changed(self, member, before, after):
+    #     if not after.channel:
+    #         voice_channel_left = before.channel
+    #         if len(voice_channel_left.members) == 0 and \
+    #                 voice_channel_left.category_id == self.halloween_category_id and \
+    #                 not self.get_group_by_voice_id(voice_channel_left.id):
+    #             await voice_channel_left.delete()
+
+
+async def setup(bot: commands.Bot) -> None:
+    await bot.add_cog(ClickGame(bot))
diff --git a/halloween.py b/halloween.py
index a1ef61d6b9ca9b6bf84125c588546f632459e7f8..5cbe3c9e1810d08be2f044a9301cbc967c95c8bd 100644
--- a/halloween.py
+++ b/halloween.py
@@ -1,26 +1,22 @@
-import os
+import json
 
 from discord import Intents, Game
 from discord.ext import commands
-from dotenv import load_dotenv
-from typing import List
+from typing import Dict
 
 from view_manager import ViewManager
 
-# .env file is necessary in the same directory, that contains several strings.
-load_dotenv()
-
 
 class HalloweenBot(commands.Bot):
-    def __init__(self, *args, initial_extensions: List[str], **kwargs):
+    def __init__(self, *args, config: Dict, **kwargs):
         super().__init__(*args, **kwargs)
-        self.is_prod = os.getenv("DISCORD_PROD") == "True"
-        self.initial_extensions: List[str] = initial_extensions
+        self.config = config
+        self.is_prod = config["is_prod"]
         self.view_manager: ViewManager = ViewManager(self)
         self.persistent_views_added: bool = False
 
     async def setup_hook(self) -> None:
-        for extension in self.initial_extensions:
+        for extension, _ in self.config["extensions"].items():
             await self.load_extension(f"extensions.{extension}")
         await self.tree.sync()
 
@@ -28,7 +24,12 @@ class HalloweenBot(commands.Bot):
         self.view_manager.on_ready()
 
 
-extensions = ["elm_street"]
-bot = HalloweenBot(command_prefix='!', help_command=None, activity=Game(os.getenv('DISCORD_ACTIVITY')),
-                   intents=Intents.all(), initial_extensions=extensions)
-bot.run(os.getenv('DISCORD_TOKEN'))
+def load_config():
+    fp = open("config.json", mode="r")
+    return json.load(fp)
+
+
+config = load_config()
+bot = HalloweenBot(command_prefix='!', help_command=None, activity=Game(config["activity"]),
+                   intents=Intents.all(), config=config)
+bot.run(config["token"])
diff --git a/images/img01.png b/images/img01.png
new file mode 100644
index 0000000000000000000000000000000000000000..7945985f0d2dddd26ee1346ee0a79fc058c65190
Binary files /dev/null and b/images/img01.png differ
diff --git a/images/img02.png b/images/img02.png
new file mode 100644
index 0000000000000000000000000000000000000000..36fd22528423cf5849df588ad0c022c704b5de27
Binary files /dev/null and b/images/img02.png differ
diff --git a/images/img03.png b/images/img03.png
new file mode 100644
index 0000000000000000000000000000000000000000..c8b9a51bc978f151dc8ff86227be0713cb64a28c
Binary files /dev/null and b/images/img03.png differ
diff --git a/requirements.txt b/requirements.txt
index d21f5e18b67b4e58dcd174f300a7f8a86480e1fe..95a91b54dd7a0bbddd2dd386b51c6b822e0c590d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,10 @@
-discord.py==2.0.1
-python-dotenv==0.21.0
+aiohttp==3.8.5
+aiosignal==1.3.1
+async-timeout==4.0.3
+attrs==23.1.0
+charset-normalizer==3.2.0
+discord.py==2.3.2
+frozenlist==1.4.0
+idna==3.4
+multidict==6.0.4
+yarl==1.9.2