Last active
August 28, 2021 00:53
-
-
Save elegos/2eb0a569d1fc5411b4661e38f89ab3fd to your computer and use it in GitHub Desktop.
Spotify Linux mpris:artUrl patcher
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# Spotify Linux mpris:artUrl patcher | |
# by Giacomo Furlan | |
# spotify-mpris-art-fix.py | |
import argparse | |
import os | |
import re | |
import shutil | |
import sys | |
from typing import List, Optional | |
defaultBasePath='/usr/share/spotify-client/spotify' | |
parser = argparse.ArgumentParser(usage=''' | |
\tSpotify MPRIS artUrl patcher. | |
\tReplaces "https://open.spotify.com/image/%%s" with "https://i.scdn.co/image/%%s". | |
\tExecute as administrator if needed. | |
''') | |
parser.add_argument('--bin-file', help=f'Path to the Spotify binary file (default: {defaultBasePath})', default=defaultBasePath) | |
parser.add_argument('--restore', action='store_true', help='Restore the last backup (and exit)') | |
parser.add_argument('--patch', action='store_true', help='Patch the mpris:artUrl base URL') | |
parser.add_argument('--no-backup', action='store_true', help='Do not make a backup of the binary (implicit --patch)') | |
def lastBackupFile(args: argparse.Namespace) -> Optional[str]: | |
baseDir = os.path.dirname(args.bin_file) | |
files = os.listdir(baseDir) | |
backupRe = re.compile(r'spotify\.bak(\.\d{1,})?$') | |
backupFiles = ['{}{}{}'.format(baseDir, os.path.sep, file) for file in files if backupRe.match(file)] | |
backupFiles.sort(reverse=True) | |
return backupFiles[0] if len(backupFiles) > 0 else None | |
def restore(args: argparse.Namespace): | |
restoreFile = lastBackupFile(args) | |
if restoreFile is None: | |
print('No backup file found, will not restore') | |
return | |
print(f'Restoring backup file {restoreFile}') | |
shutil.copyfile(restoreFile, args.bin_file) | |
os.remove(restoreFile) | |
def backup(args: argparse.Namespace): | |
baseBackupName = '{}{}spotify.bak'.format(os.path.dirname(args.bin_file), os.path.sep) | |
lastBackup = lastBackupFile(args) | |
backupName = baseBackupName | |
backupNum = 0 | |
if lastBackup is not None: | |
match = re.search(r'\.(\d+)$', lastBackup) | |
if match is not None: | |
backupNum = int(match[1]) | |
backupName += f'.{backupNum + 1}' | |
shutil.copyfile(args.bin_file, backupName) | |
def patch(args: argparse.Namespace): | |
buffer: Optional[bytes] = None | |
with open(args.bin_file, 'rb') as fh: | |
buffer = fh.read() | |
if buffer is None: | |
print("Can't read spotify binary") | |
sys.exit(0) | |
oldStr = b'https://open.spotify.com/image/%s' | |
newStr = b'https://i.scdn.co/image/%s' | |
newStr += (b'\x00' * (len(oldStr) - len(newStr))) | |
buffer = buffer.replace(oldStr, newStr) | |
with open(args.bin_file, 'wb') as fh: | |
fh.write(buffer) | |
args = parser.parse_args() | |
if args.restore: | |
restore(args) | |
sys.exit(0) | |
if args.patch or args.no_backup: | |
if not args.no_backup: | |
backup(args) | |
patch(args) | |
sys.exit(0) | |
parser.print_help() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment