Files
feishin/server/helpers/api-model.ts
T
2022-10-25 16:52:45 -07:00

521 lines
12 KiB
TypeScript

/* eslint-disable no-underscore-dangle */
import {
Album,
AlbumArtist,
AlbumArtistRating,
AlbumRating,
Artist,
ArtistRating,
External,
Genre,
Image,
ImageType,
Server,
ServerFolder,
ServerFolderPermission,
ServerPermission,
ServerType,
ServerUrl,
Song,
SongRating,
User,
UserServerUrl,
} from '@prisma/client';
const getSubsonicStreamUrl = (
remoteId: string,
url: string,
token: string,
deviceId: string
) => {
return (
`${url}/rest/stream.view` +
`?id=${remoteId}` +
`&${token}` +
`&v=1.13.0` +
`&c=Feishin_${deviceId}`
);
};
const getJellyfinStreamUrl = (
remoteId: string,
url: string,
token: string,
userId: string,
deviceId: string
) => {
return (
`${url}/audio` +
`/${remoteId}/universal` +
`?userId=${userId}` +
`&audioCodec=aac` +
`&container=opus,mp3,aac,m4a,m4b,flac,wav,ogg` +
`&transcodingContainer=ts` +
`&transcodingProtocol=hls` +
`&deviceId=Feishin_${deviceId}` +
`&playSessionId=${deviceId}` +
`&api_key=${token}`
);
};
const streamUrl = (
type: ServerType,
args: {
deviceId: string;
remoteId: string;
token: string;
url: string;
userId?: string;
}
) => {
if (type === ServerType.JELLYFIN) {
return getJellyfinStreamUrl(
args.remoteId,
args.url,
args.token,
args.userId || '',
args.deviceId
);
}
return getSubsonicStreamUrl(
args.remoteId,
args.url,
args.token,
args.deviceId
);
};
const imageUrl = (
type: ServerType,
baseUrl: string,
imageId: string,
token?: string
) => {
if (type === ServerType.JELLYFIN) {
return (
`${baseUrl}/Items` +
`/${imageId}` +
`/Images/Primary` +
'?fillHeight=250' +
`&fillWidth=250` +
'&quality=90'
);
}
if (type === ServerType.SUBSONIC || type === ServerType.NAVIDROME) {
return (
`${baseUrl}/rest/getCoverArt.view` +
`?id=${imageId}` +
`&size=250` +
`&v=1.13.0` +
`&c=Feishin` +
`&${token}`
);
}
return null;
};
const relatedAlbum = (item: Album) => {
return {
/* eslint-disable sort-keys-fix/sort-keys-fix */
id: item.id,
name: item.name,
remoteId: item.remoteId,
deleted: item.deleted,
/* eslint-enable sort-keys-fix/sort-keys-fix */
};
};
const relatedArtists = (items: Artist[]) => {
return (
items?.map((item) => {
return {
/* eslint-disable sort-keys-fix/sort-keys-fix */
id: item.id,
name: item.name,
remoteId: item.remoteId,
deleted: item.deleted,
/* eslint-enable sort-keys-fix/sort-keys-fix */
};
}) || []
);
};
const relatedAlbumArtists = (items: AlbumArtist[]) => {
return (
items?.map((item) => {
return {
/* eslint-disable sort-keys-fix/sort-keys-fix */
id: item.id,
name: item.name,
remoteId: item.remoteId,
deleted: item.deleted,
/* eslint-enable sort-keys-fix/sort-keys-fix */
};
}) || []
);
};
const relatedGenres = (items: Genre[]) => {
return (
items?.map((item) => {
return {
/* eslint-disable sort-keys-fix/sort-keys-fix */
id: item.id,
name: item.name,
/* eslint-enable sort-keys-fix/sort-keys-fix */
};
}) || []
);
};
const relatedServerFolders = (items: ServerFolder[]) => {
const serverFolders = items?.map((item) => {
return {
/* eslint-disable sort-keys-fix/sort-keys-fix */
id: item.id,
name: item.name,
remoteId: item.remoteId,
lastScannedAt: item.lastScannedAt,
/* eslint-enable sort-keys-fix/sort-keys-fix */
};
});
return serverFolders || [];
};
const relatedServerUrls = (
items: (ServerUrl & {
userServerUrls?: UserServerUrl[];
})[]
) => {
const serverUrls = items?.map((item) => {
const userServerUrlIds = item.userServerUrls?.map(
(userServerUrl) => userServerUrl.serverUrlId
);
const enabled = userServerUrlIds?.some((id) => id === item.id);
return {
/* eslint-disable sort-keys-fix/sort-keys-fix */
id: item.id,
url: item.url,
enabled,
/* eslint-enable sort-keys-fix/sort-keys-fix */
};
});
return serverUrls || [];
};
const rating = (
items: AlbumRating[] | SongRating[] | ArtistRating[] | AlbumArtistRating[]
) => {
if (items.length > 0) {
return items[0].value;
}
return null;
};
const image = (
images: Image[],
type: ServerType,
imageType: ImageType,
url: string,
remoteId: string,
token?: string
) => {
const imageRemoteUrl = images.find((i) => i.type === imageType)?.remoteUrl;
if (!imageRemoteUrl) return null;
if (type === ServerType.JELLYFIN) {
return imageUrl(type, url, remoteId);
}
if (type === ServerType.SUBSONIC || type === ServerType.NAVIDROME) {
return imageUrl(type, url, imageRemoteUrl, token);
}
return null;
};
type DbSong = Song & DbSongInclude;
type DbSongInclude = {
album: Album;
artists: Artist[];
externals: External[];
genres: Genre[];
images: Image[];
ratings: SongRating[];
server: Server & { serverUrls: ServerUrl[] };
};
const songs = (
items: DbSong[],
options: {
deviceId: string;
imageUrl?: string;
serverFolderId?: number;
token: string;
type: ServerType;
url: string;
userId: string;
}
) => {
return (
items?.map((item) => {
const url = options.url ? options.url : item.server.serverUrls[0].url;
const stream = streamUrl(options.type, {
deviceId: options.deviceId,
remoteId: item.remoteId,
token: options.token,
url: options.url,
userId: options.userId,
});
return {
/* eslint-disable sort-keys-fix/sort-keys-fix */
id: item.id,
name: item.name,
artistName: item.artistName,
album: item.album && relatedAlbum(item.album),
artists: relatedArtists(item.artists),
bitRate: item.bitRate,
container: item.container,
createdAt: item.createdAt,
deleted: item.deleted,
discNumber: item.discNumber,
duration: item.duration,
genres: relatedGenres(item.genres),
imageUrl: image(
item.images,
options.type,
ImageType.PRIMARY,
url,
item.remoteId
),
releaseDate: item.releaseDate,
releaseYear: item.releaseYear,
remoteCreatedAt: item.remoteCreatedAt,
remoteId: item.remoteId,
// serverFolderId: item.serverFolderId,
serverId: item.serverId,
streamUrl: stream,
trackNumber: item.trackNumber,
updatedAt: item.updatedAt,
/* eslint-enable sort-keys-fix/sort-keys-fix */
};
}) || []
);
};
type DbAlbum = Album & DbAlbumInclude;
type DbAlbumInclude = {
_count: {
favorites: number;
songs: number;
};
albumArtists: AlbumArtist[];
genres: Genre[];
images: Image[];
ratings: AlbumRating[];
server: Server;
serverFolders: ServerFolder[];
songs?: DbSong[];
};
const albums = (options: {
items: DbAlbum[] | any[];
serverUrl?: string;
user: User;
}) => {
const { items, serverUrl, user } = options;
return (
items?.map((item) => {
const { type, token, remoteUserId } = item.server;
const url = serverUrl || item.server.url;
return {
/* eslint-disable sort-keys-fix/sort-keys-fix */
id: item.id,
name: item.name,
sortName: item.sortName,
releaseDate: item.releaseDate,
releaseYear: item.releaseYear,
isFavorite: item.favorites.length === 1,
rating: rating(item.ratings),
songCount: item._count.songs,
type,
imageUrl: image(
item.images,
type,
ImageType.PRIMARY,
url,
item.remoteId
),
backdropImageUrl: image(
item.images,
type,
ImageType.BACKDROP,
url,
item.remoteId
),
deleted: item.deleted,
remoteId: item.remoteId,
remoteCreatedAt: item.remoteCreatedAt,
createdAt: item.createdAt,
updatedAt: item.updatedAt,
genres: item.genres ? relatedGenres(item.genres) : [],
albumArtists: item.albumArtists
? relatedAlbumArtists(item.albumArtists)
: [],
artists: item.artists ? relatedArtists(item.artists) : [],
serverFolders: relatedServerFolders(item.serverFolders),
songs:
item.songs &&
songs(item.songs, {
deviceId: user.deviceId,
token,
type,
url,
userId: remoteUserId,
}),
/* eslint-enable sort-keys-fix/sort-keys-fix */
};
}) || []
);
};
// const relatedServerCredentials = (items: ServerCredential[]) => {
// return (
// items.map((item) => {
// return {
// /* eslint-disable sort-keys-fix/sort-keys-fix */
// id: item.id,
// enabled: item.enabled,
// username: item.username,
// credential: item.credential,
// /* eslint-enable sort-keys-fix/sort-keys-fix */
// };
// }) || []
// );
// };
// const serverCredentials = (items: ServerCredential[]) => {
// return (
// items.map((item) => {
// return {
// /* eslint-disable sort-keys-fix/sort-keys-fix */
// id: item.id,
// username: item.username,
// enabled: item.enabled,
// credential: item.credential,
// createdAt: item.createdAt,
// updatedAt: item.updatedAt,
// /* eslint-enable sort-keys-fix/sort-keys-fix */
// };
// }) || []
// );
// };
const servers = (
items: (Server & {
serverFolders?: ServerFolder[];
serverUrls?: (ServerUrl & {
userServerUrls?: UserServerUrl[];
})[];
})[]
) => {
return (
items.map((item) => {
return {
/* eslint-disable sort-keys-fix/sort-keys-fix */
id: item.id,
name: item.name,
url: item.url,
type: item.type,
username: item.username,
createdAt: item.createdAt,
updatedAt: item.updatedAt,
serverFolders:
item.serverFolders && relatedServerFolders(item.serverFolders),
serverUrls: item.serverUrls && relatedServerUrls(item.serverUrls),
/* eslint-enable sort-keys-fix/sort-keys-fix */
};
}) || []
);
};
const relatedServerFolderPermissions = (items: ServerFolderPermission[]) => {
return items.map((item) => {
return {
/* eslint-disable sort-keys-fix/sort-keys-fix */
id: item.id,
serverFolderId: item.serverFolderId,
createdAt: item.createdAt,
updatedAt: item.updatedAt,
/* eslint-enable sort-keys-fix/sort-keys-fix */
};
});
};
const relatedServerPermissions = (items: ServerPermission[]) => {
return items.map((item) => {
return {
/* eslint-disable sort-keys-fix/sort-keys-fix */
id: item.id,
type: item.type,
serverId: item.serverId,
createdAt: item.createdAt,
updatedAt: item.updatedAt,
/* eslint-enable sort-keys-fix/sort-keys-fix */
};
});
};
const users = (
items: (User & {
accessToken?: string;
refreshToken?: string;
serverFolderPermissions?: ServerFolderPermission[];
serverPermissions?: ServerPermission[];
})[]
) => {
return (
items.map((item) => {
return {
/* eslint-disable sort-keys-fix/sort-keys-fix */
id: item.id,
username: item.username,
accessToken: item.accessToken,
refreshToken: item.refreshToken,
enabled: item.enabled,
isAdmin: item.isAdmin,
deviceId: item.deviceId,
createdAt: item.createdAt,
updatedAt: item.updatedAt,
flatServerPermissions:
item.serverPermissions && item.serverPermissions.map((s) => s.id),
serverFolderPermissions:
item.serverFolderPermissions &&
relatedServerFolderPermissions(item.serverFolderPermissions),
serverPermissions:
item.serverPermissions &&
relatedServerPermissions(item.serverPermissions),
/* eslint-enable sort-keys-fix/sort-keys-fix */
};
}) || []
);
};
export const toApiModel = {
albums,
servers,
songs,
users,
};