mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-08 21:10:12 +02:00
Update frontend API structure
This commit is contained in:
@@ -0,0 +1,56 @@
|
|||||||
|
import { ax } from '@/renderer/lib/axios';
|
||||||
|
import { SortOrder } from '@/types';
|
||||||
|
import {
|
||||||
|
AlbumDetailResponse,
|
||||||
|
AlbumListResponse,
|
||||||
|
PaginationParams,
|
||||||
|
} from './types';
|
||||||
|
|
||||||
|
export enum AlbumSort {
|
||||||
|
DATE_ADDED = 'added',
|
||||||
|
DATE_ADDED_REMOTE = 'addedRemote',
|
||||||
|
DATE_RELEASED = 'released',
|
||||||
|
DATE_RELEASED_YEAR = 'year',
|
||||||
|
FAVORITE = 'favorite',
|
||||||
|
NAME = 'name',
|
||||||
|
RANDOM = 'random',
|
||||||
|
RATING = 'rating',
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AlbumListParams = PaginationParams & {
|
||||||
|
orderBy: SortOrder;
|
||||||
|
serverFolderId?: string[];
|
||||||
|
serverUrlId?: string;
|
||||||
|
sortBy: AlbumSort;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAlbumDetail = async (
|
||||||
|
query: { albumId: number; serverId: string },
|
||||||
|
signal?: AbortSignal
|
||||||
|
) => {
|
||||||
|
const { data } = await ax.get<AlbumDetailResponse>(
|
||||||
|
`/servers/${query.serverId}/albums/${query.albumId}`,
|
||||||
|
{ signal }
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAlbumList = async (
|
||||||
|
query: { serverId: string },
|
||||||
|
params: AlbumListParams,
|
||||||
|
signal?: AbortSignal
|
||||||
|
) => {
|
||||||
|
const { data } = await ax.get<AlbumListResponse>(
|
||||||
|
`/servers/${query.serverId}/albums`,
|
||||||
|
{
|
||||||
|
params,
|
||||||
|
signal,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const albumsApi = {
|
||||||
|
getAlbumDetail,
|
||||||
|
getAlbumList,
|
||||||
|
};
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import { api } from '../lib';
|
|
||||||
import { AlbumResponse, AlbumsResponse, BasePaginationRequest } from './types';
|
|
||||||
|
|
||||||
export interface AlbumsRequest extends BasePaginationRequest {
|
|
||||||
orderBy: string;
|
|
||||||
serverFolderIds?: string;
|
|
||||||
sortBy: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getAlbum = async (params: { id: number }, signal?: AbortSignal) => {
|
|
||||||
const { data } = await api.get<AlbumResponse>(`/albums/${params.id}`, {
|
|
||||||
signal,
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getAlbums = async (params: AlbumsRequest, signal?: AbortSignal) => {
|
|
||||||
const { data } = await api.get<AlbumsResponse>(`/albums`, {
|
|
||||||
params,
|
|
||||||
signal,
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const albumsApi = {
|
|
||||||
getAlbum,
|
|
||||||
getAlbums,
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { albumsApi } from './albums.api';
|
||||||
|
import { authApi } from './auth.api';
|
||||||
|
import { serversApi } from './servers.api';
|
||||||
|
import { usersApi } from './users.api';
|
||||||
|
|
||||||
|
export const api = {
|
||||||
|
albums: albumsApi,
|
||||||
|
auth: authApi,
|
||||||
|
servers: serversApi,
|
||||||
|
users: usersApi,
|
||||||
|
};
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import { useQuery } from 'react-query';
|
|
||||||
import { albumsApi } from '../albumsApi';
|
|
||||||
import { queryKeys } from '../queryKeys';
|
|
||||||
|
|
||||||
export const useAlbum = (albumId: number) => {
|
|
||||||
return useQuery({
|
|
||||||
queryFn: () => albumsApi.getAlbum(albumId),
|
|
||||||
queryKey: queryKeys.album(albumId),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { AlbumListParams } from './albums.api';
|
||||||
|
|
||||||
|
export const queryKeys = {
|
||||||
|
albums: {
|
||||||
|
detail: (albumId: string) => ['albums', albumId] as const,
|
||||||
|
list: (params: AlbumListParams) => ['albums', 'list', params] as const,
|
||||||
|
root: ['albums'],
|
||||||
|
songList: (albumId: string) => ['albums', albumId, 'songs'] as const,
|
||||||
|
},
|
||||||
|
ping: (url: string) => ['ping', url] as const,
|
||||||
|
servers: {
|
||||||
|
list: () => ['servers', 'list'] as const,
|
||||||
|
},
|
||||||
|
users: {
|
||||||
|
detail: (userId: string) => ['users', userId] as const,
|
||||||
|
list: (params: any) => ['users', 'list', params] as const,
|
||||||
|
root: ['users'],
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { AlbumsRequest } from './albumsApi';
|
|
||||||
|
|
||||||
export const queryKeys = {
|
|
||||||
album: (albumId: number) => ['album', albumId] as const,
|
|
||||||
albums: (params: AlbumsRequest) => ['albums', params] as const,
|
|
||||||
ping: (url: string) => ['ping', url] as const,
|
|
||||||
servers: ['servers'] as const,
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
import {
|
||||||
|
BaseResponse,
|
||||||
|
NullResponse,
|
||||||
|
Server,
|
||||||
|
ServerType,
|
||||||
|
ServerUrl,
|
||||||
|
} from '@/renderer/api/types';
|
||||||
|
import { ax } from '@/renderer/lib/axios';
|
||||||
|
|
||||||
|
export type ServerListResponse = BaseResponse<Server[]>;
|
||||||
|
|
||||||
|
const getServerList = async (signal?: AbortSignal) => {
|
||||||
|
const { data } = await ax.get<ServerListResponse>('/servers', { signal });
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CreateServerBody = {
|
||||||
|
legacy?: boolean;
|
||||||
|
name: string;
|
||||||
|
password: string;
|
||||||
|
type: ServerType;
|
||||||
|
url: string;
|
||||||
|
username: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ServerResponse = BaseResponse<Server>;
|
||||||
|
|
||||||
|
const createServer = async (body: CreateServerBody) => {
|
||||||
|
const { data } = await ax.post<ServerResponse>('/servers', body);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateServer = async (
|
||||||
|
query: { serverId: string },
|
||||||
|
body: Partial<CreateServerBody>
|
||||||
|
) => {
|
||||||
|
const { data } = await ax.patch<ServerResponse>(
|
||||||
|
`/servers/${query.serverId}`,
|
||||||
|
body
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CreateUrlBody = {
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UrlResponse = BaseResponse<ServerUrl>;
|
||||||
|
|
||||||
|
const createUrl = async (query: { serverId: string }, body: CreateUrlBody) => {
|
||||||
|
const { data } = await ax.post<UrlResponse>(
|
||||||
|
`/servers/${query.serverId}/url`,
|
||||||
|
body
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteUrl = async (query: { serverId: string; urlId: string }) => {
|
||||||
|
const { data } = await ax.delete<NullResponse>(
|
||||||
|
`/servers/${query.serverId}/url/${query.urlId}`
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const enableUrl = async (query: { serverId: string; urlId: string }) => {
|
||||||
|
const { data } = await ax.post<NullResponse>(
|
||||||
|
`/servers/${query.serverId}/url/${query.urlId}/enable`,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const disableUrl = async (query: { serverId: string; urlId: string }) => {
|
||||||
|
const { data } = await ax.post<NullResponse>(
|
||||||
|
`/servers/${query.serverId}/url/${query.urlId}/disable`,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const serversApi = {
|
||||||
|
createServer,
|
||||||
|
createUrl,
|
||||||
|
deleteUrl,
|
||||||
|
disableUrl,
|
||||||
|
enableUrl,
|
||||||
|
getServerList,
|
||||||
|
updateServer,
|
||||||
|
};
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import { api } from '../lib';
|
|
||||||
|
|
||||||
const getServers = async () => {
|
|
||||||
const { data } = await api.get<any[]>('/servers');
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const createServer = async (body: {
|
|
||||||
name: string;
|
|
||||||
remoteUserId: string;
|
|
||||||
token: string;
|
|
||||||
url: string;
|
|
||||||
username: string;
|
|
||||||
}) => {
|
|
||||||
const { data } = await api.post<any>('/servers', body);
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const serversApi = {
|
|
||||||
createServer,
|
|
||||||
getServers,
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import md5 from 'md5';
|
||||||
|
import { ServerType } from '@/renderer/api/types';
|
||||||
|
import { randomString } from '@/renderer/utils';
|
||||||
|
|
||||||
|
type JFAuthenticate = {
|
||||||
|
AccessToken: string;
|
||||||
|
ServerId: string;
|
||||||
|
SessionInfo: any;
|
||||||
|
User: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const jfAuthenticate = async (options: {
|
||||||
|
password: string;
|
||||||
|
url: string;
|
||||||
|
username: string;
|
||||||
|
}) => {
|
||||||
|
const { password, url, username } = options;
|
||||||
|
const cleanServerUrl = url.replace(/\/$/, '');
|
||||||
|
|
||||||
|
const { data } = await axios.post<JFAuthenticate>(
|
||||||
|
`${cleanServerUrl}/users/authenticatebyname`,
|
||||||
|
{ pw: password, username },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'X-Emby-Authorization': `MediaBrowser Client="Sonixd", Device="PC", DeviceId="Sonixd", Version="1.0.0-alpha1"`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
type NDAuthenticate = {
|
||||||
|
id: string;
|
||||||
|
isAdmin: boolean;
|
||||||
|
name: string;
|
||||||
|
subsonicSalt: string;
|
||||||
|
subsonicToken: string;
|
||||||
|
token: string;
|
||||||
|
username: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ndAuthenticate = async (options: {
|
||||||
|
password: string;
|
||||||
|
url: string;
|
||||||
|
username: string;
|
||||||
|
}) => {
|
||||||
|
const { password, url, username } = options;
|
||||||
|
const cleanServerUrl = url.replace(/\/$/, '');
|
||||||
|
|
||||||
|
const { data } = await axios.post<NDAuthenticate>(
|
||||||
|
`${cleanServerUrl}/auth/login`,
|
||||||
|
{ password, username }
|
||||||
|
);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ssAuthenticate = async (options: {
|
||||||
|
legacy?: boolean;
|
||||||
|
password: string;
|
||||||
|
url: string;
|
||||||
|
username: string;
|
||||||
|
}) => {
|
||||||
|
let token;
|
||||||
|
|
||||||
|
const cleanServerUrl = options.url.replace(/\/$/, '');
|
||||||
|
|
||||||
|
if (options.legacy) {
|
||||||
|
token = `u=${options.username}&p=${options.password}`;
|
||||||
|
} else {
|
||||||
|
const salt = randomString();
|
||||||
|
const hash = md5(options.password + salt);
|
||||||
|
token = `u=${options.username}&s=${salt}&t=${hash}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await axios.get(
|
||||||
|
`${cleanServerUrl}/rest/ping.view?v=1.13.0&c=sonixd&f=json&${token}`
|
||||||
|
);
|
||||||
|
|
||||||
|
return { token, ...data };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const remoteServerLogin = async (options: {
|
||||||
|
legacy?: boolean;
|
||||||
|
password: string;
|
||||||
|
type: ServerType;
|
||||||
|
url: string;
|
||||||
|
username: string;
|
||||||
|
}) => {
|
||||||
|
if (options.type === ServerType.JELLYFIN) {
|
||||||
|
try {
|
||||||
|
const res = await jfAuthenticate({
|
||||||
|
password: options.password,
|
||||||
|
url: options.url,
|
||||||
|
username: options.username,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
remoteUserId: res.User.Id,
|
||||||
|
token: res.AccessToken,
|
||||||
|
type: ServerType.JELLYFIN,
|
||||||
|
url: options.url,
|
||||||
|
username: options.username,
|
||||||
|
};
|
||||||
|
} catch (err: any) {
|
||||||
|
return { message: err.message, type: 'error' };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.type === ServerType.SUBSONIC) {
|
||||||
|
const res = await ssAuthenticate({
|
||||||
|
legacy: options.legacy,
|
||||||
|
password: options.password,
|
||||||
|
url: options.url,
|
||||||
|
username: options.username,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.status === 'failed') {
|
||||||
|
return {
|
||||||
|
message: 'Could not validate username and password',
|
||||||
|
type: 'error',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
remoteUserId: '',
|
||||||
|
token: res.token,
|
||||||
|
type: ServerType.SUBSONIC,
|
||||||
|
url: options.url,
|
||||||
|
username: options.username,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.type === ServerType.NAVIDROME) {
|
||||||
|
try {
|
||||||
|
const res = await ndAuthenticate({
|
||||||
|
password: options.password,
|
||||||
|
url: options.url,
|
||||||
|
username: options.username,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
remoteUserId: res.id,
|
||||||
|
token: `u=${res.name}&s=${res.subsonicSalt}&t=${res.subsonicToken}`,
|
||||||
|
// token: res.token,
|
||||||
|
type: ServerType.NAVIDROME,
|
||||||
|
url: options.url,
|
||||||
|
username: options.username,
|
||||||
|
};
|
||||||
|
} catch (err: any) {
|
||||||
|
return { message: err.message, type: 'error' };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { message: 'Not found', type: 'error' };
|
||||||
|
};
|
||||||
+208
-32
@@ -1,4 +1,42 @@
|
|||||||
import { Album } from '../../types';
|
export enum ServerType {
|
||||||
|
JELLYFIN = 'JELLYFIN',
|
||||||
|
NAVIDROME = 'NAVIDROME',
|
||||||
|
SUBSONIC = 'SUBSONIC',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ServerPermissionType {
|
||||||
|
ADMIN = 'ADMIN',
|
||||||
|
EDITOR = 'EDITOR',
|
||||||
|
VIEWER = 'VIEWER',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ExternalSource {
|
||||||
|
LASTFM = 'LASTFM',
|
||||||
|
MUSICBRAINZ = 'MUSICBRAINZ',
|
||||||
|
SPOTIFY = 'SPOTIFY',
|
||||||
|
THEAUDIODB = 'THEAUDIODB',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ExternalType {
|
||||||
|
ID = 'ID',
|
||||||
|
LINK = 'LINK',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ImageType {
|
||||||
|
BACKDROP = 'BACKDROP',
|
||||||
|
LOGO = 'LOGO',
|
||||||
|
PRIMARY = 'PRIMARY',
|
||||||
|
SCREENSHOT = 'SCREENSHOT',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum TaskType {
|
||||||
|
FULL_SCAN = 'FULL_SCAN',
|
||||||
|
LASTFM = 'LASTFM',
|
||||||
|
MUSICBRAINZ = 'MUSICBRAINZ',
|
||||||
|
QUICK_SCAN = 'QUICK_SCAN',
|
||||||
|
REFRESH = 'REFRESH',
|
||||||
|
SPOTIFY = 'SPOTIFY',
|
||||||
|
}
|
||||||
|
|
||||||
export interface BaseResponse<T> {
|
export interface BaseResponse<T> {
|
||||||
data: T;
|
data: T;
|
||||||
@@ -20,45 +58,108 @@ export interface BasePaginatedResponse<T> {
|
|||||||
statusCode: number;
|
statusCode: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BasePaginationRequest {
|
export type ApiError = {
|
||||||
|
error: {
|
||||||
|
message: string;
|
||||||
|
path: string;
|
||||||
|
trace: string[];
|
||||||
|
};
|
||||||
|
response: string;
|
||||||
|
statusCode: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type NullResponse = BaseResponse<null>;
|
||||||
|
|
||||||
|
export type PaginationParams = {
|
||||||
skip: number;
|
skip: number;
|
||||||
take: number;
|
take: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export enum SortOrder {
|
||||||
|
ASC = 'asc',
|
||||||
|
DESC = 'desc',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ServerResponse = {
|
export type Server = {
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
id: number;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
remoteUserId: string;
|
remoteUserId: string;
|
||||||
serverFolder?: ServerFolderResponse[];
|
serverFolders?: RelatedServerFolder[];
|
||||||
serverType: string;
|
serverPermissions?: RelatedServerPermission[];
|
||||||
token: string;
|
serverUrls?: RelatedServerUrl[];
|
||||||
|
token?: string;
|
||||||
|
type: ServerType;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
url: string;
|
url: string;
|
||||||
username: string;
|
username: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ServerFolderResponse = {
|
export type RelatedServerFolder = {
|
||||||
createdAt: string;
|
id: string;
|
||||||
enabled: boolean;
|
lastScannedAt: string | null;
|
||||||
id: number;
|
|
||||||
isPublic: boolean;
|
|
||||||
name: string;
|
name: string;
|
||||||
remoteId: string;
|
remoteId: string;
|
||||||
serverId: number;
|
};
|
||||||
|
|
||||||
|
export type ServerFolder = {
|
||||||
|
createdAt: string;
|
||||||
|
enabled: boolean;
|
||||||
|
id: string;
|
||||||
|
lastScannedAt: string | null;
|
||||||
|
name: string;
|
||||||
|
remoteId: string;
|
||||||
|
serverId: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ServerUrl = {
|
||||||
|
createdAt: string;
|
||||||
|
id: string;
|
||||||
|
serverId: string;
|
||||||
|
updatedAt: string;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RelatedServerUrl = {
|
||||||
|
enabled: boolean;
|
||||||
|
id: string;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RelatedServerPermission = {
|
||||||
|
id: string;
|
||||||
|
type: ServerPermissionType;
|
||||||
|
};
|
||||||
|
|
||||||
export type User = {
|
export type User = {
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
id: number;
|
flatServerPermissions: string[];
|
||||||
|
id: string;
|
||||||
isAdmin: boolean;
|
isAdmin: boolean;
|
||||||
password: string;
|
password?: string;
|
||||||
|
serverFolderPermissions: ServerFolderPermission[];
|
||||||
|
serverPermissions: ServerPermission[];
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
username: string;
|
username: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ServerFolderPermission = {
|
||||||
|
createdAt: string;
|
||||||
|
id: string;
|
||||||
|
serverFolderId: string;
|
||||||
|
updatedAt: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ServerPermission = {
|
||||||
|
createdAt: string;
|
||||||
|
id: string;
|
||||||
|
serverId: string;
|
||||||
|
type: ServerPermissionType;
|
||||||
|
updatedAt: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type Login = {
|
export type Login = {
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
refreshToken: string;
|
refreshToken: string;
|
||||||
@@ -70,49 +171,124 @@ export type Ping = {
|
|||||||
version: string;
|
version: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GenreResponse = {
|
export type Genre = {
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
id: number;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ArtistResponse = {
|
export type RelatedGenre = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type External = {
|
||||||
|
createdAt: string;
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
updatedAt: string;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Image = {
|
||||||
|
createdAt: string;
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
updatedAt: string;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Album = {
|
||||||
|
albumArtists: RelatedArtist[];
|
||||||
|
artists: RelatedArtist[];
|
||||||
|
backdropImageUrl: string | null;
|
||||||
|
createdAt: string;
|
||||||
|
deleted: boolean;
|
||||||
|
genres: RelatedGenre[];
|
||||||
|
id: string;
|
||||||
|
imageUrl: string | null;
|
||||||
|
isFavorite: boolean;
|
||||||
|
name: string;
|
||||||
|
rating: number | null;
|
||||||
|
releaseDate: string | null;
|
||||||
|
releaseYear: number | null;
|
||||||
|
remoteCreatedAt: string;
|
||||||
|
remoteId: string;
|
||||||
|
serverFolders: RelatedServerFolder[];
|
||||||
|
songcount: number;
|
||||||
|
songs?: Song[];
|
||||||
|
sortName: string;
|
||||||
|
type: ServerType;
|
||||||
|
updatedAt: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Song = {
|
||||||
|
album: Album;
|
||||||
|
artistName: string;
|
||||||
|
artists: RelatedArtist[];
|
||||||
|
bitRate: number;
|
||||||
|
container: string;
|
||||||
|
createdAt: string;
|
||||||
|
deleted: boolean;
|
||||||
|
discNumber: number;
|
||||||
|
duration: number;
|
||||||
|
genres: RelatedGenre[];
|
||||||
|
id: string;
|
||||||
|
imageUrl: string;
|
||||||
|
name: string;
|
||||||
|
releaseDate: string;
|
||||||
|
releaseYear: string;
|
||||||
|
remoteCreatedAt: string;
|
||||||
|
remoteId: string;
|
||||||
|
serverFolderId: string;
|
||||||
|
serverId: string;
|
||||||
|
streamUrl: string;
|
||||||
|
trackNumber: number;
|
||||||
|
updatedAt: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AlbumArtist = {
|
||||||
biography: string | null;
|
biography: string | null;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
id: number;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
remoteCreatedAt: string | null;
|
remoteCreatedAt: string | null;
|
||||||
remoteId: string;
|
remoteId: string;
|
||||||
serverFolderId: number;
|
serverFolderId: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ExternalResponse = {
|
export type RelatedAlbumArtist = {
|
||||||
createdAt: string;
|
id: string;
|
||||||
id: number;
|
|
||||||
name: string;
|
name: string;
|
||||||
updatedAt: string;
|
remoteId: string;
|
||||||
url: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ImageResponse = {
|
export type Artist = {
|
||||||
|
biography: string | null;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
id: number;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
remoteCreatedAt: string | null;
|
||||||
|
remoteId: string;
|
||||||
|
serverFolderId: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
url: string;
|
};
|
||||||
|
|
||||||
|
export type RelatedArtist = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
remoteId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PingResponse = BaseResponse<Ping>;
|
export type PingResponse = BaseResponse<Ping>;
|
||||||
|
|
||||||
export type LoginResponse = BaseResponse<Login>;
|
export type LoginResponse = BaseResponse<Login>;
|
||||||
|
|
||||||
export type UserResponse = BaseResponse<User>;
|
export type AlbumDetailResponse = BaseResponse<Album>;
|
||||||
|
|
||||||
export type AlbumResponse = BaseResponse<Album>;
|
export type AlbumListResponse = BasePaginatedResponse<Album[]>;
|
||||||
|
|
||||||
export type AlbumsResponse = BasePaginatedResponse<Album[]>;
|
|
||||||
|
|
||||||
export type Count = {
|
export type Count = {
|
||||||
artists?: number;
|
artists?: number;
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { BaseResponse, User } from '@/renderer/api/types';
|
||||||
|
import { ax } from '@/renderer/lib/axios';
|
||||||
|
|
||||||
|
export type UserDetailResponse = BaseResponse<User>;
|
||||||
|
export type UserListResponse = BaseResponse<User[]>;
|
||||||
|
|
||||||
|
const getUserDetail = async (query: { userId: string }) => {
|
||||||
|
const { data } = await ax.get<UserDetailResponse>(`/users/${query.userId}`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getUserList = async () => {
|
||||||
|
const { data } = await ax.get<UserListResponse>('/users');
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const usersApi = {
|
||||||
|
getUserDetail,
|
||||||
|
getUserList,
|
||||||
|
};
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import { api } from '../lib';
|
|
||||||
import { UserResponse } from './types';
|
|
||||||
|
|
||||||
const getUsers = async () => {
|
|
||||||
const { data } = await api.get<UserResponse>('/users');
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const usersApi = {
|
|
||||||
getUsers,
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user