|
| 1 | +import requests |
| 2 | +from typing import Any |
| 3 | +from hashlib import md5 |
| 4 | +from urllib.parse import quote_plus |
| 5 | + |
| 6 | +from app.config import UserConfig |
| 7 | +from app.models.track import Track |
| 8 | +from app.utils.auth import get_current_userid |
| 9 | +from app.utils.threading import background |
| 10 | +from app.plugins import Plugin, plugin_method |
| 11 | + |
| 12 | + |
| 13 | +class LastFmPlugin(Plugin): |
| 14 | + def __init__(self): |
| 15 | + self.config = UserConfig() |
| 16 | + super().__init__("lastfm", "Last.fm scrobbler") |
| 17 | + self.set_active( |
| 18 | + bool( |
| 19 | + self.config.lastfmApiKey |
| 20 | + and self.config.lastfmApiSecret |
| 21 | + and self.config.lastfmSessionKeys.get(str(get_current_userid())) |
| 22 | + ) |
| 23 | + ) |
| 24 | + |
| 25 | + def get_api_signature(self, data: dict[str, Any]) -> str: |
| 26 | + params = {k: v for k, v in data.items()} |
| 27 | + |
| 28 | + signature = "".join(f"{k}{v}" for k, v in sorted(params.items())) |
| 29 | + signature += self.config.lastfmApiSecret |
| 30 | + |
| 31 | + return md5(signature.encode("utf-8")).hexdigest() |
| 32 | + |
| 33 | + def post(self, data: dict[str, Any], useSessionKey: bool = True): |
| 34 | + url = "http://ws.audioscrobbler.com/2.0/?format=json" |
| 35 | + data["api_key"] = self.config.lastfmApiKey |
| 36 | + if useSessionKey: |
| 37 | + data["sk"] = self.config.lastfmSessionKeys.get(str(get_current_userid())) |
| 38 | + |
| 39 | + data["api_sig"] = self.get_api_signature(data) |
| 40 | + |
| 41 | + final_url = ( |
| 42 | + url + "&" + "&".join(f"{k}={quote_plus(str(v))}" for k, v in data.items()) |
| 43 | + ) |
| 44 | + |
| 45 | + return requests.post(final_url) |
| 46 | + |
| 47 | + def get_session_key(self, token: str): |
| 48 | + data = { |
| 49 | + "method": "auth.getSession", |
| 50 | + "token": token, |
| 51 | + } |
| 52 | + |
| 53 | + try: |
| 54 | + res = self.post(data, useSessionKey=False) |
| 55 | + return res.json()["session"]["key"] |
| 56 | + except Exception as e: |
| 57 | + print("get_session_key error", e) |
| 58 | + return None |
| 59 | + |
| 60 | + @plugin_method |
| 61 | + @background |
| 62 | + def scrobble(self, track: Track, timestamp: int): |
| 63 | + print("Last.fm: logging track: ", track.title, "-", track.artists[0]["name"]) |
| 64 | + data = { |
| 65 | + "method": "track.scrobble", |
| 66 | + "artist": track.artists[0]["name"], |
| 67 | + "track": track.title, |
| 68 | + "timestamp": timestamp, |
| 69 | + "album": track.album, |
| 70 | + "albumArtist": track.albumartists[0]["name"], |
| 71 | + } |
| 72 | + |
| 73 | + try: |
| 74 | + self.post(data) |
| 75 | + except Exception as e: |
| 76 | + print("scrobble error", e) |
0 commit comments