mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
feat: PWA Support (#1488)
This commit is contained in:
@@ -11,7 +11,7 @@ collectionRoutes.get<{ id: string }>('/:id', async (req, res, next) => {
|
||||
try {
|
||||
const collection = await tmdb.getCollection({
|
||||
collectionId: Number(req.params.id),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
const media = await Media.getRelatedMedia(
|
||||
|
@@ -1,16 +1,16 @@
|
||||
import { Router } from 'express';
|
||||
import TheMovieDb from '../api/themoviedb';
|
||||
import { mapMovieResult, mapTvResult, mapPersonResult } from '../models/Search';
|
||||
import Media from '../entity/Media';
|
||||
import { isMovie, isPerson } from '../utils/typeHelpers';
|
||||
import { MediaType } from '../constants/media';
|
||||
import { getSettings } from '../lib/settings';
|
||||
import { User } from '../entity/User';
|
||||
import { mapProductionCompany } from '../models/Movie';
|
||||
import { mapNetwork } from '../models/Tv';
|
||||
import logger from '../logger';
|
||||
import { sortBy } from 'lodash';
|
||||
import TheMovieDb from '../api/themoviedb';
|
||||
import { MediaType } from '../constants/media';
|
||||
import Media from '../entity/Media';
|
||||
import { User } from '../entity/User';
|
||||
import { GenreSliderItem } from '../interfaces/api/discoverInterfaces';
|
||||
import { getSettings } from '../lib/settings';
|
||||
import logger from '../logger';
|
||||
import { mapProductionCompany } from '../models/Movie';
|
||||
import { mapMovieResult, mapPersonResult, mapTvResult } from '../models/Search';
|
||||
import { mapNetwork } from '../models/Tv';
|
||||
import { isMovie, isPerson } from '../utils/typeHelpers';
|
||||
|
||||
const createTmdbWithRegionLanaguage = (user?: User): TheMovieDb => {
|
||||
const settings = getSettings();
|
||||
@@ -42,7 +42,7 @@ discoverRoutes.get('/movies', async (req, res) => {
|
||||
|
||||
const data = await tmdb.getDiscoverMovies({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
genre: req.query.genre ? Number(req.query.genre) : undefined,
|
||||
studio: req.query.studio ? Number(req.query.studio) : undefined,
|
||||
});
|
||||
@@ -83,7 +83,7 @@ discoverRoutes.get<{ language: string }>(
|
||||
|
||||
const data = await tmdb.getDiscoverMovies({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
originalLanguage: req.params.language,
|
||||
});
|
||||
|
||||
@@ -115,7 +115,7 @@ discoverRoutes.get<{ genreId: string }>(
|
||||
const tmdb = createTmdbWithRegionLanaguage(req.user);
|
||||
|
||||
const genres = await tmdb.getMovieGenres({
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
const genre = genres.find(
|
||||
@@ -128,7 +128,7 @@ discoverRoutes.get<{ genreId: string }>(
|
||||
|
||||
const data = await tmdb.getDiscoverMovies({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
genre: Number(req.params.genreId),
|
||||
});
|
||||
|
||||
@@ -164,7 +164,7 @@ discoverRoutes.get<{ studioId: string }>(
|
||||
|
||||
const data = await tmdb.getDiscoverMovies({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
studio: Number(req.params.studioId),
|
||||
});
|
||||
|
||||
@@ -204,7 +204,7 @@ discoverRoutes.get('/movies/upcoming', async (req, res) => {
|
||||
|
||||
const data = await tmdb.getDiscoverMovies({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
primaryReleaseDateGte: date,
|
||||
});
|
||||
|
||||
@@ -232,7 +232,7 @@ discoverRoutes.get('/tv', async (req, res) => {
|
||||
|
||||
const data = await tmdb.getDiscoverTv({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
genre: req.query.genre ? Number(req.query.genre) : undefined,
|
||||
network: req.query.network ? Number(req.query.network) : undefined,
|
||||
});
|
||||
@@ -273,7 +273,7 @@ discoverRoutes.get<{ language: string }>(
|
||||
|
||||
const data = await tmdb.getDiscoverTv({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
originalLanguage: req.params.language,
|
||||
});
|
||||
|
||||
@@ -304,7 +304,7 @@ discoverRoutes.get<{ genreId: string }>(
|
||||
const tmdb = createTmdbWithRegionLanaguage(req.user);
|
||||
|
||||
const genres = await tmdb.getTvGenres({
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
const genre = genres.find(
|
||||
@@ -317,7 +317,7 @@ discoverRoutes.get<{ genreId: string }>(
|
||||
|
||||
const data = await tmdb.getDiscoverTv({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
genre: Number(req.params.genreId),
|
||||
});
|
||||
|
||||
@@ -352,7 +352,7 @@ discoverRoutes.get<{ networkId: string }>(
|
||||
|
||||
const data = await tmdb.getDiscoverTv({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
network: Number(req.params.networkId),
|
||||
});
|
||||
|
||||
@@ -392,7 +392,7 @@ discoverRoutes.get('/tv/upcoming', async (req, res) => {
|
||||
|
||||
const data = await tmdb.getDiscoverTv({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
firstAirDateGte: date,
|
||||
});
|
||||
|
||||
@@ -420,7 +420,7 @@ discoverRoutes.get('/trending', async (req, res) => {
|
||||
|
||||
const data = await tmdb.getAllTrending({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
const media = await Media.getRelatedMedia(
|
||||
@@ -461,7 +461,7 @@ discoverRoutes.get<{ keywordId: string }>(
|
||||
const data = await tmdb.getMoviesByKeyword({
|
||||
keywordId: Number(req.params.keywordId),
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
const media = await Media.getRelatedMedia(
|
||||
@@ -494,7 +494,7 @@ discoverRoutes.get<{ language: string }, GenreSliderItem[]>(
|
||||
const mappedGenres: GenreSliderItem[] = [];
|
||||
|
||||
const genres = await tmdb.getMovieGenres({
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
@@ -535,7 +535,7 @@ discoverRoutes.get<{ language: string }, GenreSliderItem[]>(
|
||||
const mappedGenres: GenreSliderItem[] = [];
|
||||
|
||||
const genres = await tmdb.getTvGenres({
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
|
@@ -138,7 +138,7 @@ router.get('/genres/movie', isAuthenticated(), async (req, res) => {
|
||||
const tmdb = new TheMovieDb();
|
||||
|
||||
const genres = await tmdb.getMovieGenres({
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
return res.status(200).json(genres);
|
||||
@@ -148,7 +148,7 @@ router.get('/genres/tv', isAuthenticated(), async (req, res) => {
|
||||
const tmdb = new TheMovieDb();
|
||||
|
||||
const genres = await tmdb.getTvGenres({
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
return res.status(200).json(genres);
|
||||
|
@@ -1,11 +1,11 @@
|
||||
import { Router } from 'express';
|
||||
import RottenTomatoes from '../api/rottentomatoes';
|
||||
import TheMovieDb from '../api/themoviedb';
|
||||
import { MediaType } from '../constants/media';
|
||||
import Media from '../entity/Media';
|
||||
import logger from '../logger';
|
||||
import { mapMovieDetails } from '../models/Movie';
|
||||
import { mapMovieResult } from '../models/Search';
|
||||
import Media from '../entity/Media';
|
||||
import RottenTomatoes from '../api/rottentomatoes';
|
||||
import logger from '../logger';
|
||||
import { MediaType } from '../constants/media';
|
||||
|
||||
const movieRoutes = Router();
|
||||
|
||||
@@ -15,7 +15,7 @@ movieRoutes.get('/:id', async (req, res, next) => {
|
||||
try {
|
||||
const tmdbMovie = await tmdb.getMovie({
|
||||
movieId: Number(req.params.id),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
const media = await Media.getMedia(tmdbMovie.id, MediaType.MOVIE);
|
||||
@@ -36,7 +36,7 @@ movieRoutes.get('/:id/recommendations', async (req, res) => {
|
||||
const results = await tmdb.getMovieRecommendations({
|
||||
movieId: Number(req.params.id),
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
const media = await Media.getRelatedMedia(
|
||||
@@ -64,7 +64,7 @@ movieRoutes.get('/:id/similar', async (req, res) => {
|
||||
const results = await tmdb.getMovieSimilar({
|
||||
movieId: Number(req.params.id),
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
const media = await Media.getRelatedMedia(
|
||||
|
@@ -16,7 +16,7 @@ personRoutes.get('/:id', async (req, res, next) => {
|
||||
try {
|
||||
const person = await tmdb.getPerson({
|
||||
personId: Number(req.params.id),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
return res.status(200).json(mapPersonDetails(person));
|
||||
} catch (e) {
|
||||
@@ -30,7 +30,7 @@ personRoutes.get('/:id/combined_credits', async (req, res) => {
|
||||
|
||||
const combinedCredits = await tmdb.getPersonCombinedCredits({
|
||||
personId: Number(req.params.id),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
const castMedia = await Media.getRelatedMedia(
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { Router } from 'express';
|
||||
import TheMovieDb from '../api/themoviedb';
|
||||
import { mapSearchResults } from '../models/Search';
|
||||
import Media from '../entity/Media';
|
||||
import { mapSearchResults } from '../models/Search';
|
||||
|
||||
const searchRoutes = Router();
|
||||
|
||||
@@ -11,7 +11,7 @@ searchRoutes.get('/', async (req, res) => {
|
||||
const results = await tmdb.searchMulti({
|
||||
query: req.query.query as string,
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
const media = await Media.getRelatedMedia(
|
||||
|
@@ -191,7 +191,7 @@ serviceRoutes.get<{ tmdbId: string }>(
|
||||
try {
|
||||
const tv = await tmdb.getTvShow({
|
||||
tvId: Number(req.params.tmdbId),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
const response = await sonarr.getSeriesByTitle(tv.name);
|
||||
|
@@ -7,6 +7,7 @@ import PushoverAgent from '../../lib/notifications/agents/pushover';
|
||||
import SlackAgent from '../../lib/notifications/agents/slack';
|
||||
import TelegramAgent from '../../lib/notifications/agents/telegram';
|
||||
import WebhookAgent from '../../lib/notifications/agents/webhook';
|
||||
import WebPushAgent from '../../lib/notifications/agents/webpush';
|
||||
import { getSettings } from '../../lib/settings';
|
||||
|
||||
const notificationRoutes = Router();
|
||||
@@ -215,6 +216,40 @@ notificationRoutes.post('/email/test', (req, res, next) => {
|
||||
return res.status(204).send();
|
||||
});
|
||||
|
||||
notificationRoutes.get('/webpush', (_req, res) => {
|
||||
const settings = getSettings();
|
||||
|
||||
res.status(200).json(settings.notifications.agents.webpush);
|
||||
});
|
||||
|
||||
notificationRoutes.post('/webpush', (req, res) => {
|
||||
const settings = getSettings();
|
||||
|
||||
settings.notifications.agents.webpush = req.body;
|
||||
settings.save();
|
||||
|
||||
res.status(200).json(settings.notifications.agents.webpush);
|
||||
});
|
||||
|
||||
notificationRoutes.post('/webpush/test', (req, res, next) => {
|
||||
if (!req.user) {
|
||||
return next({
|
||||
status: 500,
|
||||
message: 'User information missing from request',
|
||||
});
|
||||
}
|
||||
|
||||
const webpushAgent = new WebPushAgent(req.body);
|
||||
webpushAgent.send(Notification.TEST_NOTIFICATION, {
|
||||
notifyUser: req.user,
|
||||
subject: 'Test Notification',
|
||||
message:
|
||||
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
||||
});
|
||||
|
||||
return res.status(204).send();
|
||||
});
|
||||
|
||||
notificationRoutes.get('/webhook', (_req, res) => {
|
||||
const settings = getSettings();
|
||||
|
||||
|
@@ -1,11 +1,11 @@
|
||||
import { Router } from 'express';
|
||||
import TheMovieDb from '../api/themoviedb';
|
||||
import { mapTvDetails, mapSeasonWithEpisodes } from '../models/Tv';
|
||||
import { mapTvResult } from '../models/Search';
|
||||
import Media from '../entity/Media';
|
||||
import RottenTomatoes from '../api/rottentomatoes';
|
||||
import logger from '../logger';
|
||||
import TheMovieDb from '../api/themoviedb';
|
||||
import { MediaType } from '../constants/media';
|
||||
import Media from '../entity/Media';
|
||||
import logger from '../logger';
|
||||
import { mapTvResult } from '../models/Search';
|
||||
import { mapSeasonWithEpisodes, mapTvDetails } from '../models/Tv';
|
||||
|
||||
const tvRoutes = Router();
|
||||
|
||||
@@ -14,7 +14,7 @@ tvRoutes.get('/:id', async (req, res, next) => {
|
||||
try {
|
||||
const tv = await tmdb.getTvShow({
|
||||
tvId: Number(req.params.id),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
const media = await Media.getMedia(tv.id, MediaType.TV);
|
||||
@@ -35,7 +35,7 @@ tvRoutes.get('/:id/season/:seasonNumber', async (req, res) => {
|
||||
const season = await tmdb.getTvSeason({
|
||||
tvId: Number(req.params.id),
|
||||
seasonNumber: Number(req.params.seasonNumber),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
return res.status(200).json(mapSeasonWithEpisodes(season));
|
||||
@@ -47,7 +47,7 @@ tvRoutes.get('/:id/recommendations', async (req, res) => {
|
||||
const results = await tmdb.getTvRecommendations({
|
||||
tvId: Number(req.params.id),
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
const media = await Media.getRelatedMedia(
|
||||
@@ -75,7 +75,7 @@ tvRoutes.get('/:id/similar', async (req, res) => {
|
||||
const results = await tmdb.getTvSimilar({
|
||||
tvId: Number(req.params.id),
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
language: req.locale ?? (req.query.language as string),
|
||||
});
|
||||
|
||||
const media = await Media.getRelatedMedia(
|
||||
|
@@ -5,6 +5,7 @@ import PlexTvAPI from '../../api/plextv';
|
||||
import { UserType } from '../../constants/user';
|
||||
import { MediaRequest } from '../../entity/MediaRequest';
|
||||
import { User } from '../../entity/User';
|
||||
import { UserPushSubscription } from '../../entity/UserPushSubscription';
|
||||
import {
|
||||
QuotaResponse,
|
||||
UserRequestsResponse,
|
||||
@@ -127,6 +128,48 @@ router.post(
|
||||
}
|
||||
);
|
||||
|
||||
router.post<
|
||||
never,
|
||||
unknown,
|
||||
{
|
||||
endpoint: string;
|
||||
p256dh: string;
|
||||
auth: string;
|
||||
}
|
||||
>('/registerPushSubscription', async (req, res, next) => {
|
||||
try {
|
||||
const userPushSubRepository = getRepository(UserPushSubscription);
|
||||
|
||||
const existingSubs = await userPushSubRepository.find({
|
||||
where: { auth: req.body.auth },
|
||||
});
|
||||
|
||||
if (existingSubs.length > 0) {
|
||||
logger.debug(
|
||||
'User push subscription already exists. Skipping registration.',
|
||||
{ label: 'API' }
|
||||
);
|
||||
return res.status(204).send();
|
||||
}
|
||||
|
||||
const userPushSubscription = new UserPushSubscription({
|
||||
auth: req.body.auth,
|
||||
endpoint: req.body.endpoint,
|
||||
p256dh: req.body.p256dh,
|
||||
user: req.user,
|
||||
});
|
||||
|
||||
userPushSubRepository.save(userPushSubscription);
|
||||
|
||||
return res.status(204).send();
|
||||
} catch (e) {
|
||||
logger.error('Failed to register user push subscription', {
|
||||
label: 'API',
|
||||
});
|
||||
next({ status: 500, message: 'Failed to register subscription.' });
|
||||
}
|
||||
});
|
||||
|
||||
router.get<{ id: string }>('/:id', async (req, res, next) => {
|
||||
try {
|
||||
const userRepository = getRepository(User);
|
||||
|
@@ -7,7 +7,6 @@ import {
|
||||
UserSettingsGeneralResponse,
|
||||
UserSettingsNotificationsResponse,
|
||||
} from '../../interfaces/api/userSettingsInterfaces';
|
||||
import { NotificationAgentType } from '../../lib/notifications/agenttypes';
|
||||
import { Permission } from '../../lib/permissions';
|
||||
import { getSettings } from '../../lib/settings';
|
||||
import logger from '../../logger';
|
||||
@@ -52,6 +51,7 @@ userSettingsRoutes.get<{ id: string }, UserSettingsGeneralResponse>(
|
||||
|
||||
return res.status(200).json({
|
||||
username: user.username,
|
||||
locale: user.settings?.locale,
|
||||
region: user.settings?.region,
|
||||
originalLanguage: user.settings?.originalLanguage,
|
||||
movieQuotaLimit: user.movieQuotaLimit,
|
||||
@@ -109,17 +109,24 @@ userSettingsRoutes.post<
|
||||
if (!user.settings) {
|
||||
user.settings = new UserSettings({
|
||||
user: req.user,
|
||||
locale: req.body.locale,
|
||||
region: req.body.region,
|
||||
originalLanguage: req.body.originalLanguage,
|
||||
});
|
||||
} else {
|
||||
user.settings.region = req.body.region;
|
||||
(user.settings.locale = req.body.locale),
|
||||
(user.settings.region = req.body.region);
|
||||
user.settings.originalLanguage = req.body.originalLanguage;
|
||||
}
|
||||
|
||||
await userRepository.save(user);
|
||||
|
||||
return res.status(200).json({ username: user.username });
|
||||
return res.status(200).json({
|
||||
username: user.username,
|
||||
region: user.settings.region,
|
||||
locale: user.settings.locale,
|
||||
originalLanguage: user.settings.originalLanguage,
|
||||
});
|
||||
} catch (e) {
|
||||
next({ status: 500, message: e.message });
|
||||
}
|
||||
@@ -243,8 +250,6 @@ userSettingsRoutes.get<{ id: string }, UserSettingsNotificationsResponse>(
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
notificationAgents:
|
||||
user.settings?.notificationAgents ?? NotificationAgentType.EMAIL,
|
||||
emailEnabled: settings?.notifications.agents.email.enabled,
|
||||
pgpKey: user.settings?.pgpKey,
|
||||
discordEnabled: settings?.notifications.agents.discord.enabled,
|
||||
@@ -254,6 +259,8 @@ userSettingsRoutes.get<{ id: string }, UserSettingsNotificationsResponse>(
|
||||
settings?.notifications.agents.telegram.options.botUsername,
|
||||
telegramChatId: user.settings?.telegramChatId,
|
||||
telegramSendSilently: user?.settings?.telegramSendSilently,
|
||||
webPushEnabled: settings?.notifications.agents.webpush.enabled,
|
||||
notificationTypes: user.settings?.notificationTypes ?? {},
|
||||
});
|
||||
} catch (e) {
|
||||
next({ status: 500, message: e.message });
|
||||
@@ -287,30 +294,32 @@ userSettingsRoutes.post<{ id: string }, UserSettingsNotificationsResponse>(
|
||||
if (!user.settings) {
|
||||
user.settings = new UserSettings({
|
||||
user: req.user,
|
||||
notificationAgents:
|
||||
req.body.notificationAgents ?? NotificationAgentType.EMAIL,
|
||||
pgpKey: req.body.pgpKey,
|
||||
discordId: req.body.discordId,
|
||||
telegramChatId: req.body.telegramChatId,
|
||||
telegramSendSilently: req.body.telegramSendSilently,
|
||||
notificationTypes: req.body.notificationTypes,
|
||||
});
|
||||
} else {
|
||||
user.settings.notificationAgents =
|
||||
req.body.notificationAgents ?? NotificationAgentType.EMAIL;
|
||||
user.settings.pgpKey = req.body.pgpKey;
|
||||
user.settings.discordId = req.body.discordId;
|
||||
user.settings.telegramChatId = req.body.telegramChatId;
|
||||
user.settings.telegramSendSilently = req.body.telegramSendSilently;
|
||||
user.settings.notificationTypes = Object.assign(
|
||||
{},
|
||||
user.settings.notificationTypes,
|
||||
req.body.notificationTypes
|
||||
);
|
||||
}
|
||||
|
||||
userRepository.save(user);
|
||||
|
||||
return res.status(200).json({
|
||||
notificationAgents: user.settings?.notificationAgents,
|
||||
pgpKey: user.settings?.pgpKey,
|
||||
discordId: user.settings?.discordId,
|
||||
telegramChatId: user.settings?.telegramChatId,
|
||||
telegramSendSilently: user?.settings?.telegramSendSilently,
|
||||
notificationTypes: user.settings.notificationTypes,
|
||||
});
|
||||
} catch (e) {
|
||||
next({ status: 500, message: e.message });
|
||||
|
Reference in New Issue
Block a user