diff --git a/src/components/AppShelf/AddAppShelfItem.tsx b/src/components/AppShelf/AddAppShelfItem.tsx index c061930e9..871e45f05 100644 --- a/src/components/AppShelf/AddAppShelfItem.tsx +++ b/src/components/AppShelf/AddAppShelfItem.tsx @@ -173,7 +173,10 @@ export function AddAppShelfItemForm(props: { setOpened: (b: boolean) => void } & {...form.getInputProps('type')} /> - {(form.values.type === 'Sonarr' || form.values.type === 'Radarr') && ( + {(form.values.type === 'Sonarr' || + form.values.type === 'Radarr' || + form.values.type === 'Lidarr' || + form.values.type === 'Readarr') && ( { // Filter only sonarr and radarr services const filtered = config.services.filter( - (service) => service.type === 'Sonarr' || service.type === 'Radarr' + (service) => + service.type === 'Sonarr' || + service.type === 'Radarr' || + service.type === 'Lidarr' || + service.type === 'Readarr' ); // Get the url and apiKey for all Sonarr and Radarr services const sonarrService = filtered.filter((service) => service.type === 'Sonarr').at(0); const radarrService = filtered.filter((service) => service.type === 'Radarr').at(0); + const lidarrService = filtered.filter((service) => service.type === 'Lidarr').at(0); + const readarrService = filtered.filter((service) => service.type === 'Readarr').at(0); const nextMonth = new Date(new Date().setMonth(new Date().getMonth() + 2)).toISOString(); if (sonarrService && sonarrService.apiKey) { const baseUrl = new URL(sonarrService.url).origin; @@ -69,6 +82,44 @@ export default function CalendarComponent(props: any) { } ); } + if (lidarrService && lidarrService.apiKey) { + const baseUrl = new URL(lidarrService.url).origin; + fetch(`${baseUrl}/api/v1/calendar?apikey=${lidarrService?.apiKey}&end=${nextMonth}`).then( + (response) => { + response.ok && + response.json().then((data) => { + setLidarrMedias(data); + showNotification({ + title: 'Lidarr', + icon: , + color: 'green', + autoClose: 1500, + radius: 'md', + message: `Loaded ${data.length} releases`, + }); + }); + } + ); + } + if (readarrService && readarrService.apiKey) { + const baseUrl = new URL(readarrService.url).origin; + fetch(`${baseUrl}/api/v1/calendar?apikey=${readarrService?.apiKey}&end=${nextMonth}`).then( + (response) => { + response.ok && + response.json().then((data) => { + setReadarrMedias(data); + showNotification({ + title: 'Readarr', + icon: , + color: 'green', + autoClose: 1500, + radius: 'md', + message: `Loaded ${data.length} releases`, + }); + }); + } + ); + } }, [config.services]); if (sonarrMedias === undefined && radarrMedias === undefined) { @@ -82,6 +133,8 @@ export default function CalendarComponent(props: any) { renderdate={renderdate} sonarrmedias={sonarrMedias} radarrmedias={radarrMedias} + lidarrmedias={lidarrMedias} + readarrmedias={readarrMedias} /> )} /> @@ -93,12 +146,25 @@ function DayComponent(props: any) { renderdate, sonarrmedias, radarrmedias, - }: { renderdate: Date; sonarrmedias: []; radarrmedias: [] } = props; + lidarrmedias, + readarrmedias, + }: { renderdate: Date; sonarrmedias: []; radarrmedias: []; lidarrmedias: []; readarrmedias: [] } = + props; const [opened, setOpened] = useState(false); const theme = useMantineTheme(); const day = renderdate.getDate(); - // Itterate over the medias and filter the ones that are on the same day + + const readarrFiltered = readarrmedias.filter((media: any) => { + const mediaDate = new Date(media.releaseDate); + return mediaDate.getDate() === day; + }); + + const lidarrFiltered = lidarrmedias.filter((media: any) => { + const date = new Date(media.releaseDate); + // Return true if the date is renerdate without counting hours and minutes + return date.getDate() === day && date.getMonth() === renderdate.getMonth(); + }); const sonarrFiltered = sonarrmedias.filter((media: any) => { const date = new Date(media.airDate); // Return true if the date is renerdate without counting hours and minutes @@ -109,7 +175,12 @@ function DayComponent(props: any) { // Return true if the date is renerdate without counting hours and minutes return date.getDate() === day && date.getMonth() === renderdate.getMonth(); }); - if (sonarrFiltered.length === 0 && radarrFiltered.length === 0) { + if ( + sonarrFiltered.length === 0 && + radarrFiltered.length === 0 && + lidarrFiltered.length === 0 && + readarrFiltered.length === 0 + ) { return
{day}
; } @@ -119,8 +190,58 @@ function DayComponent(props: any) { setOpened(true); }} > - {radarrFiltered.length > 0 && } - {sonarrFiltered.length > 0 && } + {readarrFiltered.length > 0 && ( + + )} + {radarrFiltered.length > 0 && ( + + )} + {sonarrFiltered.length > 0 && ( + + )} + {lidarrFiltered.length > 0 && ( + + )} } ))} + {lidarrFiltered.map((media: any, index: number) => ( + + + {index < lidarrFiltered.length - 1 && } + + ))} + {readarrFiltered.map((media: any, index: number) => ( + + + {index < readarrFiltered.length - 1 && } + + ))} diff --git a/src/components/modules/calendar/MediaDisplay.tsx b/src/components/modules/calendar/MediaDisplay.tsx index ccf6745b3..a3e5a5674 100644 --- a/src/components/modules/calendar/MediaDisplay.tsx +++ b/src/components/modules/calendar/MediaDisplay.tsx @@ -3,9 +3,10 @@ import { Link } from 'tabler-icons-react'; export interface IMedia { overview: string; - imdbId: any; + imdbId?: any; + artist?: string; title: string; - poster: string; + poster?: string; genres: string[]; seasonNumber?: number; episodeNumber?: number; @@ -15,14 +16,17 @@ function MediaDisplay(props: { media: IMedia }) { const { media }: { media: IMedia } = props; return ( - {media.title} + {media.poster && ( + {media.title} + )} + ({ @@ -32,12 +36,28 @@ function MediaDisplay(props: { media: IMedia }) { {media.title} - - - - - + {media.imdbId && ( + + + + + + )} + {media.artist && ( + + New album from {media.artist} + + )} {media.episodeNumber && media.seasonNumber && ( image.coverType === 'poster'); + // Return a movie poster containting the title and the description + return ( + + ); +} + +export function LidarrMediaDisplay(props: any) { + const { media }: { media: any } = props; + // Find a poster CoverType + const poster = media.artist.images.find((image: any) => image.coverType === 'poster'); + // Return a movie poster containting the title and the description + return ( + + ); +} + export function RadarrMediaDisplay(props: any) { const { media }: { media: any } = props; // Find a poster CoverType diff --git a/src/tools/types.ts b/src/tools/types.ts index 92a56f8fc..71a0b3fea 100644 --- a/src/tools/types.ts +++ b/src/tools/types.ts @@ -27,6 +27,7 @@ export const ServiceTypeList = [ 'Lidarr', 'Plex', 'Radarr', + 'Readarr', 'Sonarr', 'qBittorrent', ]; @@ -36,6 +37,7 @@ export type ServiceType = | 'Lidarr' | 'Plex' | 'Radarr' + | 'Readarr' | 'Sonarr' | 'qBittorrent';