xref: /MusicFree/src/utils/getSimilarMusic.ts (revision 3991724e7964221aea8a8deb6f9ae34ada13af9d)
1*3991724eS猫头猫import PluginManager from '@/core/pluginManager';
2*3991724eS猫头猫import minDistance from './minDistance';
3*3991724eS猫头猫
4*3991724eS猫头猫/**
5*3991724eS猫头猫 *
6*3991724eS猫头猫 * @param musicItem 音乐类型
7*3991724eS猫头猫 * @param type 媒体类型
8*3991724eS猫头猫 * @param abortFunction 如果函数为true,则中断
9*3991724eS猫头猫 * @returns
10*3991724eS猫头猫 */
11*3991724eS猫头猫export default async function <T extends ICommon.SupportMediaType>(
12*3991724eS猫头猫    musicItem: IMusic.IMusicItem,
13*3991724eS猫头猫    type: T = 'music' as T,
14*3991724eS猫头猫    abortFunction?: () => boolean,
15*3991724eS猫头猫): Promise<ICommon.SupportMediaItemBase[T] | null> {
16*3991724eS猫头猫    const keyword = musicItem.alias || musicItem.title;
17*3991724eS猫头猫    const plugins = PluginManager.getSearchablePlugins(type);
18*3991724eS猫头猫
19*3991724eS猫头猫    let distance = Infinity;
20*3991724eS猫头猫    let minDistanceMusicItem;
21*3991724eS猫头猫    let targetPlugin;
22*3991724eS猫头猫
23*3991724eS猫头猫    const startTime = Date.now();
24*3991724eS猫头猫
25*3991724eS猫头猫    for (let plugin of plugins) {
26*3991724eS猫头猫        // 超时时间:10s
27*3991724eS猫头猫        if (abortFunction?.() || Date.now() - startTime > 8000) {
28*3991724eS猫头猫            break;
29*3991724eS猫头猫        }
30*3991724eS猫头猫        if (plugin.name === musicItem.platform) {
31*3991724eS猫头猫            continue;
32*3991724eS猫头猫        }
33*3991724eS猫头猫        const results = await plugin.methods
34*3991724eS猫头猫            .search(keyword, 1, type)
35*3991724eS猫头猫            .catch(() => null);
36*3991724eS猫头猫
37*3991724eS猫头猫        // 取前两个
38*3991724eS猫头猫        const firstTwo = results?.data?.slice(0, 2) || [];
39*3991724eS猫头猫
40*3991724eS猫头猫        for (let item of firstTwo) {
41*3991724eS猫头猫            if (item.title === keyword && item.artist === musicItem.artist) {
42*3991724eS猫头猫                distance = 0;
43*3991724eS猫头猫                minDistanceMusicItem = item;
44*3991724eS猫头猫                targetPlugin = plugin;
45*3991724eS猫头猫                break;
46*3991724eS猫头猫            } else {
47*3991724eS猫头猫                const dist =
48*3991724eS猫头猫                    minDistance(keyword, musicItem.title) +
49*3991724eS猫头猫                    minDistance(item.artist, musicItem.artist);
50*3991724eS猫头猫                if (dist < distance) {
51*3991724eS猫头猫                    distance = dist;
52*3991724eS猫头猫                    minDistanceMusicItem = item;
53*3991724eS猫头猫                    targetPlugin = plugin;
54*3991724eS猫头猫                }
55*3991724eS猫头猫            }
56*3991724eS猫头猫        }
57*3991724eS猫头猫
58*3991724eS猫头猫        if (distance === 0) {
59*3991724eS猫头猫            break;
60*3991724eS猫头猫        }
61*3991724eS猫头猫    }
62*3991724eS猫头猫    if (minDistanceMusicItem && targetPlugin) {
63*3991724eS猫头猫        return minDistanceMusicItem as ICommon.SupportMediaItemBase[T];
64*3991724eS猫头猫    }
65*3991724eS猫头猫
66*3991724eS猫头猫    return null;
67*3991724eS猫头猫}
68