Update fetchers to support search

This commit is contained in:
jeffvli 2023-06-09 02:36:38 -07:00 committed by Jeff
parent 01608fa875
commit f8ecb3fc53
8 changed files with 69 additions and 38 deletions

View file

@ -5,7 +5,7 @@ import type {
InternetProviderLyricSearchResponse, InternetProviderLyricSearchResponse,
LyricSearchQuery, LyricSearchQuery,
} from '/@/renderer/api/types'; } from '/@/renderer/api/types';
import { LyricSource } from '../../../../renderer/types'; import { LyricSource } from '../../../../renderer/api/types';
const SEARCH_URL = 'https://genius.com/api/search/song'; const SEARCH_URL = 'https://genius.com/api/search/song';
@ -117,7 +117,7 @@ async function getSongURL(params: LyricSearchQuery): Promise<GeniusResponse | un
}; };
} }
async function getLyricsFromGenius(url: string): Promise<string | null> { export async function getLyricsByURL(url: string): Promise<string | null> {
let result: AxiosResponse<string, any>; let result: AxiosResponse<string, any>;
try { try {
result = await axios.get<string>(url, { responseType: 'text' }); result = await axios.get<string>(url, { responseType: 'text' });
@ -147,7 +147,7 @@ export async function query(
return null; return null;
} }
const lyrics = await getLyricsFromGenius(response.url); const lyrics = await getLyricsByURL(response.url);
if (!lyrics) { if (!lyrics) {
console.error('Could not get lyrics on Genius!'); console.error('Could not get lyrics on Genius!');
return null; return null;

View file

@ -3,10 +3,19 @@ import {
InternetProviderLyricSearchResponse, InternetProviderLyricSearchResponse,
LyricSearchQuery, LyricSearchQuery,
QueueSong, QueueSong,
LyricGetQuery,
LyricSource,
} from '/@/renderer/api/types'; } from '/@/renderer/api/types';
import { query as queryGenius, getSearchResults as searchGenius } from './genius'; import {
import { query as queryNetease, getSearchResults as searchNetease } from './netease'; query as queryGenius,
import { LyricSource } from '../../../../renderer/types'; getSearchResults as searchGenius,
getLyricsByURL as getGenius,
} from './genius';
import {
query as queryNetease,
getSearchResults as searchNetease,
getLyricsBySongId as getNetease,
} from './netease';
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import { store } from '../settings/index'; import { store } from '../settings/index';
@ -14,6 +23,7 @@ type SongFetcher = (params: LyricSearchQuery) => Promise<InternetProviderLyricRe
type SearchFetcher = ( type SearchFetcher = (
params: LyricSearchQuery, params: LyricSearchQuery,
) => Promise<InternetProviderLyricSearchResponse[] | null>; ) => Promise<InternetProviderLyricSearchResponse[] | null>;
type GetFetcher = (id: string) => Promise<string | null>;
type CachedLyrics = Record<LyricSource, InternetProviderLyricResponse>; type CachedLyrics = Record<LyricSource, InternetProviderLyricResponse>;
@ -27,6 +37,11 @@ const SEARCH_FETCHERS: Record<LyricSource, SearchFetcher> = {
[LyricSource.NETEASE]: searchNetease, [LyricSource.NETEASE]: searchNetease,
}; };
const GET_FETCHERS: Record<LyricSource, GetFetcher> = {
[LyricSource.GENIUS]: getGenius,
[LyricSource.NETEASE]: getNetease,
};
const MAX_CACHED_ITEMS = 10; const MAX_CACHED_ITEMS = 10;
const lyricCache = new Map<string, CachedLyrics>(); const lyricCache = new Map<string, CachedLyrics>();
@ -93,7 +108,18 @@ const searchRemoteLyrics = async (params: LyricSearchQuery) => {
return results; return results;
}; };
ipcMain.handle('lyric-fetch-manual', async (_event, song: QueueSong) => { const getRemoteLyricsById = async (params: LyricGetQuery): Promise<string | null> => {
const { remoteSongId, remoteSource } = params;
const response = await GET_FETCHERS[remoteSource](remoteSongId);
if (!response) {
return null;
}
return response;
};
ipcMain.handle('lyric-by-song', async (_event, song: QueueSong) => {
const lyric = await getRemoteLyrics(song); const lyric = await getRemoteLyrics(song);
return lyric; return lyric;
}); });
@ -102,3 +128,8 @@ ipcMain.handle('lyric-search', async (_event, params: LyricSearchQuery) => {
const lyricResults = await searchRemoteLyrics(params); const lyricResults = await searchRemoteLyrics(params);
return lyricResults; return lyricResults;
}); });
ipcMain.handle('lyric-by-remote-id', async (_event, params: LyricGetQuery) => {
const lyricResults = await getRemoteLyricsById(params);
return lyricResults;
});

