diff --git a/docs/using-seerr/notifications/webhook.md b/docs/using-seerr/notifications/webhook.md index c359c9262f..263058f9ae 100644 --- a/docs/using-seerr/notifications/webhook.md +++ b/docs/using-seerr/notifications/webhook.md @@ -53,13 +53,13 @@ Customize the JSON payload to suit your needs. Seerr provides several [template These variables are for the target recipient of the notification. -| Variable | Value | -| ---------------------------------------- | ------------------------------------------------------------- | -| `{{notifyuser_username}}` | The target notification recipient's username | -| `{{notifyuser_email}}` | The target notification recipient's email address | -| `{{notifyuser_avatar}}` | The target notification recipient's avatar URL | -| `{{notifyuser_settings_discordId}}` | The target notification recipient's Discord ID (if set) | -| `{{notifyuser_settings_telegramChatId}}` | The target notification recipient's Telegram Chat ID (if set) | +| Variable | Value | +| ---------------------------------------- | -------------------------------------------------------------------------------------------- | +| `{{notifyuser_username}}` | The target notification recipient's username | +| `{{notifyuser_email}}` | The target notification recipient's email address | +| `{{notifyuser_avatar}}` | The target notification recipient's avatar URL | +| `{{notifyuser_settings_discordIds}}` | The target notification recipient's Discord ID(s) as a JSON array (if set) | +| `{{notifyuser_settings_telegramChatId}}` | The target notification recipient's Telegram Chat ID (if set) | :::info The `notifyuser` variables are not defined for the following request notification types, as they are intended for application administrators rather than end users: @@ -113,15 +113,15 @@ The `{{request}}` will be `null` if there is no relevant media object for the no The following special variables are only included in request-related notifications. -| Variable | Value | -| ----------------------------------------- | ----------------------------------------------- | -| `{{request_id}}` | The request ID | -| `{{requestedBy_username}}` | The requesting user's username | -| `{{requestedBy_email}}` | The requesting user's email address | -| `{{requestedBy_avatar}}` | The requesting user's avatar URL | -| `{{requestedBy_jellyfinUserId}}` | The requesting user's Jellyfin User ID | -| `{{requestedBy_settings_discordId}}` | The requesting user's Discord ID (if set) | -| `{{requestedBy_settings_telegramChatId}}` | The requesting user's Telegram Chat ID (if set) | +| Variable | Value | +| ----------------------------------------- | ------------------------------------------------------------------------------ | +| `{{request_id}}` | The request ID | +| `{{requestedBy_username}}` | The requesting user's username | +| `{{requestedBy_email}}` | The requesting user's email address | +| `{{requestedBy_avatar}}` | The requesting user's avatar URL | +| `{{requestedBy_jellyfinUserId}}` | The requesting user's Jellyfin User ID | +| `{{requestedBy_settings_discordIds}}` | The requesting user's Discord ID(s) as a JSON array (if set) | +| `{{requestedBy_settings_telegramChatId}}` | The requesting user's Telegram Chat ID (if set) | #### Issue @@ -129,14 +129,14 @@ The `{{issue}}` will be `null` if there is no relevant media object for the noti The following special variables are only included in issue-related notifications. -| Variable | Value | -| ---------------------------------------- | ----------------------------------------------- | -| `{{issue_id}}` | The issue ID | -| `{{reportedBy_username}}` | The requesting user's username | -| `{{reportedBy_email}}` | The requesting user's email address | -| `{{reportedBy_avatar}}` | The requesting user's avatar URL | -| `{{reportedBy_settings_discordId}}` | The requesting user's Discord ID (if set) | -| `{{reportedBy_settings_telegramChatId}}` | The requesting user's Telegram Chat ID (if set) | +| Variable | Value | +| ---------------------------------------- | ------------------------------------------------------------------------------ | +| `{{issue_id}}` | The issue ID | +| `{{reportedBy_username}}` | The requesting user's username | +| `{{reportedBy_email}}` | The requesting user's email address | +| `{{reportedBy_avatar}}` | The requesting user's avatar URL | +| `{{reportedBy_settings_discordIds}}` | The reporting user's Discord ID(s) as a JSON array (if set) | +| `{{reportedBy_settings_telegramChatId}}` | The requesting user's Telegram Chat ID (if set) | #### Comment @@ -144,11 +144,11 @@ The `{{comment}}` will be `null` if there is no relevant media object for the no The following special variables are only included in issue comment-related notifications. -| Variable | Value | -| ----------------------------------------- | ----------------------------------------------- | -| `{{comment_message}}` | The comment message | -| `{{commentedBy_username}}` | The commenting user's username | -| `{{commentedBy_email}}` | The commenting user's email address | -| `{{commentedBy_avatar}}` | The commenting user's avatar URL | -| `{{commentedBy_settings_discordId}}` | The commenting user's Discord ID (if set) | -| `{{commentedBy_settings_telegramChatId}}` | The commenting user's Telegram Chat ID (if set) | +| Variable | Value | +| ----------------------------------------- | ------------------------------------------------------------------------------ | +| `{{comment_message}}` | The comment message | +| `{{commentedBy_username}}` | The commenting user's username | +| `{{commentedBy_email}}` | The commenting user's email address | +| `{{commentedBy_avatar}}` | The commenting user's avatar URL | +| `{{commentedBy_settings_discordIds}}` | The commenting user's Discord ID(s) as a JSON array (if set) | +| `{{commentedBy_settings_telegramChatId}}` | The commenting user's Telegram Chat ID (if set) | diff --git a/seerr-api.yml b/seerr-api.yml index e517722609..fe952dd7d1 100644 --- a/seerr-api.yml +++ b/seerr-api.yml @@ -148,10 +148,6 @@ components: email: type: string example: 'user@example.com' - discordId: - type: string - nullable: true - example: '123456789' locale: type: string nullable: true @@ -1952,8 +1948,10 @@ components: discordEnabledTypes: type: number nullable: true - discordId: - type: string + discordIds: + type: array + items: + type: string nullable: true pushbulletAccessToken: type: string diff --git a/server/constants/discord.ts b/server/constants/discord.ts new file mode 100644 index 0000000000..c6b7fc1ca1 --- /dev/null +++ b/server/constants/discord.ts @@ -0,0 +1,27 @@ +export const DISCORD_SNOWFLAKE_REGEX = /^\d{17,20}$/; + +export enum EmbedColors { + DEFAULT = 0, + AQUA = 1752220, + GREEN = 3066993, + BLUE = 3447003, + PURPLE = 10181046, + GOLD = 15844367, + ORANGE = 15105570, + RED = 15158332, + GREY = 9807270, + DARKER_GREY = 8359053, + NAVY = 3426654, + DARK_AQUA = 1146986, + DARK_GREEN = 2067276, + DARK_BLUE = 2123412, + DARK_PURPLE = 7419530, + DARK_GOLD = 12745742, + DARK_ORANGE = 11027200, + DARK_RED = 10038562, + DARK_GREY = 9936031, + LIGHT_GREY = 12370112, + DARK_NAVY = 2899536, + LUMINOUS_VIVID_PINK = 16580705, + DARK_VIVID_PINK = 12320855, +} diff --git a/server/entity/UserSettings.ts b/server/entity/UserSettings.ts index 82671fe3b3..d0f2ef1f7e 100644 --- a/server/entity/UserSettings.ts +++ b/server/entity/UserSettings.ts @@ -14,6 +14,19 @@ export const ALL_NOTIFICATIONS = Object.values(Notification) .filter((v) => !isNaN(Number(v))) .reduce((a, v) => a + Number(v), 0); +// convert between DB representation (JSON string) into typescript array +const jsonArrayTransformer = { + from: (v: string | null): string[] => { + try { + return v ? JSON.parse(v) : []; + } catch { + return []; + } + }, + to: (v: string[] | null): string | null => + v?.length ? JSON.stringify(v) : null, +}; + @Entity() export class UserSettings { constructor(init?: Partial) { @@ -42,8 +55,8 @@ export class UserSettings { @Column({ nullable: true }) public pgpKey?: string; - @Column({ nullable: true }) - public discordId?: string; + @Column({ type: 'text', nullable: true, transformer: jsonArrayTransformer }) + public discordIds: string[]; @Column({ nullable: true }) public pushbulletAccessToken?: string; diff --git a/server/interfaces/api/userSettingsInterfaces.ts b/server/interfaces/api/userSettingsInterfaces.ts index 327764618e..57e7b3f614 100644 --- a/server/interfaces/api/userSettingsInterfaces.ts +++ b/server/interfaces/api/userSettingsInterfaces.ts @@ -3,7 +3,6 @@ import type { NotificationAgentKey } from '@server/lib/settings'; export interface UserSettingsGeneralResponse { username?: string; email?: string; - discordId?: string; locale?: string; discoverRegion?: string; streamingRegion?: string; @@ -26,7 +25,7 @@ export interface UserSettingsNotificationsResponse { pgpKey?: string; discordEnabled?: boolean; discordEnabledTypes?: number; - discordId?: string; + discordIds?: string[]; pushbulletAccessToken?: string; pushoverApplicationToken?: string; pushoverUserKey?: string; diff --git a/server/lib/notifications/agents/discord.ts b/server/lib/notifications/agents/discord.ts index d37bc6e58f..e043833c66 100644 --- a/server/lib/notifications/agents/discord.ts +++ b/server/lib/notifications/agents/discord.ts @@ -1,3 +1,7 @@ +import { + DISCORD_SNOWFLAKE_REGEX, + EmbedColors, +} from '@server/constants/discord'; import { IssueStatus, IssueTypeName } from '@server/constants/issue'; import { getRepository } from '@server/datasource'; import { User } from '@server/entity/User'; @@ -16,31 +20,8 @@ import { import type { NotificationAgent, NotificationPayload } from './agent'; import { BaseAgent } from './agent'; -enum EmbedColors { - DEFAULT = 0, - AQUA = 1752220, - GREEN = 3066993, - BLUE = 3447003, - PURPLE = 10181046, - GOLD = 15844367, - ORANGE = 15105570, - RED = 15158332, - GREY = 9807270, - DARKER_GREY = 8359053, - NAVY = 3426654, - DARK_AQUA = 1146986, - DARK_GREEN = 2067276, - DARK_BLUE = 2123412, - DARK_PURPLE = 7419530, - DARK_GOLD = 12745742, - DARK_ORANGE = 11027200, - DARK_RED = 10038562, - DARK_GREY = 9936031, - LIGHT_GREY = 12370112, - DARK_NAVY = 2899536, - LUMINOUS_VIVID_PINK = 16580705, - DARK_VIVID_PINK = 12320855, -} +const isValidSnowflake = (id: string): boolean => + DISCORD_SNOWFLAKE_REGEX.test(id); interface DiscordImageEmbed { url?: string; @@ -278,9 +259,12 @@ class DiscordAgent NotificationAgentKey.DISCORD, type ) && - payload.notifyUser.settings.discordId + payload.notifyUser.settings.discordIds?.length ) { - userMentions.push(`<@${payload.notifyUser.settings.discordId}>`); + const validIds = payload.notifyUser.settings.discordIds.filter( + (id) => isValidSnowflake(id) + ); + userMentions.push(...validIds.map((id) => `<@${id}>`)); } } @@ -296,16 +280,30 @@ class DiscordAgent NotificationAgentKey.DISCORD, type ) && - user.settings.discordId && + user.settings.discordIds?.length && shouldSendAdminNotification(type, user, payload) ) - .map((user) => `<@${user.settings?.discordId}>`) + .flatMap((user) => + user + .settings!.discordIds.filter((id) => isValidSnowflake(id)) + .map((id) => `<@${id}>`) + ) ); } } - if (settings.options.webhookRoleId) { + const allowedUserIds = userMentions.map((mention) => + mention.replace(/[<@>]/g, '') + ); + + const allowedRoleIds: string[] = []; + + if ( + settings.options.webhookRoleId && + isValidSnowflake(settings.options.webhookRoleId) + ) { userMentions.push(`<@&${settings.options.webhookRoleId}>`); + allowedRoleIds.push(settings.options.webhookRoleId); } // Discord webhooks go to a channel, not per-user, @@ -322,6 +320,10 @@ class DiscordAgent avatar_url: settings.options.botAvatarUrl, embeds: [this.buildEmbed(type, payload, locale)], content: userMentions.join(' '), + allowed_mentions: { + users: allowedUserIds, + roles: allowedRoleIds, + }, } as DiscordWebhookPayload); return true; diff --git a/server/lib/notifications/agents/webhook.ts b/server/lib/notifications/agents/webhook.ts index a7a80595b9..3fdde03ab8 100644 --- a/server/lib/notifications/agents/webhook.ts +++ b/server/lib/notifications/agents/webhook.ts @@ -23,7 +23,7 @@ const KeyMap: Record = { notifyuser_username: 'notifyUser.displayName', notifyuser_email: 'notifyUser.email', notifyuser_avatar: 'notifyUser.avatar', - notifyuser_settings_discordId: 'notifyUser.settings.discordId', + notifyuser_settings_discordIds: 'notifyUser.settings.discordIds', notifyuser_settings_telegramChatId: 'notifyUser.settings.telegramChatId', media_imdbid: 'media.imdbId', media_tmdbid: 'media.tmdbId', @@ -42,7 +42,7 @@ const KeyMap: Record = { requestedBy_username: 'request.requestedBy.displayName', requestedBy_email: 'request.requestedBy.email', requestedBy_avatar: 'request.requestedBy.avatar', - requestedBy_settings_discordId: 'request.requestedBy.settings.discordId', + requestedBy_settings_discordIds: 'request.requestedBy.settings.discordIds', requestedBy_settings_telegramChatId: 'request.requestedBy.settings.telegramChatId', issue_id: 'issue.id', @@ -53,13 +53,13 @@ const KeyMap: Record = { reportedBy_username: 'issue.createdBy.displayName', reportedBy_email: 'issue.createdBy.email', reportedBy_avatar: 'issue.createdBy.avatar', - reportedBy_settings_discordId: 'issue.createdBy.settings.discordId', + reportedBy_settings_discordIds: 'issue.createdBy.settings.discordIds', reportedBy_settings_telegramChatId: 'issue.createdBy.settings.telegramChatId', comment_message: 'comment.message', commentedBy_username: 'comment.user.displayName', commentedBy_email: 'comment.user.email', commentedBy_avatar: 'comment.user.avatar', - commentedBy_settings_discordId: 'comment.user.settings.discordId', + commentedBy_settings_discordIds: 'comment.user.settings.discordIds', commentedBy_settings_telegramChatId: 'comment.user.settings.telegramChatId', }; diff --git a/server/migration/postgres/1779783365432-AddDiscordIdsColumn.ts b/server/migration/postgres/1779783365432-AddDiscordIdsColumn.ts new file mode 100644 index 0000000000..98a04bd8a7 --- /dev/null +++ b/server/migration/postgres/1779783365432-AddDiscordIdsColumn.ts @@ -0,0 +1,30 @@ +import type { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddDiscordIdsColumn1779783365432 implements MigrationInterface { + name = 'AddDiscordIdsColumn1779783365432'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_settings" ADD "discordIds" text` + ); + // same for postgres (convert existing single ID into list with one entry) + await queryRunner.query( + `UPDATE "user_settings" SET "discordIds" = '["' || "discordId" || '"]' WHERE "discordId" IS NOT NULL AND "discordId" != ''` + ); + await queryRunner.query( + `ALTER TABLE "user_settings" DROP COLUMN "discordId"` + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_settings" ADD "discordId" character varying` + ); + await queryRunner.query( + `UPDATE "user_settings" SET "discordId" = ("discordIds"::jsonb ->> 0) WHERE "discordIds" IS NOT NULL AND "discordIds" != ''` + ); + await queryRunner.query( + `ALTER TABLE "user_settings" DROP COLUMN "discordIds"` + ); + } +} diff --git a/server/migration/sqlite/1779783365432-AddDiscordIdsColumn.ts b/server/migration/sqlite/1779783365432-AddDiscordIdsColumn.ts new file mode 100644 index 0000000000..36fb1ad59a --- /dev/null +++ b/server/migration/sqlite/1779783365432-AddDiscordIdsColumn.ts @@ -0,0 +1,31 @@ +import type { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddDiscordIdsColumn1779783365432 implements MigrationInterface { + name = 'AddDiscordIdsColumn1779783365432'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TABLE "temporary_user_settings" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "locale" varchar NOT NULL DEFAULT (''), "discoverRegion" varchar, "streamingRegion" varchar, "originalLanguage" varchar, "pgpKey" varchar, "discordIds" text, "pushbulletAccessToken" varchar, "pushoverApplicationToken" varchar, "pushoverUserKey" varchar, "pushoverSound" varchar, "telegramChatId" varchar, "telegramSendSilently" boolean, "watchlistSyncMovies" boolean, "watchlistSyncTv" boolean, "notificationTypes" text, "userId" integer, "telegramMessageThreadId" varchar, CONSTRAINT "REL_986a2b6d3c05eb4091bb8066f7" UNIQUE ("userId"), CONSTRAINT "FK_986a2b6d3c05eb4091bb8066f78" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)` + ); + await queryRunner.query( + `INSERT INTO "temporary_user_settings"("id", "locale", "discoverRegion", "streamingRegion", "originalLanguage", "pgpKey", "discordIds", "pushbulletAccessToken", "pushoverApplicationToken", "pushoverUserKey", "pushoverSound", "telegramChatId", "telegramSendSilently", "watchlistSyncMovies", "watchlistSyncTv", "notificationTypes", "userId", "telegramMessageThreadId") SELECT "id", "locale", "discoverRegion", "streamingRegion", "originalLanguage", "pgpKey", CASE WHEN "discordId" IS NOT NULL AND "discordId" != '' THEN '["' || "discordId" || '"]' ELSE NULL END, "pushbulletAccessToken", "pushoverApplicationToken", "pushoverUserKey", "pushoverSound", "telegramChatId", "telegramSendSilently", "watchlistSyncMovies", "watchlistSyncTv", "notificationTypes", "userId", "telegramMessageThreadId" FROM "user_settings"` + ); + await queryRunner.query(`DROP TABLE "user_settings"`); + await queryRunner.query( + `ALTER TABLE "temporary_user_settings" RENAME TO "user_settings"` + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_settings" RENAME TO "temporary_user_settings"` + ); + await queryRunner.query( + `CREATE TABLE "user_settings" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "locale" varchar NOT NULL DEFAULT (''), "discoverRegion" varchar, "streamingRegion" varchar, "originalLanguage" varchar, "pgpKey" varchar, "discordId" varchar, "pushbulletAccessToken" varchar, "pushoverApplicationToken" varchar, "pushoverUserKey" varchar, "pushoverSound" varchar, "telegramChatId" varchar, "telegramSendSilently" boolean, "watchlistSyncMovies" boolean, "watchlistSyncTv" boolean, "notificationTypes" text, "userId" integer, "telegramMessageThreadId" varchar, CONSTRAINT "REL_986a2b6d3c05eb4091bb8066f7" UNIQUE ("userId"), CONSTRAINT "FK_986a2b6d3c05eb4091bb8066f78" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)` + ); + await queryRunner.query( + `INSERT INTO "user_settings"("id", "locale", "discoverRegion", "streamingRegion", "originalLanguage", "pgpKey", "discordId", "pushbulletAccessToken", "pushoverApplicationToken", "pushoverUserKey", "pushoverSound", "telegramChatId", "telegramSendSilently", "watchlistSyncMovies", "watchlistSyncTv", "notificationTypes", "userId", "telegramMessageThreadId") SELECT "id", "locale", "discoverRegion", "streamingRegion", "originalLanguage", "pgpKey", json_extract("discordIds", '$[0]'), "pushbulletAccessToken", "pushoverApplicationToken", "pushoverUserKey", "pushoverSound", "telegramChatId", "telegramSendSilently", "watchlistSyncMovies", "watchlistSyncTv", "notificationTypes", "userId", "telegramMessageThreadId" FROM "temporary_user_settings"` + ); + await queryRunner.query(`DROP TABLE "temporary_user_settings"`); + } +} diff --git a/server/routes/user/usersettings.ts b/server/routes/user/usersettings.ts index 784f7b5fd8..b54254a4fc 100644 --- a/server/routes/user/usersettings.ts +++ b/server/routes/user/usersettings.ts @@ -48,7 +48,6 @@ userSettingsRoutes.get<{ id: string }, UserSettingsGeneralResponse>( return res.status(200).json({ username: user.username, email: user.email, - discordId: user.settings?.discordId, locale: user.settings?.locale, discoverRegion: user.settings?.discoverRegion, streamingRegion: user.settings?.streamingRegion, @@ -122,7 +121,6 @@ userSettingsRoutes.post< if (!user.settings) { user.settings = new UserSettings({ user: req.user, - discordId: req.body.discordId, locale: req.body.locale, discoverRegion: req.body.discoverRegion, streamingRegion: req.body.streamingRegion, @@ -131,7 +129,6 @@ userSettingsRoutes.post< watchlistSyncTv: req.body.watchlistSyncTv, }); } else { - user.settings.discordId = req.body.discordId; user.settings.locale = req.body.locale; user.settings.discoverRegion = req.body.discoverRegion; user.settings.streamingRegion = req.body.streamingRegion; @@ -144,7 +141,6 @@ userSettingsRoutes.post< return res.status(200).json({ username: savedUser.username, - discordId: savedUser.settings?.discordId, locale: savedUser.settings?.locale, discoverRegion: savedUser.settings?.discoverRegion, streamingRegion: savedUser.settings?.streamingRegion, @@ -543,7 +539,7 @@ userSettingsRoutes.get<{ id: string }, UserSettingsNotificationsResponse>( settings?.discord.enabled && settings.discord.options.enableMentions ? settings.discord.types : 0, - discordId: user.settings?.discordId, + discordIds: user.settings?.discordIds ?? [], pushbulletAccessToken: user.settings?.pushbulletAccessToken, pushoverApplicationToken: user.settings?.pushoverApplicationToken, pushoverUserKey: user.settings?.pushoverUserKey, @@ -585,11 +581,14 @@ userSettingsRoutes.post<{ id: string }, UserSettingsNotificationsResponse>( }); } + const discordIds = + req.body.discordIds?.filter((id: string) => id !== '') ?? []; + if (!user.settings) { user.settings = new UserSettings({ user: req.user, pgpKey: req.body.pgpKey, - discordId: req.body.discordId, + discordIds, pushbulletAccessToken: req.body.pushbulletAccessToken, pushoverApplicationToken: req.body.pushoverApplicationToken, pushoverUserKey: req.body.pushoverUserKey, @@ -600,7 +599,7 @@ userSettingsRoutes.post<{ id: string }, UserSettingsNotificationsResponse>( }); } else { user.settings.pgpKey = req.body.pgpKey; - user.settings.discordId = req.body.discordId; + user.settings.discordIds = discordIds; user.settings.pushbulletAccessToken = req.body.pushbulletAccessToken; user.settings.pushoverApplicationToken = req.body.pushoverApplicationToken; @@ -621,7 +620,7 @@ userSettingsRoutes.post<{ id: string }, UserSettingsNotificationsResponse>( return res.status(200).json({ pgpKey: user.settings.pgpKey, - discordId: user.settings.discordId, + discordIds: user.settings.discordIds ?? [], pushbulletAccessToken: user.settings.pushbulletAccessToken, pushoverApplicationToken: user.settings.pushoverApplicationToken, pushoverUserKey: user.settings.pushoverUserKey, diff --git a/src/components/Settings/Notifications/NotificationsWebhook/index.tsx b/src/components/Settings/Notifications/NotificationsWebhook/index.tsx index 0ff8629ef9..d69a6c9c4f 100644 --- a/src/components/Settings/Notifications/NotificationsWebhook/index.tsx +++ b/src/components/Settings/Notifications/NotificationsWebhook/index.tsx @@ -50,7 +50,7 @@ const defaultPayload = { requestedBy_username: '{{requestedBy_username}}', requestedBy_avatar: '{{requestedBy_avatar}}', requestedBy_jellyfinUserId: '{{requestedBy_jellyfinUserId}}', - requestedBy_settings_discordId: '{{requestedBy_settings_discordId}}', + requestedBy_settings_discordIds: '{{requestedBy_settings_discordIds}}', requestedBy_settings_telegramChatId: '{{requestedBy_settings_telegramChatId}}', }, @@ -61,7 +61,7 @@ const defaultPayload = { reportedBy_email: '{{reportedBy_email}}', reportedBy_username: '{{reportedBy_username}}', reportedBy_avatar: '{{reportedBy_avatar}}', - reportedBy_settings_discordId: '{{reportedBy_settings_discordId}}', + reportedBy_settings_discordIds: '{{reportedBy_settings_discordIds}}', reportedBy_settings_telegramChatId: '{{reportedBy_settings_telegramChatId}}', }, @@ -70,7 +70,7 @@ const defaultPayload = { commentedBy_email: '{{commentedBy_email}}', commentedBy_username: '{{commentedBy_username}}', commentedBy_avatar: '{{commentedBy_avatar}}', - commentedBy_settings_discordId: '{{commentedBy_settings_discordId}}', + commentedBy_settings_discordIds: '{{commentedBy_settings_discordIds}}', commentedBy_settings_telegramChatId: '{{commentedBy_settings_telegramChatId}}', }, diff --git a/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx b/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx index 525dabb07d..c0e9100869 100644 --- a/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx +++ b/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx @@ -61,12 +61,8 @@ const messages = defineMessages( enableOverride: 'Override Global Limit', applanguage: 'Display Language', languageDefault: 'Default ({language})', - discordId: 'Discord User ID', - discordIdTip: - 'The multi-digit ID number associated with your Discord user account', validationemailrequired: 'Email required', validationemailformat: 'Valid email required', - validationDiscordId: 'You must provide a valid Discord user ID', plexwatchlistsyncmovies: 'Auto-Request Movies', plexwatchlistsyncmoviestip: 'Automatically request movies on your Plex Watchlist', @@ -119,9 +115,6 @@ const UserGeneralSettings = () => { (value) => !value || validator.isEmail(value, { require_tld: false }) ), - discordId: Yup.string() - .nullable() - .matches(/^\d{17,19}$/, intl.formatMessage(messages.validationDiscordId)), }); useEffect(() => { @@ -158,7 +151,6 @@ const UserGeneralSettings = () => { initialValues={{ displayName: data?.username !== user?.email ? data?.username : '', email: data?.email?.includes('@') ? data.email : '', - discordId: data?.discordId ?? '', locale: data?.locale, discoverRegion: data?.discoverRegion, streamingRegion: data?.streamingRegion, @@ -178,7 +170,6 @@ const UserGeneralSettings = () => { username: values.displayName, email: values.email || user?.jellyfinUsername || user?.plexUsername, - discordId: values.discordId, locale: values.locale, discoverRegion: values.discoverRegion, streamingRegion: values.streamingRegion, @@ -341,36 +332,6 @@ const UserGeneralSettings = () => { )} -
- -
-
- -
- {errors.discordId && - touched.discordId && - typeof errors.discordId === 'string' && ( -
{errors.discordId}
- )} -
-