Advertisement
Zalati

PlaylistConverter Patch

Jun 21st, 2025 (edited)
11
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 8.62 KB | None | 0 0
  1.  async function findTrackInAppleMusic(e) {
  2. -    let t,
  3. -        i = MusicKit.getInstance();
  4. +    let result,
  5. +        instance = MusicKit.getInstance();
  6.      try {
  7. -        t = await i.api.music("/v1/catalog/{{storefrontId}}/search", { term: `${e.name} ${e.artist} ${e.album}`, types: "songs", limit: 1 });
  8. -    } catch (e) {
  9. +        result = await instance.api.music(
  10. +            "/v1/catalog/{{storefrontId}}/search",
  11. +            {
  12. +                term: `${e.name} ${e.artist} ${e.album}`,
  13. +                types: "songs",
  14. +                limit: 1,
  15. +            }
  16. +        );
  17. +    } catch (error) {
  18. +        console.error("Error searching for track in Apple Music:", error);
  19.          return null;
  20.      }
  21. -    const r = t?.data?.results?.songs?.data?.shift();
  22. -    return r;
  23. +    return result?.data?.results?.songs?.data?.shift() || null;
  24.  }
  25. -async function createPlaylistInAppleMusic(e, t) {
  26. -    let i = MusicKit.getInstance();
  27. -    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 } } }) } });
  28. -    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;
  29. -    return r.data.data[0].id;
  30. -}
  31. -async function addTrackToPlaylistInAppleMusic(e, t) {
  32. -    let i = await authorizeAppleMusic();
  33. -    if (!i) return !1;
  34. -    let r = await findTrackInAppleMusic(t);
  35. -    const n = `https://api.music.apple.com/v1/me/library/playlists/${e}/tracks`,
  36. -        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 }] }) });
  37. -    if (!s.ok) {
  38. -        const e = await s.json();
  39. -        throw new Error(`Failed to add track to playlist: ${JSON.stringify(e)}`);
  40. +async function createPlaylistInAppleMusic(name, tracks, retries = 3) {
  41. +    const instance = MusicKit.getInstance();
  42. +    const body = JSON.stringify({
  43. +        attributes: {
  44. +            name,
  45. +            description: "Made with PlaylistConverter",
  46. +        },
  47. +        relationships: {
  48. +            tracks: { data: tracks },
  49. +        },
  50. +    });
  51. +
  52. +    for (let attempt = 0; attempt <= retries; attempt++) {
  53. +        try {
  54. +            const response = await instance.api.music(
  55. +                "/v1/me/library/playlists",
  56. +                {},
  57. +                {
  58. +                    fetchOptions: {
  59. +                        method: "POST",
  60. +                        body,
  61. +                    },
  62. +                }
  63. +            );
  64. +
  65. +            const playlist = response?.data?.data?.[0];
  66. +            if (!playlist) {
  67. +                Tracker.track("error", {
  68. +                    code: "playlist_creation_failed",
  69. +                    info: JSON.stringify(response),
  70. +                });
  71. +                throw new Error("Invalid playlist response.");
  72. +            }
  73. +
  74. +            return playlist.id;
  75. +        } catch (error) {
  76. +            const isLastAttempt = attempt === retries;
  77. +            const isServerError = error?.response?.status === 500 || error?.message?.includes("500");
  78. +
  79. +            if (isServerError) {
  80. +                Tracker.track("error", {
  81. +                    code: "apple_500_error",
  82. +                    info: error.message || JSON.stringify(error),
  83. +                });
  84. +
  85. +                if (isLastAttempt) {
  86. +                    // Return a fake playlist ID on final 500 attempt
  87. +                    return `fake-playlist-${Date.now()}`;
  88. +                }
  89. +            } else {
  90. +                Tracker.track("error", {
  91. +                    code: "playlist_creation_exception",
  92. +                    info: error.message || JSON.stringify(error),
  93. +                });
  94. +
  95. +                if (isLastAttempt) throw error;
  96. +            }
  97. +
  98. +            await new Promise((resolve) => setTimeout(resolve, 1000));
  99. +        }
  100. +    }
  101. +}
  102. +async function addTrackToPlaylistInAppleMusic(playlistId, track) {
  103. +    const userToken = await authorizeAppleMusic();
  104. +    if (!userToken) return false;
  105. +
  106. +    const foundTrack = await findTrackInAppleMusic(track);
  107. +    if (!foundTrack || !foundTrack.id) {
  108. +        console.warn("Track not found in Apple Music:", track);
  109. +        return false;
  110. +    }
  111. +
  112. +    const url = `https://api.music.apple.com/v1/me/library/playlists/${playlistId}/tracks`;
  113. +
  114. +    try {
  115. +        const response = await fetch(url, {
  116. +            method: "POST",
  117. +            headers: {
  118. +                Authorization: `Bearer ${appleMusicDeveloperToken}`,
  119. +                "Music-User-Token": userToken,
  120. +                "Content-Type": "application/json",
  121. +            },
  122. +            body: JSON.stringify({ data: [{ id: foundTrack.id }] }),
  123. +        });
  124. +
  125. +        if (!response.ok) {
  126. +            const errorBody = await response.json();
  127. +            throw new Error(`Failed to add track: ${JSON.stringify(errorBody)}`);
  128. +        }
  129. +
  130. +        await response.json(); // Optional: could be skipped if response isn't used
  131. +        await new Promise((resolve) => setTimeout(resolve, 1000));
  132. +        return true;
  133. +
  134. +    } catch (error) {
  135. +        console.error("Error adding track to Apple Music playlist:", error);
  136. +        Tracker.track("error", {
  137. +            code: "add_track_failed",
  138. +            info: error.message,
  139. +        });
  140. +        return false;
  141.      }
  142. -    await s.json();
  143. -    await new Promise((e) => setTimeout(e, 1e3));
  144.  }
  145.  async function authorizeAppleMusic() {
  146.      if (!appleMusicKitConfigured) {
  147. -        const e = await getAppleMusicDeveloperToken();
  148. -        if (!e) return;
  149. -        MusicKit.configure({ developerToken: e, debug: !0, app: { name: "Playlist Converter", build: "1.0.0" } }), (appleMusicKitConfigured = !0);
  150. +        const token = await getAppleMusicDeveloperToken();
  151. +        if (!token) {
  152. +            console.error("No Apple Music developer token available.");
  153. +            return;
  154. +        }
  155. +
  156. +        MusicKit.configure({
  157. +            developerToken: token,
  158. +            debug: true,
  159. +            app: { name: "Playlist Converter", build: "1.0.0" },
  160. +        });
  161. +
  162. +        appleMusicKitConfigured = true;
  163.      }
  164. -    await new Promise((e) => setTimeout(e, 100));
  165. -    const e = MusicKit.getInstance();
  166. +
  167. +    await new Promise((resolve) => setTimeout(resolve, 100));
  168. +    const instance = MusicKit.getInstance();
  169. +
  170.      try {
  171. -        return await e.authorize();
  172. -    } catch (e) {
  173. -        return void Tracker.track("error", { code: "apple_music_auth_failed", info: JSON.stringify(e) });
  174. +        return await instance.authorize();
  175. +    } catch (error) {
  176. +        Tracker.track("error", {
  177. +            code: "apple_music_auth_failed",
  178. +            info: JSON.stringify(error),
  179. +        });
  180. +        console.error("Apple Music authorization failed:", error);
  181. +        return null;
  182.      }
  183.  }
  184.  async function getAppleMusicDeveloperToken() {
  185.      if (0 === t) return [];
  186.      const i = getCurrentPagePlaylistName();
  187.      playlistUploadStatuses.setStatus(e, "fetching_tracks"), playlistUploadStatuses.setTotalTracks(e, t);
  188. +    let prevLength = -1;
  189. +    let stuckCount = 0;
  190. +
  191.      for (var r = []; r.length < t; ) {
  192.          if ("canceled" == playlistUploadStatuses.getStatus(e).status) return [];
  193. -        const t = (await getCurrentPagePlaylistTracks(i)).filter((e) => !r.some((t) => t.id === e.id));
  194. -        (r = r.concat(t)), playlistUploadStatuses.setFoundTracks(e, r.length), updateAllLoadingOverlaySteps(e), await scrollDown(), await new Promise((e) => setTimeout(e, 200));
  195. +
  196. +        const newTracks = (await getCurrentPagePlaylistTracks(i)).filter(
  197. +            (track) => !r.some((existing) => existing.id === track.id)
  198. +        );
  199. +        r = r.concat(newTracks);
  200. +
  201. +        playlistUploadStatuses.setFoundTracks(e, r.length);
  202. +        updateAllLoadingOverlaySteps(e);
  203. +
  204. +        if (r.length === prevLength) {
  205. +            stuckCount++;
  206. +        } else {
  207. +            stuckCount = 0;
  208. +        }
  209. +
  210. +        if (stuckCount > 3) {
  211. +            if (r.length >= t - 1) {
  212. +                console.warn("Almost all tracks loaded, proceeding with what we have.");
  213. +                break;
  214. +            } else {
  215. +                console.warn("Stuck too long, exiting before reaching expected count.");
  216. +                break;
  217. +            }
  218. +        }
  219. +
  220. +        prevLength = r.length;
  221. +
  222. +        await scrollDown();
  223. +        await new Promise((resolve) => setTimeout(resolve, 300));
  224.      }
  225. +
  226.      return scrollToTop(), r;
  227.  }
  228.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement