Skip to content

Commit

Permalink
fix(lyrics-plus/netease): use PyNCMd API (#2508)
Browse files Browse the repository at this point in the history
  • Loading branch information
pan93412 authored Aug 12, 2023
1 parent 901c185 commit c2fffa2
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 14 deletions.
79 changes: 65 additions & 14 deletions CustomApps/lyrics-plus/ProviderNetease.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,77 @@
const ProviderNetease = (function () {
const requestHeader = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0"
};
/**
* @typedef {{
* result: {
* songs: {
* name: string,
* id: number,
* dt: number, // duration in ms
* al: { // album
* name: string,
* },
* }[],
* },
* }} SearchResponse
*
* @typedef {{
* title: string,
* artist: string,
* album: string,
* duration: number,
* }} Info
*/

async function findLyrics(info) {
const searchURL = `https://music.xianqiao.wang/neteaseapiv2/search?limit=10&type=1&keywords=`;
const lyricURL = `https://music.xianqiao.wang/neteaseapiv2/lyric?id=`;
const ProviderNetease = (function () {
/**
* Search with PyNCM api.
*
* @param {Info} info
* @throw "Cannot find track"
*/
async function search(info) {
const searchURL = `https://pyncmd.apis.imouto.in/api/pyncm?module=cloudsearch&method=GetSearchResult&keyword=`;

const cleanTitle = Utils.removeExtraInfo(Utils.removeSongFeat(Utils.normalize(info.title)));
const finalURL = searchURL + encodeURIComponent(`${cleanTitle} ${info.artist}`);

const searchResults = await CosmosAsync.get(finalURL, null, requestHeader);
/** @type {SearchResponse} */
const searchResults = await Spicetify.CosmosAsync.get(finalURL);
const items = searchResults.result.songs;
if (!items?.length) {
throw "Cannot find track";

// Find the best match.
for (const song of items) {
const expectedDuration = info.duration;
const actualDuration = song.dt;

// normalized expected album name
const neAlbumName = Utils.normalize(info.album);
const expectedAlbumName = Utils.containsHanCharacter(neAlbumName) ? await Utils.toSimplifiedChinese(neAlbumName) : neAlbumName;
const actualAlbumName = Utils.normalize(song.al.name); // usually in Simplified Chinese

if (actualAlbumName == expectedAlbumName || Math.abs(expectedDuration - actualDuration) < 1000) {
return song;
}
}

const album = Utils.capitalize(info.album);
let itemId = items.findIndex(val => Utils.capitalize(val.album.name) === album || Math.abs(info.duration - val.duration) < 1000);
if (itemId === -1) throw "Cannot find track";
throw "Cannot find track";
}

/**
* @param {Info} info
*
* @returns {{
* lrc: {
* lyric: string,
* klyric: undefined, // unimplemented
* },
* }}
*/
async function findLyrics(info) {
const lyricURL = `https://pyncmd.apis.imouto.in/api/pyncm?module=track&method=GetTrackLyrics&song_id=`;

const searchResponse = await search(info);
const songID = searchResponse.id;

return await CosmosAsync.get(lyricURL + items[itemId].id, null, requestHeader);
return CosmosAsync.get(lyricURL + songID);
}

const creditInfo = [
Expand Down
38 changes: 38 additions & 0 deletions CustomApps/lyrics-plus/Utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,44 @@ class Utils {
return result.replace(/\s+/g, " ").trim();
}

/**
* Check if the specified string contains Han character.
*
* @param {string} s
* @returns {boolean}
*/
static containsHanCharacter(s) {
const hanRegex = /\p{Script=Han}/u;
return hanRegex.test(s);
}

/**
* Singleton Translator instance for {@link toSimplifiedChinese}.
*
* @type {Translator | null}
*/
static #translator = null;

/**
* Convert all Han characters to Simplified Chinese.
*
* Choosing Simplified Chinese makes the converted result more accurate,
* as the conversion from SC to TC may have multiple possibilities,
* while the conversion from TC to SC usually has only one possibility.
*
* @param {string} s
* @returns {Promise<string>}
*/
static async toSimplifiedChinese(s) {
// create a singleton Translator instance
if (!Utils.#translator) {
Utils.#translator = new Translator("zh");
}

// translate it to Simplified Chinese
return Utils.#translator.convertChinese(s, "tw", "cn");
}

static removeSongFeat(s) {
return (
s
Expand Down

0 comments on commit c2fffa2

Please sign in to comment.