Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"prettier": "turbo run prettier",
"lint": "turbo run lint",
"pretest": "npm run clean && npm run build",
"test": "vitest run",
"test": "NODE_OPTIONS='--es-module-specifier-resolution=node' vitest run",
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love this, but ckohen tells me to not need it I gotta make my code ugly sadface emoji

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That implies your code isn't ugly already 😆

"version": "npx changeset version",
"changeset": "npx changeset add",
"publish": "npx changeset publish"
Expand Down
2 changes: 1 addition & 1 deletion packages/discord-api/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Client from "discord-request";
import pkg from "../package.json" assert { type: "json" };
import pkg from "../package.json";

export class DiscordApiClient extends Client {
get userAgent() {
Expand Down
72 changes: 49 additions & 23 deletions packages/discord-api/src/routes/commands.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type {
RESTGetAPIApplicationCommandResult,
RESTGetAPIApplicationCommandsResult,
RESTGetAPIApplicationGuildCommandResult,
RESTGetAPIApplicationGuildCommandsResult,
RESTPatchAPIApplicationCommandJSONBody,
RESTPatchAPIApplicationCommandResult,
RESTPatchAPIApplicationGuildCommandJSONBody,
RESTPatchAPIApplicationGuildCommandResult,
RESTPostAPIApplicationCommandsJSONBody,
RESTPostAPIApplicationCommandsResult,
RESTPostAPIApplicationGuildCommandsJSONBody,
Expand All @@ -18,6 +18,10 @@ import { Routes } from "discord-api-types/v10";
import type { Snowflake } from "discord-snowflake";
import { client } from "../client";

/**
* Global Commands
*/

// TODO: Test, Document
export async function getGlobalApplicationCommands(applicationId: Snowflake) {
return client.get(
Expand All @@ -26,7 +30,7 @@ export async function getGlobalApplicationCommands(applicationId: Snowflake) {
}

// TODO: Test, Document
export async function postGlobalApplicationCommand(
export async function createGlobalApplicationCommand(
applicationId: Snowflake,
command: RESTPostAPIApplicationCommandsJSONBody
) {
Expand All @@ -36,17 +40,17 @@ export async function postGlobalApplicationCommand(
}

// TODO: Test, Document
export async function putGlobalApplicationCommands(
export async function getGlobalApplicationCommand(
applicationId: Snowflake,
commands: RESTPutAPIApplicationCommandsJSONBody
commandId: Snowflake
) {
return client.put(Routes.applicationCommands(applicationId), {
body: commands,
}) as Promise<RESTPutAPIApplicationCommandsResult>;
return client.get(
Routes.applicationCommand(applicationId, commandId)
) as Promise<RESTGetAPIApplicationCommandResult>;
}

// TODO: Test, Document
export async function patchGlobalApplicationCommand(
export async function editGlobalApplicationCommand(
applicationId: Snowflake,
command: RESTPatchAPIApplicationCommandJSONBody & { id: Snowflake }
) {
Expand All @@ -63,6 +67,20 @@ export async function deleteGlobalApplicationCommand(
return client.delete(Routes.applicationCommand(applicationId, commandId));
}

// TODO: Test, Document
export async function bulkOverwriteGlobalApplicationCommands(
applicationId: Snowflake,
commands: RESTPutAPIApplicationCommandsJSONBody
) {
return client.put(Routes.applicationCommands(applicationId), {
body: commands,
}) as Promise<RESTPutAPIApplicationCommandsResult>;
}

/**
* Guild Commands
*/

// TODO: Test, Document
export async function getGuildApplicationCommands(
applicationId: Snowflake,
Expand All @@ -74,7 +92,7 @@ export async function getGuildApplicationCommands(
}

// TODO: Test, Document
export async function postGuildApplicationCommand(
export async function createGuildApplicationCommand(
applicationId: Snowflake,
guildId: Snowflake,
command: RESTPostAPIApplicationGuildCommandsJSONBody
Expand All @@ -85,28 +103,25 @@ export async function postGuildApplicationCommand(
}

// TODO: Test, Document
export async function putGuildApplicationCommands(
export async function getGuildApplicationCommand(
applicationId: Snowflake,
guildId: Snowflake,
commands: RESTPutAPIApplicationGuildCommandsJSONBody
commandId: Snowflake
) {
return client.put(Routes.applicationGuildCommands(applicationId, guildId), {
body: commands,
}) as Promise<RESTPutAPIApplicationGuildCommandsResult>;
return client.get(
Routes.applicationGuildCommand(applicationId, guildId, commandId)
) as Promise<RESTGetAPIApplicationGuildCommandResult>;
}

// TODO: Test, Document
export async function patchGuildApplicationCommand(
export async function editGuildApplicationCommands(
applicationId: Snowflake,
guildId: Snowflake,
command: RESTPatchAPIApplicationGuildCommandJSONBody & { id: Snowflake }
commands: RESTPutAPIApplicationGuildCommandsJSONBody
) {
return client.patch(
Routes.applicationGuildCommand(applicationId, guildId, command.id),
{
body: command,
}
) as Promise<RESTPatchAPIApplicationGuildCommandResult>;
return client.put(Routes.applicationGuildCommands(applicationId, guildId), {
body: commands,
}) as Promise<RESTPutAPIApplicationGuildCommandsResult>;
}

// TODO: Test, Document
Expand All @@ -119,3 +134,14 @@ export async function deleteGuildApplicationCommand(
Routes.applicationGuildCommand(applicationId, guildId, commandId)
);
}

// TODO: Test, Document
export async function bulkOverwriteGuildApplicationCommands(
applicationId: Snowflake,
guildId: Snowflake,
commands: RESTPutAPIApplicationGuildCommandsJSONBody
) {
return client.put(Routes.applicationGuildCommands(applicationId, guildId), {
body: commands,
}) as Promise<RESTPutAPIApplicationCommandsResult>;
}
14 changes: 12 additions & 2 deletions packages/discord-api/src/routes/interactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { Snowflake } from "discord-snowflake";
import { client } from "../client";

// TODO: Test, Document
export async function postInteractionFollowup(
export async function createInteractionFollowup(
applicationId: Snowflake,
interactionToken: string,
data: RESTPostAPIInteractionFollowupJSONBody
Expand All @@ -20,8 +20,18 @@ export async function postInteractionFollowup(
}) as Promise<RESTPostAPIInteractionFollowupResult>;
}

// export async function getInteractionFollowup(
// applicationId: Snowflake,
// interactionToken: string,
// messageId: Snowflake
// ) {
// return client.get(
// Routes.webhook(applicationId, interactionToken, messageId)
// ) as Promise<RESTGetAPIInteractionFollowupResult>;
// }

// TODO: Test, Document
export async function patchInteractionFollowup(
export async function editInteractionFollowup(
applicationId: Snowflake,
interactionToken: string,
id: string,
Expand Down
32 changes: 32 additions & 0 deletions packages/discord-api/src/routes/webhook.ts
Original file line number Diff line number Diff line change
@@ -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";

/**
* Creates a Channel Webhook
* @link https://discord.com/developers/docs/resources/webhook#create-webhook
* @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<RESTPostAPIChannelWebhookResult>;
}
34 changes: 34 additions & 0 deletions packages/discord-api/test/webhook.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { describe, expect, test, vi } from "vitest";
import { client } from "../src/client";
import { createWebhook } from "../src/routes/webhook";

describe("createWebhook", () => {
test("Accepts an optional audit log entry", async () => {
const spy = vi.spyOn(client, "post").mockImplementation(async () => "");

await createWebhook(
"123",
{ name: "Test Webhook", avatar: "avatar.png" },
"Vitest Log"
);
expect(spy).toHaveBeenCalledWith(expect.anything(), {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
body: expect.anything(),
headers: new Headers({ "X-Audit-Log-Reason": "Vitest Log" }),
});
});

test("Includes webhook information", async () => {
const spy = vi.spyOn(client, "post").mockImplementation(async () => "");

await createWebhook("123", { name: "Test Webhook", avatar: "avatar.png" });
expect(spy).toHaveBeenCalledWith("/channels/123/webhooks", {
body: {
name: "Test Webhook",
avatar: "avatar.png",
},
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
headers: expect.any(Headers),
});
});
});
2 changes: 1 addition & 1 deletion packages/discord-request/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"node": ">=18"
},
"dependencies": {
"discord-error": "0.0.1",
"discord-error": "0.0.2",
"discord-snowflake": "2.0.0",
"debug": "^4.3.4"
}
Expand Down
7 changes: 5 additions & 2 deletions packages/interaction-kit/src/cli/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { putGlobalApplicationCommands } from "discord-api";
import { bulkOverwriteGlobalApplicationCommands } from "discord-api";
import type { RESTPutAPIApplicationCommandsJSONBody } from "discord-api-types/v10";
import { getApplicationEntrypoint } from "../scripts";

Expand All @@ -18,6 +18,9 @@ export default async function command(argv?: string[]) {
const serializedCommands: RESTPutAPIApplicationCommandsJSONBody =
application.commands.map((command) => command.serialize());

await putGlobalApplicationCommands(application.id, serializedCommands);
await bulkOverwriteGlobalApplicationCommands(
application.id,
serializedCommands
);
process.exit(0);
}
4 changes: 2 additions & 2 deletions packages/interaction-kit/src/cli/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import arg from "arg";
import boxen from "boxen";
import chalk from "chalk";
import debug from "debug";
import { putGuildApplicationCommands } from "discord-api";
import { bulkOverwriteGuildApplicationCommands } from "discord-api";
import server from "discord-edge-runner";
import type { Snowflake } from "discord-snowflake";
import ngrok from "ngrok";
Expand Down Expand Up @@ -34,7 +34,7 @@ async function updateCommands(guildId: Snowflake) {

try {
if (devCommandChangeSet.hasChanges) {
await putGuildApplicationCommands(
await bulkOverwriteGuildApplicationCommands(
application.id,
guildId,
serializedCommands
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
createInteractionFollowup,
deleteInteractionFollowup,
patchInteractionFollowup,
postInteractionFollowup,
editInteractionFollowup,
} from "discord-api";
import type {
APIApplicationCommandInteraction,
Expand Down Expand Up @@ -63,7 +63,7 @@ export default class ApplicationCommandInteraction implements Interaction {
data: RESTPatchAPIInteractionFollowupJSONBody,
id = "@original"
) =>
patchInteractionFollowup(
editInteractionFollowup(
Config.getApplicationId(),
this.token,
id,
Expand Down Expand Up @@ -125,7 +125,7 @@ export default class ApplicationCommandInteraction implements Interaction {
return "@original";
}

const responseData = await postInteractionFollowup(
const responseData = await createInteractionFollowup(
Config.getApplicationId(),
this.token,
payload.data
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
createInteractionFollowup,
deleteInteractionFollowup,
patchInteractionFollowup,
postInteractionFollowup,
editInteractionFollowup,
} from "discord-api";
import type {
APIInteractionGuildMember,
Expand Down Expand Up @@ -67,7 +67,7 @@ export default class MessageComponentInteraction implements Interaction {
data: RESTPatchAPIInteractionFollowupJSONBody,
id = "@original"
) =>
patchInteractionFollowup(
editInteractionFollowup(
Config.getApplicationId(),
this.token,
id,
Expand Down Expand Up @@ -135,7 +135,7 @@ export default class MessageComponentInteraction implements Interaction {
return "@original";
}

const responseData = await postInteractionFollowup(
const responseData = await createInteractionFollowup(
Config.getApplicationId(),
this.token,
payload.data
Expand Down
4 changes: 2 additions & 2 deletions packages/interaction-kit/src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type {
deleteInteractionFollowup,
patchInteractionFollowup,
editInteractionFollowup,
} from "discord-api";
import type {
APIApplicationCommand,
Expand Down Expand Up @@ -77,7 +77,7 @@ export type InteractionMessageModifiers = {
edit: (
data: RESTPatchAPIInteractionFollowupJSONBody,
id?: string
) => ReturnType<typeof patchInteractionFollowup>;
) => ReturnType<typeof editInteractionFollowup>;
delete: (id?: string) => ReturnType<typeof deleteInteractionFollowup>;
};

Expand Down