瀏覽代碼

ref: remove advancedLyricsFilter feature

Sv443 8 月之前
父節點
當前提交
c9b2664095
共有 6 個文件被更改,包括 96 次插入95 次删除
  1. 1 0
      changelog.md
  2. 3 2
      src/config.ts
  3. 75 0
      src/dev/snippets/lyricsFuzzyFilter.ts
  4. 10 10
      src/features/index.ts
  5. 5 81
      src/features/lyrics.ts
  6. 2 2
      src/types.ts

+ 1 - 0
changelog.md

@@ -24,6 +24,7 @@
   - Added Shift and Ctrl modifier keys to the above-queue buttons that can skip prompts or customize the behavior
   - Arrow key and number key skipping works more reliably and now also in the config menu
   - Removed broken feature "remove upgrade tab"
+  - Removed unnecessary experimental feature "advancedLyricsFilter" as the API's native search improved a lot
 
 <details><summary>Click to expand internal and plugin changes</summary>
 

+ 3 - 2
src/config.ts

@@ -1,4 +1,4 @@
-import { DataStore, compress, type DataMigrationsDict, decompress } from "@sv443-network/userutils";
+import { DataStore, compress, type DataMigrationsDict, decompress, type LooseUnion } from "@sv443-network/userutils";
 import { disableBeforeUnload, featInfo } from "./features/index.js";
 import { compressionSupported, error, getVideoTime, info, log, t } from "./utils/index.js";
 import { emitSiteEvent } from "./siteEvents.js";
@@ -86,6 +86,7 @@ export const migrations: DataMigrationsDict = {
       ],
     );
     "removeUpgradeTab" in newData && delete newData.removeUpgradeTab;
+    "advancedLyricsFilter" in newData && delete newData.advancedLyricsFilter;
     return newData;
   },
 
@@ -98,7 +99,7 @@ export const migrations: DataMigrationsDict = {
 } as const satisfies DataMigrationsDict;
 
 /** Uses the default config as the base, then overwrites all values with the passed {@linkcode baseData}, then sets all passed {@linkcode resetKeys} to their default values */
