maloja/maloja/apis/audioscrobbler_legacy.py

125 lines
3.4 KiB
Python
Raw Normal View History

2020-10-01 23:01:41 +03:00
from ._base import APIHandler
from ._exceptions import *
from .. import database
from ._apikeys import apikeystore
2020-10-01 23:01:41 +03:00
from bottle import request
2020-10-29 17:56:51 +03:00
class AudioscrobblerLegacy(APIHandler):
2020-10-01 23:01:41 +03:00
__apiname__ = "Legacy Audioscrobbler"
__doclink__ = "https://web.archive.org/web/20190531021725/https://www.last.fm/api/submissions"
__aliases__ = [
2020-10-29 18:46:45 +03:00
"audioscrobbler_legacy",
2020-10-29 19:21:50 +03:00
"audioscrobbler/1.2"
2020-10-01 23:01:41 +03:00
]
def init(self):
# no need to save these on disk, clients can always request a new session
self.mobile_sessions = {}
2020-10-01 23:01:41 +03:00
self.methods = {
"handshake":self.handshake,
"nowplaying":self.now_playing,
"scrobble":self.submit_scrobble
}
self.errors = {
2020-10-31 21:57:49 +03:00
BadAuthException:(403,"BADAUTH\n"),
InvalidAuthException:(403,"BADAUTH\n"),
InvalidMethodException:(400,"FAILED\n"),
InvalidSessionKey:(403,"BADSESSION\n"),
ScrobblingException:(500,"FAILED\n")
2020-10-01 23:01:41 +03:00
}
def get_method(self,pathnodes,keys):
2020-10-29 18:46:45 +03:00
if keys.get("hs") == 'true': return 'handshake'
2020-10-29 19:14:22 +03:00
else: return pathnodes[0]
2020-10-01 23:01:41 +03:00
def handshake(self,pathnodes,keys):
auth = keys.get("a")
timestamp = keys.get("t")
apikey = keys.get("api_key")
2020-10-02 05:35:36 +03:00
host = keys.get("Host")
Refactoring (#83) * Merge isinstance calls * Inline variable that is immediately returned * Replace set() with comprehension * Replace assignment with augmented assignment * Remove unnecessary else after guard condition * Convert for loop into list comprehension * Replace unused for index with underscore * Merge nested if conditions * Convert for loop into list comprehension * Convert for loop into set comprehension * Remove unnecessary else after guard condition * Replace if statements with if expressions * Simplify sequence comparison * Replace multiple comparisons with in operator * Merge isinstance calls * Merge nested if conditions * Add guard clause * Merge duplicate blocks in conditional * Replace unneeded comprehension with generator * Inline variable that is immediately returned * Remove unused imports * Replace unneeded comprehension with generator * Remove unused imports * Remove unused import * Inline variable that is immediately returned * Swap if/else branches and remove unnecessary else * Use str.join() instead of for loop * Multiple refactors - Remove redundant pass statement - Hoist repeated code outside conditional statement - Swap if/else to remove empty if body * Inline variable that is immediately returned * Simplify generator expression * Replace if statement with if expression * Multiple refactoring - Replace range(0, x) with range(x) - Swap if/else branches - Remove unnecessary else after guard condition * Use str.join() instead of for loop * Hoist repeated code outside conditional statement * Use str.join() instead of for loop * Inline variables that are immediately returned * Merge dictionary assignment with declaration * Use items() to directly unpack dictionary values * Extract dup code from methods into a new one
2021-10-19 15:58:24 +03:00
protocol = 'http' if (keys.get("u") == 'nossl') else request.urlparts.scheme
2020-10-29 18:46:45 +03:00
if auth is not None:
2022-04-06 23:51:14 +03:00
for client in apikeystore:
key = apikeystore[client]
if self.check_token(auth,key,timestamp):
sessionkey = self.generate_key(client)
2020-10-29 18:46:45 +03:00
return 200, (
"OK\n"
f"{sessionkey}\n"
f"{protocol}://{host}/apis/audioscrobbler_legacy/nowplaying\n"
f"{protocol}://{host}/apis/audioscrobbler_legacy/scrobble\n"
)
2020-10-01 23:01:41 +03:00
else:
raise InvalidAuthException()
else:
raise BadAuthException()
def now_playing(self,pathnodes,keys):
# I see no implementation in the other compatible APIs, so I have just
# created a route that always says it was successful except if the
# session is invalid
if keys.get("s") is None or keys.get("s") not in self.mobile_sessions:
raise InvalidSessionKey()
else:
2020-10-31 21:57:49 +03:00
return 200,"OK\n"
2020-10-01 23:01:41 +03:00
def submit_scrobble(self,pathnodes,keys):
key = keys.get("s")
if key is None or key not in self.mobile_sessions:
2020-10-01 23:01:41 +03:00
raise InvalidSessionKey()
client = self.mobile_sessions.get(key)
Refactoring (#83) * Merge isinstance calls * Inline variable that is immediately returned * Replace set() with comprehension * Replace assignment with augmented assignment * Remove unnecessary else after guard condition * Convert for loop into list comprehension * Replace unused for index with underscore * Merge nested if conditions * Convert for loop into list comprehension * Convert for loop into set comprehension * Remove unnecessary else after guard condition * Replace if statements with if expressions * Simplify sequence comparison * Replace multiple comparisons with in operator * Merge isinstance calls * Merge nested if conditions * Add guard clause * Merge duplicate blocks in conditional * Replace unneeded comprehension with generator * Inline variable that is immediately returned * Remove unused imports * Replace unneeded comprehension with generator * Remove unused imports * Remove unused import * Inline variable that is immediately returned * Swap if/else branches and remove unnecessary else * Use str.join() instead of for loop * Multiple refactors - Remove redundant pass statement - Hoist repeated code outside conditional statement - Swap if/else to remove empty if body * Inline variable that is immediately returned * Simplify generator expression * Replace if statement with if expression * Multiple refactoring - Replace range(0, x) with range(x) - Swap if/else branches - Remove unnecessary else after guard condition * Use str.join() instead of for loop * Hoist repeated code outside conditional statement * Use str.join() instead of for loop * Inline variables that are immediately returned * Merge dictionary assignment with declaration * Use items() to directly unpack dictionary values * Extract dup code from methods into a new one
2021-10-19 15:58:24 +03:00
for count in range(50):
artist_key = f"a[{count}]"
2022-05-08 16:26:42 +03:00
album_key = f"b[{count}]"
length_key = f"l[{count}]"
Refactoring (#83) * Merge isinstance calls * Inline variable that is immediately returned * Replace set() with comprehension * Replace assignment with augmented assignment * Remove unnecessary else after guard condition * Convert for loop into list comprehension * Replace unused for index with underscore * Merge nested if conditions * Convert for loop into list comprehension * Convert for loop into set comprehension * Remove unnecessary else after guard condition * Replace if statements with if expressions * Simplify sequence comparison * Replace multiple comparisons with in operator * Merge isinstance calls * Merge nested if conditions * Add guard clause * Merge duplicate blocks in conditional * Replace unneeded comprehension with generator * Inline variable that is immediately returned * Remove unused imports * Replace unneeded comprehension with generator * Remove unused imports * Remove unused import * Inline variable that is immediately returned * Swap if/else branches and remove unnecessary else * Use str.join() instead of for loop * Multiple refactors - Remove redundant pass statement - Hoist repeated code outside conditional statement - Swap if/else to remove empty if body * Inline variable that is immediately returned * Simplify generator expression * Replace if statement with if expression * Multiple refactoring - Replace range(0, x) with range(x) - Swap if/else branches - Remove unnecessary else after guard condition * Use str.join() instead of for loop * Hoist repeated code outside conditional statement * Use str.join() instead of for loop * Inline variables that are immediately returned * Merge dictionary assignment with declaration * Use items() to directly unpack dictionary values * Extract dup code from methods into a new one
2021-10-19 15:58:24 +03:00
track_key = f"t[{count}]"
time_key = f"i[{count}]"
if artist_key not in keys or track_key not in keys:
return 200,"OK\n"
artiststr,titlestr = keys[artist_key], keys[track_key]
try:
timestamp = int(keys[time_key])
2022-04-24 21:47:17 +03:00
except Exception:
Refactoring (#83) * Merge isinstance calls * Inline variable that is immediately returned * Replace set() with comprehension * Replace assignment with augmented assignment * Remove unnecessary else after guard condition * Convert for loop into list comprehension * Replace unused for index with underscore * Merge nested if conditions * Convert for loop into list comprehension * Convert for loop into set comprehension * Remove unnecessary else after guard condition * Replace if statements with if expressions * Simplify sequence comparison * Replace multiple comparisons with in operator * Merge isinstance calls * Merge nested if conditions * Add guard clause * Merge duplicate blocks in conditional * Replace unneeded comprehension with generator * Inline variable that is immediately returned * Remove unused imports * Replace unneeded comprehension with generator * Remove unused imports * Remove unused import * Inline variable that is immediately returned * Swap if/else branches and remove unnecessary else * Use str.join() instead of for loop * Multiple refactors - Remove redundant pass statement - Hoist repeated code outside conditional statement - Swap if/else to remove empty if body * Inline variable that is immediately returned * Simplify generator expression * Replace if statement with if expression * Multiple refactoring - Replace range(0, x) with range(x) - Swap if/else branches - Remove unnecessary else after guard condition * Use str.join() instead of for loop * Hoist repeated code outside conditional statement * Use str.join() instead of for loop * Inline variables that are immediately returned * Merge dictionary assignment with declaration * Use items() to directly unpack dictionary values * Extract dup code from methods into a new one
2021-10-19 15:58:24 +03:00
timestamp = None
2022-05-08 16:26:42 +03:00
scrobble = {
'track_artists':[artiststr],
'track_title':titlestr,
2022-05-08 16:26:42 +03:00
'scrobble_time':timestamp,
}
if album_key in keys:
scrobble['album_name'] = keys[album_key]
if length_key in keys:
scrobble['track_length'] = keys[length_key]
#database.createScrobble(artists,title,timestamp)
self.scrobble(scrobble, client=client)
Refactoring (#83) * Merge isinstance calls * Inline variable that is immediately returned * Replace set() with comprehension * Replace assignment with augmented assignment * Remove unnecessary else after guard condition * Convert for loop into list comprehension * Replace unused for index with underscore * Merge nested if conditions * Convert for loop into list comprehension * Convert for loop into set comprehension * Remove unnecessary else after guard condition * Replace if statements with if expressions * Simplify sequence comparison * Replace multiple comparisons with in operator * Merge isinstance calls * Merge nested if conditions * Add guard clause * Merge duplicate blocks in conditional * Replace unneeded comprehension with generator * Inline variable that is immediately returned * Remove unused imports * Replace unneeded comprehension with generator * Remove unused imports * Remove unused import * Inline variable that is immediately returned * Swap if/else branches and remove unnecessary else * Use str.join() instead of for loop * Multiple refactors - Remove redundant pass statement - Hoist repeated code outside conditional statement - Swap if/else to remove empty if body * Inline variable that is immediately returned * Simplify generator expression * Replace if statement with if expression * Multiple refactoring - Replace range(0, x) with range(x) - Swap if/else branches - Remove unnecessary else after guard condition * Use str.join() instead of for loop * Hoist repeated code outside conditional statement * Use str.join() instead of for loop * Inline variables that are immediately returned * Merge dictionary assignment with declaration * Use items() to directly unpack dictionary values * Extract dup code from methods into a new one
2021-10-19 15:58:24 +03:00
return 200,"OK\n"
2020-10-01 23:01:41 +03:00
def check_token(self, received_token, expected_key, ts):
expected_token = md5(md5(expected_key) + ts)
return received_token == expected_token
def generate_key(self,client):
key = "".join(
str(
random.choice(
list(range(10)) + list("abcdefghijklmnopqrstuvwxyz") +
list("ABCDEFGHIJKLMNOPQRSTUVWXYZ"))) for _ in range(64))
self.mobile_sessions[key] = client
return key
2020-10-01 23:01:41 +03:00
import hashlib
import random
def md5(input):
m = hashlib.md5()
m.update(bytes(input,encoding="utf-8"))
return m.hexdigest()