import { SnowflakeBase } from './base.ts' import { Attachment, MessageActivity, MessageApplication, MessageOptions, MessagePayload, MessageReference } from '../types/channel.ts' import { Client } from '../models/client.ts' import { User } from './user.ts' import { Member } from './member.ts' import { Embed } from './embed.ts' import { CHANNEL_MESSAGE } from '../types/endpoint.ts' import { MessageMentions } from './messageMentions.ts' import { TextChannel } from './textChannel.ts' import { GuildTextBasedChannel } from './guildTextChannel.ts' import { Guild } from './guild.ts' import { MessageReactionsManager } from '../managers/messageReactions.ts' import { MessageSticker } from './messageSticker.ts' import { Emoji } from './emoji.ts' type AllMessageOptions = MessageOptions | Embed export class Message extends SnowflakeBase { id: string channelID: string channel: TextChannel guildID?: string guild?: Guild author: User member?: Member content: string editedTimestamp?: Date tts: boolean mentions: MessageMentions attachments: Attachment[] embeds: Embed[] reactions: MessageReactionsManager nonce?: string | number pinned: boolean webhookID?: string type: number activity?: MessageActivity application?: MessageApplication messageReference?: MessageReference flags?: number stickers?: MessageSticker[] get createdAt(): Date { return new Date(this.timestamp) } constructor( client: Client, data: MessagePayload, channel: TextChannel, author: User ) { super(client) this.id = data.id this.channelID = data.channel_id this.guildID = data.guild_id this.author = author this.content = data.content this.editedTimestamp = data.edited_timestamp === undefined ? undefined : new Date(data.edited_timestamp) this.tts = data.tts this.mentions = new MessageMentions(this.client, this) this.attachments = data.attachments this.embeds = data.embeds.map((v) => new Embed(v)) this.reactions = new MessageReactionsManager(this.client, this) this.nonce = data.nonce this.pinned = data.pinned this.webhookID = data.webhook_id this.type = data.type this.activity = data.activity this.application = data.application this.messageReference = data.message_reference this.flags = data.flags this.channel = channel this.stickers = data.stickers !== undefined ? data.stickers.map( (payload) => new MessageSticker(this.client, payload) ) : undefined } readFromData(data: MessagePayload): void { this.channelID = data.channel_id ?? this.channelID this.guildID = data.guild_id ?? this.guildID this.content = data.content ?? this.content this.editedTimestamp = data.edited_timestamp === undefined ? this.editedTimestamp : new Date(data.edited_timestamp) this.tts = data.tts ?? this.tts this.attachments = data.attachments ?? this.attachments this.embeds = data.embeds.map((v) => new Embed(v)) ?? this.embeds this.nonce = data.nonce ?? this.nonce this.pinned = data.pinned ?? this.pinned this.webhookID = data.webhook_id ?? this.webhookID this.type = data.type ?? this.type this.activity = data.activity ?? this.activity this.application = data.application ?? this.application this.messageReference = data.message_reference ?? this.messageReference this.flags = data.flags ?? this.flags this.stickers = data.stickers !== undefined ? data.stickers.map( (payload) => new MessageSticker(this.client, payload) ) : this.stickers } async updateRefs(): Promise { if (this.guildID !== undefined) this.guild = await this.client.guilds.get(this.guildID) const newVal = await this.client.channels.get(this.channelID) if (newVal !== undefined) this.channel = newVal const newUser = await this.client.users.get(this.author.id) if (newUser !== undefined) this.author = newUser if (this.member !== undefined) { const newMember = await this.guild?.members.get(this.member?.id) if (newMember !== undefined) this.member = newMember } if ( ((this.channel as unknown) as GuildTextBasedChannel).guild !== undefined ) this.guild = ((this.channel as unknown) as GuildTextBasedChannel).guild if (this.guild !== undefined && this.guildID === undefined) this.guildID = this.guild.id } /** Edits this message. */ async edit( content?: string | AllMessageOptions, option?: AllMessageOptions ): Promise { if (typeof content === 'object') { option = content content = undefined } if (content === undefined && option === undefined) { throw new Error('Either text or option is necessary.') } if (option instanceof Embed) { option = { embed: option } } if ( this.client.user !== undefined && this.author.id !== this.client.user?.id ) { throw new Error("Cannot edit other users' messages") } return this.channel.editMessage(this.id, content, option) } /** Creates a Reply to this Message. */ async reply( content?: string | AllMessageOptions, option?: AllMessageOptions ): Promise { return this.channel.send(content, option, this) } /** Deletes the Message. */ async delete(): Promise { return this.client.rest.delete(CHANNEL_MESSAGE(this.channelID, this.id)) } /** * Adds a reaction to the message. * @param emoji Emoji in string or object */ async addReaction(emoji: string | Emoji): Promise { return this.channel.addReaction(this, emoji) } /** * Removes a reaction to the message. * @param emoji Emoji in string or object * @param user User or Member or user id */ async removeReaction( emoji: string | Emoji, user?: User | Member | string ): Promise { return this.channel.removeReaction(this, emoji, user) } } const encoder = new TextEncoder() /** Message Attachment that can be sent while Creating Message */ export class MessageAttachment { name: string blob: Blob constructor(name: string, blob: Blob | Uint8Array | string) { this.name = name this.blob = typeof blob === 'string' ? new Blob([encoder.encode(blob)]) : blob instanceof Uint8Array ? new Blob([blob]) : blob } /** Load an Message Attachment from local file or URL */ static async load( path: string, filename?: string ): Promise { const blob = path.startsWith('http') ? await fetch(path).then((res) => res.blob()) : await Deno.readFile(path) if (filename === undefined) { const split = path.replaceAll('\\', '/').split('/').pop() if (split !== undefined) filename = split.split('?')[0].split('#')[0] else filename = 'unnamed_attachment' } return new MessageAttachment(filename, blob) } }