-function useDefaultConfig(baseData: Partial<FeatureConfig> | undefined, resetKeys: (keyof typeof featInfo)[]): FeatureConfig {
+function useDefaultConfig(baseData: Partial<FeatureConfig> | undefined, resetKeys: LooseUnion<keyof typeof featInfo>[]): FeatureConfig {
   const newData = { ...defaultData, ...(baseData ?? {}) };
   for(const key of resetKeys) // @ts-ignore
     newData[key] = featInfo?.[key]?.default as never; // typescript funny moments

+ 75 - 0
src/dev/snippets/lyricsFuzzyFilter.ts

@@ -0,0 +1,75 @@
+// comes from pre-v2.2 in "src/features/lyrics.ts"
+// for the deprecated feature "advancedLyricsFilter"
+
+
+const exactish = (input: string) => input.toLowerCase()
+  .replace(/[\s\-_&,.()[\]]+/gm, "");
+
+// exact-ish matches, best matching one first
+const exactishResults = [...allResultsSan].sort((a, b) => {
+  const aTitleScore = exactish(a.meta.title).localeCompare(exactish(song));
+  const bTitleScore = exactish(b.meta.title).localeCompare(exactish(song));
+  const aArtistScore = exactish(a.meta.primaryArtist.name).localeCompare(exactish(artist));
+  const bArtistScore = exactish(b.meta.primaryArtist.name).localeCompare(exactish(artist));
+
+  return aTitleScore + aArtistScore - bTitleScore - bArtistScore;
+});
+
+// use fuse.js for fuzzy match
+// search song title and artist separately, then combine the scores
+const titleFuse = new Fuse([...allResultsSan], {
+  keys: ["title"],
+  includeScore: true,
+  threshold: 0.4,
+});
+
+const artistFuse = new Fuse([...allResultsSan], {
+  keys: ["primaryArtist.name"],
+  includeScore: true,
+  threshold: 0.4,
+});
+
+let fuzzyResults: typeof allResultsSan = allResultsSan.map(r => {
+  const titleRes = titleFuse.search(r.meta.title);
+  const artistRes = artistFuse.search(r.meta.primaryArtist.name);
+
+  const titleScore = titleRes[0]?.score ?? 0;
+  const artistScore = artistRes[0]?.score ?? 0;
+
+  return {
+    ...r,
+    score: titleScore + artistScore,
+  };
+});
+// I love TS
+fuzzyResults = (fuzzyResults as (typeof allResultsSan[0] & { score: number })[])
+  .map(({ score, ...rest }) => rest as typeof allResultsSan[0]);
+
+const hasExactMatch = exactishResults.slice(0, 3).find(r => exactish(r.meta.title) === exactish(fuzzyResults[0].meta.title) && exactish(r.meta.primaryArtist.name) === exactish(fuzzyResults[0].meta.primaryArtist.name));
+const finalResults = [
+  ...(
+    hasExactMatch
+      ? [fuzzyResults[0], ...allResultsSan.filter(r => r.url !== fuzzyResults[0].url)]
+      : [...allResultsSan]
+  ),
+].slice(0, 5);
+
+// add top 3 results to the cache with a penalty to their time to live
+// so every entry is deleted faster if it's not considered as relevant
+finalResults.slice(0, 3).forEach(({ meta: { artists, title }, url }, i) => {
+  const penaltyFraction = hasExactMatch
+  // if there's an exact match, give it 0 penalty and penalize all other results with the full value
+    ? i === 0 ? 0 : 1
+  // if there's no exact match, penalize all results with a fraction of the full penalty since they're more likely to be unrelated
+    : 0.6;
+  addLyricsCacheEntryPenalized(sanitizeArtists(artists), sanitizeSong(title), url, penaltyFraction);
+});
+
+finalResults.length > 0 && log("Found", finalResults.length, "lyrics", autoPlural("URL", finalResults), "in", Date.now() - startTs, "ms:", finalResults);
+
+// returns search results sorted by relevance
+return finalResults.map(r => ({
+  artist: r.meta.primaryArtist.name,
+  song: r.meta.title,
+  url: r.url,
+}));

+ 10 - 10
src/features/index.ts

@@ -598,16 +598,16 @@ export const featInfo = {
     advanced: true,
     textAdornment: adornments.advanced,
   },
-  advancedLyricsFilter: {
-    type: "toggle",
-    category: "lyrics",
-    default: false,
-    change: () => setTimeout(() => confirm(t("lyrics_cache_changed_clear_confirm")) && clearLyricsCache(), 200),
-    advanced: true,
-    textAdornment: adornments.experimental,
-    reloadRequired: false,
-    enable: noop,
-  },
+  // advancedLyricsFilter: {
+  //   type: "toggle",
+  //   category: "lyrics",
+  //   default: false,
+  //   change: () => setTimeout(() => confirm(t("lyrics_cache_changed_clear_confirm")) && clearLyricsCache(), 200),
+  //   advanced: true,
+  //   textAdornment: adornments.experimental,
+  //   reloadRequired: false,
+  //   enable: noop,
+  // },
 
   //#region general
   locale: {

+ 5 - 81
src/features/lyrics.ts

@@ -1,10 +1,9 @@
-import { autoPlural, fetchAdvanced } from "@sv443-network/userutils";
-import Fuse from "fuse.js";
+import { fetchAdvanced } from "@sv443-network/userutils";
 import { error, getResourceUrl, info, log, warn, t, tp, currentMediaType, constructUrl, onInteraction, openInTab } from "../utils/index.js";
 import { emitInterface } from "../interface.js";
 import { mode, scriptInfo } from "../constants.js";
 import { getFeature } from "../config.js";
-import { addLyricsCacheEntryBest, addLyricsCacheEntryPenalized, getLyricsCacheEntry } from "./lyricsCache.js";
+import { addLyricsCacheEntryBest, getLyricsCacheEntry } from "./lyricsCache.js";
 import type { LyricsCacheEntry } from "../types.js";
 import { addSelectorListener } from "../observers.js";
 
@@ -220,7 +219,6 @@ export async function fetchLyricsUrls(artist: string, song: string): Promise<Omi
       return [cacheEntry];
     }
 
-    const startTs = Date.now();
     const fetchUrl = constructUrl(`${getFeature("geniUrlBase")}/search`, {
       disableFuzzy: null,
       utm_source: `${scriptInfo.name} v${scriptInfo.version}${mode === "development" ? "-pre" : ""}`,
@@ -283,84 +281,10 @@ export async function fetchLyricsUrls(artist: string, song: string): Promise<Omi
         url,
       }));
 
-    if(!getFeature("advancedLyricsFilter")) {
-      const topRes = allResultsSan[0];
-      topRes && addLyricsCacheEntryBest(topRes.meta.artists, topRes.meta.title, topRes.url);
+    const topRes = allResultsSan[0];
+    topRes && addLyricsCacheEntryBest(topRes.meta.artists, topRes.meta.title, topRes.url);
 
-      return allResultsSan.map(r => ({
-        artist: r.meta.primaryArtist.name,
-        song: r.meta.title,
-        url: r.url,
-      }));
-    }
-    
-    const exactish = (input: string) => input.toLowerCase()
-      .replace(/[\s\-_&,.()[\]]+/gm, "");
-
-    // exact-ish matches, best matching one first
-    const exactishResults = [...allResultsSan].sort((a, b) => {
-      const aTitleScore = exactish(a.meta.title).localeCompare(exactish(song));
-      const bTitleScore = exactish(b.meta.title).localeCompare(exactish(song));
-      const aArtistScore = exactish(a.meta.primaryArtist.name).localeCompare(exactish(artist));
-      const bArtistScore = exactish(b.meta.primaryArtist.name).localeCompare(exactish(artist));
-
-      return aTitleScore + aArtistScore - bTitleScore - bArtistScore;
-    });
-
-    // use fuse.js for fuzzy match
-    // search song title and artist separately, then combine the scores
-    const titleFuse = new Fuse([...allResultsSan], {
-      keys: ["title"],
-      includeScore: true,
-      threshold: 0.4,
-    });
-
-    const artistFuse = new Fuse([...allResultsSan], {
-      keys: ["primaryArtist.name"],
-      includeScore: true,
-      threshold: 0.4,
-    });
-
-    let fuzzyResults: typeof allResultsSan = allResultsSan.map(r => {
-      const titleRes = titleFuse.search(r.meta.title);
-      const artistRes = artistFuse.search(r.meta.primaryArtist.name);
-
-      const titleScore = titleRes[0]?.score ?? 0;
-      const artistScore = artistRes[0]?.score ?? 0;
-
-      return {
-        ...r,
-        score: titleScore + artistScore,
-      };
-    });
-    // I love TS
-    fuzzyResults = (fuzzyResults as (typeof allResultsSan[0] & { score: number })[])
-      .map(({ score, ...rest }) => rest as typeof allResultsSan[0]);
-
-    const hasExactMatch = exactishResults.slice(0, 3).find(r => exactish(r.meta.title) === exactish(fuzzyResults[0].meta.title) && exactish(r.meta.primaryArtist.name) === exactish(fuzzyResults[0].meta.primaryArtist.name));
-    const finalResults = [
-      ...(
-        hasExactMatch
-          ? [fuzzyResults[0], ...allResultsSan.filter(r => r.url !== fuzzyResults[0].url)]
-          : [...allResultsSan]
-      ),
-    ].slice(0, 5);
-
-    // add top 3 results to the cache with a penalty to their time to live
-    // so every entry is deleted faster if it's not considered as relevant
-    finalResults.slice(0, 3).forEach(({ meta: { artists, title }, url }, i) => {
-      const penaltyFraction = hasExactMatch
-        // if there's an exact match, give it 0 penalty and penalize all other results with the full value
-        ? i === 0 ? 0 : 1
-        // if there's no exact match, penalize all results with a fraction of the full penalty since they're more likely to be unrelated
-        : 0.6;
-      addLyricsCacheEntryPenalized(sanitizeArtists(artists), sanitizeSong(title), url, penaltyFraction);
-    });
-
-    finalResults.length > 0 && log("Found", finalResults.length, "lyrics", autoPlural("URL", finalResults), "in", Date.now() - startTs, "ms:", finalResults);
-
-    // returns search results sorted by relevance
-    return finalResults.map(r => ({
+    return allResultsSan.map(r => ({
       artist: r.meta.primaryArtist.name,
       song: r.meta.title,
       url: r.url,

+ 2 - 2
src/types.ts

@@ -562,8 +562,8 @@ export interface FeatureConfig {
   lyricsCacheTTL: number;
   /** Button to clear lyrics cache */
   clearLyricsCache: undefined;
-  /** Whether to use advanced filtering when searching for lyrics (exact, exact-ish) */
-  advancedLyricsFilter: boolean;
+  // /** Whether to use advanced filtering when searching for lyrics (exact, exact-ish) */
+  // advancedLyricsFilter: boolean;
 
   //#region misc
   /** The locale to use for translations */