viperinius / jellyfin-plugin-spotify-import Goto Github PK
View Code? Open in Web Editor NEWImport playlists from Spotify in Jellyfin
License: GNU General Public License v3.0
Import playlists from Spotify in Jellyfin
License: GNU General Public License v3.0
I used the plugin successfully for a few months, but suddenly it just stopped working. And since then the songs are no longer matched.
Log excerpt:
Viperinius.Plugin.SpotifyImport.PlaylistSync: Now processing provider track "Another Love" ["Another Love"]["OsTEKKe"]["OsTEKKe"]
[2024-03-16 19:05:59.868 +00:00] [DBG] [21] Viperinius.Plugin.SpotifyImport.PlaylistSync: > Found matching artist "OsTEKKe"
[2024-03-16 19:05:59.869 +00:00] [INF] [21] Viperinius.Plugin.SpotifyImport.PlaylistSync: > Reached end of album list
[2024-03-16 19:05:59.869 +00:00] [INF] [21] Viperinius.Plugin.SpotifyImport.PlaylistSync: > Reached end of artist list
[2024-03-16 19:05:59.869 +00:00] [INF] [21] Viperinius.Plugin.SpotifyImport.PlaylistSync: AlbumName, Artists did not match for track "Another Love" ["Another Love"]["OsTEKKe"]
[2024-03-16 19:05:59.869 +00:00] [INF] [21]
Plugin Version: 1.7
First up, great work on making this plugin. Install and setup was a breeze. Managed to get it working somewhat but am finding some songs not being picked up (correctly) by the plugin no matter what combination of the matching criteria I set. I'm thinking instead of selecting the matching criteria in a "all or nothing" fashion, perhaps it will work better if it can be prioritised/sequenced? i.e. first search by track name, if multiple are found, then narrow by artist, if there are still multiples, then use album, etc. this can be user defined by setting the order of the criteria in the list?
I haven't triaged this all to much..
but it seems that the plugin creates folders under config/data/
with the names playlist[1]*
the contents of each of the folders is:
all files in all folders have different hash values.
Version 1.4.0.0
Logs:
[INF] [15] Emby.Server.Implementations.ScheduledTasks.TaskManager: Executing "Import Spotify playlists"
[INF] [81] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyPlaylistProvider: Starting to query N playlists from "Spotify"
[WRN] [67] Emby.Server.Implementations.Playlists.PlaylistManager: Ignored adding 1 duplicate items to playlist "playlists1".
Whenever I run the plugin with fuzzy matching enabled, it seems to error out and complain about being unable to find the Fastenshtein
library.
I've tried to put the net80 dll from the 1.0.0.8 version of the library's package into the plugin directory, but this didn't seem to work. Other matching types seem to work.
Server OS: Debian 12
Jellyfin version: 10.9.6
Plugin version: 1.8.1.0
[2024-06-21 01:33:37.231 +01:00] [INF] Removing item, Type: "Playlist", Name: "genshin and also not genshin", Path: "/var/lib/jellyfin/data/playlists/genshin and also not genshin", Id: 35e32465-be50-700c-58b0-abc42a2b97f0
[2024-06-21 01:33:37.231 +01:00] [INF] Deleting item path, Type: "Playlist", Name: "genshin and also not genshin", Path: "/var/lib/jellyfin/data/playlists/genshin and also not genshin", Id: 35e32465-be50-700c-58b0-abc42a2b97f0
[2024-06-21 01:33:37.345 +01:00] [ERR] Error executing Scheduled Task
System.IO.FileNotFoundException: Could not load file or assembly 'Fastenshtein, Version=1.0.0.8, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
File name: 'Fastenshtein, Version=1.0.0.8, Culture=neutral, PublicKeyToken=null'
at Viperinius.Plugin.SpotifyImport.Matchers.FuzzyMatcher.Matches(String target, String item)
at Viperinius.Plugin.SpotifyImport.Matchers.TrackComparison.Equal(String jellyfinName, String providerName, ItemMatchLevel matchLevel)
at Viperinius.Plugin.SpotifyImport.Matchers.TrackComparison.AlbumNameEqual(MusicAlbum jfItem, ProviderTrackInfo providerItem, ItemMatchLevel matchLevel)
at Viperinius.Plugin.SpotifyImport.PlaylistSync.GetAlbum(MusicArtist artist, ProviderTrackInfo providerTrackInfo, Int32& nextAlbumIndex)
at Viperinius.Plugin.SpotifyImport.PlaylistSync.GetMatchingTrack(ProviderTrackInfo providerTrackInfo, ItemMatchCriteria& failedMatchCriterium)
at Viperinius.Plugin.SpotifyImport.PlaylistSync.FindTracksAndAddToPlaylist(Playlist playlist, List`1 providerTrackInfos, User user, CancellationToken cancellationToken)
at Viperinius.Plugin.SpotifyImport.PlaylistSync.Execute(CancellationToken cancellationToken)
at Viperinius.Plugin.SpotifyImport.Tasks.SpotifyImportTask.ExecuteAsync(IProgress`1 progress, CancellationToken cancellationToken)
at Emby.Server.Implementations.ScheduledTasks.ScheduledTaskWorker.ExecuteInternal(TaskOptions options)
[2024-06-21 01:33:37.346 +01:00] [INF] "Import Spotify playlists" Failed after 0 minute(s) and 2 seconds
the current regex in
https://github.com/Viperinius/jellyfin-plugin-spotify-import/blob/master/Viperinius.Plugin.SpotifyImport/Configuration/playlistConfig.js#L296
does not allow special characters in the username (mine has underscores).
This results in the username not being sent to the server and stored with the configuration. After "Save" and page reload the rows remain empty.
I checked the spotify registration, seems like they don't limit the username in any way.
I think the better approach might be to check for the 3 currently allowed username formats and just match the parts we know and strip them instead of a regex?
if string contains spotify.com/user -> strip everything until "...spotify.com/user/", remaining part is the username
if string contains spotify:user: -> strip that, remaining part is the username
else: its just the username.
This would circumvent the whole "valid URL" regex mess and fiddling the username out of the URL.
Description
When trying to configure the plugins Spotify Client ID field, an error 500 is reported in the console (onClick of the Authorize button in the configuration panel) while following the instructions in the readme. My Spotify dashboard is as follow:
On the logs side:
[2024-05-19 14:03:50.115 +02:00] [ERR] [35] Jellyfin.Api.Middleware.ExceptionMiddleware: Error processing request. URL "POST" "/Viperinius.Plugin.SpotifyImport/SpotifyAuth".
System.InvalidOperationException: The AuthorizationPolicy named: 'DefaultAuthorization' was not found.
at Microsoft.AspNetCore.Authorization.AuthorizationPolicy.CombineAsync(IAuthorizationPolicyProvider policyProvider, IEnumerable`1 authorizeData, IEnumerable`1 policies)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Jellyfin.Api.Middleware.QueryStringDecodingMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.ReDoc.ReDocMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Jellyfin.Api.Middleware.RobotsRedirectionMiddleware.Invoke(HttpContext httpContext)
at Jellyfin.Api.Middleware.LegacyEmbyRouteRewriteMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.ResponseCompression.ResponseCompressionMiddleware.InvokeCore(HttpContext context)
at Jellyfin.Api.Middleware.ResponseTimeMiddleware.Invoke(HttpContext context, IServerConfigurationManager serverConfigurationManager)
at Jellyfin.Api.Middleware.ExceptionMiddleware.Invoke(HttpContext context)
Hi, I use this almost every day, but I also reboot my server regularly, so I have to keep re-scanning to generate the file again.
Thanks for this plugin! Sorry if I'm not providing this issue correctly, first issue I've ever done on here. When I'm trying to do a manual import it fails with the following error:
[2023-05-05 22:01:42.902 -04:00] [INF] [49] Emby.Server.Implementations.ScheduledTasks.TaskManager: Executing "Import Spotify playlists"
[2023-05-05 22:01:42.931 -04:00] [INF] [49] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyPlaylistProvider: Starting to query 45 playlists from "Spotify"
[2023-05-05 22:01:42.934 -04:00] [INF] [49] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/5RaVopYCKGV35v9CtPTZku ["additional_types=track,episode"] null
[2023-05-05 22:01:43.804 -04:00] [INF] [47] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "This"
[2023-05-05 22:01:43.813 -04:00] [INF] [47] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/17LkxNsWjzjdqyEQggFMom ["additional_types=track,episode"] null
[2023-05-05 22:01:44.885 -04:00] [INF] [47] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "", "
[2023-05-05 22:01:44.952 -04:00] [INF] [47] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1E4xrfzBBWuj3M ["additional_types=track,episode"] null
[2023-05-05 22:01:45.547 -04:00] [INF] [49] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "With"
[2023-05-05 22:01:45.601 -04:00] [INF] [49] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DX6lOApl1SnDm ["additional_types=track,episode"] null
[2023-05-05 22:01:46.107 -04:00] [INF] [48] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "", "
[2023-05-05 22:01:46.144 -04:00] [INF] [48] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DX24Kh15JFQJ0 ["additional_types=track,episode"] null
[2023-05-05 22:01:47.392 -04:00] [INF] [44] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "The "
[2023-05-05 22:01:47.451 -04:00] [INF] [44] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/37i9dQZF1DX24Kh15JFQJ0/tracks?offset=100&limit=100&additional_types=track%2Cepisode [""] null
[2023-05-05 22:01:47.905 -04:00] [INF] [50] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "href" : "https://api.spotify.com/v1/playlists/"
[2023-05-05 22:01:47.933 -04:00] [INF] [50] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DWWH0izG4erma ["additional_types=track,episode"] null
[2023-05-05 22:01:49.015 -04:00] [INF] [47] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "Coun"
[2023-05-05 22:01:49.077 -04:00] [INF] [47] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1E371RstrE3yly ["additional_types=track,episode"] null
[2023-05-05 22:01:49.562 -04:00] [INF] [46] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "Kidz"
[2023-05-05 22:01:49.593 -04:00] [INF] [46] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1EQqZgBURAEzWH ["additional_types=track,episode"] null
[2023-05-05 22:01:50.208 -04:00] [INF] [28] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "<a h"
[2023-05-05 22:01:50.232 -04:00] [INF] [28] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1EIfLh3vzsUwSp ["additional_types=track,episode"] null
[2023-05-05 22:01:50.729 -04:00] [INF] [44] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "Upbe"
[2023-05-05 22:01:50.805 -04:00] [INF] [44] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DWTQebjaPYhvs ["additional_types=track,episode"] null
[2023-05-05 22:01:51.894 -04:00] [INF] [47] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "The "
[2023-05-05 22:01:51.946 -04:00] [INF] [47] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/37i9dQZF1DWTQebjaPYhvs/tracks?offset=100&limit=100&additional_types=track%2Cepisode [""] null
[2023-05-05 22:01:52.895 -04:00] [INF] [44] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "href" : "https://api.spotify.com/v1/playlists/"
[2023-05-05 22:01:52.947 -04:00] [INF] [44] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DWTkxQvqMy4WW ["additional_types=track,episode"] null
[2023-05-05 22:01:53.704 -04:00] [INF] [28] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "Coun"
[2023-05-05 22:01:53.749 -04:00] [INF] [28] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DWXi7h4mmmkzD ["additional_types=track,episode"] null
[2023-05-05 22:01:54.761 -04:00] [INF] [44] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "Nigh"
[2023-05-05 22:01:54.815 -04:00] [INF] [44] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DX8WMG8VPSOJC ["additional_types=track,episode"] null
[2023-05-05 22:01:55.951 -04:00] [INF] [44] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "Noth"
[2023-05-05 22:01:55.991 -04:00] [INF] [44] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1EQmPV0vrce2QZ ["additional_types=track,episode"] null
[2023-05-05 22:01:56.422 -04:00] [INF] [49] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "<a h"
[2023-05-05 22:01:56.440 -04:00] [INF] [49] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/1bJQE1wWzKigCazmql9GOS ["additional_types=track,episode"] null
[2023-05-05 22:01:57.157 -04:00] [INF] [44] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "", "
[2023-05-05 22:01:57.181 -04:00] [INF] [44] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/7owszSrCw7tXCjoVHxc8B7 ["additional_types=track,episode"] null
[2023-05-05 22:01:57.646 -04:00] [INF] [49] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "", "
[2023-05-05 22:01:57.675 -04:00] [INF] [49] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/6U3lDn1EPqlFEZrIOzoxVf ["additional_types=track,episode"] null
[2023-05-05 22:01:58.663 -04:00] [INF] [34] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "The "
[2023-05-05 22:01:58.710 -04:00] [INF] [34] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DWVn8zvR5ROMB ["additional_types=track,episode"] null
[2023-05-05 22:01:59.279 -04:00] [INF] [34] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "All "
[2023-05-05 22:01:59.316 -04:00] [INF] [34] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DXaJXCbmtHVHV ["additional_types=track,episode"] null
[2023-05-05 22:02:00.423 -04:00] [INF] [34] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "Top "
[2023-05-05 22:02:00.507 -04:00] [INF] [34] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DX7hnECllVaUq ["additional_types=track,episode"] null
[2023-05-05 22:02:01.656 -04:00] [INF] [45] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "The "
[2023-05-05 22:02:01.706 -04:00] [INF] [45] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DX13kFuGnInkY ["additional_types=track,episode"] null
[2023-05-05 22:02:02.202 -04:00] [INF] [49] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "Cong"
[2023-05-05 22:02:02.222 -04:00] [INF] [49] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DWZBCPUIUs2iR ["additional_types=track,episode"] null
[2023-05-05 22:02:03.193 -04:00] [INF] [34] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "A co"
[2023-05-05 22:02:03.236 -04:00] [INF] [34] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DX5iKSDtVcf7Q ["additional_types=track,episode"] null
[2023-05-05 22:02:04.181 -04:00] [INF] [34] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "Musi"
[2023-05-05 22:02:04.238 -04:00] [INF] [34] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/79beQYmpATfGXz9Bns3mT9 ["additional_types=track,episode"] null
[2023-05-05 22:02:04.618 -04:00] [INF] [45] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "", "
[2023-05-05 22:02:04.636 -04:00] [INF] [45] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DX2SzDYPXnP1a ["additional_types=track,episode"] null
[2023-05-05 22:02:05.130 -04:00] [INF] [49] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "Coun"
[2023-05-05 22:02:05.152 -04:00] [INF] [49] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DWW7RgkOJG32Y ["additional_types=track,episode"] null
[2023-05-05 22:02:05.623 -04:00] [INF] [43] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "Top "
[2023-05-05 22:02:05.652 -04:00] [INF] [43] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/5sC7iKLcQ5cad1gLHulhSy ["additional_types=track,episode"] null
[2023-05-05 22:02:06.105 -04:00] [INF] [48] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "", "
[2023-05-05 22:02:06.136 -04:00] [INF] [48] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DX7aUUBCKwo4Y ["additional_types=track,episode"] null
[2023-05-05 22:02:06.654 -04:00] [INF] [43] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "Coun"
[2023-05-05 22:02:06.690 -04:00] [INF] [43] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DWYyZ38lseF2K ["additional_types=track,episode"] null
[2023-05-05 22:02:07.526 -04:00] [INF] [48] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "Our "
[2023-05-05 22:02:07.571 -04:00] [INF] [48] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DX8S0uQvJ4gaa ["additional_types=track,episode"] null
[2023-05-05 22:02:08.536 -04:00] [INF] [43] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "New "
[2023-05-05 22:02:08.619 -04:00] [INF] [43] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1DZ06evO1TkYCI ["additional_types=track,episode"] null
[2023-05-05 22:02:09.210 -04:00] [INF] [47] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "This"
[2023-05-05 22:02:09.240 -04:00] [INF] [47] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/37i9dQZF1E35JmMSzsiIaX ["additional_types=track,episode"] null
[2023-05-05 22:02:09.651 -04:00] [INF] [48] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "Ian "
[2023-05-05 22:02:09.677 -04:00] [INF] [48] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/2X0ZTyy8fPDkL5BzxWfECm ["additional_types=track,episode"] null
[2023-05-05 22:02:09.857 -04:00] [INF] [49] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ "collaborative" : false, "description" : "vibe"
[2023-05-05 22:02:09.859 -04:00] [ERR] [49] Emby.Server.Implementations.ScheduledTasks.TaskManager: Error
System.NullReferenceException: Object reference not set to an instance of an object.
at Viperinius.Plugin.SpotifyImport.Spotify.SpotifyPlaylistProvider.GetTrackInfo(PlaylistTrack1 track) at Viperinius.Plugin.SpotifyImport.Spotify.SpotifyPlaylistProvider.GetPlaylist(String playlistId, Nullable
1 cancellationToken)
at Viperinius.Plugin.SpotifyImport.Spotify.SpotifyPlaylistProvider.GetPlaylist(String playlistId, Nullable1 cancellationToken) at Viperinius.Plugin.SpotifyImport.GenericPlaylistProvider.PopulatePlaylists(List
1 playlistIds, Nullable1 cancellationToken) at Viperinius.Plugin.SpotifyImport.Tasks.SpotifyImportTask.ExecuteAsync(IProgress
1 progress, CancellationToken cancellationToken)
at Emby.Server.Implementations.ScheduledTasks.ScheduledTaskWorker.ExecuteInternal(TaskOptions options)
[2023-05-05 22:02:09.860 -04:00] [INF] [49] Emby.Server.Implementations.ScheduledTasks.TaskManager: "Import Spotify playlists" Failed after 0 minute(s) and 26 seconds
[2023-05-05 22:02:09.861 -04:00] [INF] [49] Emby.Server.Implementations.ScheduledTasks.TaskManager: ExecuteQueuedTasks
It only imported one of my playlists, and another one but with no tracks(even though I have the song in my library)
It didn't import most of my playlists
Am i doing it correctly? the user id is the string of characters from spotify profile >>copy link to profile?
First off, thanks for this plugin, it's fantastic, and certainly helps to bridge the gap between Jellyfin's lack of playlist creation and those from the streaming services.
I pulled in an artist radio playlist, and many of that artist's songs aren't showing up in the playlist. I'm wondering if there's some hard-coded requirements on case-sensitive matching or punctuation, etc. I'm using the Musicbrainz metadata agent to tag the music, and it's likely there's some issues with the tracks. A couple of examples:
These tracks show as missing from my library:
{
"Name": "My Friends Over You",
"AlbumName": "Sticks And Stones",
"ArtistName": "New Found Glory"
},
{
"Name": "The Best Of Me",
"AlbumName": "Say It Like You Mean It",
"ArtistName": "The Starting Line"
},
They do both exist, however the album for the first track is "Sticks and Stones" (lowercase "and"), and the second track name is "The Best of Me" (lowercase "of"). Everything else is the same.
If you need more specifics from somewhere, please let me know. If the plugin is case sensitive, can it be made more lenient? I'm also thinking removing punctuation from the search might be helpful (and I can't think that it would lead to many false matches).
If not, would it be possible to add this feature? Thanks!
I ask this because there are some missing songs, even though they are an exact match with what they should be.
I follow a shared playlist on spotify that is managed by the spotify team. They add new songs to the front of the playlist on a regular basis. They also remove some to keep the list to 50 songs (not necessary from the end though).
The current implementation adds new songs to the end of the jellyfin playlist and doesn't remove any that is no longer on the spotify list (although I can see that the latter is on your todo). This becomes a problem for me because over time, my jellyfin playlist will grow indefinitely and as new songs are added to the end, I will likely not get to hear them at all.
I'm thinking perhaps the plugin can offer a user option to recreate the jellyfin playlist from scratch (i.e. delete existing playlist) instead of just appending new songs to the existing list?
please add the ability to auto add newly created playlists, so if a user creates a new spotify playlist it will auto add it to jellyfin
Cool plugin, thank you.
I get the following error on a freshly installed jellyfin instance when manually triggering a sync job:
[ERR] [47] Emby.Server.Implementations.ScheduledTasks.TaskManager: Error
Newtonsoft.Json.JsonReaderException: Error reading integer. Unexpected token: StartObject. Path 'duration_ms', line 1, position 285041.
at Newtonsoft.Json.JsonReader.ReadAsInt32()
at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Populate(JsonReader reader, Object target)
at SpotifyAPI.Web.PlayableItemConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)
[... more Newtonsoft stack frames]
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
at SpotifyAPI.Web.Http.NewtonsoftJSONSerializer.DeserializeResponse[T](IResponse response)
at SpotifyAPI.Web.Http.APIConnector.DoSerializedRequest[T](IRequest request, CancellationToken cancel)
at SpotifyAPI.Web.Http.APIConnector.SendAPIRequest[T](Uri uri, HttpMethod method, IDictionary`2 parameters, Object body, IDictionary`2 headers, CancellationToken cancel)
at Viperinius.Plugin.SpotifyImport.Spotify.SpotifyPlaylistProvider.GetPlaylist(String playlistId, Nullable`1 cancellationToken)
at Viperinius.Plugin.SpotifyImport.GenericPlaylistProvider.PopulatePlaylists(List`1 playlistIds, Nullable`1 cancellationToken)
at Viperinius.Plugin.SpotifyImport.Tasks.SpotifyImportTask.ExecuteAsync(IProgress`1 progress, CancellationToken cancellationToken)
at Emby.Server.Implementations.ScheduledTasks.ScheduledTaskWorker.ExecuteInternal(TaskOptions options)
[INF] [47] Emby.Server.Implementations.ScheduledTasks.TaskManager: "Import Spotify playlists" Failed after 0 minute(s) and 39 seconds
For reasons unknown an exception in SpotifyAPI playableItemConverter is thrown.
Usually, exceptions in the library are caught in SpotifyPlaylistProvider, but this one is not since it is a JsonReaderException
.
As a result the sync tasks stops with errors.
The exception should not be thrown in the first place, but if it still happens I would expect this to be logged as a warning and the sync process should continue.
A quick fix for now could be to add a catch (JsonException)
block. This would however not solve the underlying issue, which might come from the used SpotifyWeb
library. (@JohnnyCrazy ?)
Description
On Spotify, hyphens are sometimes used for details, when parentheses are used in many other places. This means that things like remixes or acoustic versions can sometimes show up as "<track name> - xyz Remix" on Spotify but as "<track name> (xyz Remix)" on platforms like MusicBrainz.
Example: SLANDER, Said the Sky, JT Roach - Potions (Acoustic)
Matching seems to fail because of this.
There are a few other examples:
Spotify Playlist
Affected Track(s)
Title | Album | Artists | Album Artists |
---|---|---|---|
Potions (Acoustic) | Potions (Acoustic) | SLANDER, Said The Sky, JT Roach | JT Roach, SLANDER, Said The Sky |
Great Valley (Approaching Nirvana Remix) | Great Valley | Veela | Veela |
Happiest Year (Prince Fox Remix) | Happiest Year (Prince Fox Remix) | Jaymes Young | Jaymes Young |
Matches (Acoustic) [feat. Aaron Richards] | Matches (The Remixes) [feat. Aaron Richards] | Ephixa, Stephen Walking, Aaron Richards | Aaron Richards, Ephixa, Stephen Walking |
Plugin settings
Match Type
: Ignore Case + Punctuation + Parentheses Content (this probably kind of explains why the wrong version of "Matches" was selected)Match Criteria
Logs
I'm currently on mobile, but can do some proper testing with debug logging if needed :)
Hello, I have been trying to use your plugin, but I cant seem to get it to work.
I set up the authorization as per your instructions and added a playlist ID.
When I run the scheduled task manually it fails. It does create the playlist with title and image, but no tracks are added:
Here is the corresponding part of the log:
[2023-04-15 11:04:17.910 +02:00] [INF] [68] Emby.Server.Implementations.HttpServer.WebSocketManager: WS "192.168.2.75" closed
[2023-04-15 11:04:20.574 +02:00] [INF] [55] Emby.Server.Implementations.HttpServer.WebSocketManager: WS "192.168.2.75" request
[2023-04-15 11:05:13.157 +02:00] [INF] [84] Emby.Server.Implementations.ScheduledTasks.TaskManager: Executing "Import Spotify playlists"
[2023-04-15 11:05:13.157 +02:00] [INF] [84] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyPlaylistProvider: Starting to query 1 playlists from "Spotify"
[2023-04-15 11:05:13.159 +02:00] [INF] [84] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" playlists/3FxYX8AaDH02XsLBGeqnc8 ["additional_types=track,episode"] null
[2023-04-15 11:05:14.635 +02:00] [INF] [85] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"collaborative\" : false, \"description\" : \"\", "
[2023-04-15 11:05:14.713 +02:00] [INF] [85] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=100&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:15.449 +02:00] [INF] [60] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:15.529 +02:00] [INF] [60] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=200&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:16.170 +02:00] [INF] [8] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:16.241 +02:00] [INF] [8] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=300&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:16.778 +02:00] [INF] [84] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:16.835 +02:00] [INF] [84] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=400&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:17.538 +02:00] [INF] [84] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:17.607 +02:00] [INF] [84] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=500&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:18.133 +02:00] [INF] [60] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:18.171 +02:00] [INF] [60] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=600&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:18.909 +02:00] [INF] [60] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:18.955 +02:00] [INF] [60] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=700&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:19.508 +02:00] [INF] [84] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:19.583 +02:00] [INF] [84] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=800&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:20.212 +02:00] [INF] [62] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:20.297 +02:00] [INF] [62] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=900&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:20.765 +02:00] [INF] [62] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:20.839 +02:00] [INF] [62] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=1000&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:21.469 +02:00] [INF] [60] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:21.533 +02:00] [INF] [60] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=1100&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:22.196 +02:00] [INF] [62] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:22.291 +02:00] [INF] [62] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=1200&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:22.889 +02:00] [INF] [60] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:22.937 +02:00] [INF] [60] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=1300&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:23.635 +02:00] [INF] [84] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:23.720 +02:00] [INF] [84] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=1400&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:24.380 +02:00] [INF] [84] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:24.472 +02:00] [INF] [84] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=1500&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:25.189 +02:00] [INF] [85] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:25.225 +02:00] [INF] [85] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=1600&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:25.881 +02:00] [INF] [85] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:25.957 +02:00] [INF] [85] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: "GET" https://api.spotify.com/v1/playlists/3FxYX8AaDH02XsLBGeqnc8/tracks?offset=1700&limit=100&additional_types=track%2Cepisode [""] null
[2023-04-15 11:05:26.374 +02:00] [INF] [11] Viperinius.Plugin.SpotifyImport.Spotify.SpotifyLogger: --> OK "application/json" "{ \"href\" : \"https://api.spotify.com/v1/playlists/"
[2023-04-15 11:05:26.484 +02:00] [ERR] [11] Emby.Server.Implementations.ScheduledTasks.TaskManager: Error
System.NullReferenceException: Object reference not set to an instance of an object.
at Viperinius.Plugin.SpotifyImport.PlaylistSync.ItemMatchesTrackInfo(Audio audioItem, ProviderTrackInfo trackInfo)
at Viperinius.Plugin.SpotifyImport.PlaylistSync.GetTrack(ProviderTrackInfo providerTrackInfo)
at Viperinius.Plugin.SpotifyImport.PlaylistSync.FindTracksAndAddToPlaylist(Playlist playlist, List`1 providerTrackInfos, User user, CancellationToken cancellationToken)
at Viperinius.Plugin.SpotifyImport.PlaylistSync.Execute(CancellationToken cancellationToken)
at Viperinius.Plugin.SpotifyImport.Tasks.SpotifyImportTask.ExecuteAsync(IProgress`1 progress, CancellationToken cancellationToken)
at Emby.Server.Implementations.ScheduledTasks.ScheduledTaskWorker.ExecuteInternal(TaskOptions options)
[2023-04-15 11:05:26.497 +02:00] [INF] [11] Emby.Server.Implementations.ScheduledTasks.TaskManager: "Import Spotify playlists" Failed after 0 minute(s) and 13 seconds
[2023-04-15 11:05:26.500 +02:00] [INF] [11] Emby.Server.Implementations.ScheduledTasks.TaskManager: ExecuteQueuedTasks
[2023-04-15 11:05:30.543 +02:00] [INF] [60] Emby.Server.Implementations.HttpServer.WebSocketManager: WS "192.168.2.75" closed
[2023-04-15 11:05:30.941 +02:00] [INF] [60] Emby.Server.Implementations.HttpServer.WebSocketManager: WS "192.168.2.75" request
Any idea why it is not working? Am I doing something wrong?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.