Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support nonce/enforceNonce when creating messages #128

Merged
merged 4 commits into from
Mar 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ declare namespace Dysnomia {
type ComponentTypes = Constants["ComponentTypes"][keyof Constants["ComponentTypes"]];
type ImageFormat = Constants["ImageFormats"][number];
type MessageActivityTypes = Constants["MessageActivityTypes"][keyof Constants["MessageActivityTypes"]];
type MessageContent = string | AdvancedMessageContent;
type MessageContent<T extends "hasNonce" | "" = ""> = string | AdvancedMessageContent<T>;
type MFALevel = Constants["MFALevels"][keyof Constants["MFALevels"]];
type PossiblyUncachedMessage = Message | { author?: User | Uncached; channel: TextableChannel | { id: string; guild?: Uncached }; guildID?: string; id: string };
type SelectMenu = BaseSelectMenu | ChannelSelectMenu | StringSelectMenu | UserSelectMenu | RoleSelectMenu | MentionableSelectMenu;
Expand Down Expand Up @@ -438,7 +438,7 @@ declare namespace Dysnomia {
lastMessageID: string;
messages: Collection<Message<this>>;
addMessageReaction(messageID: string, reaction: string): Promise<void>;
createMessage(content: MessageContent): Promise<Message<this>>;
createMessage(content: MessageContent<"hasNonce">): Promise<Message<this>>;
deleteMessage(messageID: string, reason?: string): Promise<void>;
editMessage(messageID: string, content: MessageContent): Promise<Message<this>>;
getMessage(messageID: string): Promise<Message<this>>;
Expand Down Expand Up @@ -1344,14 +1344,16 @@ declare namespace Dysnomia {
components: TextInput[];
type: Constants["ComponentTypes"]["ACTION_ROW"];
}
interface AdvancedMessageContent {
interface AdvancedMessageContent<T extends "hasNonce" | "" = ""> {
allowedMentions?: AllowedMentions;
attachments?: AdvancedMessageContentAttachment[];
components?: ActionRow[];
content?: string;
enforceNonce?: T extends "hasNonce" ? boolean : never;
embeds?: EmbedOptions[];
flags?: number;
messageReference?: MessageReferenceReply;
nonce?: T extends "hasNonce" ? (string | number) : never;
stickerIDs?: string[];
tts?: boolean;
}
Expand Down Expand Up @@ -2643,7 +2645,7 @@ declare namespace Dysnomia {
createGuildSticker(guildID: string, options: CreateStickerOptions, reason?: string): Promise<Sticker>;
createGuildTemplate(guildID: string, name: string, description?: string | null): Promise<GuildTemplate>;
createInteractionResponse(interactionID: string, interactionToken: string, options: InteractionResponse, file?: FileContent | FileContent[]): Promise<void>;
createMessage(channelID: string, content: MessageContent): Promise<Message>;
createMessage(channelID: string, content: MessageContent<"hasNonce">): Promise<Message>;
createRole(guildID: string, options?: RoleOptions, reason?: string): Promise<Role>;
createRole(guildID: string, options?: Role, reason?: string): Promise<Role>;
createStageInstance(channelID: string, options: CreateStageInstanceOptions): Promise<StageInstance>;
Expand Down Expand Up @@ -3349,6 +3351,7 @@ declare namespace Dysnomia {
mentionEveryone: boolean;
mentions: User[];
messageReference: MessageReference | null;
nonce?: string | number;
pinned: boolean;
position?: number;
reactions: { [s: string]: { count: number; me: boolean } };
Expand Down Expand Up @@ -3402,7 +3405,7 @@ declare namespace Dysnomia {
rateLimitPerUser: 0;
type: Constants["ChannelTypes"]["GUILD_ANNOUNCEMENT"];
createInvite(options?: CreateInviteOptions, reason?: string): Promise<Invite<"withMetadata", this>>;
createMessage(content: MessageContent): Promise<Message<this>>;
createMessage(content: MessageContent<"hasNonce">): Promise<Message<this>>;
createThreadWithMessage(messageID: string, options: CreateThreadOptions): Promise<NewsThreadChannel>;
crosspostMessage(messageID: string): Promise<Message<this>>;
editMessage(messageID: string, content: MessageContent): Promise<Message<this>>;
Expand Down Expand Up @@ -3461,7 +3464,7 @@ declare namespace Dysnomia {
recipient: User;
type: PrivateChannelTypes;
addMessageReaction(messageID: string, reaction: string): Promise<void>;
createMessage(content: MessageContent): Promise<Message<this>>;
createMessage(content: MessageContent<"hasNonce">): Promise<Message<this>>;
deleteMessage(messageID: string, reason?: string): Promise<void>;
editMessage(messageID: string, content: MessageContent): Promise<Message<this>>;
getMessage(messageID: string): Promise<Message<this>>;
Expand Down Expand Up @@ -3674,7 +3677,7 @@ declare namespace Dysnomia {
constructor(data: BaseData, client: Client, messageLimit: number);
addMessageReaction(messageID: string, reaction: string): Promise<void>;
createInvite(options?: CreateInviteOptions, reason?: string): Promise<Invite<"withMetadata", this>>;
createMessage(content: MessageContent): Promise<Message<this>>;
createMessage(content: MessageContent<"hasNonce">): Promise<Message<this>>;
createThread(options: CreateThreadWithoutMessageOptions): Promise<ThreadChannel>;
createThreadWithMessage(messageID: string, options: CreateThreadOptions): Promise<PublicThreadChannel>;
createWebhook(options: Omit<WebhookOptions, "channelID">, reason?: string): Promise<Webhook>;
Expand Down Expand Up @@ -3706,7 +3709,7 @@ declare namespace Dysnomia {
messages: Collection<Message<this>>;
rateLimitPerUser: number;
addMessageReaction(messageID: string, reaction: string): Promise<void>;
createMessage(content: MessageContent): Promise<Message<this>>;
createMessage(content: MessageContent<"hasNonce">): Promise<Message<this>>;
createWebhook(options: { name: string; avatar?: string | null }, reason?: string): Promise<Webhook>;
deleteMessage(messageID: string, reason?: string): Promise<void>;
deleteMessages(messageIDs: string[], reason?: string): Promise<void>;
Expand Down Expand Up @@ -3738,7 +3741,7 @@ declare namespace Dysnomia {
type: GuildThreadChannelTypes;
constructor(data: BaseData, client: Client, messageLimit?: number);
addMessageReaction(messageID: string, reaction: string): Promise<void>;
createMessage(content: MessageContent): Promise<Message<this>>;
createMessage(content: MessageContent<"hasNonce">): Promise<Message<this>>;
deleteMessage(messageID: string, reason?: string): Promise<void>;
deleteMessages(messageIDs: string[], reason?: string): Promise<void>;
edit(options: Pick<EditChannelOptions, "archived" | "autoArchiveDuration" | "invitable" | "locked" | "name" | "rateLimitPerUser">, reason?: string): Promise<this>;
Expand Down
3 changes: 3 additions & 0 deletions lib/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -777,13 +777,15 @@ class Client extends EventEmitter {
* @arg {String} [content.attachments[].description] A description for the attachment
* @arg {Array<Object>} [content.components] An array of components. See [Discord's Documentation](https://discord.com/developers/docs/interactions/message-components#what-is-a-component) for object structure
* @arg {String} [content.content] A content string
* @arg {Boolean} [content.enforceNonce] If set and nonce is present, check the message for uniqueness in the past few minutes
* @arg {Array<Object>} [content.embeds] An array of embed objects. See [Discord's Documentation](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
* @arg {Number} [content.flags] Message flags. See [Discord's Documentation](https://discord.com/developers/docs/resources/channel#message-object-message-flags) for a list
* @arg {Object} [content.messageReference] The message reference, used when replying to messages
* @arg {String} [content.messageReference.channelID] The channel ID of the referenced message
* @arg {Boolean} [content.messageReference.failIfNotExists=true] Whether to throw an error if the message reference doesn't exist. If false, and the referenced message doesn't exist, the message is created without a referenced message
* @arg {String} [content.messageReference.guildID] The guild ID of the referenced message
* @arg {String} content.messageReference.messageID The message ID of the referenced message. This cannot reference a system message
* @arg {String | Number} [content.nonce] A value that can be used to check if the message was sent
* @arg {Array<String>} [content.stickerIDs] An array of IDs corresponding to stickers to send
* @arg {Boolean} [content.tts] Set the message TTS flag
* @returns {Promise<Message>}
Expand Down Expand Up @@ -818,6 +820,7 @@ class Client extends EventEmitter {
content.messageReference.failIfNotExists = undefined;
}
}
content.enforce_nonce = content.enforceNonce;
}

const {files, attachments} = this._processAttachments(content.attachments);
Expand Down
9 changes: 9 additions & 0 deletions lib/structures/Message.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,15 @@ class Message extends Base {
};
}

/**
* A unique user-provided value used to check whether a message was sent.
* Available only when the message is created over REST, or received via
* the messageCreate event.
*
* @type {(String | Number)?}
*/
this.nonce = data.nonce;

switch(this.type) {
case MessageTypes.DEFAULT: {
break;
Expand Down
2 changes: 2 additions & 0 deletions lib/structures/PrivateChannel.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,14 @@ class PrivateChannel extends Channel {
* @arg {String} [content.attachments[].description] A description for the attachment
* @arg {Array<Object>} [content.components] An array of components. See [Discord's Documentation](https://discord.com/developers/docs/interactions/message-components#what-is-a-component) for object structure
* @arg {String} [content.content] A content string
* @arg {Boolean} [content.enforceNonce] If set and nonce is present, check the message for uniqueness in the past few minutes
* @arg {Array<Object>} [content.embeds] An array of embed objects. See [Discord's Documentation](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
* @arg {Object} [content.messageReference] The message reference, used when replying to messages
* @arg {String} [content.messageReference.channelID] The channel ID of the referenced message
* @arg {Boolean} [content.messageReference.failIfNotExists=true] Whether to throw an error if the message reference doesn't exist. If false, and the referenced message doesn't exist, the message is created without a referenced message
* @arg {String} [content.messageReference.guildID] The guild ID of the referenced message
* @arg {String} content.messageReference.messageID The message ID of the referenced message. This cannot reference a system message
* @arg {String | Number} [content.nonce] A value that can be used to check if the message was sent
* @arg {Array<String>} [content.stickerIDs] An array of IDs corresponding to stickers to send
* @arg {Boolean} [content.tts] Set the message TTS flag
* @returns {Promise<Message>}
Expand Down
2 changes: 2 additions & 0 deletions lib/structures/TextChannel.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,15 @@ class TextChannel extends GuildChannel {
* @arg {String} [content.attachments[].description] A description for the attachment
* @arg {Array<Object>} [content.components] An array of components. See [Discord's Documentation](https://discord.com/developers/docs/interactions/message-components#what-is-a-component) for object structure
* @arg {String} [content.content] A content string
* @arg {Boolean} [content.enforceNonce] If set and nonce is present, check the message for uniqueness in the past few minutes
* @arg {Array<Object>} [content.embeds] An array of embed objects. See [Discord's Documentation](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
* @arg {Number} [content.flags] Message flags. See [Discord's Documentation](https://discord.com/developers/docs/resources/channel#message-object-message-flags) for a list
* @arg {Object} [content.messageReference] The message reference, used when replying to messages
* @arg {String} [content.messageReference.channelID] The channel ID of the referenced message
* @arg {Boolean} [content.messageReference.failIfNotExists=true] Whether to throw an error if the message reference doesn't exist. If false, and the referenced message doesn't exist, the message is created without a referenced message
* @arg {String} [content.messageReference.guildID] The guild ID of the referenced message
* @arg {String} content.messageReference.messageID The message ID of the referenced message. This cannot reference a system message
* @arg {String | Number} [content.nonce] A value that can be used to check if the message was sent
* @arg {Array<String>} [content.stickerIDs] An array of IDs corresponding to stickers to send
* @arg {Boolean} [content.tts] Set the message TTS flag
* @returns {Promise<Message>}
Expand Down
2 changes: 2 additions & 0 deletions lib/structures/TextVoiceChannel.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,14 @@ class TextVoiceChannel extends VoiceChannel {
* @arg {String} [content.attachments[].description] A description for the attachment
* @arg {Array<Object>} [content.components] An array of components. See [the official Discord API documentation entry](https://discord.com/developers/docs/interactions/message-components#what-is-a-component) for object structure
* @arg {String} content.content A content string
* @arg {Boolean} [content.enforceNonce] If set and nonce is present, check the message for uniqueness in the past few minutes
* @arg {Array<Object>} [content.embeds] An array of embed objects. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
* @arg {Object} [content.messageReference] The message reference, used when replying to messages
* @arg {String} [content.messageReference.channelID] The channel ID of the referenced message
* @arg {Boolean} [content.messageReference.failIfNotExists=true] Whether to throw an error if the message reference doesn't exist. If false, and the referenced message doesn't exist, the message is created without a referenced message
* @arg {String} [content.messageReference.guildID] The guild ID of the referenced message
* @arg {String} content.messageReference.messageID The message ID of the referenced message. This cannot reference a system message
* @arg {String | Number} [content.nonce] A unique value that can be used to check if the message was sent
* @arg {Array<String>} [content.stickerIDs] An array of IDs corresponding to the stickers to send
* @arg {Boolean} [content.tts] Set the message TTS flag
* @returns {Promise<Message>}
Expand Down
2 changes: 2 additions & 0 deletions lib/structures/ThreadChannel.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,14 @@ class ThreadChannel extends GuildChannel {
* @arg {String} [content.attachments[].description] A description for the attachment
* @arg {Array<Object>} [content.components] An array of components. See [the official Discord API documentation entry](https://discord.com/developers/docs/interactions/message-components#what-is-a-component) for object structure
* @arg {String} [content.content] A content string
* @arg {Boolean} [content.enforceNonce] If set and nonce is present, check the message for uniqueness in the past few minutes
* @arg {Array<Object>} [content.embeds] An array of embed objects. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
* @arg {Object} [content.messageReference] The message reference, used when replying to messages
* @arg {String} [content.messageReference.channelID] The channel ID of the referenced message
* @arg {Boolean} [content.messageReference.failIfNotExists=true] Whether to throw an error if the message reference doesn't exist. If false, and the referenced message doesn't exist, the message is created without a referenced message
* @arg {String} [content.messageReference.guildID] The guild ID of the referenced message
* @arg {String} content.messageReference.messageID The message ID of the referenced message. This cannot reference a system message
* @arg {String | Number} [content.nonce] A value that can be used to check if the message was sent
* @arg {Array<String>} [content.stickerIDs] An array of IDs corresponding to stickers to send
* @arg {Boolean} [content.tts] Set the message TTS flag
* @returns {Promise<Message>}
Expand Down
Loading