Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videostreaming/plugins/spotify
1 result
Show changes
Commits on Source (3)
......@@ -7,7 +7,7 @@
"sourceUrl": "https://plugins.grayjay.app/Spotify/SpotifyConfig.json",
"repositoryUrl": "https://gitlab.futo.org/videostreaming/plugins/spotify",
"scriptUrl": "./SpotifyScript.js",
"version": 8,
"version": 11,
"iconUrl": "./SpotifyIcon.png",
"id": "4e365633-6d3f-4267-8941-fdc36631d813",
"scriptSignature": "",
......
......@@ -243,7 +243,8 @@ function getHome() {
}
};
}
if (section_item._uri === `spotify:user:${local_state.username}:collection:your-episodes`) {
if (section_item._uri === `spotify:user:${local_state.username}:collection:your-episodes`
|| section_item._uri === "spotify:collection:podcasts:episodes") {
return {
content: {
data: {
......@@ -262,8 +263,13 @@ function getHome() {
}
};
}
const regex = /^spotify:user:[a-zA-Z0-9]*?:collection:artist/;
if (regex.test(section_item._uri)) {
const artist_collection_regex = /^spotify:user:[a-zA-Z0-9]*?:collection:artist/;
if (artist_collection_regex.test(section_item._uri)) {
return [];
}
// ignore legacy stations
const station_regex = /^spotify:station:track:/;
if (station_regex.test(section_item._uri)) {
return [];
}
log(section_item);
......@@ -2107,7 +2113,7 @@ function format_section_item(section, section_as_author) {
})?.value;
const image_url = section.images.items[0]?.sources[0]?.url;
if (image_url === undefined) {
throw new ScriptException("missing playlist thumbnail");
throw new ScriptException(`missing playlist thumbnail for: ${section.uri}`);
}
let author = section_as_author;
// TODO we might want to look up the username of the playlist if it is missing instead of using the section/page/genre as the channel
......@@ -2435,6 +2441,8 @@ function getUserPlaylists() {
...playlists,
...library_response.data.me.libraryV3.items.flatMap(function (library_item) {
const item = library_item.item.data;
// to avoid the never type
const type = item.__typename;
switch (item.__typename) {
case "Album":
return `${ALBUM_URL_PREFIX}${id_from_uri(item.uri)}`;
......@@ -2450,8 +2458,10 @@ function getUserPlaylists() {
return [];
case "Folder":
return [];
case "NotFound":
return [];
default:
throw assert_exhaustive(item, `unknown item type: item.__typename`);
throw assert_exhaustive(item, `unknown item type: ${type}`);
}
})
];
......@@ -2549,6 +2559,8 @@ function getUserSubscriptions() {
...following,
...library_response.data.me.libraryV3.items.flatMap(function (library_item) {
const item = library_item.item.data;
// to avoid the never type
const type = item.__typename;
switch (item.__typename) {
case "Album":
return [];
......@@ -2564,8 +2576,10 @@ function getUserSubscriptions() {
return `${ARTIST_URL_PREFIX}${id_from_uri(item.uri)}`;
case "Folder":
return [];
case "NotFound":
return [];
default:
throw assert_exhaustive(item, "unreachable");
throw assert_exhaustive(item, `unknown item type: ${type}`);
}
})
];
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
......@@ -350,7 +350,10 @@ function getHome() {
}
}
}
if (section_item._uri === `spotify:user:${local_state.username}:collection:your-episodes`) {
if (
section_item._uri === `spotify:user:${local_state.username}:collection:your-episodes`
|| section_item._uri === "spotify:collection:podcasts:episodes"
) {
return {
content: {
data: {
......@@ -369,8 +372,13 @@ function getHome() {
}
}
}
const regex = /^spotify:user:[a-zA-Z0-9]*?:collection:artist/
if(regex.test(section_item._uri)){
const artist_collection_regex = /^spotify:user:[a-zA-Z0-9]*?:collection:artist/
if (artist_collection_regex.test(section_item._uri)) {
return []
}
// ignore legacy stations
const station_regex = /^spotify:station:track:/
if (station_regex.test(section_item._uri)) {
return []
}
log(section_item)
......@@ -2470,7 +2478,7 @@ function format_section_item(section: SectionItemAlbum | SectionItemPlaylist | S
})?.value
const image_url = section.images.items[0]?.sources[0]?.url
if (image_url === undefined) {
throw new ScriptException("missing playlist thumbnail")
throw new ScriptException(`missing playlist thumbnail for: ${section.uri}`)
}
let author = section_as_author
// TODO we might want to look up the username of the playlist if it is missing instead of using the section/page/genre as the channel
......@@ -2847,6 +2855,10 @@ function getUserPlaylists() {
...playlists,
...library_response.data.me.libraryV3.items.flatMap(function (library_item) {
const item = library_item.item.data
// to avoid the never type
const type = item.__typename
switch (item.__typename) {
case "Album":
return `${ALBUM_URL_PREFIX}${id_from_uri(item.uri)}`
......@@ -2862,8 +2874,10 @@ function getUserPlaylists() {
return []
case "Folder":
return []
case "NotFound":
return []
default:
throw assert_exhaustive(item, `unknown item type: item.__typename`)
throw assert_exhaustive(item, `unknown item type: ${type}`)
}
})
]
......@@ -2962,6 +2976,10 @@ function getUserSubscriptions(): string[] {
...following,
...library_response.data.me.libraryV3.items.flatMap(function (library_item) {
const item = library_item.item.data
// to avoid the never type
const type = item.__typename
switch (item.__typename) {
case "Album":
return []
......@@ -2977,8 +2995,10 @@ function getUserSubscriptions(): string[] {
return `${ARTIST_URL_PREFIX}${id_from_uri(item.uri)}`
case "Folder":
return []
case "NotFound":
return []
default:
throw assert_exhaustive(item, "unreachable")
throw assert_exhaustive(item, `unknown item type: ${type}`)
}
})
]
......
......@@ -135,7 +135,14 @@ export type LibraryResponse = {
readonly totalCount: number
readonly items: {
readonly item: {
readonly data: SectionItemFolder | SectionItemPodcast | SectionItemPlaylist | SectionItemAlbum | SectionItemArtist | SectionItemAudiobook | SectionItemPseudoPlaylist
readonly data: SectionItemFolder
| SectionItemPodcast
| SectionItemPlaylist
| SectionItemAlbum
| SectionItemArtist
| SectionItemAudiobook
| SectionItemPseudoPlaylist
| SectionItemNotFound
}
}[]
}
......
......@@ -9,14 +9,14 @@
"version": "1.0.0",
"license": "MPL-2.0",
"devDependencies": {
"@eslint/js": "^9.14.0",
"@eslint/js": "^9.15.0",
"@kaidelorenzo/grayjay-polyfill": "gitlab:kaidelorenzo/grayjay-polyfill#9a48957ba321192416e820002aab528104567654",
"@types/eslint__js": "^8.42.3",
"@types/grayjay-source": "gitlab:kaidelorenzo/grayjay-plugin-types#ddffcd5573f102c45d0ac4d8a5f87452e76ffa77",
"@types/node": "^22.9.0",
"eslint": "^9.14.0",
"typescript": "^5.6.3",
"typescript-eslint": "^8.14.0"
"@types/node": "^22.10.0",
"eslint": "^9.15.0",
"typescript": "^5.7.2",
"typescript-eslint": "^8.16.0"
}
},
"node_modules/@eslint-community/eslint-utils": {
......@@ -301,27 +301,27 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "22.9.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.1.tgz",
"integrity": "sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg==",
"version": "22.10.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.0.tgz",
"integrity": "sha512-XC70cRZVElFHfIUB40FgZOBbgJYFKKMa5nb9lxcwYstFG/Mi+/Y0bGS+rs6Dmhmkpq4pnNiLiuZAbc02YCOnmA==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.19.8"
"undici-types": "~6.20.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz",
"integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==",
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.16.0.tgz",
"integrity": "sha512-5YTHKV8MYlyMI6BaEG7crQ9BhSc8RxzshOReKwZwRWN0+XvvTOm+L/UYLCYxFpfwYuAAqhxiq4yae0CMFwbL7Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.15.0",
"@typescript-eslint/type-utils": "8.15.0",
"@typescript-eslint/utils": "8.15.0",
"@typescript-eslint/visitor-keys": "8.15.0",
"@typescript-eslint/scope-manager": "8.16.0",
"@typescript-eslint/type-utils": "8.16.0",
"@typescript-eslint/utils": "8.16.0",
"@typescript-eslint/visitor-keys": "8.16.0",
"graphemer": "^1.4.0",
"ignore": "^5.3.1",
"natural-compare": "^1.4.0",
......@@ -345,16 +345,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz",
"integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==",
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.16.0.tgz",
"integrity": "sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"@typescript-eslint/scope-manager": "8.15.0",
"@typescript-eslint/types": "8.15.0",
"@typescript-eslint/typescript-estree": "8.15.0",
"@typescript-eslint/visitor-keys": "8.15.0",
"@typescript-eslint/scope-manager": "8.16.0",
"@typescript-eslint/types": "8.16.0",
"@typescript-eslint/typescript-estree": "8.16.0",
"@typescript-eslint/visitor-keys": "8.16.0",
"debug": "^4.3.4"
},
"engines": {
......@@ -374,14 +374,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz",
"integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==",
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.16.0.tgz",
"integrity": "sha512-mwsZWubQvBki2t5565uxF0EYvG+FwdFb8bMtDuGQLdCCnGPrDEDvm1gtfynuKlnpzeBRqdFCkMf9jg1fnAK8sg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.15.0",
"@typescript-eslint/visitor-keys": "8.15.0"
"@typescript-eslint/types": "8.16.0",
"@typescript-eslint/visitor-keys": "8.16.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
......@@ -392,14 +392,14 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz",
"integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==",
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.16.0.tgz",
"integrity": "sha512-IqZHGG+g1XCWX9NyqnI/0CX5LL8/18awQqmkZSl2ynn8F76j579dByc0jhfVSnSnhf7zv76mKBQv9HQFKvDCgg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/typescript-estree": "8.15.0",
"@typescript-eslint/utils": "8.15.0",
"@typescript-eslint/typescript-estree": "8.16.0",
"@typescript-eslint/utils": "8.16.0",
"debug": "^4.3.4",
"ts-api-utils": "^1.3.0"
},
......@@ -420,9 +420,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz",
"integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==",
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.16.0.tgz",
"integrity": "sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ==",
"dev": true,
"license": "MIT",
"engines": {
......@@ -434,14 +434,14 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz",
"integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==",
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.16.0.tgz",
"integrity": "sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"@typescript-eslint/types": "8.15.0",
"@typescript-eslint/visitor-keys": "8.15.0",
"@typescript-eslint/types": "8.16.0",
"@typescript-eslint/visitor-keys": "8.16.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
......@@ -489,16 +489,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz",
"integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==",
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.16.0.tgz",
"integrity": "sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "8.15.0",
"@typescript-eslint/types": "8.15.0",
"@typescript-eslint/typescript-estree": "8.15.0"
"@typescript-eslint/scope-manager": "8.16.0",
"@typescript-eslint/types": "8.16.0",
"@typescript-eslint/typescript-estree": "8.16.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
......@@ -517,13 +517,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz",
"integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==",
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.16.0.tgz",
"integrity": "sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.15.0",
"@typescript-eslint/types": "8.16.0",
"eslint-visitor-keys": "^4.2.0"
},
"engines": {
......@@ -1572,9 +1572,9 @@
"license": "MIT"
},
"node_modules/ts-api-utils": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz",
"integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==",
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.2.tgz",
"integrity": "sha512-ZF5gQIQa/UmzfvxbHZI3JXN0/Jt+vnAfAviNRAMc491laiK6YCLpCW9ft8oaCRFOTxCZtUTE6XB0ZQAe3olntw==",
"dev": true,
"license": "MIT",
"engines": {
......@@ -1598,9 +1598,9 @@
}
},
"node_modules/typescript": {
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
"integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz",
"integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==",
"dev": true,
"license": "Apache-2.0",
"bin": {
......@@ -1612,15 +1612,15 @@
}
},
"node_modules/typescript-eslint": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.15.0.tgz",
"integrity": "sha512-wY4FRGl0ZI+ZU4Jo/yjdBu0lVTSML58pu6PgGtJmCufvzfV565pUF6iACQt092uFOd49iLOTX/sEVmHtbSrS+w==",
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.16.0.tgz",
"integrity": "sha512-wDkVmlY6O2do4V+lZd0GtRfbtXbeD0q9WygwXXSJnC1xorE8eqyC2L1tJimqpSeFrOzRlYtWnUp/uzgHQOgfBQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.15.0",
"@typescript-eslint/parser": "8.15.0",
"@typescript-eslint/utils": "8.15.0"
"@typescript-eslint/eslint-plugin": "8.16.0",
"@typescript-eslint/parser": "8.16.0",
"@typescript-eslint/utils": "8.16.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
......@@ -1639,9 +1639,9 @@
}
},
"node_modules/undici-types": {
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
"dev": true,
"license": "MIT"
},
......
......@@ -350,7 +350,10 @@ function getHome() {
}
}
}
if (section_item._uri === `spotify:user:${local_state.username}:collection:your-episodes`) {
if (
section_item._uri === `spotify:user:${local_state.username}:collection:your-episodes`
|| section_item._uri === "spotify:collection:podcasts:episodes"
) {
return {
content: {
data: {
......@@ -369,8 +372,13 @@ function getHome() {
}
}
}
const regex = /^spotify:user:[a-zA-Z0-9]*?:collection:artist/
if(regex.test(section_item._uri)){
const artist_collection_regex = /^spotify:user:[a-zA-Z0-9]*?:collection:artist/
if (artist_collection_regex.test(section_item._uri)) {
return []
}
// ignore legacy stations
const station_regex = /^spotify:station:track:/
if (station_regex.test(section_item._uri)) {
return []
}
log(section_item)
......@@ -2470,7 +2478,7 @@ function format_section_item(section: SectionItemAlbum | SectionItemPlaylist | S
})?.value
const image_url = section.images.items[0]?.sources[0]?.url
if (image_url === undefined) {
throw new ScriptException("missing playlist thumbnail")
throw new ScriptException(`missing playlist thumbnail for: ${section.uri}`)
}
let author = section_as_author
// TODO we might want to look up the username of the playlist if it is missing instead of using the section/page/genre as the channel
......@@ -2847,6 +2855,10 @@ function getUserPlaylists() {
...playlists,
...library_response.data.me.libraryV3.items.flatMap(function (library_item) {
const item = library_item.item.data
// to avoid the never type
const type = item.__typename
switch (item.__typename) {
case "Album":
return `${ALBUM_URL_PREFIX}${id_from_uri(item.uri)}`
......@@ -2862,8 +2874,10 @@ function getUserPlaylists() {
return []
case "Folder":
return []
case "NotFound":
return []
default:
throw assert_exhaustive(item, `unknown item type: item.__typename`)
throw assert_exhaustive(item, `unknown item type: ${type}`)
}
})
]
......@@ -2962,6 +2976,10 @@ function getUserSubscriptions(): string[] {
...following,
...library_response.data.me.libraryV3.items.flatMap(function (library_item) {
const item = library_item.item.data
// to avoid the never type
const type = item.__typename
switch (item.__typename) {
case "Album":
return []
......@@ -2977,8 +2995,10 @@ function getUserSubscriptions(): string[] {
return `${ARTIST_URL_PREFIX}${id_from_uri(item.uri)}`
case "Folder":
return []
case "NotFound":
return []
default:
throw assert_exhaustive(item, "unreachable")
throw assert_exhaustive(item, `unknown item type: ${type}`)
}
})
]
......
......@@ -135,7 +135,14 @@ export type LibraryResponse = {
readonly totalCount: number
readonly items: {
readonly item: {
readonly data: SectionItemFolder | SectionItemPodcast | SectionItemPlaylist | SectionItemAlbum | SectionItemArtist | SectionItemAudiobook | SectionItemPseudoPlaylist
readonly data: SectionItemFolder
| SectionItemPodcast
| SectionItemPlaylist
| SectionItemAlbum
| SectionItemArtist
| SectionItemAudiobook
| SectionItemPseudoPlaylist
| SectionItemNotFound
}
}[]
}
......