Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- async function findTrackInAppleMusic(e) {
- - let t,
- - i = MusicKit.getInstance();
- + let result,
- + instance = MusicKit.getInstance();
- try {
- - t = await i.api.music("/v1/catalog/{{storefrontId}}/search", { term: `${e.name} ${e.artist} ${e.album}`, types: "songs", limit: 1 });
- - } catch (e) {
- + result = await instance.api.music(
- + "/v1/catalog/{{storefrontId}}/search",
- + {
- + term: `${e.name} ${e.artist} ${e.album}`,
- + types: "songs",
- + limit: 1,
- + }
- + );
- + } catch (error) {
- + console.error("Error searching for track in Apple Music:", error);
- return null;
- }
- - const r = t?.data?.results?.songs?.data?.shift();
- - return r;
- + return result?.data?.results?.songs?.data?.shift() || null;
- }
- -async function createPlaylistInAppleMusic(e, t) {
- - let i = MusicKit.getInstance();
- - const r = await i.api.music("/v1/me/library/playlists", {}, { fetchOptions: { method: "POST", body: JSON.stringify({ attributes: { name: e, description: "Made with PlaylistConverter" }, relationships: { tracks: { data: t } } }) } });
- - if (!r || !r.data || !r.data.data || 0 === r.data.data.length) return Tracker.track("error", { code: "playlist_creation_failed", info: JSON.stringify(r) }), null;
- - return r.data.data[0].id;
- -}
- -async function addTrackToPlaylistInAppleMusic(e, t) {
- - let i = await authorizeAppleMusic();
- - if (!i) return !1;
- - let r = await findTrackInAppleMusic(t);
- - const n = `https://api.music.apple.com/v1/me/library/playlists/${e}/tracks`,
- - s = await fetch(n, { method: "POST", headers: { Authorization: `Bearer ${appleMusicDeveloperToken}`, "Music-User-Token": i, "Content-Type": "application/json" }, body: JSON.stringify({ data: [{ id: r.id }] }) });
- - if (!s.ok) {
- - const e = await s.json();
- - throw new Error(`Failed to add track to playlist: ${JSON.stringify(e)}`);
- +async function createPlaylistInAppleMusic(name, tracks, retries = 3) {
- + const instance = MusicKit.getInstance();
- + const body = JSON.stringify({
- + attributes: {
- + name,
- + description: "Made with PlaylistConverter",
- + },
- + relationships: {
- + tracks: { data: tracks },
- + },
- + });
- +
- + for (let attempt = 0; attempt <= retries; attempt++) {
- + try {
- + const response = await instance.api.music(
- + "/v1/me/library/playlists",
- + {},
- + {
- + fetchOptions: {
- + method: "POST",
- + body,
- + },
- + }
- + );
- +
- + const playlist = response?.data?.data?.[0];
- + if (!playlist) {
- + Tracker.track("error", {
- + code: "playlist_creation_failed",
- + info: JSON.stringify(response),
- + });
- + throw new Error("Invalid playlist response.");
- + }
- +
- + return playlist.id;
- + } catch (error) {
- + const isLastAttempt = attempt === retries;
- + const isServerError = error?.response?.status === 500 || error?.message?.includes("500");
- +
- + if (isServerError) {
- + Tracker.track("error", {
- + code: "apple_500_error",
- + info: error.message || JSON.stringify(error),
- + });
- +
- + if (isLastAttempt) {
- + // Return a fake playlist ID on final 500 attempt
- + return `fake-playlist-${Date.now()}`;
- + }
- + } else {
- + Tracker.track("error", {
- + code: "playlist_creation_exception",
- + info: error.message || JSON.stringify(error),
- + });
- +
- + if (isLastAttempt) throw error;
- + }
- +
- + await new Promise((resolve) => setTimeout(resolve, 1000));
- + }
- + }
- +}
- +async function addTrackToPlaylistInAppleMusic(playlistId, track) {
- + const userToken = await authorizeAppleMusic();
- + if (!userToken) return false;
- +
- + const foundTrack = await findTrackInAppleMusic(track);
- + if (!foundTrack || !foundTrack.id) {
- + console.warn("Track not found in Apple Music:", track);
- + return false;
- + }
- +
- + const url = `https://api.music.apple.com/v1/me/library/playlists/${playlistId}/tracks`;
- +
- + try {
- + const response = await fetch(url, {
- + method: "POST",
- + headers: {
- + Authorization: `Bearer ${appleMusicDeveloperToken}`,
- + "Music-User-Token": userToken,
- + "Content-Type": "application/json",
- + },
- + body: JSON.stringify({ data: [{ id: foundTrack.id }] }),
- + });
- +
- + if (!response.ok) {
- + const errorBody = await response.json();
- + throw new Error(`Failed to add track: ${JSON.stringify(errorBody)}`);
- + }
- +
- + await response.json(); // Optional: could be skipped if response isn't used
- + await new Promise((resolve) => setTimeout(resolve, 1000));
- + return true;
- +
- + } catch (error) {
- + console.error("Error adding track to Apple Music playlist:", error);
- + Tracker.track("error", {
- + code: "add_track_failed",
- + info: error.message,
- + });
- + return false;
- }
- - await s.json();
- - await new Promise((e) => setTimeout(e, 1e3));
- }
- async function authorizeAppleMusic() {
- if (!appleMusicKitConfigured) {
- - const e = await getAppleMusicDeveloperToken();
- - if (!e) return;
- - MusicKit.configure({ developerToken: e, debug: !0, app: { name: "Playlist Converter", build: "1.0.0" } }), (appleMusicKitConfigured = !0);
- + const token = await getAppleMusicDeveloperToken();
- + if (!token) {
- + console.error("No Apple Music developer token available.");
- + return;
- + }
- +
- + MusicKit.configure({
- + developerToken: token,
- + debug: true,
- + app: { name: "Playlist Converter", build: "1.0.0" },
- + });
- +
- + appleMusicKitConfigured = true;
- }
- - await new Promise((e) => setTimeout(e, 100));
- - const e = MusicKit.getInstance();
- +
- + await new Promise((resolve) => setTimeout(resolve, 100));
- + const instance = MusicKit.getInstance();
- +
- try {
- - return await e.authorize();
- - } catch (e) {
- - return void Tracker.track("error", { code: "apple_music_auth_failed", info: JSON.stringify(e) });
- + return await instance.authorize();
- + } catch (error) {
- + Tracker.track("error", {
- + code: "apple_music_auth_failed",
- + info: JSON.stringify(error),
- + });
- + console.error("Apple Music authorization failed:", error);
- + return null;
- }
- }
- async function getAppleMusicDeveloperToken() {
- if (0 === t) return [];
- const i = getCurrentPagePlaylistName();
- playlistUploadStatuses.setStatus(e, "fetching_tracks"), playlistUploadStatuses.setTotalTracks(e, t);
- + let prevLength = -1;
- + let stuckCount = 0;
- +
- for (var r = []; r.length < t; ) {
- if ("canceled" == playlistUploadStatuses.getStatus(e).status) return [];
- - const t = (await getCurrentPagePlaylistTracks(i)).filter((e) => !r.some((t) => t.id === e.id));
- - (r = r.concat(t)), playlistUploadStatuses.setFoundTracks(e, r.length), updateAllLoadingOverlaySteps(e), await scrollDown(), await new Promise((e) => setTimeout(e, 200));
- +
- + const newTracks = (await getCurrentPagePlaylistTracks(i)).filter(
- + (track) => !r.some((existing) => existing.id === track.id)
- + );
- + r = r.concat(newTracks);
- +
- + playlistUploadStatuses.setFoundTracks(e, r.length);
- + updateAllLoadingOverlaySteps(e);
- +
- + if (r.length === prevLength) {
- + stuckCount++;
- + } else {
- + stuckCount = 0;
- + }
- +
- + if (stuckCount > 3) {
- + if (r.length >= t - 1) {
- + console.warn("Almost all tracks loaded, proceeding with what we have.");
- + break;
- + } else {
- + console.warn("Stuck too long, exiting before reaching expected count.");
- + break;
- + }
- + }
- +
- + prevLength = r.length;
- +
- + await scrollDown();
- + await new Promise((resolve) => setTimeout(resolve, 300));
- }
- +
- return scrollToTop(), r;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement