import { delay } from "../../deps.ts"; import { cacheHandlers } from "../controllers/cache.ts"; import { botID } from "../module/client.ts"; import { RequestManager } from "../module/requestManager.ts"; import { Message } from "../structures/message.ts"; import { structures } from "../structures/mod.ts"; import { MessageContent } from "../types/channel.ts"; import { Errors } from "../types/errors.ts"; import { UserPayload } from "../types/guild.ts"; import { MessageCreateOptions } from "../types/message.ts"; import { Permissions } from "../types/permission.ts"; import { endpoints } from "../utils/constants.ts"; import { botHasChannelPermissions } from "../utils/permissions.ts"; /** Delete a message with the channel id and message id only. */ export async function deleteMessageByID( channelID: string, messageID: string, reason?: string, delayMilliseconds = 0, ) { const message = await cacheHandlers.get("messages", messageID); if (message) return deleteMessage(message, reason, delayMilliseconds); if (delayMilliseconds) await delay(delayMilliseconds); return RequestManager.delete( endpoints.CHANNEL_MESSAGE(channelID, messageID), { reason }, ); } /** Delete a message */ export async function deleteMessage( message: Message, reason?: string, delayMilliseconds = 0, ) { if (message.author.id !== botID) { // This needs to check the channels permission not the guild permission const hasManageMessages = await botHasChannelPermissions( message.channelID, [Permissions.MANAGE_MESSAGES], ); if ( !hasManageMessages ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } } if (delayMilliseconds) await delay(delayMilliseconds); return RequestManager.delete( endpoints.CHANNEL_MESSAGE(message.channelID, message.id), { reason }, ); } /** Pin a message in a channel. Requires MANAGE_MESSAGES. Max pins allowed in a channel = 50. */ export async function pin(channelID: string, messageID: string) { const hasManageMessagesPerm = await botHasChannelPermissions( channelID, [Permissions.MANAGE_MESSAGES], ); if ( !hasManageMessagesPerm ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } RequestManager.put(endpoints.CHANNEL_MESSAGE(channelID, messageID)); } /** Unpin a message in a channel. Requires MANAGE_MESSAGES. */ export async function unpin(channelID: string, messageID: string) { const hasManageMessagesPerm = await botHasChannelPermissions( channelID, [Permissions.MANAGE_MESSAGES], ); if ( !hasManageMessagesPerm ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } RequestManager.delete( endpoints.CHANNEL_MESSAGE(channelID, messageID), ); } /** Create a reaction for the message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. Requires READ_MESSAGE_HISTORY and ADD_REACTIONS */ export async function addReaction( channelID: string, messageID: string, reaction: string, ) { const hasAddReactionsPerm = await botHasChannelPermissions( channelID, [Permissions.ADD_REACTIONS], ); if (!hasAddReactionsPerm) { throw new Error(Errors.MISSING_ADD_REACTIONS); } const hasReadMessageHistoryPerm = await botHasChannelPermissions( channelID, [Permissions.READ_MESSAGE_HISTORY], ); if ( !hasReadMessageHistoryPerm ) { throw new Error(Errors.MISSING_READ_MESSAGE_HISTORY); } if (reaction.startsWith("<:")) { reaction = reaction.substring(2, reaction.length - 1); } else if (reaction.startsWith(" addReaction(channelID, messageID, reaction) ); } else { for (const reaction of reactions) { await addReaction(channelID, messageID, reaction); } } } /** Removes a reaction from the bot on this message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. */ export function removeReaction( channelID: string, messageID: string, reaction: string, ) { return RequestManager.delete( endpoints.CHANNEL_MESSAGE_REACTION_ME( channelID, messageID, reaction, ), ); } /** Removes a reaction from the specified user on this message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. */ export async function removeUserReaction( channelID: string, messageID: string, reaction: string, userID: string, ) { const hasManageMessagesPerm = await botHasChannelPermissions( channelID, [Permissions.MANAGE_MESSAGES], ); if (!hasManageMessagesPerm) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } return RequestManager.delete( endpoints.CHANNEL_MESSAGE_REACTION_USER( channelID, messageID, reaction, userID, ), ); } /** Removes all reactions for all emojis on this message. */ export async function removeAllReactions(channelID: string, messageID: string) { const hasManageMessagesPerm = await botHasChannelPermissions( channelID, [Permissions.MANAGE_MESSAGES], ); if ( !hasManageMessagesPerm ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } return RequestManager.delete( endpoints.CHANNEL_MESSAGE_REACTIONS(channelID, messageID), ); } /** Removes all reactions for a single emoji on this message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. */ export async function removeReactionEmoji( channelID: string, messageID: string, reaction: string, ) { const hasManageMessagesPerm = await botHasChannelPermissions( channelID, [Permissions.MANAGE_MESSAGES], ); if ( !hasManageMessagesPerm ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } return RequestManager.delete( endpoints.CHANNEL_MESSAGE_REACTION(channelID, messageID, reaction), ); } /** Get a list of users that reacted with this emoji. */ export async function getReactions(message: Message, reaction: string) { const result = (await RequestManager.get( endpoints.CHANNEL_MESSAGE_REACTION(message.channelID, message.id, reaction), )) as UserPayload[]; return Promise.all(result.map(async (res) => { const member = await cacheHandlers.get("members", res.id); return member || res; })); } /** Edit the message. */ export async function editMessage( message: Message, content: string | MessageContent, ) { if ( message.author.id !== botID ) { throw "You can only edit a message that was sent by the bot."; } if (typeof content === "string") content = { content }; const hasSendMessagesPerm = await botHasChannelPermissions( message.channelID, [Permissions.SEND_MESSAGES], ); if ( !hasSendMessagesPerm ) { throw new Error(Errors.MISSING_SEND_MESSAGES); } const hasSendTtsMessagesPerm = await botHasChannelPermissions( message.channelID, [Permissions.SEND_TTS_MESSAGES], ); if ( content.tts && !hasSendTtsMessagesPerm ) { throw new Error(Errors.MISSING_SEND_TTS_MESSAGE); } if (content.content && content.content.length > 2000) { throw new Error(Errors.MESSAGE_MAX_LENGTH); } const result = await RequestManager.patch( endpoints.CHANNEL_MESSAGE(message.channelID, message.id), content, ); return structures.createMessage(result as MessageCreateOptions); } export async function publishMessage(channelID: string, messageID: string) { const data = await RequestManager.post( endpoints.CHANNEL_MESSAGE_CROSSPOST(channelID, messageID), ) as MessageCreateOptions; return structures.createMessage(data); }