chore: remove NetEase lyrics fallback from Android and web
NetEase returned wrong/unsynced results. lrclib with exact + fuzzy search is sufficient; no third-party Chinese platform needed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
eb5b0ea360
commit
0272b9e99f
2 files changed
+2
-68
No files matched your search
@@ -10,7 +10,6 @@ import io.ktor.http.*
|
|||||||
import io.ktor.serialization.kotlinx.json.*
|
import io.ktor.serialization.kotlinx.json.*
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.coroutineScope
|
import kotlinx.coroutines.coroutineScope
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
@@ -26,16 +25,6 @@ data class LrcLibResponse(
|
|||||||
val syncedLyrics: String? = null,
|
val syncedLyrics: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
|
||||||
private data class NetEaseSearchResp(val result: NetEaseResult? = null, val code: Int = 0)
|
|
||||||
@Serializable
|
|
||||||
private data class NetEaseResult(val songs: List<NetEaseSong> = emptyList())
|
|
||||||
@Serializable
|
|
||||||
private data class NetEaseSong(val id: Long = 0, val duration: Long = 0)
|
|
||||||
@Serializable
|
|
||||||
private data class NetEaseLyricsResp(val lrc: NetEaseLrc? = null, val code: Int = 0)
|
|
||||||
@Serializable
|
|
||||||
private data class NetEaseLrc(val lyric: String? = null)
|
|
||||||
|
|
||||||
data class LrcLine(val timeMs: Long, val text: String)
|
data class LrcLine(val timeMs: Long, val text: String)
|
||||||
|
|
||||||
@@ -115,15 +104,8 @@ object LrcLibClient {
|
|||||||
?: bestMatch(titleDef.await(), durationSecs)
|
?: bestMatch(titleDef.await(), durationSecs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lrclibResult != null) return lrclibResult.also { cache[cacheKey] = it }
|
cache[cacheKey] = lrclibResult
|
||||||
|
return lrclibResult
|
||||||
// 4. NetEase fallback
|
|
||||||
val neLrc = withTimeoutOrNull(8_000) {
|
|
||||||
runCatching { netEaseLyrics(artist, title, durationSecs) }.getOrNull()
|
|
||||||
}
|
|
||||||
val result = if (!neLrc.isNullOrBlank()) LrcLibResponse(syncedLyrics = neLrc) else null
|
|
||||||
cache[cacheKey] = result
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun LrcLibResponse?.hasContent() =
|
private fun LrcLibResponse?.hasContent() =
|
||||||
@@ -142,28 +124,4 @@ object LrcLibClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun netEaseLyrics(artist: String, title: String, durationSecs: Int?): String? {
|
|
||||||
val search = client.get("https://music.163.com/api/search/get") {
|
|
||||||
parameter("s", "$artist $title".trim())
|
|
||||||
parameter("type", 1)
|
|
||||||
parameter("limit", 5)
|
|
||||||
header("Referer", "https://music.163.com")
|
|
||||||
}.body<NetEaseSearchResp>()
|
|
||||||
|
|
||||||
val songs = search.result?.songs ?: return null
|
|
||||||
val song = if (durationSecs != null && durationSecs > 0) {
|
|
||||||
val durMs = durationSecs * 1000L
|
|
||||||
songs.minByOrNull { kotlin.math.abs(it.duration - durMs) }
|
|
||||||
?.takeIf { kotlin.math.abs(it.duration - durMs) <= 5000L }
|
|
||||||
?: songs.firstOrNull()
|
|
||||||
} else songs.firstOrNull() ?: return null
|
|
||||||
|
|
||||||
return client.get("https://music.163.com/api/song/lyric") {
|
|
||||||
parameter("id", song!!.id)
|
|
||||||
parameter("lv", 1)
|
|
||||||
parameter("kv", 1)
|
|
||||||
parameter("tv", -1)
|
|
||||||
header("Referer", "https://music.163.com")
|
|
||||||
}.body<NetEaseLyricsResp>().lrc?.lyric?.takeIf { it.isNotBlank() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -204,30 +204,6 @@ async function _loadNpLyrics(songId) {
|
|||||||
|
|
||||||
if(token !== _lyricsLoadToken) return;
|
if(token !== _lyricsLoadToken) return;
|
||||||
|
|
||||||
// NetEase fallback — good for Asian/Japanese music
|
|
||||||
if(!result?.syncedLyrics && !result?.plainLyrics) {
|
|
||||||
try {
|
|
||||||
const q = encodeURIComponent(`${artist} ${title}`.trim());
|
|
||||||
const sd = await safeJson(fetch(`https://music.163.com/api/search/get?s=${q}&type=1&limit=5`, {
|
|
||||||
headers: { Referer: 'https://music.163.com' }, signal: SIG(),
|
|
||||||
}));
|
|
||||||
const songs = sd?.result?.songs || [];
|
|
||||||
const durMs = dur * 1000;
|
|
||||||
const song = dur
|
|
||||||
? [...songs].sort((a, b) => Math.abs(a.duration - durMs) - Math.abs(b.duration - durMs))
|
|
||||||
.find(s => Math.abs(s.duration - durMs) <= 5000)
|
|
||||||
: songs[0];
|
|
||||||
if(song && token === _lyricsLoadToken) {
|
|
||||||
const ld = await safeJson(fetch(
|
|
||||||
`https://music.163.com/api/song/lyric?id=${song.id}&lv=1&kv=1&tv=-1`,
|
|
||||||
{ headers: { Referer: 'https://music.163.com' }, signal: SIG() },
|
|
||||||
));
|
|
||||||
const lrc = ld?.lrc?.lyric;
|
|
||||||
if(lrc) result = { syncedLyrics: lrc };
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(token !== _lyricsLoadToken) return;
|
if(token !== _lyricsLoadToken) return;
|
||||||
_lyricsCache.set(cacheKey, result ?? null);
|
_lyricsCache.set(cacheKey, result ?? null);
|
||||||
content.innerHTML = '';
|
content.innerHTML = '';
|
||||||
|
|||||||
Reference in new issue
Block a user