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,
LyricSearchQuery,
} from '/@/renderer/api/types';
import { LyricSource } from '../../../../renderer/types';
import { LyricSource } from '../../../../renderer/api/types';
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>;
try {
result = await axios.get<string>(url, { responseType: 'text' });
@ -147,7 +147,7 @@ export async function query(
return null;
}
const lyrics = await getLyricsFromGenius(response.url);
const lyrics = await getLyricsByURL(response.url);
if (!lyrics) {
console.error('Could not get lyrics on Genius!');
return null;

View file

@ -3,10 +3,19 @@ import {
InternetProviderLyricSearchResponse,
LyricSearchQuery,
QueueSong,
LyricGetQuery,
LyricSource,
} from '/@/renderer/api/types';
import { query as queryGenius, getSearchResults as searchGenius } from './genius';
import { query as queryNetease, getSearchResults as searchNetease } from './netease';
import { LyricSource } from '../../../../renderer/types';
import {
query as queryGenius,
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 { store } from '../settings/index';
@ -14,6 +23,7 @@ type SongFetcher = (params: LyricSearchQuery) => Promise<InternetProviderLyricRe
type SearchFetcher = (
params: LyricSearchQuery,
) => Promise<InternetProviderLyricSearchResponse[] | null>;
type GetFetcher = (id: string) => Promise<string | null>;
type CachedLyrics = Record<LyricSource, InternetProviderLyricResponse>;
@ -27,6 +37,11 @@ const SEARCH_FETCHERS: Record<LyricSource, SearchFetcher> = {
[LyricSource.NETEASE]: searchNetease,
};
const GET_FETCHERS: Record<LyricSource, GetFetcher> = {
[LyricSource.GENIUS]: getGenius,
[LyricSource.NETEASE]: getNetease,
};
const MAX_CACHED_ITEMS = 10;
const lyricCache = new Map<string, CachedLyrics>();
@ -93,7 +108,18 @@ const searchRemoteLyrics = async (params: LyricSearchQuery) => {
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);
return lyric;
});
@ -102,3 +128,8 @@ ipcMain.handle('lyric-search', async (_event, params: LyricSearchQuery) => {
const lyricResults = await searchRemoteLyrics(params);
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 { LyricSource } from '../../../../renderer/types';
import { LyricSource } from '../../../../renderer/api/types';
import type {
InternetProviderLyricResponse,
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>;
try {
result = await axios.get(LYRICS_URL, {
@ -76,7 +76,7 @@ async function getLyricsFromSongId(songId: string): Promise<string | undefined>
});
} catch (e) {
console.error('NetEase lyrics request got an error!', e);
return undefined;
return null;
}
return result.data.klyric?.lyric || result.data.lrc?.lyric;
@ -91,7 +91,7 @@ export async function query(
return null;
}
const lyrics = await getLyricsFromSongId(response.id);
const lyrics = await getLyricsBySongId(response.id);
if (!lyrics) {
console.error('Could not get lyrics on NetEase!');
return null;

View file

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

View file

@ -1033,14 +1033,14 @@ export type InternetProviderLyricResponse = {
artist: string;
lyrics: string;
name: string;
source: string;
source: LyricSource;
};
export type InternetProviderLyricSearchResponse = {
artist: string;
id: string;
name: string;
source: string;
source: LyricSource;
};
export type SynchronizedLyricMetadata = {
@ -1048,12 +1048,12 @@ export type SynchronizedLyricMetadata = {
remote: boolean;
} & Omit<InternetProviderLyricResponse, 'lyrics'>;
export type UnsyhchronizedLyricMetadata = {
export type UnsynchronizedLyricMetadata = {
lyrics: string;
remote: boolean;
} & Omit<InternetProviderLyricResponse, 'lyrics'>;
export type FullLyricsMetadata = SynchronizedLyricMetadata | UnsyhchronizedLyricMetadata;
export type FullLyricsMetadata = SynchronizedLyricMetadata | UnsynchronizedLyricMetadata;
export type LyricOverride = Omit<InternetProviderLyricResponse, 'lyrics'>;
@ -1065,3 +1065,15 @@ export type LyricSearchQuery = {
artist: 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 isElectron from 'is-electron';
import styled from 'styled-components';
import { LyricSource } from '/@/renderer/types';
import { LyricSource } from '/@/renderer/api/types';
const localSettings = isElectron() ? window.electron.localSettings : null;

View file

@ -8,7 +8,7 @@ import { create } from 'zustand';
import { devtools, persist } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';
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 { AppTheme } from '/@/renderer/themes/types';
import {
@ -19,7 +19,6 @@ import {
PlaybackType,
TableType,
Platform,
LyricSource,
} from '/@/renderer/types';
export type SidebarItemType = {

View file

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