diff --git a/DOCKER.md b/DOCKER.md index a5b78e9..93cb170 100644 --- a/DOCKER.md +++ b/DOCKER.md @@ -139,7 +139,7 @@ Portainer can deploy directly from your GitHub fork with auto-updates on push. > **Tip:** `COMPOSE_PROFILES` is a built-in Docker Compose variable. Setting it to `pocketbase` is equivalent to passing `--profile pocketbase` on the command line. -> **Warning:** The `dev` profile is for **local development only**. It uses volume mounts to enable hot-reload, which requires the source code to be present on the host machine. Do **not** include `dev` in `COMPOSE_PROFILES` on Portainer deployments from GitHub — it will fail because there's no local source code to mount. +> **Warning:** The `dev` profile is for **local development only**. It uses volume mounts to enable hot-reload, which requires the source code to be present on the host machine. Do **not** include `dev` in `COMPOSE_PROFILES` on Portainer deployments from GitHub - it will fail because there's no local source code to mount. ### Fork Workflow diff --git a/index.html b/index.html index b0e24f3..b44a998 100644 --- a/index.html +++ b/index.html @@ -3187,6 +3187,18 @@ +
+
+
+ Editor's Picks Source + Choose which editor's picks file to display +
+ +
+
+
diff --git a/js/app.js b/js/app.js index c3baadb..94abf54 100644 --- a/js/app.js +++ b/js/app.js @@ -550,8 +550,8 @@ document.addEventListener('DOMContentLoaded', async () => { * having to manually re-scan. * * When called with a `blob` and `filename` (single-track download case) it - * performs a cheap partial update — reading metadata only from that one file - * and inserting it into the existing cache — so the full folder does not need + * performs a cheap partial update - reading metadata only from that one file + * and inserting it into the existing cache - so the full folder does not need * to be re-walked. When called with no arguments (bulk download case, or when * `localFilesCache` has never been populated) it falls back to a full rescan. */ diff --git a/js/db.js b/js/db.js index bcc6835..9017296 100644 --- a/js/db.js +++ b/js/db.js @@ -24,7 +24,7 @@ export class MusicDatabase { request.onupgradeneeded = (event) => { const db = event.target.result; - // v10 introduced track_ratings (bad PR) — remove it + // v10 introduced track_ratings (bad PR) - remove it if (db.objectStoreNames.contains('track_ratings')) { db.deleteObjectStore('track_ratings'); } diff --git a/js/haptics.js b/js/haptics.js index 18ebeb1..d01390b 100644 --- a/js/haptics.js +++ b/js/haptics.js @@ -5,7 +5,7 @@ let _Haptics = null; let _ImpactStyle = null; let _NotificationStyle = null; -// Single stored promise — subsequent calls reuse the same one +// Single stored promise - subsequent calls reuse the same one const _ready = import('@capacitor/haptics') .then((mod) => { _Haptics = mod.Haptics; @@ -13,14 +13,14 @@ const _ready = import('@capacitor/haptics') _NotificationStyle = mod.NotificationStyle; }) .catch(() => { - // Not in Capacitor or haptics not available — fall back to navigator.vibrate + // Not in Capacitor or haptics not available - fall back to navigator.vibrate }); function vibrateFallback(ms) { if (navigator.vibrate) navigator.vibrate(ms); } -/** Light tap — for toggles, menu opens */ +/** Light tap - for toggles, menu opens */ export async function hapticLight() { await _ready; try { @@ -32,7 +32,7 @@ export async function hapticLight() { vibrateFallback(30); } -/** Medium impact — for play/pause, skip */ +/** Medium impact - for play/pause, skip */ export async function hapticMedium() { await _ready; try { @@ -44,7 +44,7 @@ export async function hapticMedium() { vibrateFallback(50); } -/** Success notification — for like/unlike, add to queue */ +/** Success notification - for like/unlike, add to queue */ export async function hapticSuccess() { await _ready; try { @@ -56,7 +56,7 @@ export async function hapticSuccess() { vibrateFallback(40); } -/** Long press — replaces navigator.vibrate(50) for track selection */ +/** Long press - replaces navigator.vibrate(50) for track selection */ export async function hapticLongPress() { await _ready; try { diff --git a/js/settings.js b/js/settings.js index 7ea8974..93be865 100644 --- a/js/settings.js +++ b/js/settings.js @@ -4917,6 +4917,34 @@ export async function initializeSettings(scrobbler, player, api, ui) { }); } + const editorsPicksSourceSelect = document.getElementById('editors-picks-source-select'); + if (editorsPicksSourceSelect) { + async function populateEditorsPicksSource() { + try { + const response = await fetch('/editors-picks-old/index.json'); + if (response.ok) { + const oldPicks = await response.json(); + oldPicks.forEach((pick) => { + const option = document.createElement('option'); + option.value = pick.file; + option.textContent = pick.label; + editorsPicksSourceSelect.appendChild(option); + }); + } + } catch (e) { + console.warn('Could not load editors-picks-old index:', e); + } + const currentSource = homePageSettings.getEditorsPicksSource(); + editorsPicksSourceSelect.value = currentSource; + } + populateEditorsPicksSource(); + + editorsPicksSourceSelect.addEventListener('change', (e) => { + homePageSettings.setEditorsPicksSource(e.target.value); + window.dispatchEvent(new CustomEvent('refresh-home-editors-picks')); + }); + } + // Sidebar Section Toggles const sidebarShowHomeToggle = document.getElementById('sidebar-show-home-toggle'); if (sidebarShowHomeToggle) { diff --git a/js/storage.js b/js/storage.js index 4d553fa..e70be5c 100644 --- a/js/storage.js +++ b/js/storage.js @@ -2009,6 +2009,20 @@ export const homePageSettings = { setShuffleEditorsPicks(enabled) { localStorage.setItem(this.SHUFFLE_EDITORS_PICKS_KEY, enabled ? 'true' : 'false'); }, + + EDITORS_PICKS_SOURCE_KEY: 'home-editors-picks-source', + + getEditorsPicksSource() { + try { + return localStorage.getItem(this.EDITORS_PICKS_SOURCE_KEY) || 'current'; + } catch { + return 'current'; + } + }, + + setEditorsPicksSource(source) { + localStorage.setItem(this.EDITORS_PICKS_SOURCE_KEY, source); + }, }; export const radioSettings = { diff --git a/js/taglib.worker.ts b/js/taglib.worker.ts index 8b01a15..fb91b10 100644 --- a/js/taglib.worker.ts +++ b/js/taglib.worker.ts @@ -135,7 +135,7 @@ export async function addMetadataToAudio(message: _AddMetadataMessage): Promise< if (explicit !== undefined) { if (isMp4) { - // rtng is a byte item — must be set directly on the Mp4Tag + // rtng is a byte item - must be set directly on the Mp4Tag const mp4Tag = (underlying as Mp4File).tag() as Mp4Tag; mp4Tag.setItem('rtng', Mp4Item.fromByte(explicit ? 1 : 0)); } else { diff --git a/js/ui.js b/js/ui.js index 1855ee5..c169529 100644 --- a/js/ui.js +++ b/js/ui.js @@ -165,6 +165,11 @@ export class UIRenderer { this.visualizer.updateDimming(); } }); + + window.addEventListener('refresh-home-editors-picks', () => { + this.renderHomeEditorsPicks(true, 'home-editors-picks'); + this.renderHomeEditorsPicks(true, 'home-editors-picks-empty'); + }); } static async initialize(api, player) { @@ -2510,7 +2515,9 @@ export class UIRenderer { else if (picksContainer.children.length > 0 && !picksContainer.querySelector('.skeleton')) return; try { - const response = await fetch('/editors-picks.json'); + const source = homePageSettings.getEditorsPicksSource(); + const picksPath = source === 'current' ? '/editors-picks.json' : `/editors-picks-old/${source}`; + const response = await fetch(picksPath); if (!response.ok) throw new Error("Failed to load editor's picks"); let items = await response.json(); diff --git a/public/editors-picks.json.old b/public/editors-picks-old/2026-3-20-before-april-fools.json similarity index 100% rename from public/editors-picks.json.old rename to public/editors-picks-old/2026-3-20-before-april-fools.json diff --git a/public/editors-picks-old/2026-4-1-april-fools.json b/public/editors-picks-old/2026-4-1-april-fools.json new file mode 100644 index 0000000..b7e8c8b --- /dev/null +++ b/public/editors-picks-old/2026-4-1-april-fools.json @@ -0,0 +1,189 @@ +[ + { + "type": "album", + "id": 510893864, + "title": "BULLY", + "artist": { "id": 25022, "name": "Kanye West" }, + "releaseDate": "2026-03-28", + "cover": "cf2f2c9c-ff67-44f6-83aa-a7622f8c6b64", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 403172104, + "title": "From A Man's Perspective", + "artist": { "id": 3561564, "name": "Dax" }, + "releaseDate": "2024-12-06", + "cover": "c52a53ea-f021-44bf-8cef-fb31d3b82940", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 341529881, + "title": "FACTS", + "artist": { "id": 5691796, "name": "Tom MacDonald" }, + "releaseDate": "2024-01-26", + "cover": "34198718-cc7d-47eb-9bf1-1dc5c26fc8a1", + "explicit": false, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 452163300, + "title": "Tackle Box", + "artist": { "id": 44771714, "name": "JamWayne" }, + "releaseDate": "2025-09-01", + "cover": "bf7d2e55-52dc-4e41-9f53-1db31918798e", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 106210035, + "title": "Supermarket (Soundtrack)", + "artist": { "id": 3533999, "name": "LOGIC" }, + "releaseDate": "2019-03-26", + "cover": "bdd39738-7177-4836-bd7f-cd4fe4ccf535", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 138458381, + "title": "JOKER", + "artist": { "id": 39109746, "name": "Dax" }, + "releaseDate": "2020-05-06", + "cover": "d6a39491-fece-4594-a538-9cfbce7c6c68", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 318467376, + "title": "The Draco Tape 2", + "artist": { "id": 22467779, "name": "60PERCENTHOMO" }, + "releaseDate": "2023-09-30", + "cover": "9169e8ab-fdb0-49d1-a14f-82a2b541223c", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 456582219, + "title": "bbno$", + "artist": { "id": 8173944, "name": "bbno$" }, + "releaseDate": "2025-10-17", + "cover": "8162c739-4bb2-4218-8915-93cb1f0d9eea", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 506216548, + "title": "Declassified", + "artist": { "id": 5691796, "name": "Tom MacDonald" }, + "releaseDate": "2026-03-13", + "cover": "5cf188e5-1660-4a01-bacc-10ca81e7af73", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 486673299, + "title": "Novelty", + "artist": { "id": 3589848, "name": "Goofy" }, + "releaseDate": "2026-01-23", + "cover": "dd543595-e604-440e-a24c-e2eaccda3804", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 440469641, + "title": "Tha Carter VI", + "artist": { "id": 27518, "name": "Lil Wayne" }, + "releaseDate": "2025-06-06", + "cover": "f2807cfe-6df8-4ea0-ab32-fd0ad9e91072", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 384057608, + "title": "FREE VIPER!", + "artist": { "id": 10285483, "name": "Viper" }, + "releaseDate": "2024-08-28", + "cover": "642d73d9-2a45-4598-bec3-033a09181bdf", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 460015533, + "title": "CHARLIE", + "artist": { "id": 5691796, "name": "Tom MacDonald" }, + "releaseDate": "2025-09-11", + "cover": "18180e3d-e178-4bd3-aada-e26ca32bc8f4", + "explicit": false, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 123319314, + "title": "BABY G.O.A.T.", + "artist": { "id": 9160626, "name": "Kevo Muney" }, + "releaseDate": "2019-12-12", + "cover": "6c87aee6-76da-413e-a639-79b670b3e3d1", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 510493672, + "title": "ADL", + "artist": { "id": 9318056, "name": "Yeat" }, + "releaseDate": "2026-03-27", + "cover": "b799025a-7ff6-494c-aa11-5e0461bbca40", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 440096189, + "title": "Rebel", + "artist": { "id": 52081927, "name": "EsDeeKid" }, + "releaseDate": "2025-06-20", + "cover": "3433b56c-6386-4e21-90ee-f2369d4bfde7", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 85287313, + "title": "Toilet", + "artist": { "id": 9598562, "name": "Clown Core" }, + "releaseDate": "2018-03-03", + "cover": "d6d32464-864e-422f-b8c3-0c30baa563b1", + "explicit": false, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + } +] diff --git a/public/editors-picks-old/index.json b/public/editors-picks-old/index.json new file mode 100644 index 0000000..0d5f958 --- /dev/null +++ b/public/editors-picks-old/index.json @@ -0,0 +1,12 @@ +[ + { + "file": "2026-3-20-before-april-fools.json", + "label": "Before April Fools '26", + "date": "2026-03-20" + }, + { + "file": "2026-4-1-april-fools.json", + "label": "April Fools '26", + "date": "2026-04-01" + } +] diff --git a/public/editors-picks.json b/public/editors-picks.json index b7e8c8b..6ce3464 100644 --- a/public/editors-picks.json +++ b/public/editors-picks.json @@ -8,182 +8,127 @@ "cover": "cf2f2c9c-ff67-44f6-83aa-a7622f8c6b64", "explicit": true, "audioQuality": "LOSSLESS", - "mediaMetadata": { "tags": ["LOSSLESS"] } + "mediaMetadata": { "tags": ["LOSSLESS", "HIRES_LOSSLESS"] } }, { "type": "album", - "id": 403172104, - "title": "From A Man's Perspective", - "artist": { "id": 3561564, "name": "Dax" }, - "releaseDate": "2024-12-06", - "cover": "c52a53ea-f021-44bf-8cef-fb31d3b82940", + "id": 324660713, + "title": "JOECHILLWORLD", + "artist": { "id": 40978758, "name": "Devon Hendryx" }, + "releaseDate": "2010-07-10", + "cover": "25d45544-3e82-4184-b8c2-2c2c6f0f152a", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS", "HIRES_LOSSLESS"] } + }, + { + "type": "album", + "id": 15427733, + "title": "Mysterious Phonk: The Chronicles of SpaceGhostPurrp", + "artist": { "id": 4611745, "name": "Spaceghostpurrp" }, + "releaseDate": "2012-06-12", + "cover": "c78b7543-1cd8-4921-9155-e81d421353a0", "explicit": true, "audioQuality": "LOSSLESS", "mediaMetadata": { "tags": ["LOSSLESS"] } }, { "type": "album", - "id": 341529881, - "title": "FACTS", - "artist": { "id": 5691796, "name": "Tom MacDonald" }, - "releaseDate": "2024-01-26", - "cover": "34198718-cc7d-47eb-9bf1-1dc5c26fc8a1", + "id": 464178301, + "title": "Never Forget", + "artist": { "id": 5516508, "name": "Chris Travis" }, + "releaseDate": "2014-05-14", + "cover": "4ab11f0d-0768-4cce-8de5-1894134d5994", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 75115890, + "title": "Blood Shore Season 2", + "artist": { "id": 6332342, "name": "Xavier Wulf" }, + "releaseDate": "2014-10-30", + "cover": "517303e5-d541-4704-b552-026427e05fcb", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 410197513, + "title": "THE PEAK", + "artist": { "id": 33481052, "name": "smokedope2016" }, + "releaseDate": "2025-01-17", + "cover": "ea18084d-36ec-4cea-98a7-fe4684246986", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 418729278, + "title": "I LAY DOWN MY LIFE FOR YOU: DIRECTOR'S CUT", + "artist": { "id": 7958797, "name": "JPEGMAFIA" }, + "releaseDate": "2025-02-03", + "cover": "9c84302b-2584-4c0a-9db7-e648542f459f", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS", "HIRES_LOSSLESS"] } + }, + { + "type": "album", + "id": 504004321, + "title": "Half Blood (BloodLuxe)", + "artist": { "id": 50799233, "name": "slayr" }, + "releaseDate": "2025-11-05", + "cover": "2767cc63-7e92-4a48-aa4b-806a3ea7ec1c", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS", "HIRES_LOSSLESS"] } + }, + { + "type": "album", + "id": 325723583, + "title": "Replica", + "artist": { "id": 3715530, "name": "Oneohtrix Point Never" }, + "releaseDate": "2011-11-05", + "cover": "95ceeae9-cac7-42dc-ae37-7c93c223f809", "explicit": false, "audioQuality": "LOSSLESS", "mediaMetadata": { "tags": ["LOSSLESS"] } }, { "type": "album", - "id": 452163300, - "title": "Tackle Box", - "artist": { "id": 44771714, "name": "JamWayne" }, - "releaseDate": "2025-09-01", - "cover": "bf7d2e55-52dc-4e41-9f53-1db31918798e", + "id": 336178142, + "title": "Pirate This Album", + "artist": { "id": 8622751, "name": "Shamana" }, + "releaseDate": "2023-12-25", + "cover": "a8a647be-0331-4779-9a6e-31645a9abdab", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS", "HIRES_LOSSLESS"] } + }, + { + "type": "album", + "id": 106369871, + "title": "Organic Thoughts from the Synthetic Mind", + "artist": { "id": 6436013, "name": "Shinjuku Mad" }, + "releaseDate": "2009-07-01", + "cover": "3acc888e-35da-40a8-a4b7-7ffd00576cc9", "explicit": true, "audioQuality": "LOSSLESS", "mediaMetadata": { "tags": ["LOSSLESS"] } }, { "type": "album", - "id": 106210035, - "title": "Supermarket (Soundtrack)", - "artist": { "id": 3533999, "name": "LOGIC" }, - "releaseDate": "2019-03-26", - "cover": "bdd39738-7177-4836-bd7f-cd4fe4ccf535", + "id": 423471869, + "title": "pain", + "artist": { "id": 44257324, "name": "bleood" }, + "releaseDate": "2025-03-11", + "cover": "711b23ba-c473-44e6-a2f0-010fefa9c5b8", "explicit": true, "audioQuality": "LOSSLESS", "mediaMetadata": { "tags": ["LOSSLESS"] } - }, - { - "type": "album", - "id": 138458381, - "title": "JOKER", - "artist": { "id": 39109746, "name": "Dax" }, - "releaseDate": "2020-05-06", - "cover": "d6a39491-fece-4594-a538-9cfbce7c6c68", - "explicit": true, - "audioQuality": "LOSSLESS", - "mediaMetadata": { "tags": ["LOSSLESS"] } - }, - { - "type": "album", - "id": 318467376, - "title": "The Draco Tape 2", - "artist": { "id": 22467779, "name": "60PERCENTHOMO" }, - "releaseDate": "2023-09-30", - "cover": "9169e8ab-fdb0-49d1-a14f-82a2b541223c", - "explicit": true, - "audioQuality": "LOSSLESS", - "mediaMetadata": { "tags": ["LOSSLESS"] } - }, - { - "type": "album", - "id": 456582219, - "title": "bbno$", - "artist": { "id": 8173944, "name": "bbno$" }, - "releaseDate": "2025-10-17", - "cover": "8162c739-4bb2-4218-8915-93cb1f0d9eea", - "explicit": true, - "audioQuality": "LOSSLESS", - "mediaMetadata": { "tags": ["LOSSLESS"] } - }, - { - "type": "album", - "id": 506216548, - "title": "Declassified", - "artist": { "id": 5691796, "name": "Tom MacDonald" }, - "releaseDate": "2026-03-13", - "cover": "5cf188e5-1660-4a01-bacc-10ca81e7af73", - "explicit": true, - "audioQuality": "LOSSLESS", - "mediaMetadata": { "tags": ["LOSSLESS"] } - }, - { - "type": "album", - "id": 486673299, - "title": "Novelty", - "artist": { "id": 3589848, "name": "Goofy" }, - "releaseDate": "2026-01-23", - "cover": "dd543595-e604-440e-a24c-e2eaccda3804", - "explicit": true, - "audioQuality": "LOSSLESS", - "mediaMetadata": { "tags": ["LOSSLESS"] } - }, - { - "type": "album", - "id": 440469641, - "title": "Tha Carter VI", - "artist": { "id": 27518, "name": "Lil Wayne" }, - "releaseDate": "2025-06-06", - "cover": "f2807cfe-6df8-4ea0-ab32-fd0ad9e91072", - "explicit": true, - "audioQuality": "LOSSLESS", - "mediaMetadata": { "tags": ["LOSSLESS"] } - }, - { - "type": "album", - "id": 384057608, - "title": "FREE VIPER!", - "artist": { "id": 10285483, "name": "Viper" }, - "releaseDate": "2024-08-28", - "cover": "642d73d9-2a45-4598-bec3-033a09181bdf", - "explicit": true, - "audioQuality": "LOSSLESS", - "mediaMetadata": { "tags": ["LOSSLESS"] } - }, - { - "type": "album", - "id": 460015533, - "title": "CHARLIE", - "artist": { "id": 5691796, "name": "Tom MacDonald" }, - "releaseDate": "2025-09-11", - "cover": "18180e3d-e178-4bd3-aada-e26ca32bc8f4", - "explicit": false, - "audioQuality": "LOSSLESS", - "mediaMetadata": { "tags": ["LOSSLESS"] } - }, - { - "type": "album", - "id": 123319314, - "title": "BABY G.O.A.T.", - "artist": { "id": 9160626, "name": "Kevo Muney" }, - "releaseDate": "2019-12-12", - "cover": "6c87aee6-76da-413e-a639-79b670b3e3d1", - "explicit": true, - "audioQuality": "LOSSLESS", - "mediaMetadata": { "tags": ["LOSSLESS"] } - }, - { - "type": "album", - "id": 510493672, - "title": "ADL", - "artist": { "id": 9318056, "name": "Yeat" }, - "releaseDate": "2026-03-27", - "cover": "b799025a-7ff6-494c-aa11-5e0461bbca40", - "explicit": true, - "audioQuality": "LOSSLESS", - "mediaMetadata": { "tags": ["LOSSLESS"] } - }, - { - "type": "album", - "id": 440096189, - "title": "Rebel", - "artist": { "id": 52081927, "name": "EsDeeKid" }, - "releaseDate": "2025-06-20", - "cover": "3433b56c-6386-4e21-90ee-f2369d4bfde7", - "explicit": true, - "audioQuality": "LOSSLESS", - "mediaMetadata": { "tags": ["LOSSLESS"] } - }, - { - "type": "album", - "id": 85287313, - "title": "Toilet", - "artist": { "id": 9598562, "name": "Clown Core" }, - "releaseDate": "2018-03-03", - "cover": "d6d32464-864e-422f-b8c3-0c30baa563b1", - "explicit": false, - "audioQuality": "LOSSLESS", - "mediaMetadata": { "tags": ["LOSSLESS"] } } ]