From 54633ef5ab23148d09c63e2bc31f471f77815534 Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Tue, 24 Sep 2019 18:12:44 +0200
Subject: [PATCH] Working audioscrobbler with last.fm!

---
 api/plugins/fw_scrobbler/hooks.py     | 26 +++++++++++++++-
 api/plugins/fw_scrobbler/scrobbler.py | 44 ++++++++++++++++++++-------
 front/src/components/audio/Player.vue |  2 +-
 3 files changed, 59 insertions(+), 13 deletions(-)

diff --git a/api/plugins/fw_scrobbler/hooks.py b/api/plugins/fw_scrobbler/hooks.py
index 4769bbf723..dc919014c7 100644
--- a/api/plugins/fw_scrobbler/hooks.py
+++ b/api/plugins/fw_scrobbler/hooks.py
@@ -19,7 +19,7 @@ def forward_to_scrobblers(listening, plugin_conf, **kwargs):
     if username and password:
         plugin.logger.info("Forwarding scrobbler to %s", url)
         session = plugin.get_requests_session()
-        session_key, scrobble_url = scrobbler.handshake_v1(
+        session_key, _, scrobble_url = scrobbler.handshake_v1(
             session=session, url=url, username=username, password=password
         )
         scrobbler.submit_scrobble_v1(
@@ -31,3 +31,27 @@ def forward_to_scrobblers(listening, plugin_conf, **kwargs):
         )
     else:
         plugin.logger.debug("No scrobbler configuration for user, skipping")
+
+
+@plugin.hooks.connect("history.listening.now")
+def forward_to_now_playing(track, user, plugin_conf, **kwargs):
+    if plugin_conf["user"] is None:
+        raise plugins.Skip()
+
+    username = plugin_conf["user"]["settings"].get("service__username")
+    password = plugin_conf["user"]["settings"].get("service__password")
+    url = plugin_conf["user"]["settings"].get("service__url", DEFAULT_SCROBBLER_URL)
+    if username and password:
+        plugin.logger.info("Forwarding scrobbler to %s", url)
+        session = plugin.get_requests_session()
+        session_key, now_playing_url, _ = scrobbler.handshake_v1(
+            session=session, url=url, username=username, password=password
+        )
+        scrobbler.submit_now_playing_v1(
+            session=session,
+            track=track,
+            session_key=session_key,
+            now_playing_url=now_playing_url,
+        )
+    else:
+        plugin.logger.debug("No scrobbler configuration for user, skipping")
diff --git a/api/plugins/fw_scrobbler/scrobbler.py b/api/plugins/fw_scrobbler/scrobbler.py
index 84653ca6cc..fe365e533c 100644
--- a/api/plugins/fw_scrobbler/scrobbler.py
+++ b/api/plugins/fw_scrobbler/scrobbler.py
@@ -38,7 +38,7 @@ def handshake_v1(session, url, username, password):
     result = handshake_response.text.split("\n")
     if len(result) >= 4 and result[0] == "OK":
         session_key = result[1]
-        # nowplaying_url = result[2]
+        nowplaying_url = result[2]
         scrobble_url = result[3]
     elif result[0] == "BANNED":
         raise ScrobblerException("BANNED")
@@ -50,7 +50,7 @@ def handshake_v1(session, url, username, password):
         raise ScrobblerException(handshake_response.text)
 
     plugin.logger.debug("Handshake successful, scrobble url: %s", scrobble_url)
-    return session_key, scrobble_url
+    return session_key, nowplaying_url, scrobble_url
 
 
 def submit_scrobble_v1(session, scrobble_time, track, session_key, scrobble_url):
@@ -69,14 +69,36 @@ def submit_scrobble_v1(session, scrobble_time, track, session_key, scrobble_url)
     plugin.logger.debug("Scrobble successfull!")
 
 
-def get_scrobble_payload(track, scrobble_time):
+def submit_now_playing_v1(session, track, session_key, now_playing_url):
+    payload = get_scrobble_payload(track, date=None, suffix="")
+    plugin.logger.debug("Sending now playing with payload %s", payload)
+    payload["s"] = session_key
+    response = session.post(now_playing_url, payload)
+    response.raise_for_status()
+    if response.text.startswith("OK"):
+        return
+    elif response.text.startswith("BADSESSION"):
+        raise ScrobblerException("Remote server says the session is invalid")
+    else:
+        raise ScrobblerException(response.text)
+
+    plugin.logger.debug("Now playing successfull!")
+
+
+def get_scrobble_payload(track, date, suffix="[0]"):
+    """
+    Documentation available at https://web.archive.org/web/20190531021725/https://www.last.fm/api/submissions
+    """
     upload = track.uploads.filter(duration__gte=0).first()
-    return {
-        "a[0]": track.artist.name,
-        "t[0]": track.title,
-        "i[0]": int(scrobble_time.timestamp()),
-        "l[0]": upload.duration if upload else 0,
-        "b[0]": track.album.title or "",
-        "n[0]": track.position or "",
-        "m[0]": str(track.mbid) or "",
+    data = {
+        "a{}".format(suffix): track.artist.name,
+        "t{}".format(suffix): track.title,
+        "l{}".format(suffix): upload.duration if upload else 0,
+        "b{}".format(suffix): track.album.title or "",
+        "n{}".format(suffix): track.position or "",
+        "m{}".format(suffix): str(track.mbid) or "",
+        "o{}".format(suffix): "P",  # Source: P = chosen by user
     }
+    if date:
+        data["i{}".format(suffix)] = int(date.timestamp())
+    return data
diff --git a/front/src/components/audio/Player.vue b/front/src/components/audio/Player.vue
index 7349220eec..6daba83b98 100644
--- a/front/src/components/audio/Player.vue
+++ b/front/src/components/audio/Player.vue
@@ -395,7 +395,7 @@ export default {
         },
         onunlock: function () {
           if (self.$store.state.player.playing) {
-            self.soundId = self.sound.play(self.soundId)
+            self.soundId = sound.play(self.soundId)
           }
         },
         onload: function () {
-- 
GitLab