From 7836ec393fedb200ebb77d2e410746d53c222b33 Mon Sep 17 00:00:00 2001 From: Fleny Date: Sat, 13 Jul 2024 15:52:05 +0200 Subject: [PATCH] Add missing proprieties on channel (#3736) --- packages/bot/src/transformers.ts | 60 +++++++++++++- packages/bot/src/transformers/channel.ts | 80 ++++++++++++++++++- packages/bot/src/transformers/emoji.ts | 19 ++++- .../bot/src/transformers/toggles/channel.ts | 7 ++ 4 files changed, 160 insertions(+), 6 deletions(-) diff --git a/packages/bot/src/transformers.ts b/packages/bot/src/transformers.ts index 12f2ca190..22f005c17 100644 --- a/packages/bot/src/transformers.ts +++ b/packages/bot/src/transformers.ts @@ -15,9 +15,11 @@ import type { DiscordAvatarDecorationData, DiscordChannel, DiscordCreateApplicationCommand, + DiscordDefaultReactionEmoji, DiscordEmbed, DiscordEmoji, DiscordEntitlement, + DiscordForumTag, DiscordGetGatewayBot, DiscordGuild, DiscordGuildApplicationCommandPermissions, @@ -64,10 +66,10 @@ import { transformAttachment, type Attachment } from './transformers/attachment. import { transformAuditLogEntry, type AuditLogEntry } from './transformers/auditLogEntry.js' import { transformAutoModerationActionExecution, type AutoModerationActionExecution } from './transformers/automodActionExecution.js' import { transformAutoModerationRule, type AutoModerationRule } from './transformers/automodRule.js' -import { transformChannel, type Channel } from './transformers/channel.js' +import { transformChannel, transformForumTag, type Channel, type ForumTag } from './transformers/channel.js' import { transformComponent, type Component } from './transformers/component.js' import { transformEmbed, type Embed } from './transformers/embed.js' -import { transformEmoji, type Emoji } from './transformers/emoji.js' +import { transformDefaultReactionEmoji, transformEmoji, type DefaultReactionEmoji, type Emoji } from './transformers/emoji.js' import { transformEntitlement, type Entitlement } from './transformers/entitlement.js' import { transformGatewayBot, type GetGatewayBot } from './transformers/gatewayBot.js' import { transformGuild, type Guild } from './transformers/guild.js' @@ -130,6 +132,7 @@ import type { BotInteractionResponse, DiscordComponent, DiscordInteractionRespon export interface Transformers { customizers: { channel: (bot: Bot, payload: DiscordChannel, channel: Channel) => any + forumTag: (bot: Bot, payload: DiscordForumTag, forumTag: ForumTag) => any interaction: (bot: Bot, payload: { interaction: DiscordInteraction; shardId: number }, interaction: Interaction) => any message: (bot: Bot, payload: DiscordMessage, message: Message) => any messageInteractionMetadata: (bot: Bot, payload: DiscordMessageInteractionMetadata, metadata: MessageInteractionMetadata) => any @@ -147,6 +150,7 @@ export interface Transformers { application: (bot: Bot, payload: DiscordApplication, application: Application) => any team: (bot: Bot, payload: DiscordTeam, team: Team) => any emoji: (bot: Bot, payload: DiscordEmoji, emoji: Emoji) => any + defaultReactionEmoji: (bot: Bot, payload: DiscordDefaultReactionEmoji, defaultReactionEmoji: DefaultReactionEmoji) => any activity: (bot: Bot, payload: DiscordActivity, activity: Activity) => any presence: (bot: Bot, payload: DiscordPresenceUpdate, presence: PresenceUpdate) => any attachment: (bot: Bot, payload: DiscordAttachment, attachment: Attachment) => any @@ -236,6 +240,23 @@ export interface Transformers { createTimestamp: boolean newlyCreated: boolean flags: boolean + recipients: boolean + icon: boolean + member: boolean + totalMessageSent: boolean + availableTags: boolean + appliedTags: boolean + defaultReactionEmoji: boolean + defaultThreadRateLimitPerUser: boolean + defaultSortOrder: boolean + defaultForumLayout: boolean + } + forumTag: { + id: boolean + name: boolean + moderated: boolean + emojiId: boolean + emojiName: boolean } emoji: { id: boolean @@ -243,6 +264,10 @@ export interface Transformers { roles: boolean user: boolean } + defaultReactionEmoji: { + emojiId: boolean + emojiName: boolean + } guild: { afkTimeout: boolean approximateMemberCount: boolean @@ -596,6 +621,7 @@ export interface Transformers { automodRule: (bot: Bot, payload: DiscordAutoModerationRule) => AutoModerationRule automodActionExecution: (bot: Bot, payload: DiscordAutoModerationActionExecution) => AutoModerationActionExecution channel: (bot: Bot, payload: { channel: DiscordChannel } & { guildId?: BigString }) => Channel + forumTag: (bot: Bot, payload: DiscordForumTag) => ForumTag guild: (bot: Bot, payload: { guild: DiscordGuild } & { shardId: number }) => Guild user: (bot: Bot, payload: DiscordUser) => User member: (bot: Bot, payload: DiscordMember, guildId: BigString, userId: BigString) => Member @@ -611,6 +637,7 @@ export interface Transformers { application: (bot: Bot, payload: { application: DiscordApplication; shardId: number }) => Application team: (bot: Bot, payload: DiscordTeam) => Team emoji: (bot: Bot, payload: DiscordEmoji) => Emoji + defaultReactionEmoji: (bot: Bot, payload: DiscordDefaultReactionEmoji) => DefaultReactionEmoji activity: (bot: Bot, payload: DiscordActivity) => Activity presence: (bot: Bot, payload: DiscordPresenceUpdate) => PresenceUpdate attachment: (bot: Bot, payload: DiscordAttachment) => Attachment @@ -665,6 +692,9 @@ export function createTransformers(options: Partial, opts?: Create channel(bot, payload, channel) { return channel }, + forumTag(bot, payload, forumTag) { + return forumTag + }, interaction(bot, payload, interaction) { return interaction }, @@ -725,6 +755,9 @@ export function createTransformers(options: Partial, opts?: Create emoji(bot, payload, emoji) { return emoji }, + defaultReactionEmoji(bot, payload, defaultReactionEmoji) { + return defaultReactionEmoji + }, guild(bot, payload, guild) { return guild }, @@ -857,6 +890,23 @@ export function createTransformers(options: Partial, opts?: Create createTimestamp: opts?.defaultDesiredPropertiesValue ?? false, newlyCreated: opts?.defaultDesiredPropertiesValue ?? false, flags: opts?.defaultDesiredPropertiesValue ?? false, + appliedTags: opts?.defaultDesiredPropertiesValue ?? false, + availableTags: opts?.defaultDesiredPropertiesValue ?? false, + defaultForumLayout: opts?.defaultDesiredPropertiesValue ?? false, + defaultReactionEmoji: opts?.defaultDesiredPropertiesValue ?? false, + defaultSortOrder: opts?.defaultDesiredPropertiesValue ?? false, + defaultThreadRateLimitPerUser: opts?.defaultDesiredPropertiesValue ?? false, + icon: opts?.defaultDesiredPropertiesValue ?? false, + member: opts?.defaultDesiredPropertiesValue ?? false, + recipients: opts?.defaultDesiredPropertiesValue ?? false, + totalMessageSent: opts?.defaultDesiredPropertiesValue ?? false, + }, + forumTag: { + emojiId: opts?.defaultDesiredPropertiesValue ?? false, + emojiName: opts?.defaultDesiredPropertiesValue ?? false, + id: opts?.defaultDesiredPropertiesValue ?? false, + moderated: opts?.defaultDesiredPropertiesValue ?? false, + name: opts?.defaultDesiredPropertiesValue ?? false, }, emoji: { id: opts?.defaultDesiredPropertiesValue ?? false, @@ -864,6 +914,10 @@ export function createTransformers(options: Partial, opts?: Create roles: opts?.defaultDesiredPropertiesValue ?? false, user: opts?.defaultDesiredPropertiesValue ?? false, }, + defaultReactionEmoji: { + emojiId: opts?.defaultDesiredPropertiesValue ?? false, + emojiName: opts?.defaultDesiredPropertiesValue ?? false, + }, guild: { afkTimeout: opts?.defaultDesiredPropertiesValue ?? false, approximateMemberCount: opts?.defaultDesiredPropertiesValue ?? false, @@ -1219,9 +1273,11 @@ export function createTransformers(options: Partial, opts?: Create application: options.application ?? transformApplication, attachment: options.attachment ?? transformAttachment, channel: options.channel ?? transformChannel, + forumTag: options.forumTag ?? transformForumTag, component: options.component ?? transformComponent, embed: options.embed ?? transformEmbed, emoji: options.emoji ?? transformEmoji, + defaultReactionEmoji: options.defaultReactionEmoji ?? transformDefaultReactionEmoji, guild: options.guild ?? transformGuild, integration: options.integration ?? transformIntegration, interaction: options.interaction ?? transformInteraction, diff --git a/packages/bot/src/transformers/channel.ts b/packages/bot/src/transformers/channel.ts index a2932c0ef..b9293b82a 100644 --- a/packages/bot/src/transformers/channel.ts +++ b/packages/bot/src/transformers/channel.ts @@ -1,6 +1,15 @@ /* eslint-disable @typescript-eslint/no-unsafe-argument */ -import type { BigString, ChannelTypes, DiscordChannel, DiscordThreadMember, OverwriteReadable, VideoQualityModes } from '@discordeno/types' -import { calculatePermissions, type Bot } from '../index.js' +import type { + BigString, + ChannelTypes, + DiscordChannel, + DiscordForumTag, + ForumLayout, + OverwriteReadable, + SortOrderTypes, + VideoQualityModes, +} from '@discordeno/types' +import { calculatePermissions, iconHashToBigInt, type Bot, type DefaultReactionEmoji, type ThreadMember, type User } from '../index.js' import { Permissions } from './toggles/Permissions.js' import { ChannelToggles } from './toggles/channel.js' @@ -37,6 +46,9 @@ export const baseChannel: Partial & BaseChannel = { get newlyCreated() { return !!this.toggles?.newlyCreated }, + get managed() { + return !!this.toggles?.managed + }, get permissionOverwrites() { return ( this.internalOverwrites?.map((overwrite) => { @@ -100,10 +112,38 @@ export function transformChannel(bot: Bot, payload: { channel: DiscordChannel } if (props.permissionOverwrites && payload.channel.permission_overwrites) channel.internalOverwrites = payload.channel.permission_overwrites.map((o) => packOverwrites(o.allow ?? '0', o.deny ?? '0', o.id, o.type)) if (props.parentId && payload.channel.parent_id) channel.parentId = bot.transformers.snowflake(payload.channel.parent_id) + if (props.recipients && payload.channel.recipients) channel.recipients = payload.channel.recipients.map((u) => bot.transformers.user(bot, u)) + if (props.icon && payload.channel.icon) channel.icon = iconHashToBigInt(payload.channel.icon) + if (props.applicationId && payload.channel.application_id) channel.applicationId = bot.transformers.snowflake(payload.channel.application_id) + if (props.member && payload.channel.member) channel.member = bot.transformers.threadMember(bot, payload.channel.member) + if (props.totalMessageSent && payload.channel.total_message_sent !== undefined) channel.totalMessageSent = payload.channel.total_message_sent + if (props.availableTags && payload.channel.available_tags) + channel.availableTags = payload.channel.available_tags.map((x) => bot.transformers.forumTag(bot, x)) + if (props.appliedTags && payload.channel.applied_tags) channel.appliedTags = payload.channel.applied_tags.map((x) => bot.transformers.snowflake(x)) + if (props.defaultReactionEmoji && payload.channel.default_reaction_emoji) + channel.defaultReactionEmoji = bot.transformers.defaultReactionEmoji(bot, payload.channel.default_reaction_emoji) + if (props.defaultThreadRateLimitPerUser && payload.channel.default_thread_rate_limit_per_user) + channel.defaultThreadRateLimitPerUser = payload.channel.default_thread_rate_limit_per_user + if (props.defaultSortOrder && payload.channel.default_sort_order !== undefined) channel.defaultSortOrder = payload.channel.default_sort_order + if (props.defaultForumLayout && payload.channel.default_forum_layout !== undefined) + channel.defaultForumLayout = payload.channel.default_forum_layout return bot.transformers.customizers.channel(bot, payload.channel, channel) } +export function transformForumTag(bot: Bot, payload: DiscordForumTag): ForumTag { + const props = bot.transformers.desiredProperties.forumTag + const forumTag = {} as ForumTag + + if (props.id && payload.id) forumTag.id = bot.transformers.snowflake(payload.id) + if (props.name && payload.name) forumTag.name = payload.name + if (props.moderated && payload.moderated) forumTag.moderated = payload.moderated + if (props.emojiId && payload.emoji_id) forumTag.emojiId = bot.transformers.snowflake(payload.emoji_id) + if (props.emojiName && payload.emoji_name) forumTag.emojiName = payload.emoji_name + + return bot.transformers.customizers.forumTag(bot, payload, forumTag) +} + export interface BaseChannel { /** Whether the channel is nsfw */ nsfw: boolean @@ -130,6 +170,8 @@ export interface BaseChannel { invitable: boolean /** Whether the thread is archived */ archived: boolean + /** for group DM channels: whether the channel is managed by an application via the `gdm.join` OAuth2 scope */ + managed: boolean /** Explicit permission overwrites for members and roles. */ permissionOverwrites: OverwriteReadable[] } @@ -185,7 +227,7 @@ export interface Channel extends BaseChannel { autoArchiveDuration: 60 | 1440 | 4320 | 10080 } /** Thread member object for the current user, if they have joined the thread, only included on certain API endpoints */ - member?: DiscordThreadMember + member?: ThreadMember /** Default duration for newly created threads, in minutes, to automatically archive the thread after recent activity, can be set to: 60, 1440, 4320, 10080 */ defaultAutoArchiveDuration?: number /** computed permissions for the invoking user in the channel, including overwrites, only included when part of the resolved data received on a slash command interaction. This does not include implicit permissions, which may need to be checked separately. */ @@ -198,4 +240,36 @@ export interface Channel extends BaseChannel { * @private This is for internal use only, and prone to breaking changes. */ internalOverwrites?: bigint[] + /** The recipients of a group dm */ + recipients?: User[] + /** Icon hash of the group dm */ + icon?: bigint + /** Application id of the group DM creator if it is bot-created */ + applicationId?: bigint + /** Number of messages ever sent in a thread, it's similar to `message_count` on message creation, but will not decrement the number when a message is deleted */ + totalMessageSent?: number + /** The set of tags that can be used in a `GUILD_FORUM` or a `GUILD_MEDIA` channel */ + availableTags?: ForumTag[] + /** The IDs of the set of tags that have been applied to a thread in a `GUILD_FORUM` or a `GUILD_MEDIA` channel */ + appliedTags?: bigint[] + /** The emoji to show in the add reaction button on a thread in a `GUILD_FORUM` or a `GUILD_MEDIA` channel */ + defaultReactionEmoji?: DefaultReactionEmoji + /** the initial `rateLimitPerUser` to set on newly created threads in a channel. this field is copied to the thread at creation time and does not live update. */ + defaultThreadRateLimitPerUser?: number + /** The default sort order type used to order posts in `GUILD_FORUM` and `GUILD_MEDIA` channels. Defaults to null, which indicates a preferred sort order hasn't been set by a channel admin */ + defaultSortOrder?: SortOrderTypes | null + defaultForumLayout?: ForumLayout +} + +export interface ForumTag { + /** The id of the tag */ + id: bigint + /** The name of the tag (0-20 characters) */ + name: string + /** Whether this tag can only be added to or removed from threads by a member with the MANAGE_THREADS permission */ + moderated: boolean + /** The id of a guild's custom emoji At most one of emoji_id and emoji_name may be set. */ + emojiId: bigint + /** The unicode character of the emoji */ + emojiName: string | null } diff --git a/packages/bot/src/transformers/emoji.ts b/packages/bot/src/transformers/emoji.ts index 8ab93349e..d66cddd20 100644 --- a/packages/bot/src/transformers/emoji.ts +++ b/packages/bot/src/transformers/emoji.ts @@ -1,4 +1,4 @@ -import type { DiscordEmoji } from '@discordeno/types' +import type { DiscordDefaultReactionEmoji, DiscordEmoji } from '@discordeno/types' import type { Bot, User } from '../index.js' import { EmojiToggles } from './toggles/emoji.js' @@ -16,6 +16,16 @@ export function transformEmoji(bot: Bot, payload: DiscordEmoji): Emoji { return bot.transformers.customizers.emoji(bot, payload, emoji) } +export function transformDefaultReactionEmoji(bot: Bot, payload: DiscordDefaultReactionEmoji): DefaultReactionEmoji { + const props = bot.transformers.desiredProperties.defaultReactionEmoji + const defaultReactionEmoji = {} as DefaultReactionEmoji + + if (props.emojiId && payload.emoji_id) defaultReactionEmoji.emojiId = bot.transformers.snowflake(payload.emoji_id) + if (props.emojiName && payload.emoji_name) defaultReactionEmoji.emojiName = payload.emoji_name + + return bot.transformers.customizers.defaultReactionEmoji(bot, payload, defaultReactionEmoji) +} + export interface Emoji { /** Emoji name (can only be null in reaction emoji objects) */ name?: string @@ -35,3 +45,10 @@ export interface Emoji { available?: boolean toggles: EmojiToggles } + +export interface DefaultReactionEmoji { + /** The id of a guild's custom emoji */ + emojiId: bigint + /** The unicode character of the emoji */ + emojiName?: string +} diff --git a/packages/bot/src/transformers/toggles/channel.ts b/packages/bot/src/transformers/toggles/channel.ts index cbf44c96c..e775b5ebf 100644 --- a/packages/bot/src/transformers/toggles/channel.ts +++ b/packages/bot/src/transformers/toggles/channel.ts @@ -12,6 +12,8 @@ export const ChannelToggle = { archived: 1 << 3, /** When a thread is created this will be true on that channel payload for the thread. */ newlyCreated: 1 << 4, + /** for group DM channels: whether the channel is managed by an application via the `gdm.join` OAuth2 scope */ + managed: 1 << 5, } export class ChannelToggles extends ToggleBitfield { @@ -26,6 +28,7 @@ export class ChannelToggles extends ToggleBitfield { if (channel.thread_metadata?.invitable) this.add(ChannelToggle.invitable) if (channel.thread_metadata?.archived) this.add(ChannelToggle.archived) if (channel.newly_created) this.add(ChannelToggle.newlyCreated) + if (channel.managed) this.add(ChannelToggle.managed) } } @@ -54,6 +57,10 @@ export class ChannelToggles extends ToggleBitfield { return this.has('newlyCreated') } + get managed(): boolean { + return this.has('managed') + } + /** Checks whether or not the permissions exist in this */ has(permissions: ChannelToggleKeys | ChannelToggleKeys[]): boolean { if (!Array.isArray(permissions)) return super.contains(ChannelToggle[permissions])