235 lines
6.5 KiB
TypeScript
235 lines
6.5 KiB
TypeScript
import { fetchDiscord } from "./core";
|
|
|
|
/**
|
|
* Represents a message sent in a channel within Discord.
|
|
* This is a partial interface based on the Discord API documentation.
|
|
*/
|
|
export interface Message {
|
|
id: string;
|
|
channel_id: string;
|
|
author: any; // User object
|
|
content: string;
|
|
timestamp: string; // ISO8601 timestamp
|
|
edited_timestamp: string | null; // ISO8601 timestamp
|
|
tts: boolean;
|
|
mention_everyone: boolean;
|
|
mentions: any[]; // array of user objects
|
|
mention_roles: string[]; // array of role object ids
|
|
mention_channels?: any[]; // array of channel mention objects
|
|
attachments: any[]; // array of attachment objects
|
|
embeds: any[]; // array of embed objects
|
|
reactions?: any[]; // array of reaction objects
|
|
nonce?: number | string;
|
|
pinned: boolean;
|
|
webhook_id?: string;
|
|
type: number;
|
|
activity?: any; // message activity object
|
|
application?: any; // partial application object
|
|
application_id?: string;
|
|
flags?: number;
|
|
message_reference?: any; // message reference object
|
|
referenced_message?: Message | null;
|
|
interaction?: any; // message interaction object
|
|
thread?: any; // channel object
|
|
components?: any[]; // array of message components
|
|
sticker_items?: any[]; // array of message sticker item objects
|
|
stickers?: any[]; // array of sticker objects
|
|
position?: number;
|
|
role_subscription_data?: any; // role subscription data object
|
|
resolved?: any;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the messages in a channel.
|
|
* @param channelId The ID of the channel.
|
|
* @param options Options for fetching messages.
|
|
* @returns An array of message objects.
|
|
*/
|
|
export const getChannelMessages = async (
|
|
channelId: string,
|
|
options?: {
|
|
around?: string;
|
|
before?: string;
|
|
after?: string;
|
|
limit?: number;
|
|
},
|
|
): Promise<Message[]> => {
|
|
const query = new URLSearchParams();
|
|
if (options?.around) query.append("around", options.around);
|
|
if (options?.before) query.append("before", options.before);
|
|
if (options?.after) query.append("after", options.after);
|
|
if (options?.limit) query.append("limit", String(options.limit));
|
|
|
|
const queryString = query.toString();
|
|
const path = `/channels/${channelId}/messages${queryString ? `?${queryString}` : ""}`;
|
|
|
|
const res = await fetchDiscord(path);
|
|
return res.json();
|
|
};
|
|
|
|
/**
|
|
* Retrieves a specific message in the channel.
|
|
* @param channelId The ID of the channel.
|
|
* @param messageId The ID of the message.
|
|
* @returns A message object.
|
|
*/
|
|
export const getChannelMessage = async (
|
|
channelId: string,
|
|
messageId: string,
|
|
): Promise<Message> => {
|
|
const path = `/channels/${channelId}/messages/${messageId}`;
|
|
const res = await fetchDiscord(path);
|
|
return res.json();
|
|
};
|
|
|
|
export interface CreateMessageParams {
|
|
content?: string;
|
|
tts?: boolean;
|
|
embeds?: any[];
|
|
allowed_mentions?: any;
|
|
message_reference?: any;
|
|
components?: any[];
|
|
sticker_ids?: string[];
|
|
files?: any[];
|
|
payload_json?: string;
|
|
attachments?: any[];
|
|
flags?: number;
|
|
}
|
|
|
|
/**
|
|
* Post a message to a guild text or DM channel.
|
|
* @param channelId The ID of the channel.
|
|
* @param data The message data.
|
|
* @returns The created message object.
|
|
*/
|
|
export const createMessage = async (
|
|
channelId: string,
|
|
data: CreateMessageParams,
|
|
): Promise<Message> => {
|
|
const path = `/channels/${channelId}/messages`;
|
|
const res = await fetchDiscord(path, {
|
|
method: "POST",
|
|
body: JSON.stringify(data),
|
|
});
|
|
return res.json();
|
|
};
|
|
|
|
export interface EditMessageParams {
|
|
content?: string;
|
|
embeds?: any[];
|
|
flags?: number;
|
|
allowed_mentions?: any;
|
|
components?: any[];
|
|
files?: any[];
|
|
payload_json?: string;
|
|
attachments?: any[];
|
|
}
|
|
|
|
/**
|
|
* Edit a previously sent message.
|
|
* @param channelId The ID of the channel.
|
|
* @param messageId The ID of the message to edit.
|
|
* @param data The new message data.
|
|
* @returns The updated message object.
|
|
*/
|
|
export const editMessage = async (
|
|
channelId: string,
|
|
messageId: string,
|
|
data: EditMessageParams,
|
|
): Promise<Message> => {
|
|
const path = `/channels/${channelId}/messages/${messageId}`;
|
|
const res = await fetchDiscord(path, {
|
|
method: "PATCH",
|
|
body: JSON.stringify(data),
|
|
});
|
|
return res.json();
|
|
};
|
|
|
|
/**
|
|
* Delete a message.
|
|
* @param channelId The ID of the channel.
|
|
* @param messageId The ID of the message to delete.
|
|
*/
|
|
export const deleteMessage = async (
|
|
channelId: string,
|
|
messageId: string,
|
|
): Promise<void> => {
|
|
const path = `/channels/${channelId}/messages/${messageId}`;
|
|
await fetchDiscord(path, {
|
|
method: "DELETE",
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Delete multiple messages in a single request.
|
|
* @param channelId The ID of the channel.
|
|
* @param messageIds An array of message IDs to delete.
|
|
*/
|
|
export const bulkDeleteMessages = async (
|
|
channelId: string,
|
|
messageIds: string[],
|
|
): Promise<void> => {
|
|
const path = `/channels/${channelId}/messages/bulk-delete`;
|
|
await fetchDiscord(path, {
|
|
method: "POST",
|
|
body: JSON.stringify({ messages: messageIds }),
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Create a reaction for the message.
|
|
* @param channelId The ID of the channel.
|
|
* @param messageId The ID of the message.
|
|
* @param emoji The emoji to react with.
|
|
*/
|
|
export const addReaction = async (
|
|
channelId: string,
|
|
messageId: string,
|
|
emoji: string,
|
|
): Promise<void> => {
|
|
const path = `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(
|
|
emoji,
|
|
)}/@me`;
|
|
await fetchDiscord(path, { method: "PUT" });
|
|
};
|
|
|
|
/**
|
|
* Get a list of users that reacted with this emoji.
|
|
* @param channelId The ID of the channel.
|
|
* @param messageId The ID of the message.
|
|
* @param emoji The emoji.
|
|
* @param options Options for fetching reactions.
|
|
* @returns A list of user objects.
|
|
*/
|
|
export const getReactions = async (
|
|
channelId: string,
|
|
messageId: string,
|
|
emoji: string,
|
|
options?: { after?: string; limit?: number },
|
|
): Promise<any[]> => {
|
|
const query = new URLSearchParams();
|
|
if (options?.after) query.append("after", options.after);
|
|
if (options?.limit) query.append("limit", String(options.limit ?? 100));
|
|
const queryString = query.toString();
|
|
const path = `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(
|
|
emoji,
|
|
)}${queryString ? `?${queryString}` : ""}`;
|
|
const res = await fetchDiscord(path);
|
|
return res.json();
|
|
};
|
|
|
|
export const listReactionUsersMulti = async (
|
|
channelId: string,
|
|
messageId: string,
|
|
emojis: string[],
|
|
) => {
|
|
const results = await Promise.all(
|
|
emojis.map((e) => getReactions(channelId, messageId, e)),
|
|
);
|
|
const byId = new Map<string, any>();
|
|
for (const arr of results) {
|
|
for (const u of arr) byId.set(u.id, u); // de-dupe across variants
|
|
}
|
|
return Array.from(byId.values());
|
|
};
|