From d1c262e31eb46184719ace8d5c3f239f170705c6 Mon Sep 17 00:00:00 2001 From: aria Date: Mon, 5 Aug 2024 01:04:01 -0400 Subject: [PATCH 01/36] add dispatcher support for all platforms --- src/streamers/deezer/main.ts | 26 +++++++++++++++++++------- src/streamers/qobuz/main.ts | 10 +++++++--- src/streamers/soundcloud/main.ts | 27 ++++++++++++++++++++------- src/streamers/tidal/main.ts | 28 +++++++++++++++++++--------- 4 files changed, 65 insertions(+), 26 deletions(-) diff --git a/src/streamers/deezer/main.ts b/src/streamers/deezer/main.ts index 9c2a95b..2a71983 100644 --- a/src/streamers/deezer/main.ts +++ b/src/streamers/deezer/main.ts @@ -1,4 +1,4 @@ -import { fetch } from 'undici' +import { Dispatcher, fetch } from 'undici' import { Album, Artist, @@ -29,6 +29,7 @@ import { Blowfish } from 'blowfish-cbc' interface DeezerOptions { arl?: string + dispatcher?: Dispatcher | undefined } interface APIMethod { @@ -86,11 +87,13 @@ export default class Deezer implements StreamerWithLogin { renewTimestamp?: number country?: string language?: string + dispatcher?: Dispatcher | undefined availableFormats: Set = new Set() constructor(options?: DeezerOptions) { if (options?.arl) this.arl = options.arl + //if (options?.dispatcher) this.dispatcher = options.dispatcher } async #apiCall( @@ -114,7 +117,12 @@ export default class Deezer implements StreamerWithLogin { } const body = JSON.stringify(data) - const req = await fetch(url, { method: 'POST', body, headers: this.headers }) + const req = await fetch(url, { + method: 'POST', + body, + headers: this.headers, + dispatcher: this.dispatcher + }) const { results, error } = await req.json() if (error.constructor.name == 'Object') { @@ -167,7 +175,10 @@ export default class Deezer implements StreamerWithLogin { async login(username: string, password: string): Promise { if (this.arl) await this.#loginViaArl(this.arl) else { - const resp = await fetch('https://www.deezer.com/', { headers: this.headers }) + const resp = await fetch('https://www.deezer.com/', { + headers: this.headers, + dispatcher: this.dispatcher + }) const setCookie = resp.headers.get('Set-Cookie') ?? '' const sid = setCookie.match(/sid=(fr[0-9a-f]+)/)![1] this.headers['Cookie'] = `sid=${sid}` @@ -181,7 +192,7 @@ export default class Deezer implements StreamerWithLogin { password, hash: this.#md5(CLIENT_ID + username + password + CLIENT_SECRET) })}`, - { headers: this.headers } + { headers: this.headers, dispatcher: this.dispatcher } ) const { error } = await loginReq.json() @@ -242,7 +253,7 @@ export default class Deezer implements StreamerWithLogin { /* ---------- GET INFO FROM URL ---------- */ async #unshortenUrl(url: URL): Promise { - const res = await fetch(url, { redirect: 'manual' }) + const res = await fetch(url, { redirect: 'manual', dispatcher: this.dispatcher }) const location = res.headers.get('Location') if (res.status != 302 || !location) throw new Error('URL not supported') @@ -351,7 +362,7 @@ export default class Deezer implements StreamerWithLogin { // download const url = await this.#getTrackUrl(id, trackToken, trackTokenExpiry, format) - const streamResp = await fetch(url) + const streamResp = await fetch(url, { dispatcher: this.dispatcher }) if (!streamResp.ok) throw new Error(`Failed to get track stream. Status code: ${streamResp.status}`) @@ -441,7 +452,8 @@ export default class Deezer implements StreamerWithLogin { } ], track_tokens: [trackToken] - }) + }), + dispatcher: this.dispatcher }) const res = await req.json() diff --git a/src/streamers/qobuz/main.ts b/src/streamers/qobuz/main.ts index 11e20fc..a9fc7d9 100644 --- a/src/streamers/qobuz/main.ts +++ b/src/streamers/qobuz/main.ts @@ -1,5 +1,5 @@ import crypto from 'crypto' -import { fetch } from 'undici' +import { fetch, Dispatcher } from 'undici' import { ItemType, StreamerWithLogin, @@ -27,6 +27,7 @@ interface QobuzOptions { appSecret: string appId: string token?: string + dispatcher?: Dispatcher } interface LoginResponse { @@ -66,11 +67,13 @@ export default class Qobuz implements StreamerWithLogin { token?: string appSecret: string appId: string + dispatcher: Dispatcher | undefined fetch?(url: URL | RequestInfo, init?: RequestInit): Promise constructor(options: QobuzOptions) { this.appSecret = options.appSecret this.appId = options.appId if (options.token) this.token = options.token + if (options.dispatcher) this.dispatcher = options.dispatcher } async #get(url: string, params: { [key: string]: string | number }) { @@ -83,7 +86,8 @@ export default class Qobuz implements StreamerWithLogin { )}`, { method: 'get', - headers: headers(this.token) + headers: headers(this.token), + dispatcher: this.dispatcher } ) if (!response.ok) { @@ -179,7 +183,7 @@ export default class Qobuz implements StreamerWithLogin { ) if (trackFileResponse.sample == true) throw new Error(`Could not get non-sample file. Make sure the track isn't purchase-only.`) - const streamResponse = await fetch(trackFileResponse.url) + const streamResponse = await fetch(trackFileResponse.url, { dispatcher: this.dispatcher }) return { mimeType: trackFileResponse.mime_type, sizeBytes: parseInt(streamResponse.headers.get('Content-Length')), diff --git a/src/streamers/soundcloud/main.ts b/src/streamers/soundcloud/main.ts index 069cfc9..e90b528 100644 --- a/src/streamers/soundcloud/main.ts +++ b/src/streamers/soundcloud/main.ts @@ -1,4 +1,4 @@ -import { fetch, HeadersInit } from 'undici' +import { Dispatcher, fetch, HeadersInit } from 'undici' import { DEFAULT_HEADERS } from './constants.js' import { ItemType, @@ -30,6 +30,7 @@ function headers(oauthToken?: string | undefined): HeadersInit { interface SoundcloudOptions { oauthToken?: string + dispatcher: Dispatcher | undefined } interface SoundcloudTranscoding { @@ -69,8 +70,10 @@ export default class Soundcloud implements Streamer { } as const oauthToken?: string client?: ScClient + dispatcher: Dispatcher | undefined constructor(options: SoundcloudOptions) { this.oauthToken = options?.oauthToken + this.dispatcher = options?.dispatcher } async search(query: string, limit = 20): Promise { const client = this.client || (await this.#getClient()) @@ -81,7 +84,7 @@ export default class Soundcloud implements Streamer { )}&offset=0&linked_partitioning=1&app_locale=en&limit=${limit}`, client ), - { method: 'get', headers: headers(this.oauthToken) } + { method: 'get', headers: headers(this.oauthToken), dispatcher: this.dispatcher } ) if (!response.ok) { const errMsg = await response.text() @@ -116,7 +119,8 @@ export default class Soundcloud implements Streamer { const response = await ( await fetch(`https://soundcloud.com/`, { method: 'get', - headers: headers() + headers: headers(this.oauthToken), + dispatcher: this.dispatcher }) ).text() @@ -163,7 +167,13 @@ export default class Soundcloud implements Streamer { url = url.replace('//m.', '//') // getting the IDs and track authorization - const html = await (await fetch(url, { method: 'get', headers: headers() })).text() + const html = await ( + await fetch(url, { + method: 'get', + headers: headers(this.oauthToken), + dispatcher: this.dispatcher + }) + ).text() switch (type) { case 'track': { @@ -177,7 +187,8 @@ export default class Soundcloud implements Streamer { await ( await fetch(this.#formatURL(naked, client), { method: 'get', - headers: headers(this.oauthToken) + headers: headers(this.oauthToken), + dispatcher: this.dispatcher }) ).text() ) @@ -248,7 +259,8 @@ export default class Soundcloud implements Streamer { await ( await fetch(this.#formatURL(`https://api-v2.soundcloud.com/tracks/${id}`, client), { method: 'get', - headers: headers(this.oauthToken) + headers: headers(this.oauthToken), + dispatcher: this.dispatcher }) ).text() ) @@ -265,7 +277,8 @@ export default class Soundcloud implements Streamer { ), { method: 'get', - headers: headers(this.oauthToken) + headers: headers(this.oauthToken), + dispatcher: this.dispatcher } ) ).json() diff --git a/src/streamers/tidal/main.ts b/src/streamers/tidal/main.ts index 53d83a2..085b1f4 100644 --- a/src/streamers/tidal/main.ts +++ b/src/streamers/tidal/main.ts @@ -1,4 +1,4 @@ -import { fetch } from 'undici' +import { Dispatcher, fetch } from 'undici' import { spawn } from 'child_process' import os from 'node:os' import fs from 'node:fs' @@ -32,6 +32,7 @@ interface TidalOptions { refreshToken: string expires: number countryCode: string + dispatcher?: Dispatcher } interface LoginData { @@ -71,6 +72,7 @@ export default class Tidal implements Streamer { expires: number countryCode: string userId: number | undefined + dispatcher: Dispatcher | undefined hostnames = ['tidal.com', 'www.tidal.com', 'listen.tidal.com'] testData = { 'https://tidal.com/browse/artist/3908662': { @@ -96,6 +98,7 @@ export default class Tidal implements Streamer { this.refreshToken = options.refreshToken this.expires = options.expires this.countryCode = options.countryCode + if (options.dispatcher) this.dispatcher = options.dispatcher const getReady = async () => { if (!this.refreshToken) return @@ -130,7 +133,8 @@ export default class Tidal implements Streamer { const response = await fetch( `${base}${url}?${new URLSearchParams(<{ [key: string]: string }>params)}`, { - headers: this.headers() + headers: this.headers(), + dispatcher: this.dispatcher } ) if (!response.ok) { @@ -156,13 +160,15 @@ export default class Tidal implements Streamer { } async sessionValid() { const resp = await fetch('https://api.tidal.com/v1/sessions', { - headers: this.headers() + headers: this.headers(), + dispatcher: this.dispatcher }) return resp.ok } async getCountryCode() { const sessionResponse = await fetch('https://api.tidal.com/v1/sessions', { - headers: this.headers() + headers: this.headers(), + dispatcher: this.dispatcher }) if (sessionResponse.status != 200) return false const sessionData = await sessionResponse.json() @@ -176,7 +182,8 @@ export default class Tidal implements Streamer { body: new URLSearchParams({ client_id: this.tvToken, scope: 'r_usr w_usr' - }) + }), + dispatcher: this.dispatcher }) if (deviceAuthResponse.status != 200) throw new Error(`Couldn't authorize Tidal`) interface DeviceAuth { @@ -199,7 +206,8 @@ export default class Tidal implements Streamer { await new Promise((r) => setTimeout(r, 1000)) const loginResponse = await fetch(`${TIDAL_AUTH_BASE}oauth2/token`, { method: 'post', - body: new URLSearchParams(params) + body: new URLSearchParams(params), + dispatcher: this.dispatcher }) statusCode = loginResponse.status loginData = await loginResponse.json() @@ -235,7 +243,8 @@ export default class Tidal implements Streamer { client_id: this.tvToken, client_secret: this.tvSecret, grant_type: 'refresh_token' - }) + }), + dispatcher: this.dispatcher }) if (refreshResponse.status == 200) { @@ -350,7 +359,7 @@ export default class Tidal implements Streamer { if (playbackInfoResponse.manifestMimeType != 'application/dash+xml') { const manifest = JSON.parse(manifestStr) - const streamResponse = await fetch(manifest.urls[0]) + const streamResponse = await fetch(manifest.urls[0], { dispatcher: this.dispatcher }) return { mimeType: manifest.mimeType, sizeBytes: parseInt(streamResponse.headers.get('Content-Length')), @@ -500,7 +509,8 @@ export default class Tidal implements Streamer { if (this.userId == undefined || this.countryCode == undefined) { if (Date.now() > this.expires) await this.refresh() const sessionResponse = await fetch('https://api.tidal.com/v1/sessions', { - headers: this.headers() + headers: this.headers(), + dispatcher: this.dispatcher }) const sessionData = await sessionResponse.json() From b842872d0bfb3a3d408722e59fcad56e413b186b Mon Sep 17 00:00:00 2001 From: aria Date: Mon, 5 Aug 2024 01:04:23 -0400 Subject: [PATCH 02/36] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1499b61..2d2e7f5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-23", + "version": "2.0.0-24", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", From 847ba0ec3098841f3c2331d6afd2e30f910649d3 Mon Sep 17 00:00:00 2001 From: uh wot Date: Wed, 7 Aug 2024 01:32:55 +0200 Subject: [PATCH 03/36] add deezer session renewal --- src/streamers/deezer/main.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/streamers/deezer/main.ts b/src/streamers/deezer/main.ts index 2a71983..d0f7d8f 100644 --- a/src/streamers/deezer/main.ts +++ b/src/streamers/deezer/main.ts @@ -100,6 +100,10 @@ export default class Deezer implements StreamerWithLogin { method: T, data: { [key: string]: string | number | string[] } = {} ): Promise { + // sid + checkForm renewal + if (method != 'deezer.getUserData' && method != 'user.getArl' && this.#isSessionExpired()) + await this.#apiCall('deezer.getUserData') + let apiToken = this.apiToken if (method == 'deezer.getUserData' || method == 'user.getArl') apiToken = '' @@ -168,6 +172,10 @@ export default class Deezer implements StreamerWithLogin { return userData } + #isSessionExpired() { + return Date.now() - (this.renewTimestamp ?? 0) >= 3600 * 1000 + } + #md5(str: string) { return createHash('md5').update(str).digest('hex') } @@ -428,7 +436,7 @@ export default class Deezer implements StreamerWithLogin { trackTokenExpiry: number, format: DeezerFormat ): Promise { - if (Date.now() - (this.renewTimestamp ?? 0) >= 3600 * 1000) + if (this.#isSessionExpired()) // renew license token await this.#apiCall('deezer.getUserData') From f917f0a868c5807362594766f6504aab236dace7 Mon Sep 17 00:00:00 2001 From: aria Date: Thu, 8 Aug 2024 17:54:57 -0400 Subject: [PATCH 04/36] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2d2e7f5..c6ef7ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-24", + "version": "2.0.0-25", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", From c9c15f98b4e6dcb8efc1607dbdb69ab0d99a073a Mon Sep 17 00:00:00 2001 From: aria Date: Mon, 12 Aug 2024 19:43:21 -0400 Subject: [PATCH 05/36] bump librespot & lucida version --- package.json | 4 ++-- pnpm-lock.yaml | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index c6ef7ee..ac4a343 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-25", + "version": "2.0.0-26", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", @@ -36,7 +36,7 @@ "dependencies": { "blowfish-cbc": "^1.0.1", "image-size": "^1.1.1", - "librespot": "^0.2.4", + "librespot": "^0.2.5", "undici": "^6.19.4", "xmldom-qsa": "^1.1.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a5855a9..d12985a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 librespot: - specifier: ^0.2.4 - version: 0.2.4 + specifier: ^0.2.5 + version: 0.2.5 undici: specifier: ^6.19.4 version: 6.19.4 @@ -464,8 +464,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - librespot@0.2.4: - resolution: {integrity: sha512-Ufx/8x2lOALfh/BvtuLf8plSrH+t9oEMXxj330YhjzJfvZMibyhKsZUYVPWeb47J/MRtHNAHeaRxZUTVkt+HJg==} + librespot@0.2.5: + resolution: {integrity: sha512-xGqLMYzWGdyDXabWZzmH7av2HZiiza1HW6SAtROcxxvXjpPw3cglgIPMiG/ccCS8jZZuf5kTuHgCHOlfF0Jm5g==} locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -1135,7 +1135,7 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - librespot@0.2.4: + librespot@0.2.5: dependencies: fast-xml-parser: 4.3.4 protobufjs: 7.2.6 From 43216bb2f2474ba3ec36f689dbb59dea1c2ec7b0 Mon Sep 17 00:00:00 2001 From: aria Date: Mon, 12 Aug 2024 23:44:10 -0400 Subject: [PATCH 06/36] add on.soundcloud.com support, bump version --- package.json | 2 +- src/streamers/soundcloud/main.ts | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ac4a343..d609e88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-26", + "version": "2.0.0-27", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", diff --git a/src/streamers/soundcloud/main.ts b/src/streamers/soundcloud/main.ts index e90b528..d121ff1 100644 --- a/src/streamers/soundcloud/main.ts +++ b/src/streamers/soundcloud/main.ts @@ -57,7 +57,7 @@ interface SoundCloudSubscriptionData { } export default class Soundcloud implements Streamer { - hostnames = ['soundcloud.com', 'm.soundcloud.com', 'www.soundcloud.com'] + hostnames = ['soundcloud.com', 'm.soundcloud.com', 'www.soundcloud.com', 'on.soundcloud.com'] testData = { 'https://soundcloud.com/saoirsedream/charlikartlanparty': { type: 'track', @@ -144,6 +144,9 @@ export default class Soundcloud implements Streamer { } async getByUrl(url: string): Promise { + const { hostname } = new URL(url) + + if (hostname == 'on.soundcloud.com') url = await followRedirect(url) return await this.#getMetadata(url) } @@ -355,3 +358,12 @@ async function getStream( } } } + +async function followRedirect(url: string) { + const res = await fetch(url, { redirect: 'manual' }) + const location = res.headers.get('Location') + + if (res.status != 302 || !location) throw new Error('URL not supported') + + return location +} From dfdecafc1fd2758a8b4d1956cc324a0d9db0be8a Mon Sep 17 00:00:00 2001 From: aria Date: Tue, 13 Aug 2024 13:48:29 -0400 Subject: [PATCH 07/36] bump librespot, and version --- package.json | 4 ++-- pnpm-lock.yaml | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index d609e88..c0679f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-27", + "version": "2.0.0-28", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", @@ -36,7 +36,7 @@ "dependencies": { "blowfish-cbc": "^1.0.1", "image-size": "^1.1.1", - "librespot": "^0.2.5", + "librespot": "^0.2.7", "undici": "^6.19.4", "xmldom-qsa": "^1.1.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d12985a..ab9d79e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 librespot: - specifier: ^0.2.5 - version: 0.2.5 + specifier: ^0.2.7 + version: 0.2.7 undici: specifier: ^6.19.4 version: 6.19.4 @@ -464,8 +464,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - librespot@0.2.5: - resolution: {integrity: sha512-xGqLMYzWGdyDXabWZzmH7av2HZiiza1HW6SAtROcxxvXjpPw3cglgIPMiG/ccCS8jZZuf5kTuHgCHOlfF0Jm5g==} + librespot@0.2.7: + resolution: {integrity: sha512-xHphLPxoW75P7iPqVF8mtsbcKxnuV3yEj4OWmGcnGzq1HohMifUaEVKlYPGWz7er4p0aCom39pDKQnf9UrkguQ==} locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -1135,7 +1135,7 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - librespot@0.2.5: + librespot@0.2.7: dependencies: fast-xml-parser: 4.3.4 protobufjs: 7.2.6 From 64ed4d9d0e29f6b7e3ba8e197ac412d8a9356290 Mon Sep 17 00:00:00 2001 From: uh wot Date: Tue, 13 Aug 2024 22:49:16 +0200 Subject: [PATCH 08/36] fix deezer cookies being bigger on every renew --- src/streamers/deezer/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/streamers/deezer/main.ts b/src/streamers/deezer/main.ts index d0f7d8f..db9f78a 100644 --- a/src/streamers/deezer/main.ts +++ b/src/streamers/deezer/main.ts @@ -138,7 +138,7 @@ export default class Deezer implements StreamerWithLogin { if (method == 'deezer.getUserData') { const setCookie = req.headers.get('Set-Cookie') ?? '' const sid = setCookie.match(/sid=(fr[0-9a-f]+)/)![1] - this.headers['Cookie'] += `arl=${this.arl}; sid=${sid}` + this.headers['Cookie'] = `arl=${this.arl}; sid=${sid}` const res = results From f184c90c5d49a55523d1801c84c65a2a9756537d Mon Sep 17 00:00:00 2001 From: uh wot Date: Tue, 13 Aug 2024 23:45:53 +0200 Subject: [PATCH 09/36] use session renewal logic from deezer webclient --- src/streamers/deezer/main.ts | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/streamers/deezer/main.ts b/src/streamers/deezer/main.ts index d0f7d8f..aeb10be 100644 --- a/src/streamers/deezer/main.ts +++ b/src/streamers/deezer/main.ts @@ -84,7 +84,6 @@ export default class Deezer implements StreamerWithLogin { arl?: string apiToken?: string licenseToken?: string - renewTimestamp?: number country?: string language?: string dispatcher?: Dispatcher | undefined @@ -98,12 +97,9 @@ export default class Deezer implements StreamerWithLogin { async #apiCall( method: T, - data: { [key: string]: string | number | string[] } = {} + data: { [key: string]: string | number | string[] } = {}, + doSessionRenewal = true ): Promise { - // sid + checkForm renewal - if (method != 'deezer.getUserData' && method != 'user.getArl' && this.#isSessionExpired()) - await this.#apiCall('deezer.getUserData') - let apiToken = this.apiToken if (method == 'deezer.getUserData' || method == 'user.getArl') apiToken = '' @@ -131,7 +127,17 @@ export default class Deezer implements StreamerWithLogin { if (error.constructor.name == 'Object') { const [type, msg] = Object.entries(error)[0] - if (type == 'VALID_TOKEN_REQUIRED') throw new Error('Invalid ARL') + + // session renewal + if ( + doSessionRenewal && + (type == 'VALID_TOKEN_REQUIRED' || type == 'NEED_USER_AUTH_REQUIRED') + ) { + const userData = await this.#apiCall('deezer.getUserData', {}, false) + if (userData.USER.USER_ID == 0) throw new Error('ARL expired') + return await this.#apiCall(method, data, false) + } + throw new Error(`API Error: ${type}\n${msg}`) } @@ -151,8 +157,6 @@ export default class Deezer implements StreamerWithLogin { this.availableFormats = new Set([DeezerFormat.MP3_128]) if (res?.USER?.OPTIONS?.web_hq) this.availableFormats.add(DeezerFormat.MP3_320) if (res?.USER?.OPTIONS?.web_lossless) this.availableFormats.add(DeezerFormat.FLAC) - - this.renewTimestamp = Date.now() } return results @@ -172,10 +176,6 @@ export default class Deezer implements StreamerWithLogin { return userData } - #isSessionExpired() { - return Date.now() - (this.renewTimestamp ?? 0) >= 3600 * 1000 - } - #md5(str: string) { return createHash('md5').update(str).digest('hex') } @@ -436,10 +436,6 @@ export default class Deezer implements StreamerWithLogin { trackTokenExpiry: number, format: DeezerFormat ): Promise { - if (this.#isSessionExpired()) - // renew license token - await this.#apiCall('deezer.getUserData') - if (Date.now() / 1000 - trackTokenExpiry >= 0) // renew track token trackToken = ( From 2d2bfb93db69c082145bb2f1ac392da4a1590940 Mon Sep 17 00:00:00 2001 From: aria Date: Thu, 15 Aug 2024 00:54:16 -0400 Subject: [PATCH 10/36] add isrc lookup to applicable services --- package.json | 2 +- src/index.ts | 9 +++++++++ src/streamers/deezer/main.ts | 10 ++++++++++ src/streamers/qobuz/main.ts | 8 ++++++++ src/streamers/spotify/main.ts | 8 +++++++- src/streamers/tidal/main.ts | 34 +++++++++++++++++++++++----------- src/types.ts | 1 + 7 files changed, 59 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index c0679f4..f53737c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-28", + "version": "2.0.0-29", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", diff --git a/src/index.ts b/src/index.ts index 9c4b6fd..be82ae1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -91,6 +91,15 @@ class Lucida { }) ) } + async isrcLookup(isrc: string) { + const results = await Promise.all( + Object.values(this.modules).map(async (e) => { + if (e.isrcLookup) return await e.isrcLookup(isrc) + }) + ) + const moduleNames = Object.keys(this.modules) + return Object.fromEntries(results.map((e, i) => [moduleNames[i], e])) + } } export default Lucida diff --git a/src/streamers/deezer/main.ts b/src/streamers/deezer/main.ts index d0f7d8f..4d4974c 100644 --- a/src/streamers/deezer/main.ts +++ b/src/streamers/deezer/main.ts @@ -520,4 +520,14 @@ export default class Deezer implements StreamerWithLogin { explicit: userData.USER.EXPLICIT_CONTENT_LEVEL != 'explicit_hide' } } + + async isrcLookup(isrc: string): Promise { + const resp = <{ type?: 'track'; link?: string }>( + await (await fetch(`https://api.deezer.com/track/isrc:${isrc}`)).json() + ) + if (resp.type == 'track' && resp.link) { + const track = (await this.getByUrl(resp.link)).metadata + return track + } else throw new Error(`Not available on Deezer.`) + } } diff --git a/src/streamers/qobuz/main.ts b/src/streamers/qobuz/main.ts index a9fc7d9..54ea7e5 100644 --- a/src/streamers/qobuz/main.ts +++ b/src/streamers/qobuz/main.ts @@ -300,4 +300,12 @@ export default class Qobuz implements StreamerWithLogin { explicit: true } } + async isrcLookup(isrc: string): Promise { + const isrcUrl = (await this.search(isrc)).tracks?.[0]?.url + if (!isrcUrl) throw new Error(`Not available on Qobuz.`) + else { + const track = (await this.getByUrl(isrcUrl)).metadata + return track + } + } } diff --git a/src/streamers/spotify/main.ts b/src/streamers/spotify/main.ts index 7c5f517..96b4b76 100644 --- a/src/streamers/spotify/main.ts +++ b/src/streamers/spotify/main.ts @@ -5,7 +5,8 @@ import { ItemType, SearchResults, StreamerAccount, - StreamerWithLogin + StreamerWithLogin, + Track } from '../../types.js' class Spotify implements StreamerWithLogin { @@ -134,6 +135,11 @@ class Spotify implements StreamerWithLogin { tracks: results.tracks?.map((e) => parseTrack(e)) ?? [] } } + async isrcLookup(isrc: string): Promise { + const results = await this.search(`isrc:${isrc}`) + if (results?.tracks[0]) return (await this.getByUrl(results.tracks?.[0]?.url)).metadata + else throw new Error(`Not available on Spotify.`) + } async getAccountInfo(): Promise { const info = await this.client.get.me() diff --git a/src/streamers/tidal/main.ts b/src/streamers/tidal/main.ts index 085b1f4..6beec31 100644 --- a/src/streamers/tidal/main.ts +++ b/src/streamers/tidal/main.ts @@ -64,6 +64,24 @@ interface SubscriptionData { paymentOverdue: boolean } +interface RawSearchResults { + albums: { + items: RawAlbum[] + } + artists: { + items: RawArtist[] + } + tracks: { + items: RawTrack[] + } +} + +interface RawIsrcLookup { + limit: number + offset: number + items: RawTrack[] +} + export default class Tidal implements Streamer { tvToken: string tvSecret: string @@ -116,6 +134,11 @@ export default class Tidal implements Streamer { 'User-Agent': 'TIDAL_ANDROID/1039 okhttp/3.14.9' } } + async isrcLookup(isrc: string): Promise { + const isrcQuery = await this.#get('tracks', { isrc }) + if (isrcQuery?.items?.[0]) return (await this.getByUrl(isrcQuery.items[0].url)).metadata + else throw new Error(`Not available on Tidal.`) + } async #get( url: string, params: { [key: string]: string | number } = {}, @@ -257,17 +280,6 @@ export default class Tidal implements Streamer { return false } async search(query: string, limit = 20): Promise { - interface RawSearchResults { - albums: { - items: RawAlbum[] - } - artists: { - items: RawArtist[] - } - tracks: { - items: RawTrack[] - } - } const results = await this.#get('search/top-hits', { query: query, limit: limit, diff --git a/src/types.ts b/src/types.ts index 8ea2c9e..4df61b0 100644 --- a/src/types.ts +++ b/src/types.ts @@ -149,6 +149,7 @@ export interface Streamer { hostnames: string[] testData?: StreamerTestData search(query: string, limit: number): Promise + isrcLookup?(isrc: string): Promise getTypeFromUrl(url: string): Promise getByUrl: | ((url: string) => Promise) From f5fcb04b0af00ed8962d9d756e35e205b16656ff Mon Sep 17 00:00:00 2001 From: aria Date: Sat, 17 Aug 2024 01:01:16 -0400 Subject: [PATCH 11/36] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f53737c..0489290 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-29", + "version": "2.0.0-30", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", From e1ea9bcc6b2588c6e92a92e380cb8ec84103edee Mon Sep 17 00:00:00 2001 From: aria Date: Sat, 17 Aug 2024 01:54:01 -0400 Subject: [PATCH 12/36] add total track count --- package.json | 2 +- src/streamers/deezer/main.ts | 2 +- src/streamers/qobuz/main.ts | 2 +- src/streamers/tidal/main.ts | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 0489290..eb75d5c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-30", + "version": "2.0.0-31", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", diff --git a/src/streamers/deezer/main.ts b/src/streamers/deezer/main.ts index 7d91438..7928c0e 100644 --- a/src/streamers/deezer/main.ts +++ b/src/streamers/deezer/main.ts @@ -308,7 +308,7 @@ export default class Deezer implements StreamerWithLogin { }) const data = { - metadata: parseAlbum(DATA), + metadata: { ...parseAlbum(DATA), trackCount: SONGS.data.length }, tracks: SONGS.data.map(parseTrack) } diff --git a/src/streamers/qobuz/main.ts b/src/streamers/qobuz/main.ts index 54ea7e5..aa54b1f 100644 --- a/src/streamers/qobuz/main.ts +++ b/src/streamers/qobuz/main.ts @@ -207,7 +207,7 @@ export default class Qobuz implements StreamerWithLogin { app_id: this.appId }) return { - metadata: parseAlbum(albumResponse), + metadata: { ...parseAlbum(albumResponse), trackCount: albumResponse.tracks?.items.length }, tracks: albumResponse.tracks?.items.map(parseTrack) } } diff --git a/src/streamers/tidal/main.ts b/src/streamers/tidal/main.ts index 6beec31..6b3a6fd 100644 --- a/src/streamers/tidal/main.ts +++ b/src/streamers/tidal/main.ts @@ -505,10 +505,11 @@ export default class Tidal implements Streamer { metadata: await this.#getTrack(id) } case 'album': + const tracks = await this.#getAlbumTracks(id) return { type, - tracks: await this.#getAlbumTracks(id), - metadata: await this.#getAlbum(id) + tracks: tracks, + metadata: { ...(await this.#getAlbum(id)), trackCount: tracks.length } } case 'artist': return { From 0aac14a3f3958ae70ccec0215fd81b237ae48922 Mon Sep 17 00:00:00 2001 From: aria Date: Sat, 17 Aug 2024 01:55:56 -0400 Subject: [PATCH 13/36] add track count to other services --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index eb75d5c..4d8f427 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-31", + "version": "2.0.0-32", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", From 34fba212d25c6f160515c4d758820b77ade476fb Mon Sep 17 00:00:00 2001 From: uh wot Date: Mon, 19 Aug 2024 18:16:37 +0200 Subject: [PATCH 14/36] qobuz: fallback to album artist if track has missing performer yes, that's a thing. wtf man https://open.qobuz.com/track/571707 --- src/streamers/qobuz/parse.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/streamers/qobuz/parse.ts b/src/streamers/qobuz/parse.ts index 66adb63..96910ff 100644 --- a/src/streamers/qobuz/parse.ts +++ b/src/streamers/qobuz/parse.ts @@ -111,12 +111,16 @@ export interface RawTrack { } export function parseTrack(raw: RawTrack): Track { + const artists = [] + const artist = raw.performer ?? raw.album?.artist + if (artist) artists.push(parseArtist(artist)) + let track: Track = { title: raw.version ? `${raw.title} (${raw.version})` : raw.title, id: raw.id.toString(), url: `https://play.qobuz.com/track/${raw.id.toString()}`, copyright: raw.copyright, - artists: [parseArtist(raw.performer)], + artists, durationMs: raw.duration * 1000, explicit: raw.parental_warning, isrc: raw.isrc, From 923e5f4240d981f753e3e45c7d16be67dcd412e7 Mon Sep 17 00:00:00 2001 From: uh wot Date: Mon, 19 Aug 2024 18:18:26 +0200 Subject: [PATCH 15/36] bump librespot version --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 4d8f427..852d0a1 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "dependencies": { "blowfish-cbc": "^1.0.1", "image-size": "^1.1.1", - "librespot": "^0.2.7", + "librespot": "^0.2.8", "undici": "^6.19.4", "xmldom-qsa": "^1.1.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ab9d79e..fdb358c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 librespot: - specifier: ^0.2.7 - version: 0.2.7 + specifier: ^0.2.8 + version: 0.2.8 undici: specifier: ^6.19.4 version: 6.19.4 @@ -464,8 +464,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - librespot@0.2.7: - resolution: {integrity: sha512-xHphLPxoW75P7iPqVF8mtsbcKxnuV3yEj4OWmGcnGzq1HohMifUaEVKlYPGWz7er4p0aCom39pDKQnf9UrkguQ==} + librespot@0.2.8: + resolution: {integrity: sha512-HwBEod6kkoPV+W5qwRuu0GKDFEW8eNqtRYuuhlgE8rVIkO3Epb7mmYaVi5qKiTDuee7UFtax/6WbANiNOnL/cQ==} locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -1135,7 +1135,7 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - librespot@0.2.7: + librespot@0.2.8: dependencies: fast-xml-parser: 4.3.4 protobufjs: 7.2.6 From 44d79f83f1a6179cbc3dbff159c8f089f539afb6 Mon Sep 17 00:00:00 2001 From: aria Date: Tue, 20 Aug 2024 01:28:39 -0400 Subject: [PATCH 16/36] bump lucida version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 852d0a1..2f44ec6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-32", + "version": "2.0.0-33", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", From 832d718b3df20e4a5cbd3765361cd2f8e67bba6d Mon Sep 17 00:00:00 2001 From: uh wot Date: Wed, 21 Aug 2024 17:30:28 +0200 Subject: [PATCH 17/36] add await to spotify login lmfao --- src/streamers/spotify/main.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/streamers/spotify/main.ts b/src/streamers/spotify/main.ts index 96b4b76..0a99408 100644 --- a/src/streamers/spotify/main.ts +++ b/src/streamers/spotify/main.ts @@ -30,8 +30,8 @@ class Spotify implements StreamerWithLogin { constructor(options: LibrespotOptions) { this.client = new Librespot(options) } - login(username: string, password: string) { - return this.client.login(username, password) + async login(username: string, password: string) { + return await this.client.login(username, password) } #getUrlParts(url: string): ['artist' | 'album' | 'track' | 'episode' | 'show', string] { const urlObj = new URL(url) From 2488c27ba611774edb0606ce42642703f20457c3 Mon Sep 17 00:00:00 2001 From: aria Date: Thu, 22 Aug 2024 01:34:03 -0400 Subject: [PATCH 18/36] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2f44ec6..91fe804 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-33", + "version": "2.0.0-34", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", From 6cbe870f91d631ae80e619f646ff7009affc1889 Mon Sep 17 00:00:00 2001 From: uh wot Date: Fri, 23 Aug 2024 01:43:07 +0200 Subject: [PATCH 19/36] soundcloud: correct ffmpeg container argument for mp3 --- src/streamers/soundcloud/main.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/streamers/soundcloud/main.ts b/src/streamers/soundcloud/main.ts index d121ff1..10a28a9 100644 --- a/src/streamers/soundcloud/main.ts +++ b/src/streamers/soundcloud/main.ts @@ -350,7 +350,8 @@ async function getStream( stream: Readable.fromWeb(streamResp.body!) } } else { - const container = transcoding.format.mime_type.split('/')[1].split(';')[0].split('+')[0] + let container = transcoding.format.mime_type.split('/')[1].split(';')[0].split('+')[0] + if (container == 'mpeg') container = 'mp3' return { mimeType: transcoding.format.mime_type, From a69dbe288fbd8d64759af31b37b1d4ee7d1c0207 Mon Sep 17 00:00:00 2001 From: uh wot Date: Mon, 2 Sep 2024 20:07:02 +0200 Subject: [PATCH 20/36] bump librespot version --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 91fe804..2943d0d 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "dependencies": { "blowfish-cbc": "^1.0.1", "image-size": "^1.1.1", - "librespot": "^0.2.8", + "librespot": "^0.2.9", "undici": "^6.19.4", "xmldom-qsa": "^1.1.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fdb358c..b75f2f5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 librespot: - specifier: ^0.2.8 - version: 0.2.8 + specifier: ^0.2.9 + version: 0.2.9 undici: specifier: ^6.19.4 version: 6.19.4 @@ -464,8 +464,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - librespot@0.2.8: - resolution: {integrity: sha512-HwBEod6kkoPV+W5qwRuu0GKDFEW8eNqtRYuuhlgE8rVIkO3Epb7mmYaVi5qKiTDuee7UFtax/6WbANiNOnL/cQ==} + librespot@0.2.9: + resolution: {integrity: sha512-Y4PrB1t1OcsgEQUU902FNIyBqVGphXhIwF1DR0KHWZ7JXXrGxySk2FNCAgdgINV7d/HD6q5Jd03W59JQ6Jw/Lg==} locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -1135,7 +1135,7 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - librespot@0.2.8: + librespot@0.2.9: dependencies: fast-xml-parser: 4.3.4 protobufjs: 7.2.6 From 1352d88c7f02bdec696ce82a95c9ea50abb7137c Mon Sep 17 00:00:00 2001 From: uh wot Date: Mon, 2 Sep 2024 20:16:58 +0200 Subject: [PATCH 21/36] eslint pls shut up --- src/streamers/tidal/main.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/streamers/tidal/main.ts b/src/streamers/tidal/main.ts index 6b3a6fd..c51db85 100644 --- a/src/streamers/tidal/main.ts +++ b/src/streamers/tidal/main.ts @@ -505,6 +505,7 @@ export default class Tidal implements Streamer { metadata: await this.#getTrack(id) } case 'album': + // eslint-disable-next-line no-case-declarations const tracks = await this.#getAlbumTracks(id) return { type, From da4964c7749ad713a157d7d161e34536e23ca5ef Mon Sep 17 00:00:00 2001 From: aria Date: Mon, 2 Sep 2024 15:06:11 -0400 Subject: [PATCH 22/36] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2943d0d..3064b2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-34", + "version": "2.0.0-35", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", From 019b167583ddbe5219bb1fc0f05f248a28d5c19d Mon Sep 17 00:00:00 2001 From: uh wot Date: Tue, 3 Sep 2024 15:15:18 +0200 Subject: [PATCH 23/36] bump librespot version again --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 3064b2b..945711c 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "dependencies": { "blowfish-cbc": "^1.0.1", "image-size": "^1.1.1", - "librespot": "^0.2.9", + "librespot": "^0.2.10", "undici": "^6.19.4", "xmldom-qsa": "^1.1.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b75f2f5..8074915 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 librespot: - specifier: ^0.2.9 - version: 0.2.9 + specifier: ^0.2.10 + version: 0.2.10 undici: specifier: ^6.19.4 version: 6.19.4 @@ -464,8 +464,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - librespot@0.2.9: - resolution: {integrity: sha512-Y4PrB1t1OcsgEQUU902FNIyBqVGphXhIwF1DR0KHWZ7JXXrGxySk2FNCAgdgINV7d/HD6q5Jd03W59JQ6Jw/Lg==} + librespot@0.2.10: + resolution: {integrity: sha512-yyeqIERbRHYJ4wvsiMNX2s4ewr/Zi3fwDdy68d3VtrthHZAL3x9ObiY2oOgPbUzx3/EsuWyiahRpADDEqe2aZw==} locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -1135,7 +1135,7 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - librespot@0.2.9: + librespot@0.2.10: dependencies: fast-xml-parser: 4.3.4 protobufjs: 7.2.6 From e84c9a69a82f43429f4948dcbded286851862a53 Mon Sep 17 00:00:00 2001 From: aria Date: Tue, 3 Sep 2024 14:56:39 -0400 Subject: [PATCH 24/36] fix private track extraction --- src/streamers/soundcloud/main.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/streamers/soundcloud/main.ts b/src/streamers/soundcloud/main.ts index 10a28a9..457988f 100644 --- a/src/streamers/soundcloud/main.ts +++ b/src/streamers/soundcloud/main.ts @@ -180,7 +180,14 @@ export default class Soundcloud implements Streamer { switch (type) { case 'track': { - const trackId = html.split(`"soundcloud://sounds:`)?.[1]?.split(`">`)?.[0] + let trackId = html.split('"soundcloud://sounds:')?.[1]?.split('">')?.[0] + if (!trackId) + trackId = html + .split( + 'content="https://w.soundcloud.com/player/?url=https%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F' + )?.[1] + ?.split('%3F')[0] + if (!trackId) throw new Error('Could not extract track ID.') let naked = `https://api-v2.soundcloud.com/tracks/${trackId}` const path = new URL(url).pathname From 433aa37b8b2916c59199c10e2df5686f0cac6e64 Mon Sep 17 00:00:00 2001 From: aria Date: Tue, 3 Sep 2024 14:57:06 -0400 Subject: [PATCH 25/36] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 945711c..b957bf6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-35", + "version": "2.0.0-36", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", From 52ab7f0b3746b94d858b402a9f95ecc7c1a208c5 Mon Sep 17 00:00:00 2001 From: aria Date: Tue, 3 Sep 2024 17:07:34 -0400 Subject: [PATCH 26/36] fix stream ripping private tracks --- src/streamers/soundcloud/main.ts | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/streamers/soundcloud/main.ts b/src/streamers/soundcloud/main.ts index 457988f..992ef42 100644 --- a/src/streamers/soundcloud/main.ts +++ b/src/streamers/soundcloud/main.ts @@ -212,7 +212,8 @@ export default class Soundcloud implements Streamer { api.media.transcodings, api.track_authorization, client, - this.oauthToken + this.oauthToken, + path.split('/')[3] ) }, metadata: await parseTrack(api) @@ -261,7 +262,7 @@ export default class Soundcloud implements Streamer { } } default: - throw `Type "${type}" not supported.` + throw new Error(`Type "${type}" not supported.`) } } async #getRawTrackInfo(id: number | string, client: ScClient) { @@ -329,7 +330,8 @@ async function getStream( transcodings: Array, trackAuth: string, client: ScClient, - oauthToken?: string | undefined + oauthToken?: string | undefined, + secretToken?: string | undefined ): Promise { let filter = transcodings.filter((x) => x.quality == 'hq') if (hq == true && filter.length == 0) throw new Error('Could not find HQ format.') @@ -338,14 +340,15 @@ async function getStream( if (filter.length == 0) filter = transcodings.filter((x) => x.preset.startsWith('mp3_')) // then mp3 if (filter.length == 0) filter = transcodings.filter((x) => x.preset.startsWith('opus_')) // then opus if (filter.length == 0) throw new Error('Could not find applicable format.') // and this is just in case none of those exist - const transcoding = filter[0] - const streamUrlResp = await fetch( - `${transcoding.url}?client_id=${client.id}&track_authorization=${trackAuth}`, - { - headers: headers(oauthToken) - } - ) + + let streamUrl = new URL(transcoding.url) + streamUrl.searchParams.append('client_id', client?.id) + streamUrl.searchParams.append('track_authorization', trackAuth) + + const streamUrlResp = await fetch(streamUrl.toString(), { + headers: headers(oauthToken) + }) const json = <{ url: string }>await streamUrlResp.json() if (!json.url) throw new Error('Stream URL could not be retreieved.') From 243be434618e5a73c8b40888e9dca3643beea8f7 Mon Sep 17 00:00:00 2001 From: aria Date: Tue, 3 Sep 2024 17:08:17 -0400 Subject: [PATCH 27/36] fix errors, bump version --- package.json | 2 +- src/streamers/soundcloud/main.ts | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index b957bf6..6fa024b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-36", + "version": "2.0.0-37", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", diff --git a/src/streamers/soundcloud/main.ts b/src/streamers/soundcloud/main.ts index 992ef42..7fdf7f4 100644 --- a/src/streamers/soundcloud/main.ts +++ b/src/streamers/soundcloud/main.ts @@ -212,8 +212,7 @@ export default class Soundcloud implements Streamer { api.media.transcodings, api.track_authorization, client, - this.oauthToken, - path.split('/')[3] + this.oauthToken ) }, metadata: await parseTrack(api) @@ -330,8 +329,7 @@ async function getStream( transcodings: Array, trackAuth: string, client: ScClient, - oauthToken?: string | undefined, - secretToken?: string | undefined + oauthToken?: string | undefined ): Promise { let filter = transcodings.filter((x) => x.quality == 'hq') if (hq == true && filter.length == 0) throw new Error('Could not find HQ format.') @@ -343,7 +341,7 @@ async function getStream( const transcoding = filter[0] let streamUrl = new URL(transcoding.url) - streamUrl.searchParams.append('client_id', client?.id) + if (client?.id) streamUrl.searchParams.append('client_id', client?.id) streamUrl.searchParams.append('track_authorization', trackAuth) const streamUrlResp = await fetch(streamUrl.toString(), { From 4de85f42ee74a1ecf038af0b3d78baf1d452b2a8 Mon Sep 17 00:00:00 2001 From: uh wot Date: Thu, 5 Sep 2024 01:05:12 +0200 Subject: [PATCH 28/36] bump librespot version --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 6fa024b..12b8d86 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "dependencies": { "blowfish-cbc": "^1.0.1", "image-size": "^1.1.1", - "librespot": "^0.2.10", + "librespot": "^0.2.11", "undici": "^6.19.4", "xmldom-qsa": "^1.1.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8074915..2dcb24d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 librespot: - specifier: ^0.2.10 - version: 0.2.10 + specifier: ^0.2.11 + version: 0.2.11 undici: specifier: ^6.19.4 version: 6.19.4 @@ -464,8 +464,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - librespot@0.2.10: - resolution: {integrity: sha512-yyeqIERbRHYJ4wvsiMNX2s4ewr/Zi3fwDdy68d3VtrthHZAL3x9ObiY2oOgPbUzx3/EsuWyiahRpADDEqe2aZw==} + librespot@0.2.11: + resolution: {integrity: sha512-WAbqvBCqiyutBSC+3rxIsIJcsFcb7l9fyAHVtvPLh3qHyIimV4jqN46GkLgJDASzTuNK9F6v3yG6EQcSh0Zn8Q==} locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -1135,7 +1135,7 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - librespot@0.2.10: + librespot@0.2.11: dependencies: fast-xml-parser: 4.3.4 protobufjs: 7.2.6 From ef983da16b272c8623ea0543960f118f17bb637c Mon Sep 17 00:00:00 2001 From: uh wot Date: Thu, 5 Sep 2024 01:08:21 +0200 Subject: [PATCH 29/36] fix eslint error --- src/streamers/soundcloud/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/streamers/soundcloud/main.ts b/src/streamers/soundcloud/main.ts index 7fdf7f4..70d8d29 100644 --- a/src/streamers/soundcloud/main.ts +++ b/src/streamers/soundcloud/main.ts @@ -340,7 +340,7 @@ async function getStream( if (filter.length == 0) throw new Error('Could not find applicable format.') // and this is just in case none of those exist const transcoding = filter[0] - let streamUrl = new URL(transcoding.url) + const streamUrl = new URL(transcoding.url) if (client?.id) streamUrl.searchParams.append('client_id', client?.id) streamUrl.searchParams.append('track_authorization', trackAuth) From 911eac80dbc17963b04d1d0f83dba6f656d291dd Mon Sep 17 00:00:00 2001 From: aria Date: Wed, 4 Sep 2024 20:19:24 -0400 Subject: [PATCH 30/36] bump librespot --- package.json | 4 ++-- pnpm-lock.yaml | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 6fa024b..0c8bd08 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-37", + "version": "2.0.0-38", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", @@ -36,7 +36,7 @@ "dependencies": { "blowfish-cbc": "^1.0.1", "image-size": "^1.1.1", - "librespot": "^0.2.10", + "librespot": "^0.2.11", "undici": "^6.19.4", "xmldom-qsa": "^1.1.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8074915..2dcb24d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 librespot: - specifier: ^0.2.10 - version: 0.2.10 + specifier: ^0.2.11 + version: 0.2.11 undici: specifier: ^6.19.4 version: 6.19.4 @@ -464,8 +464,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - librespot@0.2.10: - resolution: {integrity: sha512-yyeqIERbRHYJ4wvsiMNX2s4ewr/Zi3fwDdy68d3VtrthHZAL3x9ObiY2oOgPbUzx3/EsuWyiahRpADDEqe2aZw==} + librespot@0.2.11: + resolution: {integrity: sha512-WAbqvBCqiyutBSC+3rxIsIJcsFcb7l9fyAHVtvPLh3qHyIimV4jqN46GkLgJDASzTuNK9F6v3yG6EQcSh0Zn8Q==} locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -1135,7 +1135,7 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - librespot@0.2.10: + librespot@0.2.11: dependencies: fast-xml-parser: 4.3.4 protobufjs: 7.2.6 From b72c8de2195b531ce02800cee31dda191611b22c Mon Sep 17 00:00:00 2001 From: uh wot Date: Thu, 5 Sep 2024 22:22:14 +0200 Subject: [PATCH 31/36] bump librespot, add stored creds login to spotify --- package.json | 2 +- pnpm-lock.yaml | 18 +++++++++++++----- src/streamers/spotify/main.ts | 12 ++++++++++-- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 0c8bd08..a32fa7f 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "dependencies": { "blowfish-cbc": "^1.0.1", "image-size": "^1.1.1", - "librespot": "^0.2.11", + "librespot": "^0.2.12", "undici": "^6.19.4", "xmldom-qsa": "^1.1.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2dcb24d..d2e3006 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 librespot: - specifier: ^0.2.11 - version: 0.2.11 + specifier: ^0.2.12 + version: 0.2.12 undici: specifier: ^6.19.4 version: 6.19.4 @@ -464,8 +464,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - librespot@0.2.11: - resolution: {integrity: sha512-WAbqvBCqiyutBSC+3rxIsIJcsFcb7l9fyAHVtvPLh3qHyIimV4jqN46GkLgJDASzTuNK9F6v3yG6EQcSh0Zn8Q==} + librespot@0.2.12: + resolution: {integrity: sha512-c3/bikWtgu64S2zWjiKXM4xs2YfsodpZGtHhpQ6fLqqw414rvO85NcwPnadh6GRHdYeSE4z8k5qF4n9rBeQAow==} locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -658,6 +658,9 @@ packages: resolution: {integrity: sha512-i3uaEUwNdkRq2qtTRRJb13moW5HWqviu7Vl7oYRYz++uPtGHJj+x7TGjcEuwS5Mt2P4nA0U9dhIX3DdB6JGY0g==} engines: {node: '>=18.17'} + unplayplay@1.0.0: + resolution: {integrity: sha512-ukQX79Ze9I4+gZARvyQY36ZRkkoFrzvDZmzL39DCODvFjRARVjo+hD/azDBkIa3b73tmd8hKMszrQzfi7hi+SQ==} + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -1135,12 +1138,13 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - librespot@0.2.11: + librespot@0.2.12: dependencies: fast-xml-parser: 4.3.4 protobufjs: 7.2.6 shannon-bindings: 0.1.0 undici: 5.28.3 + unplayplay: 1.0.0 locate-path@6.0.0: dependencies: @@ -1305,6 +1309,10 @@ snapshots: undici@6.19.4: {} + unplayplay@1.0.0: + dependencies: + node-addon-api: 8.1.0 + uri-js@4.4.1: dependencies: punycode: 2.3.1 diff --git a/src/streamers/spotify/main.ts b/src/streamers/spotify/main.ts index 0a99408..d9cd8a0 100644 --- a/src/streamers/spotify/main.ts +++ b/src/streamers/spotify/main.ts @@ -9,6 +9,10 @@ import { Track } from '../../types.js' +interface SpotifyOptions extends LibrespotOptions { + storedCredential?: boolean +} + class Spotify implements StreamerWithLogin { client: Librespot hostnames = ['open.spotify.com'] @@ -27,11 +31,15 @@ class Spotify implements StreamerWithLogin { } } as const - constructor(options: LibrespotOptions) { + storedCredential: boolean + + constructor(options: SpotifyOptions) { this.client = new Librespot(options) + this.storedCredential = options.storedCredential == true } async login(username: string, password: string) { - return await this.client.login(username, password) + if (this.storedCredential) return await this.client.loginWithStoredCreds(username, password) + else return await this.client.login(username, password) } #getUrlParts(url: string): ['artist' | 'album' | 'track' | 'episode' | 'show', string] { const urlObj = new URL(url) From 822d173ce3d4b39a6c6aa6b60fd30157544b6048 Mon Sep 17 00:00:00 2001 From: uh wot Date: Thu, 5 Sep 2024 23:00:07 +0200 Subject: [PATCH 32/36] bump librespot again lololol --- package.json | 2 +- pnpm-lock.yaml | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index a32fa7f..8ef90e0 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "dependencies": { "blowfish-cbc": "^1.0.1", "image-size": "^1.1.1", - "librespot": "^0.2.12", + "librespot": "^0.2.13", "undici": "^6.19.4", "xmldom-qsa": "^1.1.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d2e3006..7c2ece2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 librespot: - specifier: ^0.2.12 - version: 0.2.12 + specifier: ^0.2.13 + version: 0.2.13 undici: specifier: ^6.19.4 version: 6.19.4 @@ -464,8 +464,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - librespot@0.2.12: - resolution: {integrity: sha512-c3/bikWtgu64S2zWjiKXM4xs2YfsodpZGtHhpQ6fLqqw414rvO85NcwPnadh6GRHdYeSE4z8k5qF4n9rBeQAow==} + librespot@0.2.13: + resolution: {integrity: sha512-+olkx5BerGEMHK/facYWy7tZH4MzLEVw65ETs8xRc54fNtPl+Xzuxi3igo59iSGbReACXIJqHt31rM7+1+3JbQ==} locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -658,8 +658,8 @@ packages: resolution: {integrity: sha512-i3uaEUwNdkRq2qtTRRJb13moW5HWqviu7Vl7oYRYz++uPtGHJj+x7TGjcEuwS5Mt2P4nA0U9dhIX3DdB6JGY0g==} engines: {node: '>=18.17'} - unplayplay@1.0.0: - resolution: {integrity: sha512-ukQX79Ze9I4+gZARvyQY36ZRkkoFrzvDZmzL39DCODvFjRARVjo+hD/azDBkIa3b73tmd8hKMszrQzfi7hi+SQ==} + unplayplay@1.0.1: + resolution: {integrity: sha512-n9GC445z1V2ar4467bg0CFWTZasjFgRupw6MV7Ol2oa1Drudl2YvIhJypl9laHgITJIll9zQN5ItjPkor71kWw==} uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -1138,13 +1138,13 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - librespot@0.2.12: + librespot@0.2.13: dependencies: fast-xml-parser: 4.3.4 protobufjs: 7.2.6 shannon-bindings: 0.1.0 undici: 5.28.3 - unplayplay: 1.0.0 + unplayplay: 1.0.1 locate-path@6.0.0: dependencies: @@ -1309,7 +1309,7 @@ snapshots: undici@6.19.4: {} - unplayplay@1.0.0: + unplayplay@1.0.1: dependencies: node-addon-api: 8.1.0 From d465e5f11e4bdf5b14e02fa1d84a1b687ad5c8c0 Mon Sep 17 00:00:00 2001 From: uh wot Date: Thu, 5 Sep 2024 23:26:38 +0200 Subject: [PATCH 33/36] bump librespot: the third sequel --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 8ef90e0..0e791c0 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "dependencies": { "blowfish-cbc": "^1.0.1", "image-size": "^1.1.1", - "librespot": "^0.2.13", + "librespot": "^0.2.14", "undici": "^6.19.4", "xmldom-qsa": "^1.1.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7c2ece2..0606fa6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 librespot: - specifier: ^0.2.13 - version: 0.2.13 + specifier: ^0.2.14 + version: 0.2.14 undici: specifier: ^6.19.4 version: 6.19.4 @@ -464,8 +464,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - librespot@0.2.13: - resolution: {integrity: sha512-+olkx5BerGEMHK/facYWy7tZH4MzLEVw65ETs8xRc54fNtPl+Xzuxi3igo59iSGbReACXIJqHt31rM7+1+3JbQ==} + librespot@0.2.14: + resolution: {integrity: sha512-kl8nPF2KNg6y8LKl/qKOobN0vFeX03NQqJDdCiZSC3N133Dee4SNkmpMZOFOFktWqueToe0M4MmhNpDvmuwavw==} locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -1138,7 +1138,7 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - librespot@0.2.13: + librespot@0.2.14: dependencies: fast-xml-parser: 4.3.4 protobufjs: 7.2.6 From c413de924c6599bf87b9ccf95b3b12465a379e06 Mon Sep 17 00:00:00 2001 From: aria Date: Thu, 5 Sep 2024 19:03:44 -0400 Subject: [PATCH 34/36] update librespot, bump vers (2) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0e791c0..3de37e8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-38", + "version": "2.0.0-39", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", From 0fa3bde17756af95cdc57a44cd23f01458ca6a71 Mon Sep 17 00:00:00 2001 From: shoenko Date: Thu, 5 Sep 2024 20:38:30 -0400 Subject: [PATCH 35/36] Add lyrics type --- src/types.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index 4df61b0..7e15822 100644 --- a/src/types.ts +++ b/src/types.ts @@ -9,6 +9,18 @@ export interface CoverArtwork { height: number } +export interface Lyrics { + id: Id + source: string + lines?: LyricLine[] +} + +export interface LyricLine { + text: string + startTimeMs?: number + endTimeMs?: number +} + export interface Artist { id: Id url: string @@ -53,10 +65,11 @@ export interface Track { album?: Album durationMs?: number coverArtwork?: CoverArtwork[] + lyrics?: Lyrics genres?: string[] releaseDate?: Date - regions?: string[] description?: string + regions?: string[] } export interface Episode { From 16949400afebe1e9a538ba332844634e31b09dda Mon Sep 17 00:00:00 2001 From: aria Date: Thu, 5 Sep 2024 21:47:41 -0400 Subject: [PATCH 36/36] update librespot, bump version --- package.json | 4 ++-- pnpm-lock.yaml | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 3de37e8..a447534 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-39", + "version": "2.0.0-40", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", @@ -36,7 +36,7 @@ "dependencies": { "blowfish-cbc": "^1.0.1", "image-size": "^1.1.1", - "librespot": "^0.2.14", + "librespot": "^0.2.15", "undici": "^6.19.4", "xmldom-qsa": "^1.1.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0606fa6..4f49703 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 librespot: - specifier: ^0.2.14 - version: 0.2.14 + specifier: ^0.2.15 + version: 0.2.15 undici: specifier: ^6.19.4 version: 6.19.4 @@ -464,8 +464,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - librespot@0.2.14: - resolution: {integrity: sha512-kl8nPF2KNg6y8LKl/qKOobN0vFeX03NQqJDdCiZSC3N133Dee4SNkmpMZOFOFktWqueToe0M4MmhNpDvmuwavw==} + librespot@0.2.15: + resolution: {integrity: sha512-k8/qd7xWZ+eOGUmX4jevRS79+uMjisIeXzfeXc0roxUhJgRDzGYbGVblovy6378NR9OdoQtBhXts7k7uvgmF5g==} locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -658,8 +658,8 @@ packages: resolution: {integrity: sha512-i3uaEUwNdkRq2qtTRRJb13moW5HWqviu7Vl7oYRYz++uPtGHJj+x7TGjcEuwS5Mt2P4nA0U9dhIX3DdB6JGY0g==} engines: {node: '>=18.17'} - unplayplay@1.0.1: - resolution: {integrity: sha512-n9GC445z1V2ar4467bg0CFWTZasjFgRupw6MV7Ol2oa1Drudl2YvIhJypl9laHgITJIll9zQN5ItjPkor71kWw==} + unplayplay@1.0.2: + resolution: {integrity: sha512-93aGwcNPyWpIhro6HCWqtWZ0mlurpcpVU2ODSYZCI1PhWGKrJfe7oOF4AKVuVK74YFLYlW3JVzl6Vw1Bck2Vpg==} uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -1138,13 +1138,13 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - librespot@0.2.14: + librespot@0.2.15: dependencies: fast-xml-parser: 4.3.4 protobufjs: 7.2.6 shannon-bindings: 0.1.0 undici: 5.28.3 - unplayplay: 1.0.1 + unplayplay: 1.0.2 locate-path@6.0.0: dependencies: @@ -1309,7 +1309,7 @@ snapshots: undici@6.19.4: {} - unplayplay@1.0.1: + unplayplay@1.0.2: dependencies: node-addon-api: 8.1.0