A music player that connects to your cloud/distributed storage. diffuse.sh
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172import * as TID from "@atcute/tid";import foundation from "~/common/foundation.js";
foundation.setup({ title: "Diffuse v3.x Import" });
const main = /** @type {HTMLElement} */ (document.querySelector("main"));
/** * @import {PlaylistItem, Track} from "~/definitions/types.d.ts" */
// Setupconst favourites = await foundation.orchestrator.favourites();const output = await foundation.orchestrator.output();
// Elementsconst fileInput = /** @type {HTMLInputElement} */ (document.querySelector("#file"));const importFavouritesBtn = /** @type {HTMLButtonElement} */ (document.querySelector( "#import-favourites", ));const importPlaylistItemsBtn = /** @type {HTMLButtonElement} */ (document.querySelector( "#import-playlist-items", ));const statusEl = /** @type {HTMLElement} */ (document.querySelector("#status"));
/** @type {Record<string, any> | null} */let json = null;
/** * Show a status message. * @param {string} message * @param {"success" | "error"} type */function showStatus(message, type) { statusEl.textContent = message; statusEl.className = `status status--${type}`; statusEl.hidden = false;}
// Parse file on selectionfileInput.onchange = async () => { const file = fileInput.files?.[0];
json = null; statusEl.hidden = true; importFavouritesBtn.disabled = true; importPlaylistItemsBtn.disabled = true;
if (!file) return;
try { json = JSON.parse(await file.text()); } catch (err) { console.error("Failed to parse JSON:", err); showStatus( `Failed to parse JSON: ${/** @type {Error} */ (err).message}`, "error", ); return; }
if (json?.favourites?.data?.length > 0) { importFavouritesBtn.disabled = false; }
if (json?.playlists?.data?.length > 0) { importPlaylistItemsBtn.disabled = false; }};
// Import favourites on button clickimportFavouritesBtn.onclick = async () => { /** @type {any[]} */ const items = json?.favourites?.data; if (!items || items.length === 0) return;
try { /** @type {Track[]} */ const tracks = items.map((item) => ({ $type: "sh.diffuse.output.track", id: "", uri: "", tags: { artist: item.artist ?? "", title: item.title ?? "", }, }));
await favourites.include(tracks); showStatus(`Imported ${tracks.length} favourite(s).`, "success"); } catch (err) { console.error("Import failed:", err); showStatus(`Import failed: ${/** @type {Error} */ (err).message}`, "error"); }};
// Import playlist items on button clickimportPlaylistItemsBtn.onclick = async () => { /** @type {any[]} */ const items = json?.playlists?.data; if (!items || items.length === 0) return;
try { const now = new Date().toISOString();
const existingCol = output.playlistItems.collection(); /** @type {any[]} */ const existing = existingCol.state === "loaded" ? existingCol.data : []; const existingPlaylistNames = new Set(existing.map((p) => p.playlist));
const newPlaylistItems = items .filter((item) => !existingPlaylistNames.has(item.name ?? "Untitled")) .flatMap((item) => { const playlistName = item.name ?? "Untitled"; const isUnordered = !!item.collection;
/** @type {PlaylistItem[]} */ const playlistItems = [];
/** @type {any[]} */ (item.tracks ?? []).forEach((track, index) => { playlistItems.push({ $type: "sh.diffuse.output.playlistItem", id: TID.now(), playlist: playlistName, positionedAfter: isUnordered ? undefined : index > 0 ? playlistItems[index - 1].id : undefined, criteria: [ { field: "tags.album", value: track.album ?? "", transformations: ["toLowerCase"], }, { field: "tags.artist", value: track.artist ?? "", transformations: ["toLowerCase"], }, { field: "tags.title", value: track.title ?? "", transformations: ["toLowerCase"], }, ], createdAt: now, updatedAt: now, }); });
return playlistItems; });
await output.playlistItems.save([...existing, ...newPlaylistItems]); const playlistCount = new Set(newPlaylistItems.map((p) => p.playlist)).size; showStatus(`Imported ${playlistCount} playlist(s).`, "success"); } catch (err) { console.error("Import failed:", err); showStatus(`Import failed: ${/** @type {Error} */ (err).message}`, "error"); }};
////////////////////////////////////////////// 🚀////////////////////////////////////////////
foundation.ready();