mirror of
https://github.com/sct/overseerr.git
synced 2025-09-26 20:12:33 +02:00
feat: allow users to select notification types (#1512)
* feat: allow users to select notification types * fix(ui): display personal notification types before management types * fix: update allRequestsAutoApproved check to account for new REQUEST_MOVIE & REQUEST_TV perms * fix(ui): do not display Discord notif type selector if user not eligible for any types * refactor(ui): remove unnecessary 'enabled' checkboxes from user notif settings * fix(ui): correct checkbox behavior * fix: add missing return type on hasNotificationType * refactor: remove unused isValid prop in NotificationsWebPush * fix(ui): use SensitiveInput for users' public PGP keys * fix(ui): add missing tip/hint for email encryption setting * refactor(svg): use the new Discord logo * revert(api): undo breaking change removing discordEnabled from UserSettingsNotificationsResponse * fix(lang): update notification type descriptions for clarity * fix(telegram): do not send users notifications of their own auto-approved requests
This commit is contained in:
@@ -24,6 +24,6 @@ export abstract class BaseAgent<T extends NotificationAgentConfig> {
|
||||
}
|
||||
|
||||
export interface NotificationAgent {
|
||||
shouldSend(type: Notification): boolean;
|
||||
shouldSend(): boolean;
|
||||
send(type: Notification, payload: NotificationPayload): Promise<boolean>;
|
||||
}
|
||||
|
@@ -193,12 +193,10 @@ class DiscordAgent
|
||||
};
|
||||
}
|
||||
|
||||
public shouldSend(type: Notification): boolean {
|
||||
if (
|
||||
this.getSettings().enabled &&
|
||||
this.getSettings().options.webhookUrl &&
|
||||
hasNotificationType(type, this.getSettings().types)
|
||||
) {
|
||||
public shouldSend(): boolean {
|
||||
const settings = this.getSettings();
|
||||
|
||||
if (settings.enabled && settings.options.webhookUrl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -209,6 +207,12 @@ class DiscordAgent
|
||||
type: Notification,
|
||||
payload: NotificationPayload
|
||||
): Promise<boolean> {
|
||||
const settings = this.getSettings();
|
||||
|
||||
if (!hasNotificationType(type, settings.types ?? 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
logger.debug('Sending Discord notification', {
|
||||
label: 'Notifications',
|
||||
type: Notification[type],
|
||||
@@ -218,13 +222,6 @@ class DiscordAgent
|
||||
let content = undefined;
|
||||
|
||||
try {
|
||||
const { botUsername, botAvatarUrl, webhookUrl } =
|
||||
this.getSettings().options;
|
||||
|
||||
if (!webhookUrl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (payload.notifyUser) {
|
||||
// Mention user who submitted the request
|
||||
if (
|
||||
@@ -258,9 +255,9 @@ class DiscordAgent
|
||||
.join(' ');
|
||||
}
|
||||
|
||||
await axios.post(webhookUrl, {
|
||||
username: botUsername,
|
||||
avatar_url: botAvatarUrl,
|
||||
await axios.post(settings.options.webhookUrl, {
|
||||
username: settings.options.botUsername,
|
||||
avatar_url: settings.options.botAvatarUrl,
|
||||
embeds: [this.buildEmbed(type, payload)],
|
||||
content,
|
||||
} as DiscordWebhookPayload);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { EmailOptions } from 'email-templates';
|
||||
import path from 'path';
|
||||
import { getRepository } from 'typeorm';
|
||||
import { hasNotificationType, Notification } from '..';
|
||||
import { Notification } from '..';
|
||||
import { MediaType } from '../../../constants/media';
|
||||
import { User } from '../../../entity/User';
|
||||
import logger from '../../../logger';
|
||||
@@ -28,12 +28,14 @@ class EmailAgent
|
||||
return settings.notifications.agents.email;
|
||||
}
|
||||
|
||||
public shouldSend(type: Notification): boolean {
|
||||
public shouldSend(): boolean {
|
||||
const settings = this.getSettings();
|
||||
|
||||
if (
|
||||
settings.enabled &&
|
||||
hasNotificationType(type, this.getSettings().types)
|
||||
settings.options.emailFrom &&
|
||||
settings.options.smtpHost &&
|
||||
settings.options.smtpPort
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
@@ -50,12 +50,10 @@ class LunaSeaAgent
|
||||
};
|
||||
}
|
||||
|
||||
public shouldSend(type: Notification): boolean {
|
||||
if (
|
||||
this.getSettings().enabled &&
|
||||
this.getSettings().options.webhookUrl &&
|
||||
hasNotificationType(type, this.getSettings().types)
|
||||
) {
|
||||
public shouldSend(): boolean {
|
||||
const settings = this.getSettings();
|
||||
|
||||
if (settings.enabled && settings.options.webhookUrl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -66,6 +64,12 @@ class LunaSeaAgent
|
||||
type: Notification,
|
||||
payload: NotificationPayload
|
||||
): Promise<boolean> {
|
||||
const settings = this.getSettings();
|
||||
|
||||
if (!hasNotificationType(type, settings.types ?? 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
logger.debug('Sending LunaSea notification', {
|
||||
label: 'Notifications',
|
||||
type: Notification[type],
|
||||
@@ -73,19 +77,19 @@ class LunaSeaAgent
|
||||
});
|
||||
|
||||
try {
|
||||
const { webhookUrl, profileName } = this.getSettings().options;
|
||||
|
||||
if (!webhookUrl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await axios.post(webhookUrl, this.buildPayload(type, payload), {
|
||||
headers: {
|
||||
Authorization: `Basic ${Buffer.from(`${profileName}:`).toString(
|
||||
'base64'
|
||||
)}`,
|
||||
},
|
||||
});
|
||||
await axios.post(
|
||||
settings.options.webhookUrl,
|
||||
this.buildPayload(type, payload),
|
||||
settings.options.profileName
|
||||
? {
|
||||
headers: {
|
||||
Authorization: `Basic ${Buffer.from(
|
||||
`${settings.options.profileName}:`
|
||||
).toString('base64')}`,
|
||||
},
|
||||
}
|
||||
: undefined
|
||||
);
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
@@ -94,7 +98,7 @@ class LunaSeaAgent
|
||||
type: Notification[type],
|
||||
subject: payload.subject,
|
||||
errorMessage: e.message,
|
||||
response: e.response.data,
|
||||
response: e.response?.data,
|
||||
});
|
||||
|
||||
return false;
|
||||
|
@@ -24,12 +24,10 @@ class PushbulletAgent
|
||||
return settings.notifications.agents.pushbullet;
|
||||
}
|
||||
|
||||
public shouldSend(type: Notification): boolean {
|
||||
if (
|
||||
this.getSettings().enabled &&
|
||||
this.getSettings().options.accessToken &&
|
||||
hasNotificationType(type, this.getSettings().types)
|
||||
) {
|
||||
public shouldSend(): boolean {
|
||||
const settings = this.getSettings();
|
||||
|
||||
if (settings.enabled && settings.options.accessToken) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -137,6 +135,12 @@ class PushbulletAgent
|
||||
type: Notification,
|
||||
payload: NotificationPayload
|
||||
): Promise<boolean> {
|
||||
const settings = this.getSettings();
|
||||
|
||||
if (!hasNotificationType(type, settings.types ?? 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
logger.debug('Sending Pushbullet notification', {
|
||||
label: 'Notifications',
|
||||
type: Notification[type],
|
||||
@@ -144,14 +148,10 @@ class PushbulletAgent
|
||||
});
|
||||
|
||||
try {
|
||||
const endpoint = 'https://api.pushbullet.com/v2/pushes';
|
||||
|
||||
const { accessToken } = this.getSettings().options;
|
||||
|
||||
const { title, body } = this.constructMessageDetails(type, payload);
|
||||
|
||||
await axios.post(
|
||||
endpoint,
|
||||
'https://api.pushbullet.com/v2/pushes',
|
||||
{
|
||||
type: 'note',
|
||||
title: title,
|
||||
@@ -159,7 +159,7 @@ class PushbulletAgent
|
||||
} as PushbulletPayload,
|
||||
{
|
||||
headers: {
|
||||
'Access-Token': accessToken,
|
||||
'Access-Token': settings.options.accessToken,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
@@ -30,12 +30,13 @@ class PushoverAgent
|
||||
return settings.notifications.agents.pushover;
|
||||
}
|
||||
|
||||
public shouldSend(type: Notification): boolean {
|
||||
public shouldSend(): boolean {
|
||||
const settings = this.getSettings();
|
||||
|
||||
if (
|
||||
this.getSettings().enabled &&
|
||||
this.getSettings().options.accessToken &&
|
||||
this.getSettings().options.userToken &&
|
||||
hasNotificationType(type, this.getSettings().types)
|
||||
settings.enabled &&
|
||||
settings.options.accessToken &&
|
||||
settings.options.userToken
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
@@ -161,6 +162,12 @@ class PushoverAgent
|
||||
type: Notification,
|
||||
payload: NotificationPayload
|
||||
): Promise<boolean> {
|
||||
const settings = this.getSettings();
|
||||
|
||||
if (!hasNotificationType(type, settings.types ?? 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
logger.debug('Sending Pushover notification', {
|
||||
label: 'Notifications',
|
||||
type: Notification[type],
|
||||
@@ -169,14 +176,12 @@ class PushoverAgent
|
||||
try {
|
||||
const endpoint = 'https://api.pushover.net/1/messages.json';
|
||||
|
||||
const { accessToken, userToken } = this.getSettings().options;
|
||||
|
||||
const { title, message, url, url_title, priority } =
|
||||
this.constructMessageDetails(type, payload);
|
||||
|
||||
await axios.post(endpoint, {
|
||||
token: accessToken,
|
||||
user: userToken,
|
||||
token: settings.options.accessToken,
|
||||
user: settings.options.userToken,
|
||||
title: title,
|
||||
message: message,
|
||||
url: url,
|
||||
|
@@ -218,12 +218,10 @@ class SlackAgent
|
||||
};
|
||||
}
|
||||
|
||||
public shouldSend(type: Notification): boolean {
|
||||
if (
|
||||
this.getSettings().enabled &&
|
||||
this.getSettings().options.webhookUrl &&
|
||||
hasNotificationType(type, this.getSettings().types)
|
||||
) {
|
||||
public shouldSend(): boolean {
|
||||
const settings = this.getSettings();
|
||||
|
||||
if (settings.enabled && settings.options.webhookUrl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -234,19 +232,22 @@ class SlackAgent
|
||||
type: Notification,
|
||||
payload: NotificationPayload
|
||||
): Promise<boolean> {
|
||||
const settings = this.getSettings();
|
||||
|
||||
if (!hasNotificationType(type, settings.types ?? 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
logger.debug('Sending Slack notification', {
|
||||
label: 'Notifications',
|
||||
type: Notification[type],
|
||||
subject: payload.subject,
|
||||
});
|
||||
try {
|
||||
const webhookUrl = this.getSettings().options.webhookUrl;
|
||||
|
||||
if (!webhookUrl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await axios.post(webhookUrl, this.buildEmbed(type, payload));
|
||||
await axios.post(
|
||||
settings.options.webhookUrl,
|
||||
this.buildEmbed(type, payload)
|
||||
);
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
|
@@ -1,7 +1,10 @@
|
||||
import axios from 'axios';
|
||||
import { getRepository } from 'typeorm';
|
||||
import { hasNotificationType, Notification } from '..';
|
||||
import { MediaType } from '../../../constants/media';
|
||||
import { User } from '../../../entity/User';
|
||||
import logger from '../../../logger';
|
||||
import { Permission } from '../../permissions';
|
||||
import {
|
||||
getSettings,
|
||||
NotificationAgentKey,
|
||||
@@ -40,12 +43,13 @@ class TelegramAgent
|
||||
return settings.notifications.agents.telegram;
|
||||
}
|
||||
|
||||
public shouldSend(type: Notification): boolean {
|
||||
public shouldSend(): boolean {
|
||||
const settings = this.getSettings();
|
||||
|
||||
if (
|
||||
this.getSettings().enabled &&
|
||||
this.getSettings().options.botAPI &&
|
||||
this.getSettings().options.chatId &&
|
||||
hasNotificationType(type, this.getSettings().types)
|
||||
settings.enabled &&
|
||||
settings.options.botAPI &&
|
||||
settings.options.chatId
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
@@ -59,8 +63,10 @@ class TelegramAgent
|
||||
|
||||
private buildMessage(
|
||||
type: Notification,
|
||||
payload: NotificationPayload
|
||||
): string {
|
||||
payload: NotificationPayload,
|
||||
chatId: string,
|
||||
sendSilently: boolean
|
||||
): TelegramMessagePayload | TelegramPhotoPayload {
|
||||
const settings = getSettings();
|
||||
let message = '';
|
||||
|
||||
@@ -153,95 +159,53 @@ class TelegramAgent
|
||||
}
|
||||
/* eslint-enable */
|
||||
|
||||
return message;
|
||||
return payload.image
|
||||
? ({
|
||||
photo: payload.image,
|
||||
caption: message,
|
||||
parse_mode: 'MarkdownV2',
|
||||
chat_id: chatId,
|
||||
disable_notification: !!sendSilently,
|
||||
} as TelegramPhotoPayload)
|
||||
: ({
|
||||
text: message,
|
||||
parse_mode: 'MarkdownV2',
|
||||
chat_id: chatId,
|
||||
disable_notification: !!sendSilently,
|
||||
} as TelegramMessagePayload);
|
||||
}
|
||||
|
||||
public async send(
|
||||
type: Notification,
|
||||
payload: NotificationPayload
|
||||
): Promise<boolean> {
|
||||
const endpoint = `${this.baseUrl}bot${this.getSettings().options.botAPI}/${
|
||||
const settings = this.getSettings();
|
||||
|
||||
const endpoint = `${this.baseUrl}bot${settings.options.botAPI}/${
|
||||
payload.image ? 'sendPhoto' : 'sendMessage'
|
||||
}`;
|
||||
|
||||
// Send system notification
|
||||
try {
|
||||
if (hasNotificationType(type, settings.types ?? 0)) {
|
||||
logger.debug('Sending Telegram notification', {
|
||||
label: 'Notifications',
|
||||
type: Notification[type],
|
||||
subject: payload.subject,
|
||||
});
|
||||
|
||||
await axios.post(
|
||||
endpoint,
|
||||
payload.image
|
||||
? ({
|
||||
photo: payload.image,
|
||||
caption: this.buildMessage(type, payload),
|
||||
parse_mode: 'MarkdownV2',
|
||||
chat_id: this.getSettings().options.chatId,
|
||||
disable_notification: this.getSettings().options.sendSilently,
|
||||
} as TelegramPhotoPayload)
|
||||
: ({
|
||||
text: this.buildMessage(type, payload),
|
||||
parse_mode: 'MarkdownV2',
|
||||
chat_id: `${this.getSettings().options.chatId}`,
|
||||
disable_notification: this.getSettings().options.sendSilently,
|
||||
} as TelegramMessagePayload)
|
||||
);
|
||||
} catch (e) {
|
||||
logger.error('Error sending Telegram notification', {
|
||||
label: 'Notifications',
|
||||
type: Notification[type],
|
||||
subject: payload.subject,
|
||||
errorMessage: e.message,
|
||||
response: e.response.data,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
payload.notifyUser &&
|
||||
payload.notifyUser.settings?.hasNotificationType(
|
||||
NotificationAgentKey.TELEGRAM,
|
||||
type
|
||||
) &&
|
||||
payload.notifyUser.settings?.telegramChatId &&
|
||||
payload.notifyUser.settings?.telegramChatId !==
|
||||
this.getSettings().options.chatId
|
||||
) {
|
||||
// Send notification to the user who submitted the request
|
||||
logger.debug('Sending Telegram notification', {
|
||||
label: 'Notifications',
|
||||
recipient: payload.notifyUser.displayName,
|
||||
type: Notification[type],
|
||||
subject: payload.subject,
|
||||
});
|
||||
|
||||
try {
|
||||
await axios.post(
|
||||
endpoint,
|
||||
payload.image
|
||||
? ({
|
||||
photo: payload.image,
|
||||
caption: this.buildMessage(type, payload),
|
||||
parse_mode: 'MarkdownV2',
|
||||
chat_id: payload.notifyUser.settings.telegramChatId,
|
||||
disable_notification:
|
||||
payload.notifyUser.settings.telegramSendSilently,
|
||||
} as TelegramPhotoPayload)
|
||||
: ({
|
||||
text: this.buildMessage(type, payload),
|
||||
parse_mode: 'MarkdownV2',
|
||||
chat_id: payload.notifyUser.settings.telegramChatId,
|
||||
disable_notification:
|
||||
payload.notifyUser.settings.telegramSendSilently,
|
||||
} as TelegramMessagePayload)
|
||||
this.buildMessage(
|
||||
type,
|
||||
payload,
|
||||
settings.options.chatId,
|
||||
settings.options.sendSilently
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
logger.error('Error sending Telegram notification', {
|
||||
label: 'Notifications',
|
||||
recipient: payload.notifyUser.displayName,
|
||||
type: Notification[type],
|
||||
subject: payload.subject,
|
||||
errorMessage: e.message,
|
||||
@@ -252,6 +216,103 @@ class TelegramAgent
|
||||
}
|
||||
}
|
||||
|
||||
if (payload.notifyUser) {
|
||||
// Send notification to the user who submitted the request
|
||||
if (
|
||||
payload.notifyUser.settings?.hasNotificationType(
|
||||
NotificationAgentKey.TELEGRAM,
|
||||
type
|
||||
) &&
|
||||
payload.notifyUser.settings?.telegramChatId &&
|
||||
payload.notifyUser.settings?.telegramChatId !== settings.options.chatId
|
||||
) {
|
||||
logger.debug('Sending Telegram notification', {
|
||||
label: 'Notifications',
|
||||
recipient: payload.notifyUser.displayName,
|
||||
type: Notification[type],
|
||||
subject: payload.subject,
|
||||
});
|
||||
|
||||
try {
|
||||
await axios.post(
|
||||
endpoint,
|
||||
this.buildMessage(
|
||||
type,
|
||||
payload,
|
||||
payload.notifyUser.settings.telegramChatId,
|
||||
!!payload.notifyUser.settings.telegramSendSilently
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
logger.error('Error sending Telegram notification', {
|
||||
label: 'Notifications',
|
||||
recipient: payload.notifyUser.displayName,
|
||||
type: Notification[type],
|
||||
subject: payload.subject,
|
||||
errorMessage: e.message,
|
||||
response: e.response?.data,
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Send notifications to all users with the Manage Requests permission
|
||||
const userRepository = getRepository(User);
|
||||
const users = await userRepository.find();
|
||||
|
||||
await Promise.all(
|
||||
users
|
||||
.filter(
|
||||
(user) =>
|
||||
user.hasPermission(Permission.MANAGE_REQUESTS) &&
|
||||
user.settings?.hasNotificationType(
|
||||
NotificationAgentKey.TELEGRAM,
|
||||
type
|
||||
) &&
|
||||
// Check if it's the user's own auto-approved request
|
||||
(type !== Notification.MEDIA_AUTO_APPROVED ||
|
||||
user.id !== payload.request?.requestedBy.id)
|
||||
)
|
||||
.map(async (user) => {
|
||||
if (
|
||||
user.settings?.telegramChatId &&
|
||||
user.settings.telegramChatId !== settings.options.chatId
|
||||
) {
|
||||
logger.debug('Sending Telegram notification', {
|
||||
label: 'Notifications',
|
||||
recipient: user.displayName,
|
||||
type: Notification[type],
|
||||
subject: payload.subject,
|
||||
});
|
||||
|
||||
try {
|
||||
await axios.post(
|
||||
endpoint,
|
||||
this.buildMessage(
|
||||
type,
|
||||
payload,
|
||||
user.settings.telegramChatId,
|
||||
!!user.settings?.telegramSendSilently
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
logger.error('Error sending Telegram notification', {
|
||||
label: 'Notifications',
|
||||
recipient: user.displayName,
|
||||
type: Notification[type],
|
||||
subject: payload.subject,
|
||||
errorMessage: e.message,
|
||||
response: e.response?.data,
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -113,12 +113,10 @@ class WebhookAgent
|
||||
return this.parseKeys(parsedJSON, payload, type);
|
||||
}
|
||||
|
||||
public shouldSend(type: Notification): boolean {
|
||||
if (
|
||||
this.getSettings().enabled &&
|
||||
this.getSettings().options.webhookUrl &&
|
||||
hasNotificationType(type, this.getSettings().types)
|
||||
) {
|
||||
public shouldSend(): boolean {
|
||||
const settings = this.getSettings();
|
||||
|
||||
if (settings.enabled && settings.options.webhookUrl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -129,6 +127,12 @@ class WebhookAgent
|
||||
type: Notification,
|
||||
payload: NotificationPayload
|
||||
): Promise<boolean> {
|
||||
const settings = this.getSettings();
|
||||
|
||||
if (!hasNotificationType(type, settings.types ?? 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
logger.debug('Sending webhook notification', {
|
||||
label: 'Notifications',
|
||||
type: Notification[type],
|
||||
@@ -136,17 +140,17 @@ class WebhookAgent
|
||||
});
|
||||
|
||||
try {
|
||||
const { webhookUrl, authHeader } = this.getSettings().options;
|
||||
|
||||
if (!webhookUrl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await axios.post(webhookUrl, this.buildPayload(type, payload), {
|
||||
headers: {
|
||||
Authorization: authHeader,
|
||||
},
|
||||
});
|
||||
await axios.post(
|
||||
settings.options.webhookUrl,
|
||||
this.buildPayload(type, payload),
|
||||
settings.options.authHeader
|
||||
? {
|
||||
headers: {
|
||||
Authorization: settings.options.authHeader,
|
||||
},
|
||||
}
|
||||
: undefined
|
||||
);
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { getRepository } from 'typeorm';
|
||||
import webpush from 'web-push';
|
||||
import { hasNotificationType, Notification } from '..';
|
||||
import { Notification } from '..';
|
||||
import { MediaType } from '../../../constants/media';
|
||||
import { User } from '../../../entity/User';
|
||||
import { UserPushSubscription } from '../../../entity/UserPushSubscription';
|
||||
@@ -135,11 +135,8 @@ class WebPushAgent
|
||||
}
|
||||
}
|
||||
|
||||
public shouldSend(type: Notification): boolean {
|
||||
if (
|
||||
this.getSettings().enabled &&
|
||||
hasNotificationType(type, this.getSettings().types)
|
||||
) {
|
||||
public shouldSend(): boolean {
|
||||
if (this.getSettings().enabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -150,11 +147,6 @@ class WebPushAgent
|
||||
type: Notification,
|
||||
payload: NotificationPayload
|
||||
): Promise<boolean> {
|
||||
logger.debug('Sending web push notification', {
|
||||
label: 'Notifications',
|
||||
type: Notification[type],
|
||||
subject: payload.subject,
|
||||
});
|
||||
const userRepository = getRepository(User);
|
||||
const userPushSubRepository = getRepository(UserPushSubscription);
|
||||
const settings = getSettings();
|
||||
@@ -213,8 +205,15 @@ class WebPushAgent
|
||||
settings.vapidPrivate
|
||||
);
|
||||
|
||||
Promise.all(
|
||||
await Promise.all(
|
||||
pushSubs.map(async (sub) => {
|
||||
logger.debug('Sending web push notification', {
|
||||
label: 'Notifications',
|
||||
recipient: sub.user.displayName,
|
||||
type: Notification[type],
|
||||
subject: payload.subject,
|
||||
});
|
||||
|
||||
try {
|
||||
await webpush.sendNotification(
|
||||
{
|
||||
@@ -230,12 +229,24 @@ class WebPushAgent
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
logger.error(
|
||||
'Error sending web push notification; removing subscription',
|
||||
{
|
||||
label: 'Notifications',
|
||||
recipient: sub.user.displayName,
|
||||
type: Notification[type],
|
||||
subject: payload.subject,
|
||||
errorMessage: e.message,
|
||||
}
|
||||
);
|
||||
|
||||
// Failed to send notification so we need to remove the subscription
|
||||
userPushSubRepository.remove(sub);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user