@ovencord/discord.js 14.16.3
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.
- package/LICENSE +191 -0
- package/README.md +148 -0
- package/package.json +73 -0
- package/src/client/Client.ts +967 -0
- package/src/client/actions/Action.ts +141 -0
- package/src/client/actions/ActionsManager.ts +138 -0
- package/src/client/actions/ChannelCreate.ts +21 -0
- package/src/client/actions/ChannelDelete.ts +20 -0
- package/src/client/actions/ChannelUpdate.ts +38 -0
- package/src/client/actions/GuildChannelsPositionUpdate.ts +17 -0
- package/src/client/actions/GuildEmojiCreate.ts +17 -0
- package/src/client/actions/GuildEmojiDelete.ts +16 -0
- package/src/client/actions/GuildEmojiUpdate.ts +17 -0
- package/src/client/actions/GuildEmojisUpdate.ts +30 -0
- package/src/client/actions/GuildMemberRemove.ts +29 -0
- package/src/client/actions/GuildMemberUpdate.ts +41 -0
- package/src/client/actions/GuildRoleCreate.ts +23 -0
- package/src/client/actions/GuildRoleDelete.ts +26 -0
- package/src/client/actions/GuildRolesPositionUpdate.ts +17 -0
- package/src/client/actions/GuildScheduledEventDelete.ts +28 -0
- package/src/client/actions/GuildScheduledEventUserAdd.ts +29 -0
- package/src/client/actions/GuildScheduledEventUserRemove.ts +29 -0
- package/src/client/actions/GuildSoundboardSoundDelete.ts +26 -0
- package/src/client/actions/GuildStickerCreate.ts +17 -0
- package/src/client/actions/GuildStickerDelete.ts +16 -0
- package/src/client/actions/GuildStickerUpdate.ts +17 -0
- package/src/client/actions/GuildStickersUpdate.ts +30 -0
- package/src/client/actions/GuildUpdate.ts +30 -0
- package/src/client/actions/InteractionCreate.ts +104 -0
- package/src/client/actions/MessageCreate.ts +38 -0
- package/src/client/actions/MessageDelete.ts +29 -0
- package/src/client/actions/MessageDeleteBulk.ts +45 -0
- package/src/client/actions/MessagePollVoteAdd.ts +37 -0
- package/src/client/actions/MessagePollVoteRemove.ts +35 -0
- package/src/client/actions/MessageReactionAdd.ts +68 -0
- package/src/client/actions/MessageReactionRemove.ts +47 -0
- package/src/client/actions/MessageReactionRemoveAll.ts +30 -0
- package/src/client/actions/MessageReactionRemoveEmoji.ts +25 -0
- package/src/client/actions/MessageUpdate.ts +22 -0
- package/src/client/actions/StageInstanceCreate.ts +25 -0
- package/src/client/actions/StageInstanceDelete.ts +28 -0
- package/src/client/actions/StageInstanceUpdate.ts +27 -0
- package/src/client/actions/ThreadCreate.ts +22 -0
- package/src/client/actions/ThreadMembersUpdate.ts +45 -0
- package/src/client/actions/TypingStart.ts +26 -0
- package/src/client/actions/UserUpdate.ts +33 -0
- package/src/client/voice/ClientVoiceManager.ts +46 -0
- package/src/client/websocket/handlers/APPLICATION_COMMAND_PERMISSIONS_UPDATE.ts +19 -0
- package/src/client/websocket/handlers/AUTO_MODERATION_ACTION_EXECUTION.ts +17 -0
- package/src/client/websocket/handlers/AUTO_MODERATION_RULE_CREATE.ts +18 -0
- package/src/client/websocket/handlers/AUTO_MODERATION_RULE_DELETE.ts +21 -0
- package/src/client/websocket/handlers/AUTO_MODERATION_RULE_UPDATE.ts +20 -0
- package/src/client/websocket/handlers/CHANNEL_CREATE.ts +4 -0
- package/src/client/websocket/handlers/CHANNEL_DELETE.ts +4 -0
- package/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.ts +22 -0
- package/src/client/websocket/handlers/CHANNEL_UPDATE.ts +16 -0
- package/src/client/websocket/handlers/ENTITLEMENT_CREATE.ts +14 -0
- package/src/client/websocket/handlers/ENTITLEMENT_DELETE.ts +18 -0
- package/src/client/websocket/handlers/ENTITLEMENT_UPDATE.ts +16 -0
- package/src/client/websocket/handlers/GUILD_AUDIT_LOG_ENTRY_CREATE.ts +19 -0
- package/src/client/websocket/handlers/GUILD_BAN_ADD.ts +15 -0
- package/src/client/websocket/handlers/GUILD_BAN_REMOVE.ts +20 -0
- package/src/client/websocket/handlers/GUILD_CREATE.ts +34 -0
- package/src/client/websocket/handlers/GUILD_DELETE.ts +36 -0
- package/src/client/websocket/handlers/GUILD_EMOJIS_UPDATE.ts +4 -0
- package/src/client/websocket/handlers/GUILD_INTEGRATIONS_UPDATE.ts +15 -0
- package/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.ts +40 -0
- package/src/client/websocket/handlers/GUILD_MEMBER_ADD.ts +17 -0
- package/src/client/websocket/handlers/GUILD_MEMBER_REMOVE.ts +4 -0
- package/src/client/websocket/handlers/GUILD_MEMBER_UPDATE.ts +4 -0
- package/src/client/websocket/handlers/GUILD_ROLE_CREATE.ts +4 -0
- package/src/client/websocket/handlers/GUILD_ROLE_DELETE.ts +4 -0
- package/src/client/websocket/handlers/GUILD_ROLE_UPDATE.ts +21 -0
- package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_CREATE.ts +17 -0
- package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_DELETE.ts +4 -0
- package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_UPDATE.ts +19 -0
- package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_USER_ADD.ts +4 -0
- package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_USER_REMOVE.ts +4 -0
- package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUNDS_UPDATE.ts +24 -0
- package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_CREATE.ts +18 -0
- package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_DELETE.ts +4 -0
- package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_UPDATE.ts +20 -0
- package/src/client/websocket/handlers/GUILD_STICKERS_UPDATE.ts +4 -0
- package/src/client/websocket/handlers/GUILD_UPDATE.ts +4 -0
- package/src/client/websocket/handlers/INTERACTION_CREATE.ts +4 -0
- package/src/client/websocket/handlers/INVITE_CREATE.ts +20 -0
- package/src/client/websocket/handlers/INVITE_DELETE.ts +23 -0
- package/src/client/websocket/handlers/MESSAGE_CREATE.ts +4 -0
- package/src/client/websocket/handlers/MESSAGE_DELETE.ts +4 -0
- package/src/client/websocket/handlers/MESSAGE_DELETE_BULK.ts +4 -0
- package/src/client/websocket/handlers/MESSAGE_POLL_VOTE_ADD.ts +4 -0
- package/src/client/websocket/handlers/MESSAGE_POLL_VOTE_REMOVE.ts +4 -0
- package/src/client/websocket/handlers/MESSAGE_REACTION_ADD.ts +4 -0
- package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE.ts +4 -0
- package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_ALL.ts +4 -0
- package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.ts +4 -0
- package/src/client/websocket/handlers/MESSAGE_UPDATE.ts +16 -0
- package/src/client/websocket/handlers/PRESENCE_UPDATE.ts +42 -0
- package/src/client/websocket/handlers/RATE_LIMITED.ts +23 -0
- package/src/client/websocket/handlers/READY.ts +29 -0
- package/src/client/websocket/handlers/SOUNDBOARD_SOUNDS.ts +24 -0
- package/src/client/websocket/handlers/STAGE_INSTANCE_CREATE.ts +4 -0
- package/src/client/websocket/handlers/STAGE_INSTANCE_DELETE.ts +4 -0
- package/src/client/websocket/handlers/STAGE_INSTANCE_UPDATE.ts +4 -0
- package/src/client/websocket/handlers/SUBSCRIPTION_CREATE.ts +14 -0
- package/src/client/websocket/handlers/SUBSCRIPTION_DELETE.ts +16 -0
- package/src/client/websocket/handlers/SUBSCRIPTION_UPDATE.ts +16 -0
- package/src/client/websocket/handlers/THREAD_CREATE.ts +4 -0
- package/src/client/websocket/handlers/THREAD_DELETE.ts +17 -0
- package/src/client/websocket/handlers/THREAD_LIST_SYNC.ts +50 -0
- package/src/client/websocket/handlers/THREAD_MEMBERS_UPDATE.ts +4 -0
- package/src/client/websocket/handlers/THREAD_MEMBER_UPDATE.ts +25 -0
- package/src/client/websocket/handlers/THREAD_UPDATE.ts +16 -0
- package/src/client/websocket/handlers/TYPING_START.ts +4 -0
- package/src/client/websocket/handlers/USER_UPDATE.ts +4 -0
- package/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.ts +16 -0
- package/src/client/websocket/handlers/VOICE_SERVER_UPDATE.ts +5 -0
- package/src/client/websocket/handlers/VOICE_STATE_UPDATE.ts +37 -0
- package/src/client/websocket/handlers/WEBHOOKS_UPDATE.ts +16 -0
- package/src/client/websocket/handlers/index.ts +74 -0
- package/src/errors/DJSError.ts +50 -0
- package/src/errors/ErrorCodes.ts +277 -0
- package/src/errors/Messages.ts +155 -0
- package/src/errors/index.ts +6 -0
- package/src/index.ts +241 -0
- package/src/managers/ApplicationCommandManager.ts +303 -0
- package/src/managers/ApplicationCommandPermissionsManager.ts +453 -0
- package/src/managers/ApplicationEmojiManager.ts +149 -0
- package/src/managers/AutoModerationRuleManager.ts +307 -0
- package/src/managers/BaseManager.ts +13 -0
- package/src/managers/CachedManager.ts +56 -0
- package/src/managers/CategoryChannelChildManager.ts +81 -0
- package/src/managers/ChannelManager.ts +194 -0
- package/src/managers/DMMessageManager.ts +15 -0
- package/src/managers/DataManager.ts +38 -0
- package/src/managers/EntitlementManager.ts +182 -0
- package/src/managers/GuildApplicationCommandManager.ts +29 -0
- package/src/managers/GuildBanManager.ts +221 -0
- package/src/managers/GuildChannelManager.ts +552 -0
- package/src/managers/GuildEmojiManager.ts +262 -0
- package/src/managers/GuildEmojiRoleManager.ts +134 -0
- package/src/managers/GuildForumThreadManager.ts +84 -0
- package/src/managers/GuildInviteManager.ts +236 -0
- package/src/managers/GuildManager.ts +265 -0
- package/src/managers/GuildMemberManager.ts +619 -0
- package/src/managers/GuildMemberRoleManager.ts +230 -0
- package/src/managers/GuildMessageManager.ts +31 -0
- package/src/managers/GuildScheduledEventManager.ts +330 -0
- package/src/managers/GuildSoundboardSoundManager.ts +157 -0
- package/src/managers/GuildStickerManager.ts +192 -0
- package/src/managers/GuildTextThreadManager.ts +91 -0
- package/src/managers/MessageManager.ts +352 -0
- package/src/managers/PartialGroupDMMessageManager.ts +15 -0
- package/src/managers/PermissionOverwriteManager.ts +174 -0
- package/src/managers/PollAnswerVoterManager.ts +59 -0
- package/src/managers/PresenceManager.ts +60 -0
- package/src/managers/ReactionManager.ts +72 -0
- package/src/managers/ReactionUserManager.ts +82 -0
- package/src/managers/RoleManager.ts +432 -0
- package/src/managers/StageInstanceManager.ts +166 -0
- package/src/managers/SubscriptionManager.ts +83 -0
- package/src/managers/ThreadManager.ts +210 -0
- package/src/managers/ThreadMemberManager.ts +194 -0
- package/src/managers/UserManager.ts +139 -0
- package/src/managers/VoiceStateManager.ts +61 -0
- package/src/sharding/Shard.ts +513 -0
- package/src/sharding/ShardClientUtil.ts +293 -0
- package/src/sharding/ShardingManager.ts +374 -0
- package/src/structures/ActionRow.ts +31 -0
- package/src/structures/AnnouncementChannel.ts +25 -0
- package/src/structures/AnonymousGuild.ts +110 -0
- package/src/structures/ApplicationCommand.ts +675 -0
- package/src/structures/ApplicationEmoji.ts +189 -0
- package/src/structures/ApplicationRoleConnectionMetadata.ts +54 -0
- package/src/structures/Attachment.ts +189 -0
- package/src/structures/AuthorizingIntegrationOwners.ts +63 -0
- package/src/structures/AutoModerationActionExecution.ts +138 -0
- package/src/structures/AutoModerationRule.ts +325 -0
- package/src/structures/AutocompleteInteraction.ts +115 -0
- package/src/structures/Base.ts +37 -0
- package/src/structures/BaseChannel.ts +188 -0
- package/src/structures/BaseGuild.ts +134 -0
- package/src/structures/BaseGuildEmoji.ts +113 -0
- package/src/structures/BaseGuildTextChannel.ts +230 -0
- package/src/structures/BaseGuildVoiceChannel.ts +270 -0
- package/src/structures/BaseInteraction.ts +393 -0
- package/src/structures/BaseInvite.ts +192 -0
- package/src/structures/BaseSelectMenuComponent.ts +58 -0
- package/src/structures/ButtonComponent.ts +68 -0
- package/src/structures/ButtonInteraction.ts +8 -0
- package/src/structures/CategoryChannel.ts +46 -0
- package/src/structures/ChannelSelectMenuComponent.ts +18 -0
- package/src/structures/ChannelSelectMenuInteraction.ts +34 -0
- package/src/structures/ChatInputCommandInteraction.ts +43 -0
- package/src/structures/ClientApplication.ts +470 -0
- package/src/structures/ClientPresence.ts +87 -0
- package/src/structures/ClientUser.ts +219 -0
- package/src/structures/CommandInteraction.ts +193 -0
- package/src/structures/CommandInteractionOptionResolver.ts +336 -0
- package/src/structures/Component.ts +59 -0
- package/src/structures/ContainerComponent.ts +63 -0
- package/src/structures/ContextMenuCommandInteraction.ts +68 -0
- package/src/structures/DMChannel.ts +148 -0
- package/src/structures/DirectoryChannel.ts +40 -0
- package/src/structures/Embed.ts +251 -0
- package/src/structures/Emoji.ts +61 -0
- package/src/structures/Entitlement.ts +206 -0
- package/src/structures/FileComponent.ts +41 -0
- package/src/structures/ForumChannel.ts +31 -0
- package/src/structures/GroupDMInvite.ts +34 -0
- package/src/structures/Guild.ts +1605 -0
- package/src/structures/GuildAuditLogs.ts +99 -0
- package/src/structures/GuildAuditLogsEntry.ts +557 -0
- package/src/structures/GuildBan.ts +65 -0
- package/src/structures/GuildChannel.ts +515 -0
- package/src/structures/GuildEmoji.ts +159 -0
- package/src/structures/GuildInvite.ts +233 -0
- package/src/structures/GuildMember.ts +643 -0
- package/src/structures/GuildOnboarding.ts +73 -0
- package/src/structures/GuildOnboardingPrompt.ts +93 -0
- package/src/structures/GuildOnboardingPromptOption.ts +100 -0
- package/src/structures/GuildPreview.ts +218 -0
- package/src/structures/GuildPreviewEmoji.ts +28 -0
- package/src/structures/GuildScheduledEvent.ts +593 -0
- package/src/structures/GuildTemplate.ts +229 -0
- package/src/structures/Integration.ts +257 -0
- package/src/structures/IntegrationApplication.ts +84 -0
- package/src/structures/InteractionCallback.ts +86 -0
- package/src/structures/InteractionCallbackResource.ts +57 -0
- package/src/structures/InteractionCallbackResponse.ts +35 -0
- package/src/structures/InteractionCollector.ts +260 -0
- package/src/structures/InteractionWebhook.ts +65 -0
- package/src/structures/InviteGuild.ts +22 -0
- package/src/structures/LabelComponent.ts +51 -0
- package/src/structures/MediaChannel.ts +8 -0
- package/src/structures/MediaGalleryComponent.ts +31 -0
- package/src/structures/MediaGalleryItem.ts +54 -0
- package/src/structures/MentionableSelectMenuComponent.ts +8 -0
- package/src/structures/MentionableSelectMenuInteraction.ts +76 -0
- package/src/structures/Message.ts +1202 -0
- package/src/structures/MessageCollector.ts +155 -0
- package/src/structures/MessageComponentInteraction.ts +132 -0
- package/src/structures/MessageContextMenuCommandInteraction.ts +18 -0
- package/src/structures/MessageMentions.ts +327 -0
- package/src/structures/MessagePayload.ts +325 -0
- package/src/structures/MessageReaction.ts +219 -0
- package/src/structures/ModalComponentResolver.ts +237 -0
- package/src/structures/ModalSubmitInteraction.ts +260 -0
- package/src/structures/OAuth2Guild.ts +30 -0
- package/src/structures/PartialGroupDMChannel.ts +151 -0
- package/src/structures/PermissionOverwrites.ts +222 -0
- package/src/structures/Poll.ts +195 -0
- package/src/structures/PollAnswer.ts +100 -0
- package/src/structures/Presence.ts +448 -0
- package/src/structures/PrimaryEntryPointCommandInteraction.ts +8 -0
- package/src/structures/ReactionCollector.ts +245 -0
- package/src/structures/ReactionEmoji.ts +30 -0
- package/src/structures/Role.ts +543 -0
- package/src/structures/RoleSelectMenuComponent.ts +8 -0
- package/src/structures/RoleSelectMenuInteraction.ts +34 -0
- package/src/structures/SKU.ts +62 -0
- package/src/structures/SectionComponent.ts +44 -0
- package/src/structures/SeparatorComponent.ts +29 -0
- package/src/structures/SoundboardSound.ts +176 -0
- package/src/structures/StageChannel.ts +118 -0
- package/src/structures/StageInstance.ts +173 -0
- package/src/structures/Sticker.ts +300 -0
- package/src/structures/StickerPack.ts +111 -0
- package/src/structures/StringSelectMenuComponent.ts +18 -0
- package/src/structures/StringSelectMenuInteraction.ts +21 -0
- package/src/structures/Subscription.ts +138 -0
- package/src/structures/Team.ts +131 -0
- package/src/structures/TeamMember.ts +77 -0
- package/src/structures/TextChannel.ts +33 -0
- package/src/structures/TextDisplayComponent.ts +18 -0
- package/src/structures/TextInputComponent.ts +28 -0
- package/src/structures/ThreadChannel.ts +680 -0
- package/src/structures/ThreadMember.ts +125 -0
- package/src/structures/ThreadOnlyChannel.ts +276 -0
- package/src/structures/ThumbnailComponent.ts +51 -0
- package/src/structures/Typing.ts +81 -0
- package/src/structures/UnfurledMediaItem.ts +33 -0
- package/src/structures/User.ts +511 -0
- package/src/structures/UserContextMenuCommandInteraction.ts +28 -0
- package/src/structures/UserSelectMenuComponent.ts +8 -0
- package/src/structures/UserSelectMenuInteraction.ts +54 -0
- package/src/structures/VoiceChannel.ts +119 -0
- package/src/structures/VoiceChannelEffect.ts +92 -0
- package/src/structures/VoiceRegion.ts +52 -0
- package/src/structures/VoiceState.ts +346 -0
- package/src/structures/Webhook.ts +526 -0
- package/src/structures/WelcomeChannel.ts +67 -0
- package/src/structures/WelcomeScreen.ts +53 -0
- package/src/structures/Widget.ts +110 -0
- package/src/structures/WidgetMember.ts +124 -0
- package/src/structures/interfaces/Application.ts +179 -0
- package/src/structures/interfaces/Collector.ts +372 -0
- package/src/structures/interfaces/InteractionResponses.ts +384 -0
- package/src/structures/interfaces/TextBasedChannel.ts +430 -0
- package/src/util/APITypes.ts +690 -0
- package/src/util/ActivityFlagsBitField.ts +26 -0
- package/src/util/ApplicationFlagsBitField.ts +43 -0
- package/src/util/AttachmentFlagsBitField.ts +26 -0
- package/src/util/BitField.ts +178 -0
- package/src/util/ChannelFlagsBitField.ts +43 -0
- package/src/util/Channels.ts +165 -0
- package/src/util/Colors.ts +72 -0
- package/src/util/Components.ts +285 -0
- package/src/util/Constants.ts +251 -0
- package/src/util/DataResolver.ts +146 -0
- package/src/util/Enums.ts +10 -0
- package/src/util/Events.ts +178 -0
- package/src/util/GuildMemberFlagsBitField.ts +43 -0
- package/src/util/IntentsBitField.ts +35 -0
- package/src/util/InviteFlagsBitField.ts +26 -0
- package/src/util/Invites.ts +27 -0
- package/src/util/LimitedCollection.ts +73 -0
- package/src/util/MessageFlagsBitField.ts +43 -0
- package/src/util/Options.ts +215 -0
- package/src/util/Partials.ts +50 -0
- package/src/util/PermissionsBitField.ts +113 -0
- package/src/util/RoleFlagsBitField.ts +26 -0
- package/src/util/SKUFlagsBitField.ts +26 -0
- package/src/util/ShardEvents.ts +26 -0
- package/src/util/Status.ts +16 -0
- package/src/util/Sweepers.ts +532 -0
- package/src/util/Symbols.ts +1 -0
- package/src/util/SystemChannelFlagsBitField.ts +45 -0
- package/src/util/ThreadMemberFlagsBitField.ts +33 -0
- package/src/util/Transformers.ts +123 -0
- package/src/util/UserFlagsBitField.ts +33 -0
- package/src/util/Util.ts +519 -0
|
@@ -0,0 +1,1202 @@
|
|
|
1
|
+
import { Collection } from '@ovencord/collection';
|
|
2
|
+
import { messageLink } from '@ovencord/formatters';
|
|
3
|
+
import { DiscordSnowflake } from '@sapphire/snowflake';
|
|
4
|
+
import { InteractionType,
|
|
5
|
+
ChannelType,
|
|
6
|
+
MessageType,
|
|
7
|
+
MessageFlags,
|
|
8
|
+
MessageReferenceType,
|
|
9
|
+
PermissionFlagsBits,
|
|
10
|
+
} from 'discord-api-types/v10';
|
|
11
|
+
import { DiscordjsError, ErrorCodes } from '../errors/index.js';
|
|
12
|
+
import { ReactionManager } from '../managers/ReactionManager.js';
|
|
13
|
+
import { createComponent, findComponentByCustomId } from '../util/Components.js';
|
|
14
|
+
import { NonSystemMessageTypes, MaxBulkDeletableMessageAge, UndeletableMessageTypes } from '../util/Constants.js';
|
|
15
|
+
import { MessageFlagsBitField } from '../util/MessageFlagsBitField.js';
|
|
16
|
+
import { PermissionsBitField } from '../util/PermissionsBitField.js';
|
|
17
|
+
import { _transformAPIMessageInteractionMetadata } from '../util/Transformers.js';
|
|
18
|
+
import { cleanContent, resolvePartialEmoji, transformResolved } from '../util/Util.js';
|
|
19
|
+
import { Attachment } from './Attachment.js';
|
|
20
|
+
import { Base } from './Base.js';
|
|
21
|
+
import { ClientApplication } from './ClientApplication.js';
|
|
22
|
+
import { Embed } from './Embed.js';
|
|
23
|
+
import { InteractionCollector } from './InteractionCollector.js';
|
|
24
|
+
import { MessageMentions } from './MessageMentions.js';
|
|
25
|
+
import { MessagePayload } from './MessagePayload.js';
|
|
26
|
+
import { Poll } from './Poll.js';
|
|
27
|
+
import { ReactionCollector } from './ReactionCollector.js';
|
|
28
|
+
import { Sticker } from './Sticker.js';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Represents a message on Discord.
|
|
32
|
+
*
|
|
33
|
+
* @extends {Base}
|
|
34
|
+
*/
|
|
35
|
+
export class Message extends Base {
|
|
36
|
+
public client: any;
|
|
37
|
+
public channelId: any;
|
|
38
|
+
public guildId: any;
|
|
39
|
+
public id: any;
|
|
40
|
+
public createdTimestamp: any;
|
|
41
|
+
public type: any;
|
|
42
|
+
public system: any;
|
|
43
|
+
public content: any;
|
|
44
|
+
public author: any;
|
|
45
|
+
public pinned: any;
|
|
46
|
+
public tts: any;
|
|
47
|
+
public nonce: any;
|
|
48
|
+
public embeds: any;
|
|
49
|
+
public components: any;
|
|
50
|
+
public attachments: any;
|
|
51
|
+
public stickers: any;
|
|
52
|
+
public position: any;
|
|
53
|
+
public roleSubscriptionData: any;
|
|
54
|
+
public resolved: any;
|
|
55
|
+
public editedTimestamp: any;
|
|
56
|
+
public reactions: any;
|
|
57
|
+
public mentions: any;
|
|
58
|
+
public webhookId: any;
|
|
59
|
+
public groupActivityApplication: any;
|
|
60
|
+
public applicationId: any;
|
|
61
|
+
public activity: any;
|
|
62
|
+
public flags: any;
|
|
63
|
+
public reference: any;
|
|
64
|
+
public interactionMetadata: any;
|
|
65
|
+
public poll: any;
|
|
66
|
+
public messageSnapshots: any;
|
|
67
|
+
public call: any;
|
|
68
|
+
constructor(client, data) {
|
|
69
|
+
super(client);
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The id of the channel the message was sent in
|
|
73
|
+
*
|
|
74
|
+
* @type {Snowflake}
|
|
75
|
+
*/
|
|
76
|
+
this.channelId = data.channel_id;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The id of the guild the message was sent in, if any
|
|
80
|
+
*
|
|
81
|
+
* @type {?Snowflake}
|
|
82
|
+
*/
|
|
83
|
+
this.guildId = data.guild_id ?? this.channel?.guild?.id ?? null;
|
|
84
|
+
|
|
85
|
+
this._patch(data);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
_patch(data) {
|
|
89
|
+
/**
|
|
90
|
+
* The message's id
|
|
91
|
+
*
|
|
92
|
+
* @type {Snowflake}
|
|
93
|
+
*/
|
|
94
|
+
this.id = data.id;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The timestamp the message was sent at
|
|
98
|
+
*
|
|
99
|
+
* @type {number}
|
|
100
|
+
*/
|
|
101
|
+
this.createdTimestamp = DiscordSnowflake.timestampFrom(this.id);
|
|
102
|
+
|
|
103
|
+
if ('type' in data) {
|
|
104
|
+
/**
|
|
105
|
+
* The type of the message
|
|
106
|
+
*
|
|
107
|
+
* @type {?MessageType}
|
|
108
|
+
*/
|
|
109
|
+
this.type = data.type;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Whether or not this message was sent by Discord, not actually a user (e.g. pin notifications)
|
|
113
|
+
*
|
|
114
|
+
* @type {?boolean}
|
|
115
|
+
*/
|
|
116
|
+
this.system = !NonSystemMessageTypes.includes(this.type);
|
|
117
|
+
} else {
|
|
118
|
+
this.system ??= null;
|
|
119
|
+
this.type ??= null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if ('content' in data) {
|
|
123
|
+
/**
|
|
124
|
+
* The content of the message.
|
|
125
|
+
* <info>This property requires the {@link GatewayIntentBits.MessageContent} privileged intent
|
|
126
|
+
* in a guild for messages that do not mention the client.</info>
|
|
127
|
+
*
|
|
128
|
+
* @type {?string}
|
|
129
|
+
*/
|
|
130
|
+
this.content = data.content;
|
|
131
|
+
} else {
|
|
132
|
+
this.content ??= null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if ('author' in data) {
|
|
136
|
+
/**
|
|
137
|
+
* The author of the message
|
|
138
|
+
*
|
|
139
|
+
* @type {?User}
|
|
140
|
+
*/
|
|
141
|
+
this.author = this.client.users._add(data.author, !data.webhook_id);
|
|
142
|
+
} else {
|
|
143
|
+
this.author ??= null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if ('pinned' in data) {
|
|
147
|
+
/**
|
|
148
|
+
* Whether or not this message is pinned
|
|
149
|
+
*
|
|
150
|
+
* @type {?boolean}
|
|
151
|
+
*/
|
|
152
|
+
this.pinned = Boolean(data.pinned);
|
|
153
|
+
} else {
|
|
154
|
+
this.pinned ??= null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if ('tts' in data) {
|
|
158
|
+
/**
|
|
159
|
+
* Whether or not the message was Text-To-Speech
|
|
160
|
+
*
|
|
161
|
+
* @type {?boolean}
|
|
162
|
+
*/
|
|
163
|
+
this.tts = data.tts;
|
|
164
|
+
} else {
|
|
165
|
+
this.tts ??= null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if ('nonce' in data) {
|
|
169
|
+
/**
|
|
170
|
+
* A random number or string used for checking message delivery
|
|
171
|
+
* <warn>This is only received after the message was sent successfully, and
|
|
172
|
+
* lost if re-fetched</warn>
|
|
173
|
+
*
|
|
174
|
+
* @type {?string}
|
|
175
|
+
*/
|
|
176
|
+
this.nonce = data.nonce;
|
|
177
|
+
} else {
|
|
178
|
+
this.nonce ??= null;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if ('embeds' in data) {
|
|
182
|
+
/**
|
|
183
|
+
* An array of embeds in the message - e.g. YouTube Player.
|
|
184
|
+
* <info>This property requires the {@link GatewayIntentBits.MessageContent} privileged intent
|
|
185
|
+
* in a guild for messages that do not mention the client.</info>
|
|
186
|
+
*
|
|
187
|
+
* @type {Embed[]}
|
|
188
|
+
*/
|
|
189
|
+
this.embeds = data.embeds.map(embed => new Embed(embed));
|
|
190
|
+
} else {
|
|
191
|
+
this.embeds = this.embeds?.slice() ?? [];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if ('components' in data) {
|
|
195
|
+
/**
|
|
196
|
+
* An array of components in the message.
|
|
197
|
+
* <info>This property requires the {@link GatewayIntentBits.MessageContent} privileged intent
|
|
198
|
+
* in a guild for messages that do not mention the client.</info>
|
|
199
|
+
*
|
|
200
|
+
* @type {Component[]}
|
|
201
|
+
*/
|
|
202
|
+
this.components = data.components.map(component => createComponent(component));
|
|
203
|
+
} else {
|
|
204
|
+
this.components = this.components?.slice() ?? [];
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if ('attachments' in data) {
|
|
208
|
+
/**
|
|
209
|
+
* A collection of attachments in the message - e.g. Pictures - mapped by their ids.
|
|
210
|
+
* <info>This property requires the {@link GatewayIntentBits.MessageContent} privileged intent
|
|
211
|
+
* in a guild for messages that do not mention the client.</info>
|
|
212
|
+
*
|
|
213
|
+
* @type {Collection<Snowflake, Attachment>}
|
|
214
|
+
*/
|
|
215
|
+
this.attachments = new Collection();
|
|
216
|
+
if (data.attachments) {
|
|
217
|
+
for (const attachment of data.attachments) {
|
|
218
|
+
this.attachments.set(attachment.id, new Attachment(attachment));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
} else {
|
|
222
|
+
this.attachments = new Collection(this.attachments);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if ('sticker_items' in data || 'stickers' in data) {
|
|
226
|
+
/**
|
|
227
|
+
* A collection of stickers in the message
|
|
228
|
+
*
|
|
229
|
+
* @type {Collection<Snowflake, Sticker>}
|
|
230
|
+
*/
|
|
231
|
+
this.stickers = new Collection(
|
|
232
|
+
(data.sticker_items ?? data.stickers)?.map(sticker => [sticker.id, new Sticker(this.client, sticker)]),
|
|
233
|
+
);
|
|
234
|
+
} else {
|
|
235
|
+
this.stickers = new Collection(this.stickers);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if ('position' in data) {
|
|
239
|
+
/**
|
|
240
|
+
* A generally increasing integer (there may be gaps or duplicates) that represents
|
|
241
|
+
* the approximate position of the message in a thread.
|
|
242
|
+
*
|
|
243
|
+
* @type {?number}
|
|
244
|
+
*/
|
|
245
|
+
this.position = data.position;
|
|
246
|
+
} else {
|
|
247
|
+
this.position ??= null;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if ('role_subscription_data' in data) {
|
|
251
|
+
/**
|
|
252
|
+
* Role subscription data found on {@link MessageType.RoleSubscriptionPurchase} messages.
|
|
253
|
+
*
|
|
254
|
+
* @typedef {Object} RoleSubscriptionData
|
|
255
|
+
* @property {Snowflake} roleSubscriptionListingId The id of the SKU and listing the user is subscribed to
|
|
256
|
+
* @property {string} tierName The name of the tier the user is subscribed to
|
|
257
|
+
* @property {number} totalMonthsSubscribed The total number of months the user has been subscribed for
|
|
258
|
+
* @property {boolean} isRenewal Whether this notification is a renewal
|
|
259
|
+
*/
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* The data of the role subscription purchase or renewal.
|
|
263
|
+
* <info>This is present on {@link MessageType.RoleSubscriptionPurchase} messages.</info>
|
|
264
|
+
*
|
|
265
|
+
* @type {?RoleSubscriptionData}
|
|
266
|
+
*/
|
|
267
|
+
this.roleSubscriptionData = {
|
|
268
|
+
roleSubscriptionListingId: data.role_subscription_data.role_subscription_listing_id,
|
|
269
|
+
tierName: data.role_subscription_data.tier_name,
|
|
270
|
+
totalMonthsSubscribed: data.role_subscription_data.total_months_subscribed,
|
|
271
|
+
isRenewal: data.role_subscription_data.is_renewal,
|
|
272
|
+
};
|
|
273
|
+
} else {
|
|
274
|
+
this.roleSubscriptionData ??= null;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if ('resolved' in data) {
|
|
278
|
+
/**
|
|
279
|
+
* Resolved data from auto-populated select menus.
|
|
280
|
+
*
|
|
281
|
+
* @type {?CommandInteractionResolvedData}
|
|
282
|
+
*/
|
|
283
|
+
this.resolved = transformResolved(
|
|
284
|
+
{ client: this.client, guild: this.guild, channel: this.channel },
|
|
285
|
+
data.resolved,
|
|
286
|
+
);
|
|
287
|
+
} else {
|
|
288
|
+
this.resolved ??= null;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Discord sends null if the message has not been edited
|
|
292
|
+
if (data.edited_timestamp) {
|
|
293
|
+
/**
|
|
294
|
+
* The timestamp the message was last edited at (if applicable)
|
|
295
|
+
*
|
|
296
|
+
* @type {?number}
|
|
297
|
+
*/
|
|
298
|
+
this.editedTimestamp = Date.parse(data.edited_timestamp);
|
|
299
|
+
} else {
|
|
300
|
+
this.editedTimestamp ??= null;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if ('reactions' in data) {
|
|
304
|
+
/**
|
|
305
|
+
* A manager of the reactions belonging to this message
|
|
306
|
+
*
|
|
307
|
+
* @type {ReactionManager}
|
|
308
|
+
*/
|
|
309
|
+
this.reactions = new ReactionManager(this);
|
|
310
|
+
if (data.reactions?.length > 0) {
|
|
311
|
+
for (const reaction of data.reactions) {
|
|
312
|
+
this.reactions._add(reaction);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
} else {
|
|
316
|
+
this.reactions ??= new ReactionManager(this);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* All valid mentions that the message contains
|
|
321
|
+
*
|
|
322
|
+
* @type {MessageMentions}
|
|
323
|
+
*/
|
|
324
|
+
this.mentions = new MessageMentions(
|
|
325
|
+
this,
|
|
326
|
+
data.mentions ?? this.mentions?.users,
|
|
327
|
+
data.mention_roles ?? this.mentions?.roles,
|
|
328
|
+
data.mention_everyone ?? this.mentions?.everyone,
|
|
329
|
+
data.mention_channels ?? this.mentions?.crosspostedChannels,
|
|
330
|
+
data.referenced_message?.author ?? this.mentions?.repliedUser,
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
if ('webhook_id' in data) {
|
|
334
|
+
/**
|
|
335
|
+
* The id of the webhook that sent the message, if applicable
|
|
336
|
+
*
|
|
337
|
+
* @type {?Snowflake}
|
|
338
|
+
*/
|
|
339
|
+
this.webhookId = data.webhook_id;
|
|
340
|
+
} else {
|
|
341
|
+
this.webhookId ??= null;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if ('application' in data) {
|
|
345
|
+
/**
|
|
346
|
+
* Supplemental application information for group activities
|
|
347
|
+
*
|
|
348
|
+
* @type {?ClientApplication}
|
|
349
|
+
*/
|
|
350
|
+
this.groupActivityApplication = new ClientApplication(this.client, data.application);
|
|
351
|
+
} else {
|
|
352
|
+
this.groupActivityApplication ??= null;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if ('application_id' in data) {
|
|
356
|
+
/**
|
|
357
|
+
* The id of the application of the interaction that sent this message, if any
|
|
358
|
+
*
|
|
359
|
+
* @type {?Snowflake}
|
|
360
|
+
*/
|
|
361
|
+
this.applicationId = data.application_id;
|
|
362
|
+
} else {
|
|
363
|
+
this.applicationId ??= null;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if ('activity' in data) {
|
|
367
|
+
/**
|
|
368
|
+
* Group activity
|
|
369
|
+
*
|
|
370
|
+
* @type {?MessageActivity}
|
|
371
|
+
*/
|
|
372
|
+
this.activity = {
|
|
373
|
+
partyId: data.activity.party_id,
|
|
374
|
+
type: data.activity.type,
|
|
375
|
+
};
|
|
376
|
+
} else {
|
|
377
|
+
this.activity ??= null;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if ('thread' in data) {
|
|
381
|
+
this.client.channels._add(data.thread, this.guild);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (this.member && data.member) {
|
|
385
|
+
this.member._patch(data.member);
|
|
386
|
+
} else if (data.member && this.guild && this.author) {
|
|
387
|
+
this.guild.members._add(Object.assign(data.member, { user: this.author }));
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if ('flags' in data) {
|
|
391
|
+
/**
|
|
392
|
+
* Flags that are applied to the message
|
|
393
|
+
*
|
|
394
|
+
* @type {Readonly<MessageFlagsBitField>}
|
|
395
|
+
*/
|
|
396
|
+
this.flags = new MessageFlagsBitField(data.flags).freeze();
|
|
397
|
+
} else {
|
|
398
|
+
this.flags = new MessageFlagsBitField(this.flags).freeze();
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Reference data sent in a message that contains ids identifying the referenced message.
|
|
403
|
+
* This can be present in the following types of message:
|
|
404
|
+
* - {@link MessageFlags.Crossposted}
|
|
405
|
+
* - {@link MessageType.ChannelPinnedMessage}
|
|
406
|
+
* - {@link MessageType.ChannelFollowAdd}
|
|
407
|
+
* - {@link MessageType.Reply}
|
|
408
|
+
* - {@link MessageType.ThreadStarterMessage}
|
|
409
|
+
*
|
|
410
|
+
* @see {@link https://discord.com/developers/docs/resources/message#message-object-message-types}
|
|
411
|
+
* @typedef {Object} MessageReference
|
|
412
|
+
* @property {Snowflake} channelId The channel id that was referenced
|
|
413
|
+
* @property {Snowflake|undefined} guildId The guild id that was referenced
|
|
414
|
+
* @property {Snowflake|undefined} messageId The message id that was referenced
|
|
415
|
+
* @property {MessageReferenceType} type The type of message reference
|
|
416
|
+
*/
|
|
417
|
+
|
|
418
|
+
if ('message_reference' in data) {
|
|
419
|
+
/**
|
|
420
|
+
* Message reference data
|
|
421
|
+
*
|
|
422
|
+
* @type {?MessageReference}
|
|
423
|
+
*/
|
|
424
|
+
this.reference = {
|
|
425
|
+
channelId: data.message_reference.channel_id,
|
|
426
|
+
guildId: data.message_reference.guild_id,
|
|
427
|
+
messageId: data.message_reference.message_id,
|
|
428
|
+
type: data.message_reference.type,
|
|
429
|
+
};
|
|
430
|
+
} else {
|
|
431
|
+
this.reference ??= null;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
if (data.referenced_message) {
|
|
435
|
+
this.channel?.messages._add({ guild_id: data.message_reference?.guild_id, ...data.referenced_message });
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
if (data.interaction_metadata) {
|
|
439
|
+
/**
|
|
440
|
+
* Partial data of the interaction that a message is a result of
|
|
441
|
+
*
|
|
442
|
+
* @typedef {Object} MessageInteractionMetadata
|
|
443
|
+
* @property {Snowflake} id The interaction's id
|
|
444
|
+
* @property {InteractionType} type The type of the interaction
|
|
445
|
+
* @property {User} user The user that invoked the interaction
|
|
446
|
+
* @property {AuthorizingIntegrationOwners} authorizingIntegrationOwners
|
|
447
|
+
* Mapping of integration types that the application was authorized for the related user or guild ids
|
|
448
|
+
* @property {?Snowflake} originalResponseMessageId
|
|
449
|
+
* Id of the original response message. Present only on follow-up messages
|
|
450
|
+
* @property {?Snowflake} interactedMessageId
|
|
451
|
+
* Id of the message that contained interactive component.
|
|
452
|
+
* Present only on messages created from component interactions
|
|
453
|
+
* @property {?MessageInteractionMetadata} triggeringInteractionMetadata
|
|
454
|
+
* Metadata for the interaction that was used to open the modal. Present only on modal submit interactions
|
|
455
|
+
*/
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Partial data of the interaction that this message is a result of
|
|
459
|
+
*
|
|
460
|
+
* @type {?MessageInteractionMetadata}
|
|
461
|
+
*/
|
|
462
|
+
this.interactionMetadata = _transformAPIMessageInteractionMetadata(this.client, data.interaction_metadata);
|
|
463
|
+
} else {
|
|
464
|
+
this.interactionMetadata ??= null;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (data.poll) {
|
|
468
|
+
if (this.poll) {
|
|
469
|
+
this.poll._patch(data.poll);
|
|
470
|
+
} else {
|
|
471
|
+
/**
|
|
472
|
+
* The poll that was sent with the message
|
|
473
|
+
*
|
|
474
|
+
* @type {?Poll}
|
|
475
|
+
*/
|
|
476
|
+
this.poll = new Poll(this.client, data.poll, this, this.channel);
|
|
477
|
+
}
|
|
478
|
+
} else {
|
|
479
|
+
this.poll ??= null;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (data.message_snapshots) {
|
|
483
|
+
/**
|
|
484
|
+
* The message snapshots associated with the message reference
|
|
485
|
+
*
|
|
486
|
+
* @type {Collection<Snowflake, Message>}
|
|
487
|
+
*/
|
|
488
|
+
this.messageSnapshots = data.message_snapshots.reduce((coll, snapshot) => {
|
|
489
|
+
const channel = this.client.channels.resolve(this.reference.channelId);
|
|
490
|
+
const snapshotData = {
|
|
491
|
+
...snapshot.message,
|
|
492
|
+
id: this.reference.messageId,
|
|
493
|
+
channel_id: this.reference.channelId,
|
|
494
|
+
guild_id: this.reference.guildId,
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
return coll.set(
|
|
498
|
+
this.reference.messageId,
|
|
499
|
+
channel ? channel.messages._add(snapshotData) : new this.constructor(this.client, snapshotData),
|
|
500
|
+
);
|
|
501
|
+
}, new Collection());
|
|
502
|
+
} else {
|
|
503
|
+
this.messageSnapshots ??= new Collection();
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* A call associated with a message
|
|
508
|
+
*
|
|
509
|
+
* @typedef {Object} MessageCall
|
|
510
|
+
* @property {Readonly<?Date>} endedAt The time the call ended
|
|
511
|
+
* @property {?number} endedTimestamp The timestamp the call ended
|
|
512
|
+
* @property {Snowflake[]} participants The ids of the users that participated in the call
|
|
513
|
+
*/
|
|
514
|
+
|
|
515
|
+
if (data.call) {
|
|
516
|
+
/**
|
|
517
|
+
* The call associated with the message
|
|
518
|
+
*
|
|
519
|
+
* @type {?MessageCall}
|
|
520
|
+
*/
|
|
521
|
+
this.call = {
|
|
522
|
+
endedTimestamp: data.call.ended_timestamp ? Date.parse(data.call.ended_timestamp) : null,
|
|
523
|
+
participants: data.call.participants,
|
|
524
|
+
get endedAt() {
|
|
525
|
+
return this.endedTimestamp && new Date(this.endedTimestamp);
|
|
526
|
+
},
|
|
527
|
+
};
|
|
528
|
+
} else {
|
|
529
|
+
this.call ??= null;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* The channel that the message was sent in
|
|
535
|
+
*
|
|
536
|
+
* @type {TextBasedChannels}
|
|
537
|
+
* @readonly
|
|
538
|
+
*/
|
|
539
|
+
get channel() {
|
|
540
|
+
return this.client.channels.resolve(this.channelId);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Whether or not this message is a partial
|
|
545
|
+
*
|
|
546
|
+
* @type {boolean}
|
|
547
|
+
* @readonly
|
|
548
|
+
*/
|
|
549
|
+
get partial() {
|
|
550
|
+
return typeof this.content !== 'string' || !this.author;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Represents the author of the message as a guild member.
|
|
555
|
+
* Only available if the message comes from a guild where the author is still a member
|
|
556
|
+
*
|
|
557
|
+
* @type {?GuildMember}
|
|
558
|
+
* @readonly
|
|
559
|
+
*/
|
|
560
|
+
get member() {
|
|
561
|
+
return this.guild?.members.resolve(this.author) ?? null;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* The time the message was sent at
|
|
566
|
+
*
|
|
567
|
+
* @type {Date}
|
|
568
|
+
* @readonly
|
|
569
|
+
*/
|
|
570
|
+
get createdAt() {
|
|
571
|
+
return new Date(this.createdTimestamp);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* The time the message was last edited at (if applicable)
|
|
576
|
+
*
|
|
577
|
+
* @type {?Date}
|
|
578
|
+
* @readonly
|
|
579
|
+
*/
|
|
580
|
+
get editedAt() {
|
|
581
|
+
return this.editedTimestamp && new Date(this.editedTimestamp);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* The guild the message was sent in (if in a guild channel)
|
|
586
|
+
*
|
|
587
|
+
* @type {?Guild}
|
|
588
|
+
* @readonly
|
|
589
|
+
*/
|
|
590
|
+
get guild() {
|
|
591
|
+
return this.client.guilds.resolve(this.guildId) ?? this.channel?.guild ?? null;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Whether this message has a thread associated with it
|
|
596
|
+
*
|
|
597
|
+
* @type {boolean}
|
|
598
|
+
* @readonly
|
|
599
|
+
*/
|
|
600
|
+
get hasThread() {
|
|
601
|
+
return this.flags.has(MessageFlags.HasThread);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* The thread started by this message
|
|
606
|
+
* <info>This property is not suitable for checking whether a message has a thread,
|
|
607
|
+
* use {@link Message#hasThread} instead.</info>
|
|
608
|
+
*
|
|
609
|
+
* @type {?ThreadChannel}
|
|
610
|
+
* @readonly
|
|
611
|
+
*/
|
|
612
|
+
get thread() {
|
|
613
|
+
return this.channel?.threads?.cache.get(this.id) ?? null;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* The URL to jump to this message
|
|
618
|
+
*
|
|
619
|
+
* @type {string}
|
|
620
|
+
* @readonly
|
|
621
|
+
*/
|
|
622
|
+
get url() {
|
|
623
|
+
return this.inGuild() ? messageLink(this.channelId, this.id, this.guildId) : messageLink(this.channelId, this.id);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* The message contents with all mentions replaced by the equivalent text.
|
|
628
|
+
* If mentions cannot be resolved to a name, the relevant mention in the message content will not be converted.
|
|
629
|
+
*
|
|
630
|
+
* @type {?string}
|
|
631
|
+
* @readonly
|
|
632
|
+
*/
|
|
633
|
+
get cleanContent() {
|
|
634
|
+
// eslint-disable-next-line eqeqeq
|
|
635
|
+
return this.content != null && this.channel ? cleanContent(this.content, this.channel) : null;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* Creates a reaction collector.
|
|
640
|
+
*
|
|
641
|
+
* @param {ReactionCollectorOptions} [options={}] Options to send to the collector
|
|
642
|
+
* @returns {ReactionCollector}
|
|
643
|
+
* @example
|
|
644
|
+
* // Create a reaction collector
|
|
645
|
+
* const filter = (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someId';
|
|
646
|
+
* const collector = message.createReactionCollector({ filter, time: 15_000 });
|
|
647
|
+
* collector.on('collect', r => console.log(`Collected ${r.emoji.name}`));
|
|
648
|
+
* collector.on('end', collected => console.log(`Collected ${collected.size} items`));
|
|
649
|
+
*/
|
|
650
|
+
createReactionCollector(options = {}) {
|
|
651
|
+
return new ReactionCollector(this, options);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* An object containing the same properties as CollectorOptions, but a few more:
|
|
656
|
+
*
|
|
657
|
+
* @typedef {ReactionCollectorOptions} AwaitReactionsOptions
|
|
658
|
+
* @property {string[]} [errors] Stop/end reasons that cause the promise to reject
|
|
659
|
+
*/
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Similar to createReactionCollector but in promise form.
|
|
663
|
+
* Resolves with a collection of reactions that pass the specified filter.
|
|
664
|
+
*
|
|
665
|
+
* @param {AwaitReactionsOptions} [options={}] Optional options to pass to the internal collector
|
|
666
|
+
* @returns {Promise<Collection<string|Snowflake, MessageReaction>>}
|
|
667
|
+
* @example
|
|
668
|
+
* // Create a reaction collector
|
|
669
|
+
* const filter = (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someId'
|
|
670
|
+
* message.awaitReactions({ filter, time: 15_000 })
|
|
671
|
+
* .then(collected => console.log(`Collected ${collected.size} reactions`))
|
|
672
|
+
* .catch(console.error);
|
|
673
|
+
*/
|
|
674
|
+
async awaitReactions(options = {}) {
|
|
675
|
+
return new Promise((resolve, reject) => {
|
|
676
|
+
const collector = this.createReactionCollector(options);
|
|
677
|
+
collector.once('end', (reactions, reason) => {
|
|
678
|
+
if (options.errors?.includes(reason)) reject(reactions);
|
|
679
|
+
else resolve(reactions);
|
|
680
|
+
});
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* @typedef {CollectorOptions} MessageComponentCollectorOptions
|
|
686
|
+
* @property {ComponentType} [componentType] The type of component to listen for
|
|
687
|
+
* @property {number} [max] The maximum total amount of interactions to collect
|
|
688
|
+
* @property {number} [maxComponents] The maximum number of components to collect
|
|
689
|
+
* @property {number} [maxUsers] The maximum number of users to interact
|
|
690
|
+
*/
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* Creates a message component interaction collector.
|
|
694
|
+
*
|
|
695
|
+
* @param {MessageComponentCollectorOptions} [options={}] Options to send to the collector
|
|
696
|
+
* @returns {InteractionCollector}
|
|
697
|
+
* @example
|
|
698
|
+
* // Create a message component interaction collector
|
|
699
|
+
* const filter = (interaction) => interaction.customId === 'button' && interaction.user.id === 'someId';
|
|
700
|
+
* const collector = message.createMessageComponentCollector({ filter, time: 15_000 });
|
|
701
|
+
* collector.on('collect', i => console.log(`Collected ${i.customId}`));
|
|
702
|
+
* collector.on('end', collected => console.log(`Collected ${collected.size} items`));
|
|
703
|
+
*/
|
|
704
|
+
createMessageComponentCollector(options = {}) {
|
|
705
|
+
return new InteractionCollector(this.client, {
|
|
706
|
+
...options,
|
|
707
|
+
interactionType: InteractionType.MessageComponent,
|
|
708
|
+
message: this,
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
/**
|
|
713
|
+
* An object containing the same properties as CollectorOptions, but a few more:
|
|
714
|
+
*
|
|
715
|
+
* @typedef {Object} AwaitMessageComponentOptions
|
|
716
|
+
* @property {CollectorFilter} [filter] The filter applied to this collector
|
|
717
|
+
* @property {number} [time] Time to wait for an interaction before rejecting
|
|
718
|
+
* @property {ComponentType} [componentType] The type of component interaction to collect
|
|
719
|
+
* @property {number} [idle] Time to wait without another message component interaction before ending the collector
|
|
720
|
+
* @property {boolean} [dispose] Whether to remove the message component interaction after collecting
|
|
721
|
+
*/
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* Collects a single component interaction that passes the filter.
|
|
725
|
+
* The Promise will reject if the time expires.
|
|
726
|
+
*
|
|
727
|
+
* @param {AwaitMessageComponentOptions} [options={}] Options to pass to the internal collector
|
|
728
|
+
* @returns {Promise<MessageComponentInteraction>}
|
|
729
|
+
* @example
|
|
730
|
+
* // Collect a message component interaction
|
|
731
|
+
* const filter = (interaction) => interaction.customId === 'button' && interaction.user.id === 'someId';
|
|
732
|
+
* message.awaitMessageComponent({ filter, time: 15_000 })
|
|
733
|
+
* .then(interaction => console.log(`${interaction.customId} was clicked!`))
|
|
734
|
+
* .catch(console.error);
|
|
735
|
+
*/
|
|
736
|
+
async awaitMessageComponent(options = {}) {
|
|
737
|
+
const _options = { ...options, max: 1 };
|
|
738
|
+
return new Promise((resolve, reject) => {
|
|
739
|
+
const collector = this.createMessageComponentCollector(_options);
|
|
740
|
+
collector.once('end', (interactions, reason) => {
|
|
741
|
+
const interaction = interactions.first();
|
|
742
|
+
if (interaction) resolve(interaction);
|
|
743
|
+
else reject(new DiscordjsError(ErrorCodes.InteractionCollectorError, reason));
|
|
744
|
+
});
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/**
|
|
749
|
+
* Whether the message is editable by the client user
|
|
750
|
+
*
|
|
751
|
+
* @type {boolean}
|
|
752
|
+
* @readonly
|
|
753
|
+
*/
|
|
754
|
+
get editable() {
|
|
755
|
+
const precheck = Boolean(
|
|
756
|
+
this.author.id === this.client.user.id &&
|
|
757
|
+
(!this.guild || this.channel?.viewable) &&
|
|
758
|
+
this.reference?.type !== MessageReferenceType.Forward,
|
|
759
|
+
);
|
|
760
|
+
|
|
761
|
+
// Regardless of permissions thread messages cannot be edited if
|
|
762
|
+
// the thread is archived or the thread is locked and the bot does not have permission to manage threads.
|
|
763
|
+
if (this.channel?.isThread()) {
|
|
764
|
+
if (this.channel.archived) return false;
|
|
765
|
+
if (this.channel.locked) {
|
|
766
|
+
const permissions = this.channel.permissionsFor(this.client.user);
|
|
767
|
+
if (!permissions?.has(PermissionFlagsBits.ManageThreads, true)) return false;
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
return precheck;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* Whether the message is deletable by the client user
|
|
776
|
+
*
|
|
777
|
+
* @type {boolean}
|
|
778
|
+
* @readonly
|
|
779
|
+
*/
|
|
780
|
+
get deletable() {
|
|
781
|
+
if (UndeletableMessageTypes.includes(this.type)) return false;
|
|
782
|
+
|
|
783
|
+
if (!this.guild) {
|
|
784
|
+
return this.author.id === this.client.user.id;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
// DMChannel does not have viewable property, so check viewable after proved that message is on a guild.
|
|
788
|
+
if (!this.channel?.viewable) {
|
|
789
|
+
return false;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
const permissions = this.channel?.permissionsFor(this.client.user);
|
|
793
|
+
if (!permissions) return false;
|
|
794
|
+
// This flag allows deleting even if timed out
|
|
795
|
+
if (permissions.has(PermissionFlagsBits.Administrator, false)) return true;
|
|
796
|
+
|
|
797
|
+
// The auto moderation action message author is the reference message author
|
|
798
|
+
return (
|
|
799
|
+
(this.type !== MessageType.AutoModerationAction && this.author.id === this.client.user.id) ||
|
|
800
|
+
(permissions.has(PermissionFlagsBits.ManageMessages, false) && !this.guild.members.me.isCommunicationDisabled())
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Whether the message is bulk deletable by the client user
|
|
806
|
+
*
|
|
807
|
+
* @type {boolean}
|
|
808
|
+
* @readonly
|
|
809
|
+
* @example
|
|
810
|
+
* // Filter for bulk deletable messages
|
|
811
|
+
* channel.bulkDelete(messages.filter(message => message.bulkDeletable));
|
|
812
|
+
*/
|
|
813
|
+
get bulkDeletable() {
|
|
814
|
+
return (
|
|
815
|
+
(this.inGuild() &&
|
|
816
|
+
Date.now() - this.createdTimestamp < MaxBulkDeletableMessageAge &&
|
|
817
|
+
this.deletable &&
|
|
818
|
+
this.channel?.permissionsFor(this.client.user).has(PermissionFlagsBits.ManageMessages, false)) ??
|
|
819
|
+
false
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Whether the message is pinnable by the client user
|
|
825
|
+
*
|
|
826
|
+
* @type {boolean}
|
|
827
|
+
* @readonly
|
|
828
|
+
*/
|
|
829
|
+
get pinnable() {
|
|
830
|
+
const { channel } = this;
|
|
831
|
+
|
|
832
|
+
if (this.system) return false;
|
|
833
|
+
if (!this.guild) return true;
|
|
834
|
+
if (!channel || channel.isVoiceBased() || !channel.viewable) return false;
|
|
835
|
+
|
|
836
|
+
const permissions = channel.permissionsFor(this.client.user);
|
|
837
|
+
if (!permissions) return false;
|
|
838
|
+
|
|
839
|
+
return permissions.has(PermissionFlagsBits.ReadMessageHistory | PermissionFlagsBits.PinMessages);
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* Fetches the Message this crosspost/reply/pin-add references, if available to the client
|
|
844
|
+
*
|
|
845
|
+
* @returns {Promise<Message>}
|
|
846
|
+
*/
|
|
847
|
+
async fetchReference() {
|
|
848
|
+
if (!this.reference) throw new DiscordjsError(ErrorCodes.MessageReferenceMissing);
|
|
849
|
+
const { channelId, messageId } = this.reference;
|
|
850
|
+
if (!messageId) throw new DiscordjsError(ErrorCodes.MessageReferenceMissing);
|
|
851
|
+
const channel = this.client.channels.resolve(channelId);
|
|
852
|
+
if (!channel) throw new DiscordjsError(ErrorCodes.GuildChannelResolve);
|
|
853
|
+
return channel.messages.fetch(messageId);
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
/**
|
|
857
|
+
* Whether the message is crosspostable by the client user
|
|
858
|
+
*
|
|
859
|
+
* @type {boolean}
|
|
860
|
+
* @readonly
|
|
861
|
+
*/
|
|
862
|
+
get crosspostable() {
|
|
863
|
+
const bitfield =
|
|
864
|
+
PermissionFlagsBits.SendMessages |
|
|
865
|
+
(this.author.id === this.client.user.id ? PermissionsBitField.DefaultBit : PermissionFlagsBits.ManageMessages);
|
|
866
|
+
const { channel } = this;
|
|
867
|
+
return Boolean(
|
|
868
|
+
channel?.type === ChannelType.GuildAnnouncement &&
|
|
869
|
+
!this.flags.has(MessageFlags.Crossposted) &&
|
|
870
|
+
this.reference?.type !== MessageReferenceType.Forward &&
|
|
871
|
+
this.type === MessageType.Default &&
|
|
872
|
+
!this.poll &&
|
|
873
|
+
channel.viewable &&
|
|
874
|
+
channel.permissionsFor(this.client.user)?.has(bitfield, false),
|
|
875
|
+
);
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Edits the content of the message.
|
|
880
|
+
*
|
|
881
|
+
* @param {string|MessageEditOptions|MessagePayload|FileBodyEncodable<RESTPatchAPIChannelMessageJSONBody>|JSONEncodable<RESTPatchAPIChannelMessageJSONBody>} options The options to provide
|
|
882
|
+
* @returns {Promise<Message>}
|
|
883
|
+
* @example
|
|
884
|
+
* // Update the content of a message
|
|
885
|
+
* message.edit('This is my new content!')
|
|
886
|
+
* .then(msg => console.log(`Updated the content of a message to ${msg.content}`))
|
|
887
|
+
* .catch(console.error);
|
|
888
|
+
*/
|
|
889
|
+
async edit(options) {
|
|
890
|
+
if (!this.channel) throw new DiscordjsError(ErrorCodes.ChannelNotCached);
|
|
891
|
+
return this.channel.messages.edit(this, options);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
/**
|
|
895
|
+
* Publishes a message in an announcement channel to all channels following it.
|
|
896
|
+
*
|
|
897
|
+
* @returns {Promise<Message>}
|
|
898
|
+
* @example
|
|
899
|
+
* // Crosspost a message
|
|
900
|
+
* if (message.channel.type === ChannelType.GuildAnnouncement) {
|
|
901
|
+
* message.crosspost()
|
|
902
|
+
* .then(() => console.log('Crossposted message'))
|
|
903
|
+
* .catch(console.error);
|
|
904
|
+
* }
|
|
905
|
+
*/
|
|
906
|
+
async crosspost() {
|
|
907
|
+
if (!this.channel) throw new DiscordjsError(ErrorCodes.ChannelNotCached);
|
|
908
|
+
return this.channel.messages.crosspost(this.id);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* Pins this message to the channel's pinned messages.
|
|
913
|
+
*
|
|
914
|
+
* @param {string} [reason] Reason for pinning
|
|
915
|
+
* @returns {Promise<Message>}
|
|
916
|
+
* @example
|
|
917
|
+
* // Pin a message
|
|
918
|
+
* message.pin()
|
|
919
|
+
* .then(console.log)
|
|
920
|
+
* .catch(console.error)
|
|
921
|
+
*/
|
|
922
|
+
async pin(reason) {
|
|
923
|
+
if (!this.channel) throw new DiscordjsError(ErrorCodes.ChannelNotCached);
|
|
924
|
+
await this.channel.messages.pin(this.id, reason);
|
|
925
|
+
return this;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/**
|
|
929
|
+
* Unpins this message from the channel's pinned messages.
|
|
930
|
+
*
|
|
931
|
+
* @param {string} [reason] Reason for unpinning
|
|
932
|
+
* @returns {Promise<Message>}
|
|
933
|
+
* @example
|
|
934
|
+
* // Unpin a message
|
|
935
|
+
* message.unpin()
|
|
936
|
+
* .then(console.log)
|
|
937
|
+
* .catch(console.error)
|
|
938
|
+
*/
|
|
939
|
+
async unpin(reason) {
|
|
940
|
+
if (!this.channel) throw new DiscordjsError(ErrorCodes.ChannelNotCached);
|
|
941
|
+
await this.channel.messages.unpin(this.id, reason);
|
|
942
|
+
return this;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
/**
|
|
946
|
+
* Adds a reaction to the message.
|
|
947
|
+
*
|
|
948
|
+
* @param {EmojiIdentifierResolvable} emoji The emoji to react with
|
|
949
|
+
* @returns {Promise<MessageReaction>}
|
|
950
|
+
* @example
|
|
951
|
+
* // React to a message with a unicode emoji
|
|
952
|
+
* message.react('🤔')
|
|
953
|
+
* .then(console.log)
|
|
954
|
+
* .catch(console.error);
|
|
955
|
+
* @example
|
|
956
|
+
* // React to a message with a custom emoji
|
|
957
|
+
* message.react(message.guild.emojis.cache.get('123456789012345678'))
|
|
958
|
+
* .then(console.log)
|
|
959
|
+
* .catch(console.error);
|
|
960
|
+
*/
|
|
961
|
+
async react(emoji) {
|
|
962
|
+
if (!this.channel) throw new DiscordjsError(ErrorCodes.ChannelNotCached);
|
|
963
|
+
await this.channel.messages.react(this.id, emoji);
|
|
964
|
+
|
|
965
|
+
return this.client.actions.MessageReactionAdd.handle(
|
|
966
|
+
{
|
|
967
|
+
[this.client.actions.injectedUser]: this.client.user,
|
|
968
|
+
[this.client.actions.injectedChannel]: this.channel,
|
|
969
|
+
[this.client.actions.injectedMessage]: this,
|
|
970
|
+
emoji: resolvePartialEmoji(emoji),
|
|
971
|
+
},
|
|
972
|
+
true,
|
|
973
|
+
).reaction;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
/**
|
|
977
|
+
* Deletes the message.
|
|
978
|
+
*
|
|
979
|
+
* @returns {Promise<Message>}
|
|
980
|
+
* @example
|
|
981
|
+
* // Delete a message
|
|
982
|
+
* message.delete()
|
|
983
|
+
* .then(msg => console.log(`Deleted message from ${msg.author.username}`))
|
|
984
|
+
* .catch(console.error);
|
|
985
|
+
*/
|
|
986
|
+
async delete() {
|
|
987
|
+
if (!this.channel) throw new DiscordjsError(ErrorCodes.ChannelNotCached);
|
|
988
|
+
await this.channel.messages.delete(this.id);
|
|
989
|
+
return this;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
/**
|
|
993
|
+
* Options provided when sending a message as an inline reply.
|
|
994
|
+
*
|
|
995
|
+
* @typedef {BaseMessageCreateOptions} MessageReplyOptions
|
|
996
|
+
* @property {boolean} [failIfNotExists=this.client.options.failIfNotExists] Whether to error if the referenced
|
|
997
|
+
* message does not exist (creates a standard message in this case when false)
|
|
998
|
+
*/
|
|
999
|
+
|
|
1000
|
+
/**
|
|
1001
|
+
* Send an inline reply to this message.
|
|
1002
|
+
*
|
|
1003
|
+
* @param {string|MessagePayload|MessageReplyOptions} options The options to provide
|
|
1004
|
+
* @returns {Promise<Message>}
|
|
1005
|
+
* @example
|
|
1006
|
+
* // Reply to a message
|
|
1007
|
+
* message.reply('This is a reply!')
|
|
1008
|
+
* .then(() => console.log(`Replied to message "${message.content}"`))
|
|
1009
|
+
* .catch(console.error);
|
|
1010
|
+
*/
|
|
1011
|
+
async reply(options) {
|
|
1012
|
+
let data;
|
|
1013
|
+
|
|
1014
|
+
if (options instanceof MessagePayload) {
|
|
1015
|
+
data = options;
|
|
1016
|
+
} else {
|
|
1017
|
+
data = MessagePayload.create(this, options, {
|
|
1018
|
+
messageReference: {
|
|
1019
|
+
messageId: this.id,
|
|
1020
|
+
channelId: this.channelId,
|
|
1021
|
+
guildId: this.guildId ?? undefined,
|
|
1022
|
+
type: MessageReferenceType.Default,
|
|
1023
|
+
failIfNotExists: options?.failIfNotExists ?? this.client.options.failIfNotExists,
|
|
1024
|
+
},
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
return this.client.channels.createMessage(this.channelId, data);
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
/**
|
|
1032
|
+
* Forwards this message.
|
|
1033
|
+
*
|
|
1034
|
+
* @param {TextChannelResolvable} channel The channel to forward this message to.
|
|
1035
|
+
* @returns {Promise<Message>}
|
|
1036
|
+
*/
|
|
1037
|
+
async forward(channel) {
|
|
1038
|
+
return this.client.channels.createMessage(channel, {
|
|
1039
|
+
messageReference: {
|
|
1040
|
+
messageId: this.id,
|
|
1041
|
+
channelId: this.channelId,
|
|
1042
|
+
guildId: this.guildId ?? undefined,
|
|
1043
|
+
type: MessageReferenceType.Forward,
|
|
1044
|
+
},
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
/**
|
|
1049
|
+
* Options for starting a thread on a message.
|
|
1050
|
+
*
|
|
1051
|
+
* @typedef {Object} StartThreadOptions
|
|
1052
|
+
* @property {string} name The name of the new thread
|
|
1053
|
+
* @property {ThreadAutoArchiveDuration} [autoArchiveDuration=this.channel.defaultAutoArchiveDuration] The amount of
|
|
1054
|
+
* time after which the thread should automatically archive in case of no recent activity
|
|
1055
|
+
* @property {string} [reason] Reason for creating the thread
|
|
1056
|
+
* @property {number} [rateLimitPerUser] The rate limit per user (slowmode) for the thread in seconds
|
|
1057
|
+
*/
|
|
1058
|
+
|
|
1059
|
+
/**
|
|
1060
|
+
* Create a new public thread from this message
|
|
1061
|
+
*
|
|
1062
|
+
* @see GuildTextThreadManager#create
|
|
1063
|
+
* @param {StartThreadOptions} [options] Options for starting a thread on this message
|
|
1064
|
+
* @returns {Promise<ThreadChannel>}
|
|
1065
|
+
*/
|
|
1066
|
+
async startThread(options = {}) {
|
|
1067
|
+
if (!this.channel) throw new DiscordjsError(ErrorCodes.ChannelNotCached);
|
|
1068
|
+
if (![ChannelType.GuildText, ChannelType.GuildAnnouncement].includes(this.channel.type)) {
|
|
1069
|
+
throw new DiscordjsError(ErrorCodes.MessageThreadParent);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
if (this.hasThread) throw new DiscordjsError(ErrorCodes.MessageExistingThread);
|
|
1073
|
+
return this.channel.threads.create({ ...options, startMessage: this });
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
/**
|
|
1077
|
+
* Fetch this message.
|
|
1078
|
+
*
|
|
1079
|
+
* @param {boolean} [force=true] Whether to skip the cache check and request the API
|
|
1080
|
+
* @returns {Promise<Message>}
|
|
1081
|
+
*/
|
|
1082
|
+
async fetch(force = true) {
|
|
1083
|
+
if (!this.channel) throw new DiscordjsError(ErrorCodes.ChannelNotCached);
|
|
1084
|
+
return this.channel.messages.fetch({ message: this.id, force });
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
/**
|
|
1088
|
+
* Fetches the webhook used to create this message.
|
|
1089
|
+
*
|
|
1090
|
+
* @returns {Promise<?Webhook>}
|
|
1091
|
+
*/
|
|
1092
|
+
async fetchWebhook() {
|
|
1093
|
+
if (!this.webhookId) throw new DiscordjsError(ErrorCodes.WebhookMessage);
|
|
1094
|
+
if (this.webhookId === this.applicationId) throw new DiscordjsError(ErrorCodes.WebhookApplication);
|
|
1095
|
+
return this.client.fetchWebhook(this.webhookId);
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
/**
|
|
1099
|
+
* Suppresses or unsuppresses embeds on a message.
|
|
1100
|
+
*
|
|
1101
|
+
* @param {boolean} [suppress=true] If the embeds should be suppressed or not
|
|
1102
|
+
* @returns {Promise<Message>}
|
|
1103
|
+
*/
|
|
1104
|
+
async suppressEmbeds(suppress = true) {
|
|
1105
|
+
const flags = new MessageFlagsBitField(this.flags.bitfield);
|
|
1106
|
+
|
|
1107
|
+
if (suppress) {
|
|
1108
|
+
flags.add(MessageFlags.SuppressEmbeds);
|
|
1109
|
+
} else {
|
|
1110
|
+
flags.remove(MessageFlags.SuppressEmbeds);
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
return this.edit({ flags });
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
/**
|
|
1117
|
+
* Removes the attachments from this message.
|
|
1118
|
+
*
|
|
1119
|
+
* @returns {Promise<Message>}
|
|
1120
|
+
*/
|
|
1121
|
+
async removeAttachments() {
|
|
1122
|
+
return this.edit({ attachments: [] });
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
/**
|
|
1126
|
+
* Resolves a component by a custom id.
|
|
1127
|
+
*
|
|
1128
|
+
* @param {string} customId The custom id to resolve against
|
|
1129
|
+
* @returns {?MessageActionRowComponent}
|
|
1130
|
+
*/
|
|
1131
|
+
resolveComponent(customId) {
|
|
1132
|
+
return findComponentByCustomId(this.components, customId);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
/**
|
|
1136
|
+
* Used mainly internally. Whether two messages are identical in properties. If you want to compare messages
|
|
1137
|
+
* without checking all the properties, use `message.id === message2.id`, which is much more efficient. This
|
|
1138
|
+
* method allows you to see if there are differences in content, embeds, attachments, nonce and tts properties.
|
|
1139
|
+
*
|
|
1140
|
+
* @param {Message} message The message to compare it to
|
|
1141
|
+
* @param {APIMessage} [rawData] Raw data passed through the WebSocket about this message
|
|
1142
|
+
* @returns {boolean}
|
|
1143
|
+
*/
|
|
1144
|
+
equals(message, rawData) {
|
|
1145
|
+
if (!message) return false;
|
|
1146
|
+
const embedUpdate = !message.author && !message.attachments;
|
|
1147
|
+
if (embedUpdate) return this.id === message.id && this.embeds.length === message.embeds.length;
|
|
1148
|
+
|
|
1149
|
+
let equal =
|
|
1150
|
+
this.id === message.id &&
|
|
1151
|
+
this.author.id === message.author.id &&
|
|
1152
|
+
this.content === message.content &&
|
|
1153
|
+
this.nonce === message.nonce &&
|
|
1154
|
+
this.tts === message.tts &&
|
|
1155
|
+
this.attachments.size === message.attachments.size &&
|
|
1156
|
+
this.embeds.length === message.embeds.length &&
|
|
1157
|
+
this.attachments.every(attachment => message.attachments.has(attachment.id)) &&
|
|
1158
|
+
this.embeds.every((embed, index) => embed.equals(message.embeds[index]));
|
|
1159
|
+
|
|
1160
|
+
if (equal && rawData) {
|
|
1161
|
+
equal =
|
|
1162
|
+
this.mentions.everyone === message.mentions.everyone &&
|
|
1163
|
+
this.createdTimestamp === Date.parse(rawData.timestamp) &&
|
|
1164
|
+
this.editedTimestamp === Date.parse(rawData.edited_timestamp);
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
return equal;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
/**
|
|
1171
|
+
* Whether this message is from a guild.
|
|
1172
|
+
*
|
|
1173
|
+
* @returns {boolean}
|
|
1174
|
+
*/
|
|
1175
|
+
inGuild() {
|
|
1176
|
+
return Boolean(this.guildId);
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
/**
|
|
1180
|
+
* When concatenated with a string, this automatically concatenates the message's content instead of the object.
|
|
1181
|
+
*
|
|
1182
|
+
* @returns {string}
|
|
1183
|
+
* @example
|
|
1184
|
+
* // Logs: Message: This is a message!
|
|
1185
|
+
* console.log(`Message: ${message}`);
|
|
1186
|
+
*/
|
|
1187
|
+
toString() {
|
|
1188
|
+
return this.content;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
toJSON() {
|
|
1192
|
+
return super.toJSON({
|
|
1193
|
+
channel: 'channelId',
|
|
1194
|
+
author: 'authorId',
|
|
1195
|
+
groupActivityApplication: 'groupActivityApplicationId',
|
|
1196
|
+
guild: 'guildId',
|
|
1197
|
+
cleanContent: true,
|
|
1198
|
+
member: false,
|
|
1199
|
+
reactions: false,
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
}
|