From 2bbe19fcd9a31efbdd33fbd0772ef9c5e201c231 Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Sat, 12 Feb 2022 00:56:45 +0100
Subject: [PATCH 01/16] modules/CommandSpoiler.py

---
 modules/CommandSpoiler.py | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/modules/CommandSpoiler.py b/modules/CommandSpoiler.py
index 5ef48c9..9db6b22 100644
--- a/modules/CommandSpoiler.py
+++ b/modules/CommandSpoiler.py
@@ -15,15 +15,20 @@ class CommandSpoiler(AbstractCommand):
 
 
     def on_POST(self, request, data):
-        if len(data['text']) > 15000:
-            request.respond_cmd_err("``/"+self.TRIGGER+"`` reason-text must be smaller than 15000 characters :(\nYour text is: "+str(len(data['text']))+" characters long.")
+        msg_text = data['text'].strip()
+
+        if len(msg_text) == 1:
+            request.respond_cmd_err("``/"+self.TRIGGER+"`` It seems like you did not supply any spoiler-text. (use --remove to remove)")
+            return
+        if len(msg_text) > 15000:
+            request.respond_cmd_err("``/"+self.TRIGGER+"`` reason-text must be smaller than 15000 characters :(\nYour text is: "+str(len(msg_text))+" characters long.")
             return
 
         att = [{
             "text": "This post contains spoilers.",
             "actions": [{
                 "name": ":ghost: show me the spoilers :ghost:",
-                "integration": {"url": self.URL+"/interactive", "context": {"action": "show_spoiler", "spoiler":data['text'].strip()}}
+                "integration": {"url": self.URL+"/interactive", "context": {"action": "show_spoiler", "spoiler":msg_text}}
                 }]
             }]
 
@@ -32,4 +37,7 @@ class CommandSpoiler(AbstractCommand):
 
     def on_POST_interactive(self, request, data):
         if data["context"]["action"] == "show_spoiler":
-            request.respond_interactive_temp(data["context"]["spoiler"])
+            if data["context"]["spoiler"] != "":
+                request.respond_interactive_temp(data["context"]["spoiler"])
+            else:
+                request.respond_interactive_err("Post has no stored spoiler text")
-- 
2.43.0


From 6658be3e03cbc4cb6b45ed7edd8eb8a71f25f906 Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Sat, 12 Feb 2022 00:56:45 +0100
Subject: [PATCH 02/16] modules/DialogManagedCourseFeedback.py

---
 modules/DialogManagedCourseFeedback.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/DialogManagedCourseFeedback.py b/modules/DialogManagedCourseFeedback.py
index 69c1008..457e3e3 100644
--- a/modules/DialogManagedCourseFeedback.py
+++ b/modules/DialogManagedCourseFeedback.py
@@ -33,7 +33,7 @@ class DialogManagedCourseFeedback(AbstractCommand):
 
                 What we want to know:
                 + Was there an online option and how was it?
-                + How much time did you spent on this course.
+                + How much time did you spent on this course?
                 + This course's modalities - describe them in a few words. (Also consider updating the info in VoWi - its a work resource for us and we use it to represent you)
                 + How did you like the modalities of this course? (Would you want it to be applied to others?)
                 + Overall feedback for this course.
-- 
2.43.0


From fbe2f4e5392c1a213891010c46fbcc42f20d637f Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Sat, 12 Feb 2022 00:56:45 +0100
Subject: [PATCH 03/16] modules/TACommandSyncFSInf.py

---
 modules/TACommandSyncFSInf.py | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/modules/TACommandSyncFSInf.py b/modules/TACommandSyncFSInf.py
index bb4785a..45856ec 100644
--- a/modules/TACommandSyncFSInf.py
+++ b/modules/TACommandSyncFSInf.py
@@ -7,12 +7,12 @@ from inspect import cleandoc
 
 
 # pylint: disable=wrong-import-position
-from AbstractCommand import *
+from AbstractCommand import AbstractCommand
 class TACommandSyncFSInf(AbstractCommand):
     TRIGGER = "sync-fsinf"
     CONFIG = {"display_name": "somebot-command", "auto_complete": False,
              }
