Removed MediaItem type

This commit is contained in:
Eclypsed
2024-03-27 23:53:59 -04:00
parent 2314bc638d
commit a4bad9d73b
7 changed files with 34 additions and 34 deletions

32
src/app.d.ts vendored
View File

@@ -24,8 +24,6 @@ declare global {
passwordHash: string
}
type serviceType = 'jellyfin' | 'youtube-music'
type ConnectionInfo = {
id: string
userId: string
@@ -43,27 +41,24 @@ declare global {
)
interface Connection {
getRecommendations: () => Promise<MediaItem[]>
getRecommendations: () => Promise<(Song | Album | Playlist)[]>
getConnectionInfo: () => Promise<ConnectionInfo>
search: (searchTerm: string) => Promise<MediaItem[]>
search: (searchTerm: string) => Promise<(Song | Album | Playlist)[]>
}
// These Schemas should only contain general info data that is necessary for data fetching purposes.
// They are NOT meant to be stores for large amounts of data, i.e. Don't include the data for every single song the Playlist type.
// Big data should be fetched as needed in the app, these exist to ensure that the info necessary to fetch that data is there.
interface MediaItem {
type: 'song' | 'album' | 'playlist' | 'artist'
id: string
name: string
thumbnail?: string
}
interface Song extends MediaItem {
type Song = {
connection: {
id: string
type: serviceType
}
id: string
name: string
type: 'song'
duration?: number
thumbnail?: string
artists?: {
id: string
name: string
@@ -77,13 +72,16 @@ declare global {
releaseDate?: string
}
interface Album extends MediaItem {
type Album = {
connection: {
id: string
type: serviceType
}
id: string
name: string
type: 'album'
duration?: number
thumbnail?: string
artists?: {
// Album Artists
id: string
@@ -93,8 +91,11 @@ declare global {
}
// IMPORTANT: This interface is for Lazuli created and stored playlists. Use service-specific interfaces when pulling playlists from services
interface Playlist extends MediaItem {
type Playlist = {
id: string
name: string
type: 'playlist'
thumbnail?: string
description?: string
items: {
connectionId: string
@@ -102,8 +103,11 @@ declare global {
}[]
}
interface Artist extends MediaItem {
type Artist = {
id: string
name: string
type: 'artist'
thumbnail?: string
}
namespace Jellyfin {

View File

@@ -1,14 +1,10 @@
<script lang="ts">
export let mediaItem: MediaItem
export let mediaItem: Song | Album | Playlist
import IconButton from '$lib/components/util/iconButton.svelte'
import { goto } from '$app/navigation'
let image: HTMLImageElement, captionText: HTMLDivElement
const checkSongOrAlbum = (item: MediaItem): item is Song | Album => {
return item.type === 'song' || item.type === 'album'
}
</script>
<div id="card-wrapper" class="flex-shrink-0">
@@ -29,7 +25,7 @@
<div bind:this={captionText} class="w-56 p-1">
<div class="mb-0.5 line-clamp-2 text-wrap text-sm" title={mediaItem.name}>{mediaItem.name}</div>
<div class="leading-2 line-clamp-2 text-neutral-400" style="font-size: 0;">
{#if checkSongOrAlbum(mediaItem) && 'artists' in mediaItem && mediaItem.artists}
{#if 'artists' in mediaItem && mediaItem.artists}
{#each mediaItem.artists as artist}
{@const listIndex = mediaItem.artists.indexOf(artist)}
<a class="text-sm hover:underline focus:underline" href="/details/artist?id={artist.id}&connection={mediaItem.connection.id}">{artist.name}</a>

View File

@@ -1,6 +1,6 @@
<script lang="ts">
export let header: string
export let cardDataList: MediaItem[]
export let cardDataList: (Song | Album | Playlist)[]
import MediaCard from '$lib/components/media/mediaCard.svelte'
import IconButton from '$lib/components/util/iconButton.svelte'

View File

@@ -5,7 +5,7 @@ import { generateUUID } from '$lib/utils'
interface DBConnectionsTableSchema {
id: string
userId: string
type: serviceType
type: string
service?: string
tokens?: string
}
@@ -86,7 +86,7 @@ class Storage {
const { userId, type, service, tokens } = result
const parsedService = service ? JSON.parse(service) : undefined
const parsedTokens = tokens ? JSON.parse(tokens) : undefined
connectionInfo.push({ id, userId, type, serviceInfo: parsedService, tokens: parsedTokens })
connectionInfo.push({ id, userId, type: type as DBServiceInfo['type'], serviceInfo: parsedService, tokens: parsedTokens })
}
return connectionInfo
}
@@ -97,7 +97,7 @@ class Storage {
for (const { id, type, service, tokens } of connectionRows) {
const parsedService = service ? JSON.parse(service) : undefined
const parsedTokens = tokens ? JSON.parse(tokens) : undefined
connections.push({ id, userId, type, serviceInfo: parsedService, tokens: parsedTokens })
connections.push({ id, userId, type: type as DBServiceInfo['type'], serviceInfo: parsedService, tokens: parsedTokens })
}
return connections
}

View File

@@ -52,7 +52,7 @@ export class Jellyfin implements Connection {
}
}
public getRecommendations = async (): Promise<MediaItem[]> => {
public getRecommendations = async (): Promise<(Song | Album | Playlist)[]> => {
const searchParams = new URLSearchParams({
SortBy: 'PlayCount',
SortOrder: 'Descending',
@@ -69,7 +69,7 @@ export class Jellyfin implements Connection {
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<(Song | Album | Playlist)[]> => {
const searchParams = new URLSearchParams({
searchTerm,
includeItemTypes: 'Audio,MusicAlbum', // Potentially add MusicArtist
@@ -81,7 +81,7 @@ export class Jellyfin implements Connection {
if (!searchResponse.ok) throw new JellyfinFetchError('Failed to search Jellyfin', searchResponse.status, searchURL)
const searchResults = (await searchResponse.json()).Items as (JellyfinAPI.Song | JellyfinAPI.Album)[] // JellyfinAPI.Artist
const parsedResults: MediaItem[] = Array.from(searchResults, (result) => {
const parsedResults: (Song | Album)[] = Array.from(searchResults, (result) => {
switch (result.Type) {
case 'Audio':
return this.parseSong(result)

View File

@@ -69,12 +69,12 @@ export class YouTubeMusic implements Connection {
}
}
public getRecommendations = async (): Promise<MediaItem[]> => {
public getRecommendations = async (): Promise<(Song | Album | Playlist)[]> => {
const { listenAgain, quickPicks } = await this.getHome()
return listenAgain.concat(quickPicks)
}
public search = async (searchTerm: string): Promise<MediaItem[]> => {
public search = async (searchTerm: string): Promise<(Song | Album | Playlist)[]> => {
const headers = Object.assign(this.BASEHEADERS, { authorization: `Bearer ${(await this.getTokens()).accessToken}`, 'X-Goog-Request-Time': `${Date.now()}` })
const response = await fetch(`https://music.youtube.com/youtubei/v1/search`, {
@@ -127,7 +127,7 @@ export class YouTubeMusic implements Connection {
const headerTitle = section.musicCarouselShelfRenderer.header.musicCarouselShelfBasicHeaderRenderer.title.runs[0].text
const rawContents = section.musicCarouselShelfRenderer.contents
const parsedContent: MediaItem[] =
const parsedContent: (Song | Album | Playlist)[] =
'musicTwoRowItemRenderer' in rawContents[0]
? this.parseTwoRowItemRenderer((rawContents as { musicTwoRowItemRenderer: InnerTube.musicTwoRowItemRenderer }[]).map((item) => item.musicTwoRowItemRenderer))
: this.parseResponsiveListItemRenderer((rawContents as { musicResponsiveListItemRenderer: InnerTube.musicResponsiveListItemRenderer }[]).map((item) => item.musicResponsiveListItemRenderer))
@@ -144,8 +144,8 @@ export class YouTubeMusic implements Connection {
return homeItems
}
private parseTwoRowItemRenderer = (rowContent: InnerTube.musicTwoRowItemRenderer[]): MediaItem[] => {
const parsedContent: MediaItem[] = []
private parseTwoRowItemRenderer = (rowContent: InnerTube.musicTwoRowItemRenderer[]): (Song | Album | Playlist)[] => {
const parsedContent: (Song | Album | Playlist)[] = []
for (const data of rowContent) {
const title = data.title.runs[0].text
const subtitles = data.subtitle.runs
@@ -201,7 +201,7 @@ export class YouTubeMusic implements Connection {
}
}
const thumbnail: MediaItem['thumbnail'] = refineThumbnailUrl(data.thumbnail.musicThumbnailRenderer.thumbnail.thumbnails[0].url)
const thumbnail = refineThumbnailUrl(data.thumbnail.musicThumbnailRenderer.thumbnail.thumbnails[0].url)
const song: Song = {
connection: {

View File

@@ -6,7 +6,7 @@ import { Connections } from '$lib/server/connections'
export const GET: RequestHandler = async ({ params }) => {
const userId = params.userId!
const recommendations: MediaItem[] = []
const recommendations: (Song | Album | Playlist)[] = []
for (const connection of Connections.getUserConnections(userId)) {
await connection
.getRecommendations()