From 78f62c8d78b379f83ef42bd8bad0a30b81cf8900 Mon Sep 17 00:00:00 2001 From: Rimma Kubanova Date: Thu, 22 Aug 2024 21:53:07 +0500 Subject: [PATCH 1/9] soundcloud export & import --- .../src/playlists/components/PlaylistMenu.tsx | 57 ++++- frontend/js/src/user/playlists/Playlists.tsx | 30 ++- .../ImportSoundCloudPlaylistModal.tsx | 203 ++++++++++++++++++ frontend/js/src/utils/APIService.ts | 45 ++++ frontend/js/src/utils/soundcloudTypes.d.ts | 39 ++++ frontend/js/src/utils/types.d.ts | 4 - .../metadata_cache/soundcloud/client.py | 41 ++++ listenbrainz/troi/export.py | 21 ++ listenbrainz/troi/import_ms.py | 19 +- listenbrainz/webserver/views/playlist_api.py | 104 ++++++--- 10 files changed, 527 insertions(+), 36 deletions(-) create mode 100644 frontend/js/src/user/playlists/components/ImportSoundCloudPlaylistModal.tsx create mode 100644 frontend/js/src/utils/soundcloudTypes.d.ts create mode 100644 listenbrainz/metadata_cache/soundcloud/client.py diff --git a/frontend/js/src/playlists/components/PlaylistMenu.tsx b/frontend/js/src/playlists/components/PlaylistMenu.tsx index 52aa3f2399..b0e00bd9fc 100644 --- a/frontend/js/src/playlists/components/PlaylistMenu.tsx +++ b/frontend/js/src/playlists/components/PlaylistMenu.tsx @@ -1,7 +1,7 @@ /* eslint-disable jsx-a11y/anchor-is-valid */ /* eslint-disable react/jsx-no-comment-textnodes */ import { IconProp } from "@fortawesome/fontawesome-svg-core"; -import { faSpotify } from "@fortawesome/free-brands-svg-icons"; +import { faSpotify, faSoundcloud } from "@fortawesome/free-brands-svg-icons"; import { faCopy, faFileExport, @@ -36,7 +36,9 @@ function PlaylistMenu({ onPlaylistCopied, disallowEmptyPlaylistExport, }: PlaylistMenuProps) { - const { APIService, currentUser, spotifyAuth } = useContext(GlobalAppContext); + const { APIService, currentUser, spotifyAuth, soundcloudAuth } = useContext( + GlobalAppContext + ); const { auth_token } = currentUser; const playlistID = getPlaylistId(playlist); const playlistTitle = playlist.title; @@ -159,6 +161,40 @@ function PlaylistMenu({ { toastId: "export-playlist" } ); }; + const exportToSoundcloud = async () => { + if (!auth_token) { + alertMustBeLoggedIn(); + return; + } + let result; + if (playlistID) { + result = await APIService.exportPlaylistToSoundCloud( + auth_token, + playlistID + ); + } else { + // TODO + // result = await APIService.exportJSPFPlaylistToSoundCloud( + // auth_token, + // playlist + // ); + } + const { external_url } = result; + toast.success( + + Successfully exported playlist:{" "} + + {playlistTitle} + + + } + />, + { toastId: "export-playlist" } + ); + }; const handlePlaylistExport = async (handler: () => Promise) => { if (!playlist || (disallowEmptyPlaylistExport && !playlist.track.length)) { toast.warn( @@ -179,6 +215,7 @@ function PlaylistMenu({ const showSpotifyExportButton = spotifyAuth?.permission?.includes( "playlist-modify-public" ); + const showSoundCloudExportButton = soundcloudAuth; return (