-    CONFIG["auto_complete_desc"] = CONFIG["description"] = "Sync TAs to other managed teams. [BOT_ADMIN]"
+    CONFIG["auto_complete_desc"] = CONFIG["description"] = AbstractCommand.ICON_PUBLIC+"Sync TAs to other managed teams. [BOT_ADMIN]"
 
 
     def __init__(self, team_id, managed_teams, fsinf_intern_channelid, ignore_accounts_channelid, fsinf_teams_and_channels):
@@ -25,7 +25,6 @@ class TACommandSyncFSInf(AbstractCommand):
 
 
     def on_POST(self, request, data):
-        raise Exception ("borked. low priority todo.")
         self._require_bot_admin(data) # will throw an exception if not. (Dont try-except: Its handled up the stack.)
 
 
@@ -34,7 +33,7 @@ class TACommandSyncFSInf(AbstractCommand):
         all_users = {u["id"]:u["username"] for u in self.bot.api.get_users()}
 
         fsinf_aktive_userids = fsinf_intern_userids-fsinf_altnasen_userids
-        self.bot.debug_chan(cleandoc("""
+        request.respond_cmd_chan(cleandoc("""
             ## ``/sync-fsinf``
             These accounts were detected to be fsinf-intern:
             ``"""+str(sorted([all_users[u] for u in fsinf_intern_userids]))+"""``
@@ -61,4 +60,4 @@ class TACommandSyncFSInf(AbstractCommand):
                     if not user_id in excluded_user_ids:
                         self.bot.api.add_user_to_channel(chan_id, user_id, exc=False)
 
-        request.cmd_respond_text_temp("### ``Done.`` :)")
+        request.respond_cmd_chan("## :white_check_mark: Success! :)")
-- 
2.43.0


From 5231738c127b0185ab8e5349fa27649cc3938d6d Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Wed, 16 Feb 2022 16:41:24 +0100
Subject: [PATCH 04/16] modules/TACommandSyncFSInf.py

---
 modules/TACommandSyncFSInf.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/modules/TACommandSyncFSInf.py b/modules/TACommandSyncFSInf.py
index 45856ec..6fa7127 100644
--- a/modules/TACommandSyncFSInf.py
+++ b/modules/TACommandSyncFSInf.py
@@ -55,9 +55,9 @@ class TACommandSyncFSInf(AbstractCommand):
                 self.bot.api.update_team_members_scheme_roles(t[0], user_id, {"scheme_user": True, "scheme_admin": True}, exc=False)
 
             # join into special channels
-            for team_id, chan_ids in self.guest_teams_and_channels.items():
+            for team_id, chan_ids in self.fsinf_teams_and_channels.items():
                 for chan_id, excluded_user_ids in chan_ids.items():
                     if not user_id in excluded_user_ids:
                         self.bot.api.add_user_to_channel(chan_id, user_id, exc=False)
 
-        request.respond_cmd_chan("## :white_check_mark: Success! :)")
+        request.respond_cmd_chan("## :white_check_mark: Success! :)", http_code=000)
-- 
2.43.0


From e0daeeff4e5b8228959c15785a08ea5f3cb5b97a Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Sun, 6 Mar 2022 00:33:15 +0100
Subject: [PATCH 05/16] modules/CommandCoronaPresenceLogger.py

---
 modules/CommandCoronaPresenceLogger.py | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/modules/CommandCoronaPresenceLogger.py b/modules/CommandCoronaPresenceLogger.py
index 4fbf3cf..81dfd72 100644
--- a/modules/CommandCoronaPresenceLogger.py
+++ b/modules/CommandCoronaPresenceLogger.py
@@ -54,11 +54,9 @@ class CommandCoronaPresenceLogger(AbstractCommand):
                 request.respond_cmd_temp(cleandoc("""
                     ## :white_check_mark: Success! :)
                     #### ``Your presence at FSINF today has been logged.``
-
                     This information is retained for about a month.
 
-                    If we get informed of somebody testing COVID-19 positive, we shall inform anyone being at fsinf on the same days.
-                    If you shall test COVID-19 positive, please inform us, so we can inform anyone who was at fsinf on the same days as you.
+                    #### :point_right: If you turn out to be COVID-positive please inform @someone to issue a warning to other possibly exposed people. :point_left:
                     """))
                 self.bot.api.add_user_to_channel("m5sik9jwmib6mfpnpcmsib1h7w", data["user_id"])
                 self.bot.debug_chan("``/cpl`` presence logged: ``"+data["user_name"]+"``")
-- 
2.43.0


From f0d80b3c7a7e1ee9905ef4b85b6b45dd3d79343a Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Fri, 18 Mar 2022 21:32:47 +0100
Subject: [PATCH 06/16] core/MMBot.py

---
 core/MMBot.py | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/core/MMBot.py b/core/MMBot.py
index 7a9454c..3ff565e 100644
--- a/core/MMBot.py
+++ b/core/MMBot.py
@@ -375,9 +375,6 @@ class MMBot():
                       use if_nonzero_secondary = 'force' to send secondary with http_code != 0.
                 """
 
-                import pprint
-                pprint.pprint(data)
-
                 if data is None:
                     data = {}
 
-- 
2.43.0


From 93b4f0030876d81dda55079b8a0aac2a36ca114a Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Fri, 18 Mar 2022 21:32:47 +0100
Subject: [PATCH 07/16] modules/CommandCoronaPresenceLogger.py

---
 modules/CommandCoronaPresenceLogger.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/modules/CommandCoronaPresenceLogger.py b/modules/CommandCoronaPresenceLogger.py
index 81dfd72..11af6b1 100644
--- a/modules/CommandCoronaPresenceLogger.py
+++ b/modules/CommandCoronaPresenceLogger.py
@@ -48,9 +48,9 @@ class CommandCoronaPresenceLogger(AbstractCommand):
             request.respond_cmd_chan("``AUTODELETE-DAY`` **``CPL, OIDA!``**", props={"cpl-meme-upload-todo":"todo"})
 
         elif re.match(r"^(-|—|–)+", data['text']):
-            filename = self.datadir + datetime.date.today().isoformat()+"--"+data["user_id"]
+            filename = self.datadir + datetime.date.today().isoformat()+"__"+data["user_id"]
             with open(filename, "a") as file:
-                file.write(data["user_name"]+" -- "+datetime.datetime.now().isoformat()+"\n")
+                file.write(data["user_id"]+" -- "+data["user_name"]+" -- "+datetime.datetime.now().isoformat()+"\n")
                 request.respond_cmd_temp(cleandoc("""
                     ## :white_check_mark: Success! :)
                     #### ``Your presence at FSINF today has been logged.``
-- 
2.43.0


From e566469d3a208ffbe9c086f1174cd120b78f546a Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Fri, 18 Mar 2022 21:32:47 +0100
Subject: [PATCH 08/16] modules/CommandDrink.py

---
 modules/CommandDrink.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/CommandDrink.py b/modules/CommandDrink.py
index 1e10757..65e9c5d 100644
--- a/modules/CommandDrink.py
+++ b/modules/CommandDrink.py
@@ -80,7 +80,7 @@ class CommandDrink(AbstractCommand):
                     break
 
             if shortcut is None:
-                request.respond_cmd_temp(msg+"\n:stop_sign: Invalid input: no such shortcut :(\nUse ``/drink-shortcuts`` for a list of shortcuts.")
+                request.respond_cmd_temp(msg+"\n:stop_sign: Invalid input: no such shortcut :(\nUse ``/drink`` without any parameters for a list of shortcuts.")
                 return
             else:
                 handle.do_transaction(shortcut["target"], str(int(shortcut["amount"])*count), shortcut["reason"])
-- 
2.43.0


From 854b92222a117106394f1c71f617a7da028a9896 Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Fri, 18 Mar 2022 21:32:47 +0100
Subject: [PATCH 09/16] modules/CommandJoinActive.py

---
 modules/CommandJoinActive.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/CommandJoinActive.py b/modules/CommandJoinActive.py
index 93df366..172b3af 100644
--- a/modules/CommandJoinActive.py
+++ b/modules/CommandJoinActive.py
@@ -79,7 +79,7 @@ class CommandJoinActive(AbstractCommand):
         msg = ""
         for chan in self.bot.api.get_team_channels(self.TEAM_ID):
             #check against ban list and get the last 10 posts, if all of them are newer than min_timestamp: join
-            if not chan["id"] in self.skip_chann_ids and self.channel_index[chan["id"]] > timestamp:
+            if chan["id"] not in self.channel_index and chan["id"] not in self.skip_chann_ids and self.channel_index[chan["id"]] > timestamp:
                 self.bot.api.add_user_to_channel(chan["id"], data["user_id"])
                 msg += "\n + ~"+chan["name"]
 
-- 
2.43.0


From 53dbfca8080104db3d922e40b48530d55a383753 Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Fri, 18 Mar 2022 21:32:47 +0100
Subject: [PATCH 10/16] modules/DialogManagedInfCoin.py

---
 modules/DialogManagedInfCoin.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/DialogManagedInfCoin.py b/modules/DialogManagedInfCoin.py
index bd06a45..6d1751e 100644
--- a/modules/DialogManagedInfCoin.py
+++ b/modules/DialogManagedInfCoin.py
@@ -66,7 +66,7 @@ class DialogManagedInfCoin(AbstractCommand):
 
         c = self.bot.api.create_dm_channel_with(data['user_id'])
         p = self.bot.api.create_post(c['id'], msg, props={"from_webhook":"true", "attachments":att})
-        request.cmd_respond_text_temp("@bot has written you a direct message.\n:arrow_right: https://mattermost.fsinf.at/"+data["team_domain"]+"/pl/"+p["id"])
+        request.respond_cmd_temp("@bot has written you a direct message.\n:arrow_right: https://mattermost.fsinf.at/"+data["team_domain"]+"/pl/"+p["id"])
 
 
     def on_POST_interactive(self, request, data):
-- 
2.43.0


From 87116b8d3a1b25aba0a11fe645e15dccd264e81d Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Sat, 19 Mar 2022 23:36:58 +0100
Subject: [PATCH 11/16] modules/WSDMNotSupportedNotification.py

---
 modules/WSDMNotSupportedNotification.py | 27 +++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 modules/WSDMNotSupportedNotification.py

diff --git a/modules/WSDMNotSupportedNotification.py b/modules/WSDMNotSupportedNotification.py
new file mode 100644
index 0000000..09218f3
--- /dev/null
+++ b/modules/WSDMNotSupportedNotification.py
@@ -0,0 +1,27 @@
+# Mattermost Bot module.
+#  Copyright (c) 2016-2022 by Someone <someone@somenet.org> (aka. Jan Vales <jan@jvales.net>)
+#  published under MIT-License
+
+from inspect import cleandoc
+
+
+# pylint: disable=wrong-import-position
+from AbstractWSHandler import AbstractWSHandler
+class WSDMNotSupportedNotification(AbstractWSHandler):
+    NAME = "dm-not-supported-notification"
+
+    def on_WS_EVENT(self, data):
+        if data["data"]["channel_type"] == "D" and data["data"]["sender_name"] != "@bot":
+            import pprint
+            pprint.pprint(data)
+            self.bot.api.create_post(data["broadcast"]["channel_id"], cleandoc("""
+                ``AUTODELETE-WEEK`` :warning: DMs not supported. Use self-channel as storage.
+                ## ``It seems like you sent me a direct message.``
+                While I appreciate the attention, I am not programmed to respond to this message in any meaningful way.
+
+                :warning: Also I feel like I need to point out that this channel can get wiped when I randomly malfunction and that it can happen that @someone gets to see the messages and files posted here when debugging me.
+
+                ##### :point_right: If you intended to store some files or messages for later use, maybe I can inspire you to use your "self-channel" @ https://mattermost.fsinf.at/fsinf/messages/"""+data["data"]["sender_name"]+""" instead?
+                """))
+
+        return True
-- 
2.43.0


From a173cf32b4990240bc4a1aaa019630b6c732dfb0 Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Mon, 21 Mar 2022 12:19:24 +0100
Subject: [PATCH 12/16] modules/WSDMNotSupportedNotification.py

---
 modules/WSDMNotSupportedNotification.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/WSDMNotSupportedNotification.py b/modules/WSDMNotSupportedNotification.py
index 09218f3..29036df 100644
--- a/modules/WSDMNotSupportedNotification.py
+++ b/modules/WSDMNotSupportedNotification.py
@@ -24,4 +24,4 @@ class WSDMNotSupportedNotification(AbstractWSHandler):
                 ##### :point_right: If you intended to store some files or messages for later use, maybe I can inspire you to use your "self-channel" @ https://mattermost.fsinf.at/fsinf/messages/"""+data["data"]["sender_name"]+""" instead?
                 """))
 
-        return True
+            return True
-- 
2.43.0


From 8ccdba8904b4a1d374741db6cd2fea8b391b647b Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Wed, 30 Mar 2022 18:59:38 +0200
Subject: [PATCH 13/16] modules/CommandJoinActive.py

---
 modules/CommandJoinActive.py | 93 ------------------------------------
 1 file changed, 93 deletions(-)
 delete mode 100644 modules/CommandJoinActive.py

diff --git a/modules/CommandJoinActive.py b/modules/CommandJoinActive.py
deleted file mode 100644
index 172b3af..0000000
--- a/modules/CommandJoinActive.py
+++ /dev/null
@@ -1,93 +0,0 @@
-# Mattermost Bot module.
-#  Copyright (c) 2016-2022 by Someone <someone@somenet.org> (aka. Jan Vales <jan@jvales.net>)
-#  published under MIT-License
-
-import datetime
-import threading
-from inspect import cleandoc
-
-import logging
-logger = logging.getLogger(__name__)
-
-# pylint: disable=wrong-import-position
-from AbstractCommand import AbstractCommand
-class CommandJoinActive(AbstractCommand):
-    TRIGGER = "join-active"
-    CONFIG = {"display_name": "somebot-command", "auto_complete": True,
-              "auto_complete_hint": "[<weeks; default=2>]"
-             }
-    USEINFO = CONFIG["auto_complete_desc"] = CONFIG["description"] = AbstractCommand.ICON_PRIVATE+"Join active public channels. active = '10 posts+ in the last x months'. There is no undo."
-
-
-    def __init__(self, team_id, skip_chann_ids):
-        super().__init__(team_id)
-
-        self.skip_chann_ids = skip_chann_ids
-        self.channel_index = None
-        self.channel_index_th = None
-
-
-    def on_register(self):
-        self._create_slash_command()
-        self.channel_index_th = threading.Timer(15.0, self._index_channels)
-        self.channel_index_th.setName("CommandJoinActive::_index_channels()")
-        self.channel_index_th.setDaemon(True)
-        self.channel_index_th.start()
-
-
-    def _index_channels(self):
-        if self.channel_index_th != threading.current_thread():
-            logger.warning("_index_channels(): thread mismatch")
-            return
-
-        logger.info("_index_channels(): started")
-        new_dict = {}
-        for chan in self.bot.api.get_team_channels(self.TEAM_ID):
-            if chan["id"] in self.skip_chann_ids:
-                continue
-
-            posts = []
-            for post in self.bot.api.get_posts_for_channel(chan["id"]):
-                if post["type"] in ["", "slack_attachement"]:
-                    posts.append(post)
-
-                if len(posts) == 5:
-                    break
-
-            new_dict[chan["id"]] = min([x["create_at"] for x in posts])
-
-        self.channel_index = new_dict
-        self.channel_index_th = threading.Timer(3600.0, self._index_channels)
-        self.channel_index_th.setName("CommandJoinActive::_index_channels()")
-        self.channel_index_th.setDaemon(True)
-        self.channel_index_th.start()
-        logger.info("_index_channels(): done")
-
-
-    def on_POST(self, request, data):
-        if self.channel_index is None:
-            request.respond_cmd_err("``/"+self.TRIGGER+"`` The channel indexer didnt finish yet. try again in a few minutes")
-            return
-
-        try:
-            td = datetime.timedelta(weeks=int(data["text"].strip()))
-        except:
-            td = datetime.timedelta(weeks=2)
-
-        timestamp = int((datetime.datetime.now()-td).timestamp())*1000
-
-        msg = ""
-        for chan in self.bot.api.get_team_channels(self.TEAM_ID):
-            #check against ban list and get the last 10 posts, if all of them are newer than min_timestamp: join
-            if chan["id"] not in self.channel_index and chan["id"] not in self.skip_chann_ids and self.channel_index[chan["id"]] > timestamp:
-                self.bot.api.add_user_to_channel(chan["id"], data["user_id"])
-                msg += "\n + ~"+chan["name"]
-
-        request.respond_cmd_temp(cleandoc("""
-            ## :white_check_mark: Success! :)
-            By default it wont join you into channels that had less than 5 messages posted within the last 2 weeks.
-            If you want to be joined into less active channels give the command an integer number of weeks to to consider.
-            /join-active 8 will join you into channels that had less than 5 messages posted within the last 2 months.
-            Anyway: joined the following active public channels in the team (A reload might be needed to display the updated list of channels):
-            {}
-            """).format(msg))
-- 
2.43.0


From fb51baa4dbb98ccbece3f6860a927e9491f7e1d6 Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Wed, 30 Mar 2022 18:59:38 +0200
Subject: [PATCH 14/16] modules/CommandJoinAll.py

---
 modules/CommandJoinAll.py | 74 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 69 insertions(+), 5 deletions(-)

diff --git a/modules/CommandJoinAll.py b/modules/CommandJoinAll.py
index 324eeb2..d13ca65 100644
--- a/modules/CommandJoinAll.py
+++ b/modules/CommandJoinAll.py
@@ -1,29 +1,93 @@
 # Mattermost Bot module.
 #  Copyright (c) 2016-2022 by Someone <someone@somenet.org> (aka. Jan Vales <jan@jvales.net>)
-#  Copyright (c) 2020 by lavish <marco.squarcina@tuwien.ac.at> ("Typos" fixed)
 #  published under MIT-License
 
+import datetime
+import threading
+from inspect import cleandoc
 
+import logging
+logger = logging.getLogger(__name__)
 
 # pylint: disable=wrong-import-position
 from AbstractCommand import AbstractCommand
 class CommandJoinAll(AbstractCommand):
     TRIGGER = "join-all"
-    CONFIG = {"display_name": "somebot-command", "auto_complete": True}
-    USEINFO = CONFIG["auto_complete_desc"] = CONFIG["description"] = AbstractCommand.ICON_PRIVATE+"Join all public channels in this team. There is no undo."
+    CONFIG = {"display_name": "somebot-command", "auto_complete": True,
+              "auto_complete_hint": "[<weeks; default=3>]"
+             }
+    USEINFO = CONFIG["auto_complete_desc"] = CONFIG["description"] = AbstractCommand.ICON_PRIVATE+"Join active public channels. considers channels with 7 posts+ in the last x weeks. default 3 weeks. There is no undo."
 
 
     def __init__(self, team_id, skip_chann_ids):
         super().__init__(team_id)
 
         self.skip_chann_ids = skip_chann_ids
+        self.channel_index = None
+        self.channel_index_th = None
+
+
+    def on_register(self):
+        self._create_slash_command()
+        self.channel_index_th = threading.Timer(10.0, self._index_channels)
+        self.channel_index_th.setName("CommandJoinActive::_index_channels()")
+        self.channel_index_th.setDaemon(True)
+        self.channel_index_th.start()
+
+
+    def _index_channels(self):
+        if self.channel_index_th != threading.current_thread():
+            logger.warning("_index_channels(): thread mismatch")
+            return
+
+        logger.info("_index_channels(): started")
+        new_dict = {}
+        for chan in self.bot.api.get_team_channels(self.TEAM_ID):
+            if chan["id"] in self.skip_chann_ids:
+                continue
+
+            posts = []
+            for post in self.bot.api.get_posts_for_channel(chan["id"]):
+                if not post["type"].startswith("system_"):
+                    posts.append(post)
+
+                if len(posts) == 7:
+                    break
+
+            new_dict[chan["id"]] = min([x["create_at"] for x in posts])
+
+        self.channel_index = new_dict
+        self.channel_index_th = threading.Timer(3600.0, self._index_channels)
+        self.channel_index_th.setName("CommandJoinActive::_index_channels()")
+        self.channel_index_th.setDaemon(True)
+        self.channel_index_th.start()
+        logger.info("_index_channels(): done")
 
 
     def on_POST(self, request, data):
+        if self.channel_index is None:
+            request.respond_cmd_err("``/"+self.TRIGGER+"`` The channel indexer didnt finish yet. try again in a few minutes")
+            return
+
+        try:
+            td = datetime.timedelta(weeks=int(data["text"].strip()))
+        except:
+            td = datetime.timedelta(weeks=3)
+
+        timestamp = int((datetime.datetime.now()-td).timestamp())*1000
+
         msg = ""
         for chan in self.bot.api.get_team_channels(self.TEAM_ID):
-            if not chan["id"] in self.skip_chann_ids:
+            #check against ban list and get the last 7 posts, if all of them are newer than min_timestamp: join
+            if chan["id"] not in self.channel_index and chan["id"] not in self.skip_chann_ids and self.channel_index[chan["id"]] > timestamp:
                 self.bot.api.add_user_to_channel(chan["id"], data["user_id"])
                 msg += "\n + ~"+chan["name"]
 
-        request.respond_cmd_temp("## :white_check_mark: Success! :)\nYou joined all the public channels in the team:\n{}\nA reload might be needed to display the updated list of channels".format(msg))
+        request.respond_cmd_temp(cleandoc("""
+            ## :white_check_mark: Success! :)
+            By default it wont join you into channels that had less than 5 messages posted within the last 2 weeks.
+            If you want to be joined into less active channels give the command an integer number of weeks to to consider.
+            /join-active 8 will join you into channels that had less than 5 messages posted within the last 2 months.
+            Anyway: joined the following active public channels in the team (A reload might be needed to display the updated list of channels):
+            {}
+            """).format(msg))
-- 
2.43.0


From bff7ee6a02bd63fe6c2019acaca78d0e335c9b01 Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Wed, 30 Mar 2022 18:59:38 +0200
Subject: [PATCH 15/16] modules/WSOnboarding.py

---
 modules/WSOnboarding.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/WSOnboarding.py b/modules/WSOnboarding.py
index 92b02b4..9e21312 100644
--- a/modules/WSOnboarding.py
+++ b/modules/WSOnboarding.py
@@ -49,7 +49,7 @@ class WSOnboarding(AbstractWSHandler):
 
         self.bot.api.create_post(chan['id'], cleandoc("""
             Es gibt etliche Befehle, die dir die Navigation in Mattermost erleichtern sollen. Einige wichtige sind:
-            + **``/join-active`` bzw. ``/join-all`` im FSInf-Team** - Befiehlt mir, dich in alle aktiven/verfügbaren öffentlichen Channels zu adden, damit du nich jedem Channel manuell beitreten musst.
+            + **``/join-all`` im FSInf-Team** - Befiehlt mir, dich in alle aktiven/verfügbaren öffentlichen Channels zu adden, damit du nich jedem Channel manuell beitreten musst.
             + **``/tissjoin <kopie der deutschsprachigen favoriten-tabelle aus tiss>`` nur im VoWi-Team** - Basically /join-all in sinnvoll. Added dich in die LVA-Channels deiner tiss-favoriten.
             + **``/beratungsinfo``** - Hilft dir, den Beratungschannel zu finden.
             + **``/threads``** - Mattermost benutzt Threads, um Diskussionen übersichtlicher zu gestalten. Mit diesem Befehl kannst du deine Mitstudierenden darauf hinweisen, Threads zu benutzen. Dies ist der wohl most over-used Befehl hier und ist bereits zu memes verarbeitet worden.
-- 
2.43.0


From a28313de1291c3771f67c19aaaadecf97a987540 Mon Sep 17 00:00:00 2001
From: Someone <someone@somenet.org>
Date: Fri, 22 Apr 2022 00:03:20 +0200
Subject: [PATCH 16/16] modules/CommandDrink.py

---
 modules/CommandDrink.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/CommandDrink.py b/modules/CommandDrink.py
index 65e9c5d..9dbdec4 100644
--- a/modules/CommandDrink.py
+++ b/modules/CommandDrink.py
@@ -36,7 +36,7 @@ class CommandDrink(AbstractCommand):
             account_data = handle.get_account_info()
             msg = ":arrow_right: Available credits:``"+str(account_data["account_info"]["balance"])+"``"
         except MCAPI.APIException as exc:
-            if exc.message == "AUTH_FAIL_ACCTOK":
+            if exc.message == "CERR_AUTH_FAIL_ACCTOK":
                 request.respond_cmd_temp(cleandoc("""
                     :stop_sign: Mattermost account seems to not be bound to any drink-terminal account. :(
                     Use ``/drink-bind-account <drink-terminal-username> <drink-terminal-password>`` to bind this Mattermost account to your drink-terminal account.
-- 
2.43.0