feat: implement audit log, core fetch functionality, guild management, message handling, and poll features
This commit is contained in:
parent
5b4832a2cb
commit
6272bb62ff
53
src/discord/audit-log.ts
Normal file
53
src/discord/audit-log.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { fetchDiscord } from "./core";
|
||||||
|
|
||||||
|
export interface AuditLog {
|
||||||
|
application_commands: any[];
|
||||||
|
audit_log_entries: AuditLogEntry[];
|
||||||
|
auto_moderation_rules: any[];
|
||||||
|
guild_scheduled_events: any[];
|
||||||
|
integrations: any[];
|
||||||
|
threads: any[];
|
||||||
|
users: any[];
|
||||||
|
webhooks: any[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AuditLogEntry {
|
||||||
|
target_id: string | null;
|
||||||
|
changes?: AuditLogChange[];
|
||||||
|
user_id: string | null;
|
||||||
|
id: string;
|
||||||
|
action_type: number;
|
||||||
|
options?: any;
|
||||||
|
reason?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AuditLogChange {
|
||||||
|
new_value?: any;
|
||||||
|
old_value?: any;
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getAuditLog = async (options: {
|
||||||
|
guildId: string;
|
||||||
|
userId?: string;
|
||||||
|
actionType?: number;
|
||||||
|
before?: string;
|
||||||
|
after?: string;
|
||||||
|
limit?: number;
|
||||||
|
}): Promise<AuditLog> => {
|
||||||
|
const { guildId, userId, actionType, before, after, limit } = options;
|
||||||
|
const query = new URLSearchParams();
|
||||||
|
if (userId) query.append("user_id", userId);
|
||||||
|
if (actionType) query.append("action_type", String(actionType));
|
||||||
|
if (before) query.append("before", before);
|
||||||
|
if (after) query.append("after", after);
|
||||||
|
if (limit) query.append("limit", String(limit));
|
||||||
|
|
||||||
|
const queryString = query.toString();
|
||||||
|
const path = `/guilds/${guildId}/audit-logs${
|
||||||
|
queryString ? `?${queryString}` : ""
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const response = await fetchDiscord(path);
|
||||||
|
return response.json();
|
||||||
|
};
|
||||||
21
src/discord/core.ts
Normal file
21
src/discord/core.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { Config } from "../config";
|
||||||
|
|
||||||
|
export const fetchDiscord = async (
|
||||||
|
path: string,
|
||||||
|
init?: RequestInit,
|
||||||
|
): Promise<Response> => {
|
||||||
|
const response = await fetch(`${Config.DISCORD_API}${path}`, {
|
||||||
|
...init,
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bot ${Config.BOT_TOKEN}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
...(init?.headers || {}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (response.status === 429) {
|
||||||
|
const data = await response.json().catch(() => ({}) as any);
|
||||||
|
const retry = (data?.retry_after ? Number(data.retry_after) : 1) * 1000;
|
||||||
|
await new Promise((r) => setTimeout(r, retry));
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
};
|
||||||
252
src/discord/guild.ts
Normal file
252
src/discord/guild.ts
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
import { fetchDiscord } from "./core";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a Discord guild.
|
||||||
|
* This is a partial interface based on the Discord API documentation.
|
||||||
|
*/
|
||||||
|
export interface Guild {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
icon: string | null;
|
||||||
|
owner_id: string;
|
||||||
|
verification_level: number;
|
||||||
|
roles: any[]; // Array of role objects
|
||||||
|
emojis: any[]; // Array of emoji objects
|
||||||
|
features: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a Guild Member.
|
||||||
|
* This is a partial interface.
|
||||||
|
*/
|
||||||
|
export interface GuildMember {
|
||||||
|
user?: any; // User object
|
||||||
|
nick?: string | null;
|
||||||
|
roles: string[];
|
||||||
|
joined_at: string; // ISO8601 timestamp
|
||||||
|
deaf: boolean;
|
||||||
|
mute: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a Role.
|
||||||
|
*/
|
||||||
|
export interface Role {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
color: number;
|
||||||
|
hoist: boolean;
|
||||||
|
position: number;
|
||||||
|
permissions: string;
|
||||||
|
managed: boolean;
|
||||||
|
mentionable: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a Ban.
|
||||||
|
*/
|
||||||
|
export interface Ban {
|
||||||
|
reason: string | null;
|
||||||
|
user: any; // User object
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a guild by ID.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param withCounts Whether to include approximate member and presence counts.
|
||||||
|
* @returns A guild object.
|
||||||
|
*/
|
||||||
|
export const getGuild = async (
|
||||||
|
guildId: string,
|
||||||
|
withCounts?: boolean,
|
||||||
|
): Promise<Guild> => {
|
||||||
|
const path = `/guilds/${guildId}${withCounts ? "?with_counts=true" : ""}`;
|
||||||
|
const res = await fetchDiscord(path);
|
||||||
|
return res.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify a guild's settings.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param data The new guild data.
|
||||||
|
* @returns The updated guild object.
|
||||||
|
*/
|
||||||
|
export const modifyGuild = async (
|
||||||
|
guildId: string,
|
||||||
|
data: any,
|
||||||
|
): Promise<Guild> => {
|
||||||
|
const path = `/guilds/${guildId}`;
|
||||||
|
const res = await fetchDiscord(path, {
|
||||||
|
method: "PATCH",
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
});
|
||||||
|
return res.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of guild channel objects.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @returns A list of channel objects.
|
||||||
|
*/
|
||||||
|
export const getGuildChannels = async (guildId: string): Promise<any[]> => {
|
||||||
|
const path = `/guilds/${guildId}/channels`;
|
||||||
|
const res = await fetchDiscord(path);
|
||||||
|
return res.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new channel object for the guild.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param data The channel data.
|
||||||
|
* @returns The new channel object.
|
||||||
|
*/
|
||||||
|
export const createGuildChannel = async (
|
||||||
|
guildId: string,
|
||||||
|
data: any,
|
||||||
|
): Promise<any> => {
|
||||||
|
const path = `/guilds/${guildId}/channels`;
|
||||||
|
const res = await fetchDiscord(path, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
});
|
||||||
|
return res.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of guild member objects that are members of the guild.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param options Options for listing members.
|
||||||
|
* @returns A list of guild member objects.
|
||||||
|
*/
|
||||||
|
export const listGuildMembers = async (
|
||||||
|
guildId: string,
|
||||||
|
options?: { limit?: number; after?: string },
|
||||||
|
): Promise<GuildMember[]> => {
|
||||||
|
const query = new URLSearchParams();
|
||||||
|
if (options?.limit) query.append("limit", String(options.limit));
|
||||||
|
if (options?.after) query.append("after", options.after);
|
||||||
|
const queryString = query.toString();
|
||||||
|
const path = `/guilds/${guildId}/members${queryString ? `?${queryString}` : ""}`;
|
||||||
|
const res = await fetchDiscord(path);
|
||||||
|
return res.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a guild member object for the specified user.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param userId The ID of the user.
|
||||||
|
* @returns A guild member object.
|
||||||
|
*/
|
||||||
|
export const getGuildMember = async (
|
||||||
|
guildId: string,
|
||||||
|
userId: string,
|
||||||
|
): Promise<GuildMember> => {
|
||||||
|
const path = `/guilds/${guildId}/members/${userId}`;
|
||||||
|
const res = await fetchDiscord(path);
|
||||||
|
return res.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify attributes of a guild member.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param userId The ID of the user.
|
||||||
|
* @param data The data to update.
|
||||||
|
* @returns The updated guild member.
|
||||||
|
*/
|
||||||
|
export const modifyGuildMember = async (
|
||||||
|
guildId: string,
|
||||||
|
userId: string,
|
||||||
|
data: any,
|
||||||
|
): Promise<GuildMember> => {
|
||||||
|
const path = `/guilds/${guildId}/members/${userId}`;
|
||||||
|
const res = await fetchDiscord(path, {
|
||||||
|
method: "PATCH",
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
});
|
||||||
|
return res.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a member from a guild.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param userId The ID of the user to remove.
|
||||||
|
*/
|
||||||
|
export const removeGuildMember = async (
|
||||||
|
guildId: string,
|
||||||
|
userId: string,
|
||||||
|
): Promise<void> => {
|
||||||
|
const path = `/guilds/${guildId}/members/${userId}`;
|
||||||
|
await fetchDiscord(path, {
|
||||||
|
method: "DELETE",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of role objects for the guild.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @returns A list of role objects.
|
||||||
|
*/
|
||||||
|
export const getGuildRoles = async (guildId: string): Promise<Role[]> => {
|
||||||
|
const path = `/guilds/${guildId}/roles`;
|
||||||
|
const res = await fetchDiscord(path);
|
||||||
|
return res.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of ban objects for the users banned from this guild.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @returns A list of ban objects.
|
||||||
|
*/
|
||||||
|
export const getGuildBans = async (guildId: string): Promise<Ban[]> => {
|
||||||
|
const path = `/guilds/${guildId}/bans`;
|
||||||
|
const res = await fetchDiscord(path);
|
||||||
|
return res.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a guild ban, and optionally delete previous messages sent by the banned user.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param userId The ID of the user to ban.
|
||||||
|
* @param options Options for the ban.
|
||||||
|
*/
|
||||||
|
export const createGuildBan = async (
|
||||||
|
guildId: string,
|
||||||
|
userId: string,
|
||||||
|
options?: { delete_message_seconds?: number },
|
||||||
|
): Promise<void> => {
|
||||||
|
const path = `/guilds/${guildId}/bans/${userId}`;
|
||||||
|
await fetchDiscord(path, {
|
||||||
|
method: "PUT",
|
||||||
|
body: JSON.stringify(options),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the ban for a user.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param userId The ID of the user to unban.
|
||||||
|
*/
|
||||||
|
export const removeGuildBan = async (
|
||||||
|
guildId: string,
|
||||||
|
userId: string,
|
||||||
|
): Promise<void> => {
|
||||||
|
const path = `/guilds/${guildId}/bans/${userId}`;
|
||||||
|
await fetchDiscord(path, {
|
||||||
|
method: "DELETE",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a role from a guild member.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param userId The ID of the user.
|
||||||
|
* @param roleId The ID of the role to remove.
|
||||||
|
*/
|
||||||
|
export const removeGuildMemberRole = async (
|
||||||
|
guildId: string,
|
||||||
|
userId: string,
|
||||||
|
roleId: string,
|
||||||
|
): Promise<void> => {
|
||||||
|
const path = `/guilds/${guildId}/members/${userId}/roles/${roleId}`;
|
||||||
|
await fetchDiscord(path, { method: "DELETE" });
|
||||||
|
};
|
||||||
5
src/discord/index.ts
Normal file
5
src/discord/index.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export * from "./audit-log";
|
||||||
|
export * from "./core";
|
||||||
|
export * from "./guild";
|
||||||
|
export * from "./message";
|
||||||
|
export * from "./poll";
|
||||||
219
src/discord/message.ts
Normal file
219
src/discord/message.ts
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
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();
|
||||||
|
};
|
||||||
81
src/discord/poll.ts
Normal file
81
src/discord/poll.ts
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import { fetchDiscord } from "./core";
|
||||||
|
import { Message } from "./message";
|
||||||
|
|
||||||
|
export interface PollMedia {
|
||||||
|
text?: string;
|
||||||
|
emoji?: any; // Partial Emoji
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PollAnswer {
|
||||||
|
answer_id: number;
|
||||||
|
poll_media: PollMedia;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PollAnswerCount {
|
||||||
|
id: number;
|
||||||
|
count: number;
|
||||||
|
me_voted: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PollResults {
|
||||||
|
is_finalized: boolean;
|
||||||
|
answer_counts: PollAnswerCount[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Poll {
|
||||||
|
question: PollMedia;
|
||||||
|
answers: PollAnswer[];
|
||||||
|
expiry: string | null; // ISO8601 timestamp
|
||||||
|
allow_multiselect: boolean;
|
||||||
|
layout_type: number;
|
||||||
|
results?: PollResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PollCreateRequest {
|
||||||
|
question: PollMedia;
|
||||||
|
answers: PollAnswer[];
|
||||||
|
duration?: number;
|
||||||
|
allow_multiselect?: boolean;
|
||||||
|
layout_type?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of users that voted for a specific answer.
|
||||||
|
* @param channelId The ID of the channel.
|
||||||
|
* @param messageId The ID of the message with the poll.
|
||||||
|
* @param answerId The ID of the answer.
|
||||||
|
* @param options Options for fetching voters.
|
||||||
|
* @returns A list of user objects.
|
||||||
|
*/
|
||||||
|
export const getAnswerVoters = async (
|
||||||
|
channelId: string,
|
||||||
|
messageId: string,
|
||||||
|
answerId: number,
|
||||||
|
options?: { after?: string; limit?: number },
|
||||||
|
): Promise<{ users: any[] }> => {
|
||||||
|
const query = new URLSearchParams();
|
||||||
|
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}/polls/${messageId}/answers/${answerId}${queryString ? `?${queryString}` : ""}`;
|
||||||
|
const res = await fetchDiscord(path);
|
||||||
|
return res.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immediately ends a poll.
|
||||||
|
* @param channelId The ID of the channel.
|
||||||
|
* @param messageId The ID of the message with the poll.
|
||||||
|
* @returns The updated message object.
|
||||||
|
*/
|
||||||
|
export const endPoll = async (
|
||||||
|
channelId: string,
|
||||||
|
messageId: string,
|
||||||
|
): Promise<Message> => {
|
||||||
|
const path = `/channels/${channelId}/polls/${messageId}/expire`;
|
||||||
|
const res = await fetchDiscord(path, {
|
||||||
|
method: "POST",
|
||||||
|
});
|
||||||
|
return res.json();
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user