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