Show lyric source and link
This commit is contained in:
1 parent
da525948ce
commit
e02752ab30
4 files changed
+29
-8
No files matched your search
+10
-8
@@ -11,14 +11,16 @@
|
||||
* "found": true|false,
|
||||
* "lyrics": "plain text\nwith newlines",
|
||||
* "synced": [{ "time": 12.34, "text": "…" }, …], // [] when unavailable
|
||||
* "url": "…"
|
||||
* "url": "…",
|
||||
* "source": "lrclib" | "dumb" | "genius"
|
||||
* }
|
||||
*
|
||||
* Lyrics are returned as plain text (tags/timestamps stripped) so the
|
||||
* front-end can render them with textContent — no HTML injection from a
|
||||
* third-party page. `synced` (line-level LRC timestamps, seconds) is only
|
||||
* populated when LRCLIB has synced lyrics; the Genius fallback has no timing
|
||||
* data so it's always [] there.
|
||||
* data so it's always [] there. `url` is '' for LRCLIB (the front-end only
|
||||
* shows a "source" link for dumb/genius).
|
||||
*
|
||||
* Note: the Genius fallback scrapes HTML, which can change at any time. If
|
||||
* Genius restructures their page the extraction may need updating.
|
||||
@@ -79,7 +81,7 @@ function lrclib_lyrics($artist, $title, $timeout) {
|
||||
|
||||
$lrc = lrclib_lyrics($artist, $title, $timeout);
|
||||
if ($lrc !== null) {
|
||||
json_out(['found' => true, 'lyrics' => $lrc['lyrics'], 'synced' => $lrc['synced'], 'url' => '']);
|
||||
json_out(['found' => true, 'lyrics' => $lrc['lyrics'], 'synced' => $lrc['synced'], 'url' => '', 'source' => 'lrclib']);
|
||||
}
|
||||
|
||||
/* -- dumb (Genius-API-free fallback) ----------------------------------------- */
|
||||
@@ -89,9 +91,9 @@ if (cfg('dumb.enabled')) {
|
||||
$song = dumb_song($path, $timeout);
|
||||
$url = cfg('dumb.url') . $path;
|
||||
if ($song === null || $song['lyrics'] === '') {
|
||||
json_out(['found' => false, 'lyrics' => '', 'synced' => [], 'url' => $url]);
|
||||
json_out(['found' => false, 'lyrics' => '', 'synced' => [], 'url' => $url, 'source' => 'dumb']);
|
||||
}
|
||||
json_out(['found' => true, 'lyrics' => $song['lyrics'], 'synced' => [], 'url' => $url]);
|
||||
json_out(['found' => true, 'lyrics' => $song['lyrics'], 'synced' => [], 'url' => $url, 'source' => 'dumb']);
|
||||
}
|
||||
|
||||
/* -- Genius (fallback) ------------------------------------------------------- */
|
||||
@@ -131,7 +133,7 @@ if ($pageUrl === '') json_out($empty);
|
||||
/* -- Scrape the lyric containers ------------------------------------------- */
|
||||
$page = http_get($pageUrl, $timeout);
|
||||
if ($page === null) {
|
||||
json_out(['found' => false, 'lyrics' => '', 'synced' => [], 'url' => $pageUrl]);
|
||||
json_out(['found' => false, 'lyrics' => '', 'synced' => [], 'url' => $pageUrl, 'source' => 'genius']);
|
||||
}
|
||||
|
||||
$marker = 'data-lyrics-container="true"';
|
||||
@@ -153,7 +155,7 @@ $lyrics = implode("\n", array_map('trim', explode("\n", $lyrics)));
|
||||
$lyrics = preg_replace("/\n{3,}/", "\n\n", $lyrics);
|
||||
|
||||
if ($lyrics === '') {
|
||||
json_out(['found' => false, 'lyrics' => '', 'synced' => [], 'url' => $pageUrl]);
|
||||
json_out(['found' => false, 'lyrics' => '', 'synced' => [], 'url' => $pageUrl, 'source' => 'genius']);
|
||||
}
|
||||
|
||||
json_out(['found' => true, 'lyrics' => $lyrics, 'synced' => [], 'url' => $pageUrl]);
|
||||
json_out(['found' => true, 'lyrics' => $lyrics, 'synced' => [], 'url' => $pageUrl, 'source' => 'genius']);
|
||||
@@ -227,6 +227,13 @@ audio[controls] { width: 100%; outline: 0; }
|
||||
.lyrics-line:hover, .lyrics-line:focus-visible { opacity: .85; outline: 0; }
|
||||
.lyrics-line.current { opacity: 1; font-weight: 700; }
|
||||
|
||||
.lyrics-source {
|
||||
display: block; margin-top: 14px;
|
||||
font-size: 0.75rem; opacity: .6; color: inherit;
|
||||
}
|
||||
.lyrics-source:hover, .lyrics-source:focus-visible { opacity: 1; text-decoration: underline; }
|
||||
.lyrics-source[hidden] { display: none; }
|
||||
|
||||
.lyrics-sync {
|
||||
position: absolute; top: 48px; right: 10px; z-index: 2;
|
||||
display: flex; align-items: center; gap: 6px;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
lyricsToggle: $('lyrics-toggle'),
|
||||
lyrics: $('lyrics'),
|
||||
lyricsLines: $('lyrics-lines'),
|
||||
lyricsSource: $('lyrics-source'),
|
||||
lyricsSync: $('lyrics-sync'),
|
||||
lyricsOffset: $('lyrics-offset'),
|
||||
historyBody: $('history-body'),
|
||||
@@ -719,6 +720,9 @@
|
||||
if (el.lyrics) el.lyrics.hidden = true;
|
||||
if (el.lyricsLines) el.lyricsLines.textContent = '';
|
||||
if (el.lyricsSync) el.lyricsSync.hidden = true;
|
||||
if (el.lyricsSource) el.lyricsSource.hidden = true;
|
||||
|
||||
var SOURCE_LABEL = { genius: 'Genius', dumb: 'dumb' };
|
||||
|
||||
var body = new URLSearchParams();
|
||||
body.set('artist', track.artist || '');
|
||||
@@ -741,6 +745,13 @@
|
||||
} else {
|
||||
el.lyricsLines.textContent = res.lyrics;
|
||||
}
|
||||
// No link for LRCLIB (its url is always ''); Genius/dumb link to the
|
||||
// page the lyrics were scraped from.
|
||||
if (el.lyricsSource && res.url && SOURCE_LABEL[res.source]) {
|
||||
el.lyricsSource.href = res.url;
|
||||
el.lyricsSource.textContent = 'Lyrics via ' + SOURCE_LABEL[res.source];
|
||||
el.lyricsSource.hidden = false;
|
||||
}
|
||||
el.lyricsToggle.hidden = false;
|
||||
})
|
||||
.catch(function () {});
|
||||
|
||||
@@ -41,6 +41,7 @@ $glassFx = $liquidGlass ? '<span class="glass-fx" aria-hidden="true"></spa
|
||||
</div>
|
||||
<div id="lyrics" class="lyrics" hidden>
|
||||
<div id="lyrics-lines" class="lyrics-lines"></div>
|
||||
<a id="lyrics-source" class="lyrics-source" href="" target="_blank" rel="noopener" hidden></a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user