diff --git a/.idea/reiverr.iml b/.idea/reiverr.iml index 24643cc..c681724 100644 --- a/.idea/reiverr.iml +++ b/.idea/reiverr.iml @@ -5,6 +5,8 @@ + + diff --git a/src/lib/jellyfin/jellyfin-types.d.ts b/src/lib/apis/jellyfin/jellyfin.generated.d.ts similarity index 100% rename from src/lib/jellyfin/jellyfin-types.d.ts rename to src/lib/apis/jellyfin/jellyfin.generated.d.ts diff --git a/src/lib/jellyfin/jellyfin.ts b/src/lib/apis/jellyfin/jellyfinApi.ts similarity index 95% rename from src/lib/jellyfin/jellyfin.ts rename to src/lib/apis/jellyfin/jellyfinApi.ts index cfd9542..34d4807 100644 --- a/src/lib/jellyfin/jellyfin.ts +++ b/src/lib/apis/jellyfin/jellyfinApi.ts @@ -1,8 +1,8 @@ import createClient from 'openapi-fetch'; -import type { paths } from '$lib/jellyfin/jellyfin-types'; +import type { paths } from '$lib/apis/jellyfin/jellyfin.generated'; import { PUBLIC_JELLYFIN_API_KEY, PUBLIC_JELLYFIN_URL } from '$env/static/public'; import { request } from '$lib/utils'; -import type { DeviceProfile } from '$lib/jellyfin/playback-profiles'; +import type { DeviceProfile } from '$lib/apis/jellyfin/playback-profiles'; export const JELLYFIN_DEVICE_ID = 'Reiverr Client'; export const JELLYFIN_USER_ID = '75dcb061c9404115a7acdc893ea6bbbc'; diff --git a/src/lib/jellyfin/playback-profiles/directplay-profile.ts b/src/lib/apis/jellyfin/playback-profiles/directplay-profile.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/directplay-profile.ts rename to src/lib/apis/jellyfin/playback-profiles/directplay-profile.ts diff --git a/src/lib/jellyfin/playback-profiles/helpers/audio-formats.ts b/src/lib/apis/jellyfin/playback-profiles/helpers/audio-formats.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/helpers/audio-formats.ts rename to src/lib/apis/jellyfin/playback-profiles/helpers/audio-formats.ts diff --git a/src/lib/jellyfin/playback-profiles/helpers/codec-profiles.ts b/src/lib/apis/jellyfin/playback-profiles/helpers/codec-profiles.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/helpers/codec-profiles.ts rename to src/lib/apis/jellyfin/playback-profiles/helpers/codec-profiles.ts diff --git a/src/lib/jellyfin/playback-profiles/helpers/fmp4-audio-formats.ts b/src/lib/apis/jellyfin/playback-profiles/helpers/fmp4-audio-formats.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/helpers/fmp4-audio-formats.ts rename to src/lib/apis/jellyfin/playback-profiles/helpers/fmp4-audio-formats.ts diff --git a/src/lib/jellyfin/playback-profiles/helpers/fmp4-video-formats.ts b/src/lib/apis/jellyfin/playback-profiles/helpers/fmp4-video-formats.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/helpers/fmp4-video-formats.ts rename to src/lib/apis/jellyfin/playback-profiles/helpers/fmp4-video-formats.ts diff --git a/src/lib/jellyfin/playback-profiles/helpers/hls-formats.ts b/src/lib/apis/jellyfin/playback-profiles/helpers/hls-formats.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/helpers/hls-formats.ts rename to src/lib/apis/jellyfin/playback-profiles/helpers/hls-formats.ts diff --git a/src/lib/jellyfin/playback-profiles/helpers/mp4-audio-formats.ts b/src/lib/apis/jellyfin/playback-profiles/helpers/mp4-audio-formats.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/helpers/mp4-audio-formats.ts rename to src/lib/apis/jellyfin/playback-profiles/helpers/mp4-audio-formats.ts diff --git a/src/lib/jellyfin/playback-profiles/helpers/mp4-video-formats.ts b/src/lib/apis/jellyfin/playback-profiles/helpers/mp4-video-formats.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/helpers/mp4-video-formats.ts rename to src/lib/apis/jellyfin/playback-profiles/helpers/mp4-video-formats.ts diff --git a/src/lib/jellyfin/playback-profiles/helpers/transcoding-formats.ts b/src/lib/apis/jellyfin/playback-profiles/helpers/transcoding-formats.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/helpers/transcoding-formats.ts rename to src/lib/apis/jellyfin/playback-profiles/helpers/transcoding-formats.ts diff --git a/src/lib/jellyfin/playback-profiles/helpers/ts-audio-formats.ts b/src/lib/apis/jellyfin/playback-profiles/helpers/ts-audio-formats.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/helpers/ts-audio-formats.ts rename to src/lib/apis/jellyfin/playback-profiles/helpers/ts-audio-formats.ts diff --git a/src/lib/jellyfin/playback-profiles/helpers/ts-video-formats.ts b/src/lib/apis/jellyfin/playback-profiles/helpers/ts-video-formats.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/helpers/ts-video-formats.ts rename to src/lib/apis/jellyfin/playback-profiles/helpers/ts-video-formats.ts diff --git a/src/lib/jellyfin/playback-profiles/helpers/webm-audio-formats.ts b/src/lib/apis/jellyfin/playback-profiles/helpers/webm-audio-formats.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/helpers/webm-audio-formats.ts rename to src/lib/apis/jellyfin/playback-profiles/helpers/webm-audio-formats.ts diff --git a/src/lib/jellyfin/playback-profiles/helpers/webm-video-formats.ts b/src/lib/apis/jellyfin/playback-profiles/helpers/webm-video-formats.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/helpers/webm-video-formats.ts rename to src/lib/apis/jellyfin/playback-profiles/helpers/webm-video-formats.ts diff --git a/src/lib/jellyfin/playback-profiles/index.ts b/src/lib/apis/jellyfin/playback-profiles/index.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/index.ts rename to src/lib/apis/jellyfin/playback-profiles/index.ts diff --git a/src/lib/jellyfin/playback-profiles/response-profile.ts b/src/lib/apis/jellyfin/playback-profiles/response-profile.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/response-profile.ts rename to src/lib/apis/jellyfin/playback-profiles/response-profile.ts diff --git a/src/lib/jellyfin/playback-profiles/subtitle-profile.ts b/src/lib/apis/jellyfin/playback-profiles/subtitle-profile.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/subtitle-profile.ts rename to src/lib/apis/jellyfin/playback-profiles/subtitle-profile.ts diff --git a/src/lib/jellyfin/playback-profiles/transcoding-profile.ts b/src/lib/apis/jellyfin/playback-profiles/transcoding-profile.ts similarity index 100% rename from src/lib/jellyfin/playback-profiles/transcoding-profile.ts rename to src/lib/apis/jellyfin/playback-profiles/transcoding-profile.ts diff --git a/src/lib/radarr/radarr-types.d.ts b/src/lib/apis/radarr/radarr.generated.d.ts similarity index 100% rename from src/lib/radarr/radarr-types.d.ts rename to src/lib/apis/radarr/radarr.generated.d.ts diff --git a/src/lib/radarr/radarr.ts b/src/lib/apis/radarr/radarrApi.ts similarity index 78% rename from src/lib/radarr/radarr.ts rename to src/lib/apis/radarr/radarrApi.ts index d2cea19..e7492a3 100644 --- a/src/lib/radarr/radarr.ts +++ b/src/lib/apis/radarr/radarrApi.ts @@ -1,13 +1,14 @@ import createClient from 'openapi-fetch'; import { log, request } from '$lib/utils'; -import type { paths } from '$lib/radarr/radarr-types'; -import type { components } from '$lib/radarr/radarr-types'; -import { fetchTmdbMovie } from '$lib/tmdb-api'; -import { RADARR_API_KEY, RADARR_BASE_URL } from '$env/static/private'; +import type { paths } from '$lib/apis/radarr/radarr.generated'; +import type { components } from '$lib/apis/radarr/radarr.generated'; +import { fetchTmdbMovie } from '$lib/apis/tmdbApi'; +import { PUBLIC_RADARR_API_KEY, PUBLIC_RADARR_BASE_URL } from '$env/static/public'; export type RadarrMovie = components['schemas']['MovieResource']; export type MovieFileResource = components['schemas']['MovieFileResource']; export type ReleaseResource = components['schemas']['ReleaseResource']; +export type RadarrDownload = components['schemas']['QueueResource'] & { movie: RadarrMovie }; export interface RadarrMovieOptions { title: string; @@ -23,20 +24,20 @@ export interface RadarrMovieOptions { } export const RadarrApi = createClient({ - baseUrl: RADARR_BASE_URL, + baseUrl: PUBLIC_RADARR_BASE_URL, headers: { - 'X-Api-Key': RADARR_API_KEY + 'X-Api-Key': PUBLIC_RADARR_API_KEY } }); -export const getRadarrMovies = () => +export const getRadarrMovies = (): Promise => RadarrApi.get('/api/v3/movie', { params: {} - }).then((r) => r.data); + }).then((r) => r.data || []); export const requestRadarrMovie = () => request(getRadarrMovie); -export const getRadarrMovie = (tmdbId: string) => +export const getRadarrMovie = (tmdbId: string): Promise => RadarrApi.get('/api/v3/movie', { params: { query: { @@ -121,16 +122,17 @@ export const deleteRadarrMovie = (id: number) => export const requestRadarrQueuedById = () => request(getRadarrDownload); -export const getRadarrDownload = (id: string) => +export const getRadarrDownloads = (): Promise => RadarrApi.get('/api/v3/queue', { params: { query: { includeMovie: true } } - }) - .then((r) => r.data) - .then((queue) => queue?.records?.filter((r) => (r?.movie?.id as any) == id)); + }).then((r) => (r.data?.records?.filter((record) => record.movie) as RadarrDownload[]) || []); + +export const getRadarrDownload = (id: string) => + getRadarrDownloads().then((downloads) => downloads.find((d) => d.movie.id === Number(id))); const getMovieByTmdbIdByTmdbId = (tmdbId: string) => RadarrApi.get('/api/v3/movie/lookup/tmdb', { diff --git a/src/lib/sonarr/sonarr-types.d.ts b/src/lib/apis/sonarr/sonarr.generated.d.ts similarity index 100% rename from src/lib/sonarr/sonarr-types.d.ts rename to src/lib/apis/sonarr/sonarr.generated.d.ts diff --git a/src/lib/apis/sonarr/sonarrApi.ts b/src/lib/apis/sonarr/sonarrApi.ts new file mode 100644 index 0000000..05c765c --- /dev/null +++ b/src/lib/apis/sonarr/sonarrApi.ts @@ -0,0 +1,10 @@ +import createClient from 'openapi-fetch'; +import type { paths } from '$lib/apis/sonarr/sonarr.generated'; +import { PUBLIC_SONARR_API_KEY, PUBLIC_SONARR_BASE_URL } from '$env/static/public'; + +export const SonarrApi = createClient({ + baseUrl: PUBLIC_SONARR_BASE_URL, + headers: { + 'X-Api-Key': PUBLIC_SONARR_API_KEY + } +}); diff --git a/src/lib/tmdb-api.ts b/src/lib/apis/tmdbApi.ts similarity index 100% rename from src/lib/tmdb-api.ts rename to src/lib/apis/tmdbApi.ts diff --git a/src/routes/components/Ui/Button.svelte b/src/lib/components/Button.svelte similarity index 100% rename from src/routes/components/Ui/Button.svelte rename to src/lib/components/Button.svelte diff --git a/src/routes/components/Card/Card.svelte b/src/lib/components/Card/Card.svelte similarity index 97% rename from src/routes/components/Card/Card.svelte rename to src/lib/components/Card/Card.svelte index f894fbb..7135029 100644 --- a/src/routes/components/Card/Card.svelte +++ b/src/lib/components/Card/Card.svelte @@ -14,7 +14,6 @@ export let available = true; export let progress = 0; - export let progressType: 'watched' | 'downloading' = 'watched'; export let type: 'dynamic' | 'normal' | 'large' = 'normal'; export let randomProgress = false; if (randomProgress) { diff --git a/src/routes/components/Card/CardPlaceholder.svelte b/src/lib/components/Card/CardPlaceholder.svelte similarity index 100% rename from src/routes/components/Card/CardPlaceholder.svelte rename to src/lib/components/Card/CardPlaceholder.svelte diff --git a/src/routes/components/Card/CardProvider.svelte b/src/lib/components/Card/CardProvider.svelte similarity index 85% rename from src/routes/components/Card/CardProvider.svelte rename to src/lib/components/Card/CardProvider.svelte index 21a380b..4e729d8 100644 --- a/src/routes/components/Card/CardProvider.svelte +++ b/src/lib/components/Card/CardProvider.svelte @@ -1,9 +1,9 @@
@@ -196,7 +197,7 @@
@@ -219,29 +220,29 @@
-

Details

+

Details

-
+
{movie.genres.map((g) => g.name.charAt(0).toUpperCase() + g.name.slice(1)).join(', ')}
-
- +
+
{Math.floor(movie.runtime / 60)}h {movie.runtime % 60}m
-
+
Currently Streaming
{movie.vote_average.toFixed(1)} TMDB -
+
{#if castMembers?.length > 0} -

Starring

+

Starring

{#each castMembers.slice(0, 5) as a} {a.name}{a.name} {/each} View all...View all...
{/if} @@ -285,7 +286,7 @@ jellyfinId && streamJellyfinId(jellyfinId)} jellyfinStreamDisabled={streamButtonDisabled} - tmdbId={movie.id} + tmdbId={String(movie.id)} /> {/key} diff --git a/src/routes/components/SetupRequired/SetupRequired.svelte b/src/lib/components/SetupRequired/SetupRequired.svelte similarity index 100% rename from src/routes/components/SetupRequired/SetupRequired.svelte rename to src/lib/components/SetupRequired/SetupRequired.svelte diff --git a/src/routes/components/SourceStats/RadarrStats.svelte b/src/lib/components/SourceStats/RadarrStats.svelte similarity index 75% rename from src/routes/components/SourceStats/RadarrStats.svelte rename to src/lib/components/SourceStats/RadarrStats.svelte index 782055a..2f28ca5 100644 --- a/src/routes/components/SourceStats/RadarrStats.svelte +++ b/src/lib/components/SourceStats/RadarrStats.svelte @@ -1,24 +1,22 @@ -{#await statsRequest} +{#await fetchStats()} {:then { moviesAmount }}

{subtitle}

- {title} + {title}
{#each stats as { title, value }} diff --git a/src/routes/components/SourceStats/StatsPlaceholder.svelte b/src/lib/components/SourceStats/StatsPlaceholder.svelte similarity index 100% rename from src/routes/components/SourceStats/StatsPlaceholder.svelte rename to src/lib/components/SourceStats/StatsPlaceholder.svelte diff --git a/src/routes/components/VideoPlayer/VideoPlayer.svelte b/src/lib/components/VideoPlayer/VideoPlayer.svelte similarity index 91% rename from src/routes/components/VideoPlayer/VideoPlayer.svelte rename to src/lib/components/VideoPlayer/VideoPlayer.svelte index f30ed20..87098ee 100644 --- a/src/routes/components/VideoPlayer/VideoPlayer.svelte +++ b/src/lib/components/VideoPlayer/VideoPlayer.svelte @@ -5,7 +5,7 @@ reportJellyfinPlaybackProgress, reportJellyfinPlaybackStarted, reportJellyfinPlaybackStopped - } from '$lib/jellyfin/jellyfin'; + } from '$lib/apis/jellyfin/jellyfinApi'; import Hls from 'hls.js'; import Modal from '../Modal/Modal.svelte'; import IconButton from '../IconButton.svelte'; @@ -13,10 +13,10 @@ import classNames from 'classnames'; import { getContext, onDestroy } from 'svelte'; import { PUBLIC_JELLYFIN_URL } from '$env/static/public'; - import getDeviceProfile from '$lib/jellyfin/playback-profiles'; + import getDeviceProfile from '$lib/apis/jellyfin/playback-profiles'; import type { PlayerState, PlayerStateValue } from './VideoPlayer'; - const { playerState, close }: PlayerState = getContext('player'); + const { playerState, close } = getContext('player'); let video: HTMLVideoElement; @@ -44,7 +44,7 @@ video.currentTime = item?.UserData?.PlaybackPositionTicks / 10_000_000; } }); - await reportJellyfinPlaybackStarted(itemId, sessionId, mediaSourceId); + if (mediaSourceId) await reportJellyfinPlaybackStarted(itemId, sessionId, mediaSourceId); progressInterval = setInterval(() => { reportJellyfinPlaybackProgress( itemId, diff --git a/src/routes/components/VideoPlayer/VideoPlayer.ts b/src/lib/components/VideoPlayer/VideoPlayer.ts similarity index 100% rename from src/routes/components/VideoPlayer/VideoPlayer.ts rename to src/lib/components/VideoPlayer/VideoPlayer.ts diff --git a/src/routes/components/svgs/RadarrIcon.svelte b/src/lib/components/svgs/RadarrIcon.svelte similarity index 100% rename from src/routes/components/svgs/RadarrIcon.svelte rename to src/lib/components/svgs/RadarrIcon.svelte diff --git a/src/routes/components/svgs/SonarrIcon.svelte b/src/lib/components/svgs/SonarrIcon.svelte similarity index 100% rename from src/routes/components/svgs/SonarrIcon.svelte rename to src/lib/components/svgs/SonarrIcon.svelte diff --git a/src/routes/components/Utils/WidthLimited.svelte b/src/lib/components/utils/WidthLimited.svelte similarity index 100% rename from src/routes/components/Utils/WidthLimited.svelte rename to src/lib/components/utils/WidthLimited.svelte diff --git a/src/lib/images/github.svg b/src/lib/images/github.svg deleted file mode 100644 index bc5d249..0000000 --- a/src/lib/images/github.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/lib/images/svelte-logo.svg b/src/lib/images/svelte-logo.svg deleted file mode 100644 index 49492a8..0000000 --- a/src/lib/images/svelte-logo.svg +++ /dev/null @@ -1 +0,0 @@ -svelte-logo \ No newline at end of file diff --git a/src/lib/images/svelte-welcome.png b/src/lib/images/svelte-welcome.png deleted file mode 100644 index fe7d2d6..0000000 Binary files a/src/lib/images/svelte-welcome.png and /dev/null differ diff --git a/src/lib/images/svelte-welcome.webp b/src/lib/images/svelte-welcome.webp deleted file mode 100644 index 6ec1a28..0000000 Binary files a/src/lib/images/svelte-welcome.webp and /dev/null differ diff --git a/src/lib/jellyfin/jellyfin-state.ts b/src/lib/jellyfin/jellyfin-state.ts deleted file mode 100644 index 9ff3665..0000000 --- a/src/lib/jellyfin/jellyfin-state.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { writable } from 'svelte/store'; - -async function fetchJellyfinState() { - return new Promise((resolve, reject) => { - setTimeout(() => resolve('true'), 2000); - }); -} - -export const jellyfinState = writable(fetchJellyfinState()); diff --git a/src/lib/sonarr/sonarr.ts b/src/lib/sonarr/sonarr.ts deleted file mode 100644 index 17868a4..0000000 --- a/src/lib/sonarr/sonarr.ts +++ /dev/null @@ -1,10 +0,0 @@ -import createClient from 'openapi-fetch'; -import type { paths } from '$lib/sonarr/sonarr-types'; -import { SONARR_API_KEY, SONARR_BASE_URL } from '$env/static/private'; - -export const SonarrApi = createClient({ - baseUrl: SONARR_BASE_URL, - headers: { - 'X-Api-Key': SONARR_API_KEY - } -}); diff --git a/src/lib/stores/libraryStore.ts b/src/lib/stores/libraryStore.ts new file mode 100644 index 0000000..52660be --- /dev/null +++ b/src/lib/stores/libraryStore.ts @@ -0,0 +1,68 @@ +import { + getRadarrDownloads, + getRadarrMovies, + RadarrApi, + type RadarrMovie +} from '$lib/apis/radarr/radarrApi'; +import type { CardProps } from '$lib/components/Card/card'; +import { writable } from 'svelte/store'; +import { fetchCardProps } from '$lib/components/Card/card'; +import { fetchTmdbMovieImages } from '$lib/apis/tmdbApi'; + +interface PlayableRadarrMovie extends RadarrMovie { + cardBackdropUrl: string; + download?: { + progress: number; + completionTime: string; + }; +} + +export interface Library { + movies: PlayableRadarrMovie[]; + totalMovies: number; +} + +interface DownloadingCardProps extends CardProps { + progress: number; + completionTime: string; +} + +async function getLibrary(): Promise { + const radarrMoviesPromise = getRadarrMovies(); + const radarrDownloadsPromise = getRadarrDownloads(); + + const movies: PlayableRadarrMovie[] = await radarrMoviesPromise.then(async (radarrMovies) => { + const radarrDownloads = await radarrDownloadsPromise; + + const playableMoviePromises = radarrMovies.map(async (m) => { + const radarrDownload = radarrDownloads.find((d) => d.movie.tmdbId === m.tmdbId); + + const progress = radarrDownload + ? radarrDownload.sizeleft && radarrDownload.size + ? ((radarrDownload.size - radarrDownload.sizeleft) / radarrDownload.size) * 100 + : 0 + : undefined; + const completionTime = radarrDownload ? radarrDownload.estimatedCompletionTime : undefined; + const download = progress && completionTime ? { progress, completionTime } : undefined; + + const backdropUrl = await fetchTmdbMovieImages(String(m.tmdbId)).then( + (r) => r.backdrops.filter((b) => b.iso_639_1 === 'en')[0].file_path + ); + + return { + ...m, + cardBackdropUrl: backdropUrl, + download + }; + }); + + return await Promise.all(playableMoviePromises); + }); + + return { + movies, + totalMovies: movies?.length || 0 + }; +} + +export const library = writable>(getLibrary()); diff --git a/src/lib/types.ts b/src/lib/types.ts index 282f1fc..ff9fb25 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1,3 +1,3 @@ -import type { components as sonarrComponents } from '$lib/sonarr/sonarr-types'; +import type { components as sonarrComponents } from '$lib/apis/sonarr/sonarr-types'; export type SeriesResource = sonarrComponents['schemas']['SeriesResource']; diff --git a/src/lib/utils.ts b/src/lib/utils.ts index a591914..2187985 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,4 +1,4 @@ -import type { Genre } from '$lib/tmdb-api'; +import type { Genre } from '$lib/apis/tmdbApi'; import { writable } from 'svelte/store'; export function formatMinutesToTime(minutes: number) { diff --git a/src/lib/videoPlayerState.ts b/src/lib/videoPlayerState.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts index 7378947..582aa09 100644 --- a/src/routes/+layout.server.ts +++ b/src/routes/+layout.server.ts @@ -1,37 +1,37 @@ import type { LayoutServerLoad } from './$types'; import { - RADARR_API_KEY, - RADARR_BASE_URL, - SONARR_API_KEY, - SONARR_BASE_URL -} from '$env/static/private'; + PUBLIC_RADARR_API_KEY, + PUBLIC_RADARR_BASE_URL, + PUBLIC_SONARR_API_KEY, + PUBLIC_SONARR_BASE_URL +} from '$env/static/public'; import { PUBLIC_JELLYFIN_API_KEY, PUBLIC_JELLYFIN_URL } from '$env/static/public'; export type MissingEnvironmentVariables = { - RADARR_API_KEY: boolean; - RADARR_BASE_URL: boolean; - SONARR_API_KEY: boolean; - SONARR_BASE_URL: boolean; + PUBLIC_RADARR_API_KEY: boolean; + PUBLIC_RADARR_BASE_URL: boolean; + PUBLIC_SONARR_API_KEY: boolean; + PUBLIC_SONARR_BASE_URL: boolean; PUBLIC_JELLYFIN_API_KEY: boolean; PUBLIC_JELLYFIN_URL: boolean; }; export const load = (async () => { const isApplicationSetUp = - !!RADARR_API_KEY && - !!RADARR_BASE_URL && - !!SONARR_API_KEY && - !!SONARR_BASE_URL && + !!PUBLIC_RADARR_API_KEY && + !!PUBLIC_RADARR_BASE_URL && + !!PUBLIC_SONARR_API_KEY && + !!PUBLIC_SONARR_BASE_URL && !!PUBLIC_JELLYFIN_API_KEY && !!PUBLIC_JELLYFIN_URL; return { isApplicationSetUp, missingEnvironmentVariables: { - RADARR_API_KEY: !RADARR_API_KEY, - RADARR_BASE_URL: !RADARR_BASE_URL, - SONARR_API_KEY: !SONARR_API_KEY, - SONARR_BASE_URL: !SONARR_BASE_URL, + PUBLIC_RADARR_API_KEY: !PUBLIC_RADARR_API_KEY, + PUBLIC_RADARR_BASE_URL: !PUBLIC_RADARR_BASE_URL, + PUBLIC_SONARR_API_KEY: !PUBLIC_SONARR_API_KEY, + PUBLIC_SONARR_BASE_URL: !PUBLIC_SONARR_BASE_URL, PUBLIC_JELLYFIN_API_KEY: !PUBLIC_JELLYFIN_API_KEY, PUBLIC_JELLYFIN_URL: !PUBLIC_JELLYFIN_URL } diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index baf0efe..1c00a00 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,11 +1,13 @@
- +
{#each Array.from({ length }, (_, i) => i) as i} {#if i === index} - + {:else} - + {/if} {/each}
- +
diff --git a/src/routes/discover/+page.server.ts b/src/routes/discover/+page.server.ts index 2b1a87e..862b961 100644 --- a/src/routes/discover/+page.server.ts +++ b/src/routes/discover/+page.server.ts @@ -1,6 +1,6 @@ import type { PageServerLoad } from './$types'; -import { fetchTmdbMovie, fetchTmdbPopularMovies } from '$lib/tmdb-api'; -import { fetchCardPropsTmdb } from '../components/Card/card'; +import { fetchTmdbMovie, fetchTmdbPopularMovies } from '$lib/apis/tmdbApi'; +import { fetchCardPropsTmdb } from '$lib/components/Card/card'; export const load = (() => { const popularMoviesPromise = fetchTmdbPopularMovies(); diff --git a/src/routes/discover/+page.svelte b/src/routes/discover/+page.svelte index 83e233b..5037bf4 100644 --- a/src/routes/discover/+page.svelte +++ b/src/routes/discover/+page.svelte @@ -1,7 +1,7 @@
@@ -66,49 +75,91 @@
--> - {#await Promise.all( [data.streamed.available, data.streamed.unavailable, data.streamed.downloading] )} + + {#await $library}
{#each [...Array(20).keys()] as index (index)} {/each}
- {:then [available, unavailable, downloading]} + {:then libraryData} + {@const downloading = libraryData.movies.filter((m) => !!m.download)} + {@const available = libraryData.movies.filter( + (m) => !m.download && m.movieFile && m.isAvailable + )} + {@const unavailable = libraryData.movies.filter( + (m) => !m.download && (!m.movieFile || !m.isAvailable) + )} + {#if downloading.length > 0} -

Downloading

+
+

Downloading

+ + + +
{#each downloading as movie (movie)} {/each}
{/if} {#if available.length > 0} -

Available

+
+

Available

+ + + +
{#each available as movie (movie.tmdbId)} - + {/each}
{/if} {#if unavailable.length > 0} -

Unavailable

+
+

Unavailable

+ + + +
{#each unavailable as movie (movie.tmdbId)} - + {/each}
{/if} - - {#if watched.length > 0} -

Watched

- {/if} {/await}
diff --git a/src/routes/movie/[id]/+page.server.ts b/src/routes/movie/[id]/+page.server.ts index 005a0c2..fcf3be1 100644 --- a/src/routes/movie/[id]/+page.server.ts +++ b/src/routes/movie/[id]/+page.server.ts @@ -1,4 +1,4 @@ -import { fetchTmdbMovie } from '$lib/tmdb-api'; +import { fetchTmdbMovie } from '$lib/apis/tmdbApi'; import type { PageServerLoad } from './$types'; export const load = (async ({ params }) => { diff --git a/src/routes/movie/[id]/+page.svelte b/src/routes/movie/[id]/+page.svelte index 40e12ee..a2bf230 100644 --- a/src/routes/movie/[id]/+page.svelte +++ b/src/routes/movie/[id]/+page.svelte @@ -1,6 +1,6 @@ diff --git a/src/routes/movie/[id]/+server.ts b/src/routes/movie/[id]/+server.ts index afa7ef2..f64832c 100644 --- a/src/routes/movie/[id]/+server.ts +++ b/src/routes/movie/[id]/+server.ts @@ -1,7 +1,7 @@ import { error, json } from '@sveltejs/kit'; import type { RequestHandler } from '@sveltejs/kit'; -import { getJellyfinItemByTmdbId } from '$lib/jellyfin/jellyfin'; -import { getRadarrMovie, getRadarrDownload } from '$lib/radarr/radarr'; +import { getJellyfinItemByTmdbId } from '$lib/apis/jellyfin/jellyfinApi'; +import { getRadarrMovie, getRadarrDownload } from '$lib/apis/radarr/radarrApi'; export const parseMovieId = (params: any) => { const { id: tmdbId } = params; diff --git a/src/routes/movie/[id]/file/+server.ts b/src/routes/movie/[id]/file/+server.ts index 03cd3ba..1fffc3f 100644 --- a/src/routes/movie/[id]/file/+server.ts +++ b/src/routes/movie/[id]/file/+server.ts @@ -1,7 +1,7 @@ import type { RequestHandler } from '@sveltejs/kit'; import { json } from '@sveltejs/kit'; import { parseMovieId } from '../+server'; -import { addRadarrMovie, deleteRadarrMovie } from '$lib/radarr/radarr'; +import { addRadarrMovie, deleteRadarrMovie } from '$lib/apis/radarr/radarrApi'; // Delete download export const DELETE = (async ({ params }) => { diff --git a/src/routes/movie/[id]/radarr/+server.ts b/src/routes/movie/[id]/radarr/+server.ts index 08032d0..d7516ab 100644 --- a/src/routes/movie/[id]/radarr/+server.ts +++ b/src/routes/movie/[id]/radarr/+server.ts @@ -1,5 +1,5 @@ import { parseMovieId } from '../+server'; -import { addRadarrMovie, getRadarrMovie } from '$lib/radarr/radarr'; +import { addRadarrMovie, getRadarrMovie } from '$lib/apis/radarr/radarrApi'; import { json } from '@sveltejs/kit'; import type { RequestHandler } from '@sveltejs/kit'; diff --git a/src/routes/movie/[id]/releases/+server.ts b/src/routes/movie/[id]/releases/+server.ts index c8e1053..ba9a00b 100644 --- a/src/routes/movie/[id]/releases/+server.ts +++ b/src/routes/movie/[id]/releases/+server.ts @@ -6,7 +6,7 @@ import { addRadarrMovie, fetchRadarrReleases, downloadRadarrMovie -} from '$lib/radarr/radarr'; +} from '$lib/apis/radarr/radarrApi'; export const GET = (async ({ params }) => { const radarrId = parseMovieId(params); diff --git a/src/routes/radarr/stats/+server.ts b/src/routes/radarr/stats/+server.ts index a8af922..26b6ee2 100644 --- a/src/routes/radarr/stats/+server.ts +++ b/src/routes/radarr/stats/+server.ts @@ -1,4 +1,4 @@ -import { RadarrApi, getRadarrMovies } from '$lib/radarr/radarr'; +import { RadarrApi, getRadarrMovies } from '$lib/apis/radarr/radarrApi'; import { json } from '@sveltejs/kit'; import type { RequestHandler } from '@sveltejs/kit'; diff --git a/src/routes/sources/+page.svelte b/src/routes/sources/+page.svelte index cd2eafb..3000b04 100644 --- a/src/routes/sources/+page.svelte +++ b/src/routes/sources/+page.svelte @@ -1,9 +1,9 @@
@@ -15,7 +15,7 @@ >

Sonarr is not set up

- To set up Sonarr, define the SONARR_API_KEY and SONARR_URL environment + To set up Sonarr, define the PUBLIC_SONARR_API_KEY and SONARR_URL environment variables.

diff --git a/svelte.config.js b/svelte.config.js index 1cf26a0..caa0677 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -12,6 +12,15 @@ const config = { // If your environment is not supported or you settled on a specific environment, switch out the adapter. // See https://kit.svelte.dev/docs/adapters for more information about adapters. adapter: adapter() + }, + + vitePlugin: { + experimental: { + inspector: { + toggleKeyCombo: 'meta', + holdMode: true + } + } } };