import sys import re import json from typing import Optional, Sequence from deezer_downloader.configuration import config from Crypto.Hash import MD5 from Crypto.Cipher import Blowfish import urllib.parse import html.parser import requests from binascii import a2b_hex, b2a_hex from mutagen.flac import FLAC, Picture from mutagen.mp3 import MP3 from mutagen.id3 import PictureType, TIT2, TALB, TPE1, TRCK, TDRC, TPOS, APIC, TPE2 from mutagen import MutagenError # BEGIN TYPES TYPE_TRACK = "track" TYPE_ALBUM = "album" TYPE_PLAYLIST = "playlist" TYPE_ARTIST = "artist" TYPE_ALBUM_TRACK = "album_track" # used for listing songs of an album TYPE_ARTIST_ALBUM = "artist_album" # used for listing albums of an artist TYPE_ARTIST_TOP = "artist_top" # used for listing top tracks of an artist # END TYPES session = None license_token = {} sound_format = "" USER_AGENT = "Mozilla/5.0 (X11; Linux i686; rv:135.0) Gecko/20100101 Firefox/135.0" def get_user_data() -> tuple[str, str]: try: user_data = session.get('https://www.deezer.com/ajax/gw-light.php?method=deezer.getUserData&input=3&api_version=1.0&api_token=') user_data_json = user_data.json()['results'] options = user_data_json['USER']['OPTIONS'] license_token = options['license_token'] web_sound_quality = options['web_sound_quality'] return license_token, web_sound_quality except (requests.exceptions.RequestException, KeyError) as e: print(f"ERROR: Could not get license token: {e}") # quality_config comes from config file # web_sound_quality is a dict coming from Deezer API and depends on ARL cookie (premium subscription) def set_song_quality(quality_config: str, web_sound_quality: dict): global sound_format flac_supported = web_sound_quality['lossless'] is True if flac_supported: if quality_config == "flac": sound_format = "FLAC" else: sound_format = "MP3_320" else: if quality_config == "flac": print("WARNING: flac quality is configured in config file but not supported (no premium subscription?). Falling back to mp3") sound_format = "MP3_128" def get_file_extension() -> str: return "flac" if sound_format == "FLAC" else "mp3" # quality is mp3 or flac def init_deezer_session(proxy_server: str, quality: str) -> None: global session, license_token, web_sound_quality header = { 'Pragma': 'no-cache', 'Origin': 'https://www.deezer.com', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'en-US,en;q=0.9', 'User-Agent': USER_AGENT, 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Accept': '*/*', 'Cache-Control': 'no-cache', 'X-Requested-With': 'XMLHttpRequest', 'Connection': 'keep-alive', 'Referer': 'https://www.deezer.com/login', 'DNT': '1', } session = requests.session() session.headers.update(header) session.cookies.update({'arl': config['deezer']['cookie_arl'], 'comeback': '1'}) if len(proxy_server.strip()) > 0: print(f"Using proxy {proxy_server}") session.proxies.update({"https": proxy_server}) license_token, web_sound_quality = get_user_data() set_song_quality(quality, web_sound_quality) class Deezer404Exception(Exception): pass class Deezer403Exception(Exception): pass class DeezerApiException(Exception): pass class ScriptExtractor(html.parser.HTMLParser): """ extract