mirror of
https://github.com/fallenbagel/jellyseerr.git
synced 2026-01-01 04:08:45 -05:00
fix: enhance error messages when Fetch API fails (#893)
This commit is contained in:
@@ -68,7 +68,10 @@ class ExternalAPI {
|
|||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const text = await response.text();
|
const text = await response.text();
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`${response.status} ${response.statusText}${text ? ': ' + text : ''}`
|
`${response.status} ${response.statusText}${text ? ': ' + text : ''}`,
|
||||||
|
{
|
||||||
|
cause: response,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const data = await this.getDataFromResponse(response);
|
const data = await this.getDataFromResponse(response);
|
||||||
@@ -106,6 +109,15 @@ class ExternalAPI {
|
|||||||
},
|
},
|
||||||
body: JSON.stringify(data),
|
body: JSON.stringify(data),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
const text = await response.text();
|
||||||
|
throw new Error(
|
||||||
|
`${response.status} ${response.statusText}${text ? ': ' + text : ''}`,
|
||||||
|
{
|
||||||
|
cause: response,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
const resData = await this.getDataFromResponse(response);
|
const resData = await this.getDataFromResponse(response);
|
||||||
|
|
||||||
if (this.cache) {
|
if (this.cache) {
|
||||||
@@ -141,6 +153,15 @@ class ExternalAPI {
|
|||||||
},
|
},
|
||||||
body: JSON.stringify(data),
|
body: JSON.stringify(data),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
const text = await response.text();
|
||||||
|
throw new Error(
|
||||||
|
`${response.status} ${response.statusText}${text ? ': ' + text : ''}`,
|
||||||
|
{
|
||||||
|
cause: response,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
const resData = await this.getDataFromResponse(response);
|
const resData = await this.getDataFromResponse(response);
|
||||||
|
|
||||||
if (this.cache) {
|
if (this.cache) {
|
||||||
@@ -163,6 +184,15 @@ class ExternalAPI {
|
|||||||
...config?.headers,
|
...config?.headers,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
const text = await response.text();
|
||||||
|
throw new Error(
|
||||||
|
`${response.status} ${response.statusText}${text ? ': ' + text : ''}`,
|
||||||
|
{
|
||||||
|
cause: response,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
const data = await this.getDataFromResponse(response);
|
const data = await this.getDataFromResponse(response);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@@ -197,6 +227,17 @@ class ExternalAPI {
|
|||||||
...config?.headers,
|
...config?.headers,
|
||||||
},
|
},
|
||||||
}).then(async (response) => {
|
}).then(async (response) => {
|
||||||
|
if (!response.ok) {
|
||||||
|
const text = await response.text();
|
||||||
|
throw new Error(
|
||||||
|
`${response.status} ${response.statusText}${
|
||||||
|
text ? ': ' + text : ''
|
||||||
|
}`,
|
||||||
|
{
|
||||||
|
cause: response,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
const data = await this.getDataFromResponse(response);
|
const data = await this.getDataFromResponse(response);
|
||||||
this.cache?.set(cacheKey, data, ttl ?? DEFAULT_TTL);
|
this.cache?.set(cacheKey, data, ttl ?? DEFAULT_TTL);
|
||||||
});
|
});
|
||||||
@@ -212,6 +253,15 @@ class ExternalAPI {
|
|||||||
...config?.headers,
|
...config?.headers,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
const text = await response.text();
|
||||||
|
throw new Error(
|
||||||
|
`${response.status} ${response.statusText}${text ? ': ' + text : ''}`,
|
||||||
|
{
|
||||||
|
cause: response,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
const data = await this.getDataFromResponse(response);
|
const data = await this.getDataFromResponse(response);
|
||||||
|
|
||||||
if (this.cache) {
|
if (this.cache) {
|
||||||
@@ -250,13 +300,13 @@ class ExternalAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async getDataFromResponse(response: Response) {
|
private async getDataFromResponse(response: Response) {
|
||||||
const contentType = response.headers.get('Content-Type')?.split(';')[0];
|
const contentType = response.headers.get('Content-Type');
|
||||||
if (contentType === 'application/json') {
|
if (contentType?.includes('application/json')) {
|
||||||
return await response.json();
|
return await response.json();
|
||||||
} else if (
|
} else if (
|
||||||
contentType === 'application/xml' ||
|
contentType?.includes('application/xml') ||
|
||||||
contentType === 'text/html' ||
|
contentType?.includes('text/html') ||
|
||||||
contentType === 'text/plain'
|
contentType?.includes('text/plain')
|
||||||
) {
|
) {
|
||||||
return await response.text();
|
return await response.text();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ class JellyfinAPI extends ExternalAPI {
|
|||||||
try {
|
try {
|
||||||
return await authenticate(false);
|
return await authenticate(false);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const status = e.response?.status;
|
const status = e.cause?.status;
|
||||||
|
|
||||||
const networkErrorCodes = new Set([
|
const networkErrorCodes = new Set([
|
||||||
'ECONNREFUSED',
|
'ECONNREFUSED',
|
||||||
@@ -190,7 +190,7 @@ class JellyfinAPI extends ExternalAPI {
|
|||||||
|
|
||||||
return systemInfoResponse;
|
return systemInfoResponse;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
|
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ class JellyfinAPI extends ExternalAPI {
|
|||||||
{ label: 'Jellyfin API' }
|
{ label: 'Jellyfin API' }
|
||||||
);
|
);
|
||||||
|
|
||||||
throw new ApiError(e.response?.status, ApiErrorCode.Unknown);
|
throw new ApiError(e.cause?.status, ApiErrorCode.Unknown);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +222,7 @@ class JellyfinAPI extends ExternalAPI {
|
|||||||
{ label: 'Jellyfin API' }
|
{ label: 'Jellyfin API' }
|
||||||
);
|
);
|
||||||
|
|
||||||
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
|
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +238,7 @@ class JellyfinAPI extends ExternalAPI {
|
|||||||
{ label: 'Jellyfin API' }
|
{ label: 'Jellyfin API' }
|
||||||
);
|
);
|
||||||
|
|
||||||
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
|
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,7 +317,7 @@ class JellyfinAPI extends ExternalAPI {
|
|||||||
{ label: 'Jellyfin API' }
|
{ label: 'Jellyfin API' }
|
||||||
);
|
);
|
||||||
|
|
||||||
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
|
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +338,7 @@ class JellyfinAPI extends ExternalAPI {
|
|||||||
{ label: 'Jellyfin API' }
|
{ label: 'Jellyfin API' }
|
||||||
);
|
);
|
||||||
|
|
||||||
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
|
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,7 +353,7 @@ class JellyfinAPI extends ExternalAPI {
|
|||||||
return itemResponse;
|
return itemResponse;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (availabilitySync.running) {
|
if (availabilitySync.running) {
|
||||||
if (e.response && e.response.status === 500) {
|
if (e.cause?.status === 500) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -362,7 +362,7 @@ class JellyfinAPI extends ExternalAPI {
|
|||||||
`Something went wrong while getting library content from the Jellyfin server: ${e.message}`,
|
`Something went wrong while getting library content from the Jellyfin server: ${e.message}`,
|
||||||
{ label: 'Jellyfin API' }
|
{ label: 'Jellyfin API' }
|
||||||
);
|
);
|
||||||
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
|
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,7 +377,7 @@ class JellyfinAPI extends ExternalAPI {
|
|||||||
{ label: 'Jellyfin API' }
|
{ label: 'Jellyfin API' }
|
||||||
);
|
);
|
||||||
|
|
||||||
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
|
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,7 +402,7 @@ class JellyfinAPI extends ExternalAPI {
|
|||||||
{ label: 'Jellyfin API' }
|
{ label: 'Jellyfin API' }
|
||||||
);
|
);
|
||||||
|
|
||||||
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
|
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,13 +179,20 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
|
|||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error(
|
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.',
|
'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',
|
label: 'Radarr',
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
options,
|
options,
|
||||||
response: e?.response?.data,
|
response: errorData,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
throw new Error('Failed to add movie to Radarr');
|
throw new Error('Failed to add movie to Radarr');
|
||||||
|
|||||||
@@ -257,11 +257,18 @@ class SonarrAPI extends ServarrBase<{
|
|||||||
|
|
||||||
return createdSeriesData;
|
return createdSeriesData;
|
||||||
} catch (e) {
|
} 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.', {
|
logger.error('Something went wrong while adding a series to Sonarr.', {
|
||||||
label: 'Sonarr API',
|
label: 'Sonarr API',
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
options,
|
options,
|
||||||
response: e?.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
throw new Error('Failed to add series');
|
throw new Error('Failed to add series');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ class DiscordAgent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await fetch(settings.options.webhookUrl, {
|
const response = await fetch(settings.options.webhookUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -305,15 +305,25 @@ class DiscordAgent
|
|||||||
content: userMentions.join(' '),
|
content: userMentions.join(' '),
|
||||||
} as DiscordWebhookPayload),
|
} as DiscordWebhookPayload),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText, { cause: response });
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error('Error sending Discord notification', {
|
logger.error('Error sending Discord notification', {
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -132,22 +132,32 @@ class GotifyAgent
|
|||||||
const endpoint = `${settings.options.url}/message?token=${settings.options.token}`;
|
const endpoint = `${settings.options.url}/message?token=${settings.options.token}`;
|
||||||
const notificationPayload = this.getNotificationPayload(type, payload);
|
const notificationPayload = this.getNotificationPayload(type, payload);
|
||||||
|
|
||||||
await fetch(endpoint, {
|
const response = await fetch(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify(notificationPayload),
|
body: JSON.stringify(notificationPayload),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText, { cause: response });
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error('Error sending Gotify notification', {
|
logger.error('Error sending Gotify notification', {
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class LunaSeaAgent
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fetch(settings.options.webhookUrl, {
|
const response = await fetch(settings.options.webhookUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: settings.options.profileName
|
headers: settings.options.profileName
|
||||||
? {
|
? {
|
||||||
@@ -114,15 +114,25 @@ class LunaSeaAgent
|
|||||||
},
|
},
|
||||||
body: JSON.stringify(this.buildPayload(type, payload)),
|
body: JSON.stringify(this.buildPayload(type, payload)),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText, { cause: response });
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error('Error sending LunaSea notification', {
|
logger.error('Error sending LunaSea notification', {
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ class PushbulletAgent
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fetch(endpoint, {
|
const response = await fetch(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -133,13 +133,23 @@ class PushbulletAgent
|
|||||||
channel_tag: settings.options.channelTag,
|
channel_tag: settings.options.channelTag,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText, { cause: response });
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error('Error sending Pushbullet notification', {
|
logger.error('Error sending Pushbullet notification', {
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -164,7 +174,7 @@ class PushbulletAgent
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fetch(endpoint, {
|
const response = await fetch(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -172,14 +182,24 @@ class PushbulletAgent
|
|||||||
},
|
},
|
||||||
body: JSON.stringify(notificationPayload),
|
body: JSON.stringify(notificationPayload),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText, { cause: response });
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error('Error sending Pushbullet notification', {
|
logger.error('Error sending Pushbullet notification', {
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
recipient: payload.notifyUser.displayName,
|
recipient: payload.notifyUser.displayName,
|
||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -215,7 +235,7 @@ class PushbulletAgent
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fetch(endpoint, {
|
const response = await fetch(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -223,14 +243,24 @@ class PushbulletAgent
|
|||||||
},
|
},
|
||||||
body: JSON.stringify(notificationPayload),
|
body: JSON.stringify(notificationPayload),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText, { cause: response });
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error('Error sending Pushbullet notification', {
|
logger.error('Error sending Pushbullet notification', {
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
recipient: user.displayName,
|
recipient: user.displayName,
|
||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ class PushoverAgent
|
|||||||
): Promise<Partial<PushoverImagePayload>> {
|
): Promise<Partial<PushoverImagePayload>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(imageUrl);
|
const response = await fetch(imageUrl);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText, { cause: response });
|
||||||
|
}
|
||||||
const arrayBuffer = await response.arrayBuffer();
|
const arrayBuffer = await response.arrayBuffer();
|
||||||
const base64 = Buffer.from(arrayBuffer).toString('base64');
|
const base64 = Buffer.from(arrayBuffer).toString('base64');
|
||||||
const contentType = (
|
const contentType = (
|
||||||
@@ -64,10 +67,17 @@ class PushoverAgent
|
|||||||
attachment_type: contentType,
|
attachment_type: contentType,
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error('Error getting image payload', {
|
logger.error('Error getting image payload', {
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -200,7 +210,7 @@ class PushoverAgent
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fetch(endpoint, {
|
const response = await fetch(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -212,13 +222,23 @@ class PushoverAgent
|
|||||||
sound: settings.options.sound,
|
sound: settings.options.sound,
|
||||||
} as PushoverPayload),
|
} as PushoverPayload),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText, { cause: response });
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error('Error sending Pushover notification', {
|
logger.error('Error sending Pushover notification', {
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -246,7 +266,7 @@ class PushoverAgent
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fetch(endpoint, {
|
const response = await fetch(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -258,14 +278,24 @@ class PushoverAgent
|
|||||||
sound: payload.notifyUser.settings.pushoverSound,
|
sound: payload.notifyUser.settings.pushoverSound,
|
||||||
} as PushoverPayload),
|
} as PushoverPayload),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText, { cause: response });
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error('Error sending Pushover notification', {
|
logger.error('Error sending Pushover notification', {
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
recipient: payload.notifyUser.displayName,
|
recipient: payload.notifyUser.displayName,
|
||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -302,7 +332,7 @@ class PushoverAgent
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fetch(endpoint, {
|
const response = await fetch(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -313,14 +343,24 @@ class PushoverAgent
|
|||||||
user: user.settings.pushoverUserKey,
|
user: user.settings.pushoverUserKey,
|
||||||
} as PushoverPayload),
|
} as PushoverPayload),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText, { cause: response });
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error('Error sending Pushover notification', {
|
logger.error('Error sending Pushover notification', {
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
recipient: user.displayName,
|
recipient: user.displayName,
|
||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -237,22 +237,32 @@ class SlackAgent
|
|||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await fetch(settings.options.webhookUrl, {
|
const response = await fetch(settings.options.webhookUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify(this.buildEmbed(type, payload)),
|
body: JSON.stringify(this.buildEmbed(type, payload)),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText, { cause: response });
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error('Error sending Slack notification', {
|
logger.error('Error sending Slack notification', {
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ class TelegramAgent
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fetch(endpoint, {
|
const response = await fetch(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -185,13 +185,23 @@ class TelegramAgent
|
|||||||
disable_notification: !!settings.options.sendSilently,
|
disable_notification: !!settings.options.sendSilently,
|
||||||
} as TelegramMessagePayload | TelegramPhotoPayload),
|
} as TelegramMessagePayload | TelegramPhotoPayload),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText, { cause: response });
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error('Error sending Telegram notification', {
|
logger.error('Error sending Telegram notification', {
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -215,7 +225,7 @@ class TelegramAgent
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fetch(endpoint, {
|
const response = await fetch(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -227,14 +237,24 @@ class TelegramAgent
|
|||||||
!!payload.notifyUser.settings.telegramSendSilently,
|
!!payload.notifyUser.settings.telegramSendSilently,
|
||||||
} as TelegramMessagePayload | TelegramPhotoPayload),
|
} as TelegramMessagePayload | TelegramPhotoPayload),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText, { cause: response });
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error('Error sending Telegram notification', {
|
logger.error('Error sending Telegram notification', {
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
recipient: payload.notifyUser.displayName,
|
recipient: payload.notifyUser.displayName,
|
||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -268,7 +288,7 @@ class TelegramAgent
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fetch(endpoint, {
|
const response = await fetch(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -279,14 +299,24 @@ class TelegramAgent
|
|||||||
disable_notification: !!user.settings?.telegramSendSilently,
|
disable_notification: !!user.settings?.telegramSendSilently,
|
||||||
} as TelegramMessagePayload | TelegramPhotoPayload),
|
} as TelegramMessagePayload | TelegramPhotoPayload),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText, { cause: response });
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error('Error sending Telegram notification', {
|
logger.error('Error sending Telegram notification', {
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
recipient: user.displayName,
|
recipient: user.displayName,
|
||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ class WebhookAgent
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fetch(settings.options.webhookUrl, {
|
const response = await fetch(settings.options.webhookUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -187,15 +187,25 @@ class WebhookAgent
|
|||||||
},
|
},
|
||||||
body: JSON.stringify(this.buildPayload(type, payload)),
|
body: JSON.stringify(this.buildPayload(type, payload)),
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText, { cause: response });
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
logger.error('Error sending webhook notification', {
|
logger.error('Error sending webhook notification', {
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response?.data,
|
response: errorData,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -119,10 +119,17 @@ const JellyfinLogin: React.FC<JellyfinLoginProps> = ({
|
|||||||
email: values.email,
|
email: values.email,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
if (!res.ok) throw new Error();
|
if (!res.ok) throw new Error(res.statusText, { cause: res });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
let errorMessage = null;
|
let errorMessage = null;
|
||||||
switch (e.response?.data?.message) {
|
switch (errorData?.message) {
|
||||||
case ApiErrorCode.InvalidUrl:
|
case ApiErrorCode.InvalidUrl:
|
||||||
errorMessage = messages.invalidurlerror;
|
errorMessage = messages.invalidurlerror;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -50,14 +50,21 @@ const Login = () => {
|
|||||||
},
|
},
|
||||||
body: JSON.stringify({ authToken }),
|
body: JSON.stringify({ authToken }),
|
||||||
});
|
});
|
||||||
if (!res.ok) throw new Error();
|
if (!res.ok) throw new Error(res.statusText, { cause: res });
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|
||||||
if (data?.id) {
|
if (data?.id) {
|
||||||
revalidate();
|
revalidate();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setError(e.response.data.message);
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
|
setError(errorData?.message);
|
||||||
setAuthToken(undefined);
|
setAuthToken(undefined);
|
||||||
setProcessing(false);
|
setProcessing(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,11 +173,18 @@ const SettingsJellyfin: React.FC<SettingsJellyfinProps> = ({
|
|||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`/api/v1/settings/jellyfin/library?${searchParams.toString()}`
|
`/api/v1/settings/jellyfin/library?${searchParams.toString()}`
|
||||||
);
|
);
|
||||||
if (!res.ok) throw new Error();
|
if (!res.ok) throw new Error(res.statusText, { cause: res });
|
||||||
setIsSyncing(false);
|
setIsSyncing(false);
|
||||||
revalidate();
|
revalidate();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.response.data.message === 'SYNC_ERROR_GROUPED_FOLDERS') {
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
|
if (errorData?.message === 'SYNC_ERROR_GROUPED_FOLDERS') {
|
||||||
toasts.addToast(
|
toasts.addToast(
|
||||||
intl.formatMessage(
|
intl.formatMessage(
|
||||||
messages.jellyfinSyncFailedAutomaticGroupedFolders
|
messages.jellyfinSyncFailedAutomaticGroupedFolders
|
||||||
@@ -187,7 +194,7 @@ const SettingsJellyfin: React.FC<SettingsJellyfinProps> = ({
|
|||||||
appearance: 'warning',
|
appearance: 'warning',
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else if (e.response.data.message === 'SYNC_ERROR_NO_LIBRARIES') {
|
} else if (errorData?.message === 'SYNC_ERROR_NO_LIBRARIES') {
|
||||||
toasts.addToast(
|
toasts.addToast(
|
||||||
intl.formatMessage(messages.jellyfinSyncFailedNoLibrariesFound),
|
intl.formatMessage(messages.jellyfinSyncFailedNoLibrariesFound),
|
||||||
{
|
{
|
||||||
@@ -485,7 +492,7 @@ const SettingsJellyfin: React.FC<SettingsJellyfinProps> = ({
|
|||||||
jellyfinForgotPasswordUrl: values.jellyfinForgotPasswordUrl,
|
jellyfinForgotPasswordUrl: values.jellyfinForgotPasswordUrl,
|
||||||
} as JellyfinSettings),
|
} as JellyfinSettings),
|
||||||
});
|
});
|
||||||
if (!res.ok) throw new Error();
|
if (!res.ok) throw new Error(res.statusText, { cause: res });
|
||||||
|
|
||||||
addToast(
|
addToast(
|
||||||
intl.formatMessage(messages.jellyfinSettingsSuccess, {
|
intl.formatMessage(messages.jellyfinSettingsSuccess, {
|
||||||
@@ -500,7 +507,14 @@ const SettingsJellyfin: React.FC<SettingsJellyfinProps> = ({
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.response?.data?.message === ApiErrorCode.InvalidUrl) {
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
|
if (errorData?.message === ApiErrorCode.InvalidUrl) {
|
||||||
addToast(
|
addToast(
|
||||||
intl.formatMessage(messages.invalidurlerror, {
|
intl.formatMessage(messages.invalidurlerror, {
|
||||||
mediaServerName:
|
mediaServerName:
|
||||||
|
|||||||
@@ -295,16 +295,23 @@ const UserList = () => {
|
|||||||
password: values.genpassword ? null : values.password,
|
password: values.genpassword ? null : values.password,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
if (!res.ok) throw new Error();
|
if (!res.ok) throw new Error(res.statusText, { cause: res });
|
||||||
addToast(intl.formatMessage(messages.usercreatedsuccess), {
|
addToast(intl.formatMessage(messages.usercreatedsuccess), {
|
||||||
appearance: 'success',
|
appearance: 'success',
|
||||||
autoDismiss: true,
|
autoDismiss: true,
|
||||||
});
|
});
|
||||||
setCreateModal({ isOpen: false });
|
setCreateModal({ isOpen: false });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
let errorData;
|
||||||
|
try {
|
||||||
|
errorData = await e.cause?.text();
|
||||||
|
errorData = JSON.parse(errorData);
|
||||||
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
addToast(
|
addToast(
|
||||||
intl.formatMessage(
|
intl.formatMessage(
|
||||||
e.response.data.errors?.includes('USER_EXISTS')
|
errorData.errors?.includes('USER_EXISTS')
|
||||||
? messages.usercreatedfailedexisting
|
? messages.usercreatedfailedexisting
|
||||||
: messages.usercreatedfailed
|
: messages.usercreatedfailed
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user