@notidotbot/noti-api-client 1.9.73 → 1.9.74

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +8 -1
  3. package/dist/other/bitfields.d.ts +7 -4
  4. package/dist/other/bitfields.js +3 -0
  5. package/dist/other/features.d.ts +1 -1
  6. package/dist/other/features.js +1 -0
  7. package/dist/other/multiDestination.d.ts +89 -0
  8. package/dist/other/multiDestination.js +109 -0
  9. package/dist/other/zod/clubStreamer.zod.d.ts +7 -0
  10. package/dist/other/zod/clubStreamer.zod.js +3 -0
  11. package/dist/other/zod/kickStreamer.zod.d.ts +17 -0
  12. package/dist/other/zod/kickStreamer.zod.js +4 -0
  13. package/dist/other/zod/rumbleStreamer.zod.d.ts +18 -0
  14. package/dist/other/zod/rumbleStreamer.zod.js +4 -0
  15. package/dist/other/zod/tiktokStreamer.zod.d.ts +18 -0
  16. package/dist/other/zod/tiktokStreamer.zod.js +4 -0
  17. package/dist/other/zod/twitchStreamer.zod.d.ts +17 -0
  18. package/dist/other/zod/twitchStreamer.zod.js +4 -0
  19. package/dist/other/zod/twitterStreamer.zod.d.ts +18 -0
  20. package/dist/other/zod/twitterStreamer.zod.js +4 -0
  21. package/dist/other/zod/youtubeStreamer.zod.d.ts +19 -0
  22. package/dist/other/zod/youtubeStreamer.zod.js +4 -0
  23. package/dist/other/zod/zod.d.ts +15 -0
  24. package/dist/other/zod/zod.js +12 -0
  25. package/dist/tsconfig.tsbuildinfo +1 -1
  26. package/package.json +1 -1
  27. package/prisma/schema/models/clubStreamer.prisma +4 -0
  28. package/prisma/schema/models/kickStreamer.prisma +6 -0
  29. package/prisma/schema/models/rumbleStreamer.prisma +7 -0
  30. package/prisma/schema/models/tiktokStreamer.prisma +6 -0
  31. package/prisma/schema/models/twitchStreamer.prisma +7 -0
  32. package/prisma/schema/models/twitterStreamer.prisma +7 -0
  33. package/prisma/schema/models/youtubeStreamer.prisma +6 -0
package/dist/index.d.ts CHANGED
@@ -47,6 +47,8 @@ export { GuildMessageTypeEnum, StreamerMessageTypeEnum, PlatformEnum, $Enums } f
47
47
  export { FEATURE_NAMES, } from './other/features';
48
48
  export { OFFLINE_GRACE_CHOICES, OFFLINE_GRACE_DEFAULT, OFFLINE_GRACE_PLATFORMS, } from './other/offlineGrace';
49
49
  export type { OfflineGraceMinutes, OfflineGracePlatform } from './other/offlineGrace';
50
+ export { DESTINATION_TYPES, MAX_EXTRA_DESTINATIONS, normalizeExtraDestinations, extrasFor, readExtraPosts, hasLivePost, } from './other/multiDestination';
51
+ export type { DestinationPlatform, DestinationType, ExtraDestination, ExtraPost } from './other/multiDestination';
50
52
  export { GIVEAWAY_CLAIM_WINDOWS, GIVEAWAY_CLAIM_WINDOW_LABELS, GIVEAWAY_MAX_CLAIM_ROUNDS, GIVEAWAY_WINNER_ROLE_MAX_DAYS, GIVEAWAY_MIN_ACCOUNT_AGE_MAX_DAYS, GIVEAWAY_WINNER_ROLE_FORBIDDEN_PERMISSIONS, } from './other/giveawayClaims';
51
53
  export type { GiveawayClaimWindow, GiveawayWinnerStatus } from './other/giveawayClaims';
52
54
  export type { FeatureName, FeatureStatus, ResolvedFeature, } from './other/features';
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.GIVEAWAY_WINNER_ROLE_FORBIDDEN_PERMISSIONS = exports.GIVEAWAY_MIN_ACCOUNT_AGE_MAX_DAYS = exports.GIVEAWAY_WINNER_ROLE_MAX_DAYS = exports.GIVEAWAY_MAX_CLAIM_ROUNDS = exports.GIVEAWAY_CLAIM_WINDOW_LABELS = exports.GIVEAWAY_CLAIM_WINDOWS = exports.OFFLINE_GRACE_PLATFORMS = exports.OFFLINE_GRACE_DEFAULT = exports.OFFLINE_GRACE_CHOICES = exports.FEATURE_NAMES = exports.$Enums = exports.PlatformEnum = exports.StreamerMessageTypeEnum = exports.GuildMessageTypeEnum = void 0;
17
+ exports.GIVEAWAY_WINNER_ROLE_FORBIDDEN_PERMISSIONS = exports.GIVEAWAY_MIN_ACCOUNT_AGE_MAX_DAYS = exports.GIVEAWAY_WINNER_ROLE_MAX_DAYS = exports.GIVEAWAY_MAX_CLAIM_ROUNDS = exports.GIVEAWAY_CLAIM_WINDOW_LABELS = exports.GIVEAWAY_CLAIM_WINDOWS = exports.hasLivePost = exports.readExtraPosts = exports.extrasFor = exports.normalizeExtraDestinations = exports.MAX_EXTRA_DESTINATIONS = exports.DESTINATION_TYPES = exports.OFFLINE_GRACE_PLATFORMS = exports.OFFLINE_GRACE_DEFAULT = exports.OFFLINE_GRACE_CHOICES = exports.FEATURE_NAMES = exports.$Enums = exports.PlatformEnum = exports.StreamerMessageTypeEnum = exports.GuildMessageTypeEnum = void 0;
18
18
  __exportStar(require("./core/manager"), exports);
19
19
  __exportStar(require("./types"), exports);
20
20
  __exportStar(require("./classes/@me"), exports);
@@ -73,6 +73,13 @@ var offlineGrace_1 = require("./other/offlineGrace");
73
73
  Object.defineProperty(exports, "OFFLINE_GRACE_CHOICES", { enumerable: true, get: function () { return offlineGrace_1.OFFLINE_GRACE_CHOICES; } });
74
74
  Object.defineProperty(exports, "OFFLINE_GRACE_DEFAULT", { enumerable: true, get: function () { return offlineGrace_1.OFFLINE_GRACE_DEFAULT; } });
75
75
  Object.defineProperty(exports, "OFFLINE_GRACE_PLATFORMS", { enumerable: true, get: function () { return offlineGrace_1.OFFLINE_GRACE_PLATFORMS; } });
76
+ var multiDestination_1 = require("./other/multiDestination");
77
+ Object.defineProperty(exports, "DESTINATION_TYPES", { enumerable: true, get: function () { return multiDestination_1.DESTINATION_TYPES; } });
78
+ Object.defineProperty(exports, "MAX_EXTRA_DESTINATIONS", { enumerable: true, get: function () { return multiDestination_1.MAX_EXTRA_DESTINATIONS; } });
79
+ Object.defineProperty(exports, "normalizeExtraDestinations", { enumerable: true, get: function () { return multiDestination_1.normalizeExtraDestinations; } });
80
+ Object.defineProperty(exports, "extrasFor", { enumerable: true, get: function () { return multiDestination_1.extrasFor; } });
81
+ Object.defineProperty(exports, "readExtraPosts", { enumerable: true, get: function () { return multiDestination_1.readExtraPosts; } });
82
+ Object.defineProperty(exports, "hasLivePost", { enumerable: true, get: function () { return multiDestination_1.hasLivePost; } });
76
83
  var giveawayClaims_1 = require("./other/giveawayClaims");
77
84
  Object.defineProperty(exports, "GIVEAWAY_CLAIM_WINDOWS", { enumerable: true, get: function () { return giveawayClaims_1.GIVEAWAY_CLAIM_WINDOWS; } });
78
85
  Object.defineProperty(exports, "GIVEAWAY_CLAIM_WINDOW_LABELS", { enumerable: true, get: function () { return giveawayClaims_1.GIVEAWAY_CLAIM_WINDOW_LABELS; } });
@@ -129,6 +129,7 @@ export declare const GuildFeatures: {
129
129
  StatusRoleKeepOnOffline: bigint;
130
130
  YouTubeReplayChannel: bigint;
131
131
  LivePostUpdates: bigint;
132
+ MultiDestination: bigint;
132
133
  };
133
134
  export declare const GuildFeaturesText: Record<keyof typeof GuildFeatures, string>;
134
135
  export declare const UserFeatures: {
@@ -245,8 +246,9 @@ export declare class GuildFeaturesManager extends BitFieldManager<typeof GuildFe
245
246
  StatusRoleKeepOnOffline: bigint;
246
247
  YouTubeReplayChannel: bigint;
247
248
  LivePostUpdates: bigint;
249
+ MultiDestination: bigint;
248
250
  };
249
- t: Record<"StickyMessages" | "LinkedRoles" | "StatusRoles" | "Starboards" | "KickClips" | "StatCounters" | "BaseSyncableRoles" | "FullSyncableRoles" | "LiveRole" | "VoteSkipping" | "KickAuditLogs" | "LeaderboardCommand" | "RefreshingLeaderboard" | "LeaderBoardSyncRoles" | "BetaAccess" | "PriorityNotifications" | "KickNotifications" | "TwitchNotifications" | "ImportEmojis" | "ImportEmojisWithSub" | "CustomWebhooks" | "AnyMessageEditor" | "SyncSocialUsernames" | "AutoDeleteNotifications" | "TestNotificationCommand" | "CustomCooldowns" | "WelcomeAndLeaveNotifications" | "NotificationPingRoleId" | "SwitchStreamerAndGuildEmbeds" | "BirthdayNotifications" | "AllowNotSendingOfflineNotifications" | "AutoStatusLiveRoles" | "RumbleNotifications" | "AllowAutoPublishNotifications" | "NotificationOverrides" | "UseCustomButtons" | "AllowVodFeatures" | "TikTokNotifications" | "ManageBranding" | "CustomStarboards" | "AutoThreadOnStarboard" | "StarboardRewardRole" | "Giveaways" | "GiveawayLogs" | "ModifyGiveawayWhileRunning" | "ScheduleGiveaways" | "GiveawayRequirements" | "GiveawayBonusEntries" | "GiveawayEntryLimit" | "DisableDoubleVoteEntry" | "YouTubeNotifications" | "RandomMessages" | "WeeklyBirthdayPanel" | "GameNotifications" | "GameCategoryRouting" | "GameAllTimeLowAlerts" | "GameChangelogs" | "GameRobloxTracking" | "FixUrlWebhook" | "FixUrlCustomRules" | "KickClipperSubscribe" | "WhatnotNotifications" | "ScheduledEventMessages" | "ScheduledMessageWebhooks" | "ReactionRoles" | "AdvancedRolePanels" | "KickClipForwarding" | "TwitchClipForwarding" | "ClubNotifications" | "RolePanelWebhooks" | "Fishing" | "FishingCustomization" | "FishingWebhooks" | "StreamRoles" | "RoleFilters" | "TwitterNotifications" | "TwitterLiveNotifications" | "BadgeAllGames" | "AutoRoles" | "AutoRoleTimers" | "AutoRoleInvites" | "StickyMessageRoleFilters" | "GiveawayClaims" | "GiveawayWinnerRole" | "InfluencerPanel" | "InfluencerPanelPremium" | "InfluencerPanelPlus" | "StatusRoleKeepOnOffline" | "YouTubeReplayChannel" | "LivePostUpdates", string>;
251
+ t: Record<"BaseSyncableRoles" | "FullSyncableRoles" | "LiveRole" | "StatCounters" | "VoteSkipping" | "KickAuditLogs" | "LeaderboardCommand" | "RefreshingLeaderboard" | "LeaderBoardSyncRoles" | "BetaAccess" | "PriorityNotifications" | "KickClips" | "KickNotifications" | "TwitchNotifications" | "ImportEmojis" | "ImportEmojisWithSub" | "CustomWebhooks" | "AnyMessageEditor" | "SyncSocialUsernames" | "AutoDeleteNotifications" | "TestNotificationCommand" | "CustomCooldowns" | "WelcomeAndLeaveNotifications" | "NotificationPingRoleId" | "SwitchStreamerAndGuildEmbeds" | "BirthdayNotifications" | "AllowNotSendingOfflineNotifications" | "AutoStatusLiveRoles" | "RumbleNotifications" | "AllowAutoPublishNotifications" | "NotificationOverrides" | "UseCustomButtons" | "AllowVodFeatures" | "TikTokNotifications" | "StatusRoles" | "ManageBranding" | "StickyMessages" | "Starboards" | "CustomStarboards" | "AutoThreadOnStarboard" | "StarboardRewardRole" | "Giveaways" | "GiveawayLogs" | "ModifyGiveawayWhileRunning" | "ScheduleGiveaways" | "GiveawayRequirements" | "GiveawayBonusEntries" | "GiveawayEntryLimit" | "DisableDoubleVoteEntry" | "YouTubeNotifications" | "LinkedRoles" | "RandomMessages" | "WeeklyBirthdayPanel" | "GameNotifications" | "GameCategoryRouting" | "GameAllTimeLowAlerts" | "GameChangelogs" | "GameRobloxTracking" | "FixUrlWebhook" | "FixUrlCustomRules" | "KickClipperSubscribe" | "WhatnotNotifications" | "ScheduledEventMessages" | "ScheduledMessageWebhooks" | "ReactionRoles" | "AdvancedRolePanels" | "KickClipForwarding" | "TwitchClipForwarding" | "ClubNotifications" | "RolePanelWebhooks" | "Fishing" | "FishingCustomization" | "FishingWebhooks" | "StreamRoles" | "RoleFilters" | "TwitterNotifications" | "TwitterLiveNotifications" | "BadgeAllGames" | "AutoRoles" | "AutoRoleTimers" | "AutoRoleInvites" | "StickyMessageRoleFilters" | "GiveawayClaims" | "GiveawayWinnerRole" | "InfluencerPanel" | "InfluencerPanelPremium" | "InfluencerPanelPlus" | "StatusRoleKeepOnOffline" | "YouTubeReplayChannel" | "LivePostUpdates" | "MultiDestination", string>;
250
252
  all: bigint;
