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.poster && (
+
+ )}
+
({
@@ -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';