diff --git a/package-lock.json b/package-lock.json index 32f43c9d..431fd811 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8031,9 +8031,9 @@ "link": true }, "node_modules/discord-api-types": { - "version": "0.37.4", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.4.tgz", - "integrity": "sha512-QgqYlUokWM++hdwvAtgVNLjmFumPBzFy+uWnnfVDiwBXKm+5jXHJPk2lx2eilkv/706UpAJPLSk/uVCY9NocjA==" + "version": "0.37.15", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.15.tgz", + "integrity": "sha512-2SpscsamTtctJflnz1J6cPp99PLs10DNGi2rrOdjID3KhP1nwsoJHPvcLe6zwcYxZnRdA/71M85RCNOQl83u1A==" }, "node_modules/discord-edge-runner": { "resolved": "packages/discord-edge-runner", @@ -22229,7 +22229,7 @@ "license": "MIT", "dependencies": { "debug": "^4.3.4", - "discord-api-types": "^0.37.4", + "discord-api-types": "^0.37.15", "discord-request": "0.0.5", "discord-snowflake": "2.0.0" }, @@ -22343,7 +22343,7 @@ "boxen": "7.0.0", "chalk": "^5.0.1", "discord-api": "0.0.3", - "discord-api-types": "^0.37.4", + "discord-api-types": "^0.37.15", "discord-edge-runner": "0.0.2", "discord-request": "0.0.5", "discord-snowflake": "2.0.0", @@ -27726,15 +27726,15 @@ "version": "file:packages/discord-api", "requires": { "debug": "^4.3.4", - "discord-api-types": "^0.37.4", + "discord-api-types": "^0.37.15", "discord-request": "0.0.5", "discord-snowflake": "2.0.0" } }, "discord-api-types": { - "version": "0.37.4", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.4.tgz", - "integrity": "sha512-QgqYlUokWM++hdwvAtgVNLjmFumPBzFy+uWnnfVDiwBXKm+5jXHJPk2lx2eilkv/706UpAJPLSk/uVCY9NocjA==" + "version": "0.37.15", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.15.tgz", + "integrity": "sha512-2SpscsamTtctJflnz1J6cPp99PLs10DNGi2rrOdjID3KhP1nwsoJHPvcLe6zwcYxZnRdA/71M85RCNOQl83u1A==" }, "discord-edge-runner": { "version": "file:packages/discord-edge-runner", @@ -29918,7 +29918,7 @@ "boxen": "7.0.0", "chalk": "^5.0.1", "discord-api": "0.0.3", - "discord-api-types": "^0.37.4", + "discord-api-types": "^0.37.15", "discord-edge-runner": "0.0.2", "discord-request": "0.0.5", "discord-snowflake": "2.0.0", diff --git a/packages/discord-api/package.json b/packages/discord-api/package.json index a41d1768..ba196361 100644 --- a/packages/discord-api/package.json +++ b/packages/discord-api/package.json @@ -25,7 +25,7 @@ "node": ">=18" }, "dependencies": { - "discord-api-types": "^0.37.4", + "discord-api-types": "^0.37.15", "discord-request": "0.0.5", "discord-snowflake": "2.0.0", "debug": "^4.3.4" diff --git a/packages/discord-api/src/headers/audit-log.ts b/packages/discord-api/src/headers/audit-log.ts new file mode 100644 index 00000000..4a722b55 --- /dev/null +++ b/packages/discord-api/src/headers/audit-log.ts @@ -0,0 +1,9 @@ +export function getAuditLogHeaders(auditLogReason: string | undefined) { + const headers = new Headers(); + + if (auditLogReason != null) { + headers.set("X-Audit-Log-Reason", auditLogReason); + } + + return headers; +} diff --git a/packages/discord-api/src/index.ts b/packages/discord-api/src/index.ts index 8aa57e21..c619548f 100644 --- a/packages/discord-api/src/index.ts +++ b/packages/discord-api/src/index.ts @@ -1,4 +1,6 @@ export * from "./client.js"; -export * from "./routes/commands.js"; +export * from "./routes/application-commands.js"; +export * from "./routes/audit-log.js"; +export * from "./routes/auto-moderation.js"; export * from "./routes/guild.js"; export * from "./routes/interactions.js"; diff --git a/packages/discord-api/src/routes/commands.ts b/packages/discord-api/src/routes/application-commands.ts similarity index 100% rename from packages/discord-api/src/routes/commands.ts rename to packages/discord-api/src/routes/application-commands.ts diff --git a/packages/discord-api/src/routes/audit-log.ts b/packages/discord-api/src/routes/audit-log.ts new file mode 100644 index 00000000..14c5b864 --- /dev/null +++ b/packages/discord-api/src/routes/audit-log.ts @@ -0,0 +1,16 @@ +import type { RESTGetAPIAuditLogResult } from "discord-api-types/v10"; +import { Routes } from "discord-api-types/v10"; +import type { Snowflake } from "discord-snowflake"; +import { client } from "../client.js"; + +/** + * Get the Audit Log for a Guild. + * {@link https://discord.com/developers/docs/resources/audit-log#get-guild-audit-log | Discord Documentation} + * @param guildId - TThe target Guild to get the Audit Log in. + * @returns The Audit Log for the Guild. + */ +export async function getGuildAuditLog(guildId: Snowflake) { + return client.get( + Routes.guildAuditLog(guildId) + ) as Promise; +} diff --git a/packages/discord-api/src/routes/auto-moderation.ts b/packages/discord-api/src/routes/auto-moderation.ts new file mode 100644 index 00000000..d6a3206e --- /dev/null +++ b/packages/discord-api/src/routes/auto-moderation.ts @@ -0,0 +1,97 @@ +import type { + RESTDeleteAPIAutoModerationRuleResult, + RESTGetAPIAutoModerationRuleResult, + RESTGetAPIAutoModerationRulesResult, + RESTPatchAPIAutoModerationRuleResult, + RESTPostAPIAutoModerationRuleJSONBody, + RESTPostAPIAutoModerationRuleResult, +} from "discord-api-types/v10"; +import { Routes } from "discord-api-types/v10"; +import type { Snowflake } from "discord-snowflake"; +import { client } from "../client.js"; +import { getAuditLogHeaders } from "../headers/audit-log.js"; + +/** + * Get a list of all Auto Moderation Rules. + * {@link https://discord.com/developers/docs/resources/auto-moderation#list-auto-moderation-rules-for-guild | Discord Documentation} + * @param guildId - The target Guild to view the Rules in. + * @returns A list of all the Auto Moderation Rules. + */ +export async function getAutoModerationRules(guildId: Snowflake) { + return client.get( + Routes.guildAutoModerationRules(guildId) + ) as Promise; +} + +/** + * Get an Auto Moderation Rule. + * {@link https://discord.com/developers/docs/resources/auto-moderation#get-auto-moderation-rule | Discord Documentation} + * @param guildId - The target Guild to get the Rule in. + * @param ruleId - The target Rule to view. + * @returns The Auto Moderation Rule. + */ +export async function getAutoModerationRule( + guildId: Snowflake, + ruleId: Snowflake +) { + return client.get( + Routes.guildAutoModerationRule(guildId, ruleId) + ) as Promise; +} + +/** + * Creates an Auto Moderation Rule. + * {@link https://discord.com/developers/docs/resources/auto-moderation#create-auto-moderation-rule | Discord Documentation} + * @param guildId - The target Guild to create the Rule in. + * @param data - The data to use for the new Rule. + * @param auditLogReason - An optional Audit Log entry to record this action under. + * @returns The created Auto Moderation Rule. + */ +export async function createAutoModerationRule( + guildId: Snowflake, + data: RESTPostAPIAutoModerationRuleJSONBody, + auditLogReason?: string +) { + return client.post(Routes.guildAutoModerationRules(guildId), { + body: data, + headers: getAuditLogHeaders(auditLogReason), + }) as Promise; +} + +/** + * Updates an Auto Moderation Rule. + * {@link https://discord.com/developers/docs/resources/auto-moderation#modify-auto-moderation-rule | Discord Documentation} + * @param guildId - The target Guild to update the Rule in. + * @param ruleId - The target Rule to update. + * @param data - The new data to use for the Rule. + * @param auditLogReason - An optional Audit Log entry to record this action under. + * @returns The updated Auto Moderation Rule. + */ +export async function updateAutoModerationRule( + guildId: Snowflake, + ruleId: Snowflake, + data: RESTPostAPIAutoModerationRuleJSONBody, + auditLogReason?: string +) { + return client.patch(Routes.guildAutoModerationRule(guildId, ruleId), { + body: data, + headers: getAuditLogHeaders(auditLogReason), + }) as Promise; +} + +/** + * Deletes an Auto Moderation Rule. + * {@link https://discord.com/developers/docs/resources/auto-moderation#delete-auto-moderation-rule | Discord Documentation} + * @param guildId - The target Guild to delete the Rule from. + * @param ruleId - The target Rule to delete. + * @param auditLogReason - An optional Audit Log entry to record this action under. + */ +export async function deleteAutoModerationRule( + guildId: Snowflake, + ruleId: Snowflake, + auditLogReason?: string +) { + return client.delete(Routes.guildAutoModerationRule(guildId, ruleId), { + headers: getAuditLogHeaders(auditLogReason), + }) as Promise; +} diff --git a/packages/discord-api/src/routes/channel.tsx b/packages/discord-api/src/routes/channel.tsx new file mode 100644 index 00000000..b07c8a75 --- /dev/null +++ b/packages/discord-api/src/routes/channel.tsx @@ -0,0 +1,56 @@ +import type { + RESTDeleteAPIChannelResult, + RESTGetAPIChannelResult, + RESTPatchAPIChannelJSONBody, + RESTPatchAPIChannelResult, +} from "discord-api-types/v10"; +import { Routes } from "discord-api-types/v10"; +import type { Snowflake } from "discord-snowflake"; +import { client } from "../client.js"; +import { getAuditLogHeaders } from "../headers/audit-log.js"; + +/** + * Get a Channel. + * {@link https://discord.com/developers/docs/resources/channel#get-channel | Discord Documentation} + * @param channelId - The target Channel to get. + * @returns The Channel. + */ +export async function getChannel(channelId: Snowflake) { + return client.get( + Routes.channel(channelId) + ) as Promise; +} + +/** + * Updates a Channel. + * {@link https://discord.com/developers/docs/resources/channel#modify-channel | Discord Documentation} + * @param channelId - The target Channel to update. + * @param data - The new data to use for the Channel. + * @param auditLogReason - An optional Audit Log entry to record this action under. + * @returns The updated Channel. + */ +export async function updateChannel( + channelId: Snowflake, + data: RESTPatchAPIChannelJSONBody, + auditLogReason?: string +) { + return client.patch(Routes.channel(channelId), { + body: data, + headers: getAuditLogHeaders(auditLogReason), + }) as Promise; +} + +/** + * Deletes a channel or closes a private message. + * @param channelId - The target Channel to delete. + * @param auditLogReason - An optional Audit Log entry to record this action under. + * @returns The deleted Channel. + */ +export async function deleteChannel( + channelId: Snowflake, + auditLogReason?: string +) { + return client.delete(Routes.channel(channelId), { + headers: getAuditLogHeaders(auditLogReason), + }) as Promise; +} diff --git a/packages/discord-api/src/routes/messages.tsx b/packages/discord-api/src/routes/messages.tsx new file mode 100644 index 00000000..8d3dd48b --- /dev/null +++ b/packages/discord-api/src/routes/messages.tsx @@ -0,0 +1,62 @@ +import type { + RESTGetAPIChannelMessageResult, + RESTGetAPIChannelMessagesQuery, + RESTGetAPIChannelMessagesResult, + RESTPostAPIChannelMessageJSONBody, + RESTPostAPIChannelMessageResult, +} from "discord-api-types/v10"; +import { Routes } from "discord-api-types/v10"; +import type { Snowflake } from "discord-snowflake"; +import { client } from "../client.js"; + +/** + * Returns an array of Messages for a Channel. + * {@link https://discord.com/developers/docs/resources/channel#get-channel-messages | Discord Documentation} + * @param channelId - The target Channel to get Messages in. + * @returns An array of Messages + */ +export async function getMessages( + channelId: Snowflake, + params?: RESTGetAPIChannelMessagesQuery +) { + const query = new URLSearchParams(); + + if (params) { + Object.entries(params).forEach(([key, value]) => { + query.set(key, value); + }); + } + + return client.get(Routes.channelMessages(channelId), { + query, + }) as Promise; +} + +/** + * Get a Message. + * {@link https://discord.com/developers/docs/resources/channel#get-channel-message | Discord Documentation} + * @param channelId - The target Channel to get the Message in. + * @param messageId - The target Message to get. + * @returns The Message. + */ +export async function getMessage(channelId: Snowflake, messageId: Snowflake) { + return client.get( + Routes.channelMessage(channelId, messageId) + ) as Promise; +} + +/** + * Posts a Message to a Channel. + * {@link https://discord.com/developers/docs/resources/channel#create-message | Discord Documentation} + * @param channelId - The target Channel to post the Message in. + * @param data - The Message content. + * @returns The created Message. + */ +export async function createMessage( + channelId: Snowflake, + data: RESTPostAPIChannelMessageJSONBody +) { + return client.post(Routes.channelMessages(channelId), { + body: data, + }) as Promise; +} diff --git a/packages/discord-api/src/routes/webhook.ts b/packages/discord-api/src/routes/webhook.ts new file mode 100644 index 00000000..83945a02 --- /dev/null +++ b/packages/discord-api/src/routes/webhook.ts @@ -0,0 +1,32 @@ +import type { + RESTPostAPIChannelWebhookJSONBody, + RESTPostAPIChannelWebhookResult, +} from "discord-api-types/v10"; +import { Routes } from "discord-api-types/v10"; +import type { Snowflake } from "discord-snowflake"; +import { client } from "../client.js"; + +/** + * Creates a Channel Webhook. + * {@link https://discord.com/developers/docs/resources/webhook#create-webhook | Discord Documentation} + * @param channelId - The Channel to create the webhook in + * @param data - The Webhook name and avatar + * @param auditLogReason - An optional entry to add to the audit log + * @returns The created Webhook + */ +export async function createWebhook( + channelId: Snowflake, + data: RESTPostAPIChannelWebhookJSONBody, + auditLogReason?: string +) { + const headers = new Headers(); + + if (auditLogReason != null) { + headers.set("X-Audit-Log-Reason", auditLogReason); + } + + return client.post(Routes.channelWebhooks(channelId), { + body: data, + headers, + }) as Promise; +} diff --git a/packages/discord-api/test/client.test.ts b/packages/discord-api/test/client.test.ts deleted file mode 100644 index 6388b9ce..00000000 --- a/packages/discord-api/test/client.test.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { expect, test } from "vitest"; - -test("discord-api", () => { - expect(true).toBe(true); -}); diff --git a/packages/discord-api/test/index.test.ts b/packages/discord-api/test/index.test.ts new file mode 100644 index 00000000..2399632e --- /dev/null +++ b/packages/discord-api/test/index.test.ts @@ -0,0 +1,27 @@ +import { expect, test } from "vitest"; +import * as API from "../src/index"; + +test("API is backwards compatible", () => { + expect(Object.keys(API)).toMatchInlineSnapshot(` + [ + "DiscordApiClient", + "client", + "getGlobalApplicationCommands", + "createGlobalApplicationCommand", + "getGlobalApplicationCommand", + "editGlobalApplicationCommand", + "deleteGlobalApplicationCommand", + "bulkOverwriteGlobalApplicationCommands", + "getGuildApplicationCommands", + "createGuildApplicationCommand", + "getGuildApplicationCommand", + "editGuildApplicationCommands", + "deleteGuildApplicationCommand", + "bulkOverwriteGuildApplicationCommands", + "getGuild", + "createInteractionFollowup", + "editInteractionFollowup", + "deleteInteractionFollowup", + ] + `); +}); diff --git a/packages/interaction-kit/package.json b/packages/interaction-kit/package.json index 827fe06a..0ddf8b8a 100644 --- a/packages/interaction-kit/package.json +++ b/packages/interaction-kit/package.json @@ -31,7 +31,7 @@ "boxen": "7.0.0", "chalk": "^5.0.1", "discord-api": "0.0.3", - "discord-api-types": "^0.37.4", + "discord-api-types": "^0.37.15", "discord-edge-runner": "0.0.2", "discord-request": "0.0.5", "discord-snowflake": "2.0.0",