251
253
  static b: {
252
254
  BaseSyncableRoles: bigint;
@@ -339,8 +341,9 @@ export declare class GuildFeaturesManager extends BitFieldManager<typeof GuildFe
339
341
  StatusRoleKeepOnOffline: bigint;
340
342
  YouTubeReplayChannel: bigint;
341
343
  LivePostUpdates: bigint;
344
+ MultiDestination: bigint;
342
345
  };
343
- static t: Record<"StickyMessages" | "LinkedRoles" | "StatusRoles" | "Starboards" | "KickClips" | "StatCounters" | "BaseSyncableRoles" | "FullSyncableRoles" | "LiveRole" | "VoteSkipping" | "KickAuditLogs" | "LeaderboardCommand" | "RefreshingLeaderboard" | "LeaderBoardSyncRoles" | "BetaAccess" | "PriorityNotifications" | "KickNotifications" | "TwitchNotifications" | "ImportEmojis" | "ImportEmojisWithSub" | "CustomWebhooks" | "AnyMessageEditor" | "SyncSocialUsernames" | "AutoDeleteNotifications" | "TestNotificationCommand" | "CustomCooldowns" | "WelcomeAndLeaveNotifications" | "NotificationPingRoleId" | "SwitchStreamerAndGuildEmbeds" | "BirthdayNotifications" | "AllowNotSendingOfflineNotifications" | "AutoStatusLiveRoles" | "RumbleNotifications" | "AllowAutoPublishNotifications" | "NotificationOverrides" | "UseCustomButtons" | "AllowVodFeatures" | "TikTokNotifications" | "ManageBranding" | "CustomStarboards" | "AutoThreadOnStarboard" | "StarboardRewardRole" | "Giveaways" | "GiveawayLogs" | "ModifyGiveawayWhileRunning" | "ScheduleGiveaways" | "GiveawayRequirements" | "GiveawayBonusEntries" | "GiveawayEntryLimit" | "DisableDoubleVoteEntry" | "YouTubeNotifications" | "RandomMessages" | "WeeklyBirthdayPanel" | "GameNotifications" | "GameCategoryRouting" | "GameAllTimeLowAlerts" | "GameChangelogs" | "GameRobloxTracking" | "FixUrlWebhook" | "FixUrlCustomRules" | "KickClipperSubscribe" | "WhatnotNotifications" | "ScheduledEventMessages" | "ScheduledMessageWebhooks" | "ReactionRoles" | "AdvancedRolePanels" | "KickClipForwarding" | "TwitchClipForwarding" | "ClubNotifications" | "RolePanelWebhooks" | "Fishing" | "FishingCustomization" | "FishingWebhooks" | "StreamRoles" | "RoleFilters" | "TwitterNotifications" | "TwitterLiveNotifications" | "BadgeAllGames" | "AutoRoles" | "AutoRoleTimers" | "AutoRoleInvites" | "StickyMessageRoleFilters" | "GiveawayClaims" | "GiveawayWinnerRole" | "InfluencerPanel" | "InfluencerPanelPremium" | "InfluencerPanelPlus" | "StatusRoleKeepOnOffline" | "YouTubeReplayChannel" | "LivePostUpdates", string>;
346
+ static t: Record<"BaseSyncableRoles" | "FullSyncableRoles" | "LiveRole" | "StatCounters" | "VoteSkipping" | "KickAuditLogs" | "LeaderboardCommand" | "RefreshingLeaderboard" | "LeaderBoardSyncRoles" | "BetaAccess" | "PriorityNotifications" | "KickClips" | "KickNotifications" | "TwitchNotifications" | "ImportEmojis" | "ImportEmojisWithSub" | "CustomWebhooks" | "AnyMessageEditor" | "SyncSocialUsernames" | "AutoDeleteNotifications" | "TestNotificationCommand" | "CustomCooldowns" | "WelcomeAndLeaveNotifications" | "NotificationPingRoleId" | "SwitchStreamerAndGuildEmbeds" | "BirthdayNotifications" | "AllowNotSendingOfflineNotifications" | "AutoStatusLiveRoles" | "RumbleNotifications" | "AllowAutoPublishNotifications" | "NotificationOverrides" | "UseCustomButtons" | "AllowVodFeatures" | "TikTokNotifications" | "StatusRoles" | "ManageBranding" | "StickyMessages" | "Starboards" | "CustomStarboards" | "AutoThreadOnStarboard" | "StarboardRewardRole" | "Giveaways" | "GiveawayLogs" | "ModifyGiveawayWhileRunning" | "ScheduleGiveaways" | "GiveawayRequirements" | "GiveawayBonusEntries" | "GiveawayEntryLimit" | "DisableDoubleVoteEntry" | "YouTubeNotifications" | "LinkedRoles" | "RandomMessages" | "WeeklyBirthdayPanel" | "GameNotifications" | "GameCategoryRouting" | "GameAllTimeLowAlerts" | "GameChangelogs" | "GameRobloxTracking" | "FixUrlWebhook" | "FixUrlCustomRules" | "KickClipperSubscribe" | "WhatnotNotifications" | "ScheduledEventMessages" | "ScheduledMessageWebhooks" | "ReactionRoles" | "AdvancedRolePanels" | "KickClipForwarding" | "TwitchClipForwarding" | "ClubNotifications" | "RolePanelWebhooks" | "Fishing" | "FishingCustomization" | "FishingWebhooks" | "StreamRoles" | "RoleFilters" | "TwitterNotifications" | "TwitterLiveNotifications" | "BadgeAllGames" | "AutoRoles" | "AutoRoleTimers" | "AutoRoleInvites" | "StickyMessageRoleFilters" | "GiveawayClaims" | "GiveawayWinnerRole" | "InfluencerPanel" | "InfluencerPanelPremium" | "InfluencerPanelPlus" | "StatusRoleKeepOnOffline" | "YouTubeReplayChannel" | "LivePostUpdates" | "MultiDestination", string>;
344
347
  static all: bigint;
345
348
  convertBitToField<T extends EnumValues<typeof GuildFeatures>>(bit: T): string | null;
346
349
  }
@@ -376,7 +379,7 @@ export declare class UserFlagsManager extends BitFieldManager<typeof UserFlags,
376
379
  Beta: bigint;
377
380
  Owner: bigint;
378
381
  };
379
- t: Record<"Premium" | "Partner" | "Staff" | "Developer" | "Beta" | "Owner", string>;
382
+ t: Record<"Partner" | "Premium" | "Staff" | "Developer" | "Beta" | "Owner", string>;
380
383
  all: bigint;
