mirror of
https://github.com/fallenbagel/jellyseerr.git
synced 2026-01-01 04:08:45 -05:00
refactor: switch from Fetch API to Axios (#1520)
* refactor: switch from Fetch API to Axios * fix: remove unwanted changes * fix: rewrite error handling for Axios and remove IPv4 first setting * style: run prettier * style: run prettier * fix: add back custom proxy agent * fix: add back custom proxy agent * fix: correct rebase issue * fix: resolve review comments
This commit is contained in:
@@ -113,9 +113,9 @@ class ServarrBase<QueueItemAppendT> extends ExternalAPI {
|
||||
|
||||
public getSystemStatus = async (): Promise<SystemStatus> => {
|
||||
try {
|
||||
const data = await this.get<SystemStatus>('/system/status');
|
||||
const response = await this.axios.get<SystemStatus>('/system/status');
|
||||
|
||||
return data;
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`[${this.apiName}] Failed to retrieve system status: ${e.message}`
|
||||
@@ -157,15 +157,16 @@ class ServarrBase<QueueItemAppendT> extends ExternalAPI {
|
||||
|
||||
public getQueue = async (): Promise<(QueueItem & QueueItemAppendT)[]> => {
|
||||
try {
|
||||
const data = await this.get<QueueResponse<QueueItemAppendT>>(
|
||||
const response = await this.axios.get<QueueResponse<QueueItemAppendT>>(
|
||||
`/queue`,
|
||||
{
|
||||
includeEpisode: 'true',
|
||||
},
|
||||
0
|
||||
params: {
|
||||
includeEpisode: true,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return data.records;
|
||||
return response.data.records;
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`[${this.apiName}] Failed to retrieve queue: ${e.message}`
|
||||
@@ -175,9 +176,9 @@ class ServarrBase<QueueItemAppendT> extends ExternalAPI {
|
||||
|
||||
public getTags = async (): Promise<Tag[]> => {
|
||||
try {
|
||||
const data = await this.get<Tag[]>(`/tag`);
|
||||
const response = await this.axios.get<Tag[]>(`/tag`);
|
||||
|
||||
return data;
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`[${this.apiName}] Failed to retrieve tags: ${e.message}`
|
||||
@@ -187,11 +188,11 @@ class ServarrBase<QueueItemAppendT> extends ExternalAPI {
|
||||
|
||||
public createTag = async ({ label }: { label: string }): Promise<Tag> => {
|
||||
try {
|
||||
const data = await this.post<Tag>(`/tag`, {
|
||||
const response = await this.axios.post<Tag>(`/tag`, {
|
||||
label,
|
||||
});
|
||||
|
||||
return data;
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
throw new Error(`[${this.apiName}] Failed to create tag: ${e.message}`);
|
||||
}
|
||||
@@ -206,15 +207,10 @@ class ServarrBase<QueueItemAppendT> extends ExternalAPI {
|
||||
options: Record<string, unknown>
|
||||
): Promise<void> {
|
||||
try {
|
||||
await this.post(
|
||||
`/command`,
|
||||
{
|
||||
name: commandName,
|
||||
...options,
|
||||
},
|
||||
{},
|
||||
0
|
||||
);
|
||||
await this.axios.post(`/command`, {
|
||||
name: commandName,
|
||||
...options,
|
||||
});
|
||||
} catch (e) {
|
||||
throw new Error(`[${this.apiName}] Failed to run command: ${e.message}`);
|
||||
}
|
||||
|
||||
@@ -70,9 +70,9 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
|
||||
|
||||
public getMovies = async (): Promise<RadarrMovie[]> => {
|
||||
try {
|
||||
const data = await this.get<RadarrMovie[]>('/movie');
|
||||
const response = await this.axios.get<RadarrMovie[]>('/movie');
|
||||
|
||||
return data;
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
throw new Error(`[Radarr] Failed to retrieve movies: ${e.message}`);
|
||||
}
|
||||
@@ -80,9 +80,9 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
|
||||
|
||||
public getMovie = async ({ id }: { id: number }): Promise<RadarrMovie> => {
|
||||
try {
|
||||
const data = await this.get<RadarrMovie>(`/movie/${id}`);
|
||||
const response = await this.axios.get<RadarrMovie>(`/movie/${id}`);
|
||||
|
||||
return data;
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
throw new Error(`[Radarr] Failed to retrieve movie: ${e.message}`);
|
||||
}
|
||||
@@ -90,15 +90,17 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
|
||||
|
||||
public async getMovieByTmdbId(id: number): Promise<RadarrMovie> {
|
||||
try {
|
||||
const data = await this.get<RadarrMovie[]>('/movie/lookup', {
|
||||
term: `tmdb:${id}`,
|
||||
const response = await this.axios.get<RadarrMovie[]>('/movie/lookup', {
|
||||
params: {
|
||||
term: `tmdb:${id}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (!data[0]) {
|
||||
if (!response.data[0]) {
|
||||
throw new Error('Movie not found');
|
||||
}
|
||||
|
||||
return data[0];
|
||||
return response.data[0];
|
||||
} catch (e) {
|
||||
logger.error('Error retrieving movie by TMDB ID', {
|
||||
label: 'Radarr API',
|
||||
@@ -128,7 +130,7 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
|
||||
|
||||
// movie exists in Radarr but is neither downloaded nor monitored
|
||||
if (movie.id && !movie.monitored) {
|
||||
const data = await this.put<RadarrMovie>(`/movie`, {
|
||||
const response = await this.axios.put<RadarrMovie>(`/movie`, {
|
||||
...movie,
|
||||
title: options.title,
|
||||
qualityProfileId: options.qualityProfileId,
|
||||
@@ -145,25 +147,25 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
|
||||
},
|
||||
});
|
||||
|
||||
if (data.monitored) {
|
||||
if (response.data.monitored) {
|
||||
logger.info(
|
||||
'Found existing title in Radarr and set it to monitored.',
|
||||
{
|
||||
label: 'Radarr',
|
||||
movieId: data.id,
|
||||
movieTitle: data.title,
|
||||
movieId: response.data.id,
|
||||
movieTitle: response.data.title,
|
||||
}
|
||||
);
|
||||
logger.debug('Radarr update details', {
|
||||
label: 'Radarr',
|
||||
movie: data,
|
||||
movie: response.data,
|
||||
});
|
||||
|
||||
if (options.searchNow) {
|
||||
this.searchMovie(data.id);
|
||||
this.searchMovie(response.data.id);
|
||||
}
|
||||
|
||||
return data;
|
||||
return response.data;
|
||||
} else {
|
||||
logger.error('Failed to update existing movie in Radarr.', {
|
||||
label: 'Radarr',
|
||||
@@ -181,7 +183,7 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
|
||||
return movie;
|
||||
}
|
||||
|
||||
const data = await this.post<RadarrMovie>(`/movie`, {
|
||||
const response = await this.axios.post<RadarrMovie>(`/movie`, {
|
||||
title: options.title,
|
||||
qualityProfileId: options.qualityProfileId,
|
||||
profileId: options.profileId,
|
||||
@@ -197,11 +199,11 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
|
||||
},
|
||||
});
|
||||
|
||||
if (data.id) {
|
||||
if (response.data.id) {
|
||||
logger.info('Radarr accepted request', { label: 'Radarr' });
|
||||
logger.debug('Radarr add details', {
|
||||
label: 'Radarr',
|
||||
movie: data,
|
||||
movie: response.data,
|
||||
});
|
||||
} else {
|
||||
logger.error('Failed to add movie to Radarr', {
|
||||
@@ -210,22 +212,15 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
|
||||
});
|
||||
throw new Error('Failed to add movie to Radarr');
|
||||
}
|
||||
return data;
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
let errorData;
|
||||
try {
|
||||
errorData = await e.cause?.text();
|
||||
errorData = JSON.parse(errorData);
|
||||
} catch {
|
||||
/* empty */
|
||||
}
|
||||
logger.error(
|
||||
'Failed to add movie to Radarr. This might happen if the movie already exists, in which case you can safely ignore this error.',
|
||||
{
|
||||
label: 'Radarr',
|
||||
errorMessage: e.message,
|
||||
options,
|
||||
response: errorData,
|
||||
response: e?.response?.data,
|
||||
}
|
||||
);
|
||||
throw new Error('Failed to add movie to Radarr');
|
||||
@@ -254,9 +249,11 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
|
||||
public removeMovie = async (movieId: number): Promise<void> => {
|
||||
try {
|
||||
const { id, title } = await this.getMovieByTmdbId(movieId);
|
||||
await this.delete(`/movie/${id}`, {
|
||||
deleteFiles: 'true',
|
||||
addImportExclusion: 'false',
|
||||
await this.axios.delete(`/movie/${id}`, {
|
||||
params: {
|
||||
deleteFiles: true,
|
||||
addImportExclusion: false,
|
||||
},
|
||||
});
|
||||
logger.info(`[Radarr] Removed movie ${title}`);
|
||||
} catch (e) {
|
||||
@@ -274,13 +271,10 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
|
||||
if (tmdbId) {
|
||||
this.removeCache('/movie/lookup', {
|
||||
term: `tmdb:${tmdbId}`,
|
||||
headers: this.defaultHeaders,
|
||||
});
|
||||
}
|
||||
if (externalId) {
|
||||
this.removeCache(`/movie/${externalId}`, {
|
||||
headers: this.defaultHeaders,
|
||||
});
|
||||
this.removeCache(`/movie/${externalId}`);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -117,9 +117,9 @@ class SonarrAPI extends ServarrBase<{
|
||||
|
||||
public async getSeries(): Promise<SonarrSeries[]> {
|
||||
try {
|
||||
const data = await this.get<SonarrSeries[]>('/series');
|
||||
const response = await this.axios.get<SonarrSeries[]>('/series');
|
||||
|
||||
return data;
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
throw new Error(`[Sonarr] Failed to retrieve series: ${e.message}`);
|
||||
}
|
||||
@@ -127,9 +127,9 @@ class SonarrAPI extends ServarrBase<{
|
||||
|
||||
public async getSeriesById(id: number): Promise<SonarrSeries> {
|
||||
try {
|
||||
const data = await this.get<SonarrSeries>(`/series/${id}`);
|
||||
const response = await this.axios.get<SonarrSeries>(`/series/${id}`);
|
||||
|
||||
return data;
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
throw new Error(`[Sonarr] Failed to retrieve series by ID: ${e.message}`);
|
||||
}
|
||||
@@ -137,15 +137,17 @@ class SonarrAPI extends ServarrBase<{
|
||||
|
||||
public async getSeriesByTitle(title: string): Promise<SonarrSeries[]> {
|
||||
try {
|
||||
const data = await this.get<SonarrSeries[]>('/series/lookup', {
|
||||
term: title,
|
||||
const response = await this.axios.get<SonarrSeries[]>('/series/lookup', {
|
||||
params: {
|
||||
term: title,
|
||||
},
|
||||
});
|
||||
|
||||
if (!data[0]) {
|
||||
if (!response.data[0]) {
|
||||
throw new Error('No series found');
|
||||
}
|
||||
|
||||
return data;
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
logger.error('Error retrieving series by series title', {
|
||||
label: 'Sonarr API',
|
||||
@@ -158,15 +160,17 @@ class SonarrAPI extends ServarrBase<{
|
||||
|
||||
public async getSeriesByTvdbId(id: number): Promise<SonarrSeries> {
|
||||
try {
|
||||
const data = await this.get<SonarrSeries[]>('/series/lookup', {
|
||||
term: `tvdb:${id}`,
|
||||
const response = await this.axios.get<SonarrSeries[]>('/series/lookup', {
|
||||
params: {
|
||||
term: `tvdb:${id}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (!data[0]) {
|
||||
if (!response.data[0]) {
|
||||
throw new Error('Series not found');
|
||||
}
|
||||
|
||||
return data[0];
|
||||
return response.data[0];
|
||||
} catch (e) {
|
||||
logger.error('Error retrieving series by tvdb ID', {
|
||||
label: 'Sonarr API',
|
||||
@@ -189,27 +193,27 @@ class SonarrAPI extends ServarrBase<{
|
||||
: series.tags;
|
||||
series.seasons = this.buildSeasonList(options.seasons, series.seasons);
|
||||
|
||||
const newSeriesData = await this.put<SonarrSeries>(
|
||||
const newSeriesResponse = await this.axios.put<SonarrSeries>(
|
||||
'/series',
|
||||
series as any
|
||||
series
|
||||
);
|
||||
|
||||
if (newSeriesData.id) {
|
||||
if (newSeriesResponse.data.id) {
|
||||
logger.info('Updated existing series in Sonarr.', {
|
||||
label: 'Sonarr',
|
||||
seriesId: newSeriesData.id,
|
||||
seriesTitle: newSeriesData.title,
|
||||
seriesId: newSeriesResponse.data.id,
|
||||
seriesTitle: newSeriesResponse.data.title,
|
||||
});
|
||||
logger.debug('Sonarr update details', {
|
||||
label: 'Sonarr',
|
||||
movie: newSeriesData,
|
||||
series: newSeriesResponse.data,
|
||||
});
|
||||
|
||||
if (options.searchNow) {
|
||||
this.searchSeries(newSeriesData.id);
|
||||
this.searchSeries(newSeriesResponse.data.id);
|
||||
}
|
||||
|
||||
return newSeriesData;
|
||||
return newSeriesResponse.data;
|
||||
} else {
|
||||
logger.error('Failed to update series in Sonarr', {
|
||||
label: 'Sonarr',
|
||||
@@ -219,35 +223,38 @@ class SonarrAPI extends ServarrBase<{
|
||||
}
|
||||
}
|
||||
|
||||
const createdSeriesData = await this.post<SonarrSeries>('/series', {
|
||||
tvdbId: options.tvdbid,
|
||||
title: options.title,
|
||||
qualityProfileId: options.profileId,
|
||||
languageProfileId: options.languageProfileId,
|
||||
seasons: this.buildSeasonList(
|
||||
options.seasons,
|
||||
series.seasons.map((season) => ({
|
||||
seasonNumber: season.seasonNumber,
|
||||
// We force all seasons to false if its the first request
|
||||
monitored: false,
|
||||
}))
|
||||
),
|
||||
tags: options.tags,
|
||||
seasonFolder: options.seasonFolder,
|
||||
monitored: options.monitored,
|
||||
rootFolderPath: options.rootFolderPath,
|
||||
seriesType: options.seriesType,
|
||||
addOptions: {
|
||||
ignoreEpisodesWithFiles: true,
|
||||
searchForMissingEpisodes: options.searchNow,
|
||||
},
|
||||
} as Partial<SonarrSeries>);
|
||||
const createdSeriesResponse = await this.axios.post<SonarrSeries>(
|
||||
'/series',
|
||||
{
|
||||
tvdbId: options.tvdbid,
|
||||
title: options.title,
|
||||
qualityProfileId: options.profileId,
|
||||
languageProfileId: options.languageProfileId,
|
||||
seasons: this.buildSeasonList(
|
||||
options.seasons,
|
||||
series.seasons.map((season) => ({
|
||||
seasonNumber: season.seasonNumber,
|
||||
// We force all seasons to false if its the first request
|
||||
monitored: false,
|
||||
}))
|
||||
),
|
||||
tags: options.tags,
|
||||
seasonFolder: options.seasonFolder,
|
||||
monitored: options.monitored,
|
||||
rootFolderPath: options.rootFolderPath,
|
||||
seriesType: options.seriesType,
|
||||
addOptions: {
|
||||
ignoreEpisodesWithFiles: true,
|
||||
searchForMissingEpisodes: options.searchNow,
|
||||
},
|
||||
} as Partial<SonarrSeries>
|
||||
);
|
||||
|
||||
if (createdSeriesData.id) {
|
||||
if (createdSeriesResponse.data.id) {
|
||||
logger.info('Sonarr accepted request', { label: 'Sonarr' });
|
||||
logger.debug('Sonarr add details', {
|
||||
label: 'Sonarr',
|
||||
movie: createdSeriesData,
|
||||
series: createdSeriesResponse.data,
|
||||
});
|
||||
} else {
|
||||
logger.error('Failed to add movie to Sonarr', {
|
||||
@@ -257,20 +264,13 @@ class SonarrAPI extends ServarrBase<{
|
||||
throw new Error('Failed to add series to Sonarr');
|
||||
}
|
||||
|
||||
return createdSeriesData;
|
||||
return createdSeriesResponse.data;
|
||||
} catch (e) {
|
||||
let errorData;
|
||||
try {
|
||||
errorData = await e.cause?.text();
|
||||
errorData = JSON.parse(errorData);
|
||||
} catch {
|
||||
/* empty */
|
||||
}
|
||||
logger.error('Something went wrong while adding a series to Sonarr.', {
|
||||
label: 'Sonarr API',
|
||||
errorMessage: e.message,
|
||||
options,
|
||||
response: errorData,
|
||||
response: e?.response?.data,
|
||||
});
|
||||
throw new Error('Failed to add series');
|
||||
}
|
||||
@@ -342,13 +342,14 @@ class SonarrAPI extends ServarrBase<{
|
||||
|
||||
return newSeasons;
|
||||
}
|
||||
|
||||
public removeSerie = async (serieId: number): Promise<void> => {
|
||||
try {
|
||||
const { id, title } = await this.getSeriesByTvdbId(serieId);
|
||||
await this.delete(`/series/${id}`, {
|
||||
deleteFiles: 'true',
|
||||
addImportExclusion: 'false',
|
||||
await this.axios.delete(`/series/${id}`, {
|
||||
params: {
|
||||
deleteFiles: true,
|
||||
addImportExclusion: false,
|
||||
},
|
||||
});
|
||||
logger.info(`[Radarr] Removed serie ${title}`);
|
||||
} catch (e) {
|
||||
@@ -368,18 +369,14 @@ class SonarrAPI extends ServarrBase<{
|
||||
if (tvdbId) {
|
||||
this.removeCache('/series/lookup', {
|
||||
term: `tvdb:${tvdbId}`,
|
||||
headers: this.defaultHeaders,
|
||||
});
|
||||
}
|
||||
if (externalId) {
|
||||
this.removeCache(`/series/${externalId}`, {
|
||||
headers: this.defaultHeaders,
|
||||
});
|
||||
this.removeCache(`/series/${externalId}`);
|
||||
}
|
||||
if (title) {
|
||||
this.removeCache('/series/lookup', {
|
||||
term: title,
|
||||
headers: this.defaultHeaders,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user