diff --git a/commands.json b/commands.json
index 5bf09dd85b97c9e969898a8afb1f8937cb472a8e..7fa3ed2527845cddd56d7f746c110c5b17089708 100644
--- a/commands.json
+++ b/commands.json
@@ -94,7 +94,17 @@
             "Description": "Syntax: .deepl <Language>, <String>. Translate a word, sentence or even small texts with DeepL translator. Type: .deepl ES, Where is the library?",
             "_Func": "get_deepl_translation",
             "allowedGroups":[]
+        },
+        {
+            "Names": [
+                ".addsong"
+            ],
+            "Description": "Syntax: .addsong <Message>. Just add .addsong to your normal Spotify Song Msg. The bot will do the rest.",
+            "_Func": "add_song_to_playlist",
+            "allowedGroups":["Testung", "ntp.ReleaseRadar"]
         }
+
+        
     ],
     "Crawlers": [
         {
diff --git a/mod_spotify.py b/mod_spotify.py
new file mode 100644
index 0000000000000000000000000000000000000000..f8582a0775d695733f40f71e70edd298399654cc
--- /dev/null
+++ b/mod_spotify.py
@@ -0,0 +1,45 @@
+# ntp.ReleaseRadar
+# https://open.spotify.com/playlist/3Px6Qe12qrEltV1r6AKvec?si=d740d824248a4f9a
+
+import spotipy
+from spotipy.oauth2 import SpotifyOAuth
+import re
+
+
+class ModuleSpotify:
+    # track_uri = "https://open.spotify.com/intl-de/track/1Hig7RNxPMrYZ9aN5lZtAd?si=a9a85b60cd444f2b"
+
+    def __init__(self, send, client_id, client_secret, redirect_uri, log):
+        self.tag = "%20s - " % "mSpotify"
+        self.log = log
+        self.send = send
+        scope = "playlist-modify-public"
+        self.playlist_id = "1KpS9GIl23CPmTxJrBh6iD"
+        username = "usatas"
+
+        self.sp = spotipy.Spotify(
+            auth_manager=SpotifyOAuth(
+                client_id=client_id,
+                client_secret=client_secret,
+                redirect_uri=redirect_uri,
+                scope=scope,
+                username=username,
+            )
+        )
+        self.log.debug(f"{self.tag}Modul Spotify geladen")
+
+    # https://open.spotify.com/intl-de/track/1Hig7RNxPMrYZ9aN5lZtAd?si=f084120527084c1b
+    def add_song_to_playlist(self, song_msg):
+        song_uri = "spotify:track:"
+
+        match = re.search(r"\/([a-zA-Z0-9]+)\?", song_msg)
+        if not match:
+            return "Nope - invalid song URL!"
+
+        song_uri += match.group(1)
+        self.sp.playlist_add_items(
+            playlist_id=self.playlist_id, items=[song_uri]
+        )  # TODO Abfragen ob der song schon drin ist
+        return "song added to https://open.spotify.com/playlist/1KpS9GIl23CPmTxJrBh6iD?si=6b384ff854574269"
+
+    # http://localhost:8080/?code=AQCWMXelx3cI0aH5O0s0XtG-NY1ogpwC2sQbb6nN4mwStY1irihYEYBRC13g0WBNLN8fxg5eBiS0B2jl_c9X5XHVoGs6nAAUV4A1le0jFx7FcCGqBBHndOZMnbrmQ6LFsY4TicHnvm0SgIr-gjOmcwxt0kXsCu8L9w&state=playlist-modify-public
diff --git a/requirements.txt b/requirements.txt
index 1e5c4747408d5c39870a2e151ee94b0d52060228..ef615020b4fd62572f500f4320945ff4630fcf04 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,4 +8,5 @@ matplotlib
 beautifulsoup4
 python-dateutil
 sympy
-deepl
\ No newline at end of file
+deepl
+spotipy
\ No newline at end of file
diff --git a/signalbot.py b/signalbot.py
index f1cf5b844bdca8c9a7582e2fd4ec39740cd13f7c..6c68b10f3d5bc6a34aff11289d028176654390ad 100755
--- a/signalbot.py
+++ b/signalbot.py
@@ -26,13 +26,14 @@ from mod_quotes import ModuleQuotes
 from mod_tex import ModuleTex
 from mod_eventreminder import ModuleEventReminder
 from mod_today import ModuleToday
+from mod_spotify import ModuleSpotify
 
 #  @TODO Einfacher Wrapper zum senden von Nachrichten per shell
 #  @TODO Config Programm bot-config.py mit dem allgemeine Einstellungen wie Profilname oder Profilbild angepasst werden können
 
 
 # create logger
-log = logging.getLogger('signalbot')
+log = logging.getLogger("signalbot")
 log.setLevel(logging.DEBUG)
 
 # create console handler and set level to debug
@@ -41,7 +42,7 @@ fh = logging.FileHandler("signalbot_debug.log")
 fh.setLevel(logging.DEBUG)
 
 # create formatter
-formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
+formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
 # add formatters to handlers
 fh.setFormatter(formatter)
 
@@ -86,8 +87,12 @@ def load_config(filename):
     global GROUPS
     global translator
 
+    global spotify_client_id
+    global spotify_client_secret
+    global spotify_redirect_uri
+
     try:
-        CONFIG = json.load(open(filename, 'r'))
+        CONFIG = json.load(open(filename, "r"))
         if "FUN_DICT" in CONFIG:
             FUN_DICT = CONFIG["FUN_DICT"]
         if "MQTT" in CONFIG:
@@ -109,6 +114,14 @@ def load_config(filename):
         if "DEEPLAPI" in CONFIG:
             if CONFIG["DEEPLAPI"] != "API-Key":
                 translator = deepl.Translator(CONFIG["DEEPLAPI"])
+        if "Spotify" in CONFIG:
+            if "client_id" in CONFIG["Spotify"]:
+                spotify_client_id = CONFIG["Spotify"]["client_id"]
+            if "client_secret" in CONFIG["Spotify"]:
+                spotify_client_secret = CONFIG["Spotify"]["client_secret"]
+            if "redirect_uri" in CONFIG["Spotify"]:
+                spotify_redirect_uri = CONFIG["Spotify"]["redirect_uri"]
+
     except FileNotFoundError:
         log.error(f"File:'{filename}' not accessible. Running in reduced mode.")
 
@@ -117,7 +130,12 @@ def load_config(filename):
 
 
 def handle_action(timestamp, source, groupID, message, attachments):
-    if not message.startswith(".") or len(message) <= 2 or message[0:2] == ".." or message[0:3] == "._.":
+    if (
+        not message.startswith(".")
+        or len(message) <= 2
+        or message[0:2] == ".."
+        or message[0:3] == "._."
+    ):
         return
     print(timestamp)
     print(source)
@@ -125,16 +143,16 @@ def handle_action(timestamp, source, groupID, message, attachments):
     print(message)
     print(attachments)
 
-    msgDict={
-            "timestamp":timestamp,
-            "source":source,
-            "groupID":groupID,
-            "attachments":attachments,
-            "receiver":source
+    msgDict = {
+        "timestamp": timestamp,
+        "source": source,
+        "groupID": groupID,
+        "attachments": attachments,
+        "receiver": source,
     }
-    msgDict["groupInfo"]  = None
+    msgDict["groupInfo"] = None
     if len(groupID) > 0:
-        msgDict["receiver"]=groupID
+        msgDict["receiver"] = groupID
         # wenn gruppe, dann berechtigungsobjekt suchen um die rechte zu beschneiden
         for group in GROUPS:
             if group["ID"] == groupID:
@@ -151,8 +169,11 @@ def handle_action(timestamp, source, groupID, message, attachments):
         globals()[commands.get_function(msgDict)](msgDict)
 
     except Exception as ex:
-        log.critical(f'Unknown error:"{ex}", timestamp="{timestamp}", source="{source}", groupID="{groupID}", '
-                     f'message="{message}", attachments="{attachments}"')
+        log.critical(
+            f'Unknown error:"{ex}", timestamp="{timestamp}", source="{source}", groupID="{groupID}", '
+            f'message="{message}", attachments="{attachments}"'
+        )
+
 
 def send(message, receiver):
     if not receiver:
@@ -175,6 +196,7 @@ def send(message, receiver):
                 break
         send(err_message, request_group["ID"])
 
+
 def send_a(message, receiver, attachment):
     if not receiver:
         return
@@ -196,9 +218,10 @@ def send_a(message, receiver, attachment):
         send(err_message, request_group["ID"])
 
 
-def echo (msgDict):
+def echo(msgDict):
     send(FUN_DICT[msgDict["action"]], msgDict["receiver"])
 
+
 def help_func(msgDict):
     answer = ""
     if len(msgDict["content"]) > 0:
@@ -209,36 +232,40 @@ def help_func(msgDict):
 
 
 def remus_feinste(msgDict):
-    message = "- 1,5l Weißwein\n" \
-              "- 2,5l Rotwein\n" \
-              "- Obst nach Geschmack (bspw.: grüne Äpfel und Orangen)\n" \
-              "- N Batzen Zucker\n" \
-              "- guter Schuss Obstschnaps\n" \
-              "- Gran Manier (Prangenlikör) is beste\n" \
-              "- Fanta / O-Saft\n" \
-              "Originalrezept von Onkel Remus\n"
+    message = (
+        "- 1,5l Weißwein\n"
+        "- 2,5l Rotwein\n"
+        "- Obst nach Geschmack (bspw.: grüne Äpfel und Orangen)\n"
+        "- N Batzen Zucker\n"
+        "- guter Schuss Obstschnaps\n"
+        "- Gran Manier (Prangenlikör) is beste\n"
+        "- Fanta / O-Saft\n"
+        "Originalrezept von Onkel Remus\n"
+    )
     send(message, msgDict["receiver"])
 
 
 def true_american(msgDict):
-    message = "True American Regeln: So funktioniert das Spiel aus New Girl\n\n" \
-              "- Sie nun folgende Utensilien: Mindestens zwei weitere Mitspieler, drei Dosen Bier pro Spieler, eine Flasche Schnaps, einen Mülleimer, sowie einen Raum mit Möbeln und einem großen Tisch, den Sie am nächsten Tag mit Sicherheit putzen müssen. \n\n" \
-              "- Stellen Sie die Schnapsflasche, den \"König\", in die Mitte des Tisches und die Dosenbiere (die \"Soldaten\") um den König herum, um ihn zu beschützen. Platzieren Sie die Möbel im Raum in vier Zonen kreisförmig um den Tisch herum, sodass Sie sich bewegen können, ohne den Boden zu berühren, denn: Der Boden ist Lava! \n\n" \
-              "- Nun wählen Sie Teams: Halten sie sich mit Ihren Fingern eine Zahl von eins bis fünf vor die Stirn, die Person mit einem Finger weniger vor der Stirn ist Ihr Teamkollege. Falls Sie niemanden finden, sind Sie auf sich alleine gestellt. \n\n" \
-              "JFK! Jetzt wird gespielt.\n\n" \
-              "- Zu Beginn ruft einer der Mitspieler Laut \"JFK\", alle Anderen antworten \"FDR\", rennen zur Burg, nehmen sich ein Bier und sichern sich den Platz auf einem der Möbelstücke in der äußersten Zone. Nun wird im Uhrzeigersinn gespielt. Wer eine Aufgabe erfolgreich erledigt, trinkt einen Schluck und darf einen Platz weiter. Dabei gibt es drei verschiedene Aufgabentypen. \n\n" \
-              "- Erstens: Der Spieler, der an der Reihe ist, nennt zwei Gegenstände oder Personen, die Anderen schreien eine Gemeinsamkeit der Objekte in die Runde. Zweitens: Der Spieler beginnt ein Sprichwort, die anderen Mitspieler vollenden das Sprichwort. Drittens: Alle halten sich Zahlen (mit einer Hand) an die Stirn, Spieler mit gleichen Zahlen vollenden die Aufgabe. \n\n" \
-              "- Ist eine Aufgabe erfolgreich absolviert, trinken Sie einen Schluck und ziehen ein Möbelstück weiter. Dabei dürfen Sie nie den Boden berühren oder ein leeres Bier in der Hand halten. Schreit ein beliebiger Mitspieler \"JFK\", antworten alle Anderen mit \"FDR\" und müssen ihr Bier austrinken. \n\n" \
-              "- Wenn alle Biere vom Tisch getrunken wurden, ist der König, also die Schnapsflache, \"verwundbar\". Der Spieler, der zuerst die innerste Zone erreicht, kann dann einen Schluck aus der Schnapsflasche trinken und hat damit - zusammen mit seinem Teamkollegen - gewonnen. \n\n" \
-              "- Verloren hat der Spieler, der während des Spieles mit einem leeren Bier erwischt wird oder der den Boden, also die Lava berührt. Zurück ins Spiel kommen Sie, indem Sie ein ganzes Bier austrinken. Auf welchen Platz Sie dann gesetzt werden, entscheiden die Mitspielenden. \n\n" \
-              "Willkürliche Zusatzregeln\n" \
-              "Als wäre das Spiel noch nicht kompliziert und verwirrend genug, erklären wir Ihnen in unserem letzten Kapitel noch einige - zugegeben ziemlich willkürliche - Zusatzregeln.\n\n" \
-              "- Spielen Sie mit der \"Clinton-Zusatzregel\", so muss jeder Spieler, der eine Aufgabe nicht vollenden konnte, ein Kleidungsstück ablegen. Zusätzlich müssen sich bei Aufgabentyp 3 Spieler mit der gleichen Zahl \"hinter dem eisernen Vorhang\" (zum Beispiel in einem anderen Raum) küssen. \n\n" \
-              "- Ruft ein Spieler \"All trash belongs...\" so antworten die Anderen \"in the junkyard!\" und werfen eine leere Dose in den Mülleimer am anderen Ende des Raumes. Wenn jemand \"Donald Trump\" ruft, so müssen alle mit \"Build the wall!\" antworten und trinken. \n\n" \
-              "-Die wichtigste Regeln bei True American: Alles was bei True American gesagt wird, ist angeblich eine Lüge und es geht nicht um das Gewinnen, sondern darum, ein richtiger Amerikaner zu sein. \n\n\n" \
-              "#DankeFocus: https://praxistipps.focus.de/true-american-regeln-so-funktioniert-das-spiel-aus-new-girl_126279\n\n" \
-              "https://www.trueamericanrules.com/working-rules/"
-    send_a(message, msgDict["receiver"], '/home/pi/signalbot/true_american_layout.png')
+    message = (
+        "True American Regeln: So funktioniert das Spiel aus New Girl\n\n"
+        "- Sie nun folgende Utensilien: Mindestens zwei weitere Mitspieler, drei Dosen Bier pro Spieler, eine Flasche Schnaps, einen Mülleimer, sowie einen Raum mit Möbeln und einem großen Tisch, den Sie am nächsten Tag mit Sicherheit putzen müssen. \n\n"
+        '- Stellen Sie die Schnapsflasche, den "König", in die Mitte des Tisches und die Dosenbiere (die "Soldaten") um den König herum, um ihn zu beschützen. Platzieren Sie die Möbel im Raum in vier Zonen kreisförmig um den Tisch herum, sodass Sie sich bewegen können, ohne den Boden zu berühren, denn: Der Boden ist Lava! \n\n'
+        "- Nun wählen Sie Teams: Halten sie sich mit Ihren Fingern eine Zahl von eins bis fünf vor die Stirn, die Person mit einem Finger weniger vor der Stirn ist Ihr Teamkollege. Falls Sie niemanden finden, sind Sie auf sich alleine gestellt. \n\n"
+        "JFK! Jetzt wird gespielt.\n\n"
+        '- Zu Beginn ruft einer der Mitspieler Laut "JFK", alle Anderen antworten "FDR", rennen zur Burg, nehmen sich ein Bier und sichern sich den Platz auf einem der Möbelstücke in der äußersten Zone. Nun wird im Uhrzeigersinn gespielt. Wer eine Aufgabe erfolgreich erledigt, trinkt einen Schluck und darf einen Platz weiter. Dabei gibt es drei verschiedene Aufgabentypen. \n\n'
+        "- Erstens: Der Spieler, der an der Reihe ist, nennt zwei Gegenstände oder Personen, die Anderen schreien eine Gemeinsamkeit der Objekte in die Runde. Zweitens: Der Spieler beginnt ein Sprichwort, die anderen Mitspieler vollenden das Sprichwort. Drittens: Alle halten sich Zahlen (mit einer Hand) an die Stirn, Spieler mit gleichen Zahlen vollenden die Aufgabe. \n\n"
+        '- Ist eine Aufgabe erfolgreich absolviert, trinken Sie einen Schluck und ziehen ein Möbelstück weiter. Dabei dürfen Sie nie den Boden berühren oder ein leeres Bier in der Hand halten. Schreit ein beliebiger Mitspieler "JFK", antworten alle Anderen mit "FDR" und müssen ihr Bier austrinken. \n\n'
+        '- Wenn alle Biere vom Tisch getrunken wurden, ist der König, also die Schnapsflache, "verwundbar". Der Spieler, der zuerst die innerste Zone erreicht, kann dann einen Schluck aus der Schnapsflasche trinken und hat damit - zusammen mit seinem Teamkollegen - gewonnen. \n\n'
+        "- Verloren hat der Spieler, der während des Spieles mit einem leeren Bier erwischt wird oder der den Boden, also die Lava berührt. Zurück ins Spiel kommen Sie, indem Sie ein ganzes Bier austrinken. Auf welchen Platz Sie dann gesetzt werden, entscheiden die Mitspielenden. \n\n"
+        "Willkürliche Zusatzregeln\n"
+        "Als wäre das Spiel noch nicht kompliziert und verwirrend genug, erklären wir Ihnen in unserem letzten Kapitel noch einige - zugegeben ziemlich willkürliche - Zusatzregeln.\n\n"
+        '- Spielen Sie mit der "Clinton-Zusatzregel", so muss jeder Spieler, der eine Aufgabe nicht vollenden konnte, ein Kleidungsstück ablegen. Zusätzlich müssen sich bei Aufgabentyp 3 Spieler mit der gleichen Zahl "hinter dem eisernen Vorhang" (zum Beispiel in einem anderen Raum) küssen. \n\n'
+        '- Ruft ein Spieler "All trash belongs..." so antworten die Anderen "in the junkyard!" und werfen eine leere Dose in den Mülleimer am anderen Ende des Raumes. Wenn jemand "Donald Trump" ruft, so müssen alle mit "Build the wall!" antworten und trinken. \n\n'
+        "-Die wichtigste Regeln bei True American: Alles was bei True American gesagt wird, ist angeblich eine Lüge und es geht nicht um das Gewinnen, sondern darum, ein richtiger Amerikaner zu sein. \n\n\n"
+        "#DankeFocus: https://praxistipps.focus.de/true-american-regeln-so-funktioniert-das-spiel-aus-new-girl_126279\n\n"
+        "https://www.trueamericanrules.com/working-rules/"
+    )
+    send_a(message, msgDict["receiver"], "/home/pi/signalbot/true_american_layout.png")
 
 
 def yes_no_wtf(msgDict):
@@ -246,16 +273,19 @@ def yes_no_wtf(msgDict):
     result = response[2:-1]
     json_response = json.loads(result)
     img_data = requests.get(json_response["image"]).content
-    with open('yn.gif', 'wb') as handler:
+    with open("yn.gif", "wb") as handler:
         handler.write(img_data)
-    send_a(json_response["answer"], msgDict["receiver"], '/home/pi/signalbot/yn.gif')
+    send_a(json_response["answer"], msgDict["receiver"], "/home/pi/signalbot/yn.gif")
 
 
 def dadjoke(msgDict):
-    response = requests.get(f"https://icanhazdadjoke.com", headers={"Accept": "application/json"})
+    response = requests.get(
+        f"https://icanhazdadjoke.com", headers={"Accept": "application/json"}
+    )
     result = response.json()
     send(result["joke"], msgDict["receiver"])
 
+
 def links(msgDict):
     links = {}
     if msgDict["groupInfo"] is not None and "LINKS" in msgDict["groupInfo"]:
@@ -283,7 +313,9 @@ def links(msgDict):
 
 
 def save_quote(msgDict):
-    send(quotes.save_quote(msgDict["content"], msgDict["groupInfo"]), msgDict["receiver"])
+    send(
+        quotes.save_quote(msgDict["content"], msgDict["groupInfo"]), msgDict["receiver"]
+    )
 
 
 def random_quote(msgDict):
@@ -291,17 +323,20 @@ def random_quote(msgDict):
 
 
 def credits(msgDict):
-    message = "Made with ☕ and ❤️\n" \
-              "by Frederic Aust & Philip Maas\n" \
-              "Git: https://gitlab.cvh-server.de/faust/signalbot \n" \
-              "Licence: AGPL v3"
+    message = (
+        "Made with ☕ and ❤️\n"
+        "by Frederic Aust & Philip Maas\n"
+        "Git: https://gitlab.cvh-server.de/faust/signalbot \n"
+        "Licence: AGPL v3"
+    )
     send(message, msgDict["receiver"])
 
 
 def free_games(msgDict):
-    #games.freegames(msgDict["receiver"])
+    # games.freegames(msgDict["receiver"])
     send("Sry freegamesyo.com has been discontinued... ☹️", msgDict["receiver"])
 
+
 def genderneutral(msgDict):
     global gn
     message = gn.search_in_db(msgDict["content"])
@@ -374,7 +409,10 @@ def get_random_challenge(msgDict):
 
 
 def save_birthday(msgDict):
-    send(birthday_reminder.save_birthday(msgDict["content"], msgDict["groupInfo"]), msgDict["receiver"])
+    send(
+        birthday_reminder.save_birthday(msgDict["content"], msgDict["groupInfo"]),
+        msgDict["receiver"],
+    )
 
 
 def get_all_birthdays(msgDict):
@@ -386,14 +424,20 @@ def get_next_birthday(msgDict):
 
 
 def save_event(msgDict):
-    send(event_reminder.save_event(msgDict["content"], msgDict["groupInfo"]), msgDict["receiver"])
+    send(
+        event_reminder.save_event(msgDict["content"], msgDict["groupInfo"]),
+        msgDict["receiver"],
+    )
 
 
 def get_all_upcomming_events(msgDict):
     send(event_reminder.get_eventlist(msgDict["groupInfo"]), msgDict["receiver"])
 
+
 def get_all_events(msgDict):
-    send(event_reminder.get_complete_eventlist(msgDict["groupInfo"]), msgDict["receiver"])
+    send(
+        event_reminder.get_complete_eventlist(msgDict["groupInfo"]), msgDict["receiver"]
+    )
 
 
 def get_next_event(msgDict):
@@ -401,12 +445,19 @@ def get_next_event(msgDict):
 
 
 def unknown_command(msgDict):
-    log.debug(f'Unknown action: {msgDict["action"]} {msgDict["content"]} from: {msgDict["receiver"]}')
-    send(f'Das habe ich nicht verstanden: "{msgDict["action"]} {msgDict["content"]}" ', msgDict["receiver"])
+    log.debug(
+        f'Unknown action: {msgDict["action"]} {msgDict["content"]} from: {msgDict["receiver"]}'
+    )
+    send(
+        f'Das habe ich nicht verstanden: "{msgDict["action"]} {msgDict["content"]}" ',
+        msgDict["receiver"],
+    )
 
 
 def get_tex_formula(msgDict):
-    send_a(msgDict["content"], msgDict["receiver"], tex.create_formula(msgDict["content"]))
+    send_a(
+        msgDict["content"], msgDict["receiver"], tex.create_formula(msgDict["content"])
+    )
 
 
 def get_deepl_translation(msgDict):
@@ -421,7 +472,7 @@ def get_deepl_translation(msgDict):
     try:
         result = translator.translate_text(text, target_lang=lang)
     except Exception as ex:
-        send(f'{ex}', msgDict["receiver"])
+        send(f"{ex}", msgDict["receiver"])
         return
 
     answer = "Computer says no"
@@ -433,15 +484,39 @@ def get_deepl_translation(msgDict):
     send(answer, msgDict["receiver"])
 
 
+def add_song_to_playlist(msgDict):
+    if (
+        ModuleSpotify is None
+        or spotify_client_id is None
+        or spotify_client_secret is None
+        or spotify_redirect_uri is None
+    ):  # TODO bereits in der INit berücksichtigen, wenn die Secrets nicht am start sind
+        send("There is no Spotify!", msgDict["receiver"])
+        return
+
+    try:
+        send(spotify.add_song_to_playlist(msgDict["content"]), msgDict["receiver"])
+
+    except Exception as ex:
+        send(f"{ex}", msgDict["receiver"])
+        return
+
+
 def get_kings_cup(msgDict):
-    send_a("Don't drink and derive!",msgDict["receiver"], "/home/pi/signalbot/kings_cup_regeln.png")
+    send_a(
+        "Don't drink and derive!",
+        msgDict["receiver"],
+        "/home/pi/signalbot/kings_cup_regeln.png",
+    )
+
 
 def get_today(msgDict):
     send(today.getTodayMessage(), msgDict["receiver"])
 
+
 def on_mqtt_message(client, userdata, msg):
     print(msg.topic + " " + str(msg.payload))
-    send(msg.topic + " " + str(msg.payload), CONFIG['Admins']['Fred'])
+    send(msg.topic + " " + str(msg.payload), CONFIG["Admins"]["Fred"])
 
 
 def mqtt_client():
@@ -464,25 +539,33 @@ def init_schedule_jobs():
     schedule.every().day.at("19:00").do(run_threaded, send_heartbeat)
     schedule.every().monday.at("06:00").do(run_threaded, gn.update_db)
     schedule.every().hour.do(run_threaded, games.auto_newsletter)
-    schedule.every().day.at("00:01").do(run_threaded, birthday_reminder.check_for_birthdays)
+    schedule.every().day.at("00:01").do(
+        run_threaded, birthday_reminder.check_for_birthdays
+    )
     schedule.every().day.at("09:00").do(run_threaded, event_reminder.check_for_events)
     schedule.every().tuesday.at("10:00").do(run_threaded, gg_remind_schichten)
     schedule.every().thursday.at("11:00").do(run_threaded, gg_remind_stundenzettel)
-    schedule.every().day.at("13:00").do(run_threaded,today.update)
+    schedule.every().day.at("13:00").do(run_threaded, today.update)
     schedule.every().thursday.at("10:00").do(run_threaded, remind_pflanzen)
-   # schedule.every(10).seconds.do(run_threaded, birthday_reminder.check_for_birthdays)
+
+
+# schedule.every(10).seconds.do(run_threaded, birthday_reminder.check_for_birthdays)
 
 
 def remind_pflanzen():
     for group in GROUPS:
         if group["NAME"] == "TierWG":
-            send(f'Bitte gebt den armen Pflanzen etwas Lebenselixier!', group["ID"])
+            send(f"Bitte gebt den armen Pflanzen etwas Lebenselixier!", group["ID"])
             break
 
+
 def gg_remind_schichten():
     for group in GROUPS:
         if group["NAME"] == "GGOffiziell":
-            send(f'Bitte tragt euch in die Planung ein:\n {group["LINKS"]["Planung"]}', group["ID"])
+            send(
+                f'Bitte tragt euch in die Planung ein:\n {group["LINKS"]["Planung"]}',
+                group["ID"],
+            )
             break
 
 
@@ -497,7 +580,9 @@ def gg_remind_stundenzettel():
     if now.month == 12:
         last_day = datetime.datetime(now.year + 1, 1, 1) - datetime.timedelta(days=1)
     else:
-        last_day = datetime.datetime(now.year, now.month + 1, 1) - datetime.timedelta(days=1)
+        last_day = datetime.datetime(now.year, now.month + 1, 1) - datetime.timedelta(
+            days=1
+        )
 
     # Determine the last Tuesday of the month
     # Here, we enter a loop that continues subtracting one day from the last day of the month
@@ -517,13 +602,16 @@ def gg_remind_stundenzettel():
 
     if last_day == date.today().day:
         send(
-    '''Bitte schickt eure ausgefüllten Stundenzettel!
+            """Bitte schickt eure ausgefüllten Stundenzettel!
     • ihr müsst eure Abrechnungen jeden Monat sowohl an Sarah, als auch an Ben senden.
     • sie müssen signiert und mit dem Kreuzchen im oberen Kästchen versehen sein
     • eure Emails müssen einen Anhang haben (duh)
     • der Betreff eurer Email sollte "Abrechnung Nachname Monat Jahr" beinhalten, das macht es leichter Sie zu finden.
     • in die Zeile "Tätigkeit" muss bitte "aktivierende Arbeit im offenen Bereich" eingetragen werden. Nichts anderes!!1
-    • sollten eure Abrechnungen mal falsch/ zu spät sein ist das kein Weltuntergang, dann gibt's das Geld einen Monat später - es verfällt nicht. Sollten sich dadurch persönliche Probleme ergeben sprecht uns bitte an, es gibt immer Lösungen.''', gg_group["ID"])
+    • sollten eure Abrechnungen mal falsch/ zu spät sein ist das kein Weltuntergang, dann gibt's das Geld einen Monat später - es verfällt nicht. Sollten sich dadurch persönliche Probleme ergeben sprecht uns bitte an, es gibt immer Lösungen.""",
+            gg_group["ID"],
+        )
+
 
 def start_schedule():
     while True:
@@ -537,21 +625,24 @@ def run_threaded(job_func):
 
 
 if __name__ == "__main__":
-    load_config('/home/pi/signalbot/config.json')
+    load_config("/home/pi/signalbot/config.json")
 
-    gn = ModuleGenderneutral('gn.json', log)
+    gn = ModuleGenderneutral("gn.json", log)
     quotes = ModuleQuotes(GROUPS, log)
     games = ModuleFreeGames(FREE_GAMES_SUBSCRIBER, send_a, log)
-    challenges = ModuleChallenge('/home/pi/signalbot/challenge.json', log)
+    challenges = ModuleChallenge("/home/pi/signalbot/challenge.json", log)
     birthday_reminder = ModuleBirthdayReminder(GROUPS, send, log)
     tex = ModuleTex(log)
-    commands = ModuleCommands('/home/pi/signalbot/commands.json',FUN_DICT, log)
+    commands = ModuleCommands("/home/pi/signalbot/commands.json", FUN_DICT, log)
     event_reminder = ModuleEventReminder(GROUPS, send, log)
+    spotify = ModuleSpotify(
+        send, spotify_client_id, spotify_client_secret, spotify_redirect_uri, log
+    )
     today = ModuleToday(log)
     loop = GLib.MainLoop()
     bus = SystemBus()
 
-    signal = bus.get('org.asamk.Signal')
+    signal = bus.get("org.asamk.Signal")
     signal.onMessageReceived = handle_action
 
     # mqtt_thread = Thread(target=mqtt_client)