View file

@ -1,5 +1,5 @@
import axios, { AxiosResponse } from 'axios'; import axios, { AxiosResponse } from 'axios';
import { LyricSource } from '../../../../renderer/types'; import { LyricSource } from '../../../../renderer/api/types';
import type { import type {
InternetProviderLyricResponse, InternetProviderLyricResponse,
InternetProviderLyricSearchResponse, InternetProviderLyricSearchResponse,
@ -64,7 +64,7 @@ async function getSongId(params: LyricSearchQuery): Promise<NetEaseResponse | un
}; };
} }
async function getLyricsFromSongId(songId: string): Promise<string | undefined> { export async function getLyricsBySongId(songId: string): Promise<string | null> {
let result: AxiosResponse<any, any>; let result: AxiosResponse<any, any>;
try { try {
result = await axios.get(LYRICS_URL, { result = await axios.get(LYRICS_URL, {
@ -76,7 +76,7 @@ async function getLyricsFromSongId(songId: string): Promise<string | undefined>
}); });
} catch (e) { } catch (e) {
console.error('NetEase lyrics request got an error!', e); console.error('NetEase lyrics request got an error!', e);
return undefined; return null;
} }
return result.data.klyric?.lyric || result.data.lrc?.lyric; return result.data.klyric?.lyric || result.data.lrc?.lyric;
@ -91,7 +91,7 @@ export async function query(
return null; return null;
} }
const lyrics = await getLyricsFromSongId(response.id); const lyrics = await getLyricsBySongId(response.id);
if (!lyrics) { if (!lyrics) {
console.error('Could not get lyrics on NetEase!'); console.error('Could not get lyrics on NetEase!');
return null; return null;

View file

@ -1,8 +1,8 @@
import { IpcRendererEvent, ipcRenderer } from 'electron'; import { ipcRenderer } from 'electron';
import { InternetProviderLyricResponse, LyricSearchQuery, QueueSong } from '/@/renderer/api/types'; import { LyricSearchQuery, QueueSong } from '/@/renderer/api/types';
const fetchRemoteLyrics = (song: QueueSong) => { const getRemoteLyricsBySong = (song: QueueSong) => {
const result = ipcRenderer.invoke('lyric-fetch-manual', song); const result = ipcRenderer.invoke('lyric-by-song', song);
return result; return result;
}; };
@ -11,19 +11,13 @@ const searchRemoteLyrics = (params: LyricSearchQuery) => {
return result; return result;
}; };
const remoteLyricsListener = ( const getRemoteLyricsByRemoteId = (id: string) => {
cb: ( const result = ipcRenderer.invoke('lyric-by-remote-id', id);
event: IpcRendererEvent, return result;
songName: string,
source: string,
lyric: InternetProviderLyricResponse,
) => void,
) => {
ipcRenderer.on('lyric-get', cb);
}; };
export const lyrics = { export const lyrics = {
fetchRemoteLyrics, getRemoteLyricsByRemoteId,
remoteLyricsListener, getRemoteLyricsBySong,
searchRemoteLyrics, searchRemoteLyrics,
}; };

View file

@ -1033,14 +1033,14 @@ export type InternetProviderLyricResponse = {
artist: string; artist: string;
lyrics: string; lyrics: string;
name: string; name: string;
source: string; source: LyricSource;
}; };
export type InternetProviderLyricSearchResponse = { export type InternetProviderLyricSearchResponse = {
artist: string; artist: string;
id: string; id: string;
name: string; name: string;
source: string; source: LyricSource;
}; };
export type SynchronizedLyricMetadata = { export type SynchronizedLyricMetadata = {
@ -1048,12 +1048,12 @@ export type SynchronizedLyricMetadata = {
remote: boolean; remote: boolean;
} & Omit<InternetProviderLyricResponse, 'lyrics'>; } & Omit<InternetProviderLyricResponse, 'lyrics'>;
export type UnsyhchronizedLyricMetadata = { export type UnsynchronizedLyricMetadata = {
lyrics: string; lyrics: string;
remote: boolean; remote: boolean;
} & Omit<InternetProviderLyricResponse, 'lyrics'>; } & Omit<InternetProviderLyricResponse, 'lyrics'>;
export type FullLyricsMetadata = SynchronizedLyricMetadata | UnsyhchronizedLyricMetadata; export type FullLyricsMetadata = SynchronizedLyricMetadata | UnsynchronizedLyricMetadata;
export type LyricOverride = Omit<InternetProviderLyricResponse, 'lyrics'>; export type LyricOverride = Omit<InternetProviderLyricResponse, 'lyrics'>;
@ -1065,3 +1065,15 @@ export type LyricSearchQuery = {
artist: string; artist: string;
name: string; name: string;
}; };
export type LyricGetQuery = {
remoteSongId: string;
remoteSource: LyricSource;
};
export enum LyricSource {
GENIUS = 'Genius',
NETEASE = 'NetEase',
}
export type LyricsOverride = Omit<FullLyricsMetadata, 'lyrics'> & { id: string };

View file

@ -6,7 +6,7 @@ import { useLyricsSettings, useSettingsStoreActions } from '/@/renderer/store';
import { MultiSelect, MultiSelectProps, NumberInput, Switch } from '/@/renderer/components'; import { MultiSelect, MultiSelectProps, NumberInput, Switch } from '/@/renderer/components';
import isElectron from 'is-electron'; import isElectron from 'is-electron';
import styled from 'styled-components'; import styled from 'styled-components';
import { LyricSource } from '/@/renderer/types'; import { LyricSource } from '/@/renderer/api/types';
const localSettings = isElectron() ? window.electron.localSettings : null; const localSettings = isElectron() ? window.electron.localSettings : null;

View file

@ -8,7 +8,7 @@ import { create } from 'zustand';
import { devtools, persist } from 'zustand/middleware'; import { devtools, persist } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer'; import { immer } from 'zustand/middleware/immer';
import { shallow } from 'zustand/shallow'; import { shallow } from 'zustand/shallow';
import { LibraryItem } from '/@/renderer/api/types'; import { LibraryItem, LyricSource } from '/@/renderer/api/types';
import { AppRoute } from '/@/renderer/router/routes'; import { AppRoute } from '/@/renderer/router/routes';
import { AppTheme } from '/@/renderer/themes/types'; import { AppTheme } from '/@/renderer/themes/types';
import { import {
@ -19,7 +19,6 @@ import {
PlaybackType, PlaybackType,
TableType, TableType,
Platform, Platform,
LyricSource,
} from '/@/renderer/types'; } from '/@/renderer/types';
export type SidebarItemType = { export type SidebarItemType = {

View file

@ -176,8 +176,3 @@ export type GridCardData = {
playButtonBehavior: Play; playButtonBehavior: Play;
route: CardRoute; route: CardRoute;
}; };
export enum LyricSource {
GENIUS = 'Genius',
NETEASE = 'NetEase',
}