From 6ce46c442f7b4f140853adc4cd8fca7dee8e98aa Mon Sep 17 00:00:00 2001
From: dnns01 <mail@dnns01.de>
Date: Wed, 30 Sep 2020 16:22:59 +0200
Subject: [PATCH] Added text command functionality, that allows to add
 commands, that print simply print out text. And in case there are multiple
 texts for a command, one is chosen randomly. Also added command
 !add-motivation, that allows users to add specific texts for !motivation
 command. Those texts then have to be approved by a mod.

---
 .gitignore           |   1 +
 fernuni-bot.py       |  44 +++----------
 text_commands_cog.py | 151 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 161 insertions(+), 35 deletions(-)
 create mode 100644 text_commands_cog.py

diff --git a/.gitignore b/.gitignore
index 34e507a..07b48cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -118,3 +118,4 @@ GitHub.sublime-settings
 /help.json
 /appointments.json
 /tops.json
+/text_commands.json
diff --git a/fernuni-bot.py b/fernuni-bot.py
index a4128d3..22181d9 100644
--- a/fernuni-bot.py
+++ b/fernuni-bot.py
@@ -1,6 +1,5 @@
 import json
 import os
-import random
 import re
 
 import discord
@@ -9,6 +8,7 @@ from dotenv import load_dotenv
 
 from appointments_cog import AppointmentsCog
 from poll import Poll
+from text_commands_cog import TextCommandsCog
 
 # .env file is necessary in the same directory, that contains several strings.
 load_dotenv()
@@ -20,12 +20,15 @@ ROLES_FILE = os.getenv('DISCORD_ROLES_FILE')
 HELP_FILE = os.getenv('DISCORD_HELP_FILE')
 TOPS_FILE = os.getenv('DISCORD_TOPS_FILE')
 APPOINTMENTS_FILE = os.getenv("DISCORD_APPOINTMENTS_FILE")
+TEXT_COMMANDS_FILE = os.getenv("DISCORD_TEXT_COMMANDS_FILE")
 DATE_TIME_FORMAT = os.getenv("DISCORD_DATE_TIME_FORMAT")
 
 PIN_EMOJI = "📌"
 bot = commands.Bot(command_prefix='!', help_command=None, activity=discord.Game(ACTIVITY), owner_id=OWNER)
 appointments_cog = AppointmentsCog(bot, DATE_TIME_FORMAT, APPOINTMENTS_FILE)
+text_commands_cog = TextCommandsCog(bot, TEXT_COMMANDS_FILE)
 bot.add_cog(appointments_cog)
+bot.add_cog(text_commands_cog)
 assignable_roles = {}
 tops = {}
 
@@ -103,32 +106,6 @@ async def send_dm(user, message, embed=None):
         await user.dm_channel.send(message, embed=embed)
 
 
-@bot.command(name="motivation")
-async def cmd_motivation(ctx):
-    texts = ["Leb' deinen Traum, denn er wird wahr. Geh deinen Weg, stelle dich der Gefahr...",
-             "Alles, was, wichtig, ist, wirst, du, erkennen, wenn, die, Zeit, gekommen, ist.,",
-             "\"Tue es oder tue es nicht.Es gibt kein Versuchen.\" – Meister Yoda",
-             "\"Wissen Sie noch, wie damals unser Leitspruch war?\" "
-             "\"Immer ein Ding der Unmöglichkeit nach dem ander'n\" STAR TREK PICARD",
-             "Are you kidding me?! JUST - DO - IT!",
-             "Manchmal braucht man einfach mal eine Pause. :person_shrugging:",
-             "Ich habe diese Leier doch schon mal gehört, hat eine Spitzenposition in den Charts der alten, aber guten "
-             "Leiern und kommt kurz nach dem beliebten Stück: \"Scheitert und ich werde euch töten!\". Oder vielleicht "
-             "handelt es sich in diesem Fall, um die interessante Coverversion, die von dem berüchtigten Ogerbarden "
-             "Chumba – Khan eingespielt wurde: \"Scheitert und ich werde euch fressen!\" Natürlich könnten wir doch "
-             "auch einfach gehen.",
-             "Am Morgen ein Bier und der Tag gehört dir."
-             ]
-
-    text = random.choice(texts)
-    await ctx.send(text)
-
-
-@bot.command(name="sinn")
-async def cmd_sinn(ctx):
-    await ctx.send("42 :robot:")
-
-
 @bot.command(name="help")
 async def cmd_help(ctx):
     """ Send help message as DM """
@@ -320,14 +297,6 @@ async def modify_roles(ctx, add, args):
                         await send_dm(ctx.author, f'Fehler bei der Entfernung der Rolle {role.name}')
 
 
-@bot.command(name="link")
-async def cmd_link(message):
-    """ Sends link to invite others to Discord server in Chat. """
-
-    await message.channel.send('Benutze bitte folgenden Link, um andere Studierende auf unseren Discord einzuladen: '
-                               'http://fernuni-discord.dnns01.de')
-
-
 @bot.command(name="stats")
 async def cmd_stats(message):
     """ Sends stats in Chat. """
@@ -402,6 +371,11 @@ async def on_raw_reaction_add(payload):
         elif payload.emoji.name == "🗑️" and len(message.embeds) > 0 and \
                 message.embeds[0].title == "Neuer Termin hinzugefügt!":
             await appointments_cog.handle_reactions(payload)
