From efb9ba7767891a8372b4c43f0d987f734f7a832e Mon Sep 17 00:00:00 2001 From: chme Date: Sat, 28 May 2022 06:42:29 +0200 Subject: [PATCH 1/3] [spotify] Additional cleanup of functionality only used with libspotify - Remove playlist commands only used by libspotify: adding / removing playlist command was used by the callbacks from libspotify to receive incremental updates (did not work for some time) - Remove "login" web api endpoint: no login into libspotify is required any more. Spotify web api authorization follows the OAuth flow. --- src/httpd_jsonapi.c | 72 ------------------ src/library/spotify_webapi.c | 142 ----------------------------------- src/library/spotify_webapi.h | 4 - 3 files changed, 218 deletions(-) diff --git a/src/httpd_jsonapi.c b/src/httpd_jsonapi.c index 9239088d..e6770c06 100644 --- a/src/httpd_jsonapi.c +++ b/src/httpd_jsonapi.c @@ -867,9 +867,6 @@ jsonapi_reply_config(struct httpd_request *hreq) json_object_object_add(jreply, "allow_modifying_stored_playlists", json_object_new_boolean(allow_modifying_stored_playlists)); safe_json_add_string(jreply, "default_playlist_directory", default_playlist_directory); - // libspotify is sunset, so always return false. TODO: remove this parameter. - json_object_object_add(jreply, "use_libspotify", json_object_new_boolean(false)); - CHECK_ERRNO(L_WEB, evbuffer_add_printf(hreq->reply, "%s", json_object_to_json_string(jreply))); jparse_free(jreply); @@ -1318,7 +1315,6 @@ jsonapi_reply_spotify(struct httpd_request *hreq) json_object_object_add(jreply, "spotify_installed", json_object_new_boolean(sp_status.installed)); json_object_object_add(jreply, "spotify_logged_in", json_object_new_boolean(sp_status.logged_in)); json_object_object_add(jreply, "has_podcast_support", json_object_new_boolean(sp_status.has_podcast_support)); - safe_json_add_string(jreply, "libspotify_user", sp_status.username); spotifywebapi_status_info_get(&webapi_info); json_object_object_add(jreply, "webapi_token_valid", json_object_new_boolean(webapi_info.token_valid)); @@ -1342,73 +1338,6 @@ jsonapi_reply_spotify(struct httpd_request *hreq) return HTTP_OK; } -static int -jsonapi_reply_spotify_login(struct httpd_request *hreq) -{ -#ifdef SPOTIFY - struct evbuffer *in_evbuf; - json_object* request; - const char *user; - const char *password; - const char *errmsg; - json_object* jreply; - json_object* errors; - int ret; - - DPRINTF(E_DBG, L_WEB, "Received Spotify login request\n"); - - in_evbuf = evhttp_request_get_input_buffer(hreq->req); - - request = jparse_obj_from_evbuffer(in_evbuf); - if (!request) - { - DPRINTF(E_LOG, L_WEB, "Failed to parse incoming request\n"); - return HTTP_BADREQUEST; - } - - CHECK_NULL(L_WEB, jreply = json_object_new_object()); - - user = jparse_str_from_obj(request, "user"); - password = jparse_str_from_obj(request, "password"); - if (user && strlen(user) > 0 && password && strlen(password) > 0) - { - ret = spotify_login(user, password, &errmsg); - if (ret < 0) - { - json_object_object_add(jreply, "success", json_object_new_boolean(false)); - errors = json_object_new_object(); - json_object_object_add(errors, "error", json_object_new_string(errmsg)); - json_object_object_add(jreply, "errors", errors); - } - else - { - json_object_object_add(jreply, "success", json_object_new_boolean(true)); - } - } - else - { - DPRINTF(E_LOG, L_WEB, "No user or password in spotify login post request\n"); - - json_object_object_add(jreply, "success", json_object_new_boolean(false)); - errors = json_object_new_object(); - if (!user || strlen(user) == 0) - json_object_object_add(errors, "user", json_object_new_string("Username is required")); - if (!password || strlen(password) == 0) - json_object_object_add(errors, "password", json_object_new_string("Password is required")); - json_object_object_add(jreply, "errors", errors); - } - - CHECK_ERRNO(L_WEB, evbuffer_add_printf(hreq->reply, "%s", json_object_to_json_string(jreply))); - - jparse_free(jreply); - -#else - DPRINTF(E_LOG, L_WEB, "Received spotify login request but was not compiled with enable-spotify\n"); -#endif - - return HTTP_OK; -} - static int jsonapi_reply_spotify_logout(struct httpd_request *hreq) { @@ -4716,7 +4645,6 @@ static struct httpd_uri_map adm_handlers[] = { EVHTTP_REQ_GET | EVHTTP_REQ_PUT, "^/api/update$", jsonapi_reply_update }, { EVHTTP_REQ_PUT, "^/api/rescan$", jsonapi_reply_meta_rescan }, - { EVHTTP_REQ_POST, "^/api/spotify-login$", jsonapi_reply_spotify_login }, { EVHTTP_REQ_GET, "^/api/spotify-logout$", jsonapi_reply_spotify_logout }, { EVHTTP_REQ_GET, "^/api/spotify$", jsonapi_reply_spotify }, { EVHTTP_REQ_GET, "^/api/pairing$", jsonapi_reply_pairing_get }, diff --git a/src/library/spotify_webapi.c b/src/library/spotify_webapi.c index 0ac89ab4..f654f4fa 100644 --- a/src/library/spotify_webapi.c +++ b/src/library/spotify_webapi.c @@ -153,7 +153,6 @@ static const char *spotify_scope = "playlist-read-private playlist-read- static const char *spotify_auth_uri = "https://accounts.spotify.com/authorize"; static const char *spotify_token_uri = "https://accounts.spotify.com/api/token"; -static const char *spotify_playlist_uri = "https://api.spotify.com/v1/playlists/%s"; static const char *spotify_track_uri = "https://api.spotify.com/v1/tracks/%s"; static const char *spotify_me_uri = "https://api.spotify.com/v1/me"; static const char *spotify_albums_uri = "https://api.spotify.com/v1/me/albums?limit=50"; @@ -893,27 +892,6 @@ get_id_from_uri(const char *uri, char **id) return 0; } -static char * -get_playlist_endpoint_uri(const char *uri) -{ - char *endpoint_uri = NULL; - char *id = NULL; - int ret; - - ret = get_id_from_uri(uri, &id); - if (ret < 0) - { - DPRINTF(E_LOG, L_SPOTIFY, "Error extracting owner and id from playlist uri '%s'\n", uri); - goto out; - } - - endpoint_uri = safe_asprintf(spotify_playlist_uri, id); - - out: - free(id); - return endpoint_uri; -} - static char * get_playlist_tracks_endpoint_uri(const char *uri) { @@ -1488,42 +1466,6 @@ prepare_directories(const char *artist, const char *album) return dir_id; } -/* - * Purges all Spotify files from the library that are not in a playlist - * (Note: all files from saved albums are in the spotify:savedtracks playlist) - */ -static int -cleanup_spotify_files(void) -{ - struct query_params qp; - char *path; - int ret; - - memset(&qp, 0, sizeof(struct query_params)); - - qp.type = Q_BROWSE_PATH; - qp.sort = S_NONE; - qp.filter = "f.path LIKE 'spotify:%%' AND NOT f.path IN (SELECT filepath FROM playlistitems)"; - - ret = db_query_start(&qp); - if (ret < 0) - { - db_query_end(&qp); - return -1; - } - - while (((ret = db_query_fetch_string(&path, &qp)) == 0) && (path)) - { - cache_artwork_delete_by_path(path); - } - - db_query_end(&qp); - - db_spotify_files_delete(); - - return 0; -} - static void map_track_to_mfi(struct media_file_info *mfi, const struct spotify_track *track, const struct spotify_album *album, const char *pl_name) { @@ -2125,66 +2067,6 @@ webapi_purge(void *arg, int *ret) return COMMAND_END; } -/* Thread: library */ -static enum command_state -webapi_pl_save(void *arg, int *ret) -{ - const char *uri; - char *endpoint_uri; - json_object *response; - - uri = arg; - endpoint_uri = get_playlist_endpoint_uri(uri); - - response = request_endpoint_with_token_refresh(endpoint_uri); - if (!response) - { - *ret = -1; - goto out; - } - - *ret = saved_playlist_add(response, 0, 1, SPOTIFY_REQUEST_TYPE_DEFAULT, NULL); - - jparse_free(response); - - out: - free(endpoint_uri); - - return COMMAND_END; -} - -/* Thread: library */ -static enum command_state -webapi_pl_remove(void *arg, int *ret) -{ - const char *uri; - struct playlist_info *pli; - int plid; - - uri = arg; - pli = db_pl_fetch_bypath(uri); - - if (!pli) - { - DPRINTF(E_LOG, L_SPOTIFY, "Playlist '%s' not found, can't delete\n", uri); - - *ret = -1; - return COMMAND_END; - } - - DPRINTF(E_LOG, L_SPOTIFY, "Removing playlist '%s' (%s)\n", pli->title, uri); - - plid = pli->id; - - free_pli(pli, 0); - - db_spotify_pl_delete(plid); - cleanup_spotify_files(); - *ret = 0; - - return COMMAND_END; -} - void spotifywebapi_fullrescan(void) { @@ -2203,30 +2085,6 @@ spotifywebapi_purge(void) library_exec_async(webapi_purge, NULL); } -void -spotifywebapi_pl_save(const char *uri) -{ - if (scanning || !token_valid()) - { - DPRINTF(E_DBG, L_SPOTIFY, "Scanning spotify saved tracks still in progress, ignoring update trigger for single playlist '%s'\n", uri); - return; - } - - library_exec_async(webapi_pl_save, strdup(uri)); -} - -void -spotifywebapi_pl_remove(const char *uri) -{ - if (scanning || !token_valid()) - { - DPRINTF(E_DBG, L_SPOTIFY, "Scanning spotify saved tracks still in progress, ignoring remove trigger for single playlist '%s'\n", uri); - return; - } - - library_exec_async(webapi_pl_remove, strdup(uri)); -} - char * spotifywebapi_artwork_url_get(const char *uri, int max_w, int max_h) { diff --git a/src/library/spotify_webapi.h b/src/library/spotify_webapi.h index f8736771..f57df142 100644 --- a/src/library/spotify_webapi.h +++ b/src/library/spotify_webapi.h @@ -53,10 +53,6 @@ void spotifywebapi_rescan(void); void spotifywebapi_purge(void); -void -spotifywebapi_pl_save(const char *uri); -void -spotifywebapi_pl_remove(const char *uri); char * spotifywebapi_artwork_url_get(const char *uri, int max_w, int max_h); From 9340443a3b10997b1b9c63de9b04fd8a1ef6c231 Mon Sep 17 00:00:00 2001 From: chme Date: Sat, 28 May 2022 06:44:03 +0200 Subject: [PATCH 2/3] [spotify] Remove "Spotify saved" playlist This special playlist was previously required to keep track of saved albums tracks to avoid purging them after a rescan, since then the rescan logic was changed to use the Spotify web api and this playlist has no use anymore. --- src/library/spotify_webapi.c | 41 ++---------------------------------- 1 file changed, 2 insertions(+), 39 deletions(-) diff --git a/src/library/spotify_webapi.c b/src/library/spotify_webapi.c index f654f4fa..685a4e84 100644 --- a/src/library/spotify_webapi.c +++ b/src/library/spotify_webapi.c @@ -138,8 +138,6 @@ static pthread_mutex_t token_lck; // The base playlist id for all Spotify playlists in the db static int spotify_base_plid; -// The base playlist id for Spotify saved tracks in the db -static int spotify_saved_plid; // Flag to avoid triggering playlist change events while the (re)scan is running static bool scanning; @@ -1602,7 +1600,6 @@ saved_album_add(json_object *item, int index, int total, enum spotify_request_ty int track_count; int dir_id; int i; - int ret; if (!json_object_object_get_ex(item, "album", &jsonalbum)) { @@ -1641,10 +1638,7 @@ saved_album_add(json_object *item, int index, int total, enum spotify_request_ty parse_metadata_track(jsontrack, &track, 0); track.mtime = album.mtime; - ret = track_add(&track, &album, NULL, dir_id, request_type); - - if (ret == 0 && spotify_saved_plid) - db_pl_add_item_bypath(spotify_saved_plid, track.uri); + track_add(&track, &album, NULL, dir_id, request_type); } db_transaction_end(); @@ -1679,7 +1673,6 @@ saved_episodes_add(json_object *item, int index, int total, enum spotify_request struct spotify_album *show = arg; struct spotify_track episode; int dir_id; - int ret; DPRINTF(E_DBG, L_SPOTIFY, "saved_episodes_add: %s\n", json_object_to_json_string(item)); @@ -1689,10 +1682,7 @@ saved_episodes_add(json_object *item, int index, int total, enum spotify_request // Get or create the directory structure for this album dir_id = prepare_directories(show->artist, show->name); - ret = track_add(&episode, show, NULL, dir_id, request_type); - - if (ret == 0 && spotify_saved_plid) - db_pl_add_item_bypath(spotify_saved_plid, episode.uri); + track_add(&episode, show, NULL, dir_id, request_type); return 0; } @@ -1881,30 +1871,6 @@ scan_playlists(enum spotify_request_type request_type) return ret; } -static void -create_saved_tracks_playlist(void) -{ - struct playlist_info pli = - { - .path = strdup("spotify:savedtracks"), - .title = strdup("Spotify Saved"), - .virtual_path = strdup("/spotify:/Spotify Saved"), - .type = PL_PLAIN, - .parent_id = spotify_base_plid, - .directory_id = DIR_SPOTIFY, - .scan_kind = SCAN_KIND_SPOTIFY, - }; - - spotify_saved_plid = playlist_add_or_update(&pli); - if (spotify_saved_plid < 0) - { - DPRINTF(E_LOG, L_SPOTIFY, "Error adding playlist for saved tracks\n"); - spotify_saved_plid = 0; - } - - free_pli(&pli, 1); -} - /* * Add or update playlist folder for all spotify playlists (if enabled in config) */ @@ -1956,7 +1922,6 @@ scan(enum spotify_request_type request_type) db_directory_enable_bypath("/spotify:"); create_base_playlist(); - create_saved_tracks_playlist(); scan_saved_albums(request_type); scan_playlists(request_type); spotify_status_get(&sp_status); @@ -1988,8 +1953,6 @@ initscan(void) return 0; } - spotify_saved_plid = 0; - /* * Check that the playback Spotify backend can log in, so we don't add tracks * to the library that can't be played. From 524898538d726d31212e028c88188dbfbd67b75b Mon Sep 17 00:00:00 2001 From: chme Date: Fri, 3 Jun 2022 07:21:26 +0200 Subject: [PATCH 3/3] [web] Remove libspotify integration from web interface --- web-src/src/pages/SettingsPageArtwork.vue | 2 +- .../src/pages/SettingsPageOnlineServices.vue | 78 ------------------- 2 files changed, 1 insertion(+), 79 deletions(-) diff --git a/web-src/src/pages/SettingsPageArtwork.vue b/web-src/src/pages/SettingsPageArtwork.vue index 8d716978..b7474a47 100644 --- a/web-src/src/pages/SettingsPageArtwork.vue +++ b/web-src/src/pages/SettingsPageArtwork.vue @@ -15,7 +15,7 @@ v-text="$t('page.settings.artwork.explanation-2')" /> diff --git a/web-src/src/pages/SettingsPageOnlineServices.vue b/web-src/src/pages/SettingsPageOnlineServices.vue index c08b71e8..da75696b 100644 --- a/web-src/src/pages/SettingsPageOnlineServices.vue +++ b/web-src/src/pages/SettingsPageOnlineServices.vue @@ -20,59 +20,6 @@ v-text="$t('page.settings.services.spotify.help')" /> -
-

- - -

-

- - -

-
-
-
- -

-

-
- -

-

-
-
-
-
-

-

-

-

{ - this.libspotify.user = '' - this.libspotify.password = '' - this.libspotify.errors.user = '' - this.libspotify.errors.password = '' - this.libspotify.errors.error = '' - - if (!response.data.success) { - this.libspotify.errors.user = response.data.errors.user - this.libspotify.errors.password = response.data.errors.password - this.libspotify.errors.error = response.data.errors.error - } - }) - }, - logout_spotify() { webapi.spotify_logout() },