diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 9c03e674b..914d025bc 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -1,9 +1,9 @@
---
name: Bug report
about: Create a report to help us improve
-title: ""
+title: ''
labels: bug
-assignees: ""
+assignees: ''
---
**Describe the bug** A clear and concise description of what the bug is.
@@ -11,10 +11,10 @@ assignees: ""
**To Reproduce** Write a small mod.ts example to replicate the behavior.
```ts
-import { createBot, startBot } from "https://deno.land/x/discordeno/mod.ts";
+import { createBot, startBot } from 'https://deno.land/x/discordeno/mod.ts'
-const token = "DO NOT PUT TOKEN HERE!!!";
-const botId = BigInt(atob(TOKEN.split(".")[0]));
+const token = 'DO NOT PUT TOKEN HERE!!!'
+const botId = BigInt(atob(TOKEN.split('.')[0]))
const bot = createBot({
token,
@@ -23,9 +23,9 @@ const bot = createBot({
// ADD EVENTS NEEDED TO SHOW THE BUG HERE
},
intents: 0, // ADD INTENTS NEEDED HERE FOR YOUR TEST IF NECESSARY
-});
+})
-await startBot(bot);
+await startBot(bot)
```
**Expected behavior** A clear and concise description of what you expected to happen.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index 13412bb5c..abcb29180 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -1,9 +1,9 @@
---
name: Feature request
about: Suggest an idea for this project
-title: ""
+title: ''
labels: feat
-assignees: ""
+assignees: ''
---
**Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem
diff --git a/.gitpod.yml b/.gitpod.yml
new file mode 100644
index 000000000..72c309053
--- /dev/null
+++ b/.gitpod.yml
@@ -0,0 +1,11 @@
+# This configuration file was automatically generated by Gitpod.
+# Please adjust to your needs (see https://www.gitpod.io/docs/introduction/learn-gitpod/gitpod-yaml)
+# and commit this file to your remote git repository to share the goodness with others.
+
+# Learn more from ready-to-use templates: https://www.gitpod.io/docs/introduction/getting-started/quickstart
+
+tasks:
+ - init: yarn install && yarn run build && yarn run lint && yarn run build:doc
+ command: yarn run dev
+
+
diff --git a/bench/generateMessage.ts b/bench/generateMessage.ts
index b6238ea6e..7dc7a55f7 100644
--- a/bench/generateMessage.ts
+++ b/bench/generateMessage.ts
@@ -1,64 +1,66 @@
-await import(`https://raw.githubusercontent.com/discordeno/discordeno/benchies/benchmarksResult/data.js`);
-const commitSha = await Deno.readTextFile("./sha");
-const results = JSON.parse(await Deno.readTextFile("./data.json"));
+await import(`https://raw.githubusercontent.com/discordeno/discordeno/benchies/benchmarksResult/data.js`)
+const commitSha = await Deno.readTextFile('./sha')
+const results = JSON.parse(await Deno.readTextFile('./data.json'))
interface BenchmarksData {
commit: {
- author: { email: string; name: string; username: string };
- committer: { email: string; name: string; username: string };
- distinct: boolean;
- id: string;
- message: string;
- timestamp: string;
- tree_id: string;
- url: string;
- };
- date: number;
- tool: string;
- benches: Array<{ name: string; value: number; unit: string; range: string }>;
+ author: { email: string; name: string; username: string }
+ committer: { email: string; name: string; username: string }
+ distinct: boolean
+ id: string
+ message: string
+ timestamp: string
+ tree_id: string
+ url: string
+ }
+ date: number
+ tool: string
+ benches: Array<{ name: string; value: number; unit: string; range: string }>
}
interface CompareTable {
[index: string]: {
- current: { name: string; value: number; unit: string; range: string } | {
- name?: string;
- value?: number;
- unit?: string;
- range?: string;
- };
- previous: { name: string; value: number; unit: string; range: string } | {
- name?: string;
- value?: number;
- unit?: string;
- range?: string;
- };
- };
+ current:
+ | { name: string; value: number; unit: string; range: string }
+ | {
+ name?: string
+ value?: number
+ unit?: string
+ range?: string
+ }
+ previous:
+ | { name: string; value: number; unit: string; range: string }
+ | {
+ name?: string
+ value?: number
+ unit?: string
+ range?: string
+ }
+ }
}
-const benchmarks = results.entries.Benchmark.slice(-2) as BenchmarksData[];
-const latestHeadBenchmarks = benchmarks.length === 2 ? benchmarks[1] : benchmarks[0];
-const lastHeadBenchmarks = benchmarks.length === 2 ? benchmarks[0] : undefined;
+const benchmarks = results.entries.Benchmark.slice(-2) as BenchmarksData[]
+const latestHeadBenchmarks = benchmarks.length === 2 ? benchmarks[1] : benchmarks[0]
+const lastHeadBenchmarks = benchmarks.length === 2 ? benchmarks[0] : undefined
// @ts-expect-error
-const latestBaseBenchmarks = JSON.parse(JSON.stringify(window.BENCHMARK_DATA.entries.Benchmark)).slice(
- -1,
-)[0] as BenchmarksData;
+const latestBaseBenchmarks = JSON.parse(JSON.stringify(window.BENCHMARK_DATA.entries.Benchmark)).slice(-1)[0] as BenchmarksData
-const compareWithHead: CompareTable = {};
-const compareWithBase: CompareTable = {};
+const compareWithHead: CompareTable = {}
+const compareWithBase: CompareTable = {}
if (lastHeadBenchmarks) {
for (const benchmark of lastHeadBenchmarks.benches) {
compareWithHead[benchmark.name] = {
previous: benchmark,
current: {},
- };
+ }
}
}
for (const benchmark of latestBaseBenchmarks.benches) {
compareWithBase[benchmark.name] = {
previous: benchmark,
current: {},
- };
+ }
}
for (const benchmark of latestHeadBenchmarks.benches) {
compareWithBase[benchmark.name] = {
@@ -66,51 +68,48 @@ for (const benchmark of latestHeadBenchmarks.benches) {
previous: {},
...compareWithBase[benchmark.name],
current: benchmark,
- };
+ }
compareWithHead[benchmark.name] = {
// @ts-expect-error
previous: {},
...compareWithHead[benchmark.name],
current: benchmark,
- };
-}
-
-let message = "";
-
-const compareTableInfo = [{ name: "last head", commit: lastHeadBenchmarks ? lastHeadBenchmarks.commit.id : "" }, {
- name: "base",
- commit: latestBaseBenchmarks.commit.id,
-}];
-for (const benchmarkType of ["Performance", "Memory"]) {
- message += `# ${benchmarkType} Benchmark\n\n`;
- for (const [index, compare] of [compareWithHead, compareWithBase].entries()) {
- message += `## Compared with ${compareTableInfo[index].name}\n`;
- message += "Detail results of benchmarks
\n\n";
- message += `| Benchmark suite | Current: ${latestHeadBenchmarks.commit.id} | Previous: ${
- compareTableInfo[index].commit
- } | Ratio |\n | -| -| -| -|\n`;
- for (
- const field of Object.keys(compare).filter((key) =>
- benchmarkType === "Performance" ? !key.startsWith("[Cache Plugin]") : key.startsWith("[Cache Plugin]")
- )
- ) {
- message += `| \`${field}\` | ${compare[field].current.value ? `\`${compare[field].current.value}\`` : ""} ${
- compare[field].current.unit ?? ""
- } ${compare[field].current.range ? `(\`${compare[field].current.range ?? ""}\`)` : ""} | ${
- compare[field].previous.value ? `\`${compare[field].previous.value}\`` : ""
- } ${compare[field].previous.unit ?? ""} ${
- compare[field].previous.range ? `(\`${compare[field].previous.range ?? ""}\`)` : ""
- } | ${
- compare[field].previous.value && compare[field].current.value
- ? `\`${
- // @ts-expect-error
- Math.round((parseFloat(compare[field].previous.value) / parseFloat(compare[field].current.value)) * 100) /
- 100}\``
- : ""
- } |\n`;
- }
- message += " \n\n";
}
}
-console.log(message.replaceAll("`", "\\`"));
+let message = ''
+
+const compareTableInfo = [
+ { name: 'last head', commit: lastHeadBenchmarks ? lastHeadBenchmarks.commit.id : '' },
+ {
+ name: 'base',
+ commit: latestBaseBenchmarks.commit.id,
+ },
+]
+for (const benchmarkType of ['Performance', 'Memory']) {
+ message += `# ${benchmarkType} Benchmark\n\n`
+ for (const [index, compare] of [compareWithHead, compareWithBase].entries()) {
+ message += `## Compared with ${compareTableInfo[index].name}\n`
+ message += 'Detail results of benchmarks
\n\n'
+ message += `| Benchmark suite | Current: ${latestHeadBenchmarks.commit.id} | Previous: ${compareTableInfo[index].commit} | Ratio |\n | -| -| -| -|\n`
+ for (const field of Object.keys(compare).filter((key) =>
+ benchmarkType === 'Performance' ? !key.startsWith('[Cache Plugin]') : key.startsWith('[Cache Plugin]'),
+ )) {
+ message += `| \`${field}\` | ${compare[field].current.value ? `\`${compare[field].current.value}\`` : ''} ${
+ compare[field].current.unit ?? ''
+ } ${compare[field].current.range ? `(\`${compare[field].current.range ?? ''}\`)` : ''} | ${
+ compare[field].previous.value ? `\`${compare[field].previous.value}\`` : ''
+ } ${compare[field].previous.unit ?? ''} ${compare[field].previous.range ? `(\`${compare[field].previous.range ?? ''}\`)` : ''} | ${
+ compare[field].previous.value && compare[field].current.value
+ ? `\`${
+ // @ts-expect-error
+ Math.round((parseFloat(compare[field].previous.value) / parseFloat(compare[field].current.value)) * 100) / 100
+ }\``
+ : ''
+ } |\n`
+ }
+ message += ' \n\n'
+ }
+}
+
+console.log(message.replaceAll('`', '\\`'))
diff --git a/bench/memory.ts b/bench/memory.ts
index 8e65252f3..07eac8556 100644
--- a/bench/memory.ts
+++ b/bench/memory.ts
@@ -1,28 +1,30 @@
-import { memoryBenchmarks } from "https://raw.githubusercontent.com/discordeno/benchmarks/main/index.ts";
-import { createBot } from '../mod.ts.js';
-import { enableCachePlugin } from '../plugins/mod.ts.js';
+import { memoryBenchmarks } from 'https://raw.githubusercontent.com/discordeno/benchmarks/main/index.ts'
+import { createBot } from '../mod.ts.js'
+import { enableCachePlugin } from '../plugins/mod.ts.js'
const results = await memoryBenchmarks(() =>
- enableCachePlugin(createBot({
- token: " ",
- botId: 0n,
- }))
-);
+ enableCachePlugin(
+ createBot({
+ token: ' ',
+ botId: 0n,
+ }),
+ ),
+)
const output: Array<{
- name: string;
- value: number;
- range: string;
- unit: string;
-}> = JSON.parse(await Deno.readTextFile("output.txt"));
+ name: string
+ value: number
+ range: string
+ unit: string
+}> = JSON.parse(await Deno.readTextFile('output.txt'))
for (const resultKey of Object.keys(results.Cached) as Array) {
output.push({
name: `[Cache Plugin] ${resultKey.toString()}`,
value: results.Cached[resultKey].value,
range: `${results.Cached[resultKey].min} … ${results.Cached[resultKey].max}`,
- unit: "MB",
- });
+ unit: 'MB',
+ })
}
-Deno.writeTextFile("output.txt", JSON.stringify(output, undefined, 2));
+Deno.writeTextFile('output.txt', JSON.stringify(output, undefined, 2))
diff --git a/bench/tranformOutput.ts b/bench/tranformOutput.ts
index d60d26618..1bb7f03cb 100644
--- a/bench/tranformOutput.ts
+++ b/bench/tranformOutput.ts
@@ -1,31 +1,31 @@
// Just a constant sysbench sorce to compare against
-const baselineSysbenchScore = 2000;
-let sysbenchScore = 2000;
+const baselineSysbenchScore = 2000
+let sysbenchScore = 2000
try {
- const { stdout } = await Deno.spawn("sysbench", { args: ["cpu", "run"] });
- const textout = new TextDecoder().decode(stdout);
- sysbenchScore = parseFloat(textout.match(/\s+events per second:\s+(.+)/)![1]);
+ const { stdout } = await Deno.spawn('sysbench', { args: ['cpu', 'run'] })
+ const textout = new TextDecoder().decode(stdout)
+ sysbenchScore = parseFloat(textout.match(/\s+events per second:\s+(.+)/)![1])
} catch {
//
}
-const output = await Deno.readTextFile("output.txt");
-const lines = output.split(/\r?\n/g);
+const output = await Deno.readTextFile('output.txt')
+const lines = output.split(/\r?\n/g)
-const ret = [];
+const ret = []
const unitMultiplier = {
- "s": 1000 * 1000 * 1000 * (sysbenchScore / baselineSysbenchScore),
- "ms": 1000 * 1000 * (sysbenchScore / baselineSysbenchScore),
- "µs": 1000 * (sysbenchScore / baselineSysbenchScore),
- "ns": 1 * (sysbenchScore / baselineSysbenchScore),
- "ps": 0.1 * (sysbenchScore / baselineSysbenchScore),
-};
+ s: 1000 * 1000 * 1000 * (sysbenchScore / baselineSysbenchScore),
+ ms: 1000 * 1000 * (sysbenchScore / baselineSysbenchScore),
+ µs: 1000 * (sysbenchScore / baselineSysbenchScore),
+ ns: 1 * (sysbenchScore / baselineSysbenchScore),
+ ps: 0.1 * (sysbenchScore / baselineSysbenchScore),
+}
for (const line of lines) {
- const m = line.match(/^(.+)\s+([0-9.]+) (.s)\/iter\s+\((.+) (.s) … (.+) (.s)\)(.+)$/);
- if (m === null) continue;
+ const m = line.match(/^(.+)\s+([0-9.]+) (.s)\/iter\s+\((.+) (.s) … (.+) (.s)\)(.+)$/)
+ if (m === null) continue
ret.push({
name: m[1].trim(),
@@ -33,8 +33,8 @@ for (const line of lines) {
range: `${Math.round(parseFloat(m[4]) * unitMultiplier[m[5] as keyof typeof unitMultiplier] * 100) / 100} … ${
Math.round(parseFloat(m[6]) * unitMultiplier[m[7] as keyof typeof unitMultiplier] * 100) / 100
}`,
- unit: "ns/iter",
- });
+ unit: 'ns/iter',
+ })
}
-await Deno.writeTextFile("output.txt", JSON.stringify(ret, undefined, 2));
+await Deno.writeTextFile('output.txt', JSON.stringify(ret, undefined, 2))
diff --git a/examples/beginner/bot.ts b/examples/beginner/bot.ts
index 6974b1395..444693eda 100644
--- a/examples/beginner/bot.ts
+++ b/examples/beginner/bot.ts
@@ -1,7 +1,5 @@
-import { configs } from './configs.ts.js';
-import type {
- BotWithCache,
- BotWithHelpersPlugin} from './deps.ts.js';
+import { configs } from './configs.ts.js'
+import type { BotWithCache, BotWithHelpersPlugin } from './deps.ts.js'
import {
Collection,
createBot,
@@ -10,8 +8,8 @@ import {
enableHelpersPlugin,
enablePermissionsPlugin,
GatewayIntents,
-} from './deps.ts.js';
-import type { Command } from './src/types/commands.ts.js';
+} from './deps.ts.js'
+import type { Command } from './src/types/commands.ts.js'
// MAKE THE BASIC BOT OBJECT
const bot = createBot({
@@ -19,19 +17,19 @@ const bot = createBot({
botId: configs.botId,
intents: GatewayIntents.Guilds,
events: {},
-});
+})
// ENABLE ALL THE PLUGINS THAT WILL HELP MAKE IT EASIER TO CODE YOUR BOT
-enableHelpersPlugin(bot);
-enableCachePlugin(bot);
-enableCacheSweepers(bot as BotWithCache);
-enablePermissionsPlugin(bot as BotWithCache);
+enableHelpersPlugin(bot)
+enableCachePlugin(bot)
+enableCacheSweepers(bot as BotWithCache)
+enablePermissionsPlugin(bot as BotWithCache)
export interface BotClient extends BotWithCache {
- commands: Collection;
+ commands: Collection
}
// THIS IS THE BOT YOU WANT TO USE EVERYWHERE IN YOUR CODE! IT HAS EVERYTHING BUILT INTO IT!
-export const Bot = bot as BotClient;
+export const Bot = bot as BotClient
// PREPARE COMMANDS HOLDER
-Bot.commands = new Collection();
+Bot.commands = new Collection()
diff --git a/examples/beginner/configs.ts b/examples/beginner/configs.ts
index f42459573..536e902a0 100644
--- a/examples/beginner/configs.ts
+++ b/examples/beginner/configs.ts
@@ -1,19 +1,19 @@
-import { dotEnvConfig } from './deps.ts.js';
+import { dotEnvConfig } from './deps.ts.js'
// Get the .env file that the user should have created, and get the token
-const env = dotEnvConfig({ export: true, path: "./.env" });
-const token = env.BOT_TOKEN || "";
+const env = dotEnvConfig({ export: true, path: './.env' })
+const token = env.BOT_TOKEN || ''
export interface Config {
- token: string;
- botId: bigint;
+ token: string
+ botId: bigint
}
export const configs = {
/** Get token from ENV variable */
token,
/** Get the BotId from the token */
- botId: BigInt(atob(token.split(".")[0])),
+ botId: BigInt(atob(token.split('.')[0])),
/** The server id where you develop your bot and want dev commands created. */
devGuildId: BigInt(env.DEV_GUILD_ID!),
-};
+}
diff --git a/examples/beginner/deps.ts b/examples/beginner/deps.ts
index 9da9ac457..9cf710fa8 100644
--- a/examples/beginner/deps.ts
+++ b/examples/beginner/deps.ts
@@ -1,9 +1,9 @@
-export * from "https://deno.land/x/discordeno@17.0.0/mod.ts";
-export * from "https://deno.land/x/discordeno@17.0.0/plugins/mod.ts";
+export * from 'https://deno.land/x/discordeno@17.0.0/mod.ts'
+export * from 'https://deno.land/x/discordeno@17.0.0/plugins/mod.ts'
// Terminal Colors!
-export * from "https://deno.land/std@0.117.0/fmt/colors.ts";
+export * from 'https://deno.land/std@0.117.0/fmt/colors.ts'
// Get data from .env files
-export { config as dotEnvConfig } from "https://deno.land/x/dotenv@v3.1.0/mod.ts";
+export { config as dotEnvConfig } from 'https://deno.land/x/dotenv@v3.1.0/mod.ts'
// Database, thx Tri!
-export { decode as KwikDecode, encode as KwikEncode, Kwik } from "https://deno.land/x/kwik@v1.3.1/mod.ts";
+export { decode as KwikDecode, encode as KwikEncode, Kwik } from 'https://deno.land/x/kwik@v1.3.1/mod.ts'
diff --git a/examples/beginner/mod.ts b/examples/beginner/mod.ts
index 53642f048..97b1dbdfd 100644
--- a/examples/beginner/mod.ts
+++ b/examples/beginner/mod.ts
@@ -1,25 +1,25 @@
-import { startBot } from './deps.ts.js';
-import log from './src/utils/logger.ts.js';
-import { fileLoader, importDirectory } from './src/utils/loader.ts.js';
-import { updateApplicationCommands } from './src/utils/updateCommands.ts.js';
+import { startBot } from './deps.ts.js'
+import log from './src/utils/logger.ts.js'
+import { fileLoader, importDirectory } from './src/utils/loader.ts.js'
+import { updateApplicationCommands } from './src/utils/updateCommands.ts.js'
// setup db
-import './src/database/mod.ts.js';
-import { Bot } from './bot.ts.js';
+import './src/database/mod.ts.js'
+import { Bot } from './bot.ts.js'
-log.info("Starting bot...");
+log.info('Starting bot...')
// Forces deno to read all the files which will fill the commands/inhibitors cache etc.
await Promise.all(
[
- "./src/commands",
- "./src/events",
+ './src/commands',
+ './src/events',
// "./src/tasks",
].map((path) => importDirectory(Deno.realPathSync(path))),
-);
-await fileLoader();
+)
+await fileLoader()
// UPDATES YOUR COMMANDS TO LATEST COMMANDS
-await updateApplicationCommands();
+await updateApplicationCommands()
// STARTS THE CONNECTION TO DISCORD
-await startBot(Bot);
+await startBot(Bot)
diff --git a/examples/beginner/src/commands/mod.ts b/examples/beginner/src/commands/mod.ts
index ce9f3e284..27bbef957 100644
--- a/examples/beginner/src/commands/mod.ts
+++ b/examples/beginner/src/commands/mod.ts
@@ -1,6 +1,6 @@
-import { Bot } from '../../bot.ts.js';
-import type { Command } from '../types/commands.ts.js';
+import { Bot } from '../../bot.ts.js'
+import type { Command } from '../types/commands.ts.js'
export function createCommand(command: Command) {
- Bot.commands.set(command.name, command);
+ Bot.commands.set(command.name, command)
}
diff --git a/examples/beginner/src/commands/ping.ts b/examples/beginner/src/commands/ping.ts
index 4108c590d..1922edcf4 100644
--- a/examples/beginner/src/commands/ping.ts
+++ b/examples/beginner/src/commands/ping.ts
@@ -1,22 +1,18 @@
-import { ApplicationCommandTypes, InteractionResponseTypes } from '../../deps.ts.js';
-import { snowflakeToTimestamp } from '../utils/helpers.ts.js';
-import { createCommand } from './mod.ts.js';
+import { ApplicationCommandTypes, InteractionResponseTypes } from '../../deps.ts.js'
+import { snowflakeToTimestamp } from '../utils/helpers.ts.js'
+import { createCommand } from './mod.ts.js'
createCommand({
- name: "ping",
- description: "Ping the Bot!",
+ name: 'ping',
+ description: 'Ping the Bot!',
type: ApplicationCommandTypes.ChatInput,
execute: async (Bot, interaction) => {
- const ping = Date.now() - snowflakeToTimestamp(interaction.id);
- await Bot.helpers.sendInteractionResponse(
- interaction.id,
- interaction.token,
- {
- type: InteractionResponseTypes.ChannelMessageWithSource,
- data: {
- content: `🏓 Pong! ${ping}ms`,
- },
+ const ping = Date.now() - snowflakeToTimestamp(interaction.id)
+ await Bot.helpers.sendInteractionResponse(interaction.id, interaction.token, {
+ type: InteractionResponseTypes.ChannelMessageWithSource,
+ data: {
+ content: `🏓 Pong! ${ping}ms`,
},
- );
+ })
},
-});
+})
diff --git a/examples/beginner/src/database/mod.ts b/examples/beginner/src/database/mod.ts
index d66e72931..434328763 100644
--- a/examples/beginner/src/database/mod.ts
+++ b/examples/beginner/src/database/mod.ts
@@ -1,32 +1,32 @@
-import { Kwik, KwikDecode, KwikEncode } from '../../deps.ts.js';
-import { logger } from '../utils/logger.ts.js';
+import { Kwik, KwikDecode, KwikEncode } from '../../deps.ts.js'
+import { logger } from '../utils/logger.ts.js'
-const log = logger({ name: "DB Manager" });
+const log = logger({ name: 'DB Manager' })
-log.info("Initializing Database");
+log.info('Initializing Database')
-const kwik = new Kwik();
+const kwik = new Kwik()
// Add BigInt Support
kwik.msgpackExtensionCodec.register({
type: 0,
encode: (object: unknown): Uint8Array | null => {
- if (typeof object === "bigint") {
+ if (typeof object === 'bigint') {
if (object <= Number.MAX_SAFE_INTEGER && object >= Number.MIN_SAFE_INTEGER) {
- return KwikEncode(parseInt(object.toString(), 10), {});
+ return KwikEncode(parseInt(object.toString(), 10), {})
} else {
- return KwikEncode(object.toString(), {});
+ return KwikEncode(object.toString(), {})
}
} else {
- return null;
+ return null
}
},
decode: (data: Uint8Array) => {
- return BigInt(KwikDecode(data, {}) as string);
+ return BigInt(KwikDecode(data, {}) as string)
},
-});
+})
// Initialize the Database
-await kwik.init();
+await kwik.init()
-log.info("Database Initialized!");
+log.info('Database Initialized!')
diff --git a/examples/beginner/src/events/interactionCreate.ts b/examples/beginner/src/events/interactionCreate.ts
index 46b925caa..178680dff 100644
--- a/examples/beginner/src/events/interactionCreate.ts
+++ b/examples/beginner/src/events/interactionCreate.ts
@@ -1,16 +1,14 @@
-import { Bot } from '../../bot.ts.js';
-import { InteractionTypes } from '../../deps.ts.js';
-import log from '../utils/logger.ts.js';
+import { Bot } from '../../bot.ts.js'
+import { InteractionTypes } from '../../deps.ts.js'
+import log from '../utils/logger.ts.js'
Bot.events.interactionCreate = (_, interaction) => {
- if (!interaction.data) return;
+ if (!interaction.data) return
switch (interaction.type) {
case InteractionTypes.ApplicationCommand:
- log.info(
- `[Application Command] ${interaction.data.name} command executed.`,
- );
- Bot.commands.get(interaction.data.name!)?.execute(Bot, interaction);
- break;
+ log.info(`[Application Command] ${interaction.data.name} command executed.`)
+ Bot.commands.get(interaction.data.name!)?.execute(Bot, interaction)
+ break
}
-};
+}
diff --git a/examples/beginner/src/events/ready.ts b/examples/beginner/src/events/ready.ts
index eaf12d058..1d57aeccc 100644
--- a/examples/beginner/src/events/ready.ts
+++ b/examples/beginner/src/events/ready.ts
@@ -1,16 +1,16 @@
-import { Bot } from '../../bot.ts.js';
-import log from '../utils/logger.ts.js';
+import { Bot } from '../../bot.ts.js'
+import log from '../utils/logger.ts.js'
Bot.events.ready = (_, payload) => {
- log.info(`[READY] Shard ID ${payload.shardId} of ${Bot.gateway.lastShardId + 1} shards is ready!`);
+ log.info(`[READY] Shard ID ${payload.shardId} of ${Bot.gateway.lastShardId + 1} shards is ready!`)
if (payload.shardId === Bot.gateway.lastShardId) {
- botFullyReady();
+ botFullyReady()
}
-};
+}
// This function lets you run custom code when all your bot's shards are online.
function botFullyReady() {
// DO STUFF YOU WANT HERE ONCE BOT IS FULLY ONLINE.
- log.info("[READY] Bot is fully online.");
+ log.info('[READY] Bot is fully online.')
}
diff --git a/examples/beginner/src/types/commands.ts b/examples/beginner/src/types/commands.ts
index 2d0a7e7dc..aeddaf60a 100644
--- a/examples/beginner/src/types/commands.ts
+++ b/examples/beginner/src/types/commands.ts
@@ -1,17 +1,17 @@
-import type { BotClient } from '../../bot.ts.js';
-import type { ApplicationCommandOption, ApplicationCommandTypes, Interaction } from '../../deps.ts.js';
+import type { BotClient } from '../../bot.ts.js'
+import type { ApplicationCommandOption, ApplicationCommandTypes, Interaction } from '../../deps.ts.js'
export interface Command {
/** The name of this command. */
- name: string;
+ name: string
/** What does this command do? */
- description: string;
+ description: string
/** The type of command this is. */
- type: ApplicationCommandTypes;
+ type: ApplicationCommandTypes
/** Whether or not this command is for the dev server only. */
- devOnly?: boolean;
+ devOnly?: boolean
/** The options for this command */
- options?: ApplicationCommandOption[];
+ options?: ApplicationCommandOption[]
/** This will be executed when the command is run. */
- execute: (bot: BotClient, interaction: Interaction) => unknown;
+ execute: (bot: BotClient, interaction: Interaction) => unknown
}
diff --git a/examples/beginner/src/types/mod.ts b/examples/beginner/src/types/mod.ts
index f3d0e7629..88fce63cc 100644
--- a/examples/beginner/src/types/mod.ts
+++ b/examples/beginner/src/types/mod.ts
@@ -1,3 +1,3 @@
// This file will export all of the types in this directory.
-export * from './commands.ts.js';
+export * from './commands.ts.js'
diff --git a/examples/beginner/src/utils/helpers.ts b/examples/beginner/src/utils/helpers.ts
index 2ac9255bb..d5f880cdc 100644
--- a/examples/beginner/src/utils/helpers.ts
+++ b/examples/beginner/src/utils/helpers.ts
@@ -1,3 +1,3 @@
export function snowflakeToTimestamp(id: bigint) {
- return Number(id / 4194304n + 1420070400000n);
+ return Number(id / 4194304n + 1420070400000n)
}
diff --git a/examples/beginner/src/utils/loader.ts b/examples/beginner/src/utils/loader.ts
index a5b9af0d9..807cec5a6 100644
--- a/examples/beginner/src/utils/loader.ts
+++ b/examples/beginner/src/utils/loader.ts
@@ -1,47 +1,40 @@
-import log from './logger.ts.js';
+import log from './logger.ts.js'
// Very important to make sure files are reloaded properly
-let uniqueFilePathCounter = 0;
-let paths: string[] = [];
+let uniqueFilePathCounter = 0
+let paths: string[] = []
/** This function allows reading all files in a folder. Useful for loading/reloading commands, monitors etc */
export async function importDirectory(path: string) {
- path = path.replaceAll("\\", "/");
- const files = Deno.readDirSync(Deno.realPathSync(path));
- const folder = path.substring(path.indexOf("/src/") + 5);
+ path = path.replaceAll('\\', '/')
+ const files = Deno.readDirSync(Deno.realPathSync(path))
+ const folder = path.substring(path.indexOf('/src/') + 5)
- if (!folder.includes("/")) log.info(`Loading ${folder}...`);
+ if (!folder.includes('/')) log.info(`Loading ${folder}...`)
for (const file of files) {
- if (!file.name) continue;
+ if (!file.name) continue
- const currentPath = `${path}/${file.name}`;
+ const currentPath = `${path}/${file.name}`
if (file.isFile) {
- if (!currentPath.endsWith(".ts")) continue;
+ if (!currentPath.endsWith('.ts')) continue
paths.push(
- `import "${Deno.mainModule.substring(0, Deno.mainModule.lastIndexOf("/"))}/${
- currentPath.substring(
- currentPath.indexOf("src/"),
- )
- }#${uniqueFilePathCounter}";`,
- );
- continue;
+ `import "${Deno.mainModule.substring(0, Deno.mainModule.lastIndexOf('/'))}/${currentPath.substring(
+ currentPath.indexOf('src/'),
+ )}#${uniqueFilePathCounter}";`,
+ )
+ continue
}
- await importDirectory(currentPath);
+ await importDirectory(currentPath)
}
- uniqueFilePathCounter++;
+ uniqueFilePathCounter++
}
/** Imports all everything in fileloader.ts */
export async function fileLoader() {
- await Deno.writeTextFile(
- "fileloader.ts",
- paths.join("\n").replaceAll("\\", "/"),
- );
- await import(
- `${Deno.mainModule.substring(0, Deno.mainModule.lastIndexOf("/"))}/fileloader.ts#${uniqueFilePathCounter}`
- );
- paths = [];
+ await Deno.writeTextFile('fileloader.ts', paths.join('\n').replaceAll('\\', '/'))
+ await import(`${Deno.mainModule.substring(0, Deno.mainModule.lastIndexOf('/'))}/fileloader.ts#${uniqueFilePathCounter}`)
+ paths = []
}
diff --git a/examples/beginner/src/utils/logger.ts b/examples/beginner/src/utils/logger.ts
index d5a039064..c69924a23 100644
--- a/examples/beginner/src/utils/logger.ts
+++ b/examples/beginner/src/utils/logger.ts
@@ -1,5 +1,5 @@
// deno-lint-ignore-file no-explicit-any
-import { bold, cyan, gray, italic, red, yellow } from '../../deps.ts.js';
+import { bold, cyan, gray, italic, red, yellow } from '../../deps.ts.js'
export enum LogLevels {
Debug,
@@ -10,81 +10,81 @@ export enum LogLevels {
}
const prefixes = new Map([
- [LogLevels.Debug, "DEBUG"],
- [LogLevels.Info, "INFO"],
- [LogLevels.Warn, "WARN"],
- [LogLevels.Error, "ERROR"],
- [LogLevels.Fatal, "FATAL"],
-]);
+ [LogLevels.Debug, 'DEBUG'],
+ [LogLevels.Info, 'INFO'],
+ [LogLevels.Warn, 'WARN'],
+ [LogLevels.Error, 'ERROR'],
+ [LogLevels.Fatal, 'FATAL'],
+])
-const noColor: (str: string) => string = (msg) => msg;
+const noColor: (str: string) => string = (msg) => msg
const colorFunctions = new Map string>([
[LogLevels.Debug, gray],
[LogLevels.Info, cyan],
[LogLevels.Warn, yellow],
[LogLevels.Error, (str: string) => red(str)],
[LogLevels.Fatal, (str: string) => red(bold(italic(str)))],
-]);
+])
export function logger({
logLevel = LogLevels.Info,
name,
}: {
- logLevel?: LogLevels;
- name?: string;
+ logLevel?: LogLevels
+ name?: string
} = {}) {
function log(level: LogLevels, ...args: any[]) {
- if (level < logLevel) return;
+ if (level < logLevel) return
- let color = colorFunctions.get(level);
- if (!color) color = noColor;
+ let color = colorFunctions.get(level)
+ if (!color) color = noColor
- const date = new Date();
+ const date = new Date()
const log = [
`[${date.toLocaleDateString()} ${date.toLocaleTimeString()}]`,
- color(prefixes.get(level) || "DEBUG"),
- name ? `${name} >` : ">",
+ color(prefixes.get(level) || 'DEBUG'),
+ name ? `${name} >` : '>',
...args,
- ];
+ ]
switch (level) {
case LogLevels.Debug:
- return console.debug(...log);
+ return console.debug(...log)
case LogLevels.Info:
- return console.info(...log);
+ return console.info(...log)
case LogLevels.Warn:
- return console.warn(...log);
+ return console.warn(...log)
case LogLevels.Error:
- return console.error(...log);
+ return console.error(...log)
case LogLevels.Fatal:
- return console.error(...log);
+ return console.error(...log)
default:
- return console.log(...log);
+ return console.log(...log)
}
}
function setLevel(level: LogLevels) {
- logLevel = level;
+ logLevel = level
}
function debug(...args: any[]) {
- log(LogLevels.Debug, ...args);
+ log(LogLevels.Debug, ...args)
}
function info(...args: any[]) {
- log(LogLevels.Info, ...args);
+ log(LogLevels.Info, ...args)
}
function warn(...args: any[]) {
- log(LogLevels.Warn, ...args);
+ log(LogLevels.Warn, ...args)
}
function error(...args: any[]) {
- log(LogLevels.Error, ...args);
+ log(LogLevels.Error, ...args)
}
function fatal(...args: any[]) {
- log(LogLevels.Fatal, ...args);
+ log(LogLevels.Fatal, ...args)
}
return {
@@ -95,8 +95,8 @@ export function logger({
warn,
error,
fatal,
- };
+ }
}
-export const log = logger({ name: "Main" });
-export default log;
+export const log = logger({ name: 'Main' })
+export default log
diff --git a/examples/beginner/src/utils/updateCommands.ts b/examples/beginner/src/utils/updateCommands.ts
index 9e4afd77b..f2751e7a8 100644
--- a/examples/beginner/src/utils/updateCommands.ts
+++ b/examples/beginner/src/utils/updateCommands.ts
@@ -1,5 +1,5 @@
-import { Bot } from '../../bot.ts.js';
-import { configs } from '../../configs.ts.js';
+import { Bot } from '../../bot.ts.js'
+import { configs } from '../../configs.ts.js'
export async function updateApplicationCommands() {
await Bot.helpers.upsertGlobalApplicationCommands(
@@ -7,7 +7,7 @@ export async function updateApplicationCommands() {
// ONLY GLOBAL COMMANDS
.filter((command) => !command.devOnly)
.array(),
- );
+ )
await Bot.helpers.upsertGuildApplicationCommands(
configs.devGuildId,
@@ -15,5 +15,5 @@ export async function updateApplicationCommands() {
// ONLY GLOBAL COMMANDS
.filter((command) => !!command.devOnly)
.array(),
- );
+ )
}
diff --git a/examples/bigbot/src/analytics.ts b/examples/bigbot/src/analytics.ts
index 78dd217cf..85638d167 100644
--- a/examples/bigbot/src/analytics.ts
+++ b/examples/bigbot/src/analytics.ts
@@ -1,5 +1,5 @@
-import { InfluxDB, Point } from "@influxdata/influxdb-client";
-import type { RestManager } from "discordeno/rest";
+import { InfluxDB, Point } from '@influxdata/influxdb-client';
+import type { RestManager } from 'discordeno/rest';
const INFLUX_ORG = process.env.INFLUX_ORG as string;
const INFLUX_BUCKET = process.env.INFLUX_BUCKET as string;
@@ -10,46 +10,46 @@ export const influxDB = INFLUX_URL && INFLUX_TOKEN ? new InfluxDB({ url: INFLUX_
export const Influx = influxDB?.getWriteApi(INFLUX_ORG, INFLUX_BUCKET);
export const setupAnalyticsHooks = (rest: RestManager) => {
- // If influxdb data is provided, enable analytics in this proxy.
- if (Influx) {
- rest.fetching = function (options) {
- Influx?.writePoint(
- new Point("restEvents")
- // MARK THE TIME WHEN EVENT ARRIVED
- .timestamp(new Date())
- // SET THE GUILD ID
- .stringField("type", "REQUEST_FETCHING")
- .tag("method", options.method)
- .tag("url", options.url)
- .tag("bucket", options.bucketId ?? "NA"),
- );
- };
+ // If influxdb data is provided, enable analytics in this proxy.
+ if (Influx) {
+ rest.fetching = function (options) {
+ Influx?.writePoint(
+ new Point('restEvents')
+ // MARK THE TIME WHEN EVENT ARRIVED
+ .timestamp(new Date())
+ // SET THE GUILD ID
+ .stringField('type', 'REQUEST_FETCHING')
+ .tag('method', options.method)
+ .tag('url', options.url)
+ .tag('bucket', options.bucketId ?? 'NA'),
+ );
+ };
- rest.fetched = function (options, response) {
- Influx?.writePoint(
- new Point("restEvents")
- // MARK THE TIME WHEN EVENT ARRIVED
- .timestamp(new Date())
- // SET THE GUILD ID
- .stringField("type", "REQUEST_FETCHED")
- .tag("method", options.method)
- .tag("url", options.url)
- .tag("bucket", options.bucketId ?? "NA")
- .intField("status", response.status)
- .tag("statusText", response.statusText),
- );
- };
+ rest.fetched = function (options, response) {
+ Influx?.writePoint(
+ new Point('restEvents')
+ // MARK THE TIME WHEN EVENT ARRIVED
+ .timestamp(new Date())
+ // SET THE GUILD ID
+ .stringField('type', 'REQUEST_FETCHED')
+ .tag('method', options.method)
+ .tag('url', options.url)
+ .tag('bucket', options.bucketId ?? 'NA')
+ .intField('status', response.status)
+ .tag('statusText', response.statusText),
+ );
+ };
- setInterval(() => {
- console.log(`[Influx - REST] Saving events...`);
- Influx?.flush()
- .then(() => {
- console.log(`[Influx - REST] Saved events!`);
- })
- .catch((error) => {
- console.log(`[Influx - REST] Error saving events!`, error);
- });
- // Every 30seconds
- }, 30000);
- }
+ setInterval(() => {
+ console.log(`[Influx - REST] Saving events...`);
+ Influx?.flush()
+ .then(() => {
+ console.log(`[Influx - REST] Saved events!`);
+ })
+ .catch((error) => {
+ console.log(`[Influx - REST] Error saving events!`, error);
+ });
+ // Every 30seconds
+ }, 30000);
+ }
};
diff --git a/examples/bigbot/src/bot/bot.ts b/examples/bigbot/src/bot/bot.ts
index 572a0619b..fbaca1ac9 100644
--- a/examples/bigbot/src/bot/bot.ts
+++ b/examples/bigbot/src/bot/bot.ts
@@ -1,50 +1,50 @@
-import type { Bot} from "discordeno";
-import { Collection, createBot, createRestManager } from "discordeno";
-import enableHelpersPlugin from "discordeno/helpers-plugin";
-import { createLogger } from "discordeno/logger";
-import { setupAnalyticsHooks } from "../analytics.js";
-import { INTENTS, REST_URL } from "../configs.js";
-import { setupEventHandlers } from "./events/mod.js";
-import type { MessageCollector } from "./utils/collectors.js";
-import { customizeInternals } from "./utils/internals/mod.js";
+import type { Bot } from 'discordeno';
+import { Collection, createBot, createRestManager } from 'discordeno';
+import enableHelpersPlugin from 'discordeno/helpers-plugin';
+import { createLogger } from 'discordeno/logger';
+import { setupAnalyticsHooks } from '../analytics.js';
+import { INTENTS, REST_URL } from '../configs.js';
+import { setupEventHandlers } from './events/mod.js';
+import type { MessageCollector } from './utils/collectors.js';
+import { customizeInternals } from './utils/internals/mod.js';
const DISCORD_TOKEN = process.env.DISCORD_TOKEN as string;
const REST_AUTHORIZATION = process.env.REST_AUTHORIZATION as string;
export const bot = enableHelpersPlugin(
- customizeBot(
- createBot({
- token: DISCORD_TOKEN,
- intents: INTENTS,
- }),
- ),
+ customizeBot(
+ createBot({
+ token: DISCORD_TOKEN,
+ intents: INTENTS,
+ }),
+ ),
);
/** Add custom props to your `bot` here */
// SETUP-DD-TEMP: If you want to add any custom props to `bot` you can do so here. Please make sure to also add them in the type below. As an example, i have added a `logger` property. You can add any useful methods or props you wish to have easily available.
function customizeBot(bot: B): BotWithCustomProps {
- const customized = bot as unknown as BotWithCustomProps;
- customized.logger = createLogger({ name: "[Bot]" });
- customized.collectors = {
- messages: new Collection(),
- };
- customized.commandVersions = new Collection();
+ const customized = bot as unknown as BotWithCustomProps;
+ customized.logger = createLogger({ name: '[Bot]' });
+ customized.collectors = {
+ messages: new Collection(),
+ };
+ customized.commandVersions = new Collection();
- return customized;
+ return customized;
}
// SETUP-DD-TEMP: If you want to add any custom props to `bot` you can do so here. Please make sure to also add them in the function above. Run a find all and change this to your Bot's name. For example, if your bot's name is Gamer change BotWithCustomProps to Gamer. This way whenever you need to provide the type for the Bot with your custom props it is your bots name.
// Note: ALWAYS edit the function above first before adding the type here.
export type BotWithCustomProps = B & {
- /** A easy to use logger to make clean log messages. */
- logger: ReturnType;
- /** Collectors that can be used to get input from users. */
- collectors: {
- /** Holds the pending messages collectors that users can respond to. */
- messages: Collection;
- };
- /** The command versions for each guild id. */
- commandVersions: Collection;
+ /** A easy to use logger to make clean log messages. */
+ logger: ReturnType;
+ /** Collectors that can be used to get input from users. */
+ collectors: {
+ /** Holds the pending messages collectors that users can respond to. */
+ messages: Collection;
+ };
+ /** The command versions for each guild id. */
+ commandVersions: Collection;
};
// Example of how to customize internal discordeno stuff easily.
@@ -54,9 +54,9 @@ customizeInternals(bot);
setupEventHandlers();
bot.rest = createRestManager({
- token: DISCORD_TOKEN,
- secretKey: REST_AUTHORIZATION,
- customUrl: REST_URL,
+ token: DISCORD_TOKEN,
+ secretKey: REST_AUTHORIZATION,
+ customUrl: REST_URL,
});
// Add send fetching analytics hook to rest
diff --git a/examples/bigbot/src/bot/commands/language.ts b/examples/bigbot/src/bot/commands/language.ts
index df2ba0206..3f25e4d9f 100644
--- a/examples/bigbot/src/bot/commands/language.ts
+++ b/examples/bigbot/src/bot/commands/language.ts
@@ -1,33 +1,33 @@
-import { ApplicationCommandOptionTypes } from "discordeno";
-import { prisma } from "../../prisma.js";
-import languages from "../languages/languages.js";
-import { serverLanguages, translate } from "../languages/translate.js";
-import { createCommand } from "../utils/slash/createCommand.js";
+import { ApplicationCommandOptionTypes } from 'discordeno';
+import { prisma } from '../../prisma.js';
+import languages from '../languages/languages.js';
+import { serverLanguages, translate } from '../languages/translate.js';
+import { createCommand } from '../utils/slash/createCommand.js';
export default createCommand({
- name: "LANGUAGE_NAME",
- description: "LANGUAGE_DESCRIPTION",
- options: [
- {
- name: "LANGUAGE_KEY_NAME",
- description: "LANGUAGE_KEY_DESCRIPTION",
- type: ApplicationCommandOptionTypes.String,
- choices: Object.keys(languages).map((key) => ({ name: key, value: key })),
- required: true,
- },
- ],
- execute: async function (_, interaction, args) {
- if (!interaction.guildId) return;
+ name: 'LANGUAGE_NAME',
+ description: 'LANGUAGE_DESCRIPTION',
+ options: [
+ {
+ name: 'LANGUAGE_KEY_NAME',
+ description: 'LANGUAGE_KEY_DESCRIPTION',
+ type: ApplicationCommandOptionTypes.String,
+ choices: Object.keys(languages).map((key) => ({ name: key, value: key })),
+ required: true,
+ },
+ ],
+ execute: async function (_, interaction, args) {
+ if (!interaction.guildId) return;
- // Set the new language in cache
- serverLanguages.set(interaction.guildId, args.name);
- // Let the user know its been updated.
- await interaction.reply(translate(interaction.guildId!, "LANGUAGE_UPDATED", args.name));
- // Update the db
- return await prisma.guilds.upsert({
- where: { id: interaction.guildId },
- create: { language: args.name, id: interaction.guildId },
- update: { language: args.name },
- });
- },
+ // Set the new language in cache
+ serverLanguages.set(interaction.guildId, args.name);
+ // Let the user know its been updated.
+ await interaction.reply(translate(interaction.guildId!, 'LANGUAGE_UPDATED', args.name));
+ // Update the db
+ return await prisma.guilds.upsert({
+ where: { id: interaction.guildId },
+ create: { language: args.name, id: interaction.guildId },
+ update: { language: args.name },
+ });
+ },
});
diff --git a/examples/bigbot/src/bot/commands/mod.ts b/examples/bigbot/src/bot/commands/mod.ts
index 557bbfd61..b25e3edf5 100644
--- a/examples/bigbot/src/bot/commands/mod.ts
+++ b/examples/bigbot/src/bot/commands/mod.ts
@@ -1,9 +1,9 @@
-import language from "./language.js";
-import ping from "./ping.js";
+import language from './language.js';
+import ping from './ping.js';
export const COMMANDS = {
- language,
- ping,
+ language,
+ ping,
};
export default COMMANDS;
diff --git a/examples/bigbot/src/bot/commands/ping.ts b/examples/bigbot/src/bot/commands/ping.ts
index b1856aeec..b733f9b3f 100644
--- a/examples/bigbot/src/bot/commands/ping.ts
+++ b/examples/bigbot/src/bot/commands/ping.ts
@@ -1,17 +1,17 @@
-import { translate } from "../languages/translate.js";
-import { createCommand } from "../utils/slash/createCommand.js";
+import { translate } from '../languages/translate.js';
+import { createCommand } from '../utils/slash/createCommand.js';
export default createCommand({
- name: "PING_NAME",
- description: "PING_DESCRIPTION",
- execute: async function (_, interaction) {
- return await interaction.reply(
- translate(interaction.guildId!, "PING_RESPONSE_WITH_TIME", Date.now() - snowflakeToTimestamp(interaction.id)),
- );
- },
+ name: 'PING_NAME',
+ description: 'PING_DESCRIPTION',
+ execute: async function (_, interaction) {
+ return await interaction.reply(
+ translate(interaction.guildId!, 'PING_RESPONSE_WITH_TIME', Date.now() - snowflakeToTimestamp(interaction.id)),
+ );
+ },
});
// TODO: This should be deleted once this is available in the helpers plugin.
export function snowflakeToTimestamp(id: bigint) {
- return Number(id / 4194304n + 1420070400000n);
+ return Number(id / 4194304n + 1420070400000n);
}
diff --git a/examples/bigbot/src/bot/events/interactions/button.ts b/examples/bigbot/src/bot/events/interactions/button.ts
index 89acc8322..a863ceb0c 100644
--- a/examples/bigbot/src/bot/events/interactions/button.ts
+++ b/examples/bigbot/src/bot/events/interactions/button.ts
@@ -1,14 +1,14 @@
-import type { Interaction } from "discordeno";
-import type { BotWithCustomProps } from "../../bot.js";
+import type { Interaction } from 'discordeno';
+import type { BotWithCustomProps } from '../../bot.js';
export async function executeButtonClick(bot: BotWithCustomProps, interaction: Interaction) {
- if (!interaction.data) return;
+ if (!interaction.data) return;
- bot.logger.info(
- `[Button] The ${interaction.data.customId} button was clicked in Guild: ${interaction.guildId} by ${interaction.user.id}.`,
- );
+ bot.logger.info(
+ `[Button] The ${interaction.data.customId} button was clicked in Guild: ${interaction.guildId} by ${interaction.user.id}.`,
+ );
- await Promise.allSettled([
- // SETUP-DD-TEMP: Insert any functions you wish to run when a user clicks a button.
- ]).catch(console.log);
+ await Promise.allSettled([
+ // SETUP-DD-TEMP: Insert any functions you wish to run when a user clicks a button.
+ ]).catch(console.log);
}
diff --git a/examples/bigbot/src/bot/events/interactions/command.ts b/examples/bigbot/src/bot/events/interactions/command.ts
index a8ebb2d7d..137041f4d 100644
--- a/examples/bigbot/src/bot/events/interactions/command.ts
+++ b/examples/bigbot/src/bot/events/interactions/command.ts
@@ -1,121 +1,116 @@
-import { bgBlack, bgGreen, bgMagenta, bgYellow, black, green, red, white } from "colorette";
+import { bgBlack, bgGreen, bgMagenta, bgYellow, black, green, red, white } from 'colorette';
import type {
- ApplicationCommandOption,
- Bot,
- Channel,
- ChannelTypes,
- Interaction,
- InteractionDataOption,
- Member,
- Role,
- User} from "discordeno";
-import {
- ApplicationCommandOptionTypes,
- InteractionResponseTypes
-} from "discordeno";
-import type { BotWithCustomProps } from "../../bot.js";
-import { bot } from "../../bot.js";
-import COMMANDS from "../../commands/mod.js";
-import type { translationKeys } from "../../languages/translate.js";
-import { getLanguage, loadLanguage, serverLanguages, translate } from "../../languages/translate.js";
-import type { InteractionWithCustomProps } from "../../typings/discordeno.js";
-import type { Command, ConvertArgumentDefinitionsToArgs } from "../../utils/slash/createCommand.js";
+ ApplicationCommandOption,
+ Bot,
+ Channel,
+ ChannelTypes,
+ Interaction,
+ InteractionDataOption,
+ Member,
+ Role,
+ User,
+} from 'discordeno';
+import { ApplicationCommandOptionTypes, InteractionResponseTypes } from 'discordeno';
+import type { BotWithCustomProps } from '../../bot.js';
+import { bot } from '../../bot.js';
+import COMMANDS from '../../commands/mod.js';
+import type { translationKeys } from '../../languages/translate.js';
+import { getLanguage, loadLanguage, serverLanguages, translate } from '../../languages/translate.js';
+import type { InteractionWithCustomProps } from '../../typings/discordeno.js';
+import type { Command, ConvertArgumentDefinitionsToArgs } from '../../utils/slash/createCommand.js';
function logCommand(
- info: Interaction,
- type: "Failure" | "Success" | "Trigger" | "Slowmode" | "Missing" | "Inhibit",
- commandName: string,
+ info: Interaction,
+ type: 'Failure' | 'Success' | 'Trigger' | 'Slowmode' | 'Missing' | 'Inhibit',
+ commandName: string,
) {
- const command = `[COMMAND: ${bgYellow(black(commandName || "Unknown"))} - ${
- bgBlack(
- ["Failure", "Slowmode", "Missing"].includes(type) ? red(type) : type === "Success" ? green(type) : white(type),
- )
- }]`;
+ const command = `[COMMAND: ${bgYellow(black(commandName || 'Unknown'))} - ${bgBlack(
+ ['Failure', 'Slowmode', 'Missing'].includes(type) ? red(type) : type === 'Success' ? green(type) : white(type),
+ )}]`;
- const user = bgGreen(
- black(`${info.user.username}#${info.user.discriminator.toString().padStart(4, "0")}(${info.id})`),
- );
- const guild = bgMagenta(black(`${info.guildId ? `Guild ID: (${info.guildId})` : "DM"}`));
+ const user = bgGreen(
+ black(`${info.user.username}#${info.user.discriminator.toString().padStart(4, '0')}(${info.id})`),
+ );
+ const guild = bgMagenta(black(`${info.guildId ? `Guild ID: (${info.guildId})` : 'DM'}`));
- bot.logger.info(`${command} by ${user} in ${guild} with MessageID: ${info.id}`);
+ bot.logger.info(`${command} by ${user} in ${guild} with MessageID: ${info.id}`);
}
export async function executeSlashCommand(bot: BotWithCustomProps, interaction: InteractionWithCustomProps) {
- const data = interaction.data;
- const name = data?.name as keyof typeof COMMANDS;
+ const data = interaction.data;
+ const name = data?.name as keyof typeof COMMANDS;
- const command: Command | undefined = COMMANDS[name];
+ const command: Command | undefined = COMMANDS[name];
- // Command could not be found
- if (!command?.execute) {
- return await interaction
- .reply(translate(interaction.guildId!, "EXECUTE_COMMAND_NOT_FOUND"))
- .catch(bot.logger.error);
- }
+ // Command could not be found
+ if (!command?.execute) {
+ return await interaction
+ .reply(translate(interaction.guildId!, 'EXECUTE_COMMAND_NOT_FOUND'))
+ .catch(bot.logger.error);
+ }
- // HAVE TO CONVERT OUTSIDE OF TRY SO IT CAN BE USED IN CATCH TOO
- try {
- logCommand(interaction, "Trigger", name);
+ // HAVE TO CONVERT OUTSIDE OF TRY SO IT CAN BE USED IN CATCH TOO
+ try {
+ logCommand(interaction, 'Trigger', name);
- // Check subcommand permissions and options
- if (!(await commandAllowed(interaction, command))) return;
+ // Check subcommand permissions and options
+ if (!(await commandAllowed(interaction, command))) return;
- // Load the language for this guild
- if (interaction.guildId && !serverLanguages.has(interaction.guildId)) {
- // Todo: make command.execute reply change to editReply after running this
- // await interaction.reply({
- // type: InteractionResponseTypes.DeferredChannelMessageWithSource,
- // });
- await loadLanguage(interaction.guildId);
- } // Load the language for this guild
- else if (command.acknowledge) {
- // Acknowledge the command
- await interaction.reply({
- type: InteractionResponseTypes.DeferredChannelMessageWithSource,
- });
- }
+ // Load the language for this guild
+ if (interaction.guildId && !serverLanguages.has(interaction.guildId)) {
+ // Todo: make command.execute reply change to editReply after running this
+ // await interaction.reply({
+ // type: InteractionResponseTypes.DeferredChannelMessageWithSource,
+ // });
+ await loadLanguage(interaction.guildId);
+ } // Load the language for this guild
+ else if (command.acknowledge) {
+ // Acknowledge the command
+ await interaction.reply({
+ type: InteractionResponseTypes.DeferredChannelMessageWithSource,
+ });
+ }
- // FIRST GET THE TRANSLATIONS FOR ALL OPTIONS
- const translatedOptionNames = interaction.guildId && command.options
- ? translateOptionNames(bot, interaction.guildId, command.options)
- : {};
+ // FIRST GET THE TRANSLATIONS FOR ALL OPTIONS
+ const translatedOptionNames =
+ interaction.guildId && command.options ? translateOptionNames(bot, interaction.guildId, command.options) : {};
- // PARSE THE OPTIONS TO A NICE OBJECT AND TRANSLATE THE KEYS TO ENGLISH
- const parsedArguments = optionParser(interaction, translatedOptionNames);
+ // PARSE THE OPTIONS TO A NICE OBJECT AND TRANSLATE THE KEYS TO ENGLISH
+ const parsedArguments = optionParser(interaction, translatedOptionNames);
- await command.execute(bot, interaction, parsedArguments as ConvertArgumentDefinitionsToArgs);
- logCommand(interaction, "Success", name);
- } catch (error) {
- console.error(error);
- logCommand(interaction, "Failure", name);
+ await command.execute(bot, interaction, parsedArguments as ConvertArgumentDefinitionsToArgs);
+ logCommand(interaction, 'Success', name);
+ } catch (error) {
+ console.error(error);
+ logCommand(interaction, 'Failure', name);
- try {
- console.log("try");
- // try to reply the interaction, becuase we don't know if it replied or deffered
- return await interaction.reply(translate(interaction.id, "EXECUTE_COMMAND_ERROR"));
- } catch {
- console.log("catch");
- // edit the reply or deffered reply of interaction
- return await interaction.editReply(translate(interaction.id, "EXECUTE_COMMAND_ERROR")).catch(bot.logger.error);
- }
- }
+ try {
+ console.log('try');
+ // try to reply the interaction, becuase we don't know if it replied or deffered
+ return await interaction.reply(translate(interaction.id, 'EXECUTE_COMMAND_ERROR'));
+ } catch {
+ console.log('catch');
+ // edit the reply or deffered reply of interaction
+ return await interaction.editReply(translate(interaction.id, 'EXECUTE_COMMAND_ERROR')).catch(bot.logger.error);
+ }
+ }
}
/** Runs the inhibitors to see if a command is allowed to run. */
export async function commandAllowed(interaction: InteractionWithCustomProps, command: Command) {
- // CHECK WHETHER THE USER/GUILD IS VIP
- if (command.vipOnly) {
- // SETUP-DD-TEMP: Check if this server/user is a vip.
- const isVIP = true;
+ // CHECK WHETHER THE USER/GUILD IS VIP
+ if (command.vipOnly) {
+ // SETUP-DD-TEMP: Check if this server/user is a vip.
+ const isVIP = true;
- if (!isVIP) {
- await interaction.reply(translate(interaction.id, "NEED_VIP")).catch(bot.logger.error);
+ if (!isVIP) {
+ await interaction.reply(translate(interaction.id, 'NEED_VIP')).catch(bot.logger.error);
- return false;
- }
- }
+ return false;
+ }
+ }
- return true;
+ return true;
}
// Mapped by `language-commandName`
@@ -123,189 +118,187 @@ const translatedOptionNamesCache = new Map>();
/** Translates all options of the command to an object: translatedOptionName: optionName */
export function translateOptionNames(
- bot: Bot,
- guildId: bigint,
- options: ApplicationCommandOption[],
- commandName?: string,
+ bot: Bot,
+ guildId: bigint,
+ options: ApplicationCommandOption[],
+ commandName?: string,
): Record {
- const language = getLanguage(guildId);
- // RETURN THE ALREADY TRANSLATED OPTIONS WHICH ARE IN CACHE
- if (commandName && translatedOptionNamesCache.has(`${language}-${commandName}`)) {
- return translatedOptionNamesCache.get(`${language}-${commandName}`)!;
- }
+ const language = getLanguage(guildId);
+ // RETURN THE ALREADY TRANSLATED OPTIONS WHICH ARE IN CACHE
+ if (commandName && translatedOptionNamesCache.has(`${language}-${commandName}`)) {
+ return translatedOptionNamesCache.get(`${language}-${commandName}`)!;
+ }
- // TRANSLATE ALL OPTIONS
- let translated: Record = {};
- for (const option of options) {
- translated[translate(guildId, option.name as translationKeys).toLowerCase()] = translate(
- "english",
- option.name as translationKeys,
- );
- if (option.options) {
- translated = {
- ...translated,
- ...translateOptionNames(bot, guildId, option.options),
- };
- }
- }
+ // TRANSLATE ALL OPTIONS
+ let translated: Record = {};
+ for (const option of options) {
+ translated[translate(guildId, option.name as translationKeys).toLowerCase()] = translate(
+ 'english',
+ option.name as translationKeys,
+ );
+ if (option.options) {
+ translated = {
+ ...translated,
+ ...translateOptionNames(bot, guildId, option.options),
+ };
+ }
+ }
- // SAVE THE TRANSLATED OPTIONS IN CACHE FOR FASTER ACCESS
- if (commandName) {
- translatedOptionNamesCache.set(`${language}-${commandName}`, translated);
- }
+ // SAVE THE TRANSLATED OPTIONS IN CACHE FOR FASTER ACCESS
+ if (commandName) {
+ translatedOptionNamesCache.set(`${language}-${commandName}`, translated);
+ }
- return translated;
+ return translated;
}
function convertOptionValue(
- interaction: Interaction,
- option: InteractionDataOption,
- translateOptions?: Record,
+ interaction: Interaction,
+ option: InteractionDataOption,
+ translateOptions?: Record,
): [
- string,
- (
- | { user: User; member: Member }
- | Role
- | {
- id: bigint;
- name: string;
- type: ChannelTypes;
- permissions: bigint;
- }
- | boolean
- | string
- | number
- ),
+ string,
+ (
+ | { user: User; member: Member }
+ | Role
+ | {
+ id: bigint;
+ name: string;
+ type: ChannelTypes;
+ permissions: bigint;
+ }
+ | boolean
+ | string
+ | number
+ ),
] {
- // THE OPTION IS A CHANNEL
- if (option.type === ApplicationCommandOptionTypes.Channel) {
- const channel = interaction.data?.resolved?.channels?.get(BigInt(option.value as string));
+ // THE OPTION IS A CHANNEL
+ if (option.type === ApplicationCommandOptionTypes.Channel) {
+ const channel = interaction.data?.resolved?.channels?.get(BigInt(option.value as string));
- // SAVE THE ARGUMENT WITH THE CORRECT NAME
- return [translateOptions?.[option.name] ?? option.name, channel];
- }
+ // SAVE THE ARGUMENT WITH THE CORRECT NAME
+ return [translateOptions?.[option.name] ?? option.name, channel];
+ }
- // THE OPTION IS A ROLE
- if (option.type === ApplicationCommandOptionTypes.Role) {
- const role = interaction.data?.resolved?.roles?.get(BigInt(option.value as string));
+ // THE OPTION IS A ROLE
+ if (option.type === ApplicationCommandOptionTypes.Role) {
+ const role = interaction.data?.resolved?.roles?.get(BigInt(option.value as string));
- // SAVE THE ARGUMENT WITH THE CORRECT NAME
- return [translateOptions?.[option.name] ?? option.name, role];
- }
+ // SAVE THE ARGUMENT WITH THE CORRECT NAME
+ return [translateOptions?.[option.name] ?? option.name, role];
+ }
- // THE OPTION IS A USER
- if (option.type === ApplicationCommandOptionTypes.User) {
- const user = interaction.data?.resolved?.users?.get(BigInt(option.value as string));
- const member = interaction.data?.resolved?.members?.get(BigInt(option.value as string));
+ // THE OPTION IS A USER
+ if (option.type === ApplicationCommandOptionTypes.User) {
+ const user = interaction.data?.resolved?.users?.get(BigInt(option.value as string));
+ const member = interaction.data?.resolved?.members?.get(BigInt(option.value as string));
- // SAVE THE ARGUMENT WITH THE CORRECT NAME
- return [
- translateOptions?.[option.name] ?? option.name,
- {
- member,
- user,
- },
- ];
- }
+ // SAVE THE ARGUMENT WITH THE CORRECT NAME
+ return [
+ translateOptions?.[option.name] ?? option.name,
+ {
+ member,
+ user,
+ },
+ ];
+ }
- // THE OPTION IS A MENTIONABLE
- if (option.type === ApplicationCommandOptionTypes.Mentionable) {
- const role = interaction.data?.resolved?.roles?.get(BigInt(option.value as string));
- const user = interaction.data?.resolved?.users?.get(BigInt(option.value as string));
- const member = interaction.data?.resolved?.members?.get(BigInt(option.value as string));
+ // THE OPTION IS A MENTIONABLE
+ if (option.type === ApplicationCommandOptionTypes.Mentionable) {
+ const role = interaction.data?.resolved?.roles?.get(BigInt(option.value as string));
+ const user = interaction.data?.resolved?.users?.get(BigInt(option.value as string));
+ const member = interaction.data?.resolved?.members?.get(BigInt(option.value as string));
- const final = user && member ? { user, member } : role;
+ const final = user && member ? { user, member } : role;
- // SAVE THE ARGUMENT WITH THE CORRECT NAME
- return [translateOptions?.[option.name] ?? option.name, final];
- }
+ // SAVE THE ARGUMENT WITH THE CORRECT NAME
+ return [translateOptions?.[option.name] ?? option.name, final];
+ }
- // THE REST OF OPTIONS DON'T NEED ANY CONVERTION
- // SAVE THE ARGUMENT WITH THE CORRECT NAME
- // @ts-expect-error
- return [translateOptions?.[option.name] ?? option.name, option.value];
+ // THE REST OF OPTIONS DON'T NEED ANY CONVERTION
+ // SAVE THE ARGUMENT WITH THE CORRECT NAME
+ // @ts-expect-error
+ return [translateOptions?.[option.name] ?? option.name, option.value];
}
/** Parse the options to a nice object.
* NOTE: this does not work with subcommands
*/
export function optionParser(
- interaction: Interaction,
- translateOptions?: Record,
+ interaction: Interaction,
+ translateOptions?: Record,
):
- | InteractionCommandArgs
- | { [key: string]: InteractionCommandArgs }
- | { [key: string]: { [key: string]: InteractionCommandArgs } } {
- // OPTIONS CAN BE UNDEFINED SO WE JUST RETURN AN EMPTY OBJECT
- if (!interaction.data?.options) return {};
+ | InteractionCommandArgs
+ | { [key: string]: InteractionCommandArgs }
+ | { [key: string]: { [key: string]: InteractionCommandArgs } } {
+ // OPTIONS CAN BE UNDEFINED SO WE JUST RETURN AN EMPTY OBJECT
+ if (!interaction.data?.options) return {};
- // A SUBCOMMAND WAS USED
- if (interaction.data.options[0]?.type === ApplicationCommandOptionTypes.SubCommand) {
- const convertedOptions: Record<
- string,
- | { user: User; member: Member }
- | Role
- | {
- id: bigint;
- name: string;
- type: ChannelTypes;
- permissions: bigint;
- }
- | boolean
- | string
- | number
- > = {};
- // CONVERT ALL THE OPTIONS
- for (const option of interaction.data.options[0].options ?? []) {
- const [name, value] = convertOptionValue(interaction, option, translateOptions);
- convertedOptions[name] = value;
- }
+ // A SUBCOMMAND WAS USED
+ if (interaction.data.options[0]?.type === ApplicationCommandOptionTypes.SubCommand) {
+ const convertedOptions: Record<
+ string,
+ | { user: User; member: Member }
+ | Role
+ | {
+ id: bigint;
+ name: string;
+ type: ChannelTypes;
+ permissions: bigint;
+ }
+ | boolean
+ | string
+ | number
+ > = {};
+ // CONVERT ALL THE OPTIONS
+ for (const option of interaction.data.options[0].options ?? []) {
+ const [name, value] = convertOptionValue(interaction, option, translateOptions);
+ convertedOptions[name] = value;
+ }
- // @ts-expect-error
- return {
- [translateOptions?.[interaction.data.options[0].name] ?? interaction.data.options[0].name]: convertedOptions,
- };
- }
+ // @ts-expect-error
+ return {
+ [translateOptions?.[interaction.data.options[0].name] ?? interaction.data.options[0].name]: convertedOptions,
+ };
+ }
- // A SUBCOMMAND GROUP WAS USED
- if (interaction.data.options[0]?.type === ApplicationCommandOptionTypes.SubCommandGroup) {
- const convertedOptions: Record = {};
- // CONVERT ALL THE OPTIONS
- for (const option of interaction.data.options[0]?.options![0]?.options ?? []) {
- const [name, value] = convertOptionValue(interaction, option, translateOptions);
- // @ts-expect-error
- convertedOptions[name] = value;
- }
+ // A SUBCOMMAND GROUP WAS USED
+ if (interaction.data.options[0]?.type === ApplicationCommandOptionTypes.SubCommandGroup) {
+ const convertedOptions: Record = {};
+ // CONVERT ALL THE OPTIONS
+ for (const option of interaction.data.options[0]?.options![0]?.options ?? []) {
+ const [name, value] = convertOptionValue(interaction, option, translateOptions);
+ // @ts-expect-error
+ convertedOptions[name] = value;
+ }
- // @ts-expect-error
- return {
- [translateOptions?.[interaction.data.options[0].name] ?? interaction.data.options[0].name]: {
- [
- translateOptions?.[interaction.data.options[0]!.options![0]!.name] ??
- interaction.data.options[0]!.options![0]!.name
- ]: convertedOptions,
- },
- };
- }
+ // @ts-expect-error
+ return {
+ [translateOptions?.[interaction.data.options[0].name] ?? interaction.data.options[0].name]: {
+ [translateOptions?.[interaction.data.options[0]!.options![0]!.name] ??
+ interaction.data.options[0]!.options![0]!.name]: convertedOptions,
+ },
+ };
+ }
- // A NORMAL COMMAND WAS USED
- const convertedOptions: Record<
- string,
- Member | Role | Record> | boolean | string | number
- > = {};
- for (const option of interaction.data.options ?? []) {
- const [name, value] = convertOptionValue(interaction, option, translateOptions);
- // @ts-expect-error
- convertedOptions[name] = value;
- }
+ // A NORMAL COMMAND WAS USED
+ const convertedOptions: Record<
+ string,
+ Member | Role | Record> | boolean | string | number
+ > = {};
+ for (const option of interaction.data.options ?? []) {
+ const [name, value] = convertOptionValue(interaction, option, translateOptions);
+ // @ts-expect-error
+ convertedOptions[name] = value;
+ }
- return convertedOptions;
+ return convertedOptions;
}
/** The interaction arguments.
* Important the members `deaf` and `mute` properties will always be false.
*/
export type InteractionCommandArgs = Record<
- string,
- Member | Role | Record> | boolean | string | number
+ string,
+ Member | Role | Record> | boolean | string | number
>;
diff --git a/examples/bigbot/src/bot/events/interactions/mod.ts b/examples/bigbot/src/bot/events/interactions/mod.ts
index e07a7a069..63de86904 100644
--- a/examples/bigbot/src/bot/events/interactions/mod.ts
+++ b/examples/bigbot/src/bot/events/interactions/mod.ts
@@ -1,23 +1,23 @@
-import { InteractionTypes, MessageComponentTypes } from "discordeno";
-import { bot } from "../../bot.js";
-import type { InteractionWithCustomProps } from "../../typings/discordeno.js";
-import { executeButtonClick } from "./button.js";
-import { executeSlashCommand } from "./command.js";
-import { executeModalSubmit } from "./modal.js";
+import { InteractionTypes, MessageComponentTypes } from 'discordeno';
+import { bot } from '../../bot.js';
+import type { InteractionWithCustomProps } from '../../typings/discordeno.js';
+import { executeButtonClick } from './button.js';
+import { executeSlashCommand } from './command.js';
+import { executeModalSubmit } from './modal.js';
export function setInteractionCreateEvent() {
- bot.events.interactionCreate = async function (_, interaction) {
- if (interaction.type === InteractionTypes.ApplicationCommand) {
- await executeSlashCommand(bot, interaction as InteractionWithCustomProps);
- } else if (interaction.type === InteractionTypes.MessageComponent) {
- if (!interaction.data) return;
+ bot.events.interactionCreate = async function (_, interaction) {
+ if (interaction.type === InteractionTypes.ApplicationCommand) {
+ await executeSlashCommand(bot, interaction as InteractionWithCustomProps);
+ } else if (interaction.type === InteractionTypes.MessageComponent) {
+ if (!interaction.data) return;
- // THE INTERACTION CAME FROM A BUTTON
- if (interaction.data.componentType === MessageComponentTypes.Button) {
- await executeButtonClick(bot, interaction);
- }
- } else if (interaction.type === InteractionTypes.ModalSubmit) {
- await executeModalSubmit(bot, interaction);
- }
- };
+ // THE INTERACTION CAME FROM A BUTTON
+ if (interaction.data.componentType === MessageComponentTypes.Button) {
+ await executeButtonClick(bot, interaction);
+ }
+ } else if (interaction.type === InteractionTypes.ModalSubmit) {
+ await executeModalSubmit(bot, interaction);
+ }
+ };
}
diff --git a/examples/bigbot/src/bot/events/interactions/modal.ts b/examples/bigbot/src/bot/events/interactions/modal.ts
index e01be5a0c..faf395edc 100644
--- a/examples/bigbot/src/bot/events/interactions/modal.ts
+++ b/examples/bigbot/src/bot/events/interactions/modal.ts
@@ -1,16 +1,16 @@
-import type { Interaction } from "discordeno";
-import type { BotWithCustomProps } from "../../bot.js";
+import type { Interaction } from 'discordeno';
+import type { BotWithCustomProps } from '../../bot.js';
export async function executeModalSubmit(bot: BotWithCustomProps, interaction: Interaction) {
- if (!interaction.data) return;
+ if (!interaction.data) return;
- bot.logger.info(
- `[Modal] The ${
- interaction.data?.customId || "UNKNWON"
- } modal was submitted in Guild: ${interaction.guildId} by ${interaction.user.id}.`,
- );
+ bot.logger.info(
+ `[Modal] The ${interaction.data?.customId || 'UNKNWON'} modal was submitted in Guild: ${interaction.guildId} by ${
+ interaction.user.id
+ }.`,
+ );
- await Promise.allSettled([
- // SETUP-DD-TEMP: Insert any functions you wish to run when a user clicks a button.
- ]).catch(console.log);
+ await Promise.allSettled([
+ // SETUP-DD-TEMP: Insert any functions you wish to run when a user clicks a button.
+ ]).catch(console.log);
}
diff --git a/examples/bigbot/src/bot/events/messages/create.ts b/examples/bigbot/src/bot/events/messages/create.ts
index 7f5466cda..e612077a4 100644
--- a/examples/bigbot/src/bot/events/messages/create.ts
+++ b/examples/bigbot/src/bot/events/messages/create.ts
@@ -1,12 +1,12 @@
-import { bot } from "../../bot.js";
-import { processMessageCollectors } from "../../utils/collectors.js";
+import { bot } from '../../bot.js';
+import { processMessageCollectors } from '../../utils/collectors.js';
export function setMessageCreateEvent() {
- bot.events.messageCreate = async function (_, message) {
- processMessageCollectors(message);
+ bot.events.messageCreate = async function (_, message) {
+ processMessageCollectors(message);
- await Promise.allSettled([
- // SETUP-DD-TEMP: Add any functions you want to run on every message here. For example, automoderation filters.
- ]).catch(console.log);
- };
+ await Promise.allSettled([
+ // SETUP-DD-TEMP: Add any functions you want to run on every message here. For example, automoderation filters.
+ ]).catch(console.log);
+ };
}
diff --git a/examples/bigbot/src/bot/events/mod.ts b/examples/bigbot/src/bot/events/mod.ts
index 625f3736e..d9494d269 100644
--- a/examples/bigbot/src/bot/events/mod.ts
+++ b/examples/bigbot/src/bot/events/mod.ts
@@ -1,9 +1,9 @@
-import { setInteractionCreateEvent } from "./interactions/mod.js";
-import { setMessageCreateEvent } from "./messages/create.js";
-import { setRawEvent } from "./raw.js";
+import { setInteractionCreateEvent } from './interactions/mod.js';
+import { setMessageCreateEvent } from './messages/create.js';
+import { setRawEvent } from './raw.js';
export function setupEventHandlers() {
- setInteractionCreateEvent();
- setRawEvent();
- setMessageCreateEvent();
+ setInteractionCreateEvent();
+ setRawEvent();
+ setMessageCreateEvent();
}
diff --git a/examples/bigbot/src/bot/events/raw.ts b/examples/bigbot/src/bot/events/raw.ts
index e4a6e2772..c5211497f 100644
--- a/examples/bigbot/src/bot/events/raw.ts
+++ b/examples/bigbot/src/bot/events/raw.ts
@@ -1,38 +1,38 @@
-import type { DiscordUnavailableGuild } from "discordeno";
-import { prisma } from "../../prisma.js";
-import { bot } from "../bot.js";
-import { updateGuildCommands, usesLatestCommandVersion } from "../utils/slash/updateCommands.js";
+import type { DiscordUnavailableGuild } from 'discordeno';
+import { prisma } from '../../prisma.js';
+import { bot } from '../bot.js';
+import { updateGuildCommands, usesLatestCommandVersion } from '../utils/slash/updateCommands.js';
/** To prevent updating every guild when a shard goes ready we have to ignore them using this */
// export const initialyLoadingGuildIds = new Set()
export function setRawEvent() {
- bot.events.raw = async function (_, data) {
- if (data.t === "GUILD_DELETE") {
- const id = (data.d as DiscordUnavailableGuild).id;
+ bot.events.raw = async function (_, data) {
+ if (data.t === 'GUILD_DELETE') {
+ const id = (data.d as DiscordUnavailableGuild).id;
- return await prisma.commands.delete({ where: { id: bot.transformers.snowflake(id) } });
- }
+ return await prisma.commands.delete({ where: { id: bot.transformers.snowflake(id) } });
+ }
- const id = bot.transformers.snowflake(
- (data.t && ["GUILD_UPDATE", "GUILD_CREATE"].includes(data.t)
- // deno-lint-ignore no-explicit-any
- ? (data.d )?.id
- // deno-lint-ignore no-explicit-any
- : (data.d )?.guild_id) ?? "",
- );
+ const id = bot.transformers.snowflake(
+ (data.t && ['GUILD_UPDATE', 'GUILD_CREATE'].includes(data.t)
+ ? // deno-lint-ignore no-explicit-any
+ data.d?.id
+ : // deno-lint-ignore no-explicit-any
+ data.d?.guild_id) ?? '',
+ );
- // The GUILD_CREATE event came from a shard loaded event so ignore it
- if (["READY", "GUILD_LOADED_DD", null].includes(data.t)) return;
+ // The GUILD_CREATE event came from a shard loaded event so ignore it
+ if (['READY', 'GUILD_LOADED_DD', null].includes(data.t)) return;
- // console.log({ id, v: await usesLatestCommandVersion(id) })
+ // console.log({ id, v: await usesLatestCommandVersion(id) })
- if (!id || (await usesLatestCommandVersion(id))) return;
- // dev guild
- if (id === 547046977578336286n) return;
+ if (!id || (await usesLatestCommandVersion(id))) return;
+ // dev guild
+ if (id === 547046977578336286n) return;
- // NEW GUILD AVAILABLE
- bot.logger.info(`[Slash Setup] Installing Slash commands on Guild ${id} event type: ${data.t}`);
- await updateGuildCommands(bot, id).catch(bot.logger.error);
- };
+ // NEW GUILD AVAILABLE
+ bot.logger.info(`[Slash Setup] Installing Slash commands on Guild ${id} event type: ${data.t}`);
+ await updateGuildCommands(bot, id).catch(bot.logger.error);
+ };
}
diff --git a/examples/bigbot/src/bot/index.ts b/examples/bigbot/src/bot/index.ts
index 55afe2720..32040f629 100644
--- a/examples/bigbot/src/bot/index.ts
+++ b/examples/bigbot/src/bot/index.ts
@@ -1,14 +1,14 @@
-import dotenv from "dotenv";
+import dotenv from 'dotenv';
-import type { DiscordGatewayPayload } from "discordeno";
+import type { DiscordGatewayPayload } from 'discordeno';
// ReferenceError: publishMessage is not defined
// import Embeds from "discordeno/embeds";
-import amqplib from "amqplib";
-import express from "express";
-import { BOT_ID, EVENT_HANDLER_URL } from "../configs.js";
-import { bot } from "./bot.js";
-import { updateDevCommands } from "./utils/slash/updateCommands.js";
-import { webhookURLToIDAndToken } from "./utils/webhook.js";
+import amqplib from 'amqplib';
+import express from 'express';
+import { BOT_ID, EVENT_HANDLER_URL } from '../configs.js';
+import { bot } from './bot.js';
+import { updateDevCommands } from './utils/slash/updateCommands.js';
+import { webhookURLToIDAndToken } from './utils/webhook.js';
dotenv.config();
const BUGS_ERRORS_REPORT_WEBHOOK = process.env.BUGS_ERRORS_REPORT_WEBHOOK;
@@ -16,23 +16,23 @@ const EVENT_HANDLER_AUTHORIZATION = process.env.EVENT_HANDLER_AUTHORIZATION as s
const EVENT_HANDLER_PORT = process.env.EVENT_HANDLER_PORT as string;
process
- .on("unhandledRejection", (error) => {
- if (!BUGS_ERRORS_REPORT_WEBHOOK) return;
- const { id, token } = webhookURLToIDAndToken(BUGS_ERRORS_REPORT_WEBHOOK);
- if (!id || !token) return;
+ .on('unhandledRejection', (error) => {
+ if (!BUGS_ERRORS_REPORT_WEBHOOK) return;
+ const { id, token } = webhookURLToIDAndToken(BUGS_ERRORS_REPORT_WEBHOOK);
+ if (!id || !token) return;
- // DO NOT SEND ERRORS FROM NON PRODUCTION
- if (BOT_ID !== 270010330782892032n) {
- return console.error(error);
- }
+ // DO NOT SEND ERRORS FROM NON PRODUCTION
+ if (BOT_ID !== 270010330782892032n) {
+ return console.error(error);
+ }
- // An unhandled error occurred on the bot in production
- console.error(error ?? `An unhandled rejection error occurred but error was null or undefined`);
+ // An unhandled error occurred on the bot in production
+ console.error(error ?? `An unhandled rejection error occurred but error was null or undefined`);
- if (!error) return;
+ if (!error) return;
- // ReferenceError: publishMessage is not defined
- /*
+ // ReferenceError: publishMessage is not defined
+ /*
const embeds = new Embeds()
.setDescription(["```js", error, "```"].join(`\n`))
.setTimestamp()
@@ -41,23 +41,23 @@ process
// SEND ERROR TO THE LOG CHANNEL ON THE DEV SERVER
return bot.helpers.sendWebhookMessage(bot.transformers.snowflake(id), token, { embeds }).catch(console.error);
*/
- })
- .on("uncaughtException", async (error) => {
- if (!BUGS_ERRORS_REPORT_WEBHOOK) return;
- const { id, token } = webhookURLToIDAndToken(BUGS_ERRORS_REPORT_WEBHOOK);
- if (!id || !token) return;
+ })
+ .on('uncaughtException', async (error) => {
+ if (!BUGS_ERRORS_REPORT_WEBHOOK) return;
+ const { id, token } = webhookURLToIDAndToken(BUGS_ERRORS_REPORT_WEBHOOK);
+ if (!id || !token) return;
- // DO NOT SEND ERRORS FROM NON PRODUCTION
- if (BOT_ID !== 270010330782892032n) {
- return console.error(error);
- }
+ // DO NOT SEND ERRORS FROM NON PRODUCTION
+ if (BOT_ID !== 270010330782892032n) {
+ return console.error(error);
+ }
- // An unhandled error occurred on the bot in production
- console.error(error ?? `An unhandled exception occurred but error was null or undefined`);
+ // An unhandled error occurred on the bot in production
+ console.error(error ?? `An unhandled exception occurred but error was null or undefined`);
- if (!error) process.exit(1);
+ if (!error) process.exit(1);
- /*
+ /*
const embeds = new Embeds()
.setDescription(["```js", error.stack, "```"].join(`\n`))
.setTimestamp()
@@ -66,124 +66,120 @@ process
await bot.helpers.sendWebhookMessage(bot.transformers.snowflake(id), token, { embeds }).catch(console.error);
*/
- process.exit(1);
- });
+ process.exit(1);
+ });
-if (process.env.DEVELOPMENT === "true") {
- bot.logger.info(`[DEV MODE] Updating slash commands for dev server.`);
- updateDevCommands(bot);
+if (process.env.DEVELOPMENT === 'true') {
+ bot.logger.info(`[DEV MODE] Updating slash commands for dev server.`);
+ updateDevCommands(bot);
}
// Handle events from the gateway
const handleEvent = async (message: DiscordGatewayPayload, shardId: number) => {
- // EMITS RAW EVENT
- bot.events.raw(bot, message, shardId);
+ // EMITS RAW EVENT
+ bot.events.raw(bot, message, shardId);
- if (message.t && message.t !== "RESUMED") {
- // When a guild or something isnt in cache this will fetch it before doing anything else
- if (!["READY", "GUILD_LOADED_DD"].includes(message.t)) {
- await bot.events.dispatchRequirements(bot, message, shardId);
- }
+ if (message.t && message.t !== 'RESUMED') {
+ // When a guild or something isnt in cache this will fetch it before doing anything else
+ if (!['READY', 'GUILD_LOADED_DD'].includes(message.t)) {
+ await bot.events.dispatchRequirements(bot, message, shardId);
+ }
- bot.handlers[message.t]?.(bot, message, shardId);
- }
+ bot.handlers[message.t]?.(bot, message, shardId);
+ }
};
const app = express();
app.use(
- express.urlencoded({
- extended: true,
- }),
+ express.urlencoded({
+ extended: true,
+ }),
);
app.use(express.json());
-app.all("/", async (req, res) => {
- try {
- if (!EVENT_HANDLER_AUTHORIZATION || EVENT_HANDLER_AUTHORIZATION !== req.headers.authorization) {
- return res.status(401).json({ error: "Invalid authorization key." });
- }
+app.all('/', async (req, res) => {
+ try {
+ if (!EVENT_HANDLER_AUTHORIZATION || EVENT_HANDLER_AUTHORIZATION !== req.headers.authorization) {
+ return res.status(401).json({ error: 'Invalid authorization key.' });
+ }
- const json = req.body as {
- message: DiscordGatewayPayload;
- shardId: number;
- };
+ const json = req.body as {
+ message: DiscordGatewayPayload;
+ shardId: number;
+ };
- await handleEvent(json.message, json.shardId);
+ await handleEvent(json.message, json.shardId);
- res.status(200).json({ success: true });
- } catch (error: any) {
- bot.logger.error(error);
- res.status(error.code).json(error);
- }
+ res.status(200).json({ success: true });
+ } catch (error: any) {
+ bot.logger.error(error);
+ res.status(error.code).json(error);
+ }
});
app.listen(EVENT_HANDLER_PORT, () => {
- console.log(`Bot is listening at ${EVENT_HANDLER_URL};`);
+ console.log(`Bot is listening at ${EVENT_HANDLER_URL};`);
});
const connectRabbitmq = async () => {
- let connection: amqplib.Connection | undefined;
+ let connection: amqplib.Connection | undefined;
- try {
- connection = await amqplib.connect(
- `amqp://${process.env.MESSAGEQUEUE_USERNAME}:${process.env.MESSAGEQUEUE_PASSWORD}@${process.env.MESSAGEQUEUE_URL}`,
- );
- } catch (error) {
- console.error(error);
- setTimeout(connectRabbitmq, 1000);
- }
+ try {
+ connection = await amqplib.connect(
+ `amqp://${process.env.MESSAGEQUEUE_USERNAME}:${process.env.MESSAGEQUEUE_PASSWORD}@${process.env.MESSAGEQUEUE_URL}`,
+ );
+ } catch (error) {
+ console.error(error);
+ setTimeout(connectRabbitmq, 1000);
+ }
- if (!connection) return;
- connection.on("error", (err) => {
- console.error(err);
- setTimeout(connectRabbitmq, 1000);
- });
+ if (!connection) return;
+ connection.on('error', (err) => {
+ console.error(err);
+ setTimeout(connectRabbitmq, 1000);
+ });
- connection.on("close", () => {
- setTimeout(connectRabbitmq, 1000);
- });
+ connection.on('close', () => {
+ setTimeout(connectRabbitmq, 1000);
+ });
- try {
- const channel = await connection.createChannel();
+ try {
+ const channel = await connection.createChannel();
- await channel.assertExchange(
- "gatewayMessage",
- "x-message-deduplication",
- {
- durable: true,
- arguments: {
- "x-cache-size": 1000,
- "x-cache-ttl": 500,
- },
- },
- );
+ await channel.assertExchange('gatewayMessage', 'x-message-deduplication', {
+ durable: true,
+ arguments: {
+ 'x-cache-size': 1000,
+ 'x-cache-ttl': 500,
+ },
+ });
- await channel.assertQueue("gatewayMessageQueue");
- await channel.bindQueue("gatewayMessageQueue", "gatewayMessage", "");
- await channel.consume(
- "gatewayMessageQueue",
- async (msg) => {
- if (!msg) return;
- const json = JSON.parse(msg.content.toString()) as {
- message: DiscordGatewayPayload;
- shardId: number;
- };
+ await channel.assertQueue('gatewayMessageQueue');
+ await channel.bindQueue('gatewayMessageQueue', 'gatewayMessage', '');
+ await channel.consume(
+ 'gatewayMessageQueue',
+ async (msg) => {
+ if (!msg) return;
+ const json = JSON.parse(msg.content.toString()) as {
+ message: DiscordGatewayPayload;
+ shardId: number;
+ };
- await handleEvent(json.message, json.shardId);
+ await handleEvent(json.message, json.shardId);
- await channel.ack(msg);
- },
- {
- noAck: false,
- },
- );
- } catch (error) {
- console.error(error);
- }
+ await channel.ack(msg);
+ },
+ {
+ noAck: false,
+ },
+ );
+ } catch (error) {
+ console.error(error);
+ }
};
-if (process.env.MESSAGEQUEUE_ENABLE === "true") {
- connectRabbitmq();
+if (process.env.MESSAGEQUEUE_ENABLE === 'true') {
+ connectRabbitmq();
}
diff --git a/examples/bigbot/src/bot/languages/english.ts b/examples/bigbot/src/bot/languages/english.ts
index 71afc7cea..08b37aa4d 100644
--- a/examples/bigbot/src/bot/languages/english.ts
+++ b/examples/bigbot/src/bot/languages/english.ts
@@ -1,23 +1,23 @@
const english = {
- // Permissions
- NEED_VIP: "❌ Only VIP users or servers can use this feature.",
+ // Permissions
+ NEED_VIP: '❌ Only VIP users or servers can use this feature.',
- // Execute Command
- EXECUTE_COMMAND_NOT_FOUND: "❌ Something went wrong. I was not able to find this command.",
- EXECUTE_COMMAND_ERROR: "❌ Something went wrong. The command execution has thrown an error.",
+ // Execute Command
+ EXECUTE_COMMAND_NOT_FOUND: '❌ Something went wrong. I was not able to find this command.',
+ EXECUTE_COMMAND_ERROR: '❌ Something went wrong. The command execution has thrown an error.',
- // Language Command
- LANGUAGE_NAME: "language",
- LANGUAGE_DESCRIPTION: "⚙️ Change the bots language.",
- LANGUAGE_KEY_NAME: "name",
- LANGUAGE_KEY_DESCRIPTION: "What language would you like to set?",
- LANGUAGE_UPDATED: (language: string) => `The language has been updated to ${language}`,
+ // Language Command
+ LANGUAGE_NAME: 'language',
+ LANGUAGE_DESCRIPTION: '⚙️ Change the bots language.',
+ LANGUAGE_KEY_NAME: 'name',
+ LANGUAGE_KEY_DESCRIPTION: 'What language would you like to set?',
+ LANGUAGE_UPDATED: (language: string) => `The language has been updated to ${language}`,
- // Ping Command
- PING_NAME: "ping",
- PING_DESCRIPTION: "🏓 Check whether the bot is online and responsive.",
- PING_RESPONSE: "🏓 Pong! I am online and responsive! :clock10:",
- PING_RESPONSE_WITH_TIME: (time: number) => `🏓 Pong! ${time / 1000} seconds! I am online and responsive! :clock10:`,
+ // Ping Command
+ PING_NAME: 'ping',
+ PING_DESCRIPTION: '🏓 Check whether the bot is online and responsive.',
+ PING_RESPONSE: '🏓 Pong! I am online and responsive! :clock10:',
+ PING_RESPONSE_WITH_TIME: (time: number) => `🏓 Pong! ${time / 1000} seconds! I am online and responsive! :clock10:`,
} as const;
export default english;
diff --git a/examples/bigbot/src/bot/languages/languages.ts b/examples/bigbot/src/bot/languages/languages.ts
index ede55921c..ca1142f49 100644
--- a/examples/bigbot/src/bot/languages/languages.ts
+++ b/examples/bigbot/src/bot/languages/languages.ts
@@ -1,4 +1,4 @@
-import english from "./english.js";
+import english from './english.js';
// import french from './french'
// import german from './german'
// import portuguese from './portuguese'
@@ -6,15 +6,15 @@ import english from "./english.js";
// import spanish from './spanish'
const languages: Record & Record = {
- english,
- // french,
- // german,
- // portuguese,
- // russian,
- // spanish,
+ english,
+ // french,
+ // german,
+ // portuguese,
+ // russian,
+ // spanish,
};
export default languages;
export type Language = Record string)>;
-export type LanguageNames = "english";
+export type LanguageNames = 'english';
diff --git a/examples/bigbot/src/bot/languages/translate.ts b/examples/bigbot/src/bot/languages/translate.ts
index 8fe4954ba..75371353e 100644
--- a/examples/bigbot/src/bot/languages/translate.ts
+++ b/examples/bigbot/src/bot/languages/translate.ts
@@ -1,8 +1,8 @@
-import Embeds from "discordeno/embeds";
-import { bot } from "../bot.js";
-import { webhookURLToIDAndToken } from "../utils/webhook.js";
-import type english from "./english.js";
-import languages from "./languages.js";
+import Embeds from 'discordeno/embeds';
+import { bot } from '../bot.js';
+import { webhookURLToIDAndToken } from '../utils/webhook.js';
+import type english from './english.js';
+import languages from './languages.js';
const MISSING_TRANSLATION_WEBHOOK = process.env.MISSING_TRANSLATION_WEBHOOK;
@@ -10,75 +10,75 @@ const MISSING_TRANSLATION_WEBHOOK = process.env.MISSING_TRANSLATION_WEBHOOK;
export const serverLanguages = new Map();
export function translate(
- guildIdOrLanguage: bigint | keyof typeof languages,
- key: K,
- ...params: getArgs
+ guildIdOrLanguage: bigint | keyof typeof languages,
+ key: K,
+ ...params: getArgs
): string {
- const language = getLanguage(guildIdOrLanguage);
- let value: string | ((...any: any[]) => string) | string[] | undefined = languages[language]?.[key];
+ const language = getLanguage(guildIdOrLanguage);
+ let value: string | ((...any: any[]) => string) | string[] | undefined = languages[language]?.[key];
- // Was not able to be translated
- if (!value) {
- // Check if this key is available in english
- if (language !== "english") {
- value = languages.english[key];
- }
+ // Was not able to be translated
+ if (!value) {
+ // Check if this key is available in english
+ if (language !== 'english') {
+ value = languages.english[key];
+ }
- // Still not found in english so default to using the KEY_ITSELF
- if (!value) value = key;
+ // Still not found in english so default to using the KEY_ITSELF
+ if (!value) value = key;
- // Send a log webhook so the devs know sth is missing
- missingTranslation(language, key);
- }
+ // Send a log webhook so the devs know sth is missing
+ missingTranslation(language, key);
+ }
- if (Array.isArray(value)) return value.join("\n");
+ if (Array.isArray(value)) return value.join('\n');
- if (typeof value === "function") return value(...(params || []));
+ if (typeof value === 'function') return value(...(params || []));
- return value ;
+ return value;
}
/** Get the language this guild has set, will always return "english" if it is not in cache */
export function getLanguage(guildIdOrLanguage: bigint | keyof typeof languages) {
- return typeof guildIdOrLanguage === "string"
- ? guildIdOrLanguage
- : serverLanguages.get(guildIdOrLanguage) ?? "english";
+ return typeof guildIdOrLanguage === 'string'
+ ? guildIdOrLanguage
+ : serverLanguages.get(guildIdOrLanguage) ?? 'english';
}
export async function loadLanguage(guildId: bigint) {
- // TODO: add this settings
- // const settings = await database.findOne('guilds', guildId)
- const settings = { language: "undefined" };
+ // TODO: add this settings
+ // const settings = await database.findOne('guilds', guildId)
+ const settings = { language: 'undefined' };
- if (settings?.language && languages[settings.language]) {
- serverLanguages.set(guildId, settings.language);
- } else serverLanguages.set(guildId, "english");
+ if (settings?.language && languages[settings.language]) {
+ serverLanguages.set(guildId, settings.language);
+ } else serverLanguages.set(guildId, 'english');
}
/** Send a webhook for a missing translation key */
export async function missingTranslation(language: keyof typeof languages, key: string) {
- if (!MISSING_TRANSLATION_WEBHOOK) return;
- const { id, token } = webhookURLToIDAndToken(MISSING_TRANSLATION_WEBHOOK);
- if (!id || !token) return;
+ if (!MISSING_TRANSLATION_WEBHOOK) return;
+ const { id, token } = webhookURLToIDAndToken(MISSING_TRANSLATION_WEBHOOK);
+ if (!id || !token) return;
- const embeds = new Embeds()
- .setTitle("Missing Translation")
- .setColor("RANDOM")
- .addField("Language", language, true)
- .addField("Key", key, true);
+ const embeds = new Embeds()
+ .setTitle('Missing Translation')
+ .setColor('RANDOM')
+ .addField('Language', language, true)
+ .addField('Key', key, true);
- await bot.helpers
- .sendWebhookMessage(bot.transformers.snowflake(id), token, {
- // SETUP-DD-TEMP: If you wish to make it @ mention you, please edit the next line.
- // content: `<@${owner id here}>`,
- embeds,
- wait: false,
- })
- .catch(bot.logger.error);
+ await bot.helpers
+ .sendWebhookMessage(bot.transformers.snowflake(id), token, {
+ // SETUP-DD-TEMP: If you wish to make it @ mention you, please edit the next line.
+ // content: `<@${owner id here}>`,
+ embeds,
+ wait: false,
+ })
+ .catch(bot.logger.error);
}
// type translationKeys = keyof typeof english | string
export type translationKeys = keyof typeof english;
type getArgs = typeof english[K] extends (...any: any[]) => unknown
- ? Parameters
- : [];
+ ? Parameters
+ : [];
diff --git a/examples/bigbot/src/bot/typings/discordeno.ts b/examples/bigbot/src/bot/typings/discordeno.ts
index 58a22d82d..fecaf6ec0 100644
--- a/examples/bigbot/src/bot/typings/discordeno.ts
+++ b/examples/bigbot/src/bot/typings/discordeno.ts
@@ -1,12 +1,12 @@
// This file allows you to tell typescript about any additions you have made to the internal discordeno objects.
-import type { Interaction, InteractionCallbackData, InteractionResponse, Message } from "discordeno";
+import type { Interaction, InteractionCallbackData, InteractionResponse, Message } from 'discordeno';
export interface InteractionWithCustomProps extends Interaction {
- // Normally, to send a response you would have to do something like bot.helpers.sendInteractionResponse(interaction.id, interaction.token, { type: InteractionResponseTypes.ChannelMessageWithSource, data: { content: "text here" } })
- // But with this reply method we added, it is as simple as interaction.reply("text here").
- // Feel free to delete these comments once you have understood the concept.
- /** Send a reply to an interaction. */
- reply: (response: InteractionResponse | string) => Promise;
- /** Edit a deferred reply of an interaction. */
- editReply: (response: InteractionCallbackData | string) => Promise;
+ // Normally, to send a response you would have to do something like bot.helpers.sendInteractionResponse(interaction.id, interaction.token, { type: InteractionResponseTypes.ChannelMessageWithSource, data: { content: "text here" } })
+ // But with this reply method we added, it is as simple as interaction.reply("text here").
+ // Feel free to delete these comments once you have understood the concept.
+ /** Send a reply to an interaction. */
+ reply: (response: InteractionResponse | string) => Promise;
+ /** Edit a deferred reply of an interaction. */
+ editReply: (response: InteractionCallbackData | string) => Promise;
}
diff --git a/examples/bigbot/src/bot/utils/collectors.ts b/examples/bigbot/src/bot/utils/collectors.ts
index 45a11c5a3..e9e97c2b8 100644
--- a/examples/bigbot/src/bot/utils/collectors.ts
+++ b/examples/bigbot/src/bot/utils/collectors.ts
@@ -1,151 +1,151 @@
-import type { Interaction, Member, Message } from "discordeno";
-import { bot } from "../bot.js";
+import type { Interaction, Member, Message } from 'discordeno';
+import { bot } from '../bot.js';
export async function needMessage(
- memberId: bigint,
- channelId: bigint,
- options: MessageCollectorOptions & { amount?: 1 },
+ memberId: bigint,
+ channelId: bigint,
+ options: MessageCollectorOptions & { amount?: 1 },
): Promise;
export async function needMessage(
- memberId: bigint,
- channelId: bigint,
- options: MessageCollectorOptions & { amount?: number },
+ memberId: bigint,
+ channelId: bigint,
+ options: MessageCollectorOptions & { amount?: number },
): Promise;
export async function needMessage(memberId: bigint, channelId: bigint): Promise;
export async function needMessage(memberId: bigint, channelId: bigint, options?: MessageCollectorOptions) {
- const messages = await collectMessages({
- key: memberId,
- channelId,
- createdAt: Date.now(),
- filter: options?.filter || ((msg) => memberId === msg.authorId),
- amount: options?.amount || 1,
- duration: options?.duration || (1000 * 60 * 5),
- });
+ const messages = await collectMessages({
+ key: memberId,
+ channelId,
+ createdAt: Date.now(),
+ filter: options?.filter || ((msg) => memberId === msg.authorId),
+ amount: options?.amount || 1,
+ duration: options?.duration || 1000 * 60 * 5,
+ });
- return (options?.amount || 1) > 1 ? messages : messages[0];
+ return (options?.amount || 1) > 1 ? messages : messages[0];
}
export async function collectMessages(options: CollectMessagesOptions): Promise {
- return await new Promise((resolve, reject) => {
- bot.collectors.messages.get(options.key)?.reject(
- "A new collector began before the user responded to the previous one.",
- );
+ return await new Promise((resolve, reject) => {
+ bot.collectors.messages
+ .get(options.key)
+ ?.reject('A new collector began before the user responded to the previous one.');
- bot.collectors.messages.set(options.key, {
- ...options,
- messages: [],
- resolve,
- reject,
- });
- });
+ bot.collectors.messages.set(options.key, {
+ ...options,
+ messages: [],
+ resolve,
+ reject,
+ });
+ });
}
export function processMessageCollectors(message: Message) {
- // IGNORE DMS
- if (!message.guildId) return;
+ // IGNORE DMS
+ if (!message.guildId) return;
- const collector = bot.collectors.messages.get(message.authorId);
- // This user has no collectors pending or the message is in a different channel
- if (!collector || message.channelId !== collector.channelId) return;
- // This message is a response to a collector. Now running the filter function.
- if (!collector.filter(message)) return;
+ const collector = bot.collectors.messages.get(message.authorId);
+ // This user has no collectors pending or the message is in a different channel
+ if (!collector || message.channelId !== collector.channelId) return;
+ // This message is a response to a collector. Now running the filter function.
+ if (!collector.filter(message)) return;
- // If the necessary amount has been collected
- if (collector.amount === 1 || collector.amount === collector.messages.length + 1) {
- // Remove the collector
- bot.collectors.messages.delete(message.authorId);
- // Resolve the collector
- return collector.resolve([...collector.messages, message]);
- }
+ // If the necessary amount has been collected
+ if (collector.amount === 1 || collector.amount === collector.messages.length + 1) {
+ // Remove the collector
+ bot.collectors.messages.delete(message.authorId);
+ // Resolve the collector
+ return collector.resolve([...collector.messages, message]);
+ }
- // More messages still need to be collected
- collector.messages.push(message);
+ // More messages still need to be collected
+ collector.messages.push(message);
}
export interface BaseCollectorOptions {
- /** The amount of messages to collect before resolving. Defaults to 1 */
- amount?: number;
- /** The amount of milliseconds this should collect for before expiring. Defaults to 5 minutes. */
- duration?: number;
+ /** The amount of messages to collect before resolving. Defaults to 1 */
+ amount?: number;
+ /** The amount of milliseconds this should collect for before expiring. Defaults to 5 minutes. */
+ duration?: number;
}
export interface MessageCollectorOptions extends BaseCollectorOptions {
- /** Function that will filter messages to determine whether to collect this message. Defaults to making sure the message is sent by the same member. */
- filter?: (message: Message) => boolean;
- /** The amount of messages to collect before resolving. Defaults to 1 */
- amount?: number;
- /** The amount of milliseconds this should collect for before expiring. Defaults to 5 minutes. */
- duration?: number;
+ /** Function that will filter messages to determine whether to collect this message. Defaults to making sure the message is sent by the same member. */
+ filter?: (message: Message) => boolean;
+ /** The amount of messages to collect before resolving. Defaults to 1 */
+ amount?: number;
+ /** The amount of milliseconds this should collect for before expiring. Defaults to 5 minutes. */
+ duration?: number;
}
export interface ReactionCollectorOptions extends BaseCollectorOptions {
- /** Function that will filter messages to determine whether to collect this message. Defaults to making sure the message is sent by the same member. */
- filter?: (userId: bigint, reaction: string, message: Message | { id: string }) => boolean;
+ /** Function that will filter messages to determine whether to collect this message. Defaults to making sure the message is sent by the same member. */
+ filter?: (userId: bigint, reaction: string, message: Message | { id: string }) => boolean;
}
export interface BaseCollectorCreateOptions {
- /** The unique key that will be used to get responses for this. Ideally, meant to be for member id. */
- key: bigint;
- /** The amount of messages to collect before resolving. */
- amount: number;
- /** The timestamp when this collector was created */
- createdAt: number;
- /** The duration in milliseconds how long this collector should last. */
- duration: number;
+ /** The unique key that will be used to get responses for this. Ideally, meant to be for member id. */
+ key: bigint;
+ /** The amount of messages to collect before resolving. */
+ amount: number;
+ /** The timestamp when this collector was created */
+ createdAt: number;
+ /** The duration in milliseconds how long this collector should last. */
+ duration: number;
}
export interface CollectMessagesOptions extends BaseCollectorCreateOptions {
- /** The channel Id where this is listening to */
- channelId: bigint;
- /** Function that will filter messages to determine whether to collect this message */
- filter: (message: Message) => boolean;
+ /** The channel Id where this is listening to */
+ channelId: bigint;
+ /** Function that will filter messages to determine whether to collect this message */
+ filter: (message: Message) => boolean;
}
export interface CollectReactionsOptions extends BaseCollectorCreateOptions {
- /** The message Id where this is listening to */
- messageId: bigint;
- /** Function that will filter messages to determine whether to collect this message */
- filter: (userId: bigint, reaction: string, message: Message | { id: string }) => boolean;
+ /** The message Id where this is listening to */
+ messageId: bigint;
+ /** Function that will filter messages to determine whether to collect this message */
+ filter: (userId: bigint, reaction: string, message: Message | { id: string }) => boolean;
}
export interface MessageCollector extends CollectMessagesOptions {
- resolve: (value: Message[] | PromiseLike) => void;
- // deno-lint-ignore no-explicit-any
- reject: (reason?: any) => void;
- /** Where the messages are stored if the amount to collect is more than 1. */
- messages: Message[];
+ resolve: (value: Message[] | PromiseLike) => void;
+ // deno-lint-ignore no-explicit-any
+ reject: (reason?: any) => void;
+ /** Where the messages are stored if the amount to collect is more than 1. */
+ messages: Message[];
}
export interface ReactionCollector extends CollectReactionsOptions {
- resolve: (value: string[] | PromiseLike) => void;
- // deno-lint-ignore no-explicit-any
- reject: (reason?: any) => void;
- /** Where the reactions are stored if the amount to collect is more than 1. */
- reactions: string[];
+ resolve: (value: string[] | PromiseLike) => void;
+ // deno-lint-ignore no-explicit-any
+ reject: (reason?: any) => void;
+ /** Where the reactions are stored if the amount to collect is more than 1. */
+ reactions: string[];
}
export interface CollectButtonOptions extends BaseCollectorCreateOptions {
- /** The message Id where this is listening to */
- messageId: bigint;
- /** Function that will filter messages to determine whether to collect this message */
- filter: (message: Message, member?: Member) => boolean;
+ /** The message Id where this is listening to */
+ messageId: bigint;
+ /** Function that will filter messages to determine whether to collect this message */
+ filter: (message: Message, member?: Member) => boolean;
}
export interface ButtonCollector extends CollectButtonOptions {
- resolve: (value: ButtonCollectorReturn[] | PromiseLike) => void;
- // deno-lint-ignore no-explicit-any
- reject: (reason?: any) => void;
- /** Where the buttons are stored if the amount to collect is more than 1. */
- buttons: ButtonCollectorReturn[];
+ resolve: (value: ButtonCollectorReturn[] | PromiseLike) => void;
+ // deno-lint-ignore no-explicit-any
+ reject: (reason?: any) => void;
+ /** Where the buttons are stored if the amount to collect is more than 1. */
+ buttons: ButtonCollectorReturn[];
}
export interface ButtonCollectorOptions extends BaseCollectorOptions {
- /** Function that will filter messages to determine whether to collect this message. Defaults to making sure the message is sent by the same member. */
- filter?: (message: Message, member?: Member) => boolean;
+ /** Function that will filter messages to determine whether to collect this message. Defaults to making sure the message is sent by the same member. */
+ filter?: (message: Message, member?: Member) => boolean;
}
export interface ButtonCollectorReturn {
- customId: string;
- interaction: Omit;
- member?: Member;
+ customId: string;
+ interaction: Omit;
+ member?: Member;
}
diff --git a/examples/bigbot/src/bot/utils/internals/mod.ts b/examples/bigbot/src/bot/utils/internals/mod.ts
index d5ee2dcdd..d9508bc27 100644
--- a/examples/bigbot/src/bot/utils/internals/mod.ts
+++ b/examples/bigbot/src/bot/utils/internals/mod.ts
@@ -1,6 +1,6 @@
-import type { BotWithCustomProps } from "../../bot.js";
-import { customizeTransformers } from "./transformers/mod.js";
+import type { BotWithCustomProps } from '../../bot.js';
+import { customizeTransformers } from './transformers/mod.js';
export function customizeInternals(bot: BotWithCustomProps) {
- customizeTransformers(bot);
+ customizeTransformers(bot);
}
diff --git a/examples/bigbot/src/bot/utils/internals/transformers/guild.ts b/examples/bigbot/src/bot/utils/internals/transformers/guild.ts
index 48e0c8f67..a614ead07 100644
--- a/examples/bigbot/src/bot/utils/internals/transformers/guild.ts
+++ b/examples/bigbot/src/bot/utils/internals/transformers/guild.ts
@@ -2,28 +2,28 @@
// Only keep the properties your bot uses. If your bot does not use emojis in cache, you can save all that memory.
// This file is currently disabled, but you can enable it should you choose when you go the customizer file.
// Feel free to delete this comment or file as you wish.
-import type { Guild } from "discordeno";
-import { Collection } from "discordeno";
-import type { BotWithCustomProps } from "../../../bot.js";
+import type { Guild } from 'discordeno';
+import { Collection } from 'discordeno';
+import type { BotWithCustomProps } from '../../../bot.js';
export function customizeGuildTransformer(bot: BotWithCustomProps) {
- bot.transformers.guild = function (bot, payload) {
- const guildId = bot.transformers.snowflake(payload.guild.id);
+ bot.transformers.guild = function (bot, payload) {
+ const guildId = bot.transformers.snowflake(payload.guild.id);
- return {
- name: payload.guild.name,
- joinedAt: payload.guild.joined_at ? Date.parse(payload.guild.joined_at) : undefined,
- memberCount: payload.guild.member_count ?? 0,
- shardId: payload.shardId,
- icon: payload.guild.icon ? bot.utils.iconHashToBigInt(payload.guild.icon) : undefined,
- roles: new Collection(
- payload.guild.roles?.map((role) => {
- const result = bot.transformers.role(bot, { role, guildId });
- return [result.id, result];
- }),
- ),
- id: guildId,
- ownerId: bot.transformers.snowflake(payload.guild.owner_id),
- } as unknown as Guild;
- };
+ return {
+ name: payload.guild.name,
+ joinedAt: payload.guild.joined_at ? Date.parse(payload.guild.joined_at) : undefined,
+ memberCount: payload.guild.member_count ?? 0,
+ shardId: payload.shardId,
+ icon: payload.guild.icon ? bot.utils.iconHashToBigInt(payload.guild.icon) : undefined,
+ roles: new Collection(
+ payload.guild.roles?.map((role) => {
+ const result = bot.transformers.role(bot, { role, guildId });
+ return [result.id, result];
+ }),
+ ),
+ id: guildId,
+ ownerId: bot.transformers.snowflake(payload.guild.owner_id),
+ } as unknown as Guild;
+ };
}
diff --git a/examples/bigbot/src/bot/utils/internals/transformers/interaction.ts b/examples/bigbot/src/bot/utils/internals/transformers/interaction.ts
index 7e944803f..5129e5485 100644
--- a/examples/bigbot/src/bot/utils/internals/transformers/interaction.ts
+++ b/examples/bigbot/src/bot/utils/internals/transformers/interaction.ts
@@ -1,40 +1,40 @@
// SETUP-DD-TEMP: This file serves as an example, of how to customize internal discordeno objects. Feel free to use, add more or remove as desired.
-import type { InteractionCallbackData, InteractionResponse} from "discordeno";
-import { InteractionResponseTypes } from "discordeno";
-import type { BotWithCustomProps } from "../../../bot.js";
+import type { InteractionCallbackData, InteractionResponse } from 'discordeno';
+import { InteractionResponseTypes } from 'discordeno';
+import type { BotWithCustomProps } from '../../../bot.js';
export function customizeInteractionTransformer(bot: BotWithCustomProps) {
- // Store the internal transformer function
- const oldInteraction = bot.transformers.interaction;
+ // Store the internal transformer function
+ const oldInteraction = bot.transformers.interaction;
- // Overwrite the internal function.
- bot.transformers.interaction = function (_, payload) {
- // Run the old function to get the internal value.
- const interaction = oldInteraction(bot, payload);
+ // Overwrite the internal function.
+ bot.transformers.interaction = function (_, payload) {
+ // Run the old function to get the internal value.
+ const interaction = oldInteraction(bot, payload);
- // Add anything to this object. In this case we add a Interaction.reply() method.
- Object.defineProperty(interaction, "reply", {
- value: function (response: InteractionResponse | string) {
- if (typeof response === "string") {
- response = { type: InteractionResponseTypes.ChannelMessageWithSource, data: { content: response } };
- }
+ // Add anything to this object. In this case we add a Interaction.reply() method.
+ Object.defineProperty(interaction, 'reply', {
+ value: function (response: InteractionResponse | string) {
+ if (typeof response === 'string') {
+ response = { type: InteractionResponseTypes.ChannelMessageWithSource, data: { content: response } };
+ }
- return bot.helpers.sendInteractionResponse(interaction.id, interaction.token, response);
- },
- });
- Object.defineProperty(interaction, "editReply", {
- value: function (response: InteractionCallbackData | string) {
- if (typeof response === "string") {
- response = { content: response };
- }
+ return bot.helpers.sendInteractionResponse(interaction.id, interaction.token, response);
+ },
+ });
+ Object.defineProperty(interaction, 'editReply', {
+ value: function (response: InteractionCallbackData | string) {
+ if (typeof response === 'string') {
+ response = { content: response };
+ }
- return bot.helpers.editOriginalInteractionResponse(interaction.token, response);
- },
- });
- // Add as many properties or methods you would like here.
- // NOTE: Whenever you add anything here, in order to get nice autocomplete you should also add it to the src/types/discordeno.ts file.
+ return bot.helpers.editOriginalInteractionResponse(interaction.token, response);
+ },
+ });
+ // Add as many properties or methods you would like here.
+ // NOTE: Whenever you add anything here, in order to get nice autocomplete you should also add it to the src/types/discordeno.ts file.
- // Return the new customized object.
- return interaction;
- };
+ // Return the new customized object.
+ return interaction;
+ };
}
diff --git a/examples/bigbot/src/bot/utils/internals/transformers/mod.ts b/examples/bigbot/src/bot/utils/internals/transformers/mod.ts
index bcf7160ea..f3c3d4c84 100644
--- a/examples/bigbot/src/bot/utils/internals/transformers/mod.ts
+++ b/examples/bigbot/src/bot/utils/internals/transformers/mod.ts
@@ -1,10 +1,10 @@
-import type { BotWithCustomProps } from "../../../bot.js";
+import type { BotWithCustomProps } from '../../../bot.js';
// SETUP-DD-TEMP: Enable this comment if you want to enable this customizer.
// import { customizeGuildTransformer } from "./guild.js";
-import { customizeInteractionTransformer } from "./interaction.js";
+import { customizeInteractionTransformer } from './interaction.js';
export function customizeTransformers(bot: BotWithCustomProps) {
- customizeInteractionTransformer(bot);
- // SETUP-DD-TEMP: Enable this comment if you want to enable this customizer.
- // customizeGuildTransformer(bot);
+ customizeInteractionTransformer(bot);
+ // SETUP-DD-TEMP: Enable this comment if you want to enable this customizer.
+ // customizeGuildTransformer(bot);
}
diff --git a/examples/bigbot/src/bot/utils/slash/createCommand.ts b/examples/bigbot/src/bot/utils/slash/createCommand.ts
index a48a6f5a1..0d2747a23 100644
--- a/examples/bigbot/src/bot/utils/slash/createCommand.ts
+++ b/examples/bigbot/src/bot/utils/slash/createCommand.ts
@@ -1,21 +1,21 @@
import type {
- ApplicationCommandOptionTypes,
- ApplicationCommandTypes,
- Bot,
- Channel,
- Interaction,
- Member,
- PermissionStrings,
- Role,
- User,
-} from "discordeno";
-import type english from "../../languages/english.js";
-import type { translationKeys } from "../../languages/translate.js";
-import type { InteractionWithCustomProps } from "../../typings/discordeno.js";
-import type { PermissionLevelHandlers } from "./permLevels.js";
+ ApplicationCommandOptionTypes,
+ ApplicationCommandTypes,
+ Bot,
+ Channel,
+ Interaction,
+ Member,
+ PermissionStrings,
+ Role,
+ User,
+} from 'discordeno';
+import type english from '../../languages/english.js';
+import type { translationKeys } from '../../languages/translate.js';
+import type { InteractionWithCustomProps } from '../../typings/discordeno.js';
+import type { PermissionLevelHandlers } from './permLevels.js';
export function createCommand(command: Command) {
- return command;
+ return command;
}
type UnionToIntersection = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
@@ -25,268 +25,283 @@ type Identity = { [P in keyof T]: T[P] };
// TODO: make required by default true
// Define each of the types here
interface BaseDefinition {
- description: translationKeys;
+ description: translationKeys;
}
// Subcommand
type SubcommandArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.SubCommand;
- // options: Omit[]
- options?: readonly ArgumentDefinition[];
+ name: N;
+ type: ApplicationCommandOptionTypes.SubCommand;
+ // options: Omit[]
+ options?: readonly ArgumentDefinition[];
};
// SubcommandGroup
type SubcommandGroupArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.SubCommandGroup;
- options: readonly SubcommandArgumentDefinition[];
+ name: N;
+ type: ApplicationCommandOptionTypes.SubCommandGroup;
+ options: readonly SubcommandArgumentDefinition[];
};
// String
type StringArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.String;
- choices?: ReadonlyArray<{ name: string; value: string }>;
- required?: true;
+ name: N;
+ type: ApplicationCommandOptionTypes.String;
+ choices?: ReadonlyArray<{ name: string; value: string }>;
+ required?: true;
};
type StringOptionalArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.String;
- choices?: ReadonlyArray<{ name: string; value: string }>;
- required?: false;
+ name: N;
+ type: ApplicationCommandOptionTypes.String;
+ choices?: ReadonlyArray<{ name: string; value: string }>;
+ required?: false;
};
// Integer
type IntegerArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.Integer;
- choices?: ReadonlyArray<{ name: string; value: number }>;
- required: true;
+ name: N;
+ type: ApplicationCommandOptionTypes.Integer;
+ choices?: ReadonlyArray<{ name: string; value: number }>;
+ required: true;
};
type IntegerOptionalArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.Integer;
- choices?: ReadonlyArray<{ name: string; value: number }>;
- required?: false;
+ name: N;
+ type: ApplicationCommandOptionTypes.Integer;
+ choices?: ReadonlyArray<{ name: string; value: number }>;
+ required?: false;
};
// BOOLEAN
type BooleanArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.Boolean;
- required: true;
+ name: N;
+ type: ApplicationCommandOptionTypes.Boolean;
+ required: true;
};
type BooleanOptionalArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.Boolean;
- required?: false;
+ name: N;
+ type: ApplicationCommandOptionTypes.Boolean;
+ required?: false;
};
// USER
type UserArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.User;
- required: true;
+ name: N;
+ type: ApplicationCommandOptionTypes.User;
+ required: true;
};
type UserOptionalArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.User;
- required?: false;
+ name: N;
+ type: ApplicationCommandOptionTypes.User;
+ required?: false;
};
// CHANNEL
type ChannelArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.Channel;
- required: true;
+ name: N;
+ type: ApplicationCommandOptionTypes.Channel;
+ required: true;
};
type ChannelOptionalArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.Channel;
- required?: false;
+ name: N;
+ type: ApplicationCommandOptionTypes.Channel;
+ required?: false;
};
// ROLE
type RoleArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.Role;
- required: true;
+ name: N;
+ type: ApplicationCommandOptionTypes.Role;
+ required: true;
};
type RoleOptionalArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.Role;
- required?: false;
+ name: N;
+ type: ApplicationCommandOptionTypes.Role;
+ required?: false;
};
// MENTIONABLE
type MentionableArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.Mentionable;
- required: true;
+ name: N;
+ type: ApplicationCommandOptionTypes.Mentionable;
+ required: true;
};
type MentionableOptionalArgumentDefinition = BaseDefinition & {
- name: N;
- type: ApplicationCommandOptionTypes.Mentionable;
- required?: false;
+ name: N;
+ type: ApplicationCommandOptionTypes.Mentionable;
+ required?: false;
};
// Add each of known ArgumentDefinitions to this union.
export type ArgumentDefinition =
- | StringArgumentDefinition
- | StringOptionalArgumentDefinition
- | IntegerArgumentDefinition
- | IntegerOptionalArgumentDefinition
- | BooleanArgumentDefinition
- | BooleanOptionalArgumentDefinition
- | UserArgumentDefinition
- | UserOptionalArgumentDefinition
- | ChannelArgumentDefinition
- | ChannelOptionalArgumentDefinition
- | RoleArgumentDefinition
- | RoleOptionalArgumentDefinition
- | MentionableArgumentDefinition
- | MentionableOptionalArgumentDefinition
- | SubcommandArgumentDefinition
- | SubcommandGroupArgumentDefinition;
+ | StringArgumentDefinition
+ | StringOptionalArgumentDefinition
+ | IntegerArgumentDefinition
+ | IntegerOptionalArgumentDefinition
+ | BooleanArgumentDefinition
+ | BooleanOptionalArgumentDefinition
+ | UserArgumentDefinition
+ | UserOptionalArgumentDefinition
+ | ChannelArgumentDefinition
+ | ChannelOptionalArgumentDefinition
+ | RoleArgumentDefinition
+ | RoleOptionalArgumentDefinition
+ | MentionableArgumentDefinition
+ | MentionableOptionalArgumentDefinition
+ | SubcommandArgumentDefinition
+ | SubcommandGroupArgumentDefinition;
type getName = typeof english[K] extends string ? typeof english[K] : never;
// OPTIONALS MUST BE FIRST!!!
export type ConvertArgumentDefinitionsToArgs = Identity<
- UnionToIntersection<
- {
- [P in keyof T]: T[P] extends StringOptionalArgumentDefinition // STRING
- ? {
- // @ts-expect-error TODO: fix this some day
- [_ in getName]?: T[P]["choices"] extends ReadonlyArray<{ name: string; value: string }> // @ts-expect-error
- ? T[P]["choices"][number]["value"]
- : string;
- }
- : T[P] extends StringArgumentDefinition ? {
- // @ts-expect-error TODO: fix this some day
- [_ in getName]: T[P]["choices"] extends ReadonlyArray<{ name: string; value: string }> // @ts-expect-error
- ? T[P]["choices"][number]["value"]
- : string;
- }
- // INTEGER
- : T[P] extends IntegerOptionalArgumentDefinition ? {
- [_ in getName]?: T[P]["choices"] extends ReadonlyArray<{ name: string; value: number }> // @ts-expect-error
- ? T[P]["choices"][number]["value"]
- : number;
- }
- : T[P] extends IntegerArgumentDefinition ? {
- [_ in getName]: T[P]["choices"] extends ReadonlyArray<{ name: string; value: number }> // @ts-expect-error
- ? T[P]["choices"][number]["value"]
- : number;
- }
- // BOOLEAN
- : T[P] extends BooleanOptionalArgumentDefinition ? { [_ in getName]?: boolean }
- : T[P] extends BooleanArgumentDefinition ? { [_ in getName]: boolean }
- // USER
- : T[P] extends UserOptionalArgumentDefinition ? {
- [_ in getName]?: {
- user: User;
- member: Member;
- };
- }
- : T[P] extends UserArgumentDefinition ? {
- [_ in getName]: {
- user: User;
- member: Member;
- };
- }
- // CHANNEL
- : T[P] extends ChannelOptionalArgumentDefinition ? { [_ in getName]?: Channel }
- : T[P] extends ChannelArgumentDefinition ? { [_ in getName]: Channel }
- // ROLE
- : T[P] extends RoleOptionalArgumentDefinition ? { [_ in getName]?: Role }
- : T[P] extends RoleArgumentDefinition ? { [_ in getName]: Role }
- // MENTIONABLE
- : T[P] extends MentionableOptionalArgumentDefinition ? {
- [_ in getName]?:
- | Role
- | {
- user: User;
- member: Member;
- };
- }
- : T[P] extends MentionableArgumentDefinition ? {
- [_ in getName]:
- | Role
- | {
- user: User;
- member: Member;
- };
- }
- // SUBCOMMAND
- : T[P] extends SubcommandArgumentDefinition ? {
- [_ in getName]?: T[P]["options"] extends readonly ArgumentDefinition[] // @ts-expect-error somehow this check does not work
- ? ConvertArgumentDefinitionsToArgs
- : {};
- }
- // SUBCOMMANDGROUP
- : T[P] extends SubcommandGroupArgumentDefinition ? {
- [_ in getName]?: ConvertArgumentDefinitionsToArgs;
- }
- : never;
- }[number]
- >
+ UnionToIntersection<
+ {
+ [P in keyof T]: T[P] extends StringOptionalArgumentDefinition // STRING
+ ? {
+ // @ts-expect-error TODO: fix this some day
+ [_ in getName]?: T[P]['choices'] extends ReadonlyArray<{ name: string; value: string }> // @ts-expect-error
+ ? T[P]['choices'][number]['value']
+ : string;
+ }
+ : T[P] extends StringArgumentDefinition
+ ? {
+ // @ts-expect-error TODO: fix this some day
+ [_ in getName]: T[P]['choices'] extends ReadonlyArray<{ name: string; value: string }> // @ts-expect-error
+ ? T[P]['choices'][number]['value']
+ : string;
+ }
+ : // INTEGER
+ T[P] extends IntegerOptionalArgumentDefinition
+ ? {
+ [_ in getName]?: T[P]['choices'] extends ReadonlyArray<{ name: string; value: number }> // @ts-expect-error
+ ? T[P]['choices'][number]['value']
+ : number;
+ }
+ : T[P] extends IntegerArgumentDefinition
+ ? {
+ [_ in getName]: T[P]['choices'] extends ReadonlyArray<{ name: string; value: number }> // @ts-expect-error
+ ? T[P]['choices'][number]['value']
+ : number;
+ }
+ : // BOOLEAN
+ T[P] extends BooleanOptionalArgumentDefinition
+ ? { [_ in getName]?: boolean }
+ : T[P] extends BooleanArgumentDefinition
+ ? { [_ in getName]: boolean }
+ : // USER
+ T[P] extends UserOptionalArgumentDefinition
+ ? {
+ [_ in getName]?: {
+ user: User;
+ member: Member;
+ };
+ }
+ : T[P] extends UserArgumentDefinition
+ ? {
+ [_ in getName]: {
+ user: User;
+ member: Member;
+ };
+ }
+ : // CHANNEL
+ T[P] extends ChannelOptionalArgumentDefinition
+ ? { [_ in getName]?: Channel }
+ : T[P] extends ChannelArgumentDefinition
+ ? { [_ in getName]: Channel }
+ : // ROLE
+ T[P] extends RoleOptionalArgumentDefinition
+ ? { [_ in getName]?: Role }
+ : T[P] extends RoleArgumentDefinition
+ ? { [_ in getName]: Role }
+ : // MENTIONABLE
+ T[P] extends MentionableOptionalArgumentDefinition
+ ? {
+ [_ in getName]?:
+ | Role
+ | {
+ user: User;
+ member: Member;
+ };
+ }
+ : T[P] extends MentionableArgumentDefinition
+ ? {
+ [_ in getName]:
+ | Role
+ | {
+ user: User;
+ member: Member;
+ };
+ }
+ : // SUBCOMMAND
+ T[P] extends SubcommandArgumentDefinition
+ ? {
+ [_ in getName]?: T[P]['options'] extends readonly ArgumentDefinition[] // @ts-expect-error somehow this check does not work
+ ? ConvertArgumentDefinitionsToArgs
+ : {};
+ }
+ : // SUBCOMMANDGROUP
+ T[P] extends SubcommandGroupArgumentDefinition
+ ? {
+ [_ in getName]?: ConvertArgumentDefinitionsToArgs;
+ }
+ : never;
+ }[number]
+ >
>;
export interface Command {
- /** The name of the command, used for both slash and message commands. */
- name: translationKeys;
- /** The type of command. */
- type?: ApplicationCommandTypes;
- /** The description of the command */
- description: translationKeys;
- // TODO: consider type being a string like "number" | "user" for better ux
- /** The options for the command, used for both slash and message commands. */
- // options?: ApplicationCommandOption[];
- options?: T;
- execute: (bot: Bot, data: InteractionWithCustomProps, args: ConvertArgumentDefinitionsToArgs) => unknown;
- subcommands?: Record, "subcommands"> & { group?: string }>;
- /** Whether the command should have a cooldown */
- cooldown?: {
- /** How long the user needs to wait after the first execution until he can use the command again */
- seconds: number;
- /** How often the user is allowed to use the command until he is in cooldown */
- allowedUses?: number;
- };
- nsfw?: boolean;
- /** By default false */
- global?: boolean;
- /** Dm only by default false */
- dmOnly?: boolean;
+ /** The name of the command, used for both slash and message commands. */
+ name: translationKeys;
+ /** The type of command. */
+ type?: ApplicationCommandTypes;
+ /** The description of the command */
+ description: translationKeys;
+ // TODO: consider type being a string like "number" | "user" for better ux
+ /** The options for the command, used for both slash and message commands. */
+ // options?: ApplicationCommandOption[];
+ options?: T;
+ execute: (bot: Bot, data: InteractionWithCustomProps, args: ConvertArgumentDefinitionsToArgs) => unknown;
+ subcommands?: Record, 'subcommands'> & { group?: string }>;
+ /** Whether the command should have a cooldown */
+ cooldown?: {
+ /** How long the user needs to wait after the first execution until he can use the command again */
+ seconds: number;
+ /** How often the user is allowed to use the command until he is in cooldown */
+ allowedUses?: number;
+ };
+ nsfw?: boolean;
+ /** By default false */
+ global?: boolean;
+ /** Dm only by default false */
+ dmOnly?: boolean;
- /** VIP only by default false */
- vipOnly?: boolean;
+ /** VIP only by default false */
+ vipOnly?: boolean;
- advanced?: boolean;
+ advanced?: boolean;
- /** Whether or not this slash command should be enabled right now. Defaults to true. */
- enabled?: boolean;
- /** Whether or not this command is still in development and should be setup in the dev server for testing. */
- dev?: boolean;
- /** Whether or not this command will take longer than 3s and need to acknowledge to discord. */
- acknowledge?: boolean;
+ /** Whether or not this slash command should be enabled right now. Defaults to true. */
+ enabled?: boolean;
+ /** Whether or not this command is still in development and should be setup in the dev server for testing. */
+ dev?: boolean;
+ /** Whether or not this command will take longer than 3s and need to acknowledge to discord. */
+ acknowledge?: boolean;
- permissionLevels?:
- | Array
- | ((data: Interaction, command: Command) => boolean | Promise);
- botServerPermissions?: PermissionStrings[];
- botChannelPermissions?: PermissionStrings[];
- userServerPermissions?: PermissionStrings[];
- userChannelPermissions?: PermissionStrings[];
+ permissionLevels?:
+ | Array
+ | ((data: Interaction, command: Command) => boolean | Promise);
+ botServerPermissions?: PermissionStrings[];
+ botChannelPermissions?: PermissionStrings[];
+ userServerPermissions?: PermissionStrings[];
+ userChannelPermissions?: PermissionStrings[];
}
export enum PermissionLevels {
- Member,
- Moderator,
- Admin,
- ServerOwner,
- BotSupporter,
- BotDev,
- BotOwner,
+ Member,
+ Moderator,
+ Admin,
+ ServerOwner,
+ BotSupporter,
+ BotDev,
+ BotOwner,
}
diff --git a/examples/bigbot/src/bot/utils/slash/limiter.ts b/examples/bigbot/src/bot/utils/slash/limiter.ts
index 07533466c..d6cb48ccc 100644
--- a/examples/bigbot/src/bot/utils/slash/limiter.ts
+++ b/examples/bigbot/src/bot/utils/slash/limiter.ts
@@ -1,29 +1,31 @@
-import COMMANDS from "../../commands/mod.js";
+import COMMANDS from '../../commands/mod.js';
export async function validateSlashLimits() {
- const MAX_ALLOWED_CHARACTERS = 4000;
+ const MAX_ALLOWED_CHARACTERS = 4000;
- const commands = await fetch("https://cmd-counter-play.deno.dev/", {
- body: JSON.stringify(COMMANDS),
- headers: {
- "content-type": "application/json",
- },
- }).then(async (res) => await res.json()).catch(() => undefined);
+ const commands = await fetch('https://cmd-counter-play.deno.dev/', {
+ body: JSON.stringify(COMMANDS),
+ headers: {
+ 'content-type': 'application/json',
+ },
+ })
+ .then(async (res) => await res.json())
+ .catch(() => undefined);
- if (!commands) return;
+ if (!commands) return;
- const invalidCommandNames: string[] = [];
+ const invalidCommandNames: string[] = [];
- if (commands[0]?.characters > MAX_ALLOWED_CHARACTERS) {
- for (const command of commands) {
- if (command.characters <= MAX_ALLOWED_CHARACTERS) continue;
+ if (commands[0]?.characters > MAX_ALLOWED_CHARACTERS) {
+ for (const command of commands) {
+ if (command.characters <= MAX_ALLOWED_CHARACTERS) continue;
- invalidCommandNames.push(command.name);
- console.log(
- `[Invalid Command] The ${command.name} is not a valid command. It's total characters are (${command.characters}) which is more than the max allowed ${MAX_ALLOWED_CHARACTERS}.`,
- );
- }
- }
+ invalidCommandNames.push(command.name);
+ console.log(
+ `[Invalid Command] The ${command.name} is not a valid command. It's total characters are (${command.characters}) which is more than the max allowed ${MAX_ALLOWED_CHARACTERS}.`,
+ );
+ }
+ }
- if (invalidCommandNames.length) throw new Error(`[Startup] Invalid commands: ${invalidCommandNames.join(", ")}`);
+ if (invalidCommandNames.length) throw new Error(`[Startup] Invalid commands: ${invalidCommandNames.join(', ')}`);
}
diff --git a/examples/bigbot/src/bot/utils/slash/permLevels.ts b/examples/bigbot/src/bot/utils/slash/permLevels.ts
index 1dd939ee4..38cc3a70f 100644
--- a/examples/bigbot/src/bot/utils/slash/permLevels.ts
+++ b/examples/bigbot/src/bot/utils/slash/permLevels.ts
@@ -1,48 +1,48 @@
-import type { Interaction } from "discordeno";
-import { validatePermissions } from "discordeno/permissions-plugin";
-import type { Command } from "./createCommand.js";
+import type { Interaction } from 'discordeno';
+import { validatePermissions } from 'discordeno/permissions-plugin';
+import type { Command } from './createCommand.js';
export default async function hasPermissionLevel(command: Command, payload: Interaction) {
- // This command doesnt require a perm level so allow the command.
- if (!command.permissionLevels) return true;
+ // This command doesnt require a perm level so allow the command.
+ if (!command.permissionLevels) return true;
- // If a custom function was provided
- if (typeof command.permissionLevels === "function") {
- return await command.permissionLevels(payload, command);
- }
+ // If a custom function was provided
+ if (typeof command.permissionLevels === 'function') {
+ return await command.permissionLevels(payload, command);
+ }
- // If an array of perm levels was provided
- for (const permlevel of command.permissionLevels) {
- // If this user has one of the allowed perm level, the loop is canceled and command is allowed.
- if (await PermissionLevelHandlers[permlevel](payload, command)) return true;
- }
+ // If an array of perm levels was provided
+ for (const permlevel of command.permissionLevels) {
+ // If this user has one of the allowed perm level, the loop is canceled and command is allowed.
+ if (await PermissionLevelHandlers[permlevel](payload, command)) return true;
+ }
- // None of the perm levels were met. So cancel the command
- return false;
+ // None of the perm levels were met. So cancel the command
+ return false;
}
export const PermissionLevelHandlers: Record<
- keyof typeof PermissionLevels,
- (payload: Interaction, command: Command) => boolean | Promise
+ keyof typeof PermissionLevels,
+ (payload: Interaction, command: Command) => boolean | Promise
> = {
- MEMBER: () => true,
- MODERATOR: (payload) =>
- Boolean(payload.member?.permissions) && validatePermissions(payload.member!.permissions!, ["MANAGE_GUILD"]),
- ADMIN: (payload) =>
- Boolean(payload.member?.permissions) && validatePermissions(payload.member!.permissions!, ["ADMINISTRATOR"]),
- // TODO(cache): fix this
- SERVER_OWNER: () => false,
- BOT_SUPPORT: () => false,
- BOT_DEVS: () => false,
- BOT_OWNERS: (payload) => [130136895395987456n, 615542460151496705n].includes(payload.user.id),
+ MEMBER: () => true,
+ MODERATOR: (payload) =>
+ Boolean(payload.member?.permissions) && validatePermissions(payload.member!.permissions!, ['MANAGE_GUILD']),
+ ADMIN: (payload) =>
+ Boolean(payload.member?.permissions) && validatePermissions(payload.member!.permissions!, ['ADMINISTRATOR']),
+ // TODO(cache): fix this
+ SERVER_OWNER: () => false,
+ BOT_SUPPORT: () => false,
+ BOT_DEVS: () => false,
+ BOT_OWNERS: (payload) => [130136895395987456n, 615542460151496705n].includes(payload.user.id),
};
export enum PermissionLevels {
- MEMBER,
- MODERATOR,
- ADMIN,
- SERVER_OWNER,
- BOT_SUPPORT,
- BOT_DEVS,
- BOT_OWNERS,
+ MEMBER,
+ MODERATOR,
+ ADMIN,
+ SERVER_OWNER,
+ BOT_SUPPORT,
+ BOT_DEVS,
+ BOT_OWNERS,
}
diff --git a/examples/bigbot/src/bot/utils/slash/updateCommands.ts b/examples/bigbot/src/bot/utils/slash/updateCommands.ts
index a4f82a9bd..43bc9d69a 100644
--- a/examples/bigbot/src/bot/utils/slash/updateCommands.ts
+++ b/examples/bigbot/src/bot/utils/slash/updateCommands.ts
@@ -1,43 +1,43 @@
-import type { ApplicationCommandOption, Bot } from "discordeno";
-import { ApplicationCommandTypes } from "discordeno";
-import { prisma } from "../../../prisma.js";
-import { bot } from "../../bot.js";
-import COMMANDS from "../../commands/mod.js";
-import { serverLanguages, translate } from "../../languages/translate.js";
-import type { ArgumentDefinition } from "./createCommand.js";
+import type { ApplicationCommandOption, Bot } from 'discordeno';
+import { ApplicationCommandTypes } from 'discordeno';
+import { prisma } from '../../../prisma.js';
+import { bot } from '../../bot.js';
+import COMMANDS from '../../commands/mod.js';
+import { serverLanguages, translate } from '../../languages/translate.js';
+import type { ArgumentDefinition } from './createCommand.js';
const DEV_SERVER_ID = process.env.DEV_SERVER_ID as string;
export async function updateDevCommands(bot: Bot) {
- const cmds = Object.entries(COMMANDS)
- // ONLY DEV COMMANDS
- .filter(([_name, command]) => command?.dev);
+ const cmds = Object.entries(COMMANDS)
+ // ONLY DEV COMMANDS
+ .filter(([_name, command]) => command?.dev);
- if (!cmds.length) return;
+ if (!cmds.length) return;
- // DEV RELATED COMMANDS, USE upsertGlobalApplicationCommands TO UPDATE GLOBALLY
- await bot.helpers.upsertGuildApplicationCommands(
- bot.transformers.snowflake(DEV_SERVER_ID),
- cmds.map(([name, command]) => {
- const translatedName = translate(DEV_SERVER_ID, command.name);
- const translatedDescription = command.description ? translate(DEV_SERVER_ID, command.description) : "";
+ // DEV RELATED COMMANDS, USE upsertGlobalApplicationCommands TO UPDATE GLOBALLY
+ await bot.helpers.upsertGuildApplicationCommands(
+ bot.transformers.snowflake(DEV_SERVER_ID),
+ cmds.map(([name, command]) => {
+ const translatedName = translate(DEV_SERVER_ID, command.name);
+ const translatedDescription = command.description ? translate(DEV_SERVER_ID, command.description) : '';
- if (command.type && command.type !== ApplicationCommandTypes.ChatInput) {
- return {
- name: (translatedName || name).toLowerCase(),
- type: command.type,
- };
- }
+ if (command.type && command.type !== ApplicationCommandTypes.ChatInput) {
+ return {
+ name: (translatedName || name).toLowerCase(),
+ type: command.type,
+ };
+ }
- return {
- name: (translatedName || name).toLowerCase(),
- description: translatedDescription || command.description,
- options: command.options
- ? createOptions(bot.transformers.snowflake(DEV_SERVER_ID), command.options, command.name)
- : undefined,
- };
- }),
- );
+ return {
+ name: (translatedName || name).toLowerCase(),
+ description: translatedDescription || command.description,
+ options: command.options
+ ? createOptions(bot.transformers.snowflake(DEV_SERVER_ID), command.options, command.name)
+ : undefined,
+ };
+ }),
+ );
}
// SETUP-DD-TEMP: You can make this able to be updated dynicamally by moving this value to something in the database and having a command to update it on the fly or as part of CI.
@@ -45,63 +45,63 @@ export const CURRENT_SLASH_COMMAND_VERSION = 1;
/** Whether the guild has the latest slash command version */
export async function usesLatestCommandVersion(guildId: bigint): Promise {
- return (await getCurrentCommandVersion(guildId)) === CURRENT_SLASH_COMMAND_VERSION;
+ return (await getCurrentCommandVersion(guildId)) === CURRENT_SLASH_COMMAND_VERSION;
}
/** Get the current slash command version for this guild */
export async function getCurrentCommandVersion(guildId: bigint): Promise {
- if (bot.commandVersions.has(guildId)) return bot.commandVersions.get(guildId)!;
+ if (bot.commandVersions.has(guildId)) return bot.commandVersions.get(guildId)!;
- const commandVersion = await prisma.commands.findUnique({ where: { id: guildId } });
- if (commandVersion) bot.commandVersions.set(guildId, commandVersion.version);
+ const commandVersion = await prisma.commands.findUnique({ where: { id: guildId } });
+ if (commandVersion) bot.commandVersions.set(guildId, commandVersion.version);
- return commandVersion?.version ?? 0;
+ return commandVersion?.version ?? 0;
}
export async function updateCommandVersion(guildId: bigint): Promise {
- // UPDATE THE VERSION SAVED IN THE DB
- await prisma.commands.upsert({
- where: { id: guildId },
- create: { id: guildId, version: CURRENT_SLASH_COMMAND_VERSION },
- update: { version: CURRENT_SLASH_COMMAND_VERSION },
- });
+ // UPDATE THE VERSION SAVED IN THE DB
+ await prisma.commands.upsert({
+ where: { id: guildId },
+ create: { id: guildId, version: CURRENT_SLASH_COMMAND_VERSION },
+ update: { version: CURRENT_SLASH_COMMAND_VERSION },
+ });
- bot.commandVersions.set(guildId, CURRENT_SLASH_COMMAND_VERSION);
- return CURRENT_SLASH_COMMAND_VERSION;
+ bot.commandVersions.set(guildId, CURRENT_SLASH_COMMAND_VERSION);
+ return CURRENT_SLASH_COMMAND_VERSION;
}
export async function updateGuildCommands(bot: Bot, guildId: bigint) {
- if (guildId === 547046977578336286n) return await updateDevCommands(bot);
+ if (guildId === 547046977578336286n) return await updateDevCommands(bot);
- await updateCommandVersion(guildId);
+ await updateCommandVersion(guildId);
- // GUILD RELATED COMMANDS
- await bot.helpers.upsertGuildApplicationCommands(
- guildId,
- Object.entries(COMMANDS)
- // ONLY GUILD COMMANDS
- .filter(([_name, command]) => !command.global && !command.dev)
- .map(([name, command]) => {
- // USER OPTED TO USE BASIC VERSION ONLY
- if (command.advanced === false) {
- return {
- name,
- description: translate("english", command.description),
- options: command.options ? createOptions("english", command.options, command.name) : undefined,
- };
- }
+ // GUILD RELATED COMMANDS
+ await bot.helpers.upsertGuildApplicationCommands(
+ guildId,
+ Object.entries(COMMANDS)
+ // ONLY GUILD COMMANDS
+ .filter(([_name, command]) => !command.global && !command.dev)
+ .map(([name, command]) => {
+ // USER OPTED TO USE BASIC VERSION ONLY
+ if (command.advanced === false) {
+ return {
+ name,
+ description: translate('english', command.description),
+ options: command.options ? createOptions('english', command.options, command.name) : undefined,
+ };
+ }
- // ADVANCED VERSION WILL ALLOW TRANSLATION
- const translatedName = translate(guildId, command.name);
- const translatedDescription = translate(guildId, command.description);
+ // ADVANCED VERSION WILL ALLOW TRANSLATION
+ const translatedName = translate(guildId, command.name);
+ const translatedDescription = translate(guildId, command.description);
- return {
- name: translatedName.toLowerCase(),
- description: translatedDescription,
- options: command.options ? createOptions(guildId, command.options, command.name) : undefined,
- };
- }),
- );
+ return {
+ name: translatedName.toLowerCase(),
+ description: translatedDescription,
+ options: command.options ? createOptions(guildId, command.options, command.name) : undefined,
+ };
+ }),
+ );
}
// USED TO CACHE CONVERTED COMMANDS AFTER START TO PREVENT UNNECESSARY LOOPS
@@ -109,41 +109,41 @@ const convertedCache = new Map();
/** Creates the commands options including subcommands. Also translates them. */
function createOptions(
- guildId: bigint | "english",
- options: readonly ArgumentDefinition[],
- commandName?: string,
+ guildId: bigint | 'english',
+ options: readonly ArgumentDefinition[],
+ commandName?: string,
): ApplicationCommandOption[] | undefined {
- const language = guildId === "english" ? "english" : serverLanguages.get(guildId) ?? "english";
- if (commandName && convertedCache.has(`${language}-${commandName}`)) {
- return convertedCache.get(`${language}-${commandName}`)!;
- }
+ const language = guildId === 'english' ? 'english' : serverLanguages.get(guildId) ?? 'english';
+ if (commandName && convertedCache.has(`${language}-${commandName}`)) {
+ return convertedCache.get(`${language}-${commandName}`)!;
+ }
- const newOptions: ApplicationCommandOption[] = [];
+ const newOptions: ApplicationCommandOption[] = [];
- for (const option of options || []) {
- const optionName = translate(guildId, option.name);
- const optionDescription = translate(guildId, option.description);
+ for (const option of options || []) {
+ const optionName = translate(guildId, option.name);
+ const optionDescription = translate(guildId, option.description);
- // TODO: remove this ts ignore
- // @ts-expect-error
- const choices = option.choices?.map((choice) => ({
- ...choice,
- name: translate(guildId, choice.name),
- }));
+ // TODO: remove this ts ignore
+ // @ts-expect-error
+ const choices = option.choices?.map((choice) => ({
+ ...choice,
+ name: translate(guildId, choice.name),
+ }));
- newOptions.push({
- ...option,
- name: optionName.toLowerCase(),
- description: optionDescription || "No description available.",
- choices,
- // @ts-expect-error fix this
- options: option.options
- // @ts-expect-error fix this
- ? createOptions(bot, guildId, option.options)
- : undefined,
- } as ApplicationCommandOption);
- }
- if (commandName) convertedCache.set(`${language}-${commandName}`, newOptions);
+ newOptions.push({
+ ...option,
+ name: optionName.toLowerCase(),
+ description: optionDescription || 'No description available.',
+ choices,
+ // @ts-expect-error fix this
+ options: option.options
+ ? // @ts-expect-error fix this
+ createOptions(bot, guildId, option.options)
+ : undefined,
+ } as ApplicationCommandOption);
+ }
+ if (commandName) convertedCache.set(`${language}-${commandName}`, newOptions);
- return newOptions;
+ return newOptions;
}
diff --git a/examples/bigbot/src/bot/utils/webhook.ts b/examples/bigbot/src/bot/utils/webhook.ts
index 079fee05e..b4897f0a6 100644
--- a/examples/bigbot/src/bot/utils/webhook.ts
+++ b/examples/bigbot/src/bot/utils/webhook.ts
@@ -1,11 +1,9 @@
/** Get the webhook id and token from a webhook url. */
export function webhookURLToIDAndToken(url: string) {
- const [id, token] = url.substring(url.indexOf("webhooks/") + 9).split(
- "/",
- );
+ const [id, token] = url.substring(url.indexOf('webhooks/') + 9).split('/');
- return {
- id,
- token,
- };
+ return {
+ id,
+ token,
+ };
}
diff --git a/examples/bigbot/src/configs.ts b/examples/bigbot/src/configs.ts
index f9bc3a955..dc185ea76 100644
--- a/examples/bigbot/src/configs.ts
+++ b/examples/bigbot/src/configs.ts
@@ -1,5 +1,5 @@
-import { getBotIdFromToken, Intents } from "discordeno";
-import dotenv from "dotenv";
+import { getBotIdFromToken, Intents } from 'discordeno';
+import dotenv from 'dotenv';
dotenv.config();
/** The bot id, derived from the bot token. */
@@ -11,19 +11,19 @@ export const GATEWAY_URL = `http://${process.env.GATEWAY_HOST}:${process.env.GAT
// Gateway Proxy Configurations
/** The gateway intents you would like to use. */
export const INTENTS: Intents =
- // SETUP-DD-TEMP: Add the intents you want enabled here. Or Delete the intents you don't want in your bot.
- Intents.DirectMessageReactions |
- Intents.DirectMessageTyping |
- Intents.DirectMessages |
- Intents.GuildBans |
- Intents.GuildEmojis |
- Intents.GuildIntegrations |
- Intents.GuildInvites |
- Intents.GuildMembers |
- Intents.GuildMessageReactions |
- Intents.GuildMessageTyping |
- Intents.GuildMessages |
- Intents.GuildPresences |
- Intents.GuildVoiceStates |
- Intents.GuildWebhooks |
- Intents.Guilds;
+ // SETUP-DD-TEMP: Add the intents you want enabled here. Or Delete the intents you don't want in your bot.
+ Intents.DirectMessageReactions |
+ Intents.DirectMessageTyping |
+ Intents.DirectMessages |
+ Intents.GuildBans |
+ Intents.GuildEmojis |
+ Intents.GuildIntegrations |
+ Intents.GuildInvites |
+ Intents.GuildMembers |
+ Intents.GuildMessageReactions |
+ Intents.GuildMessageTyping |
+ Intents.GuildMessages |
+ Intents.GuildPresences |
+ Intents.GuildVoiceStates |
+ Intents.GuildWebhooks |
+ Intents.Guilds;
diff --git a/examples/bigbot/src/gateway/index.ts b/examples/bigbot/src/gateway/index.ts
index f10247c28..3ca1eece8 100644
--- a/examples/bigbot/src/gateway/index.ts
+++ b/examples/bigbot/src/gateway/index.ts
@@ -1,12 +1,18 @@
-import dotenv from "dotenv";
+import dotenv from 'dotenv';
-import { Collection, createBot, createGatewayManager, createRestManager } from "discordeno";
-import { createLogger } from "discordeno/logger";
-import fastify from "fastify";
-import { nanoid } from "nanoid";
-import { Worker } from "worker_threads";
-import { EVENT_HANDLER_URL, INTENTS, REST_URL } from "../configs.js";
-import type { WorkerCreateData, WorkerGetShardInfo, WorkerMessage, WorkerShardInfo, WorkerShardPayload } from "./worker.js";
+import { Collection, createBot, createGatewayManager, createRestManager } from 'discordeno';
+import { createLogger } from 'discordeno/logger';
+import fastify from 'fastify';
+import { nanoid } from 'nanoid';
+import { Worker } from 'worker_threads';
+import { EVENT_HANDLER_URL, INTENTS, REST_URL } from '../configs.js';
+import type {
+ WorkerCreateData,
+ WorkerGetShardInfo,
+ WorkerMessage,
+ WorkerShardInfo,
+ WorkerShardPayload,
+} from './worker.js';
dotenv.config();
const DISCORD_TOKEN = process.env.DISCORD_TOKEN as string;
@@ -18,181 +24,181 @@ const SHARDS_PER_WORKER = Number(process.env.SHARDS_PER_WORKER as string);
const TOTAL_SHARDS = process.env.TOTAL_SHARDS ? Number(process.env.TOTAL_SHARDS) : undefined;
const TOTAL_WORKERS = Number(process.env.TOTAL_WORKERS as string);
-const log = createLogger({ name: "[MANAGER]" });
+const log = createLogger({ name: '[MANAGER]' });
const bot = createBot({
- token: DISCORD_TOKEN,
+ token: DISCORD_TOKEN,
});
bot.rest = createRestManager({
- token: DISCORD_TOKEN,
- secretKey: REST_AUTHORIZATION,
- customUrl: REST_URL,
+ token: DISCORD_TOKEN,
+ secretKey: REST_AUTHORIZATION,
+ customUrl: REST_URL,
});
const gatewayBot = await bot.helpers.getGatewayBot();
const gateway = createGatewayManager({
- gatewayBot,
- gatewayConfig: {
- token: DISCORD_TOKEN,
- intents: INTENTS,
- },
- // force the total amount of shards
- totalShards: TOTAL_SHARDS,
- shardsPerWorker: SHARDS_PER_WORKER,
- totalWorkers: TOTAL_WORKERS,
+ gatewayBot,
+ gatewayConfig: {
+ token: DISCORD_TOKEN,
+ intents: INTENTS,
+ },
+ // force the total amount of shards
+ totalShards: TOTAL_SHARDS,
+ shardsPerWorker: SHARDS_PER_WORKER,
+ totalWorkers: TOTAL_WORKERS,
- handleDiscordPayload: () => {},
+ handleDiscordPayload: () => {},
- tellWorkerToIdentify: async (_gateway, workerId, shardId, _bucketId) => {
- log.info("TELL TO IDENTIFY", { workerId, shardId, _bucketId });
+ tellWorkerToIdentify: async (_gateway, workerId, shardId, _bucketId) => {
+ log.info('TELL TO IDENTIFY', { workerId, shardId, _bucketId });
- let worker = workers.get(workerId);
- if (!worker) {
- worker = createWorker(workerId);
- workers.set(workerId, worker);
- }
+ let worker = workers.get(workerId);
+ if (!worker) {
+ worker = createWorker(workerId);
+ workers.set(workerId, worker);
+ }
- const identify: WorkerMessage = {
- type: "IDENTIFY_SHARD",
- shardId,
- };
+ const identify: WorkerMessage = {
+ type: 'IDENTIFY_SHARD',
+ shardId,
+ };
- worker.postMessage(identify);
- },
+ worker.postMessage(identify);
+ },
});
const workers = new Collection();
const nonces = new Collection void>();
function createWorker(workerId: number) {
- console.log(TOTAL_SHARDS, gateway.manager.totalShards, "SHARDS");
+ console.log(TOTAL_SHARDS, gateway.manager.totalShards, 'SHARDS');
- const workerData: WorkerCreateData = {
- intents: gateway.manager.gatewayConfig.intents ?? 0,
- token: DISCORD_TOKEN,
- handlerUrls: [EVENT_HANDLER_URL],
- handlerAuthorization: EVENT_HANDLER_AUTHORIZATION,
- path: "./worker.ts",
- totalShards: gateway.manager.totalShards,
- workerId,
- };
+ const workerData: WorkerCreateData = {
+ intents: gateway.manager.gatewayConfig.intents ?? 0,
+ token: DISCORD_TOKEN,
+ handlerUrls: [EVENT_HANDLER_URL],
+ handlerAuthorization: EVENT_HANDLER_AUTHORIZATION,
+ path: './worker.ts',
+ totalShards: gateway.manager.totalShards,
+ workerId,
+ };
- const worker = new Worker("./dist/gateway/worker.js", {
- workerData,
- });
+ const worker = new Worker('./dist/gateway/worker.js', {
+ workerData,
+ });
- worker.on("message", async (data: ManagerMessage) => {
- log.info({ data });
- switch (data.type) {
- case "REQUEST_IDENTIFY": {
- log.info("REQUESTING IDENTIFY #", data.shardId);
- await gateway.manager.requestIdentify(data.shardId);
+ worker.on('message', async (data: ManagerMessage) => {
+ log.info({ data });
+ switch (data.type) {
+ case 'REQUEST_IDENTIFY': {
+ log.info('REQUESTING IDENTIFY #', data.shardId);
+ await gateway.manager.requestIdentify(data.shardId);
- const allowIdentify: WorkerMessage = {
- type: "ALLOW_IDENTIFY",
- shardId: data.shardId,
- };
+ const allowIdentify: WorkerMessage = {
+ type: 'ALLOW_IDENTIFY',
+ shardId: data.shardId,
+ };
- worker.postMessage(allowIdentify);
+ worker.postMessage(allowIdentify);
- break;
- }
- case "NONCE_REPLY": {
- nonces.get(data.nonce)?.(data.data);
- }
- }
- });
+ break;
+ }
+ case 'NONCE_REPLY': {
+ nonces.get(data.nonce)?.(data.data);
+ }
+ }
+ });
- return worker;
+ return worker;
}
gateway.spawnShards();
const server = fastify();
-server.post("/", async (request, reply) => {
- if (request.headers.authorization !== GATEWAY_AUTHORIZATION) {
- reply.code(StatusCodes.Unauthorized);
+server.post('/', async (request, reply) => {
+ if (request.headers.authorization !== GATEWAY_AUTHORIZATION) {
+ reply.code(StatusCodes.Unauthorized);
- return reply.send({ processing: false, error: false, message: "Invalid authorization header." });
- }
+ return reply.send({ processing: false, error: false, message: 'Invalid authorization header.' });
+ }
- if (!request.body) {
- reply.code(StatusCodes.BadRequest);
+ if (!request.body) {
+ reply.code(StatusCodes.BadRequest);
- return reply.send({ processing: false, error: false, message: "Empty body." });
- }
+ return reply.send({ processing: false, error: false, message: 'Empty body.' });
+ }
- try {
- const data = request.body as WorkerShardPayload | Omit;
- switch (data.type) {
- case "SHARD_PAYLOAD": {
- const workerId = gateway.calculateWorkerId(data.shardId);
- const worker = workers.get(workerId);
+ try {
+ const data = request.body as WorkerShardPayload | Omit;
+ switch (data.type) {
+ case 'SHARD_PAYLOAD': {
+ const workerId = gateway.calculateWorkerId(data.shardId);
+ const worker = workers.get(workerId);
- worker?.postMessage(data);
+ worker?.postMessage(data);
- break;
- }
- case "GET_SHARD_INFO": {
- const infos = await Promise.all(
- workers.map(async (worker) => {
- const nonce = nanoid();
+ break;
+ }
+ case 'GET_SHARD_INFO': {
+ const infos = await Promise.all(
+ workers.map(async (worker) => {
+ const nonce = nanoid();
- return await new Promise((resolve) => {
- worker.postMessage({ type: "GET_SHARD_INFO", nonce });
+ return await new Promise((resolve) => {
+ worker.postMessage({ type: 'GET_SHARD_INFO', nonce });
- nonces.set(nonce, resolve);
- });
- }),
- ).then((res) =>
- res.reduce((acc, cur) => {
- acc.push(...cur);
- return acc;
- }, [] as WorkerShardInfo[])
- );
+ nonces.set(nonce, resolve);
+ });
+ }),
+ ).then((res) =>
+ res.reduce((acc, cur) => {
+ acc.push(...cur);
+ return acc;
+ }, [] as WorkerShardInfo[]),
+ );
- reply.code(StatusCodes.Ok);
+ reply.code(StatusCodes.Ok);
- return reply.send(infos);
- }
- }
+ return reply.send(infos);
+ }
+ }
- reply.code(StatusCodes.Ok);
+ reply.code(StatusCodes.Ok);
- return reply.send({ processing: true });
- } catch {
- reply.code(StatusCodes.BadRequest);
+ return reply.send({ processing: true });
+ } catch {
+ reply.code(StatusCodes.BadRequest);
- return reply.send({ processing: false, error: true, message: "Failed to parse body." });
- }
+ return reply.send({ processing: false, error: true, message: 'Failed to parse body.' });
+ }
});
server.listen({ port: GATEWAY_PORT }).catch((error) => {
- log.error(["[FASTIFY ERROR", error].join("\n"));
- process.exit(1);
+ log.error(['[FASTIFY ERROR', error].join('\n'));
+ process.exit(1);
});
export type ManagerMessage = ManagerRequestIdentify | ManagerNonceReply;
export interface ManagerRequestIdentify {
- type: "REQUEST_IDENTIFY";
- shardId: number;
+ type: 'REQUEST_IDENTIFY';
+ shardId: number;
}
export interface ManagerNonceReply {
- type: "NONCE_REPLY";
- nonce: string;
- data: T;
+ type: 'NONCE_REPLY';
+ nonce: string;
+ data: T;
}
enum StatusCodes {
- Ok = 200,
+ Ok = 200,
- BadRequest = 400,
- Unauthorized = 401,
+ BadRequest = 400,
+ Unauthorized = 401,
- InternalServerError = 500,
+ InternalServerError = 500,
}
diff --git a/examples/bigbot/src/gateway/worker.ts b/examples/bigbot/src/gateway/worker.ts
index 904b45d79..7987af85a 100644
--- a/examples/bigbot/src/gateway/worker.ts
+++ b/examples/bigbot/src/gateway/worker.ts
@@ -1,26 +1,24 @@
-import dotenv from "dotenv";
+import dotenv from 'dotenv';
-import amqplib from "amqplib";
+import amqplib from 'amqplib';
import type {
- DiscordGuild,
- DiscordReady,
- DiscordUnavailableGuild,
- Shard,
- ShardSocketRequest,
- ShardState} from "discordeno";
-import {
- createShardManager,
- GatewayEventNames
-} from "discordeno";
-import { createLogger } from "discordeno/logger";
-import fetch from "node-fetch";
-import crypto from "node:crypto";
-import { parentPort, workerData } from "worker_threads";
+ DiscordGuild,
+ DiscordReady,
+ DiscordUnavailableGuild,
+ Shard,
+ ShardSocketRequest,
+ ShardState,
+} from 'discordeno';
+import { createShardManager, GatewayEventNames } from 'discordeno';
+import { createLogger } from 'discordeno/logger';
+import fetch from 'node-fetch';
+import crypto from 'node:crypto';
+import { parentPort, workerData } from 'worker_threads';
import type { ManagerMessage } from './index.js';
dotenv.config();
if (!parentPort) {
- throw new Error("Parent port is null");
+ throw new Error('Parent port is null');
}
const script: WorkerCreateData = workerData;
@@ -31,211 +29,202 @@ const identifyPromises = new Map void>();
let channel: amqplib.Channel | undefined;
-const useMessageQueue = process.env.MESSAGEQUEUE_ENABLE === "true";
+const useMessageQueue = process.env.MESSAGEQUEUE_ENABLE === 'true';
// Store guild ids, loading guild ids to change GUILD_CREATE event to GUILD_LOADED_DD if needed.
const guildIds: Set = new Set();
const loadingGuildIds: Set = new Set();
const manager = createShardManager({
- gatewayConfig: {
- intents: script.intents,
- token: script.token,
- },
- shardIds: [],
- totalShards: script.totalShards,
- handleMessage: async (shard, message) => {
- const url = script.handlerUrls[shard.id % script.handlerUrls.length];
- if (!url) return console.log("ERROR: NO URL FOUND TO SEND MESSAGE");
+ gatewayConfig: {
+ intents: script.intents,
+ token: script.token,
+ },
+ shardIds: [],
+ totalShards: script.totalShards,
+ handleMessage: async (shard, message) => {
+ const url = script.handlerUrls[shard.id % script.handlerUrls.length];
+ if (!url) return console.log('ERROR: NO URL FOUND TO SEND MESSAGE');
- if (message.t === "READY") {
- // Marks which guilds the bot in when initial loading in cache.
- (message.d as DiscordReady).guilds.forEach((g) => loadingGuildIds.add(BigInt(g.id)));
- }
+ if (message.t === 'READY') {
+ // Marks which guilds the bot in when initial loading in cache.
+ (message.d as DiscordReady).guilds.forEach((g) => loadingGuildIds.add(BigInt(g.id)));
+ }
- // If GUILD_CREATE event came from a shard loaded event, change event to GUILD_LOADED_DD.
- if (message.t === "GUILD_CREATE") {
- const guild = message.d as DiscordGuild;
- const id = BigInt(guild.id);
+ // If GUILD_CREATE event came from a shard loaded event, change event to GUILD_LOADED_DD.
+ if (message.t === 'GUILD_CREATE') {
+ const guild = message.d as DiscordGuild;
+ const id = BigInt(guild.id);
- const existing = guildIds.has(id);
- if (existing) return;
+ const existing = guildIds.has(id);
+ if (existing) return;
- if (loadingGuildIds.has(id)) {
- (message.t ) = "GUILD_LOADED_DD";
+ if (loadingGuildIds.has(id)) {
+ message.t = 'GUILD_LOADED_DD';
- loadingGuildIds.delete(id);
- }
+ loadingGuildIds.delete(id);
+ }
- guildIds.add(id);
- }
+ guildIds.add(id);
+ }
- // Delete guild id from cache so GUILD_CREATE from the same guild later works properly.
- if (message.t === "GUILD_DELETE") {
- const guild = message.d as DiscordUnavailableGuild;
+ // Delete guild id from cache so GUILD_CREATE from the same guild later works properly.
+ if (message.t === 'GUILD_DELETE') {
+ const guild = message.d as DiscordUnavailableGuild;
- if (guild.unavailable) return;
+ if (guild.unavailable) return;
- guildIds.delete(BigInt(guild.id));
- }
+ guildIds.delete(BigInt(guild.id));
+ }
- if (useMessageQueue) {
- if (!channel) return;
- await channel.publish(
- "gatewayMessage",
- "",
- Buffer.from(JSON.stringify({ shard, message })),
- {
- contentType: "application/json",
- headers: {
- "x-deduplication-header": crypto.createHash("md5").update(JSON.stringify(message.d)).digest("hex"),
- },
- },
- );
- } else {
- await fetch(url, {
- method: "POST",
- body: JSON.stringify({ message, shardId: shard.id }),
- headers: { "Content-Type": "application/json", Authorization: script.handlerAuthorization },
- }).catch((error) => log.error(error));
- }
+ if (useMessageQueue) {
+ if (!channel) return;
+ await channel.publish('gatewayMessage', '', Buffer.from(JSON.stringify({ shard, message })), {
+ contentType: 'application/json',
+ headers: {
+ 'x-deduplication-header': crypto.createHash('md5').update(JSON.stringify(message.d)).digest('hex'),
+ },
+ });
+ } else {
+ await fetch(url, {
+ method: 'POST',
+ body: JSON.stringify({ message, shardId: shard.id }),
+ headers: { 'Content-Type': 'application/json', Authorization: script.handlerAuthorization },
+ }).catch((error) => log.error(error));
+ }
- log.debug({ shardId: shard.id, message });
- },
- requestIdentify: async function (shardId: number): Promise {
- return await new Promise((resolve) => {
- identifyPromises.set(shardId, resolve);
+ log.debug({ shardId: shard.id, message });
+ },
+ requestIdentify: async function (shardId: number): Promise {
+ return await new Promise((resolve) => {
+ identifyPromises.set(shardId, resolve);
- const identifyRequest: ManagerMessage = {
- type: "REQUEST_IDENTIFY",
- shardId,
- };
+ const identifyRequest: ManagerMessage = {
+ type: 'REQUEST_IDENTIFY',
+ shardId,
+ };
- parentPort?.postMessage(identifyRequest);
- });
- },
+ parentPort?.postMessage(identifyRequest);
+ });
+ },
});
function buildShardInfo(shard: Shard): WorkerShardInfo {
- return {
- workerId: script.workerId,
- shardId: shard.id,
- rtt: shard.heart.rtt || -1,
- state: shard.state,
- };
+ return {
+ workerId: script.workerId,
+ shardId: shard.id,
+ rtt: shard.heart.rtt || -1,
+ state: shard.state,
+ };
}
-parentPort.on("message", async (data: WorkerMessage) => {
- switch (data.type) {
- case "IDENTIFY_SHARD": {
- log.info(`starting to identify shard #${data.shardId}`);
- await manager.identify(data.shardId);
+parentPort.on('message', async (data: WorkerMessage) => {
+ switch (data.type) {
+ case 'IDENTIFY_SHARD': {
+ log.info(`starting to identify shard #${data.shardId}`);
+ await manager.identify(data.shardId);
- break;
- }
- case "ALLOW_IDENTIFY": {
- identifyPromises.get(data.shardId)?.();
- identifyPromises.delete(data.shardId);
+ break;
+ }
+ case 'ALLOW_IDENTIFY': {
+ identifyPromises.get(data.shardId)?.();
+ identifyPromises.delete(data.shardId);
- break;
- }
- case "SHARD_PAYLOAD": {
- manager.shards.get(data.shardId)?.send(data.data);
+ break;
+ }
+ case 'SHARD_PAYLOAD': {
+ manager.shards.get(data.shardId)?.send(data.data);
- break;
- }
- case "GET_SHARD_INFO": {
- const infos = manager.shards.map(buildShardInfo);
+ break;
+ }
+ case 'GET_SHARD_INFO': {
+ const infos = manager.shards.map(buildShardInfo);
- parentPort?.postMessage({ type: "NONCE_REPLY", nonce: data.nonce, data: infos });
- }
- }
+ parentPort?.postMessage({ type: 'NONCE_REPLY', nonce: data.nonce, data: infos });
+ }
+ }
});
export type WorkerMessage = WorkerIdentifyShard | WorkerAllowIdentify | WorkerShardPayload | WorkerGetShardInfo;
export interface WorkerIdentifyShard {
- type: "IDENTIFY_SHARD";
- shardId: number;
+ type: 'IDENTIFY_SHARD';
+ shardId: number;
}
export interface WorkerAllowIdentify {
- type: "ALLOW_IDENTIFY";
- shardId: number;
+ type: 'ALLOW_IDENTIFY';
+ shardId: number;
}
export interface WorkerShardPayload {
- type: "SHARD_PAYLOAD";
- shardId: number;
- data: ShardSocketRequest;
+ type: 'SHARD_PAYLOAD';
+ shardId: number;
+ data: ShardSocketRequest;
}
export interface WorkerGetShardInfo {
- type: "GET_SHARD_INFO";
- nonce: string;
+ type: 'GET_SHARD_INFO';
+ nonce: string;
}
export interface WorkerCreateData {
- intents: number;
- token: string;
- handlerUrls: string[];
- handlerAuthorization: string;
- path: string;
- totalShards: number;
- workerId: number;
+ intents: number;
+ token: string;
+ handlerUrls: string[];
+ handlerAuthorization: string;
+ path: string;
+ totalShards: number;
+ workerId: number;
}
export interface WorkerShardInfo {
- workerId: number;
- shardId: number;
- rtt: number;
- state: ShardState;
+ workerId: number;
+ shardId: number;
+ rtt: number;
+ state: ShardState;
}
const connectRabbitmq = async () => {
- let connection: amqplib.Connection | undefined;
+ let connection: amqplib.Connection | undefined;
- try {
- connection = await amqplib.connect(
- `amqp://${process.env.MESSAGEQUEUE_USERNAME}:${process.env.MESSAGEQUEUE_PASSWORD}@${process.env.MESSAGEQUEUE_URL}`,
- );
- } catch (error) {
- channel = undefined;
- log.error(error);
- setTimeout(connectRabbitmq, 1000);
- }
+ try {
+ connection = await amqplib.connect(
+ `amqp://${process.env.MESSAGEQUEUE_USERNAME}:${process.env.MESSAGEQUEUE_PASSWORD}@${process.env.MESSAGEQUEUE_URL}`,
+ );
+ } catch (error) {
+ channel = undefined;
+ log.error(error);
+ setTimeout(connectRabbitmq, 1000);
+ }
- if (!connection) return;
- connection.on("error", (err) => {
- channel = undefined;
- log.error(err);
- setTimeout(connectRabbitmq, 1000);
- });
+ if (!connection) return;
+ connection.on('error', (err) => {
+ channel = undefined;
+ log.error(err);
+ setTimeout(connectRabbitmq, 1000);
+ });
- connection.on("close", () => {
- channel = undefined;
- setTimeout(connectRabbitmq, 1000);
- });
+ connection.on('close', () => {
+ channel = undefined;
+ setTimeout(connectRabbitmq, 1000);
+ });
- try {
- channel = await connection.createChannel();
- await channel.assertExchange(
- "gatewayMessage",
- "x-message-deduplication",
- {
- durable: true,
- arguments: {
- "x-cache-size": 1000,
- "x-cache-ttl": 500,
- },
- },
- );
- } catch (error) {
- log.error(error);
- channel = undefined;
- }
+ try {
+ channel = await connection.createChannel();
+ await channel.assertExchange('gatewayMessage', 'x-message-deduplication', {
+ durable: true,
+ arguments: {
+ 'x-cache-size': 1000,
+ 'x-cache-ttl': 500,
+ },
+ });
+ } catch (error) {
+ log.error(error);
+ channel = undefined;
+ }
};
if (useMessageQueue) {
- connectRabbitmq();
+ connectRabbitmq();
}
diff --git a/examples/bigbot/src/prisma.ts b/examples/bigbot/src/prisma.ts
index 901f3a0d9..9b6c4ce30 100644
--- a/examples/bigbot/src/prisma.ts
+++ b/examples/bigbot/src/prisma.ts
@@ -1,3 +1,3 @@
-import { PrismaClient } from "@prisma/client";
+import { PrismaClient } from '@prisma/client';
export const prisma = new PrismaClient();
diff --git a/examples/bigbot/src/rest/index.ts b/examples/bigbot/src/rest/index.ts
index 0f0d03ac6..4521baa46 100644
--- a/examples/bigbot/src/rest/index.ts
+++ b/examples/bigbot/src/rest/index.ts
@@ -1,9 +1,9 @@
-import dotenv from "dotenv";
+import dotenv from 'dotenv';
-import { BASE_URL, createRestManager } from "discordeno";
-import express from "express";
-import { setupAnalyticsHooks } from "../analytics.js";
-import { REST_URL } from "../configs.js";
+import { BASE_URL, createRestManager } from 'discordeno';
+import express from 'express';
+import { setupAnalyticsHooks } from '../analytics.js';
+import { REST_URL } from '../configs.js';
dotenv.config();
const DISCORD_TOKEN = process.env.DISCORD_TOKEN as string;
@@ -11,10 +11,10 @@ const REST_AUTHORIZATION = process.env.REST_AUTHORIZATION as string;
const REST_PORT = process.env.REST_PORT as string;
const rest = createRestManager({
- token: DISCORD_TOKEN,
- secretKey: REST_AUTHORIZATION,
- customUrl: REST_URL,
- debug: console.log,
+ token: DISCORD_TOKEN,
+ secretKey: REST_AUTHORIZATION,
+ customUrl: REST_URL,
+ debug: console.log,
});
// Add send fetching analytics hook to rest
@@ -22,39 +22,39 @@ setupAnalyticsHooks(rest);
// @ts-expect-error
rest.convertRestError = (errorStack, data) => {
- if (!data) return { message: errorStack.message };
- return { ...data, message: errorStack.message };
+ if (!data) return { message: errorStack.message };
+ return { ...data, message: errorStack.message };
};
const app = express();
app.use(
- express.urlencoded({
- extended: true,
- }),
+ express.urlencoded({
+ extended: true,
+ }),
);
app.use(express.json());
-app.all("/*", async (req, res) => {
- if (!REST_AUTHORIZATION || REST_AUTHORIZATION !== req.headers.authorization) {
- return res.status(401).json({ error: "Invalid authorization key." });
- }
+app.all('/*', async (req, res) => {
+ if (!REST_AUTHORIZATION || REST_AUTHORIZATION !== req.headers.authorization) {
+ return res.status(401).json({ error: 'Invalid authorization key.' });
+ }
- try {
- const result = await rest.runMethod(rest, req.method , `${BASE_URL}${req.url}`, req.body);
+ try {
+ const result = await rest.runMethod(rest, req.method, `${BASE_URL}${req.url}`, req.body);
- if (result) {
- res.status(200).json(result);
- } else {
- res.status(204).json();
- }
- } catch (error: any) {
- console.log(error);
- res.status(500).json(error);
- }
+ if (result) {
+ res.status(200).json(result);
+ } else {
+ res.status(204).json();
+ }
+ } catch (error: any) {
+ console.log(error);
+ res.status(500).json(error);
+ }
});
app.listen(REST_PORT, () => {
- console.log(`REST listening at ${REST_URL}`);
+ console.log(`REST listening at ${REST_URL}`);
});
diff --git a/examples/minimal/configs.ts b/examples/minimal/configs.ts
index 113ae6e56..5409e62f4 100644
--- a/examples/minimal/configs.ts
+++ b/examples/minimal/configs.ts
@@ -1,5 +1,5 @@
-import { dotEnvConfig } from './deps.ts.js';
+import { dotEnvConfig } from './deps.ts.js'
-dotEnvConfig({ export: true });
-export const BOT_TOKEN = process.env.BOT_TOKEN || "";
-export const BOT_ID = BigInt(atob(BOT_TOKEN.split(".")[0]));
+dotEnvConfig({ export: true })
+export const BOT_TOKEN = process.env.BOT_TOKEN || ''
+export const BOT_ID = BigInt(atob(BOT_TOKEN.split('.')[0]))
diff --git a/examples/minimal/deps.ts b/examples/minimal/deps.ts
index 2daf246f3..d78783606 100644
--- a/examples/minimal/deps.ts
+++ b/examples/minimal/deps.ts
@@ -1,4 +1,4 @@
-export * from "https://deno.land/x/discordeno@17.0.0/mod.ts";
-export * from "https://deno.land/x/discordeno@17.0.0/plugins/mod.ts";
-export { config as dotEnvConfig } from "https://deno.land/x/dotenv@v3.1.0/mod.ts";
-export * from "https://deno.land/std@0.117.0/fmt/colors.ts";
+export * from 'https://deno.land/x/discordeno@17.0.0/mod.ts'
+export * from 'https://deno.land/x/discordeno@17.0.0/plugins/mod.ts'
+export { config as dotEnvConfig } from 'https://deno.land/x/dotenv@v3.1.0/mod.ts'
+export * from 'https://deno.land/std@0.117.0/fmt/colors.ts'
diff --git a/examples/minimal/mod.ts b/examples/minimal/mod.ts
index 9314c587a..67ecc25d2 100644
--- a/examples/minimal/mod.ts
+++ b/examples/minimal/mod.ts
@@ -1,27 +1,19 @@
-import {
- ActivityTypes,
- createBot,
- enableCachePlugin,
- enableCacheSweepers,
- fastFileLoader,
- GatewayIntents,
- startBot,
-} from './deps.ts.js';
-import { BOT_ID, BOT_TOKEN } from './configs.ts.js';
-import { logger } from './src/utils/logger.ts.js';
-import { events } from './src/events/mod.ts.js';
-import { updateCommands } from './src/utils/helpers.ts.js';
+import { ActivityTypes, createBot, enableCachePlugin, enableCacheSweepers, fastFileLoader, GatewayIntents, startBot } from './deps.ts.js'
+import { BOT_ID, BOT_TOKEN } from './configs.ts.js'
+import { logger } from './src/utils/logger.ts.js'
+import { events } from './src/events/mod.ts.js'
+import { updateCommands } from './src/utils/helpers.ts.js'
-const log = logger({ name: "Main" });
+const log = logger({ name: 'Main' })
-log.info("Starting Bot, this might take a while...");
+log.info('Starting Bot, this might take a while...')
-const paths = ["./src/events", "./src/commands"];
+const paths = ['./src/events', './src/commands']
await fastFileLoader(paths).catch((err) => {
- log.fatal(`Unable to Import ${paths}`);
- log.fatal(err);
- Deno.exit(1);
-});
+ log.fatal(`Unable to Import ${paths}`)
+ log.fatal(err)
+ Deno.exit(1)
+})
export const bot = enableCachePlugin(
createBot({
@@ -30,25 +22,25 @@ export const bot = enableCachePlugin(
intents: GatewayIntents.Guilds,
events,
}),
-);
+)
// @ts-nocheck: no-updated-depencdencies
-enableCacheSweepers(bot);
+enableCacheSweepers(bot)
bot.gateway.manager.createShardOptions.makePresence = (shardId: number) => {
return {
shardId,
- status: "online",
+ status: 'online',
activities: [
{
- name: "Discordeno is the Best Lib",
+ name: 'Discordeno is the Best Lib',
type: ActivityTypes.Game,
createdAt: Date.now(),
},
],
- };
-};
+ }
+}
-await startBot(bot);
+await startBot(bot)
-await updateCommands(bot);
+await updateCommands(bot)
diff --git a/examples/minimal/src/commands/mod.ts b/examples/minimal/src/commands/mod.ts
index 6b87af077..e4390adc8 100644
--- a/examples/minimal/src/commands/mod.ts
+++ b/examples/minimal/src/commands/mod.ts
@@ -1,25 +1,25 @@
-import type { ApplicationCommandOption, ApplicationCommandTypes, Bot, Interaction } from '../../deps.ts.js';
-import { Collection } from '../../deps.ts.js';
+import type { ApplicationCommandOption, ApplicationCommandTypes, Bot, Interaction } from '../../deps.ts.js'
+import { Collection } from '../../deps.ts.js'
-export type subCommand = Omit;
+export type subCommand = Omit
export interface subCommandGroup {
- name: string;
- subCommands: subCommand[];
+ name: string
+ subCommands: subCommand[]
}
export interface Command {
- name: string;
- description: string;
- usage?: string[];
- options?: ApplicationCommandOption[];
- type: ApplicationCommandTypes;
+ name: string
+ description: string
+ usage?: string[]
+ options?: ApplicationCommandOption[]
+ type: ApplicationCommandTypes
/** Defaults to `Guild` */
- scope?: "Global" | "Guild";
- execute: (bot: Bot, interaction: Interaction) => unknown;
- subcommands?: Array;
+ scope?: 'Global' | 'Guild'
+ execute: (bot: Bot, interaction: Interaction) => unknown
+ subcommands?: Array
}
-export const commands = new Collection();
+export const commands = new Collection()
export function createCommand(command: Command) {
- commands.set(command.name, command);
+ commands.set(command.name, command)
}
diff --git a/examples/minimal/src/commands/ping.ts b/examples/minimal/src/commands/ping.ts
index 13aca77fd..e3ae23803 100644
--- a/examples/minimal/src/commands/ping.ts
+++ b/examples/minimal/src/commands/ping.ts
@@ -1,23 +1,19 @@
-import { ApplicationCommandTypes, InteractionResponseTypes } from '../../deps.ts.js';
-import { humanizeMilliseconds, snowflakeToTimestamp } from '../utils/helpers.ts.js';
-import { createCommand } from './mod.ts.js';
+import { ApplicationCommandTypes, InteractionResponseTypes } from '../../deps.ts.js'
+import { humanizeMilliseconds, snowflakeToTimestamp } from '../utils/helpers.ts.js'
+import { createCommand } from './mod.ts.js'
createCommand({
- name: "ping",
- description: "Ping the Bot!",
+ name: 'ping',
+ description: 'Ping the Bot!',
type: ApplicationCommandTypes.ChatInput,
- scope: "Global",
+ scope: 'Global',
execute: async (bot, interaction) => {
- const ping = Date.now() - snowflakeToTimestamp(interaction.id);
- await bot.helpers.sendInteractionResponse(
- interaction.id,
- interaction.token,
- {
- type: InteractionResponseTypes.ChannelMessageWithSource,
- data: {
- content: `🏓 Pong! Ping ${ping}ms (${humanizeMilliseconds(ping)})`,
- },
+ const ping = Date.now() - snowflakeToTimestamp(interaction.id)
+ await bot.helpers.sendInteractionResponse(interaction.id, interaction.token, {
+ type: InteractionResponseTypes.ChannelMessageWithSource,
+ data: {
+ content: `🏓 Pong! Ping ${ping}ms (${humanizeMilliseconds(ping)})`,
},
- );
+ })
},
-});
+})
diff --git a/examples/minimal/src/events/guildCreate.ts b/examples/minimal/src/events/guildCreate.ts
index b33540fbf..a7f2e892c 100644
--- a/examples/minimal/src/events/guildCreate.ts
+++ b/examples/minimal/src/events/guildCreate.ts
@@ -1,4 +1,4 @@
-import { events } from './mod.ts.js';
-import { updateGuildCommands } from '../utils/helpers.ts.js';
+import { events } from './mod.ts.js'
+import { updateGuildCommands } from '../utils/helpers.ts.js'
-events.guildCreate = async (bot, guild) => await updateGuildCommands(bot, guild);
+events.guildCreate = async (bot, guild) => await updateGuildCommands(bot, guild)
diff --git a/examples/minimal/src/events/interactionCreate.ts b/examples/minimal/src/events/interactionCreate.ts
index 90ee4b0f1..4772d2ad2 100644
--- a/examples/minimal/src/events/interactionCreate.ts
+++ b/examples/minimal/src/events/interactionCreate.ts
@@ -1,135 +1,111 @@
-import type {
- BotWithCache,
- Guild} from '../../deps.ts.js';
-import {
- ApplicationCommandOptionTypes,
- bgBlack,
- bgYellow,
- black,
- green,
- red,
- white,
- yellow,
-} from '../../deps.ts.js';
-import { events } from './mod.ts.js';
-import { logger } from '../utils/logger.ts.js';
-import { getGuildFromId, isSubCommand, isSubCommandGroup } from '../utils/helpers.ts.js';
-import type { Command} from '../commands/mod.ts.js';
-import { commands } from '../commands/mod.ts.js';
+import type { BotWithCache, Guild } from '../../deps.ts.js'
+import { ApplicationCommandOptionTypes, bgBlack, bgYellow, black, green, red, white, yellow } from '../../deps.ts.js'
+import { events } from './mod.ts.js'
+import { logger } from '../utils/logger.ts.js'
+import { getGuildFromId, isSubCommand, isSubCommandGroup } from '../utils/helpers.ts.js'
+import type { Command } from '../commands/mod.ts.js'
+import { commands } from '../commands/mod.ts.js'
-const log = logger({ name: "Event: InteractionCreate" });
+const log = logger({ name: 'Event: InteractionCreate' })
events.interactionCreate = async (rawBot, interaction) => {
- const bot = rawBot as BotWithCache;
+ const bot = rawBot as BotWithCache
if (interaction.data && interaction.id) {
- let guildName = "Direct Message";
- let guild = {} as Guild;
+ let guildName = 'Direct Message'
+ let guild = {} as Guild
// Set guild, if there was an error getting the guild, then just say it was a DM. (What else are we going to do?)
if (interaction.guildId) {
- const guildOrVoid = await getGuildFromId(bot, interaction.guildId).catch(
- (err) => {
- log.error(err);
- },
- );
+ const guildOrVoid = await getGuildFromId(bot, interaction.guildId).catch((err) => {
+ log.error(err)
+ })
if (guildOrVoid) {
- guild = guildOrVoid;
- guildName = guild.name;
+ guild = guildOrVoid
+ guildName = guild.name
}
}
log.info(
- `[Command: ${bgYellow(black(String(interaction.data.name)))} - ${
- bgBlack(white(`Trigger`))
- }] by ${interaction.user.username}#${interaction.user.discriminator} in ${guildName}${
- guildName !== "Direct Message" ? ` (${guild.id})` : ``
- }`,
- );
+ `[Command: ${bgYellow(black(String(interaction.data.name)))} - ${bgBlack(white(`Trigger`))}] by ${interaction.user.username}#${
+ interaction.user.discriminator
+ } in ${guildName}${guildName !== 'Direct Message' ? ` (${guild.id})` : ``}`,
+ )
- let command: undefined | Command = interaction.data.name ? commands.get(interaction.data.name) : undefined;
- let commandName = command?.name;
+ let command: undefined | Command = interaction.data.name ? commands.get(interaction.data.name) : undefined
+ let commandName = command?.name
if (command !== undefined) {
if (interaction.data.name) {
if (interaction.data.options?.[0]) {
- const optionType = interaction.data.options[0].type;
+ const optionType = interaction.data.options[0].type
if (optionType === ApplicationCommandOptionTypes.SubCommandGroup) {
// Check if command has subcommand and handle types
- if (!command.subcommands) return;
+ if (!command.subcommands) return
// Try to find the subcommand group
- const subCommandGroup = command.subcommands?.find(
- (command) => command.name == interaction.data?.options?.[0].name,
- );
- if (!subCommandGroup) return;
+ const subCommandGroup = command.subcommands?.find((command) => command.name == interaction.data?.options?.[0].name)
+ if (!subCommandGroup) return
- if (isSubCommand(subCommandGroup)) return;
+ if (isSubCommand(subCommandGroup)) return
// Get name of the command which we are looking for
- const targetCmdName = interaction.data.options?.[0].options?.[0].name ||
- interaction.data.options?.[0].options?.[0].name;
- if (!targetCmdName) return;
+ const targetCmdName = interaction.data.options?.[0].options?.[0].name || interaction.data.options?.[0].options?.[0].name
+ if (!targetCmdName) return
// Try to find the command
- command = subCommandGroup.subCommands.find((c) => c.name === targetCmdName);
+ command = subCommandGroup.subCommands.find((c) => c.name === targetCmdName)
- commandName += ` ${subCommandGroup.name} ${command?.name}`;
+ commandName += ` ${subCommandGroup.name} ${command?.name}`
// Normal
}
if (optionType === ApplicationCommandOptionTypes.SubCommandGroup) {
// Check if command has subcommand and handle types
- if (!command?.subcommands) return;
+ if (!command?.subcommands) return
// Try to find the command
- const found = command.subcommands.find((command) => command.name == interaction.data?.options?.[0].name);
- if (!found) return;
+ const found = command.subcommands.find((command) => command.name == interaction.data?.options?.[0].name)
+ if (!found) return
- if (isSubCommandGroup(found)) return;
+ if (isSubCommandGroup(found)) return
- command = found;
- commandName += ` ${command?.name}`;
+ command = found
+ commandName += ` ${command?.name}`
}
}
try {
if (command) {
- command.execute(rawBot, interaction);
+ command.execute(rawBot, interaction)
log.info(
- `[Command: ${bgYellow(black(String(interaction.data.name)))} - ${
- bgBlack(green(`Success`))
- }] by ${interaction.user.username}#${interaction.user.discriminator} in ${guildName}${
- guildName !== "Direct Message" ? ` (${guild.id})` : ``
- }`,
- );
+ `[Command: ${bgYellow(black(String(interaction.data.name)))} - ${bgBlack(green(`Success`))}] by ${interaction.user.username}#${
+ interaction.user.discriminator
+ } in ${guildName}${guildName !== 'Direct Message' ? ` (${guild.id})` : ``}`,
+ )
} else {
- throw "";
+ throw ''
}
} catch (err) {
log.error(
- `[Command: ${bgYellow(black(String(interaction.data.name)))} - ${
- bgBlack(red(`Error`))
- }] by ${interaction.user.username}#${interaction.user.discriminator} in ${guildName}${
- guildName !== "Direct Message" ? ` (${guild.id})` : ``
- }`,
- );
- err.length ? log.error(err) : undefined;
+ `[Command: ${bgYellow(black(String(interaction.data.name)))} - ${bgBlack(red(`Error`))}] by ${interaction.user.username}#${
+ interaction.user.discriminator
+ } in ${guildName}${guildName !== 'Direct Message' ? ` (${guild.id})` : ``}`,
+ )
+ err.length ? log.error(err) : undefined
}
} else {
log.warn(
- `[Command: ${bgYellow(black(String(interaction.data.name)))} - ${
- bgBlack(yellow(`Not Found`))
- }] by ${interaction.user.username}#${interaction.user.discriminator} in ${guildName}${
- guildName !== "Direct Message" ? ` (${guild.id})` : ``
- }`,
- );
+ `[Command: ${bgYellow(black(String(interaction.data.name)))} - ${bgBlack(yellow(`Not Found`))}] by ${interaction.user.username}#${
+ interaction.user.discriminator
+ } in ${guildName}${guildName !== 'Direct Message' ? ` (${guild.id})` : ``}`,
+ )
}
}
}
-};
+}
/*
// Handle subcommands
diff --git a/examples/minimal/src/events/mod.ts b/examples/minimal/src/events/mod.ts
index 271881422..e7861048e 100644
--- a/examples/minimal/src/events/mod.ts
+++ b/examples/minimal/src/events/mod.ts
@@ -1,3 +1,3 @@
-import type { EventHandlers } from '../../deps.ts.js';
+import type { EventHandlers } from '../../deps.ts.js'
-export const events: Partial = {};
+export const events: Partial = {}
diff --git a/examples/minimal/src/events/ready.ts b/examples/minimal/src/events/ready.ts
index 70f6ed8f0..324bc42eb 100644
--- a/examples/minimal/src/events/ready.ts
+++ b/examples/minimal/src/events/ready.ts
@@ -1,8 +1,8 @@
-import { events } from './mod.ts.js';
-import { logger } from '../utils/logger.ts.js';
+import { events } from './mod.ts.js'
+import { logger } from '../utils/logger.ts.js'
-const log = logger({ name: "Event: Ready" });
+const log = logger({ name: 'Event: Ready' })
events.ready = () => {
- log.info("Bot Ready");
-};
+ log.info('Bot Ready')
+}
diff --git a/examples/minimal/src/utils/helpers.ts b/examples/minimal/src/utils/helpers.ts
index 419839b0d..93490835a 100644
--- a/examples/minimal/src/utils/helpers.ts
+++ b/examples/minimal/src/utils/helpers.ts
@@ -1,41 +1,32 @@
-import type {
- Bot,
- BotWithCache,
- CreateApplicationCommand,
- Guild,
- MakeRequired} from '../../deps.ts.js';
-import {
- getGuild,
- hasProperty,
- upsertGuildApplicationCommands,
-} from '../../deps.ts.js';
-import { logger } from './logger.ts.js';
-import type { subCommand, subCommandGroup } from '../commands/mod.ts.js';
-import { commands } from '../commands/mod.ts.js';
+import type { Bot, BotWithCache, CreateApplicationCommand, Guild, MakeRequired } from '../../deps.ts.js'
+import { getGuild, hasProperty, upsertGuildApplicationCommands } from '../../deps.ts.js'
+import { logger } from './logger.ts.js'
+import type { subCommand, subCommandGroup } from '../commands/mod.ts.js'
+import { commands } from '../commands/mod.ts.js'
-const log = logger({ name: "Helpers" });
+const log = logger({ name: 'Helpers' })
/** This function will update all commands, or the defined scope */
-export async function updateCommands(bot: BotWithCache, scope?: "Guild" | "Global") {
- const globalCommands: Array> = [];
- const perGuildCommands: Array> = [];
+export async function updateCommands(bot: BotWithCache, scope?: 'Guild' | 'Global') {
+ const globalCommands: Array> = []
+ const perGuildCommands: Array> = []
for (const command of commands.values()) {
if (command.scope) {
- if (command.scope === "Guild") {
+ if (command.scope === 'Guild') {
perGuildCommands.push({
name: command.name,
description: command.description,
type: command.type,
options: command.options ? command.options : undefined,
- });
- } else if (command.scope === "Global") {
+ })
+ } else if (command.scope === 'Global') {
globalCommands.push({
name: command.name,
description: command.description,
type: command.type,
options: command.options ? command.options : undefined,
- });
+ })
}
} else {
perGuildCommands.push({
@@ -43,87 +34,87 @@ export async function updateCommands(bot: BotWithCache, scope?: "Guild" | "Globa
description: command.description,
type: command.type,
options: command.options ? command.options : undefined,
- });
+ })
}
}
- if (globalCommands.length && (scope === "Global" || scope === undefined)) {
- log.info("Updating Global Commands, changes should apply in short...");
- await bot.helpers.upsertGlobalApplicationCommands(globalCommands).catch(log.error);
+ if (globalCommands.length && (scope === 'Global' || scope === undefined)) {
+ log.info('Updating Global Commands, changes should apply in short...')
+ await bot.helpers.upsertGlobalApplicationCommands(globalCommands).catch(log.error)
}
- if (perGuildCommands.length && (scope === "Guild" || scope === undefined)) {
+ if (perGuildCommands.length && (scope === 'Guild' || scope === undefined)) {
await bot.guilds.forEach(async (guild: Guild) => {
- await upsertGuildApplicationCommands(bot, guild.id, perGuildCommands);
- });
+ await upsertGuildApplicationCommands(bot, guild.id, perGuildCommands)
+ })
}
}
/** Update commands for a guild */
export async function updateGuildCommands(bot: Bot, guild: Guild) {
- const perGuildCommands: Array> = [];
+ const perGuildCommands: Array> = []
for (const command of commands.values()) {
if (command.scope) {
- if (command.scope === "Guild") {
+ if (command.scope === 'Guild') {
perGuildCommands.push({
name: command.name,
description: command.description,
type: command.type,
options: command.options ? command.options : undefined,
- });
+ })
}
}
}
if (perGuildCommands.length) {
- await upsertGuildApplicationCommands(bot, guild.id, perGuildCommands);
+ await upsertGuildApplicationCommands(bot, guild.id, perGuildCommands)
}
}
export async function getGuildFromId(bot: BotWithCache, guildId: bigint): Promise {
- let returnValue: Guild = {} as Guild;
+ let returnValue: Guild = {} as Guild
if (guildId !== 0n) {
if (bot.guilds.get(guildId)) {
- returnValue = bot.guilds.get(guildId) as Guild;
+ returnValue = bot.guilds.get(guildId) as Guild
}
await getGuild(bot, guildId).then((guild) => {
- if (guild) bot.guilds.set(guildId, guild);
- if (guild) returnValue = guild;
- });
+ if (guild) bot.guilds.set(guildId, guild)
+ if (guild) returnValue = guild
+ })
}
- return returnValue;
+ return returnValue
}
export function snowflakeToTimestamp(id: bigint) {
- return Number(id / 4194304n + 1420070400000n);
+ return Number(id / 4194304n + 1420070400000n)
}
export function humanizeMilliseconds(milliseconds: number) {
// Gets ms into seconds
- const time = milliseconds / 1000;
- if (time < 1) return "1s";
+ const time = milliseconds / 1000
+ if (time < 1) return '1s'
- const days = Math.floor(time / 86400);
- const hours = Math.floor((time % 86400) / 3600);
- const minutes = Math.floor(((time % 86400) % 3600) / 60);
- const seconds = Math.floor(((time % 86400) % 3600) % 60);
+ const days = Math.floor(time / 86400)
+ const hours = Math.floor((time % 86400) / 3600)
+ const minutes = Math.floor(((time % 86400) % 3600) / 60)
+ const seconds = Math.floor(((time % 86400) % 3600) % 60)
- const dayString = days ? `${days}d ` : "";
- const hourString = hours ? `${hours}h ` : "";
- const minuteString = minutes ? `${minutes}m ` : "";
- const secondString = seconds ? `${seconds}s ` : "";
+ const dayString = days ? `${days}d ` : ''
+ const hourString = hours ? `${hours}h ` : ''
+ const minuteString = minutes ? `${minutes}m ` : ''
+ const secondString = seconds ? `${seconds}s ` : ''
- return `${dayString}${hourString}${minuteString}${secondString}`;
+ return `${dayString}${hourString}${minuteString}${secondString}`
}
export function isSubCommand(data: subCommand | subCommandGroup): data is subCommand {
- return !hasProperty(data, "subCommands");
+ return !hasProperty(data, 'subCommands')
}
export function isSubCommandGroup(data: subCommand | subCommandGroup): data is subCommandGroup {
- return hasProperty(data, "subCommands");
+ return hasProperty(data, 'subCommands')
}
diff --git a/examples/minimal/src/utils/logger.ts b/examples/minimal/src/utils/logger.ts
index f711138de..9228b7074 100644
--- a/examples/minimal/src/utils/logger.ts
+++ b/examples/minimal/src/utils/logger.ts
@@ -1,5 +1,5 @@
// deno-lint-ignore-file no-explicit-any
-import { bold, cyan, gray, italic, red, yellow } from '../../deps.ts.js';
+import { bold, cyan, gray, italic, red, yellow } from '../../deps.ts.js'
export enum LogLevels {
Debug,
@@ -10,81 +10,81 @@ export enum LogLevels {
}
const prefixes = new Map([
- [LogLevels.Debug, "DEBUG"],
- [LogLevels.Info, "INFO"],
- [LogLevels.Warn, "WARN"],
- [LogLevels.Error, "ERROR"],
- [LogLevels.Fatal, "FATAL"],
-]);
+ [LogLevels.Debug, 'DEBUG'],
+ [LogLevels.Info, 'INFO'],
+ [LogLevels.Warn, 'WARN'],
+ [LogLevels.Error, 'ERROR'],
+ [LogLevels.Fatal, 'FATAL'],
+])
-const noColor: (str: string) => string = (msg) => msg;
+const noColor: (str: string) => string = (msg) => msg
const colorFunctions = new Map string>([
[LogLevels.Debug, gray],
[LogLevels.Info, cyan],
[LogLevels.Warn, yellow],
[LogLevels.Error, (str: string) => red(str)],
[LogLevels.Fatal, (str: string) => red(bold(italic(str)))],
-]);
+])
export function logger({
logLevel = LogLevels.Info,
name,
}: {
- logLevel?: LogLevels;
- name?: string;
+ logLevel?: LogLevels
+ name?: string
} = {}) {
function log(level: LogLevels, ...args: any[]) {
- if (level < logLevel) return;
+ if (level < logLevel) return
- let color = colorFunctions.get(level);
- if (!color) color = noColor;
+ let color = colorFunctions.get(level)
+ if (!color) color = noColor
- const date = new Date();
+ const date = new Date()
const log = [
`[${date.toLocaleDateString()} ${date.toLocaleTimeString()}]`,
- color(prefixes.get(level) || "DEBUG"),
- name ? `${name} >` : ">",
+ color(prefixes.get(level) || 'DEBUG'),
+ name ? `${name} >` : '>',
...args,
- ];
+ ]
switch (level) {
case LogLevels.Debug:
- return console.debug(...log);
+ return console.debug(...log)
case LogLevels.Info:
- return console.info(...log);
+ return console.info(...log)
case LogLevels.Warn:
- return console.warn(...log);
+ return console.warn(...log)
case LogLevels.Error:
- return console.error(...log);
+ return console.error(...log)
case LogLevels.Fatal:
- return console.error(...log);
+ return console.error(...log)
default:
- return console.log(...log);
+ return console.log(...log)
}
}
function setLevel(level: LogLevels) {
- logLevel = level;
+ logLevel = level
}
function debug(...args: any[]) {
- log(LogLevels.Debug, ...args);
+ log(LogLevels.Debug, ...args)
}
function info(...args: any[]) {
- log(LogLevels.Info, ...args);
+ log(LogLevels.Info, ...args)
}
function warn(...args: any[]) {
- log(LogLevels.Warn, ...args);
+ log(LogLevels.Warn, ...args)
}
function error(...args: any[]) {
- log(LogLevels.Error, ...args);
+ log(LogLevels.Error, ...args)
}
function fatal(...args: any[]) {
- log(LogLevels.Fatal, ...args);
+ log(LogLevels.Fatal, ...args)
}
return {
@@ -95,7 +95,7 @@ export function logger({
warn,
error,
fatal,
- };
+ }
}
-export const log = logger();
+export const log = logger()
diff --git a/packages/bot/src/bot.ts b/packages/bot/src/bot.ts
index 4db5cb29c..282a9d972 100644
--- a/packages/bot/src/bot.ts
+++ b/packages/bot/src/bot.ts
@@ -1,4 +1,4 @@
-import type { CreateGatewayManagerOptions, GatewayManager, Shard } from '@discordeno/gateway'
+import type { CreateGatewayManagerOptions, GatewayManager, DiscordenoShard } from '@discordeno/gateway'
import { createGatewayManager, ShardSocketCloseCodes } from '@discordeno/gateway'
import type { CreateRestManagerOptions, RestManager } from '@discordeno/rest'
import { createRestManager } from '@discordeno/rest'
@@ -61,22 +61,22 @@ import { createLogger } from '@discordeno/utils'
*/
export function createBot(options: CreateBotOptions): Bot {
if (!options.rest) options.rest = { token: options.token }
- if (!options.gateway) options.gateway = { token: options.token, events: {} };
+ if (!options.gateway) options.gateway = { token: options.token, events: {} }
if (!options.gateway.events.message) {
options.gateway.events.message = async (shard, data) => {
- // TRIGGER RAW EVENT
- bot.events.raw?.(data, shard)
+ // TRIGGER RAW EVENT
+ bot.events.raw?.(data, shard)
- if (!data.t) return
+ if (!data.t) return
- // RUN DISPATCH CHECK
- await bot.events.dispatchRequirements?.(data, shard)
- bot.events[
- data.t.toLowerCase().replace(/_([a-z])/g, function (g) {
- return g[1].toUpperCase()
- }) as keyof EventHandlers
- // @ts-expect-error as any gets removed by linter
- ]?.(data.d, shard)
+ // RUN DISPATCH CHECK
+ await bot.events.dispatchRequirements?.(data, shard)
+ bot.events[
+ data.t.toLowerCase().replace(/_([a-z])/g, function (g) {
+ return g[1].toUpperCase()
+ }) as keyof EventHandlers
+ // @ts-expect-error as any gets removed by linter
+ ]?.(data.d, shard)
}
}
@@ -134,68 +134,68 @@ export interface Bot {
export interface EventHandlers {
// Custom events here
- dispatchRequirements: (payload: Camelize, shard: Shard) => unknown
- raw: (payload: Camelize, shard: Shard) => unknown
+ dispatchRequirements: (payload: Camelize, shard: DiscordenoShard) => unknown
+ raw: (payload: Camelize, shard: DiscordenoShard) => unknown
// Gateway events below this
- applicationCommandPermissionsUpdate: (payload: Camelize, shard: Shard) => unknown
- auditLogEntryCreate: (payload: Camelize, shard: Shard) => unknown
- autoModerationRuleCreate: (payload: Camelize, shard: Shard) => unknown
- autoModerationRuleUpdate: (payload: Camelize, shard: Shard) => unknown
- autoModerationRuleDelete: (payload: Camelize, shard: Shard) => unknown
- autoModerationActionExecution: (payload: Camelize, shard: Shard) => unknown
- channelCreate: (payload: Camelize, shard: Shard) => unknown
- channelUpdate: (payload: Camelize, shard: Shard) => unknown
- channelDelete: (payload: Camelize, shard: Shard) => unknown
- channelPinsUpdate: (payload: Camelize, shard: Shard) => unknown
- threadCreate: (payload: Camelize, shard: Shard) => unknown
- threadUpdate: (payload: Camelize, shard: Shard) => unknown
- threadDelete: (payload: Camelize, shard: Shard) => unknown
- threadListSync: (payload: Camelize, shard: Shard) => unknown
- threadMemberUpdate: (payload: Camelize, shard: Shard) => unknown
- threadMembersUpdate: (payload: Camelize, shard: Shard) => unknown
- guildCreate: (payload: Camelize, shard: Shard) => unknown
- guildUpdate: (payload: Camelize, shard: Shard) => unknown
- guildDelete: (payload: Camelize, shard: Shard) => unknown
- guildBanAdd: (payload: Camelize, shard: Shard) => unknown
- guildBanRemove: (payload: Camelize, shard: Shard) => unknown
- guildEmojisUpdate: (payload: Camelize, shard: Shard) => unknown
- guildStickersUpdate: (payload: Camelize, shard: Shard) => unknown
- guildIntegrationsUpdate: (payload: Camelize, shard: Shard) => unknown
- guildMemberAdd: (payload: Camelize, shard: Shard) => unknown
- guildMemberRemove: (payload: Camelize, shard: Shard) => unknown
- guildMemberUpdate: (payload: Camelize, shard: Shard) => unknown
- guildMembersChunk: (payload: Camelize, shard: Shard) => unknown
- guildRoleCreate: (payload: Camelize, shard: Shard) => unknown
- guildRoleUpdate: (payload: Camelize, shard: Shard) => unknown
- guildRoleDelete: (payload: Camelize, shard: Shard) => unknown
- guildScheduledEventCreate: (payload: Camelize, shard: Shard) => unknown
- guildScheduledEventUpdate: (payload: Camelize, shard: Shard) => unknown
- guildScheduledEventDelete: (payload: Camelize, shard: Shard) => unknown
- guildScheduledEventUserAdd: (payload: Camelize, shard: Shard) => unknown
- guildScheduledEventUserRemove: (payload: Camelize, shard: Shard) => unknown
- integrationCreate: (payload: Camelize, shard: Shard) => unknown
- integrationUpdate: (payload: Camelize, shard: Shard) => unknown
- integrationDelete: (payload: Camelize, shard: Shard) => unknown
- interactionCreate: (payload: Camelize, shard: Shard) => unknown
- inviteCreate: (payload: Camelize, shard: Shard) => unknown
- inviteDelete: (payload: Camelize, shard: Shard) => unknown
- messageCreate: (payload: Camelize, shard: Shard) => unknown
- messageUpdate: (payload: Camelize, shard: Shard) => unknown
- messageDelete: (payload: Camelize, shard: Shard) => unknown
- messageDeleteBulk: (payload: Camelize, shard: Shard) => unknown
- messageReactionAdd: (payload: Camelize, shard: Shard) => unknown
- messageReactionRemove: (payload: Camelize, shard: Shard) => unknown
- messageReactionRemoveAll: (payload: Camelize