Skip to content

Commit

Permalink
feat(api): radarr api wrapper / send to radarr when requests approved (
Browse files Browse the repository at this point in the history
  • Loading branch information
sct committed Sep 16, 2020
1 parent d1b5c08 commit 48d62c3
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 5 deletions.
122 changes: 122 additions & 0 deletions server/api/radarr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import Axios, { AxiosInstance } from 'axios';

interface RadarrMovieOptions {
title: string;
qualityProfileId: number;
profileId: number;
year: number;
rootFolderPath: string;
tmdbId: number;
monitored?: boolean;
searchNow?: boolean;
}

interface RadarrMovie {
id: number;
title: string;
isAvailable: boolean;
monitored: boolean;
tmdbId: number;
titleSlug: string;
folderName: string;
path: string;
profileId: number;
qualityProfileId: number;
added: string;
downloaded: boolean;
hasFile: boolean;
}

interface RadarrRootFolder {
id: number;
path: string;
freeSpace: number;
totalSpace: number;
unmappedFolders: {
name: string;
path: string;
}[];
}

interface RadarrProfile {
id: number;
name: string;
}

class RadarrAPI {
private axios: AxiosInstance;
constructor({ url, apiKey }: { url: string; apiKey: string }) {
this.axios = Axios.create({
baseURL: url,
params: {
apikey: apiKey,
},
});
}

public getMovies = async (): Promise<RadarrMovie[]> => {
try {
const response = await this.axios.get<RadarrMovie[]>('/movie');

return response.data;
} catch (e) {
throw new Error(`[Radarr] Failed to retrieve movies: ${e.message}`);
}
};

public getMovie = async ({ id }: { id: number }): Promise<RadarrMovie> => {
try {
const response = await this.axios.get<RadarrMovie>(`/movie/${id}`);

return response.data;
} catch (e) {
throw new Error(`[Radarr] Failed to retrieve movie: ${e.message}`);
}
};

public addMovie = async (
options: RadarrMovieOptions
): Promise<RadarrMovie> => {
try {
const response = await this.axios.post<RadarrMovie>(`/movie`, {
title: options.title,
qualityProfileId: options.qualityProfileId,
profileId: options.profileId,
titleSlug: options.tmdbId.toString(),
tmdbId: options.tmdbId,
year: options.year,
rootFolderPath: options.rootFolderPath,
monitored: options.monitored,
addOptions: {
searchForMovie: options.searchNow,
},
});

return response.data;
} catch (e) {
throw new Error(`[Radarr] Failed to add movie: ${e.message}`);
}
};

public getProfiles = async (): Promise<RadarrProfile[]> => {
try {
const response = await this.axios.get<RadarrProfile[]>(`/profile`);

return response.data;
} catch (e) {
throw new Error(`[Radarr] Failed to retrieve profiles: ${e.message}`);
}
};

public getRootFolders = async (): Promise<RadarrRootFolder[]> => {
try {
const response = await this.axios.get<RadarrRootFolder[]>(`/rootfolder`);

return response.data;
} catch (e) {
throw new Error(`[Radarr] Failed to retrieve root folders: ${e.message}`);
}
};
}

export default RadarrAPI;
51 changes: 50 additions & 1 deletion server/entity/MediaRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ import {
getRepository,
In,
Index,
AfterUpdate,
AfterInsert,
} from 'typeorm';
import { User } from './User';
import RadarrAPI from '../api/radarr';
import { getSettings } from '../lib/settings';
import TheMovieDb from '../api/themoviedb';

export enum MediaRequestStatus {
PENDING = 1,
Expand Down Expand Up @@ -60,7 +65,6 @@ export class MediaRequest {

@ManyToOne(() => User, { nullable: true })
public modifiedBy?: User;

@CreateDateColumn()
public createdAt: Date;

Expand All @@ -70,4 +74,49 @@ export class MediaRequest {
constructor(init?: Partial<MediaRequest>) {
Object.assign(this, init);
}

@AfterUpdate()
@AfterInsert()
private async sendToRadarr() {
if (
this.mediaType === 'movie' &&
this.status === MediaRequestStatus.APPROVED
) {
try {
const settings = getSettings();
if (settings.radarr.length === 0 && !settings.radarr[0]) {
console.log(
'[MediaRequest] Skipped radarr request as there is no radarr configured'
);
return;
}

const tmdb = new TheMovieDb();
const radarrSettings = settings.radarr[0];
const radarr = new RadarrAPI({
apiKey: radarrSettings.apiKey,
url: `${radarrSettings.useSsl ? 'https' : 'http'}://${
radarrSettings.hostname
}:${radarrSettings.port}/api`,
});
const movie = await tmdb.getMovie({ movieId: this.mediaId });

await radarr.addMovie({
profileId: radarrSettings.activeProfileId,
qualityProfileId: radarrSettings.activeProfileId,
rootFolderPath: radarrSettings.activeDirectory,
title: movie.title,
tmdbId: movie.id,
year: Number(movie.release_date.slice(0, 4)),
monitored: true,
searchNow: true,
});
console.log('[MediaRequest] Sent request to Radarr');
} catch (e) {
throw new Error(
`[MediaRequest] Request failed to send to radarr: ${e.message}`
);
}
}
}
}
2 changes: 1 addition & 1 deletion server/lib/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ interface DVRSettings {
apiKey: string;
useSsl: boolean;
baseUrl?: string;
activeProfile: string;
activeProfileId: number;
activeDirectory: string;
is4k: boolean;
}
Expand Down
6 changes: 3 additions & 3 deletions server/overseerr-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ components:
example: false
baseUrl:
type: string
activeProfile:
type: string
example: '1080p'
activeProfileId:
type: number
example: 1
activeDirectory:
type: string
example: '/movies'
Expand Down

0 comments on commit 48d62c3

Please sign in to comment.