Removed db from tracking
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -8,3 +8,4 @@ node_modules
|
|||||||
!.env.example
|
!.env.example
|
||||||
vite.config.js.timestamp-*
|
vite.config.js.timestamp-*
|
||||||
vite.config.ts.timestamp-*
|
vite.config.ts.timestamp-*
|
||||||
|
*.db
|
||||||
@@ -66,43 +66,49 @@ export class Jellyfin implements Connection {
|
|||||||
const mostPlayedResponse = await fetch(mostPlayedSongsURL, { headers: this.BASEHEADERS })
|
const mostPlayedResponse = await fetch(mostPlayedSongsURL, { headers: this.BASEHEADERS })
|
||||||
const mostPlayedData = await mostPlayedResponse.json()
|
const mostPlayedData = await mostPlayedResponse.json()
|
||||||
|
|
||||||
return Array.from(mostPlayedData.Items as JellyfinAPI.Song[], (song) => this.songFactory(song))
|
return Array.from(mostPlayedData.Items as JellyfinAPI.Song[], (song) => this.parseSong(song))
|
||||||
}
|
}
|
||||||
|
|
||||||
public search = async (searchTerm: string): Promise<MediaItem[]> => {
|
public search = async (searchTerm: string): Promise<MediaItem[]> => {
|
||||||
const searchParams = new URLSearchParams({
|
const searchParams = new URLSearchParams({
|
||||||
userId: this.jfUserId,
|
|
||||||
searchTerm,
|
searchTerm,
|
||||||
includeItemTypes: 'Audio,MusicAlbum,MusicArtist',
|
includeItemTypes: 'Audio,MusicAlbum', // Potentially add MusicArtist
|
||||||
|
recursive: 'true',
|
||||||
})
|
})
|
||||||
|
|
||||||
const searchURL = new URL(`Search/Hints?${searchParams.toString()}`, this.serverUrl).toString()
|
const searchURL = new URL(`Users/${this.jfUserId}/Items?${searchParams.toString()}`, this.serverUrl).toString()
|
||||||
const searchResponse = await fetch(searchURL, { headers: this.BASEHEADERS })
|
const searchResponse = await fetch(searchURL, { headers: this.BASEHEADERS })
|
||||||
if (!searchResponse.ok) throw new JellyfinFetchError('Failed to search Jellyfin', searchResponse.status, searchURL)
|
if (!searchResponse.ok) throw new JellyfinFetchError('Failed to search Jellyfin', searchResponse.status, searchURL)
|
||||||
const searchResults = (await searchResponse.json()).SearchHints as JellyfinAPI.SearchHint[]
|
const searchResults = (await searchResponse.json()).Items as (JellyfinAPI.Song | JellyfinAPI.Album)[] // JellyfinAPI.Artist
|
||||||
|
|
||||||
|
const parsedResults: MediaItem[] = []
|
||||||
|
searchResults.forEach((result) => {
|
||||||
|
switch (result.Type) {
|
||||||
|
case 'Audio':
|
||||||
|
parsedResults.push(this.parseSong(result))
|
||||||
|
break
|
||||||
|
case 'MusicAlbum':
|
||||||
|
parsedResults.push(this.parseAlbum(result))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return parsedResults
|
||||||
}
|
}
|
||||||
|
|
||||||
private mediaItemFactory = (mediaItem: JellyfinAPI.MediaItem): MediaItem => {
|
private parseSong = (song: JellyfinAPI.Song): Song => {
|
||||||
const thumbnail = mediaItem.ImageTags?.Primary
|
|
||||||
? new URL(`Items/${mediaItem.Id}/Images/Primary`, this.serverUrl).toString()
|
|
||||||
: mediaItem.
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private songFactory = (song: JellyfinAPI.Song): Song => {
|
|
||||||
const thumbnail = song.ImageTags?.Primary
|
const thumbnail = song.ImageTags?.Primary
|
||||||
? new URL(`Items/${song.Id}/Images/Primary`, this.serverUrl).href
|
? new URL(`Items/${song.Id}/Images/Primary`, this.serverUrl).href
|
||||||
: song.AlbumPrimaryImageTag
|
: song.AlbumPrimaryImageTag
|
||||||
? new URL(`Items/${song.AlbumId}/Images/Primary`, this.serverUrl).href
|
? new URL(`Items/${song.AlbumId}/Images/Primary`, this.serverUrl).href
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
const artists = song.ArtistItems
|
const artists: Song['artists'] = song.ArtistItems
|
||||||
? Array.from(song.ArtistItems, (artist) => {
|
? Array.from(song.ArtistItems, (artist) => {
|
||||||
return { id: artist.Id, name: artist.Name }
|
return { id: artist.Id, name: artist.Name }
|
||||||
})
|
})
|
||||||
: []
|
: undefined
|
||||||
|
|
||||||
// Add Album details
|
const album: Song['album'] = song.AlbumId && song.Album ? { id: song.AlbumId, name: song.Album } : undefined
|
||||||
|
|
||||||
return {
|
return {
|
||||||
connection: {
|
connection: {
|
||||||
@@ -112,10 +118,35 @@ export class Jellyfin implements Connection {
|
|||||||
type: 'song',
|
type: 'song',
|
||||||
id: song.Id,
|
id: song.Id,
|
||||||
name: song.Name,
|
name: song.Name,
|
||||||
duration: Math.floor(song.RunTimeTicks / 10000),
|
duration: ticksToSeconds(song.RunTimeTicks),
|
||||||
thumbnail,
|
thumbnail,
|
||||||
artists,
|
artists,
|
||||||
releaseDate: String(song.ProductionYear),
|
album,
|
||||||
|
releaseDate: song.ProductionYear?.toString(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private parseAlbum = (album: JellyfinAPI.Album): Album => {
|
||||||
|
const thumbnail = album.ImageTags?.Primary ? new URL(`Items/${album.Id}/Images/Primary`, this.serverUrl).toString() : undefined
|
||||||
|
|
||||||
|
const artists: Album['artists'] = album.AlbumArtists
|
||||||
|
? Array.from(album.AlbumArtists, (artist) => {
|
||||||
|
return { id: artist.Id, name: artist.Name }
|
||||||
|
})
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
return {
|
||||||
|
connection: {
|
||||||
|
id: this.id,
|
||||||
|
type: 'jellyfin',
|
||||||
|
},
|
||||||
|
type: 'album',
|
||||||
|
id: album.Id,
|
||||||
|
name: album.Name,
|
||||||
|
duration: ticksToSeconds(album.RunTimeTicks),
|
||||||
|
thumbnail,
|
||||||
|
artists,
|
||||||
|
releaseDate: album.ProductionYear?.toString(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,6 +173,8 @@ export class Jellyfin implements Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ticksToSeconds = (ticks: number): number => Math.floor(ticks / 10000)
|
||||||
|
|
||||||
export class JellyfinFetchError extends Error {
|
export class JellyfinFetchError extends Error {
|
||||||
public httpCode: number
|
public httpCode: number
|
||||||
public url: string
|
public url: string
|
||||||
@@ -168,75 +201,64 @@ declare namespace JellyfinAPI {
|
|||||||
ServerName: string
|
ServerName: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MediaItem {
|
type Song = {
|
||||||
Name: string
|
Name: string
|
||||||
Id: string
|
Id: string
|
||||||
Type: 'Audio' | 'MusicAlbum' | 'Playlist' | 'MusicArtist'
|
|
||||||
ImageTags?: {
|
|
||||||
Primary?: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Song extends JellyfinAPI.MediaItem {
|
|
||||||
RunTimeTicks: number
|
|
||||||
ProductionYear: number
|
|
||||||
Type: 'Audio'
|
Type: 'Audio'
|
||||||
ArtistItems: {
|
RunTimeTicks: number
|
||||||
|
ProductionYear?: number
|
||||||
|
ArtistItems?: {
|
||||||
Name: string
|
Name: string
|
||||||
Id: string
|
Id: string
|
||||||
}[]
|
}[]
|
||||||
Album?: string
|
Album?: string
|
||||||
AlbumId?: string
|
AlbumId?: string
|
||||||
AlbumPrimaryImageTag?: string
|
AlbumPrimaryImageTag?: string
|
||||||
AlbumArtists: {
|
AlbumArtists?: {
|
||||||
Name: string
|
Name: string
|
||||||
Id: string
|
Id: string
|
||||||
}[]
|
}[]
|
||||||
|
ImageTags?: {
|
||||||
|
Primary?: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Album extends JellyfinAPI.MediaItem {
|
type Album = {
|
||||||
RunTimeTicks: number
|
Name: string
|
||||||
ProductionYear: number
|
Id: string
|
||||||
Type: 'MusicAlbum'
|
Type: 'MusicAlbum'
|
||||||
ArtistItems: {
|
RunTimeTicks: number
|
||||||
|
ProductionYear?: number
|
||||||
|
ArtistItems?: {
|
||||||
Name: string
|
Name: string
|
||||||
Id: string
|
Id: string
|
||||||
}[]
|
}[]
|
||||||
AlbumArtists: {
|
AlbumArtists?: {
|
||||||
Name: string
|
Name: string
|
||||||
Id: string
|
Id: string
|
||||||
}[]
|
}[]
|
||||||
|
ImageTags?: {
|
||||||
|
Primary?: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Playlist extends JellyfinAPI.MediaItem {
|
type Playlist = {
|
||||||
RunTimeTicks: number
|
Name: string
|
||||||
|
Id: string
|
||||||
Type: 'Playlist'
|
Type: 'Playlist'
|
||||||
|
RunTimeTicks: number
|
||||||
ChildCount: number
|
ChildCount: number
|
||||||
|
ImageTags?: {
|
||||||
|
Primary?: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Artist extends JellyfinAPI.MediaItem {
|
type Artist = {
|
||||||
Type: 'MusicArtist'
|
|
||||||
}
|
|
||||||
|
|
||||||
type SearchHint = {
|
|
||||||
Id: string
|
|
||||||
Name: string
|
Name: string
|
||||||
PrimaryImageTag?: string
|
Id: string
|
||||||
} & ({
|
|
||||||
Type: 'Audio'
|
|
||||||
RunTimeTicks: number
|
|
||||||
ProductionYear?: number
|
|
||||||
AlbumId: string // When no album exists, the id defaults to: "00000000000000000000000000000000"
|
|
||||||
Album?: string
|
|
||||||
Artists: {
|
|
||||||
[key: number]: string
|
|
||||||
}[]
|
|
||||||
} | {
|
|
||||||
Type: 'MusicArtist'
|
Type: 'MusicArtist'
|
||||||
} | {
|
ImageTags?: {
|
||||||
Type: 'MusicAlbum'
|
Primary?: string
|
||||||
RunTimeTicks: number
|
}
|
||||||
ProductionYear?: number
|
}
|
||||||
AlbumArtist: string
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user