|
@ -5,6 +5,7 @@ import settings from 'electron-settings'; |
|
|
import { nanoid } from 'nanoid/non-secure'; |
|
|
import { nanoid } from 'nanoid/non-secure'; |
|
|
import axiosRetry from 'axios-retry'; |
|
|
import axiosRetry from 'axios-retry'; |
|
|
import { mockSettings } from '../shared/mockSettings'; |
|
|
import { mockSettings } from '../shared/mockSettings'; |
|
|
|
|
|
import { Item } from './types'; |
|
|
|
|
|
|
|
|
const legacyAuth = |
|
|
const legacyAuth = |
|
|
process.env.NODE_ENV === 'test' |
|
|
process.env.NODE_ENV === 'test' |
|
@ -31,6 +32,23 @@ const getAuth = (useLegacyAuth: boolean) => { |
|
|
const auth = getAuth(legacyAuth); |
|
|
const auth = getAuth(legacyAuth); |
|
|
const API_BASE_URL = `${auth.server}/rest`; |
|
|
const API_BASE_URL = `${auth.server}/rest`; |
|
|
|
|
|
|
|
|
|
|
|
const authParams = legacyAuth |
|
|
|
|
|
? { |
|
|
|
|
|
u: auth.username, |
|
|
|
|
|
p: auth.password, |
|
|
|
|
|
v: '1.15.0', |
|
|
|
|
|
c: 'sonixd', |
|
|
|
|
|
f: 'json', |
|
|
|
|
|
} |
|
|
|
|
|
: { |
|
|
|
|
|
u: auth.username, |
|
|
|
|
|
s: auth.salt, |
|
|
|
|
|
t: auth.hash, |
|
|
|
|
|
v: '1.15.0', |
|
|
|
|
|
c: 'sonixd', |
|
|
|
|
|
f: 'json', |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
export const api = axios.create({ |
|
|
export const api = axios.create({ |
|
|
baseURL: API_BASE_URL, |
|
|
baseURL: API_BASE_URL, |
|
|
}); |
|
|
}); |
|
@ -65,54 +83,6 @@ axiosRetry(api, { |
|
|
}, |
|
|
}, |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
export const autoFailApi = axios.create({ |
|
|
|
|
|
baseURL: API_BASE_URL, |
|
|
|
|
|
validateStatus: () => { |
|
|
|
|
|
return false; |
|
|
|
|
|
}, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
autoFailApi.interceptors.request.use((config) => { |
|
|
|
|
|
config.params = config.params || {}; |
|
|
|
|
|
config.params.u = auth.username; |
|
|
|
|
|
config.params.s = auth.salt; |
|
|
|
|
|
config.params.t = auth.hash; |
|
|
|
|
|
config.params.v = '1.15.0'; |
|
|
|
|
|
config.params.c = 'sonixd'; |
|
|
|
|
|
config.params.f = 'json'; |
|
|
|
|
|
return config; |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
autoFailApi.interceptors.response.use( |
|
|
|
|
|
(res) => { |
|
|
|
|
|
// Return the subsonic response directly
|
|
|
|
|
|
res.data = res.data['subsonic-response']; |
|
|
|
|
|
return res; |
|
|
|
|
|
}, |
|
|
|
|
|
(err) => { |
|
|
|
|
|
return Promise.reject(err); |
|
|
|
|
|
} |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
axiosRetry(autoFailApi, { |
|
|
|
|
|
retries: 5, |
|
|
|
|
|
retryCondition: (e: any) => { |
|
|
|
|
|
return e.response.data['subsonic-response'].status !== 'ok'; |
|
|
|
|
|
}, |
|
|
|
|
|
retryDelay: (retryCount) => { |
|
|
|
|
|
return retryCount * 1000; |
|
|
|
|
|
}, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const authParams = { |
|
|
|
|
|
u: auth.username, |
|
|
|
|
|
s: auth.salt, |
|
|
|
|
|
t: auth.hash, |
|
|
|
|
|
v: '1.15.0', |
|
|
|
|
|
c: 'sonixd', |
|
|
|
|
|
f: 'json', |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const getCoverArtUrl = (item: any, useLegacyAuth: boolean, size?: number) => { |
|
|
const getCoverArtUrl = (item: any, useLegacyAuth: boolean, size?: number) => { |
|
|
if (!item.coverArt && !item.artistImageUrl) { |
|
|
if (!item.coverArt && !item.artistImageUrl) { |
|
|
return 'img/placeholder.jpg'; |
|
|
return 'img/placeholder.jpg'; |
|
@ -127,38 +97,14 @@ const getCoverArtUrl = (item: any, useLegacyAuth: boolean, size?: number) => { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (useLegacyAuth) { |
|
|
if (useLegacyAuth) { |
|
|
if (!size) { |
|
|
|
|
|
return ( |
|
|
return ( |
|
|
`${API_BASE_URL}/getCoverArt` + |
|
|
`${API_BASE_URL}/getCoverArt` + |
|
|
`?id=${item.coverArt}` + |
|
|
`?id=${item.coverArt}` + |
|
|
`&u=${auth.username}` + |
|
|
`&u=${auth.username}` + |
|
|
`&s=${auth.salt}` + |
|
|
`&p=${auth.password}` + |
|
|
`&t=${auth.hash}` + |
|
|
|
|
|
`&v=1.15.0` + |
|
|
|
|
|
`&c=sonixd` |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
return ( |
|
|
|
|
|
`${API_BASE_URL}/getCoverArt` + |
|
|
|
|
|
`?id=${item.coverArt}` + |
|
|
|
|
|
`&u=${auth.username}` + |
|
|
|
|
|
`&s=${auth.salt}` + |
|
|
|
|
|
`&t=${auth.hash}` + |
|
|
|
|
|
`&v=1.15.0` + |
|
|
`&v=1.15.0` + |
|
|
`&c=sonixd` + |
|
|
`&c=sonixd` + |
|
|
`&size=${size}` |
|
|
`${size ? `&size=${size}` : ''}` |
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!size) { |
|
|
|
|
|
return ( |
|
|
|
|
|
`${API_BASE_URL}/getCoverArt` + |
|
|
|
|
|
`?id=${item.coverArt}` + |
|
|
|
|
|
`&u=${auth.username}` + |
|
|
|
|
|
`&s=${auth.salt}` + |
|
|
|
|
|
`&t=${auth.hash}` + |
|
|
|
|
|
`&v=1.15.0` + |
|
|
|
|
|
`&c=sonixd` |
|
|
|
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -170,7 +116,7 @@ const getCoverArtUrl = (item: any, useLegacyAuth: boolean, size?: number) => { |
|
|
`&t=${auth.hash}` + |
|
|
`&t=${auth.hash}` + |
|
|
`&v=1.15.0` + |
|
|
`&v=1.15.0` + |
|
|
`&c=sonixd` + |
|
|
`&c=sonixd` + |
|
|
`&size=${size}` |
|
|
`${size ? `&size=${size}` : ''}` |
|
|
); |
|
|
); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
@ -220,205 +166,147 @@ const getStreamUrl = (id: string, useLegacyAuth: boolean) => { |
|
|
); |
|
|
); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getPlaylists = async (sortBy: string) => { |
|
|
const normalizeSong = (item: any) => { |
|
|
const { data } = await api.get('/getPlaylists'); |
|
|
return { |
|
|
|
|
|
id: item.id, |
|
|
const newData = |
|
|
parent: item.parent, |
|
|
sortBy === 'dateCreated' |
|
|
isDir: item.isDir, |
|
|
? data.playlists?.playlist.sort((a: any, b: any) => { |
|
|
title: item.title, |
|
|
return a.created > b.created ? -1 : a.created < b.created ? 1 : 0; |
|
|
album: item.album, |
|
|
}) |
|
|
albumId: item.albumId, |
|
|
: sortBy === 'dateModified' |
|
|
artist: item.artist, |
|
|
? data.playlists?.playlist.sort((a: any, b: any) => { |
|
|
artistId: item.artistId, |
|
|
return a.changed > b.changed ? -1 : a.changed < b.changed ? 1 : 0; |
|
|
track: item.track, |
|
|
}) |
|
|
year: item.year, |
|
|
: sortBy === 'name' |
|
|
genre: item.genre, |
|
|
? _.orderBy(data.playlists.playlist || [], [(entry) => entry.name.toLowerCase()], 'asc') |
|
|
size: item.size, |
|
|
: data.playlists?.playlist; |
|
|
contentType: item.contentType, |
|
|
|
|
|
suffix: item.suffix, |
|
|
return (newData || []).map((playlist: any) => ({ |
|
|
duration: item.duration, |
|
|
...playlist, |
|
|
bitRate: item.bitRate, |
|
|
name: playlist.name, |
|
|
path: item.path, |
|
|
image: |
|
|
playCount: item.playCount, |
|
|
playlist.songCount > 0 ? getCoverArtUrl(playlist, legacyAuth, 350) : 'img/placeholder.jpg', |
|
|
discNumber: item.discNumber, |
|
|
type: 'playlist', |
|
|
created: item.created, |
|
|
|
|
|
streamUrl: getStreamUrl(item.id, legacyAuth), |
|
|
|
|
|
image: getCoverArtUrl(item, legacyAuth, 150), |
|
|
|
|
|
starred: item.starred, |
|
|
|
|
|
type: Item.Music, |
|
|
uniqueId: nanoid(), |
|
|
uniqueId: nanoid(), |
|
|
})); |
|
|
}; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getPlaylist = async (id: string) => { |
|
|
const normalizeAlbum = (item: any) => { |
|
|
const { data } = await api.get(`/getPlaylist?id=${id}`); |
|
|
|
|
|
return { |
|
|
return { |
|
|
...data.playlist, |
|
|
id: item.id, |
|
|
entry: null, // Normalize to 'song' instead of 'entry'
|
|
|
title: item.name, |
|
|
song: (data.playlist.entry || []).map((entry: any, index: any) => ({ |
|
|
albumId: item.id, |
|
|
...entry, |
|
|
artist: item.artist, |
|
|
streamUrl: getStreamUrl(entry.id, legacyAuth), |
|
|
artistId: item.artistId, |
|
|
image: getCoverArtUrl(entry, legacyAuth, 150), |
|
|
songCount: item.songCount, |
|
|
type: 'music', |
|
|
duration: item.duration, |
|
|
index, |
|
|
created: item.created, |
|
|
|
|
|
year: item.year, |
|
|
|
|
|
genre: item.genre, |
|
|
|
|
|
image: getCoverArtUrl(item, legacyAuth, 350), |
|
|
|
|
|
isDir: false, |
|
|
|
|
|
starred: item.starred, |
|
|
|
|
|
type: Item.Album, |
|
|
uniqueId: nanoid(), |
|
|
uniqueId: nanoid(), |
|
|
})), |
|
|
song: (item.song || []).map((entry: any) => normalizeSong(entry)), |
|
|
image: |
|
|
|
|
|
data.playlist.songCount > 0 |
|
|
|
|
|
? getCoverArtUrl(data.playlist, legacyAuth, 350) |
|
|
|
|
|
: 'img/placeholder.jpg', |
|
|
|
|
|
}; |
|
|
}; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getPing = async () => { |
|
|
const normalizeArtist = (item: any) => { |
|
|
const { data } = await api.get(`/ping`); |
|
|
return { |
|
|
|
|
|
id: item.id, |
|
|
return data; |
|
|
title: item.name, |
|
|
}; |
|
|
albumCount: item.albumCount, |
|
|
|
|
|
image: getCoverArtUrl(item, legacyAuth, 350), |
|
|
export const getStream = async (id: string) => { |
|
|
starred: item.starred, |
|
|
const { data } = await api.get(`/stream?id=${id}`); |
|
|
type: Item.Artist, |
|
|
return data; |
|
|
uniqueId: nanoid(), |
|
|
|
|
|
album: (item.album || []).map((entry: any) => normalizeAlbum(entry)), |
|
|
|
|
|
}; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getDownload = async (options: { id: string }) => { |
|
|
const normalizeArtistInfo = (item: any) => { |
|
|
const { data } = await api.get(`/download?id=${options.id}`, { |
|
|
return { |
|
|
responseType: 'blob', |
|
|
biography: item.biography, |
|
|
onDownloadProgress: (progressEvent) => { |
|
|
lastFmUrl: item.lastFmUrl, |
|
|
const percentCompleted = Math.floor((progressEvent.loaded / progressEvent.total) * 100); |
|
|
imageUrl: item.largeImageUrl || item.mediumImageUrl || item.smallImageUrl, |
|
|
console.log(`percentCompleted`, percentCompleted); |
|
|
similarArtist: (item.similarArtist || []).map((entry: any) => normalizeArtist(entry)), |
|
|
}, |
|
|
}; |
|
|
}); |
|
|
|
|
|
return data; |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getPlayQueue = async () => { |
|
|
const normalizePlaylist = (item: any) => { |
|
|
const { data } = await api.get(`/getPlayQueue`); |
|
|
|
|
|
return { |
|
|
return { |
|
|
...data.playQueue, |
|
|
id: item.id, |
|
|
entry: (data.playQueue.entry || []).map((entry: any, index: any) => ({ |
|
|
title: item.name, |
|
|
...entry, |
|
|
comment: item.comment, |
|
|
streamUrl: getStreamUrl(entry.id, legacyAuth), |
|
|
owner: item.owner, |
|
|
index, |
|
|
public: item.public, |
|
|
})), |
|
|
songCount: item.songCount, |
|
|
|
|
|
duration: item.duration, |
|
|
|
|
|
created: item.created, |
|
|
|
|
|
changed: item.changed, |
|
|
|
|
|
image: item.songCount > 0 ? getCoverArtUrl(item, legacyAuth, 350) : 'img/placeholder.jpg', |
|
|
|
|
|
type: Item.Playlist, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
song: (item.entry || []).map((entry: any) => normalizeSong(entry)), |
|
|
}; |
|
|
}; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getStarred = async (options: { musicFolderId?: string | number }) => { |
|
|
const normalizeGenre = (item: any) => { |
|
|
const { data } = await api.get(`/getStarred2`, { params: options }); |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
return { |
|
|
...data.starred2, |
|
|
id: item.id, |
|
|
album: (data.starred2.album || []).map((entry: any, index: any) => ({ |
|
|
title: item.value, |
|
|
...entry, |
|
|
songCount: item.songCount, |
|
|
title: entry.name, |
|
|
albumCount: item.albumCount, |
|
|
albumId: entry.id, |
|
|
type: Item.Genre, |
|
|
image: getCoverArtUrl(entry, legacyAuth, 350), |
|
|
|
|
|
starred: entry.starred || undefined, |
|
|
|
|
|
type: 'album', |
|
|
|
|
|
isDir: false, |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
})), |
|
|
|
|
|
song: (data.starred2.song || []).map((entry: any, index: any) => ({ |
|
|
|
|
|
...entry, |
|
|
|
|
|
streamUrl: getStreamUrl(entry.id, legacyAuth), |
|
|
|
|
|
image: getCoverArtUrl(entry, legacyAuth, 150), |
|
|
|
|
|
starred: entry.starred || undefined, |
|
|
|
|
|
type: 'music', |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
uniqueId: nanoid(), |
|
|
})), |
|
|
|
|
|
artist: (data.starred2.artist || []).map((entry: any, index: any) => ({ |
|
|
|
|
|
...entry, |
|
|
|
|
|
albumCount: entry.albumCount || undefined, |
|
|
|
|
|
coverArt: getCoverArtUrl(entry, legacyAuth), |
|
|
|
|
|
image: getCoverArtUrl(entry, legacyAuth, 350), |
|
|
|
|
|
starred: entry.starred || Date.now(), // Airsonic does not return the starred date
|
|
|
|
|
|
type: 'artist', |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
})), |
|
|
|
|
|
}; |
|
|
}; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getAlbums = async (options: { |
|
|
const normalizeFolder = (item: any) => { |
|
|
type: |
|
|
|
|
|
| 'random' |
|
|
|
|
|
| 'newest' |
|
|
|
|
|
| 'highest' |
|
|
|
|
|
| 'frequent' |
|
|
|
|
|
| 'recent' |
|
|
|
|
|
| 'alphabeticalByName' |
|
|
|
|
|
| 'alphabeticalByArtist' |
|
|
|
|
|
| 'starred' |
|
|
|
|
|
| 'byYear' |
|
|
|
|
|
| 'byGenre'; |
|
|
|
|
|
size?: number; |
|
|
|
|
|
offset?: number; |
|
|
|
|
|
fromYear?: number; |
|
|
|
|
|
toYear?: number; |
|
|
|
|
|
genre?: string; |
|
|
|
|
|
musicFolderId?: string | number; |
|
|
|
|
|
}) => { |
|
|
|
|
|
const { data } = await api.get(`/getAlbumList2`, { |
|
|
|
|
|
params: options, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
return { |
|
|
...data.albumList2, |
|
|
id: item.id, |
|
|
album: (data.albumList2.album || []).map((entry: any, index: any) => ({ |
|
|
title: item.name || item.title, |
|
|
...entry, |
|
|
isDir: true, |
|
|
title: entry.name, |
|
|
image: getCoverArtUrl(item, legacyAuth, 150), |
|
|
albumId: entry.id, |
|
|
type: Item.Folder, |
|
|
image: getCoverArtUrl(entry, legacyAuth, 350), |
|
|
|
|
|
starred: entry.starred || undefined, |
|
|
|
|
|
type: 'album', |
|
|
|
|
|
isDir: false, |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
uniqueId: nanoid(), |
|
|
})), |
|
|
|
|
|
}; |
|
|
}; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getAlbumsDirect = async (options: { |
|
|
export const getPlaylist = async (id: string) => { |
|
|
type: |
|
|
const { data } = await api.get(`/getPlaylist?id=${id}`); |
|
|
| 'random' |
|
|
return normalizePlaylist(data.playlist); |
|
|
| 'newest' |
|
|
}; |
|
|
| 'highest' |
|
|
|
|
|
| 'frequent' |
|
|
|
|
|
| 'recent' |
|
|
|
|
|
| 'alphabeticalByName' |
|
|
|
|
|
| 'alphabeticalByArtist' |
|
|
|
|
|
| 'starred' |
|
|
|
|
|
| 'byYear' |
|
|
|
|
|
| 'byGenre'; |
|
|
|
|
|
size?: number; |
|
|
|
|
|
offset?: number; |
|
|
|
|
|
fromYear?: number; |
|
|
|
|
|
toYear?: number; |
|
|
|
|
|
genre?: string; |
|
|
|
|
|
musicFolderId?: string | number; |
|
|
|
|
|
}) => { |
|
|
|
|
|
const { data } = await api.get(`/getAlbumList2`, { |
|
|
|
|
|
params: options, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const albums = (data.albumList2.album || []).map((entry: any, index: any) => ({ |
|
|
export const getPlaylists = async () => { |
|
|
...entry, |
|
|
const { data } = await api.get('/getPlaylists'); |
|
|
title: entry.name, |
|
|
return (data.playlists?.playlist || []).map((playlist: any) => normalizePlaylist(playlist)); |
|
|
albumId: entry.id, |
|
|
}; |
|
|
image: getCoverArtUrl(entry, legacyAuth, 350), |
|
|
|
|
|
starred: entry.starred || undefined, |
|
|
|
|
|
type: 'album', |
|
|
|
|
|
isDir: false, |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
})); |
|
|
|
|
|
|
|
|
|
|
|
return albums; |
|
|
export const getStarred = async (options: { musicFolderId?: string | number }) => { |
|
|
|
|
|
const { data } = await api.get(`/getStarred2`, { params: options }); |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
album: (data.starred2.album || []).map((entry: any) => normalizeAlbum(entry)), |
|
|
|
|
|
song: (data.starred2.song || []).map((entry: any) => normalizeSong(entry)), |
|
|
|
|
|
artist: (data.starred2.artist || []).map((entry: any) => normalizeArtist(entry)), |
|
|
|
|
|
}; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
export const getAlbum = async (options: { id: string }) => { |
|
|
|
|
|
const { data } = await api.get(`/getAlbum`, { params: options }); |
|
|
|
|
|
return normalizeAlbum(data.album); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getAllAlbums = ( |
|
|
export const getAlbums = async ( |
|
|
options: { |
|
|
options: { |
|
|
type: |
|
|
type: |
|
|
| string // Handle generic genres
|
|
|
|
|
|
| 'random' |
|
|
| 'random' |
|
|
| 'newest' |
|
|
| 'newest' |
|
|
| 'highest' |
|
|
| 'highest' |
|
@ -435,9 +323,11 @@ export const getAllAlbums = ( |
|
|
toYear?: number; |
|
|
toYear?: number; |
|
|
genre?: string; |
|
|
genre?: string; |
|
|
musicFolderId?: string | number; |
|
|
musicFolderId?: string | number; |
|
|
|
|
|
recursive?: boolean; |
|
|
}, |
|
|
}, |
|
|
data: any[] = [] |
|
|
recursiveData: any[] = [] |
|
|
) => { |
|
|
) => { |
|
|
|
|
|
if (options.recursive) { |
|
|
const albums: any = api |
|
|
const albums: any = api |
|
|
.get(`/getAlbumList2`, { |
|
|
.get(`/getAlbumList2`, { |
|
|
params: { |
|
|
params: { |
|
@ -446,7 +336,9 @@ export const getAllAlbums = ( |
|
|
: 'byGenre', |
|
|
: 'byGenre', |
|
|
size: 500, |
|
|
size: 500, |
|
|
offset: options.offset, |
|
|
offset: options.offset, |
|
|
genre: options.type.match('alphabeticalByName|alphabeticalByArtist|frequent|newest|recent') |
|
|
genre: options.type.match( |
|
|
|
|
|
'alphabeticalByName|alphabeticalByArtist|frequent|newest|recent' |
|
|
|
|
|
) |
|
|
? undefined |
|
|
? undefined |
|
|
: options.type, |
|
|
: options.type, |
|
|
musicFolderId: options.musicFolderId, |
|
|
musicFolderId: options.musicFolderId, |
|
@ -454,60 +346,31 @@ export const getAllAlbums = ( |
|
|
}) |
|
|
}) |
|
|
.then((res) => { |
|
|
.then((res) => { |
|
|
if (!res.data.albumList2.album || res.data.albumList2.album.length === 0) { |
|
|
if (!res.data.albumList2.album || res.data.albumList2.album.length === 0) { |
|
|
// Flatten the array and return once there are no more albums left
|
|
|
// Flatten and return once there are no more albums left
|
|
|
const flattened = _.flatten(data); |
|
|
const flattenedAlbums = _.flatten(recursiveData); |
|
|
return flattened.map((entry: any, index: any) => ({ |
|
|
return (flattenedAlbums || []).map((entry: any) => normalizeAlbum(entry)); |
|
|
...entry, |
|
|
|
|
|
title: entry.name, |
|
|
|
|
|
albumId: entry.id, |
|
|
|
|
|
image: getCoverArtUrl(entry, legacyAuth, 350), |
|
|
|
|
|
starred: entry.starred || undefined, |
|
|
|
|
|
type: 'album', |
|
|
|
|
|
isDir: false, |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
})); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// On every iteration, push the existing combined album array and increase the offset
|
|
|
// On every iteration, push the existing combined album array and increase the offset
|
|
|
data.push(res.data.albumList2.album); |
|
|
recursiveData.push(res.data.albumList2.album); |
|
|
return getAllAlbums( |
|
|
return getAlbums( |
|
|
{ |
|
|
{ |
|
|
type: options.type, |
|
|
type: options.type, |
|
|
size: options.size, |
|
|
size: options.size, |
|
|
offset: options.offset + options.size, |
|
|
offset: options.offset + options.size, |
|
|
musicFolderId: options.musicFolderId, |
|
|
musicFolderId: options.musicFolderId, |
|
|
|
|
|
recursive: true, |
|
|
}, |
|
|
}, |
|
|
data |
|
|
recursiveData |
|
|
); |
|
|
); |
|
|
}) |
|
|
}) |
|
|
.catch((err) => console.log(err)); |
|
|
.catch((err) => console.log(err)); |
|
|
|
|
|
|
|
|
return albums; |
|
|
return albums; |
|
|
}; |
|
|
} |
|
|
|
|
|
|
|
|
export const getAlbum = async (id: string) => { |
|
|
|
|
|
const { data } = await api.get(`/getAlbum`, { |
|
|
|
|
|
params: { |
|
|
|
|
|
id, |
|
|
|
|
|
}, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
const { data } = await api.get(`/getAlbumList2`, { params: options }); |
|
|
...data.album, |
|
|
return (data.albumList2.album || []).map((entry: any) => normalizeAlbum(entry)); |
|
|
image: getCoverArtUrl(data.album, legacyAuth, 350), |
|
|
|
|
|
type: 'album', |
|
|
|
|
|
isDir: false, |
|
|
|
|
|
song: (data.album.song || []).map((entry: any, index: any) => ({ |
|
|
|
|
|
...entry, |
|
|
|
|
|
streamUrl: getStreamUrl(entry.id, legacyAuth), |
|
|
|
|
|
image: getCoverArtUrl(entry, legacyAuth, 150), |
|
|
|
|
|
type: 'music', |
|
|
|
|
|
starred: entry.starred || undefined, |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
})), |
|
|
|
|
|
}; |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getRandomSongs = async (options: { |
|
|
export const getRandomSongs = async (options: { |
|
@ -517,103 +380,47 @@ export const getRandomSongs = async (options: { |
|
|
toYear?: number; |
|
|
toYear?: number; |
|
|
musicFolderId?: number; |
|
|
musicFolderId?: number; |
|
|
}) => { |
|
|
}) => { |
|
|
const { data } = await api.get(`/getRandomSongs`, { |
|
|
const { data } = await api.get(`/getRandomSongs`, { params: options }); |
|
|
params: options, |
|
|
return (data.randomSongs.song || []).map((entry: any) => normalizeSong(entry)); |
|
|
}); |
|
|
}; |
|
|
|
|
|
|
|
|
return { |
|
|
export const getArtist = async (options: { id: string }) => { |
|
|
...data.randomSongs, |
|
|
const { data } = await api.get(`/getArtist`, { params: options }); |
|
|
song: (data.randomSongs.song || []).map((entry: any, index: any) => ({ |
|
|
return normalizeArtist(data.artist); |
|
|
...entry, |
|
|
|
|
|
streamUrl: getStreamUrl(entry.id, legacyAuth), |
|
|
|
|
|
image: getCoverArtUrl(entry, legacyAuth, 150), |
|
|
|
|
|
starred: entry.starred || undefined, |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
})), |
|
|
|
|
|
}; |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getArtists = async (options: { musicFolderId?: string | number }) => { |
|
|
export const getArtists = async (options: { musicFolderId?: string | number }) => { |
|
|
const { data } = await api.get(`/getArtists`, { |
|
|
const { data } = await api.get(`/getArtists`, { params: options }); |
|
|
params: options, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const artistList: any[] = []; |
|
|
|
|
|
const artists = (data.artists?.index || []).flatMap((index: any) => index.artist); |
|
|
const artists = (data.artists?.index || []).flatMap((index: any) => index.artist); |
|
|
|
|
|
return (artists || []).map((entry: any) => normalizeArtist(entry)); |
|
|
artists.map((artist: any) => |
|
|
|
|
|
artistList.push({ |
|
|
|
|
|
...artist, |
|
|
|
|
|
image: getCoverArtUrl(artist, legacyAuth, 350), |
|
|
|
|
|
type: 'artist', |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
}) |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
return artistList; |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getArtist = async (id: string) => { |
|
|
export const getArtistInfo = async (options: { id: string; count: number }) => { |
|
|
const { data } = await api.get(`/getArtist`, { |
|
|
const { data } = await api.get(`/getArtistInfo2`, { params: options }); |
|
|
params: { |
|
|
return normalizeArtistInfo(data.artistInfo2); |
|
|
id, |
|
|
|
|
|
}, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
...data.artist, |
|
|
|
|
|
image: getCoverArtUrl(data.artist, legacyAuth, 350), |
|
|
|
|
|
type: 'artist', |
|
|
|
|
|
album: (data.artist.album || []).map((entry: any, index: any) => ({ |
|
|
|
|
|
...entry, |
|
|
|
|
|
albumId: entry.id, |
|
|
|
|
|
type: 'album', |
|
|
|
|
|
isDir: false, |
|
|
|
|
|
image: getCoverArtUrl(entry, legacyAuth, 350), |
|
|
|
|
|
starred: entry.starred || undefined, |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
})), |
|
|
|
|
|
}; |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getArtistInfo = async (id: string, count = 10) => { |
|
|
export const getArtistSongs = async (options: { id: string }) => { |
|
|
const { data } = await api.get(`/getArtistInfo2`, { |
|
|
|
|
|
params: { |
|
|
|
|
|
id, |
|
|
|
|
|
count, |
|
|
|
|
|
}, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
...data.artistInfo2, |
|
|
|
|
|
}; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
export const getAllArtistSongs = async (id: string) => { |
|
|
|
|
|
const promises = []; |
|
|
const promises = []; |
|
|
const artist = await getArtist(id); |
|
|
const artist = await getArtist({ id: options.id }); |
|
|
|
|
|
|
|
|
for (let i = 0; i < artist.album.length; i += 1) { |
|
|
for (let i = 0; i < artist.album.length; i += 1) { |
|
|
promises.push(getAlbum(artist.album[i].id)); |
|
|
promises.push(getAlbum({ id: artist.album[i].id })); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const res = await Promise.all(promises); |
|
|
const res = await Promise.all(promises); |
|
|
return _.flatten(_.map(res, 'song')); |
|
|
return (_.flatten(_.map(res, 'song')) || []).map((entry: any) => normalizeSong(entry)); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const startScan = async () => { |
|
|
export const startScan = async () => { |
|
|
const { data } = await api.get(`/startScan`); |
|
|
const { data } = await api.get(`/startScan`); |
|
|
const scanStatus = data?.scanStatus; |
|
|
const scanStatus = data?.scanStatus; |
|
|
|
|
|
|
|
|
return scanStatus; |
|
|
return scanStatus; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getScanStatus = async () => { |
|
|
export const getScanStatus = async () => { |
|
|
const { data } = await api.get(`/getScanStatus`); |
|
|
const { data } = await api.get(`/getScanStatus`); |
|
|
const scanStatus = data?.scanStatus; |
|
|
const scanStatus = data?.scanStatus; |
|
|
|
|
|
|
|
|
return scanStatus; |
|
|
return scanStatus; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
@ -668,13 +475,7 @@ export const batchStar = async (ids: string[], type: string) => { |
|
|
params.append(key, value); |
|
|
params.append(key, value); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
res.push( |
|
|
res.push((await api.get(`/star`, { params })).data); |
|
|
( |
|
|
|
|
|
await api.get(`/star`, { |
|
|
|
|
|
params, |
|
|
|
|
|
}) |
|
|
|
|
|
).data |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return res; |
|
|
return res; |
|
@ -707,42 +508,20 @@ export const batchUnstar = async (ids: string[], type: string) => { |
|
|
params.append(key, value); |
|
|
params.append(key, value); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
res.push( |
|
|
res.push((await api.get(`/unstar`, { params })).data); |
|
|
( |
|
|
|
|
|
await api.get(`/unstar`, { |
|
|
|
|
|
params, |
|
|
|
|
|
}) |
|
|
|
|
|
).data |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return res; |
|
|
return res; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const setRating = async (id: string, rating: number) => { |
|
|
export const setRating = async (id: string, rating: number) => { |
|
|
const { data } = await api.get(`/setRating`, { |
|
|
const { data } = await api.get(`/setRating`, { params: { id, rating } }); |
|
|
params: { |
|
|
|
|
|
id, |
|
|
|
|
|
rating, |
|
|
|
|
|
}, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return data; |
|
|
return data; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getSimilarSongs = async (id: string, count: number) => { |
|
|
export const getSimilarSongs = async (id: string, count: number) => { |
|
|
const { data } = await api.get(`/getSimilarSongs2`, { |
|
|
const { data } = await api.get(`/getSimilarSongs2`, { params: { id, count } }); |
|
|
params: { id, count }, |
|
|
return (data.similarSongs2.song || []).map((entry: any) => normalizeSong(entry)); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
song: (data.similarSongs2.song || []).map((entry: any, index: any) => ({ |
|
|
|
|
|
...entry, |
|
|
|
|
|
image: getCoverArtUrl(entry, legacyAuth, 150), |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
})), |
|
|
|
|
|
}; |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const updatePlaylistSongs = async (id: string, entry: any[]) => { |
|
|
export const updatePlaylistSongs = async (id: string, entry: any[]) => { |
|
@ -793,22 +572,12 @@ export const updatePlaylistSongsLg = async (playlistId: string, entry: any[]) => |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const deletePlaylist = async (id: string) => { |
|
|
export const deletePlaylist = async (id: string) => { |
|
|
const { data } = await api.get(`/deletePlaylist`, { |
|
|
const { data } = await api.get(`/deletePlaylist`, { params: { id } }); |
|
|
params: { |
|
|
|
|
|
id, |
|
|
|
|
|
}, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return data; |
|
|
return data; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const createPlaylist = async (name: string) => { |
|
|
export const createPlaylist = async (name: string) => { |
|
|
const { data } = await api.get(`/createPlaylist`, { |
|
|
const { data } = await api.get(`/createPlaylist`, { params: { name } }); |
|
|
params: { |
|
|
|
|
|
name, |
|
|
|
|
|
}, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return data; |
|
|
return data; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
@ -832,71 +601,13 @@ export const updatePlaylist = async ( |
|
|
|
|
|
|
|
|
export const clearPlaylist = async (playlistId: string) => { |
|
|
export const clearPlaylist = async (playlistId: string) => { |
|
|
// Specifying the playlistId without any songs will empty the existing playlist
|
|
|
// Specifying the playlistId without any songs will empty the existing playlist
|
|
|
const { data } = await api.get(`/createPlaylist`, { |
|
|
const { data } = await api.get(`/createPlaylist`, { params: { playlistId, songId: '' } }); |
|
|
params: { |
|
|
|
|
|
playlistId, |
|
|
|
|
|
songId: '', |
|
|
|
|
|
}, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return data; |
|
|
return data; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getGenres = async () => { |
|
|
export const getGenres = async () => { |
|
|
const { data } = await api.get(`/getGenres`); |
|
|
const { data } = await api.get(`/getGenres`); |
|
|
|
|
|
return (data.genres.genre || []).map((entry: any) => normalizeGenre(entry)); |
|
|
return (data.genres.genre || []).map((entry: any, index: any) => ({ |
|
|
|
|
|
id: entry.value, // List view uses id to match the playing song so we need an arbitrary id here
|
|
|
|
|
|
...entry, |
|
|
|
|
|
name: entry.value, |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
})); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
export const search2 = async (options: { |
|
|
|
|
|
query: string; |
|
|
|
|
|
artistCount?: number; |
|
|
|
|
|
artistOffset?: 0; |
|
|
|
|
|
albumCount?: number; |
|
|
|
|
|
albumOffset?: 0; |
|
|
|
|
|
songCount?: number; |
|
|
|
|
|
songOffset?: 0; |
|
|
|
|
|
musicFolderId?: string | number; |
|
|
|
|
|
}) => { |
|
|
|
|
|
const { data } = await api.get(`/search2`, { params: options }); |
|
|
|
|
|
|
|
|
|
|
|
const results = data.searchResult3; |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
artist: (results.artist || []).map((entry: any, index: any) => ({ |
|
|
|
|
|
...entry, |
|
|
|
|
|
image: getCoverArtUrl(entry, legacyAuth, 350), |
|
|
|
|
|
starred: entry.starred || undefined, |
|
|
|
|
|
type: 'artist', |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
})), |
|
|
|
|
|
album: (results.album || []).map((entry: any, index: any) => ({ |
|
|
|
|
|
...entry, |
|
|
|
|
|
albumId: entry.id, |
|
|
|
|
|
image: getCoverArtUrl(entry, legacyAuth, 350), |
|
|
|
|
|
starred: entry.starred || undefined, |
|
|
|
|
|
type: 'album', |
|
|
|
|
|
isDir: false, |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
})), |
|
|
|
|
|
song: (results.song || []).map((entry: any, index: any) => ({ |
|
|
|
|
|
...entry, |
|
|
|
|
|
streamUrl: getStreamUrl(entry.id, legacyAuth), |
|
|
|
|
|
image: getCoverArtUrl(entry, legacyAuth, 150), |
|
|
|
|
|
type: 'music', |
|
|
|
|
|
starred: entry.starred || undefined, |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
})), |
|
|
|
|
|
}; |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const search3 = async (options: { |
|
|
export const search3 = async (options: { |
|
@ -911,44 +622,15 @@ export const search3 = async (options: { |
|
|
}) => { |
|
|
}) => { |
|
|
const { data } = await api.get(`/search3`, { params: options }); |
|
|
const { data } = await api.get(`/search3`, { params: options }); |
|
|
|
|
|
|
|
|
const results = data.searchResult3; |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
return { |
|
|
artist: (results.artist || []).map((entry: any, index: any) => ({ |
|
|
artist: (data.searchResult3.artist || []).map((entry: any) => normalizeArtist(entry)), |
|
|
...entry, |
|
|
album: (data.searchResult3.album || []).map((entry: any) => normalizeAlbum(entry)), |
|
|
image: getCoverArtUrl(entry, legacyAuth, 350), |
|
|
song: (data.searchResult3.song || []).map((entry: any) => normalizeSong(entry)), |
|
|
starred: entry.starred || undefined, |
|
|
|
|
|
type: 'artist', |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
})), |
|
|
|
|
|
album: (results.album || []).map((entry: any, index: any) => ({ |
|
|
|
|
|
...entry, |
|
|
|
|
|
albumId: entry.id, |
|
|
|
|
|
image: getCoverArtUrl(entry, legacyAuth, 350), |
|
|
|
|
|
starred: entry.starred || undefined, |
|
|
|
|
|
type: 'album', |
|
|
|
|
|
isDir: false, |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
})), |
|
|
|
|
|
song: (results.song || []).map((entry: any, index: any) => ({ |
|
|
|
|
|
...entry, |
|
|
|
|
|
streamUrl: getStreamUrl(entry.id, legacyAuth), |
|
|
|
|
|
image: getCoverArtUrl(entry, legacyAuth, 150), |
|
|
|
|
|
type: 'music', |
|
|
|
|
|
starred: entry.starred || undefined, |
|
|
|
|
|
index, |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
})), |
|
|
|
|
|
}; |
|
|
}; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const scrobble = async (options: { id: string; time?: number; submission?: boolean }) => { |
|
|
export const scrobble = async (options: { id: string; time?: number; submission?: boolean }) => { |
|
|
const { data } = await api.get(`/scrobble`, { |
|
|
const { data } = await api.get(`/scrobble`, { params: options }); |
|
|
params: options, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return data; |
|
|
return data; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
@ -956,97 +638,49 @@ export const getIndexes = async (options: { |
|
|
musicFolderId?: string | number; |
|
|
musicFolderId?: string | number; |
|
|
ifModifiedSince?: any; |
|
|
ifModifiedSince?: any; |
|
|
}) => { |
|
|
}) => { |
|
|
const { data } = await api.get(`/getIndexes`, { |
|
|
const { data } = await api.get(`/getIndexes`, { params: options }); |
|
|
params: options, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
let folders: any[] = []; |
|
|
const folders: any[] = []; |
|
|
data.indexes.index.forEach((entry: any) => { |
|
|
data.indexes.index.forEach((entry: any) => { |
|
|
entry.artist.forEach((folder: any) => { |
|
|
entry.artist.forEach((folder: any) => { |
|
|
folders.push({ |
|
|
folders.push(normalizeFolder(folder)); |
|
|
...folder, |
|
|
|
|
|
title: folder.name, |
|
|
|
|
|
isDir: true, |
|
|
|
|
|
image: getCoverArtUrl(folder, legacyAuth, 150), |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
type: 'folder', |
|
|
|
|
|
}); |
|
|
|
|
|
}); |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
folders = _.flatten(folders); |
|
|
const child = (data.indexes?.child || []).map((entry: any) => normalizeSong(entry)); |
|
|
|
|
|
return _.concat(_.flatten(folders), child); |
|
|
const child: any[] = []; |
|
|
|
|
|
(data.indexes?.child || []).forEach((song: any, index: any) => |
|
|
|
|
|
child.push({ |
|
|
|
|
|
...song, |
|
|
|
|
|
index, |
|
|
|
|
|
type: 'music', |
|
|
|
|
|
streamUrl: getStreamUrl(song.id, legacyAuth), |
|
|
|
|
|
image: getCoverArtUrl(song, legacyAuth, 150), |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
}) |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
return _.concat(folders, child); |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getMusicFolders = async () => { |
|
|
export const getMusicFolders = async () => { |
|
|
const { data } = await api.get(`/getMusicFolders`); |
|
|
const { data } = await api.get(`/getMusicFolders`); |
|
|
|
|
|
return (data?.musicFolders?.musicFolder || []).map((entry: any) => normalizeFolder(entry)); |
|
|
return data?.musicFolders?.musicFolder; |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getMusicDirectory = async (options: { id: string }) => { |
|
|
export const getMusicDirectory = async (options: { id: string }) => { |
|
|
const { data } = await api.get(`/getMusicDirectory`, { |
|
|
const { data } = await api.get(`/getMusicDirectory`, { params: options }); |
|
|
params: options, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const child: any[] = []; |
|
|
const child: any[] = []; |
|
|
const folders = data.directory?.child?.filter((entry: any) => entry.isDir); |
|
|
const folders = data.directory?.child?.filter((entry: any) => entry.isDir); |
|
|
const songs = data.directory?.child?.filter((entry: any) => entry.isDir === false); |
|
|
const songs = data.directory?.child?.filter((entry: any) => entry.isDir === false); |
|
|
|
|
|
|
|
|
(folders || []).forEach((folder: any) => |
|
|
(folders || []).forEach((folder: any) => child.push(normalizeFolder(folder))); |
|
|
child.push({ |
|
|
(songs || []).forEach((entry: any) => child.push(normalizeSong(entry))); |
|
|
...folder, |
|
|
|
|
|
image: getCoverArtUrl(folder, legacyAuth, 150), |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
type: 'folder', |
|
|
|
|
|
}) |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
(songs || []).forEach((song: any, index: any) => |
|
|
|
|
|
child.push({ |
|
|
|
|
|
...song, |
|
|
|
|
|
index, |
|
|
|
|
|
type: 'music', |
|
|
|
|
|
streamUrl: getStreamUrl(song.id, legacyAuth), |
|
|
|
|
|
image: getCoverArtUrl(song, legacyAuth, 150), |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
}) |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
return { |
|
|
...data.directory, |
|
|
...data.directory, |
|
|
|
|
|
title: data.directory?.name, |
|
|
child, |
|
|
child, |
|
|
}; |
|
|
}; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export const getAllDirectorySongs = async (options: { id: string }, data: any[] = []) => { |
|
|
export const getDirectorySongs = async (options: { id: string }, data: any[] = []) => { |
|
|
if (options.id === 'stop') { |
|
|
if (options.id === 'stop') { |
|
|
const songs: any[] = []; |
|
|
const songs: any[] = []; |
|
|
|
|
|
|
|
|
(data || []).forEach((song: any, index: any) => { |
|
|
(data || []).forEach((song: any) => { |
|
|
(song?.child || []).forEach((entry: any) => { |
|
|
(song?.child || []).forEach((entry: any) => { |
|
|
if (entry.isDir === false) { |
|
|
if (entry.isDir === false) { |
|
|
songs.push({ |
|
|
songs.push(normalizeSong(entry)); |
|
|
...entry, |
|
|
|
|
|
index, |
|
|
|
|
|
type: 'music', |
|
|
|
|
|
streamUrl: getStreamUrl(entry.id, legacyAuth), |
|
|
|
|
|
image: getCoverArtUrl(entry, legacyAuth, 150), |
|
|
|
|
|
uniqueId: nanoid(), |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
}); |
|
@ -1059,17 +693,17 @@ export const getAllDirectorySongs = async (options: { id: string }, data: any[] |
|
|
if (res.child.filter((entry: any) => entry.isDir === true).length === 0) { |
|
|
if (res.child.filter((entry: any) => entry.isDir === true).length === 0) { |
|
|
// Add the last directory if there are no other directories
|
|
|
// Add the last directory if there are no other directories
|
|
|
data.push(res); |
|
|
data.push(res); |
|
|
return getAllDirectorySongs({ id: 'stop' }, data); |
|
|
return getDirectorySongs({ id: 'stop' }, data); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
data.push(res); |
|
|
data.push(res); |
|
|
const nestedFolders = res.child.filter((entry: any) => entry.isDir === true); |
|
|
const nestedFolders = res.child.filter((entry: any) => entry.isDir === true); |
|
|
|
|
|
|
|
|
for (let i = 0; i < nestedFolders.length; i += 1) { |
|
|
for (let i = 0; i < nestedFolders.length; i += 1) { |
|
|
await getAllDirectorySongs({ id: nestedFolders[i].id }, data); |
|
|
await getDirectorySongs({ id: nestedFolders[i].id }, data); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return getAllDirectorySongs({ id: 'stop' }, data); |
|
|
return getDirectorySongs({ id: 'stop' }, data); |
|
|
}) |
|
|
}) |
|
|
.catch((err) => console.log(err)); |
|
|
.catch((err) => console.log(err)); |
|
|
|
|
|
|
|
|