mirror of
https://github.com/glomatico/votify.git
synced 2026-10-01 05:22:30 +02:00
Refactor TOTP and Spotify API auth flow
This commit is contained in:
@@ -53,10 +53,10 @@ class SpotifyApi:
|
||||
def __init__(
|
||||
self,
|
||||
sp_dc: str | None = None,
|
||||
use_totp: bool = False,
|
||||
use_device_flow: bool = False,
|
||||
) -> None:
|
||||
self.sp_dc = sp_dc
|
||||
self.use_totp = use_totp
|
||||
self.use_device_flow = use_device_flow
|
||||
self._set_session()
|
||||
|
||||
@classmethod
|
||||
@@ -144,10 +144,10 @@ class SpotifyApi:
|
||||
)
|
||||
|
||||
def _setup_authorization(self) -> None:
|
||||
if self.use_totp:
|
||||
self._setup_authorization_with_totp()
|
||||
else:
|
||||
if self.use_device_flow:
|
||||
self._setup_authorization_with_device_flow()
|
||||
else:
|
||||
self._setup_authorization_with_totp()
|
||||
|
||||
def _setup_authorization_with_device_flow(self) -> None:
|
||||
token_data = self._get_token_via_device_flow()
|
||||
|
||||
+29
-7
@@ -1,18 +1,40 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import hmac
|
||||
import math
|
||||
import requests
|
||||
|
||||
|
||||
# thanks to https://github.com/glomatico/votify/pull/42#issuecomment-2727036757
|
||||
class TOTP:
|
||||
SPOTIFY_SECRETS_JSON = "https://raw.githubusercontent.com/Thereallo1026/spotify-secrets/refs/heads/main/secrets/secretDict.json"
|
||||
PERIOD = 30
|
||||
DIGITS = 6
|
||||
|
||||
def __init__(self) -> None:
|
||||
# dumped directly from the object, after all decryptions
|
||||
self.secret = b"120887534115119493370126558380647147717911891615550"
|
||||
self.version = 25
|
||||
self.period = 30
|
||||
self.digits = 6
|
||||
self._setup()
|
||||
|
||||
def _setup(self) -> None:
|
||||
version, secret_cipher_bytes = self.get_latest_secret()
|
||||
self.version = version
|
||||
self.secret = self.derive_secret_number(secret_cipher_bytes).encode()
|
||||
|
||||
def derive_secret_number(self, secret_cipher_bytes: list[int]) -> str:
|
||||
transformed = [
|
||||
byte ^ ((i % 33) + 9) for i, byte in enumerate(secret_cipher_bytes)
|
||||
]
|
||||
return "".join(str(n) for n in transformed)
|
||||
|
||||
def get_latest_secret(self) -> tuple[int, list[int]]:
|
||||
response = requests.get(self.SPOTIFY_SECRETS_JSON)
|
||||
response.raise_for_status()
|
||||
secrets = response.json()
|
||||
latest_version = max(int(v) for v in secrets.keys())
|
||||
return latest_version, secrets[str(latest_version)]
|
||||
|
||||
def generate(self, timestamp: int) -> str:
|
||||
counter = math.floor(timestamp / 1000 / self.period)
|
||||
counter = math.floor(timestamp / 1000 / self.PERIOD)
|
||||
counter_bytes = counter.to_bytes(8, byteorder="big")
|
||||
|
||||
h = hmac.new(self.secret, counter_bytes, hashlib.sha1)
|
||||
@@ -26,4 +48,4 @@ class TOTP:
|
||||
| (hmac_result[offset + 3] & 0xFF)
|
||||
)
|
||||
|
||||
return str(binary % (10**self.digits)).zfill(self.digits)
|
||||
return str(binary % (10**self.DIGITS)).zfill(self.DIGITS)
|
||||
|
||||
Reference in New Issue
Block a user