381
384
  static b: {
382
385
  Partner: bigint;
@@ -386,7 +389,7 @@ export declare class UserFlagsManager extends BitFieldManager<typeof UserFlags,
386
389
  Beta: bigint;
387
390
  Owner: bigint;
388
391
  };
389
- static t: Record<"Premium" | "Partner" | "Staff" | "Developer" | "Beta" | "Owner", string>;
392
+ static t: Record<"Partner" | "Premium" | "Staff" | "Developer" | "Beta" | "Owner", string>;
390
393
  static all: bigint;
391
394
  convertBitToField<T extends EnumValues<typeof UserFlags>>(bit: T): string | null;
392
395
  }
@@ -235,6 +235,8 @@ exports.GuildFeatures = {
235
235
  YouTubeReplayChannel: 1n << 89n,
236
236
  // Live post updates: edit the live post when the streamer changes their title or category. Premium Plus.
237
237
  LivePostUpdates: 1n << 90n,
238
+ // Multiple notification channels: up to 2 extra channels per creator, each with its own ping role. Premium Plus.
239
+ MultiDestination: 1n << 91n,
238
240
  };
239
241
  exports.GuildFeaturesText = {
240
242
  BaseSyncableRoles: 'Basic Syncable Roles',
@@ -329,6 +331,7 @@ exports.GuildFeaturesText = {
329
331
  StatusRoleKeepOnOffline: 'Status Roles: Remove When Offline',
330
332
  YouTubeReplayChannel: 'YouTube: Replay Channel',
331
333
  LivePostUpdates: 'Live Post Updates',
334
+ MultiDestination: 'Multiple Notification Channels',
332
335
  };
333
336
  exports.UserFeatures = {
334
337
  HasOneServerPremium: 1n << 0n,
@@ -1,4 +1,4 @@
1
- export declare const FEATURE_NAMES: readonly ["freeGames", "gameChangelogs", "robloxNotifications", "fixLinks", "clipperNotifications", "scheduledMessages", "linkedRoles", "reactionRoles", "clipForwarding", "club", "whatnot", "fishing", "giveaways", "starboards", "syncedRoles", "birthdays", "statusRoles", "autoStatusLiveRoles", "streamRoles", "badgeNotifications", "kickBounties", "autoRoles", "giveawayClaims", "influencerPanel", "publicGiveaways", "publicDrops", "sitePolls", "siteAnnouncements", "offlineGracePeriod", "youtubeReplays", "livePostUpdates", "twitter", "voteToTest", "voteToAddSocial", "aiAssistant", "voteToUseAssistant", "assistantShareChat", "emotes", "liveRoles", "stickyMessages", "welcomeLeave", "statCounters", "voteSkipping"];
1
+ export declare const FEATURE_NAMES: readonly ["freeGames", "gameChangelogs", "robloxNotifications", "fixLinks", "clipperNotifications", "scheduledMessages", "linkedRoles", "reactionRoles", "clipForwarding", "club", "whatnot", "fishing", "giveaways", "starboards", "syncedRoles", "birthdays", "statusRoles", "autoStatusLiveRoles", "streamRoles", "badgeNotifications", "kickBounties", "autoRoles", "giveawayClaims", "influencerPanel", "publicGiveaways", "publicDrops", "sitePolls", "siteAnnouncements", "offlineGracePeriod", "youtubeReplays", "livePostUpdates", "multiDestination", "twitter", "voteToTest", "voteToAddSocial", "aiAssistant", "voteToUseAssistant", "assistantShareChat", "emotes", "liveRoles", "stickyMessages", "welcomeLeave", "statCounters", "voteSkipping"];
2
2
  export type FeatureName = (typeof FEATURE_NAMES)[number];
3
3
  export type FeatureStatus = 'off' | 'beta' | 'public';
4
4
  export type ResolvedFeature = 'public' | 'beta' | 'hidden';
@@ -36,6 +36,7 @@ exports.FEATURE_NAMES = [
36
36
  'offlineGracePeriod',
37
37
  'youtubeReplays',
38
38
  'livePostUpdates',
39
+ 'multiDestination',
39
40
  'twitter',
40
41
  'voteToTest',
41
42
  'voteToAddSocial',
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Multi-destination notifications - up to two extra channels per creator, each with its own ping role.
3
+ * Premium Plus (`MultiDestination`), launch flag `multiDestination`. Plan: phases/multi-destination/.
4
+ *
5
+ * Mirrors `src/modules/multiDestination.ts` in Noti-v3. Hand-copied; the server's `sdkDrift` test diffs everything
6
+ * below this header against it.
7
+ *
8
+ * One source of truth for the rules, because they have to agree across the zod schemas, the save
9
+ * transforms, the send path and the SDK. Deliberately has NO imports, for the same reason as
10
+ * `offlineGrace.ts`: the zod schemas pull from here, and a cycle through them is someone's afternoon.
11
+ *
12
+ * The creator's own channel + `pingRoleId` is destination 1 and is not stored here. `extraDestinations`
13
+ * holds only the extras, so a server that never opts in has nothing new anywhere.
14
+ */
15
+ /** Extra destinations a creator may have, on top of their own channel. 3 channels total. */
16
+ export declare const MAX_EXTRA_DESTINATIONS = 2;
17
+ /**
18
+ * Which post types an extra destination can be limited to, per platform. Empty `types` = everything.
19
+ *
20
+ * Offline is NOT a type: the offline path only ever edits or deletes the live post it announced, so a
21
+ * copy's offline follows its own live copy. Kick clips/VODs and the X post cooldown are separate
22
+ * features with their own channels, not notification types, so they are not here either.
23
+ */
24
+ export declare const DESTINATION_TYPES: {
25
+ readonly kick: readonly ["live"];
26
+ readonly twitch: readonly ["live"];
27
+ readonly rumble: readonly ["live", "video"];
28
+ readonly tiktok: readonly ["live", "video"];
29
+ readonly youtube: readonly ["live", "video", "replay"];
30
+ readonly twitter: readonly ["live", "post"];
31
+ readonly club: readonly ["post"];
32
+ };
33
+ export type DestinationPlatform = keyof typeof DESTINATION_TYPES;
34
+ export type DestinationType = (typeof DESTINATION_TYPES)[DestinationPlatform][number];
35
+ export type ExtraDestination = {
36
+ channelId: string;
37
+ /** A role id, `everyone`, `here`, or null for no ping - the same values the creator's own `pingRoleId` takes. */
38
+ pingRoleId: string | null;
39
+ types: DestinationType[];
40
+ };
41
+ /**
42
+ * A copy of the live post sent to an extra destination, so the offline can edit or delete it. `pingRoleId` is
43
+ * the role the copy was posted with: the offline edit rewrites the content, and it must show the copy's own
44
+ * role, not destination 1's - and not whatever the settings say by the time the stream ends.
45
+ */
46
+ export type ExtraPost = {
47
+ channelId: string;
48
+ messageId: string;
49
+ pingRoleId: string | null;
50
+ };
51
+ /**
52
+ * The stored form of whatever the dashboard sent. The save transforms call this, not only zod.
53
+ *
54
+ * Zod alone is not enough here: the creator routes validate with the PARTIAL schema, and `deepPartialify`
55
+ * keeps an array's `max` but drops custom refinements (the no-duplicates check) and makes every field
56
+ * of an item optional. So a row with no channel, a channel listed twice, or a type the platform does not
57
+ * have could all reach the database. This drops them instead of failing the whole save:
58
+ *
59
+ * - no valid `channelId` -> dropped
60
+ * - a channel already listed -> the later row dropped
61
+ * - a `pingRoleId` that is not a role / everyone / here -> no ping (null)
62
+ * - a type this platform does not have, or a repeat -> dropped from `types`
63
+ * - beyond `MAX_EXTRA_DESTINATIONS` -> cut
64
+ *
65
+ * `null` and anything that is not a list mean "no extras" and store `[]`: a Json column cannot take a
66
+ * plain null through Prisma, same as `Guild.statChannelFormats` storing `{}`.
67
+ */
68
+ export declare function normalizeExtraDestinations(platform: DestinationPlatform, input: unknown): ExtraDestination[];
69
+ /**
70
+ * The extras one notification goes to: the stored list, re-normalized (a row written before a rule changed
71
+ * still obeys today's rule), keeping only destinations that want this post type and whose channel is not
72
+ * already receiving it.
73
+ *
74
+ * `taken` is destination 1's channel AFTER any override redirect. An extra pointing at the same channel would
75
+ * post the notification there twice, so it is dropped here rather than rejected on save - a partial save body
76
+ * usually does not carry the creator's own channel, so the save could not check it.
77
+ */
78
+ export declare function extrasFor(platform: DestinationPlatform, stored: unknown, type: DestinationType, taken: (string | null | undefined)[]): ExtraDestination[];
79
+ /**
80
+ * The stored copies of a live post (`*CurrentlyLive.extraPosts`), read safely. Written only by the bot, but it is
81
+ * a Json column: anything malformed is dropped rather than trusted, and a pre-`pingRoleId` row reads as no role.
82
+ */
83
+ export declare function readExtraPosts(stored: unknown): ExtraPost[];
84
+ /** "Is there a live post to finish?" - destination 1's message, or any copy. Offline and sweep filters use this. */
85
+ export declare const hasLivePost: (live: {
86
+ channelId?: string | null;
87
+ messageId?: string | null;
88
+ extraPosts?: unknown;
89
+ } | null | undefined) => boolean;
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ /**
3
+ * Multi-destination notifications - up to two extra channels per creator, each with its own ping role.
4
+ * Premium Plus (`MultiDestination`), launch flag `multiDestination`. Plan: phases/multi-destination/.
5
+ *
6
+ * Mirrors `src/modules/multiDestination.ts` in Noti-v3. Hand-copied; the server's `sdkDrift` test diffs everything
7
+ * below this header against it.
8
+ *
9
+ * One source of truth for the rules, because they have to agree across the zod schemas, the save
10
+ * transforms, the send path and the SDK. Deliberately has NO imports, for the same reason as
11
+ * `offlineGrace.ts`: the zod schemas pull from here, and a cycle through them is someone's afternoon.
12
+ *
13
+ * The creator's own channel + `pingRoleId` is destination 1 and is not stored here. `extraDestinations`
14
+ * holds only the extras, so a server that never opts in has nothing new anywhere.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.hasLivePost = exports.DESTINATION_TYPES = exports.MAX_EXTRA_DESTINATIONS = void 0;
18
+ exports.normalizeExtraDestinations = normalizeExtraDestinations;
19
+ exports.extrasFor = extrasFor;
20
+ exports.readExtraPosts = readExtraPosts;
21
+ /** Extra destinations a creator may have, on top of their own channel. 3 channels total. */
22
+ exports.MAX_EXTRA_DESTINATIONS = 2;
23
+ /**
24
+ * Which post types an extra destination can be limited to, per platform. Empty `types` = everything.
25
+ *
26
+ * Offline is NOT a type: the offline path only ever edits or deletes the live post it announced, so a
27
+ * copy's offline follows its own live copy. Kick clips/VODs and the X post cooldown are separate
28
+ * features with their own channels, not notification types, so they are not here either.
29
+ */
30
+ exports.DESTINATION_TYPES = {
31
+ kick: ['live'],
32
+ twitch: ['live'],
33
+ rumble: ['live', 'video'],
34
+ tiktok: ['live', 'video'],
35
+ youtube: ['live', 'video', 'replay'],
36
+ twitter: ['live', 'post'],
37
+ club: ['post'],
38
+ };
39
+ const SNOWFLAKE = /^\d{17,21}$/;
40
+ const isPingTarget = (v) => typeof v === 'string' && (SNOWFLAKE.test(v) || v === 'everyone' || v === 'here');
41
+ /**
42
+ * The stored form of whatever the dashboard sent. The save transforms call this, not only zod.
43
+ *
44
+ * Zod alone is not enough here: the creator routes validate with the PARTIAL schema, and `deepPartialify`
45
+ * keeps an array's `max` but drops custom refinements (the no-duplicates check) and makes every field
46
+ * of an item optional. So a row with no channel, a channel listed twice, or a type the platform does not
47
+ * have could all reach the database. This drops them instead of failing the whole save:
48
+ *
49
+ * - no valid `channelId` -> dropped
50
+ * - a channel already listed -> the later row dropped
51
+ * - a `pingRoleId` that is not a role / everyone / here -> no ping (null)
52
+ * - a type this platform does not have, or a repeat -> dropped from `types`
53
+ * - beyond `MAX_EXTRA_DESTINATIONS` -> cut
54
+ *
55
+ * `null` and anything that is not a list mean "no extras" and store `[]`: a Json column cannot take a
56
+ * plain null through Prisma, same as `Guild.statChannelFormats` storing `{}`.
57
+ */
58
+ function normalizeExtraDestinations(platform, input) {
59
+ if (!Array.isArray(input))
60
+ return [];
61
+ const allowed = exports.DESTINATION_TYPES[platform];
62
+ const seen = new Set();
63
+ const out = [];
64
+ for (const raw of input) {
65
+ if (out.length >= exports.MAX_EXTRA_DESTINATIONS)
66
+ break;
67
+ if (!raw || typeof raw !== 'object')
68
+ continue;
69
+ const row = raw;
70
+ if (typeof row.channelId !== 'string' || !SNOWFLAKE.test(row.channelId) || seen.has(row.channelId))
71
+ continue;
72
+ seen.add(row.channelId);
73
+ const types = Array.isArray(row.types)
74
+ ? [...new Set(row.types.filter((t) => typeof t === 'string' && allowed.includes(t)))]
75
+ : [];
76
+ out.push({ channelId: row.channelId, pingRoleId: isPingTarget(row.pingRoleId) ? row.pingRoleId : null, types });
77
+ }
78
+ return out;
79
+ }
80
+ /**
81
+ * The extras one notification goes to: the stored list, re-normalized (a row written before a rule changed
82
+ * still obeys today's rule), keeping only destinations that want this post type and whose channel is not
83
+ * already receiving it.
84
+ *
85
+ * `taken` is destination 1's channel AFTER any override redirect. An extra pointing at the same channel would
86
+ * post the notification there twice, so it is dropped here rather than rejected on save - a partial save body
87
+ * usually does not carry the creator's own channel, so the save could not check it.
88
+ */
89
+ function extrasFor(platform, stored, type, taken) {
90
+ const used = new Set(taken.filter((id) => !!id));
91
+ return normalizeExtraDestinations(platform, stored).filter((d) => (!d.types.length || d.types.includes(type)) && !used.has(d.channelId));
92
+ }
93
+ /**
94
+ * The stored copies of a live post (`*CurrentlyLive.extraPosts`), read safely. Written only by the bot, but it is
95
+ * a Json column: anything malformed is dropped rather than trusted, and a pre-`pingRoleId` row reads as no role.
96
+ */
97
+ function readExtraPosts(stored) {
98
+ if (!Array.isArray(stored))
99
+ return [];
100
+ return stored.flatMap((raw) => {
101
+ const row = raw;
102
+ if (!row || typeof row.channelId !== 'string' || !SNOWFLAKE.test(row.channelId) || typeof row.messageId !== 'string' || !SNOWFLAKE.test(row.messageId))
103
+ return [];
104
+ return [{ channelId: row.channelId, messageId: row.messageId, pingRoleId: isPingTarget(row.pingRoleId) ? row.pingRoleId : null }];
105
+ });
106
+ }
107
+ /** "Is there a live post to finish?" - destination 1's message, or any copy. Offline and sweep filters use this. */
108
+ const hasLivePost = (live) => !!(live?.channelId && live?.messageId) || readExtraPosts(live?.extraPosts).length > 0;
109
+ exports.hasLivePost = hasLivePost;
@@ -10,6 +10,13 @@ export declare const ClubStreamerZod: {
10
10
  guildId: z.ZodString;
11
11
  usePerStreamerEmbeds: z.ZodNullable<z.ZodBoolean>;
12
12
  autoPublishIfAnnouncmentChannel: z.ZodNullable<z.ZodBoolean>;
13
+ extraDestinations: z.ZodNullable<z.ZodArray<z.ZodObject<{
14
+ channelId: z.ZodString;
15
+ pingRoleId: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"everyone">, z.ZodLiteral<"here">]>>;
16
+ types: z.ZodArray<z.ZodEnum<{
17
+ post: "post";
18
+ }>>;
19
+ }, z.core.$strip>>>;
13
20
  customMessages: z.ZodArray<z.ZodLazy<z.ZodObject<{
14
21
  content: z.ZodNullable<z.ZodString>;
15
22
  showInviteButton: z.ZodNullable<z.ZodBoolean>;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ClubStreamerZodPartial = exports.ClubStreamerZod = void 0;
4
4
  const schema_zod_1 = require("./schema.zod");
5
+ const multiDestination_1 = require("../multiDestination");
5
6
  const zod_1 = require("./zod");
6
7
  const zod_2 = require("zod");
7
8
  const ClubStreamerSchema = zod_2.z.object({
@@ -9,6 +10,8 @@ const ClubStreamerSchema = zod_2.z.object({
9
10
  guildId: zod_1.SnowFlake,
10
11
  usePerStreamerEmbeds: zod_2.z.boolean().nullable(),
11
12
  autoPublishIfAnnouncmentChannel: zod_2.z.boolean().nullable(),
13
+ /** Premium Plus (`MultiDestination`): up to 2 extra channels, each with its own ping role and post types. */
14
+ extraDestinations: zod_1.CentralZod.ExtraDestinations(multiDestination_1.DESTINATION_TYPES.club).nullable(),
12
15
  customMessages: (0, zod_1.NoDuplicate)(zod_2.z.array(zod_2.z.lazy(() => CSCustomMessageSchema)), ['type']),
13
16
  notificationChannelId: zod_1.SnowFlake.nullable(),
14
17
  showNotifyButton: zod_2.z.boolean().nullable(),
@@ -14,6 +14,13 @@ export declare const KickStreamerZod: {
14
14
  sendOfflineMessage: z.ZodNullable<z.ZodBoolean>;
15
15
  usePerStreamerEmbeds: z.ZodNullable<z.ZodBoolean>;
16
16
  autoPublishIfAnnouncmentChannel: z.ZodNullable<z.ZodBoolean>;
17
+ extraDestinations: z.ZodNullable<z.ZodArray<z.ZodObject<{
18
+ channelId: z.ZodString;
19
+ pingRoleId: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"everyone">, z.ZodLiteral<"here">]>>;
20
+ types: z.ZodArray<z.ZodEnum<{
21
+ live: "live";
22
+ }>>;
23
+ }, z.core.$strip>>>;
17
24
  customMessages: z.ZodArray<z.ZodLazy<z.ZodObject<{
18
25
  content: z.ZodNullable<z.ZodString>;
19
26
  showInviteButton: z.ZodNullable<z.ZodBoolean>;
@@ -133,6 +140,11 @@ export declare const KickStreamerZod: {
133
140
  correct: z.ZodNullable<z.ZodBoolean>;
134
141
  channelId: z.ZodNullable<z.ZodString>;
135
142
  messageId: z.ZodNullable<z.ZodString>;
143
+ extraPosts: z.ZodNullable<z.ZodArray<z.ZodObject<{
144
+ channelId: z.ZodString;
145
+ messageId: z.ZodString;
146
+ pingRoleId: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"everyone">, z.ZodLiteral<"here">]>>;
147
+ }, z.core.$strip>>>;
136
148
  }, z.core.$strip>>>;
137
149
  lastLive: z.ZodNullable<z.ZodDate>;
138
150
  thumbnailWaitSeconds: z.ZodNullable<z.ZodNumber>;
@@ -223,6 +235,11 @@ export declare const KickStreamerZod: {
223
235
  correct: z.ZodNullable<z.ZodBoolean>;
224
236
  channelId: z.ZodNullable<z.ZodString>;
225
237
  messageId: z.ZodNullable<z.ZodString>;
238
+ extraPosts: z.ZodNullable<z.ZodArray<z.ZodObject<{
239
+ channelId: z.ZodString;
240
+ messageId: z.ZodString;
241
+ pingRoleId: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"everyone">, z.ZodLiteral<"here">]>>;
242
+ }, z.core.$strip>>>;
226
243
  }, z.core.$strip>;
227
244
  };
228
245
  export declare const KickStreamerZodPartial: PartialZodObject<typeof KickStreamerZod>;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.KickStreamerZodPartial = exports.KickStreamerZod = void 0;
4
4
  const schema_zod_1 = require("./schema.zod");
5
+ const multiDestination_1 = require("../multiDestination");
5
6
  const zod_1 = require("./zod");
6
7
  const offlineGrace_1 = require("../offlineGrace");
7
8
  const zod_2 = require("zod");
@@ -14,6 +15,8 @@ const KickStreamerSchema = zod_2.z.object({
14
15
  sendOfflineMessage: zod_2.z.boolean().nullable(),
15
16
  usePerStreamerEmbeds: zod_2.z.boolean().nullable(),
16
17
  autoPublishIfAnnouncmentChannel: zod_2.z.boolean().nullable(),
18
+ /** Premium Plus (`MultiDestination`): up to 2 extra channels, each with its own ping role and post types. */
19
+ extraDestinations: zod_1.CentralZod.ExtraDestinations(multiDestination_1.DESTINATION_TYPES.kick).nullable(),
17
20
  customMessages: (0, zod_1.NoDuplicate)(zod_2.z.array(zod_2.z.lazy(() => KSCustomMessageSchema)), ['type']),
18
21
  clipEnabled: zod_2.z.boolean().nullable(),
19
22
  clipChannelId: zod_1.SnowFlake.nullable(),
@@ -91,6 +94,7 @@ const KSCurrentlyLiveSchema = zod_2.z.object({
91
94
  correct: zod_2.z.boolean().nullable(),
92
95
  channelId: zod_1.SnowFlake.nullable(),
93
96
  messageId: zod_1.SnowFlake.nullable(),
97
+ extraPosts: zod_1.CentralZod.ExtraPosts().nullable(),
94
98
  });
95
99
  exports.KickStreamerZod = {
96
100
  KickStreamerSchema,
@@ -17,6 +17,14 @@ export declare const RumbleStreamerZod: {
17
17
  usePerStreamerEmbeds: z.ZodNullable<z.ZodBoolean>;
18
18
  autoPublishIfAnnouncmentChannel: z.ZodNullable<z.ZodBoolean>;
19
19
  updateLivePost: z.ZodNullable<z.ZodBoolean>;
20
+ extraDestinations: z.ZodNullable<z.ZodArray<z.ZodObject<{
21
+ channelId: z.ZodString;
22
+ pingRoleId: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"everyone">, z.ZodLiteral<"here">]>>;
23
+ types: z.ZodArray<z.ZodEnum<{
24
+ live: "live";
25
+ video: "video";
26
+ }>>;
27
+ }, z.core.$strip>>>;
20
28
  customMessages: z.ZodArray<z.ZodLazy<z.ZodObject<{
21
29
  content: z.ZodNullable<z.ZodString>;
22
30
  showInviteButton: z.ZodNullable<z.ZodBoolean>;
@@ -90,6 +98,11 @@ export declare const RumbleStreamerZod: {
90
98
  correct: z.ZodNullable<z.ZodBoolean>;
91
99
  channelId: z.ZodNullable<z.ZodString>;
92
100
  messageId: z.ZodNullable<z.ZodString>;
101
+ extraPosts: z.ZodNullable<z.ZodArray<z.ZodObject<{
102
+ channelId: z.ZodString;
103
+ messageId: z.ZodString;
104
+ pingRoleId: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"everyone">, z.ZodLiteral<"here">]>>;
105
+ }, z.core.$strip>>>;
93
106
  }, z.core.$strip>>>;
94
107
  lastLive: z.ZodNullable<z.ZodDate>;
95
108
  lastVideo: z.ZodNullable<z.ZodDate>;
@@ -157,6 +170,11 @@ export declare const RumbleStreamerZod: {
157
170
  correct: z.ZodNullable<z.ZodBoolean>;
158
171
  channelId: z.ZodNullable<z.ZodString>;
159
172
  messageId: z.ZodNullable<z.ZodString>;
173
+ extraPosts: z.ZodNullable<z.ZodArray<z.ZodObject<{
174
+ channelId: z.ZodString;
175
+ messageId: z.ZodString;
176
+ pingRoleId: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"everyone">, z.ZodLiteral<"here">]>>;
177
+ }, z.core.$strip>>>;
160
178
  }, z.core.$strip>;
161
179
  };
162
180
  export declare const RumbleStreamerZodPartial: PartialZodObject<typeof RumbleStreamerZod>;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RumbleStreamerZodPartial = exports.RumbleStreamerZod = void 0;
4
4
  const schema_zod_1 = require("./schema.zod");
5
+ const multiDestination_1 = require("../multiDestination");
5
6
  const zod_1 = require("./zod");
6
7
  const offlineGrace_1 = require("../offlineGrace");
7
8
  const zod_2 = require("zod");
@@ -19,6 +20,8 @@ const RumbleStreamerSchema = zod_2.z.object({
19
20
  * this on save and never edits.
20
21
  */
21
22
  updateLivePost: zod_2.z.boolean().nullable(),
23
+ /** Premium Plus (`MultiDestination`): up to 2 extra channels, each with its own ping role and post types. */
24
+ extraDestinations: zod_1.CentralZod.ExtraDestinations(multiDestination_1.DESTINATION_TYPES.rumble).nullable(),
22
25
  customMessages: (0, zod_1.NoDuplicate)(zod_2.z.array(zod_2.z.lazy(() => RSCustomMessageSchema)), ['type']),
23
26
  notificationChannelId: zod_1.SnowFlake.nullable(),
24
27
  videoNotificationChannelId: zod_1.SnowFlake.nullable(),
@@ -50,6 +53,7 @@ const RSCurrentlyLiveSchema = zod_2.z.object({
50
53
  correct: zod_2.z.boolean().nullable(),
51
54
  channelId: zod_1.SnowFlake.nullable(),
52
55
  messageId: zod_1.SnowFlake.nullable(),
56
+ extraPosts: zod_1.CentralZod.ExtraPosts().nullable(),
53
57
  });
54
58
  exports.RumbleStreamerZod = {
55
59
  RumbleStreamerSchema,
@@ -12,6 +12,14 @@ export declare const TiktokStreamerZod: {
12
12
  sendOfflineMessage: z.ZodNullable<z.ZodBoolean>;
13
13
  usePerStreamerEmbeds: z.ZodNullable<z.ZodBoolean>;
14
14
  autoPublishIfAnnouncmentChannel: z.ZodNullable<z.ZodBoolean>;
15
+ extraDestinations: z.ZodNullable<z.ZodArray<z.ZodObject<{
16
+ channelId: z.ZodString;
17
+ pingRoleId: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"everyone">, z.ZodLiteral<"here">]>>;
18
+ types: z.ZodArray<z.ZodEnum<{
19
+ live: "live";
20
+ video: "video";
21
+ }>>;
22
+ }, z.core.$strip>>>;
15
23
  customMessages: z.ZodArray<z.ZodLazy<z.ZodObject<{
16
24
  content: z.ZodNullable<z.ZodString>;
17
25
  showInviteButton: z.ZodNullable<z.ZodBoolean>;
@@ -84,6 +92,11 @@ export declare const TiktokStreamerZod: {
84
92
  correct: z.ZodNullable<z.ZodBoolean>;
85
93
  channelId: z.ZodNullable<z.ZodString>;
86
94
  messageId: z.ZodNullable<z.ZodString>;
95
+ extraPosts: z.ZodNullable<z.ZodArray<z.ZodObject<{
96
+ channelId: z.ZodString;
97
+ messageId: z.ZodString;
98
+ pingRoleId: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"everyone">, z.ZodLiteral<"here">]>>;
99
+ }, z.core.$strip>>>;
87
100
  }, z.core.$strip>>>;
88
101
  lastLive: z.ZodNullable<z.ZodDate>;
89
102
  lastVideo: z.ZodNullable<z.ZodDate>;
@@ -150,6 +163,11 @@ export declare const TiktokStreamerZod: {
150
163
  correct: z.ZodNullable<z.ZodBoolean>;
151
164
  channelId: z.ZodNullable<z.ZodString>;
152
165
  messageId: z.ZodNullable<z.ZodString>;
166
+ extraPosts: z.ZodNullable<z.ZodArray<z.ZodObject<{
167
+ channelId: z.ZodString;
168
+ messageId: z.ZodString;
169
+ pingRoleId: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"everyone">, z.ZodLiteral<"here">]>>;
170
+ }, z.core.$strip>>>;
153
171
  }, z.core.$strip>;
154
172
  };
155
173
  export declare const TiktokStreamerZodPartial: PartialZodObject<typeof TiktokStreamerZod>;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TiktokStreamerZodPartial = exports.TiktokStreamerZod = void 0;
4
4
  const schema_zod_1 = require("./schema.zod");
5
+ const multiDestination_1 = require("../multiDestination");
5
6
  const zod_1 = require("./zod");
6
7
  const offlineGrace_1 = require("../offlineGrace");
7
8
  const zod_2 = require("zod");
@@ -12,6 +13,8 @@ const TiktokStreamerSchema = zod_2.z.object({
12
13
  sendOfflineMessage: zod_2.z.boolean().nullable(),
13
14
  usePerStreamerEmbeds: zod_2.z.boolean().nullable(),
14
15
  autoPublishIfAnnouncmentChannel: zod_2.z.boolean().nullable(),
16
+ /** Premium Plus (`MultiDestination`): up to 2 extra channels, each with its own ping role and post types. */
17
+ extraDestinations: zod_1.CentralZod.ExtraDestinations(multiDestination_1.DESTINATION_TYPES.tiktok).nullable(),
15
18
  customMessages: zod_2.z.array(zod_2.z.lazy(() => TTSCustomMessageSchema)),
16
19
  liveNotificationChannelId: zod_1.SnowFlake.nullable(),
17
20
  videoNotificationChannelId: zod_1.SnowFlake.nullable(),
@@ -42,6 +45,7 @@ const TTSCurrentlyLiveSchema = zod_2.z.object({
42
45
  correct: zod_2.z.boolean().nullable(),
43
46
  channelId: zod_1.SnowFlake.nullable(),
44
47
  messageId: zod_1.SnowFlake.nullable(),
48
+ extraPosts: zod_1.CentralZod.ExtraPosts().nullable(),
45
49
  });
46
50
  exports.TiktokStreamerZod = {
47
51
  TiktokStreamerSchema,
@@ -15,6 +15,13 @@ export declare const TwitchStreamerZod: {
15
15
  usePerStreamerEmbeds: z.ZodNullable<z.ZodBoolean>;
16
16
  autoPublishIfAnnouncmentChannel: z.ZodNullable<z.ZodBoolean>;
17
17
  updateLivePost: z.ZodNullable<z.ZodBoolean>;
18
+ extraDestinations: z.ZodNullable<z.ZodArray<z.ZodObject<{
19
+ channelId: z.ZodString;
20
+ pingRoleId: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"everyone">, z.ZodLiteral<"here">]>>;
21
+ types: z.ZodArray<z.ZodEnum<{
22
+ live: "live";
23
+ }>>;
24
+ }, z.core.$strip>>>;
18
25
  customMessages: z.ZodArray<z.ZodLazy<z.ZodObject<{
19
26
  content: z.ZodNullable<z.ZodString>;
20
27
  showInviteButton: z.ZodNullable<z.ZodBoolean>;
@@ -85,6 +92,11 @@ export declare const TwitchStreamerZod: {
85
92
  correct: z.ZodNullable<z.ZodBoolean>;
86
93
  channelId: z.ZodNullable<z.ZodString>;
87
94
  messageId: z.ZodNullable<z.ZodString>;
95
+ extraPosts: z.ZodNullable<z.ZodArray<z.ZodObject<{
96
+ channelId: z.ZodString;
97
+ messageId: z.ZodString;
98
+ pingRoleId: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"everyone">, z.ZodLiteral<"here">]>>;
99
+ }, z.core.$strip>>>;
88
100
  }, z.core.$strip>>>;
89
101
  lastLive: z.ZodNullable<z.ZodDate>;
90
102
  }, z.core.$strip>;
@@ -150,6 +162,11 @@ export declare const TwitchStreamerZod: {
150
162
  correct: z.ZodNullable<z.ZodBoolean>;
151
163
  channelId: z.ZodNullable<z.ZodString>;
152
164
  messageId: z.ZodNullable<z.ZodString>;
165
+ extraPosts: z.ZodNullable<z.ZodArray<z.ZodObject<{
166
+ channelId: z.ZodString;
167
+ messageId: z.ZodString;
168
+ pingRoleId: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"everyone">, z.ZodLiteral<"here">]>>;
169
+ }, z.core.$strip>>>;
153
170
  }, z.core.$strip>;
154
171
  };
155
172
  export declare const TwitchStreamerZodPartial: PartialZodObject<typeof TwitchStreamerZod>;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TwitchStreamerZodPartial = exports.TwitchStreamerZod = void 0;
4
4
  const schema_zod_1 = require("./schema.zod");
5
+ const multiDestination_1 = require("../multiDestination");
5
6
  const zod_1 = require("./zod");
6
7
  const offlineGrace_1 = require("../offlineGrace");
7
8
  const zod_2 = require("zod");
@@ -20,6 +21,8 @@ const TwitchStreamerSchema = zod_2.z.object({
20
21
  * this on save and never edits.
21
22
  */
22
23
  updateLivePost: zod_2.z.boolean().nullable(),
24
+ /** Premium Plus (`MultiDestination`): up to 2 extra channels, each with its own ping role and post types. */
25
+ extraDestinations: zod_1.CentralZod.ExtraDestinations(multiDestination_1.DESTINATION_TYPES.twitch).nullable(),
23
26
  customMessages: zod_2.z.array(zod_2.z.lazy(() => TSCustomMessageSchema)),
24
27
  notificationChannelId: zod_1.SnowFlake.nullable(),
25
28
  showNotifyButton: zod_2.z.boolean().nullable(),
@@ -46,6 +49,7 @@ const TSCurrentlyLiveSchema = zod_2.z.object({
46
49
  correct: zod_2.z.boolean().nullable(),
47
50
  channelId: zod_1.SnowFlake.nullable(),
48
51
  messageId: zod_1.SnowFlake.nullable(),
52
+ extraPosts: zod_1.CentralZod.ExtraPosts().nullable(),
49
53
  });
50
54
  exports.TwitchStreamerZod = {
51
55
  TwitchStreamerSchema,