-
-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
952 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { AllowedMentionsTypes, MessageFlags } from 'discord-api-types/v10'; | ||
import { describe, test, expect } from 'vitest'; | ||
import { EmbedBuilder, MessageBuilder } from '../../src/index.js'; | ||
|
||
const base = { | ||
allowed_mentions: undefined, | ||
attachments: [], | ||
components: [], | ||
embeds: [], | ||
message_reference: undefined, | ||
poll: undefined, | ||
}; | ||
|
||
describe('Message', () => { | ||
test('GIVEN a message with pre-defined content THEN return valid toJSON data', () => { | ||
const message = new MessageBuilder({ content: 'foo' }); | ||
expect(message.toJSON()).toStrictEqual({ ...base, content: 'foo' }); | ||
}); | ||
|
||
test('GIVEN bad action row THEN it throws', () => { | ||
const message = new MessageBuilder().setComponents((row) => | ||
row.addTextInputComponent((input) => input.setCustomId('abc').setLabel('def')), | ||
); | ||
expect(() => message.toJSON()).toThrow(); | ||
}); | ||
|
||
test('GIVEN tons of data THEN return valid toJSON data', () => { | ||
const message = new MessageBuilder() | ||
.setContent('foo') | ||
.setNonce(123) | ||
.setTTS() | ||
.addEmbeds(new EmbedBuilder().setTitle('foo').setDescription('bar')) | ||
.setAllowedMentions({ parse: [AllowedMentionsTypes.Role], roles: ['123'] }) | ||
.setMessageReference({ channel_id: '123', message_id: '123' }) | ||
.setComponents((row) => row.addPrimaryButtonComponents((button) => button.setCustomId('abc').setLabel('def'))) | ||
.setStickerIds('123', '456') | ||
.addAttachments((attachment) => attachment.setId('hi!').setFilename('abc')) | ||
.setFlags(MessageFlags.Ephemeral) | ||
.setEnforceNonce(false) | ||
.updatePoll((poll) => poll.addAnswers({ poll_media: { text: 'foo' } }).setQuestion({ text: 'foo' })); | ||
|
||
expect(message.toJSON()).toStrictEqual({ | ||
content: 'foo', | ||
nonce: 123, | ||
tts: true, | ||
embeds: [{ title: 'foo', description: 'bar', author: undefined, fields: [], footer: undefined }], | ||
allowed_mentions: { parse: ['roles'], roles: ['123'] }, | ||
message_reference: { channel_id: '123', message_id: '123' }, | ||
components: [ | ||
{ | ||
type: 1, | ||
components: [{ type: 2, custom_id: 'abc', label: 'def', style: 1 }], | ||
}, | ||
], | ||
sticker_ids: ['123', '456'], | ||
attachments: [{ id: 'hi!', filename: 'abc' }], | ||
flags: 64, | ||
enforce_nonce: false, | ||
poll: { | ||
question: { text: 'foo' }, | ||
answers: [{ poll_media: { text: 'foo' } }], | ||
}, | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
import type { JSONEncodable } from '@discordjs/util'; | ||
import type { AllowedMentionsTypes, APIAllowedMentions, Snowflake } from 'discord-api-types/v10'; | ||
import { normalizeArray, type RestOrArray } from '../util/normalizeArray.js'; | ||
import { validate } from '../util/validation.js'; | ||
import { allowedMentionPredicate } from './Assertions.js'; | ||
|
||
/** | ||
* A builder that creates API-compatible JSON data for allowed mentions. | ||
*/ | ||
export class AllowedMentionsBuilder implements JSONEncodable<APIAllowedMentions> { | ||
private readonly data: Partial<APIAllowedMentions>; | ||
|
||
/** | ||
* Creates new allowed mention builder from API data. | ||
* | ||
* @param data - The API data to create this attachment with | ||
*/ | ||
public constructor(data: Partial<APIAllowedMentions> = {}) { | ||
this.data = structuredClone(data); | ||
} | ||
|
||
/** | ||
* Sets the types of mentions to parse from the content. | ||
* | ||
* @param parse - The types of mentions to parse from the content | ||
*/ | ||
public setParse(...parse: RestOrArray<AllowedMentionsTypes>): this { | ||
this.data.parse = normalizeArray(parse); | ||
return this; | ||
} | ||
|
||
/** | ||
* Clear the types of mentions to parse from the content. | ||
*/ | ||
public clearParse(): this { | ||
this.data.parse = []; | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the roles to mention. | ||
* | ||
* @param roles - The roles to mention | ||
*/ | ||
public setRoles(...roles: RestOrArray<Snowflake>): this { | ||
this.data.roles = normalizeArray(roles); | ||
return this; | ||
} | ||
|
||
/** | ||
* Adds roles to mention. | ||
* | ||
* @param roles - The roles to mention | ||
*/ | ||
public addRoles(...roles: RestOrArray<Snowflake>): this { | ||
this.data.roles ??= []; | ||
this.data.roles.push(...normalizeArray(roles)); | ||
|
||
return this; | ||
} | ||
|
||
/** | ||
* Removes, replaces, or inserts roles. | ||
* | ||
* @remarks | ||
* This method behaves similarly | ||
* to {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice | Array.prototype.splice()}. | ||
* | ||
* It's useful for modifying and adjusting order of the already-existing roles. | ||
* @example | ||
* Remove the first role: | ||
* ```ts | ||
* allowedMentions.spliceRoles(0, 1); | ||
* ``` | ||
* @example | ||
* Remove the first n role: | ||
* ```ts | ||
* const n = 4; | ||
* allowedMentions.spliceRoles(0, n); | ||
* ``` | ||
* @example | ||
* Remove the last role: | ||
* ```ts | ||
* allowedMentions.spliceRoles(-1, 1); | ||
* ``` | ||
* @param index - The index to start at | ||
* @param deleteCount - The number of roles to remove | ||
* @param roles - The replacing role IDs | ||
*/ | ||
public spliceRoles(index: number, deleteCount: number, ...roles: RestOrArray<Snowflake>): this { | ||
this.data.roles ??= []; | ||
this.data.roles.splice(index, deleteCount, ...normalizeArray(roles)); | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the users to mention. | ||
* | ||
* @param users - The users to mention | ||
*/ | ||
public setUsers(...users: RestOrArray<Snowflake>): this { | ||
this.data.users = normalizeArray(users); | ||
return this; | ||
} | ||
|
||
/** | ||
* Adds users to mention. | ||
* | ||
* @param users - The users to mention | ||
*/ | ||
public addUsers(...users: RestOrArray<Snowflake>): this { | ||
this.data.users ??= []; | ||
this.data.users.push(...normalizeArray(users)); | ||
return this; | ||
} | ||
|
||
/** | ||
* Removes, replaces, or inserts users. | ||
* | ||
* @remarks | ||
* This method behaves similarly | ||
* to {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice | Array.prototype.splice()}. | ||
* | ||
* It's useful for modifying and adjusting order of the already-existing users. | ||
* @example | ||
* Remove the first user: | ||
* ```ts | ||
* allowedMentions.spliceUsers(0, 1); | ||
* ``` | ||
* @example | ||
* Remove the first n user: | ||
* ```ts | ||
* const n = 4; | ||
* allowedMentions.spliceUsers(0, n); | ||
* ``` | ||
* @example | ||
* Remove the last user: | ||
* ```ts | ||
* allowedMentions.spliceUsers(-1, 1); | ||
* ``` | ||
* @param index - The index to start at | ||
* @param deleteCount - The number of users to remove | ||
* @param users - The replacing user IDs | ||
*/ | ||
public spliceUsers(index: number, deleteCount: number, ...users: RestOrArray<Snowflake>): this { | ||
this.data.users ??= []; | ||
this.data.users.splice(index, deleteCount, ...normalizeArray(users)); | ||
return this; | ||
} | ||
|
||
/** | ||
* For replies, sets whether to mention the author of the message being replied to | ||
*/ | ||
public setRepliedUser(repliedUser = true): this { | ||
this.data.replied_user = repliedUser; | ||
return this; | ||
} | ||
|
||
/** | ||
* Serializes this builder to API-compatible JSON data. | ||
* | ||
* Note that by disabling validation, there is no guarantee that the resulting object will be valid. | ||
* | ||
* @param validationOverride - Force validation to run/not run regardless of your global preference | ||
*/ | ||
public toJSON(validationOverride?: boolean): APIAllowedMentions { | ||
const clone = structuredClone(this.data); | ||
validate(allowedMentionPredicate, clone, validationOverride); | ||
|
||
return clone as APIAllowedMentions; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.