mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-13 18:13:29 +01:00
feat: message structures (#10982)
* feat: message structures * fix: docs * chore: components and more * feat: embed and more * feat: more substructures and code review suggestions * chore: tests and date conversions * chore: jsdoc strings * fix: tests * fix: tests * feat: hexColor getters * chore: remove getters for nested data * chore: apply suggestions from code review * fix: burst_colors in toJSON * docs: rephrase SectionBuilder remark * chore: add LabelComponent * fix: add name and size to file component * chore: move resolved interaction data to interactions dir * fix: code review * chore: bump discord-api-types * chore: apply code review suggestions * fix: lockfile * chore: update remark * fix: missing export * chore: code review and tests * build: fix file * fix: typo * fix: missing toJSON * fix: remove redundant patch overrides * chore: missing component suffix * chore: better name * chore: add comment explaining timestamp conversion --------- Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
This commit is contained in:
178
packages/structures/src/messages/Message.ts
Normal file
178
packages/structures/src/messages/Message.ts
Normal file
@@ -0,0 +1,178 @@
|
||||
import { DiscordSnowflake } from '@sapphire/snowflake';
|
||||
import type { APIMessage, MessageFlags } from 'discord-api-types/v10';
|
||||
import { Structure } from '../Structure.js';
|
||||
import { MessageFlagsBitField } from '../bitfields/MessageFlagsBitField.js';
|
||||
import { dateToDiscordISOTimestamp } from '../utils/optimization.js';
|
||||
import { kData, kEditedTimestamp } from '../utils/symbols.js';
|
||||
import { isIdSet } from '../utils/type-guards.js';
|
||||
import type { Partialize } from '../utils/types.js';
|
||||
|
||||
// TODO: missing substructures: application
|
||||
|
||||
/**
|
||||
* Represents a message on Discord.
|
||||
*
|
||||
* @typeParam Omitted - Specify the properties that will not be stored in the raw data field as a union, implement via `DataTemplate`
|
||||
* @remarks has substructures `Message`, `Channel`, `MessageActivity`, `MessageCall`, `MessageReference`, `Attachment`, `Application`, `ChannelMention`, `Reaction`, `Poll`, `ResolvedInteractionData`, `RoleSubscriptionData`, `Sticker`, all the different `Component`s, ... which need to be instantiated and stored by an extending class using it
|
||||
*/
|
||||
export class Message<Omitted extends keyof APIMessage | '' = 'edited_timestamp' | 'timestamp'> extends Structure<
|
||||
APIMessage,
|
||||
Omitted
|
||||
> {
|
||||
/**
|
||||
* The template used for removing data from the raw data stored for each Message
|
||||
*/
|
||||
public static override DataTemplate: Partial<APIMessage> = {
|
||||
set timestamp(_: string) {},
|
||||
set edited_timestamp(_: string) {},
|
||||
};
|
||||
|
||||
protected [kEditedTimestamp]: number | null = null;
|
||||
|
||||
/**
|
||||
* @param data - The raw data received from the API for the message
|
||||
*/
|
||||
public constructor(data: Partialize<APIMessage, Omitted>) {
|
||||
super(data);
|
||||
this.optimizeData(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc Structure.optimizeData}
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected override optimizeData(data: Partial<APIMessage>) {
|
||||
if (data.edited_timestamp) {
|
||||
this[kEditedTimestamp] = Date.parse(data.edited_timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The message's id
|
||||
*/
|
||||
public get id() {
|
||||
return this[kData].id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The id of the interaction's application, if this message is a reply to an interaction
|
||||
*/
|
||||
public get applicationId() {
|
||||
return this[kData].application_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The channel's id this message was sent in
|
||||
*/
|
||||
public get channelId() {
|
||||
return this[kData].channel_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp this message was created at
|
||||
*/
|
||||
public get createdTimestamp() {
|
||||
return isIdSet(this.id) ? DiscordSnowflake.timestampFrom(this.id) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the message was created at
|
||||
*/
|
||||
public get createdAt() {
|
||||
const createdTimestamp = this.createdTimestamp;
|
||||
return createdTimestamp ? new Date(createdTimestamp) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The content of the message
|
||||
*/
|
||||
public get content() {
|
||||
return this[kData].content;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp this message was last edited at, or `null` if it never was edited
|
||||
*/
|
||||
public get editedTimestamp() {
|
||||
return this[kEditedTimestamp];
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the message was last edited at, or `null` if it never was edited
|
||||
*/
|
||||
public get editedAt() {
|
||||
const editedTimestamp = this.editedTimestamp;
|
||||
return editedTimestamp ? new Date(editedTimestamp) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The flags of this message as a bit field
|
||||
*/
|
||||
public get flags() {
|
||||
const flags = this[kData].flags;
|
||||
return flags ? new MessageFlagsBitField(this[kData].flags as MessageFlags) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The nonce used when sending this message.
|
||||
*
|
||||
* @remarks This is only present in MESSAGE_CREATE event, if a nonce was provided when sending
|
||||
*/
|
||||
public get nonce() {
|
||||
return this[kData].nonce;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this message is pinned in its channel
|
||||
*/
|
||||
public get pinned() {
|
||||
return this[kData].pinned;
|
||||
}
|
||||
|
||||
/**
|
||||
* A generally increasing integer (there may be gaps or duplicates) that represents the approximate position of the message in a thread
|
||||
* It can be used to estimate the relative position of the message in a thread in company with `totalMessageSent` on parent thread
|
||||
*/
|
||||
public get position() {
|
||||
return this[kData].position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this message was a TTS message
|
||||
*/
|
||||
public get tts() {
|
||||
return this[kData].tts;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of message
|
||||
*/
|
||||
public get type() {
|
||||
return this[kData].type;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the message is generated by a webhook, this is the webhook's id
|
||||
*/
|
||||
public get webhookId() {
|
||||
return this[kData].webhook_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc Structure.toJSON}
|
||||
*/
|
||||
public override toJSON() {
|
||||
const clone = super.toJSON();
|
||||
if (this[kEditedTimestamp]) {
|
||||
clone.edited_timestamp = dateToDiscordISOTimestamp(new Date(this[kEditedTimestamp]));
|
||||
}
|
||||
|
||||
const createdAt = this.createdAt;
|
||||
if (createdAt) {
|
||||
clone.timestamp = dateToDiscordISOTimestamp(createdAt);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user