+    elif payload.emoji.name in ["👍"]:
+        channel = await bot.fetch_channel(payload.channel_id)
+        message = await channel.fetch_message(payload.message_id)
+        if len(message.embeds) > 0 and message.embeds[0].title == "Neuer Motivations Text":
+            await text_commands_cog.motivation_approved(message)
 
 
 @bot.event
diff --git a/text_commands_cog.py b/text_commands_cog.py
new file mode 100644
index 0000000..8ebdea6
--- /dev/null
+++ b/text_commands_cog.py
@@ -0,0 +1,151 @@
+import json
+import os
+import random
+
+import discord
+from discord.ext import commands
+
+
+class TextCommandsCog(commands.Cog):
+    def __init__(self, bot, TEXT_COMMANDS_FILE):
+        self.bot = bot
+        self.text_commands = {}
+        self.cmd_file = TEXT_COMMANDS_FILE
+        self.load_text_commands()
+
+    def load_text_commands(self):
+        """ Loads all appointments from APPOINTMENTS_FILE """
+
+        text_commands_file = open(self.cmd_file, mode='r')
+        self.text_commands = json.load(text_commands_file)
+
+    def save_text_commands(self):
+        text_commands_file = open(self.cmd_file, mode='w')
+        json.dump(self.text_commands, text_commands_file)
+
+    def is_mod(ctx):
+        author = ctx.author
+        roles = author.roles
+
+        for role in roles:
+            if role.id == int(os.getenv("DISCORD_MOD_ROLE")):
+                return True
+
+        return False
+
+    @commands.Cog.listener(name="on_message")
+    async def process_text_commands(self, message):
+        if message.author == self.bot.user:
+            return
+
+        cmd = message.content.split(" ")[0]
+        texts = self.text_commands.get(cmd)
+
+        if texts:
+            await message.channel.send(random.choice(texts))
+
+    @commands.command(name="add-text-command")
+    @commands.check(is_mod)
+    async def cmd_add_text_command(self, ctx, cmd, text):
+        texts = self.text_commands.get(cmd)
+
+        if texts:
+            texts.append(text)
+        else:
+            self.text_commands[cmd] = [text]
+
+        self.save_text_commands()
+
+        await ctx.send(f"[{cmd}] => [{text}] erfolgreich hinzugefügt.")
+
+    @commands.command(name="text-commands")
+    @commands.check(is_mod)
+    async def cmd_text_commands(self, ctx):
+        answer = f"Text Commands:\n"
+
+        ctr = 0
+        for command in self.text_commands:
+            answer += f"{ctr}: {command}\n"
+            ctr += 1
+
+        await ctx.send(answer)
+
+    @commands.command(name="texts")
+    @commands.check(is_mod)
+    async def cmd_texts(self, ctx, cmd):
+        texts = self.text_commands.get(cmd)
+        answer = f"Für {cmd} hinterlegte Texte: \n"
+
+        for i in range(0, len(texts)):
+            text = texts[i]
+            if len(answer) + len(text) > 2000:
+                await ctx.send(answer)
+                answer = f""
+
+            answer += f"{i}: {text}\n"
+
+        await ctx.send(answer)
+
+    @commands.command(name="edit-text")
+    @commands.check(is_mod)
+    async def cmd_edit_text(self, ctx, cmd, id, text):
+        texts = self.text_commands.get(cmd)
+
+        if texts:
+            i = int(id)
+            if i < len(texts):
+                texts[i] = text
+                await ctx.send(f"Text {i} für Command {cmd} wurde erfolgreich geändert")
+                self.save_text_commands()
+            else:
+                await ctx.send(f"Ungültiger Index")
+        else:
+            await ctx.send("Command {cmd} nicht vorhanden!")
+
+    @commands.command(name="remove-text")
+    @commands.check(is_mod)
+    async def cmd_remove_text(self, ctx, cmd, id):
+        texts = self.text_commands.get(cmd)
+
+        if texts:
+            i = int(id)
+            if i < len(texts):
+                del texts[i]
+                await ctx.send(f"Text {i} für Command {cmd} wurde erfolgreich entfernt")
+
+                if len(texts) == 0:
+                    self.text_commands.pop(cmd)
+
+                self.save_text_commands()
+            else:
+                await ctx.send(f"Ungültiger Index")
+        else:
+            await ctx.send("Command {cmd} nicht vorhanden!")
+
+    @commands.command(name="remove-text-command")
+    @commands.check(is_mod)
+    async def cmd_remove_text_command(self, ctx, cmd):
+        if cmd in self.text_commands:
+            self.text_commands.pop(cmd)
+            await ctx.send(f"Text Command {cmd} wurde erfolgreich entfernt")
+            self.save_text_commands()
+        else:
+            await ctx.send(f"Text Command {cmd} nicht vorhanden")
+
+    @commands.command(name="add-motivation")
+    async def cmd_add_motivation(self, ctx, text):
+        mod_channel = await self.bot.fetch_channel(int(os.getenv("DISCORD_MOD_CHANNEL")))
+
+        embed = discord.Embed(title="Neuer Motivations Text",
+                              description=f"<@!{ctx.author.id}> Möchte folgenden Motivationstext hinzufügen:")
+        embed.add_field(name="\u200b", value=f"{text}")
+
+        message = await mod_channel.send(embed=embed)
+        await message.add_reaction("👍")
+
+    async def motivation_approved(self, message):
+        embed = message.embeds[0]
+        text = embed.fields[0].value
+        ctx = await self.bot.get_context(message)
+
+        await self.cmd_add_text_command(ctx, "!motivation", text)
-- 
GitLab