diff --git a/media_manager/metadataProvider/tmdb.py b/media_manager/metadataProvider/tmdb.py index 241d231..cdb1f8f 100644 --- a/media_manager/metadataProvider/tmdb.py +++ b/media_manager/metadataProvider/tmdb.py @@ -1,5 +1,6 @@ import logging +import requests import tmdbsimple from pydantic_settings import BaseSettings from tmdbsimple import TV, TV_Seasons @@ -15,6 +16,7 @@ from media_manager.movies.schemas import Movie class TmdbConfig(BaseSettings): + TMDB_RELAY_URL: str = "https://metadata-relay.maxid.me" TMDB_API_KEY: str | None = None @@ -31,6 +33,15 @@ class TmdbMetadataProvider(AbstractMetadataProvider): if config.TMDB_API_KEY is None: raise InvalidConfigError("TMDB_API_KEY is not set") tmdbsimple.API_KEY = config.TMDB_API_KEY + self.url = config.TMDB_RELAY_URL + + def __get_tv_metadata(self, id: int) -> dict: + """ + Helper function to get TV metadata from TMDB. + :param id: The external ID of the TV show. + :return: A dictionary containing the TV show metadata. + """ + return requests.get(url=f"{self.url}/tv/shows/{id}").json() def download_show_poster_image(self, show: Show) -> bool: show_metadata = TV(show.external_id).info() diff --git a/media_manager/movies/schemas.py b/media_manager/movies/schemas.py index 0d452c3..51878cb 100644 --- a/media_manager/movies/schemas.py +++ b/media_manager/movies/schemas.py @@ -6,7 +6,7 @@ from pydantic import BaseModel, Field, ConfigDict, model_validator from media_manager.auth.schemas import UserRead from media_manager.torrent.models import Quality -from media_manager.torrent.schemas import TorrentId, Torrent +from media_manager.torrent.schemas import TorrentId, Torrent, TorrentStatus MovieId = typing.NewType("MovieId", UUID) MovieRequestId = typing.NewType("MovieRequestId", UUID) @@ -74,9 +74,19 @@ class RichMovieRequest(MovieRequest): movie: Movie +class MovieTorrent(BaseModel): + model_config = ConfigDict(from_attributes=True) + + torrent_id: TorrentId + torrent_title: str + status: TorrentStatus + quality: Quality + imported: bool + file_path_suffix: str + class RichMovieTorrent(BaseModel): movie_id: MovieId name: str year: int | None metadata_provider: str - torrents: list[Torrent] + torrents: list[MovieTorrent] diff --git a/web/src/lib/components/torrent-table.svelte b/web/src/lib/components/torrent-table.svelte index 00db98b..5fcc437 100644 --- a/web/src/lib/components/torrent-table.svelte +++ b/web/src/lib/components/torrent-table.svelte @@ -29,7 +29,7 @@ - {torrent.torrent_title} + {isShow ? torrent.torrent_title : torrent.title} {#if isShow} diff --git a/web/src/lib/components/ui/menubar/index.ts b/web/src/lib/components/ui/menubar/index.ts new file mode 100644 index 0000000..3a09c74 --- /dev/null +++ b/web/src/lib/components/ui/menubar/index.ts @@ -0,0 +1,51 @@ +import {Menubar as MenubarPrimitive} from "bits-ui"; +import Root from "./menubar.svelte"; +import CheckboxItem from "./menubar-checkbox-item.svelte"; +import Content from "./menubar-content.svelte"; +import Item from "./menubar-item.svelte"; +import GroupHeading from "./menubar-group-heading.svelte"; +import RadioItem from "./menubar-radio-item.svelte"; +import Separator from "./menubar-separator.svelte"; +import Shortcut from "./menubar-shortcut.svelte"; +import SubContent from "./menubar-sub-content.svelte"; +import SubTrigger from "./menubar-sub-trigger.svelte"; +import Trigger from "./menubar-trigger.svelte"; + +const Menu = MenubarPrimitive.Menu; +const Group = MenubarPrimitive.Group; +const Sub = MenubarPrimitive.Sub; +const RadioGroup = MenubarPrimitive.RadioGroup; + +export { + Root, + CheckboxItem, + Content, + Item, + GroupHeading, + RadioItem, + Separator, + Shortcut, + SubContent, + SubTrigger, + Trigger, + Menu, + Group, + Sub, + RadioGroup, + // + Root as Menubar, + CheckboxItem as MenubarCheckboxItem, + Content as MenubarContent, + Item as MenubarItem, + GroupHeading as MenubarGroupHeading, + RadioItem as MenubarRadioItem, + Separator as MenubarSeparator, + Shortcut as MenubarShortcut, + SubContent as MenubarSubContent, + SubTrigger as MenubarSubTrigger, + Trigger as MenubarTrigger, + Menu as MenubarMenu, + Group as MenubarGroup, + Sub as MenubarSub, + RadioGroup as MenubarRadioGroup, +}; diff --git a/web/src/lib/components/ui/menubar/menubar-checkbox-item.svelte b/web/src/lib/components/ui/menubar/menubar-checkbox-item.svelte new file mode 100644 index 0000000..cd3827b --- /dev/null +++ b/web/src/lib/components/ui/menubar/menubar-checkbox-item.svelte @@ -0,0 +1,40 @@ + + + + {#snippet children({checked, indeterminate})} + + {#if indeterminate} + + {:else} + + {/if} + + {@render childrenProp?.()} + {/snippet} + diff --git a/web/src/lib/components/ui/menubar/menubar-content.svelte b/web/src/lib/components/ui/menubar/menubar-content.svelte new file mode 100644 index 0000000..0e953b6 --- /dev/null +++ b/web/src/lib/components/ui/menubar/menubar-content.svelte @@ -0,0 +1,32 @@ + + + + + diff --git a/web/src/lib/components/ui/menubar/menubar-group-heading.svelte b/web/src/lib/components/ui/menubar/menubar-group-heading.svelte new file mode 100644 index 0000000..91098cd --- /dev/null +++ b/web/src/lib/components/ui/menubar/menubar-group-heading.svelte @@ -0,0 +1,19 @@ + + + diff --git a/web/src/lib/components/ui/menubar/menubar-item.svelte b/web/src/lib/components/ui/menubar/menubar-item.svelte new file mode 100644 index 0000000..b60216b --- /dev/null +++ b/web/src/lib/components/ui/menubar/menubar-item.svelte @@ -0,0 +1,23 @@ + + + diff --git a/web/src/lib/components/ui/menubar/menubar-radio-item.svelte b/web/src/lib/components/ui/menubar/menubar-radio-item.svelte new file mode 100644 index 0000000..f5e6241 --- /dev/null +++ b/web/src/lib/components/ui/menubar/menubar-radio-item.svelte @@ -0,0 +1,30 @@ + + + + {#snippet children({checked})} + + {#if checked} + + {/if} + + {@render childrenProp?.({checked})} + {/snippet} + diff --git a/web/src/lib/components/ui/menubar/menubar-separator.svelte b/web/src/lib/components/ui/menubar/menubar-separator.svelte new file mode 100644 index 0000000..ae8635f --- /dev/null +++ b/web/src/lib/components/ui/menubar/menubar-separator.svelte @@ -0,0 +1,16 @@ + + + diff --git a/web/src/lib/components/ui/menubar/menubar-shortcut.svelte b/web/src/lib/components/ui/menubar/menubar-shortcut.svelte new file mode 100644 index 0000000..ca4ee6a --- /dev/null +++ b/web/src/lib/components/ui/menubar/menubar-shortcut.svelte @@ -0,0 +1,20 @@ + + + + {@render children?.()} + diff --git a/web/src/lib/components/ui/menubar/menubar-sub-content.svelte b/web/src/lib/components/ui/menubar/menubar-sub-content.svelte new file mode 100644 index 0000000..d369f10 --- /dev/null +++ b/web/src/lib/components/ui/menubar/menubar-sub-content.svelte @@ -0,0 +1,19 @@ + + + diff --git a/web/src/lib/components/ui/menubar/menubar-sub-trigger.svelte b/web/src/lib/components/ui/menubar/menubar-sub-trigger.svelte new file mode 100644 index 0000000..75639ab --- /dev/null +++ b/web/src/lib/components/ui/menubar/menubar-sub-trigger.svelte @@ -0,0 +1,28 @@ + + + + {@render children?.()} + + diff --git a/web/src/lib/components/ui/menubar/menubar-trigger.svelte b/web/src/lib/components/ui/menubar/menubar-trigger.svelte new file mode 100644 index 0000000..64b5b29 --- /dev/null +++ b/web/src/lib/components/ui/menubar/menubar-trigger.svelte @@ -0,0 +1,19 @@ + + + diff --git a/web/src/lib/components/ui/menubar/menubar.svelte b/web/src/lib/components/ui/menubar/menubar.svelte new file mode 100644 index 0000000..0012987 --- /dev/null +++ b/web/src/lib/components/ui/menubar/menubar.svelte @@ -0,0 +1,19 @@ + + + diff --git a/web/src/lib/types.ts b/web/src/lib/types.ts index 9dd927f..38a2303 100644 --- a/web/src/lib/types.ts +++ b/web/src/lib/types.ts @@ -192,6 +192,14 @@ export interface RichShowTorrent { torrents: RichSeasonTorrent[]; } +export interface RichMovieTorrent { + show_id: string; + name: string; + year: number | null; + metadata_provider: string; + torrents: Torrent[]; +} + interface SeasonRequestBase { min_quality: Quality; wanted_quality: Quality; diff --git a/web/src/routes/dashboard/movies/add-movie/+page.svelte b/web/src/routes/dashboard/movies/add-movie/+page.svelte new file mode 100644 index 0000000..c6b231e --- /dev/null +++ b/web/src/routes/dashboard/movies/add-movie/+page.svelte @@ -0,0 +1,145 @@ + + +
+
+ + + + + + + +
+
+ +
+
+

+ Add a Movie +

+
+ + +

Search for a Movie to add.

+
+
+ + +
+

Advanced Settings

+ +
+
+ + + +
+ + +
+
+ + +
+
+
+
+
+
+ +
+
+ + + + {#if results != null} + {#if results.length === 0} +

No Shows found.

+ {:else} +
+ {#each results as result} + + {/each} +
+ {/if} + {/if} +
diff --git a/web/src/routes/dashboard/tv/add-show/+page.svelte b/web/src/routes/dashboard/tv/add-show/+page.svelte index 91d7e66..20003ed 100644 --- a/web/src/routes/dashboard/tv/add-show/+page.svelte +++ b/web/src/routes/dashboard/tv/add-show/+page.svelte @@ -13,6 +13,7 @@ import AddMediaCard from '$lib/components/add-media-card.svelte'; import {toast} from 'svelte-sonner'; import {onMount} from "svelte"; + import * as Menubar from "$lib/components/ui/menubar/index.js"; const apiUrl = env.PUBLIC_API_URL; let searchTerm: string = $state(''); @@ -86,7 +87,7 @@

- Add a show + Add a Show

@@ -94,7 +95,7 @@

Search for a Show to add.

- +

Advanced Settings

@@ -104,7 +105,7 @@
- +
diff --git a/web/web.iml b/web/web.iml new file mode 100644 index 0000000..bbec431 --- /dev/null +++ b/web/web.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file