[spotify] Fix for "Premium account required" (issue #1474)

Sadly user-agent spoofing seems to be necessary after Spotify sunset of
libspotify. Apparently librespot is whitelisted.
This commit is contained in:
ejurgensen 2022-05-16 23:28:18 +02:00
parent 96b678925a
commit 79fb65fbd8
4 changed files with 16 additions and 12 deletions

View File

@ -1,3 +1,6 @@
Limited C version of librespot. No Spotify Connect support. Library only. Used
by [OwnTone](https://github.com/owntone/owntone-server).
Build: Build:
- autoreconf -i && ./configure && make - autoreconf -i && ./configure && make

View File

@ -1033,6 +1033,9 @@ msg_make_client_response_encrypted(uint8_t *out, size_t out_len, struct sp_sessi
ClientResponseEncrypted client_response = CLIENT_RESPONSE_ENCRYPTED__INIT; ClientResponseEncrypted client_response = CLIENT_RESPONSE_ENCRYPTED__INIT;
LoginCredentials login_credentials = LOGIN_CREDENTIALS__INIT; LoginCredentials login_credentials = LOGIN_CREDENTIALS__INIT;
SystemInfo system_info = SYSTEM_INFO__INIT; SystemInfo system_info = SYSTEM_INFO__INIT;
const char *client_name;
const char *client_version;
const char *client_build_id;
char system_information_string[64]; char system_information_string[64];
char version_string[64]; char version_string[64];
ssize_t len; ssize_t len;
@ -1061,18 +1064,21 @@ msg_make_client_response_encrypted(uint8_t *out, size_t out_len, struct sp_sessi
else else
return -1; return -1;
// Note that Spotify seems to have whitelisting of client_name
client_name = (sp_sysinfo.client_name[0] != '\0') ? sp_sysinfo.client_name : "librespot";
client_version = (sp_sysinfo.client_version[0] != '\0') ? sp_sysinfo.client_version : "000000";
client_build_id = (sp_sysinfo.client_build_id[0] != '\0') ? sp_sysinfo.client_build_id : "0";
snprintf(system_information_string, sizeof(system_information_string), "%s_%s_%s", client_name, client_version, client_build_id);
snprintf(version_string, sizeof(version_string), "%s-%s", client_name, client_version);
system_info.cpu_family = CPU_FAMILY__CPU_UNKNOWN; system_info.cpu_family = CPU_FAMILY__CPU_UNKNOWN;
system_info.os = OS__OS_UNKNOWN; system_info.os = OS__OS_UNKNOWN;
snprintf(system_information_string, sizeof(system_information_string), "%s_%s_%s",
sp_sysinfo.client_name, sp_sysinfo.client_version, sp_sysinfo.client_build_id);
system_info.system_information_string = system_information_string; system_info.system_information_string = system_information_string;
system_info.device_id = sp_sysinfo.device_id; system_info.device_id = sp_sysinfo.device_id;
system_info_from_uname(&system_info); // Sets cpu_family and os to actual values
system_info_from_uname(&system_info);
client_response.login_credentials = &login_credentials; client_response.login_credentials = &login_credentials;
client_response.system_info = &system_info; client_response.system_info = &system_info;
snprintf(version_string, sizeof(version_string), "%s-%s", sp_sysinfo.client_name, sp_sysinfo.client_version);
client_response.version_string = version_string; client_response.version_string = version_string;
len = client_response_encrypted__get_packed_size(&client_response); len = client_response_encrypted__get_packed_size(&client_response);

View File

@ -258,9 +258,7 @@ main(int argc, char * argv[])
goto error; goto error;
} }
snprintf(sysinfo.client_name, sizeof(sysinfo.client_name), "myclient"); memset(&sysinfo, 0, sizeof(struct sp_sysinfo));
snprintf(sysinfo.client_version, sizeof(sysinfo.client_version), "0.1");
snprintf(sysinfo.client_build_id, sizeof(sysinfo.client_build_id), "a");
snprintf(sysinfo.device_id, sizeof(sysinfo.device_id), "aabbccddeeff"); snprintf(sysinfo.device_id, sizeof(sysinfo.device_id), "aabbccddeeff");
ret = librespotc_init(&sysinfo, &callbacks); ret = librespotc_init(&sysinfo, &callbacks);

View File

@ -304,7 +304,7 @@ struct sp_callbacks callbacks = {
static int static int
initialize(struct global_ctx *ctx) initialize(struct global_ctx *ctx)
{ {
struct sp_sysinfo sysinfo; struct sp_sysinfo sysinfo = { 0 };
cfg_t *spotify_cfg; cfg_t *spotify_cfg;
int ret; int ret;
@ -316,9 +316,6 @@ initialize(struct global_ctx *ctx)
if (ctx->is_initialized) if (ctx->is_initialized)
return 0; return 0;
snprintf(sysinfo.client_name, sizeof(sysinfo.client_name), PACKAGE_NAME);
snprintf(sysinfo.client_version, sizeof(sysinfo.client_version), PACKAGE_VERSION);
snprintf(sysinfo.client_build_id, sizeof(sysinfo.client_build_id), "0");
snprintf(sysinfo.device_id, sizeof(sysinfo.device_id), "%" PRIx64, libhash); // TODO use a UUID instead snprintf(sysinfo.device_id, sizeof(sysinfo.device_id), "%" PRIx64, libhash); // TODO use a UUID instead
ret = librespotc_init(&sysinfo, &callbacks); ret = librespotc_init(&sysinfo, &callbacks);