mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
feat(notif): Notification improvements (#914)
This commit is contained in:
@@ -45,8 +45,8 @@ These variables are only included in media related notifications, such as reques
|
|||||||
- `{{media_tmdbid}}` Media's TMDb ID.
|
- `{{media_tmdbid}}` Media's TMDb ID.
|
||||||
- `{{media_imdbid}}` Media's IMDb ID.
|
- `{{media_imdbid}}` Media's IMDb ID.
|
||||||
- `{{media_tvdbid}}` Media's TVDB ID.
|
- `{{media_tvdbid}}` Media's TVDB ID.
|
||||||
- `{{media_status}}` Media's availability status. (Ex. `AVAILABLE` or `PENDING`)
|
- `{{media_status}}` Media's availability status (e.g., `AVAILABLE` or `PENDING`).
|
||||||
- `{{media_status4k}}` Media's 4K availability status. (Ex. `AVAILABLE` or `PENDING`)
|
- `{{media_status4k}}` Media's 4K availability status (e.g., `AVAILABLE` or `PENDING`).
|
||||||
|
|
||||||
### Special Key Variables
|
### Special Key Variables
|
||||||
|
|
||||||
@@ -54,3 +54,4 @@ These variables must be used as a key in the JSON Payload. (Ex, `"{{extra}}": []
|
|||||||
|
|
||||||
- `{{extra}}` This will override the value of the property to be the pre-formatted "extra" array that can come along with certain notifications. Using this variable is _not required_.
|
- `{{extra}}` This will override the value of the property to be the pre-formatted "extra" array that can come along with certain notifications. Using this variable is _not required_.
|
||||||
- `{{media}}` This will override the value of the property to `null` if there is no media object passed along with the notification.
|
- `{{media}}` This will override the value of the property to `null` if there is no media object passed along with the notification.
|
||||||
|
- `{{request}}` This will override the value of the property to `null` if there is no request object passed along with the notification.
|
||||||
|
@@ -111,6 +111,7 @@ export class MediaRequest {
|
|||||||
image: `https://image.tmdb.org/t/p/w600_and_h900_bestv2${movie.poster_path}`,
|
image: `https://image.tmdb.org/t/p/w600_and_h900_bestv2${movie.poster_path}`,
|
||||||
notifyUser: this.requestedBy,
|
notifyUser: this.requestedBy,
|
||||||
media,
|
media,
|
||||||
|
request: this,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,6 +131,7 @@ export class MediaRequest {
|
|||||||
.join(', '),
|
.join(', '),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
request: this,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,6 +179,7 @@ export class MediaRequest {
|
|||||||
image: `https://image.tmdb.org/t/p/w600_and_h900_bestv2${movie.poster_path}`,
|
image: `https://image.tmdb.org/t/p/w600_and_h900_bestv2${movie.poster_path}`,
|
||||||
notifyUser: this.requestedBy,
|
notifyUser: this.requestedBy,
|
||||||
media,
|
media,
|
||||||
|
request: this,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else if (this.media.mediaType === MediaType.TV) {
|
} else if (this.media.mediaType === MediaType.TV) {
|
||||||
@@ -199,6 +202,7 @@ export class MediaRequest {
|
|||||||
.join(', '),
|
.join(', '),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
request: this,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -454,6 +458,7 @@ export class MediaRequest {
|
|||||||
notifyUser: admin,
|
notifyUser: admin,
|
||||||
media,
|
media,
|
||||||
image: `https://image.tmdb.org/t/p/w600_and_h900_bestv2${movie.poster_path}`,
|
image: `https://image.tmdb.org/t/p/w600_and_h900_bestv2${movie.poster_path}`,
|
||||||
|
request: this,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
logger.info('Sent request to Radarr', { label: 'Media Request' });
|
logger.info('Sent request to Radarr', { label: 'Media Request' });
|
||||||
@@ -659,6 +664,7 @@ export class MediaRequest {
|
|||||||
.join(', '),
|
.join(', '),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
request: this,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
logger.info('Sent request to Sonarr', { label: 'Media Request' });
|
logger.info('Sent request to Sonarr', { label: 'Media Request' });
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { Notification } from '..';
|
import { Notification } from '..';
|
||||||
import Media from '../../../entity/Media';
|
import Media from '../../../entity/Media';
|
||||||
|
import { MediaRequest } from '../../../entity/MediaRequest';
|
||||||
import { User } from '../../../entity/User';
|
import { User } from '../../../entity/User';
|
||||||
import { NotificationAgentConfig } from '../../settings';
|
import { NotificationAgentConfig } from '../../settings';
|
||||||
|
|
||||||
@@ -10,6 +11,7 @@ export interface NotificationPayload {
|
|||||||
image?: string;
|
image?: string;
|
||||||
message?: string;
|
message?: string;
|
||||||
extra?: { name: string; value: string }[];
|
extra?: { name: string; value: string }[];
|
||||||
|
request?: MediaRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class BaseAgent<T extends NotificationAgentConfig> {
|
export abstract class BaseAgent<T extends NotificationAgentConfig> {
|
||||||
|
@@ -98,106 +98,64 @@ class DiscordAgent
|
|||||||
|
|
||||||
const fields: Field[] = [];
|
const fields: Field[] = [];
|
||||||
|
|
||||||
|
if (payload.request) {
|
||||||
|
fields.push({
|
||||||
|
name: 'Requested By',
|
||||||
|
value: payload.notifyUser.displayName ?? '',
|
||||||
|
inline: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Notification.MEDIA_PENDING:
|
case Notification.MEDIA_PENDING:
|
||||||
color = EmbedColors.ORANGE;
|
color = EmbedColors.ORANGE;
|
||||||
fields.push(
|
fields.push({
|
||||||
{
|
name: 'Status',
|
||||||
name: 'Requested By',
|
value: 'Pending Approval',
|
||||||
value: payload.notifyUser.displayName ?? '',
|
inline: true,
|
||||||
inline: true,
|
});
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Status',
|
|
||||||
value: 'Pending Approval',
|
|
||||||
inline: true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (settings.main.applicationUrl) {
|
|
||||||
fields.push({
|
|
||||||
name: 'View Media',
|
|
||||||
value: `${settings.main.applicationUrl}/${payload.media?.mediaType}/${payload.media?.tmdbId}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case Notification.MEDIA_APPROVED:
|
case Notification.MEDIA_APPROVED:
|
||||||
color = EmbedColors.PURPLE;
|
color = EmbedColors.PURPLE;
|
||||||
fields.push(
|
fields.push({
|
||||||
{
|
name: 'Status',
|
||||||
name: 'Requested By',
|
value: 'Processing',
|
||||||
value: payload.notifyUser.displayName ?? '',
|
inline: true,
|
||||||
inline: true,
|
});
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Status',
|
|
||||||
value: 'Processing Request',
|
|
||||||
inline: true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (settings.main.applicationUrl) {
|
|
||||||
fields.push({
|
|
||||||
name: 'View Media',
|
|
||||||
value: `${settings.main.applicationUrl}/${payload.media?.mediaType}/${payload.media?.tmdbId}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case Notification.MEDIA_AVAILABLE:
|
case Notification.MEDIA_AVAILABLE:
|
||||||
color = EmbedColors.GREEN;
|
color = EmbedColors.GREEN;
|
||||||
fields.push(
|
fields.push({
|
||||||
{
|
name: 'Status',
|
||||||
name: 'Requested By',
|
value: 'Available',
|
||||||
value: payload.notifyUser.displayName ?? '',
|
inline: true,
|
||||||
inline: true,
|
});
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Status',
|
|
||||||
value: 'Available',
|
|
||||||
inline: true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (settings.main.applicationUrl) {
|
|
||||||
fields.push({
|
|
||||||
name: 'View Media',
|
|
||||||
value: `${settings.main.applicationUrl}/${payload.media?.mediaType}/${payload.media?.tmdbId}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case Notification.MEDIA_DECLINED:
|
case Notification.MEDIA_DECLINED:
|
||||||
color = EmbedColors.RED;
|
color = EmbedColors.RED;
|
||||||
fields.push(
|
fields.push({
|
||||||
{
|
name: 'Status',
|
||||||
name: 'Requested By',
|
value: 'Declined',
|
||||||
value: payload.notifyUser.displayName ?? '',
|
inline: true,
|
||||||
inline: true,
|
});
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Status',
|
|
||||||
value: 'Declined',
|
|
||||||
inline: true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (settings.main.applicationUrl) {
|
|
||||||
fields.push({
|
|
||||||
name: 'View Media',
|
|
||||||
value: `${settings.main.applicationUrl}/${payload.media?.mediaType}/${payload.media?.tmdbId}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case Notification.MEDIA_FAILED:
|
case Notification.MEDIA_FAILED:
|
||||||
color = EmbedColors.RED;
|
color = EmbedColors.RED;
|
||||||
if (settings.main.applicationUrl) {
|
fields.push({
|
||||||
fields.push({
|
name: 'Status',
|
||||||
name: 'View Media',
|
value: 'Failed',
|
||||||
value: `${settings.main.applicationUrl}/${payload.media?.mediaType}/${payload.media?.tmdbId}`,
|
inline: true,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.main.applicationUrl && payload.media) {
|
||||||
|
fields.push({
|
||||||
|
name: `Open in ${settings.main.applicationTitle}`,
|
||||||
|
value: `${settings.main.applicationUrl}/${payload.media?.mediaType}/${payload.media?.tmdbId}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: payload.subject,
|
title: payload.subject,
|
||||||
description: payload.message,
|
description: payload.message,
|
||||||
|
@@ -9,6 +9,9 @@ interface PushoverPayload {
|
|||||||
user: string;
|
user: string;
|
||||||
title: string;
|
title: string;
|
||||||
message: string;
|
message: string;
|
||||||
|
url: string;
|
||||||
|
url_title: string;
|
||||||
|
priority: number;
|
||||||
html: number;
|
html: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,10 +44,19 @@ class PushoverAgent
|
|||||||
private constructMessageDetails(
|
private constructMessageDetails(
|
||||||
type: Notification,
|
type: Notification,
|
||||||
payload: NotificationPayload
|
payload: NotificationPayload
|
||||||
): { title: string; message: string } {
|
): {
|
||||||
|
title: string;
|
||||||
|
message: string;
|
||||||
|
url: string | undefined;
|
||||||
|
url_title: string | undefined;
|
||||||
|
priority: number;
|
||||||
|
} {
|
||||||
const settings = getSettings();
|
const settings = getSettings();
|
||||||
let messageTitle = '';
|
let messageTitle = '';
|
||||||
let message = '';
|
let message = '';
|
||||||
|
let url: string | undefined;
|
||||||
|
let url_title: string | undefined;
|
||||||
|
let priority = 0;
|
||||||
|
|
||||||
const title = payload.subject;
|
const title = payload.subject;
|
||||||
const plot = payload.message;
|
const plot = payload.message;
|
||||||
@@ -53,45 +65,69 @@ class PushoverAgent
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case Notification.MEDIA_PENDING:
|
case Notification.MEDIA_PENDING:
|
||||||
messageTitle = 'New Request';
|
messageTitle = 'New Request';
|
||||||
message += `${title}\n\n`;
|
message += `<b>${title}</b>`;
|
||||||
message += `${plot}\n\n`;
|
if (plot) {
|
||||||
message += `<b>Requested By</b>\n${username}\n\n`;
|
message += `\n${plot}`;
|
||||||
message += `<b>Status</b>\nPending Approval\n`;
|
}
|
||||||
|
message += `\n\n<b>Requested By</b>\n${username}`;
|
||||||
|
message += `\n\n<b>Status</b>\nPending Approval`;
|
||||||
break;
|
break;
|
||||||
case Notification.MEDIA_APPROVED:
|
case Notification.MEDIA_APPROVED:
|
||||||
messageTitle = 'Request Approved';
|
messageTitle = 'Request Approved';
|
||||||
message += `${title}\n\n`;
|
message += `<b>${title}</b>`;
|
||||||
message += `${plot}\n\n`;
|
if (plot) {
|
||||||
message += `<b>Requested By</b>\n${username}\n\n`;
|
message += `\n${plot}`;
|
||||||
message += `<b>Status</b>\nProcessing Request\n`;
|
}
|
||||||
|
message += `\n\n<b>Requested By</b>\n${username}`;
|
||||||
|
message += `\n\n<b>Status</b>\nProcessing`;
|
||||||
break;
|
break;
|
||||||
case Notification.MEDIA_AVAILABLE:
|
case Notification.MEDIA_AVAILABLE:
|
||||||
messageTitle = 'Now Available';
|
messageTitle = 'Now Available';
|
||||||
message += `${title}\n\n`;
|
message += `<b>${title}</b>`;
|
||||||
message += `${plot}\n\n`;
|
if (plot) {
|
||||||
message += `<b>Requested By</b>\n${username}\n\n`;
|
message += `\n${plot}`;
|
||||||
message += `<b>Status</b>\nAvailable\n`;
|
}
|
||||||
|
message += `\n\n<b>Requested By</b>\n${username}`;
|
||||||
|
message += `\n\n<b>Status</b>\nAvailable`;
|
||||||
break;
|
break;
|
||||||
case Notification.MEDIA_DECLINED:
|
case Notification.MEDIA_DECLINED:
|
||||||
messageTitle = 'Request Declined';
|
messageTitle = 'Request Declined';
|
||||||
message += `${title}\n\n`;
|
message += `<b>${title}</b>`;
|
||||||
message += `${plot}\n\n`;
|
if (plot) {
|
||||||
message += `<b>Requested By</b>\n${username}\n\n`;
|
message += `\n${plot}`;
|
||||||
message += `<b>Status</b>\nDeclined\n`;
|
}
|
||||||
|
message += `\n\n<b>Requested By</b>\n${username}`;
|
||||||
|
message += `\n\n<b>Status</b>\nDeclined`;
|
||||||
|
priority = 1;
|
||||||
|
break;
|
||||||
|
case Notification.MEDIA_FAILED:
|
||||||
|
messageTitle = 'Failed Request';
|
||||||
|
message += `<b>${title}</b>`;
|
||||||
|
if (plot) {
|
||||||
|
message += `\n${plot}`;
|
||||||
|
}
|
||||||
|
message += `\n\n<b>Requested By</b>\n${username}`;
|
||||||
|
message += `\n\n<b>Status</b>\nFailed`;
|
||||||
|
priority = 1;
|
||||||
break;
|
break;
|
||||||
case Notification.TEST_NOTIFICATION:
|
case Notification.TEST_NOTIFICATION:
|
||||||
messageTitle = 'Test Notification';
|
messageTitle = 'Test Notification';
|
||||||
message += `${plot}\n\n`;
|
message += `${plot}`;
|
||||||
message += `<b>Requested By</b>\n${username}\n`;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.main.applicationUrl && payload.media) {
|
if (settings.main.applicationUrl && payload.media) {
|
||||||
const actionUrl = `${settings.main.applicationUrl}/${payload.media.mediaType}/${payload.media.tmdbId}`;
|
url = `${settings.main.applicationUrl}/${payload.media.mediaType}/${payload.media.tmdbId}`;
|
||||||
message += `<a href="${actionUrl}">Open in ${settings.main.applicationTitle}</a>`;
|
url_title = `Open in ${settings.main.applicationTitle}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { title: messageTitle, message };
|
return {
|
||||||
|
title: messageTitle,
|
||||||
|
message,
|
||||||
|
url,
|
||||||
|
url_title,
|
||||||
|
priority,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async send(
|
public async send(
|
||||||
@@ -104,13 +140,22 @@ class PushoverAgent
|
|||||||
|
|
||||||
const { accessToken, userToken } = this.getSettings().options;
|
const { accessToken, userToken } = this.getSettings().options;
|
||||||
|
|
||||||
const { title, message } = this.constructMessageDetails(type, payload);
|
const {
|
||||||
|
title,
|
||||||
|
message,
|
||||||
|
url,
|
||||||
|
url_title,
|
||||||
|
priority,
|
||||||
|
} = this.constructMessageDetails(type, payload);
|
||||||
|
|
||||||
await axios.post(endpoint, {
|
await axios.post(endpoint, {
|
||||||
token: accessToken,
|
token: accessToken,
|
||||||
user: userToken,
|
user: userToken,
|
||||||
title: title,
|
title: title,
|
||||||
message: message,
|
message: message,
|
||||||
|
url: url,
|
||||||
|
url_title: url_title,
|
||||||
|
priority: priority,
|
||||||
html: 1,
|
html: 1,
|
||||||
} as PushoverPayload);
|
} as PushoverPayload);
|
||||||
|
|
||||||
|
@@ -58,77 +58,61 @@ class SlackAgent
|
|||||||
payload: NotificationPayload
|
payload: NotificationPayload
|
||||||
): SlackBlockEmbed {
|
): SlackBlockEmbed {
|
||||||
const settings = getSettings();
|
const settings = getSettings();
|
||||||
let header = settings.main.applicationTitle;
|
let header = '';
|
||||||
let actionUrl: string | undefined;
|
let actionUrl: string | undefined;
|
||||||
|
|
||||||
const fields: EmbedField[] = [];
|
const fields: EmbedField[] = [];
|
||||||
|
|
||||||
|
if (payload.request) {
|
||||||
|
fields.push({
|
||||||
|
type: 'mrkdwn',
|
||||||
|
text: `*Requested By*\n${payload.notifyUser.displayName ?? ''}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Notification.MEDIA_PENDING:
|
case Notification.MEDIA_PENDING:
|
||||||
header = 'New Request';
|
header = 'New Request';
|
||||||
fields.push(
|
fields.push({
|
||||||
{
|
type: 'mrkdwn',
|
||||||
type: 'mrkdwn',
|
text: '*Status*\nPending Approval',
|
||||||
text: `*Requested By*\n${payload.notifyUser.displayName ?? ''}`,
|
});
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'mrkdwn',
|
|
||||||
text: '*Status*\nPending Approval',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (settings.main.applicationUrl) {
|
|
||||||
actionUrl = `${settings.main.applicationUrl}/${payload.media?.mediaType}/${payload.media?.tmdbId}`;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case Notification.MEDIA_APPROVED:
|
case Notification.MEDIA_APPROVED:
|
||||||
header = 'Request Approved';
|
header = 'Request Approved';
|
||||||
fields.push(
|
fields.push({
|
||||||
{
|
type: 'mrkdwn',
|
||||||
type: 'mrkdwn',
|
text: '*Status*\nProcessing',
|
||||||
text: `*Requested By*\n${payload.notifyUser.displayName ?? ''}`,
|
});
|
||||||
},
|
break;
|
||||||
{
|
case Notification.MEDIA_AVAILABLE:
|
||||||
type: 'mrkdwn',
|
header = 'Now Available';
|
||||||
text: '*Status*\nProcessing Request',
|
fields.push({
|
||||||
}
|
type: 'mrkdwn',
|
||||||
);
|
text: '*Status*\nAvailable',
|
||||||
if (settings.main.applicationUrl) {
|
});
|
||||||
actionUrl = `${settings.main.applicationUrl}/${payload.media?.mediaType}/${payload.media?.tmdbId}`;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case Notification.MEDIA_DECLINED:
|
case Notification.MEDIA_DECLINED:
|
||||||
header = 'Request Declined';
|
header = 'Request Declined';
|
||||||
fields.push(
|
fields.push({
|
||||||
{
|
type: 'mrkdwn',
|
||||||
type: 'mrkdwn',
|
text: '*Status*\nDeclined',
|
||||||
text: `*Requested By*\n${payload.notifyUser.displayName ?? ''}`,
|
});
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'mrkdwn',
|
|
||||||
text: '*Status*\nDeclined',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (settings.main.applicationUrl) {
|
|
||||||
actionUrl = `${settings.main.applicationUrl}/${payload.media?.mediaType}/${payload.media?.tmdbId}`;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case Notification.MEDIA_AVAILABLE:
|
case Notification.MEDIA_FAILED:
|
||||||
header = 'Now available!';
|
header = 'Failed Request';
|
||||||
fields.push(
|
fields.push({
|
||||||
{
|
type: 'mrkdwn',
|
||||||
type: 'mrkdwn',
|
text: '*Status*\nFailed',
|
||||||
text: `*Requested By*\n${payload.notifyUser.displayName ?? ''}`,
|
});
|
||||||
},
|
break;
|
||||||
{
|
case Notification.TEST_NOTIFICATION:
|
||||||
type: 'mrkdwn',
|
header = 'Test Notification';
|
||||||
text: '*Status*\nAvailable',
|
break;
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
if (settings.main.applicationUrl) {
|
if (settings.main.applicationUrl && payload.media) {
|
||||||
actionUrl = `${settings.main.applicationUrl}/${payload.media?.mediaType}/${payload.media?.tmdbId}`;
|
actionUrl = `${settings.main.applicationUrl}/${payload.media?.mediaType}/${payload.media?.tmdbId}`;
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const blocks: EmbedBlock[] = [
|
const blocks: EmbedBlock[] = [
|
||||||
@@ -139,14 +123,17 @@ class SlackAgent
|
|||||||
text: header,
|
text: header,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
];
|
||||||
|
|
||||||
|
if (type !== Notification.TEST_NOTIFICATION) {
|
||||||
|
blocks.push({
|
||||||
type: 'section',
|
type: 'section',
|
||||||
text: {
|
text: {
|
||||||
type: 'mrkdwn',
|
type: 'mrkdwn',
|
||||||
text: `*${payload.subject}*`,
|
text: `*${payload.subject}*`,
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
];
|
}
|
||||||
|
|
||||||
if (payload.message) {
|
if (payload.message) {
|
||||||
blocks.push({
|
blocks.push({
|
||||||
@@ -191,7 +178,7 @@ class SlackAgent
|
|||||||
value: 'open_overseerr',
|
value: 'open_overseerr',
|
||||||
text: {
|
text: {
|
||||||
type: 'plain_text',
|
type: 'plain_text',
|
||||||
text: `Open ${settings.main.applicationTitle}`,
|
text: `Open in ${settings.main.applicationTitle}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@@ -8,6 +8,7 @@ interface TelegramPayload {
|
|||||||
text: string;
|
text: string;
|
||||||
parse_mode: string;
|
parse_mode: string;
|
||||||
chat_id: string;
|
chat_id: string;
|
||||||
|
disable_notification: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
class TelegramAgent
|
class TelegramAgent
|
||||||
@@ -56,49 +57,59 @@ class TelegramAgent
|
|||||||
/* eslint-disable no-useless-escape */
|
/* eslint-disable no-useless-escape */
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Notification.MEDIA_PENDING:
|
case Notification.MEDIA_PENDING:
|
||||||
message += `\*New Request\*\n`;
|
message += `\*New Request\*`;
|
||||||
message += `${title}\n\n`;
|
message += `\n\n\*${title}\*`;
|
||||||
message += `${plot}\n\n`;
|
if (plot) {
|
||||||
message += `\*Requested By\*\n${user}\n\n`;
|
message += `\n${plot}`;
|
||||||
message += `\*Status\*\nPending Approval\n`;
|
}
|
||||||
|
message += `\n\n\*Requested By\*\n${user}`;
|
||||||
|
message += `\n\n\*Status\*\nPending Approval`;
|
||||||
break;
|
break;
|
||||||
case Notification.MEDIA_APPROVED:
|
case Notification.MEDIA_APPROVED:
|
||||||
message += `\*Request Approved\*\n`;
|
message += `\*Request Approved\*`;
|
||||||
message += `${title}\n\n`;
|
message += `\n\n\*${title}\*`;
|
||||||
message += `${plot}\n\n`;
|
if (plot) {
|
||||||
message += `\*Requested By\*\n${user}\n\n`;
|
message += `\n${plot}`;
|
||||||
message += `\*Status\*\nProcessing Request\n`;
|
}
|
||||||
|
message += `\n\n\*Requested By\*\n${user}`;
|
||||||
break;
|
message += `\n\n\*Status\*\nProcessing`;
|
||||||
case Notification.MEDIA_DECLINED:
|
|
||||||
message += `\*Request Declined\*\n`;
|
|
||||||
message += `${title}\n\n`;
|
|
||||||
message += `${plot}\n\n`;
|
|
||||||
message += `\*Requested By\*\n${user}\n\n`;
|
|
||||||
message += `\*Status\*\nDeclined\n`;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case Notification.MEDIA_AVAILABLE:
|
case Notification.MEDIA_AVAILABLE:
|
||||||
message += `\*Now available\\!\*\n`;
|
message += `\*Now Available\*`;
|
||||||
message += `${title}\n\n`;
|
message += `\n\n\*${title}\*`;
|
||||||
message += `${plot}\n\n`;
|
if (plot) {
|
||||||
message += `\*Requested By\*\n${user}\n\n`;
|
message += `\n${plot}\n\n`;
|
||||||
message += `\*Status\*\nAvailable\n`;
|
}
|
||||||
|
message += `\n\n\*Requested By\*\n${user}`;
|
||||||
|
message += `\n\n\*Status\*\nAvailable`;
|
||||||
|
break;
|
||||||
|
case Notification.MEDIA_DECLINED:
|
||||||
|
message += `\*Request Declined\*`;
|
||||||
|
message += `\n\n\*${title}\*`;
|
||||||
|
if (plot) {
|
||||||
|
message += `\n${plot}`;
|
||||||
|
}
|
||||||
|
message += `\n\n\*Requested By\*\n${user}`;
|
||||||
|
message += `\n\n\*Status\*\nDeclined`;
|
||||||
|
break;
|
||||||
|
case Notification.MEDIA_FAILED:
|
||||||
|
message += `\*Failed Request\*`;
|
||||||
|
message += `\n\n\*${title}\*`;
|
||||||
|
if (plot) {
|
||||||
|
message += `\n${plot}`;
|
||||||
|
}
|
||||||
|
message += `\n\n\*Requested By\*\n${user}`;
|
||||||
|
message += `\n\n\*Status\*\nFailed`;
|
||||||
break;
|
break;
|
||||||
case Notification.TEST_NOTIFICATION:
|
case Notification.TEST_NOTIFICATION:
|
||||||
message += `\*Test Notification\*\n`;
|
message += `\*Test Notification\*`;
|
||||||
message += `${title}\n\n`;
|
message += `\n\n${plot}`;
|
||||||
message += `${plot}\n\n`;
|
|
||||||
message += `\*Requested By\*\n${user}\n`;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.main.applicationUrl && payload.media) {
|
if (settings.main.applicationUrl && payload.media) {
|
||||||
const actionUrl = `${settings.main.applicationUrl}/${payload.media.mediaType}/${payload.media.tmdbId}`;
|
const actionUrl = `${settings.main.applicationUrl}/${payload.media.mediaType}/${payload.media.tmdbId}`;
|
||||||
message += `\[Open in ${settings.main.applicationTitle}\]\(${actionUrl}\)`;
|
message += `\n\n\[Open in ${settings.main.applicationTitle}\]\(${actionUrl}\)`;
|
||||||
}
|
}
|
||||||
/* eslint-enable */
|
/* eslint-enable */
|
||||||
|
|
||||||
@@ -119,6 +130,7 @@ class TelegramAgent
|
|||||||
text: this.buildMessage(type, payload),
|
text: this.buildMessage(type, payload),
|
||||||
parse_mode: 'MarkdownV2',
|
parse_mode: 'MarkdownV2',
|
||||||
chat_id: `${this.getSettings().options.chatId}`,
|
chat_id: `${this.getSettings().options.chatId}`,
|
||||||
|
disable_notification: this.getSettings().options.sendSilently,
|
||||||
} as TelegramPayload);
|
} as TelegramPayload);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@@ -27,6 +27,7 @@ const KeyMap: Record<string, string | KeyMapFunction> = {
|
|||||||
payload.media?.status ? MediaStatus[payload.media?.status] : '',
|
payload.media?.status ? MediaStatus[payload.media?.status] : '',
|
||||||
media_status4k: (payload) =>
|
media_status4k: (payload) =>
|
||||||
payload.media?.status ? MediaStatus[payload.media?.status4k] : '',
|
payload.media?.status ? MediaStatus[payload.media?.status4k] : '',
|
||||||
|
request_id: 'request.id',
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebhookAgent
|
class WebhookAgent
|
||||||
@@ -60,6 +61,14 @@ class WebhookAgent
|
|||||||
}
|
}
|
||||||
delete finalPayload[key];
|
delete finalPayload[key];
|
||||||
key = 'media';
|
key = 'media';
|
||||||
|
} else if (key === '{{request}}') {
|
||||||
|
if (payload.request) {
|
||||||
|
finalPayload.request = finalPayload[key];
|
||||||
|
} else {
|
||||||
|
finalPayload.request = null;
|
||||||
|
}
|
||||||
|
delete finalPayload[key];
|
||||||
|
key = 'request';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof finalPayload[key] === 'string') {
|
if (typeof finalPayload[key] === 'string') {
|
||||||
|
@@ -107,6 +107,7 @@ export interface NotificationAgentTelegram extends NotificationAgentConfig {
|
|||||||
options: {
|
options: {
|
||||||
botAPI: string;
|
botAPI: string;
|
||||||
chatId: string;
|
chatId: string;
|
||||||
|
sendSilently: boolean;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,6 +221,7 @@ class Settings {
|
|||||||
options: {
|
options: {
|
||||||
botAPI: '',
|
botAPI: '',
|
||||||
chatId: '',
|
chatId: '',
|
||||||
|
sendSilently: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
pushover: {
|
pushover: {
|
||||||
|
@@ -35,6 +35,7 @@ export class MediaSubscriber implements EntitySubscriberInterface {
|
|||||||
message: movie.overview,
|
message: movie.overview,
|
||||||
media: entity,
|
media: entity,
|
||||||
image: `https://image.tmdb.org/t/p/w600_and_h900_bestv2${movie.poster_path}`,
|
image: `https://image.tmdb.org/t/p/w600_and_h900_bestv2${movie.poster_path}`,
|
||||||
|
request: request,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -96,6 +97,7 @@ export class MediaSubscriber implements EntitySubscriberInterface {
|
|||||||
.join(', '),
|
.join(', '),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
request: request,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -204,12 +204,10 @@ const NotificationsEmail: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="form-row">
|
<div className="form-row">
|
||||||
<label htmlFor="secure" className="checkbox-label">
|
<label htmlFor="secure" className="checkbox-label">
|
||||||
<div className="flex flex-col">
|
<span>{intl.formatMessage(messages.enableSsl)}</span>
|
||||||
<span>{intl.formatMessage(messages.enableSsl)}</span>
|
<span className="label-tip">
|
||||||
<span className="text-gray-500">
|
{intl.formatMessage(messages.ssldisabletip)}
|
||||||
{intl.formatMessage(messages.ssldisabletip)}
|
</span>
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</label>
|
</label>
|
||||||
<div className="form-input">
|
<div className="form-input">
|
||||||
<Field type="checkbox" id="secure" name="secure" />
|
<Field type="checkbox" id="secure" name="secure" />
|
||||||
|
@@ -28,6 +28,8 @@ const messages = defineMessages({
|
|||||||
Additionally, you need the chat ID for the chat you want the bot to send notifications to.\
|
Additionally, you need the chat ID for the chat you want the bot to send notifications to.\
|
||||||
You can do this by adding <GetIdBotLink>@get_id_bot</GetIdBotLink> to the chat or group chat.',
|
You can do this by adding <GetIdBotLink>@get_id_bot</GetIdBotLink> to the chat or group chat.',
|
||||||
notificationtypes: 'Notification Types',
|
notificationtypes: 'Notification Types',
|
||||||
|
sendSilently: 'Send Silently',
|
||||||
|
sendSilentlyTip: 'Send notifications with no sound',
|
||||||
});
|
});
|
||||||
|
|
||||||
const NotificationsTelegram: React.FC = () => {
|
const NotificationsTelegram: React.FC = () => {
|
||||||
@@ -57,6 +59,7 @@ const NotificationsTelegram: React.FC = () => {
|
|||||||
types: data?.types,
|
types: data?.types,
|
||||||
botAPI: data?.options.botAPI,
|
botAPI: data?.options.botAPI,
|
||||||
chatId: data?.options.chatId,
|
chatId: data?.options.chatId,
|
||||||
|
sendSilently: data?.options.sendSilently,
|
||||||
}}
|
}}
|
||||||
validationSchema={NotificationsTelegramSchema}
|
validationSchema={NotificationsTelegramSchema}
|
||||||
onSubmit={async (values) => {
|
onSubmit={async (values) => {
|
||||||
@@ -67,6 +70,7 @@ const NotificationsTelegram: React.FC = () => {
|
|||||||
options: {
|
options: {
|
||||||
botAPI: values.botAPI,
|
botAPI: values.botAPI,
|
||||||
chatId: values.chatId,
|
chatId: values.chatId,
|
||||||
|
sendSilently: values.sendSilently,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
addToast(intl.formatMessage(messages.telegramsettingssaved), {
|
addToast(intl.formatMessage(messages.telegramsettingssaved), {
|
||||||
@@ -91,6 +95,7 @@ const NotificationsTelegram: React.FC = () => {
|
|||||||
options: {
|
options: {
|
||||||
botAPI: values.botAPI,
|
botAPI: values.botAPI,
|
||||||
chatId: values.chatId,
|
chatId: values.chatId,
|
||||||
|
sendSilently: values.sendSilently,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -178,6 +183,21 @@ const NotificationsTelegram: React.FC = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="form-row">
|
||||||
|
<label htmlFor="sendSilently" className="checkbox-label">
|
||||||
|
<span>{intl.formatMessage(messages.sendSilently)}</span>
|
||||||
|
<span className="label-tip">
|
||||||
|
{intl.formatMessage(messages.sendSilentlyTip)}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<div className="form-input">
|
||||||
|
<Field
|
||||||
|
type="checkbox"
|
||||||
|
id="sendSilently"
|
||||||
|
name="sendSilently"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
role="group"
|
role="group"
|
||||||
aria-labelledby="group-label"
|
aria-labelledby="group-label"
|
||||||
|
@@ -29,6 +29,9 @@ const defaultPayload = {
|
|||||||
status4k: '{{media_status4k}}',
|
status4k: '{{media_status4k}}',
|
||||||
},
|
},
|
||||||
'{{extra}}': [],
|
'{{extra}}': [],
|
||||||
|
'{{request}}': {
|
||||||
|
request_id: '{{request_id}}',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
@@ -287,6 +287,8 @@
|
|||||||
"components.Settings.Notifications.notificationtypes": "Notification Types",
|
"components.Settings.Notifications.notificationtypes": "Notification Types",
|
||||||
"components.Settings.Notifications.save": "Save Changes",
|
"components.Settings.Notifications.save": "Save Changes",
|
||||||
"components.Settings.Notifications.saving": "Saving…",
|
"components.Settings.Notifications.saving": "Saving…",
|
||||||
|
"components.Settings.Notifications.sendSilently": "Send Silently",
|
||||||
|
"components.Settings.Notifications.sendSilentlyTip": "Send notifications with no sound",
|
||||||
"components.Settings.Notifications.senderName": "Sender Name",
|
"components.Settings.Notifications.senderName": "Sender Name",
|
||||||
"components.Settings.Notifications.settinguptelegram": "Setting Up Telegram Notifications",
|
"components.Settings.Notifications.settinguptelegram": "Setting Up Telegram Notifications",
|
||||||
"components.Settings.Notifications.settinguptelegramDescription": "To set up Telegram, you need to <CreateBotLink>create a bot</CreateBotLink> and get the bot API key. Additionally, you need the chat ID for the chat you want the bot to send notifications to. You can do this by adding <GetIdBotLink>@get_id_bot</GetIdBotLink> to the chat or group chat.",
|
"components.Settings.Notifications.settinguptelegramDescription": "To set up Telegram, you need to <CreateBotLink>create a bot</CreateBotLink> and get the bot API key. Additionally, you need the chat ID for the chat you want the bot to send notifications to. You can do this by adding <GetIdBotLink>@get_id_bot</GetIdBotLink> to the chat or group chat.",
|
||||||
|
Reference in New Issue
Block a user