From 399967c2d74d7bf73da7e1073bc4e6f71a5ab529 Mon Sep 17 00:00:00 2001 From: Lseoksee Date: Mon, 12 Aug 2024 17:08:20 +0900 Subject: [PATCH 1/3] popupLyrics add LRCLIB --- Extensions/popupLyrics.js | 64 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/Extensions/popupLyrics.js b/Extensions/popupLyrics.js index 0660d30634..28a22258f9 100644 --- a/Extensions/popupLyrics.js +++ b/Extensions/popupLyrics.js @@ -248,6 +248,65 @@ function PopupLyrics() { return { lyrics }; }, + + async fetchLrclib(info) { + const baseURL = "https://lrclib.net/api/get"; + const durr = info.duration / 1000; + const params = { + track_name: info.title, + artist_name: info.artist, + album_name: info.album, + duration: durr, + }; + + const finalURL = `${baseURL}?${Object.keys(params) + .map((key) => `${key}=${encodeURIComponent(params[key])}`) + .join("&")}`; + + const body = await fetch(finalURL, { + headers: { + "x-user-agent": `spicetify v${Spicetify.Config.version} (https://github.com/spicetify/cli)`, + }, + }); + + if (body.status !== 200) { + return { error: "Request error: Track wasn't found" }; + } + + const meta = await body.json(); + if (meta?.instrumental) { + return { error: "Instrumental" }; + } + if (!meta?.plainLyrics && !meta?.syncedLyrics) { + return { error: "No lyrics" }; + } + if (!meta?.syncedLyrics) { + return { error: "No synced lyrics" }; + } + + // Preprocess lyrics by removing [tags] and empty lines + const lines = meta?.syncedLyrics + .replaceAll(/\[[a-zA-Z]+:.+\]/g, "") + .trim() + .split("\n"); + + const syncedTimestamp = /\[([0-9:.]+)\]/; + const isSynced = lines[0].match(syncedTimestamp); + + const lyrics = lines.map((line) => { + const time = line.match(syncedTimestamp)?.[1]; + let lyricContent = line.replace(syncedTimestamp, "").trim(); + const lyric = lyricContent.replaceAll(/\<([0-9:.]+)\>/g, "").trim(); + const [min, sec] = time.replace(/\[\]\<\>/, "").split(":"); + + if (line.trim() !== "" && isSynced && time) { + return { text: lyric || "♪", startTime: Number(min) * 60 + Number(sec) }; + } + return; + }); + + return { lyrics }; + }, }; const userConfigs = { @@ -276,6 +335,11 @@ function PopupLyrics() { call: LyricProviders.fetchSpotify, desc: "Lyrics sourced from official Spotify API.", }, + lrclib: { + on: boolLocalStorage("popup-lyrics:services:lrclib:on"), + call: LyricProviders.fetchLrclib, + desc: "Lyrics sourced from lrclib.net. Supports both synced and unsynced lyrics. LRCLIB is a free and open-source lyrics provider.", + }, }, servicesOrder: [], }; From 4394b29955c5a60b72f84f013db0b6b6b118bd61 Mon Sep 17 00:00:00 2001 From: Lseoksee Date: Mon, 12 Aug 2024 17:14:51 +0900 Subject: [PATCH 2/3] biome --- Extensions/popupLyrics.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extensions/popupLyrics.js b/Extensions/popupLyrics.js index 28a22258f9..a2e80a583f 100644 --- a/Extensions/popupLyrics.js +++ b/Extensions/popupLyrics.js @@ -295,7 +295,7 @@ function PopupLyrics() { const lyrics = lines.map((line) => { const time = line.match(syncedTimestamp)?.[1]; - let lyricContent = line.replace(syncedTimestamp, "").trim(); + const lyricContent = line.replace(syncedTimestamp, "").trim(); const lyric = lyricContent.replaceAll(/\<([0-9:.]+)\>/g, "").trim(); const [min, sec] = time.replace(/\[\]\<\>/, "").split(":"); From 7fdc28f135fe7e2af1e665b85cfe9399b1b28dae Mon Sep 17 00:00:00 2001 From: Jeong Hyeon Date: Tue, 13 Aug 2024 09:19:57 +0900 Subject: [PATCH 3/3] Update Extensions/popupLyrics.js Co-authored-by: em --- Extensions/popupLyrics.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/Extensions/popupLyrics.js b/Extensions/popupLyrics.js index a2e80a583f..abde9ec914 100644 --- a/Extensions/popupLyrics.js +++ b/Extensions/popupLyrics.js @@ -277,9 +277,6 @@ function PopupLyrics() { if (meta?.instrumental) { return { error: "Instrumental" }; } - if (!meta?.plainLyrics && !meta?.syncedLyrics) { - return { error: "No lyrics" }; - } if (!meta?.syncedLyrics) { return { error: "No synced lyrics" }; }