mirror of
https://github.com/discordeno/discordeno.git
synced 2026-06-01 00:10:07 +00:00
fix: bigbot template (#2535)
* chore: fix script extension * chore: remove extention * fix: at least it run can now * chore: fix dev script * refactor: change to use env file for config * chore: update readme
This commit is contained in:
@@ -1,4 +1,86 @@
|
||||
# For Prisma use. Remember to remove the `[` and `]`
|
||||
DATABASE_URL=postgres://[username]:[password]@[host]:[port]/[db]
|
||||
# For Prisma use. Remember to remove the [ and ]
|
||||
DATABASE_URL=postgres:#[username]:[password]@[host]:[port]/[db]
|
||||
|
||||
# For other configs, update src/configs.ts
|
||||
# For other configs, update src/configs.ts
|
||||
|
||||
# General Configurations
|
||||
# Whether or not this process is a local development version. Change to false for the main production bot. */
|
||||
# SETUP-DD-TEMP: Change this to false in your server for production bot. Keep true in local testing.
|
||||
DEVELOPMENT=true
|
||||
|
||||
# The server id where you develop/test the bot. */
|
||||
# SETUP-DD-TEMP: Change the id to a server where you develop the bot privately.
|
||||
DEV_SERVER_ID=
|
||||
|
||||
# The discord bot token, without the BOT prefix. */
|
||||
# SETUP-DD-TEMP: Add the bot token here.
|
||||
DISCORD_TOKEN=
|
||||
|
||||
# Bot Configurations
|
||||
# The secret passcode that the bot code (event handler) is listening for. This is used to prevent someone else from trying to send malicious messages to your bot. */
|
||||
# SETUP-DD-TEMP: Add a secret passcode here.
|
||||
EVENT_HANDLER_AUTHORIZATION=server
|
||||
|
||||
# The host where the event handler will run. Must follow https:#nodejs.org/api/net.html#serverlistenoptions-callback. */
|
||||
# SETUP-DD-TEMP: Set the event handler's host here.
|
||||
EVENT_HANDLER_HOST=localhost
|
||||
|
||||
# The port where the event handler is listening for events. */
|
||||
# SETUP-DD-TEMP: Set the desired port where events will be sent to be processed.
|
||||
EVENT_HANDLER_PORT=8081
|
||||
|
||||
# The full webhook url where the bot can send errors to alert you that the bot is missing translations. */
|
||||
# SETUP-DD-TEMP: Set a full discord webhook url here.
|
||||
MISSING_TRANSLATION_WEBHOOK=
|
||||
|
||||
# The full webhook url where the bot can send errors to alert you that the bot is throwing errors. */
|
||||
# SETUP-DD-TEMP: Set a full discord webhook url here.
|
||||
BUGS_ERRORS_REPORT_WEBHOOK=
|
||||
|
||||
# Rest Proxy Configurations
|
||||
# The authorization code that the REST proxy will check for to make sure the requests are coming from you. */
|
||||
# SETUP-DD-TEMP: Add a secret passcode here.
|
||||
REST_AUTHORIZATION=secret
|
||||
|
||||
# The host where the REST proxy will run. Must follow https:#nodejs.org/api/net.html#serverlistenoptions-callback. */
|
||||
# SETUP-DD-TEMP: Set the REST proxy's host here.
|
||||
REST_HOST=localhost
|
||||
|
||||
# The port that will run the REST proxy. */
|
||||
# SETUP-DD-TEMP: Choose the port number here that will be used for the REST proxy.
|
||||
REST_PORT=8000
|
||||
|
||||
# Gateway Proxy Configurations
|
||||
|
||||
# The amount of shards to start. Useful with multiple servers where each server is handling a portion of your bot. */
|
||||
# SETUP-DD-TEMP: To start all bots, leave it as undefined. Specify he number of shards this process should handle.
|
||||
TOTAL_SHARDS=
|
||||
|
||||
# The amount of shards to start per worker. */
|
||||
# SETUP-DD-TEMP: Choose how many shards to start per worker. If you are not sure just stick to 16.
|
||||
SHARDS_PER_WORKER=16
|
||||
|
||||
# The total amount of workers to start. Generally this should be equal to the number of cores your server has. */
|
||||
# SETUP-DD-TEMP: Choose how many workers to start up. If you are not sure, check how many cores your server has.
|
||||
TOTAL_WORKERS=4
|
||||
|
||||
# The secret passcode that the gateway is listening for. This is used to prevent someone else from trying to send malicious messages to your bot. */
|
||||
# SETUP-DD-TEMP: Add a secret passcode here.
|
||||
GATEWAY_AUTHORIZATION=
|
||||
|
||||
# The host where the gateway will run. Must follow https:#nodejs.org/api/net.html#serverlistenoptions-callback. */
|
||||
# SETUP-DD-TEMP: Set the gateways's host here.
|
||||
GATEWAY_HOST=localhost
|
||||
|
||||
# The port where the gateway will run. This is where the bot will send its messages to the gateway. */
|
||||
# SETUP-DD-TEMP: Set the gateways's port here.
|
||||
GATEWAY_PORT=8080
|
||||
|
||||
# Database Configurations
|
||||
|
||||
# These INFLUX configs are only if you wish to enable analytics. */
|
||||
# SETUP-DD-TEMP: This is optional. If you want to build analytics, add influxdb here.
|
||||
INFLUX_BUCKET=
|
||||
INFLUX_ORG=
|
||||
INFLUX_TOKEN=
|
||||
INFLUX_URL=
|
||||
|
||||
31
template/bigbot/.swcrc
Normal file
31
template/bigbot/.swcrc
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"minify": true,
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "typescript",
|
||||
"decorators": true,
|
||||
"dynamicImport": true
|
||||
},
|
||||
"transform": {
|
||||
"legacyDecorator": true,
|
||||
"decoratorMetadata": true
|
||||
},
|
||||
"target": "es2022",
|
||||
"keepClassNames": true,
|
||||
"loose": true,
|
||||
"minify": {
|
||||
"compress": {
|
||||
"unused": true
|
||||
},
|
||||
"mangle": true
|
||||
}
|
||||
},
|
||||
"module": {
|
||||
"type": "es6",
|
||||
"strict": false,
|
||||
"strictMode": true,
|
||||
"lazy": false,
|
||||
"noInterop": false
|
||||
},
|
||||
"sourceMaps": "inline"
|
||||
}
|
||||
@@ -17,15 +17,11 @@ Make sure to install the latest version when you use it.
|
||||
To start your bot, you will need to start a few processes. The instructions below will use `node` but you can use
|
||||
something like `pm2` to help keep your processes alive.
|
||||
|
||||
Please compile everything first with `tsc`.
|
||||
Please compile everything first with `npm run build`.
|
||||
|
||||
- Start REST
|
||||
- `ts-node src/rest/index.ts`
|
||||
- `npm run startr`
|
||||
- Start Gateway
|
||||
- `ts-node src/gateway/index.ts`
|
||||
- `npm run startg`
|
||||
- Start Bot
|
||||
- `ts-node src/bot/index.ts`
|
||||
|
||||
## Improvements
|
||||
|
||||
- Change configs.ts file to use an .env file.
|
||||
- `npm run startb`
|
||||
|
||||
6
template/bigbot/nodemon.json
Normal file
6
template/bigbot/nodemon.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"watch": "./src/**/*.ts",
|
||||
"ext ": "env,ts",
|
||||
"signal": "SIGKILL",
|
||||
"exec": "npm run build && node --experimental-specifier-resolution=node"
|
||||
}
|
||||
999
template/bigbot/package-lock.json
generated
999
template/bigbot/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,39 +2,41 @@
|
||||
"name": "dd-big-bot",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "nodemon -e ts --exec 'npm run start'",
|
||||
"start": "node --no-warnings dist/index.js",
|
||||
"devbg": "npx prisma generate && tsc --watch",
|
||||
"fmt": "prettier -w ./src",
|
||||
"dg": "ts-node src/gateway/index.ts",
|
||||
"dr": "ts-node src/rest/index.js",
|
||||
"db": "ts-node src/bot/index.ts",
|
||||
"tsc": "tsc",
|
||||
"tscw": "tsc --watch",
|
||||
"devr": "node dist/rest/index",
|
||||
"devg": "node dist/gateway/index",
|
||||
"devb": "node dist/bot/index"
|
||||
"devg": "nodemon --ignore ./src/bot/**/* --ignore ./src/rest/**/* --ignore ./dist/**/* -e ts dist/gateway/index.js",
|
||||
"devr": "nodemon --ignore ./src/bot/**/* --ignore ./src/gateway/**/* --ignore ./dist/**/* -e ts dist/rest/index.js",
|
||||
"devb": "nodemon --ignore ./src/rest/**/* --ignore ./src/gateway/**/* --ignore ./dist/**/* -e ts dist/bot/index.js",
|
||||
"type": "tsc --noEmit",
|
||||
"build": "swc src --out-dir dist",
|
||||
"startr": "node --experimental-specifier-resolution=node dist/rest/index.js",
|
||||
"startg": "node --experimental-specifier-resolution=node dist/gateway/index.js",
|
||||
"startb": "node --experimental-specifier-resolution=node dist/bot/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@influxdata/influxdb-client": "^1.29.0",
|
||||
"@prisma/client": "^3.15.2",
|
||||
"colorette": "^2.0.19",
|
||||
"discordeno": "^16.0.1",
|
||||
"dotenv": "^16.0.3",
|
||||
"express": "^4.18.1",
|
||||
"fastify": "^4.8.1",
|
||||
"nanoid": "^4.0.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"tslib": "^2.3.1",
|
||||
"node-fetch": "^3.2.10",
|
||||
"web-worker": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@swc/cli": "^0.1.57",
|
||||
"@swc/core": "^1.3.9",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/node": "^17.0.23",
|
||||
"@types/ws": "^8.5.3",
|
||||
"nodemon": "^2.0.15",
|
||||
"prettier": "2.6.2",
|
||||
"prisma": "^4.2.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.6.3"
|
||||
},
|
||||
"prettier": {
|
||||
@@ -45,4 +47,4 @@
|
||||
"semi": true,
|
||||
"printWidth": 120
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
import { InfluxDB } from "@influxdata/influxdb-client";
|
||||
import { INFLUX_BUCKET, INFLUX_ORG, INFLUX_TOKEN, INFLUX_URL } from "./configs.js";
|
||||
|
||||
const INFLUX_BUCKET = process.env.INFLUX_BUCKET as string
|
||||
const INFLUX_ORG = process.env.INFLUX_ORG as string
|
||||
const INFLUX_TOKEN = process.env.INFLUX_TOKEN as string
|
||||
const INFLUX_URL = process.env.INFLUX_URL as string
|
||||
|
||||
export const influxDB = INFLUX_URL && INFLUX_TOKEN ? new InfluxDB({ url: INFLUX_URL, token: INFLUX_TOKEN }) : undefined;
|
||||
export const Influx = influxDB?.getWriteApi(INFLUX_ORG, INFLUX_BUCKET);
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { Bot, Collection, createBot, createRestManager } from "discordeno";
|
||||
import enableHelpersPlugin from "discordeno/helpers-plugin";
|
||||
import { createLogger } from "discordeno/logger";
|
||||
import { DISCORD_TOKEN, INTENTS, REST_AUTHORIZATION, REST_URL } from "../configs.js";
|
||||
import { setupEventHandlers } from "./events/mod.js";
|
||||
import { MessageCollector } from "./utils/collectors.js";
|
||||
import { customizeInternals } from "./utils/internals/mod.js";
|
||||
import { INTENTS, REST_URL } from "../configs";
|
||||
import { setupEventHandlers } from "./events/mod";
|
||||
import { MessageCollector } from "./utils/collectors";
|
||||
import { customizeInternals } from "./utils/internals/mod";
|
||||
|
||||
const DISCORD_TOKEN = process.env.DISCORD_TOKEN as string
|
||||
const REST_AUTHORIZATION = process.env.REST_AUTHORIZATION as string
|
||||
|
||||
export const bot = enableHelpersPlugin(
|
||||
customizeBot(
|
||||
|
||||
@@ -10,11 +10,12 @@ import {
|
||||
InteractionResponseTypes,
|
||||
Member,
|
||||
Role,
|
||||
User,
|
||||
User
|
||||
} from "discordeno";
|
||||
import { bot, BotWithCustomProps } from "../../bot.js";
|
||||
import COMMANDS from "../../commands/mod.js";
|
||||
import { getLanguage, loadLanguage, serverLanguages, translate, translationKeys } from "../../languages/translate.js";
|
||||
import { InteractionWithCustomProps } from "../../typings/discordeno.js";
|
||||
import { Command, ConvertArgumentDefinitionsToArgs } from "../../utils/slash/createCommand.js";
|
||||
|
||||
function logCommand(
|
||||
@@ -22,11 +23,10 @@ function logCommand(
|
||||
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})`),
|
||||
@@ -36,7 +36,7 @@ function logCommand(
|
||||
bot.logger.info(`${command} by ${user} in ${guild} with MessageID: ${info.id}`);
|
||||
}
|
||||
|
||||
export async function executeSlashCommand(bot: BotWithCustomProps, interaction: Interaction) {
|
||||
export async function executeSlashCommand(bot: BotWithCustomProps, interaction: InteractionWithCustomProps) {
|
||||
const data = interaction.data;
|
||||
const name = data?.name as keyof typeof COMMANDS;
|
||||
|
||||
@@ -89,7 +89,7 @@ export async function executeSlashCommand(bot: BotWithCustomProps, interaction:
|
||||
}
|
||||
|
||||
/** Runs the inhibitors to see if a command is allowed to run. */
|
||||
export async function commandAllowed(interaction: Interaction, command: Command<any>) {
|
||||
export async function commandAllowed(interaction: InteractionWithCustomProps, command: Command<any>) {
|
||||
// CHECK WHETHER THE USER/GUILD IS VIP
|
||||
if (command.vipOnly) {
|
||||
// SETUP-DD-TEMP: Check if this server/user is a vip.
|
||||
@@ -149,21 +149,21 @@ function convertOptionValue(
|
||||
option: InteractionDataOption,
|
||||
translateOptions?: Record<string, string>,
|
||||
): [
|
||||
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));
|
||||
@@ -269,7 +269,7 @@ export function optionParser(
|
||||
[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
|
||||
interaction.data.options[0]!.options![0]!.name
|
||||
]: convertedOptions,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { InteractionTypes, MessageComponentTypes } from "discordeno";
|
||||
import { bot } from "../../bot.js";
|
||||
import { InteractionWithCustomProps } from "../../typings/discordeno.js";
|
||||
import { executeButtonClick } from "./button.js";
|
||||
import { executeSlashCommand } from "./command.js";
|
||||
import { executeModalSubmit } from "./modal.js";
|
||||
@@ -7,7 +8,7 @@ import { executeModalSubmit } from "./modal.js";
|
||||
export function setInteractionCreateEvent() {
|
||||
bot.events.interactionCreate = async function (_, interaction) {
|
||||
if (interaction.type === InteractionTypes.ApplicationCommand) {
|
||||
await executeSlashCommand(bot, interaction);
|
||||
await executeSlashCommand(bot, interaction as InteractionWithCustomProps);
|
||||
} else if (interaction.type === InteractionTypes.MessageComponent) {
|
||||
if (!interaction.data) return;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { setInteractionCreateEvent } from "./interactions/mod.js";
|
||||
import { setMessageCreateEvent } from "./messages/create.js";
|
||||
import { setRawEvent } from "./raw.js";
|
||||
import { setInteractionCreateEvent } from "./interactions/mod";
|
||||
import { setMessageCreateEvent } from "./messages/create";
|
||||
import { setRawEvent } from "./raw";
|
||||
|
||||
export function setupEventHandlers() {
|
||||
setInteractionCreateEvent();
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
import { DiscordGatewayPayload } from "discordeno";
|
||||
import Embeds from "discordeno/embeds";
|
||||
// ReferenceError: publishMessage is not defined
|
||||
// import Embeds from "discordeno/embeds";
|
||||
import dotenv from 'dotenv';
|
||||
import express from "express";
|
||||
import {
|
||||
BOT_ID,
|
||||
BUGS_ERRORS_REPORT_WEBHOOK,
|
||||
DEVELOPMENT,
|
||||
EVENT_HANDLER_AUTHORIZATION,
|
||||
EVENT_HANDLER_PORT,
|
||||
EVENT_HANDLER_URL,
|
||||
} from "../configs.js";
|
||||
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 as string
|
||||
const DEVELOPMENT = process.env.DEVELOPMENT as string
|
||||
const EVENT_HANDLER_AUTHORIZATION = process.env.EVENT_HANDLER_AUTHORIZATION as string
|
||||
const EVENT_HANDLER_PORT = process.env.EVENT_HANDLER_PORT as string
|
||||
|
||||
process
|
||||
.on("unhandledRejection", (error) => {
|
||||
const { id, token } = webhookURLToIDAndToken(BUGS_ERRORS_REPORT_WEBHOOK);
|
||||
@@ -28,6 +30,8 @@ process
|
||||
|
||||
if (!error) return;
|
||||
|
||||
// ReferenceError: publishMessage is not defined
|
||||
/*
|
||||
const embeds = new Embeds()
|
||||
.setDescription(["```js", error, "```"].join(`\n`))
|
||||
.setTimestamp()
|
||||
@@ -35,6 +39,7 @@ 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) => {
|
||||
const { id, token } = webhookURLToIDAndToken(BUGS_ERRORS_REPORT_WEBHOOK);
|
||||
@@ -50,13 +55,14 @@ process
|
||||
|
||||
if (!error) process.exit(1);
|
||||
|
||||
/*
|
||||
const embeds = new Embeds()
|
||||
.setDescription(["```js", error.stack, "```"].join(`\n`))
|
||||
.setTimestamp()
|
||||
.setFooter("Unhandled Exception Error Occurred");
|
||||
|
||||
// SEND ERROR TO THE LOG CHANNEL ON THE DEV SERVER
|
||||
await bot.helpers.sendWebhookMessage(bot.transformers.snowflake(id), token, { embeds }).catch(console.error);
|
||||
// SEND ERROR TO THE LOG CHANNEL ON THE DEV SERVER
|
||||
await bot.helpers.sendWebhookMessage(bot.transformers.snowflake(id), token, { embeds }).catch(console.error);
|
||||
*/
|
||||
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import Embeds from "discordeno/embeds";
|
||||
import { MISSING_TRANSLATION_WEBHOOK } from "../../configs.js";
|
||||
import { bot } from "../bot.js";
|
||||
import { webhookURLToIDAndToken } from "../utils/webhook.js";
|
||||
import english from "./english.js";
|
||||
import languages from "./languages.js";
|
||||
|
||||
const MISSING_TRANSLATION_WEBHOOK = process.env.MISSING_TRANSLATION_WEBHOOK as string;
|
||||
|
||||
/** This should hold the language names per guild id. <guildId, language> */
|
||||
export const serverLanguages = new Map<bigint, keyof typeof languages>();
|
||||
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
// This file allows you to tell typescript about any additions you have made to the internal discordeno objects.
|
||||
import { InteractionResponse, Message } from "discordeno";
|
||||
import { Interaction, InteractionResponse, Message } from "discordeno";
|
||||
|
||||
declare module "discordeno" {
|
||||
// We want to add something to the Interaction object.
|
||||
interface 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<Message | undefined>;
|
||||
}
|
||||
}
|
||||
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<Message | undefined>;
|
||||
}
|
||||
@@ -7,10 +7,11 @@ import {
|
||||
Member,
|
||||
PermissionStrings,
|
||||
Role,
|
||||
User,
|
||||
User
|
||||
} from "discordeno";
|
||||
import english from "../../languages/english.js";
|
||||
import { translationKeys } from "../../languages/translate.js";
|
||||
import { InteractionWithCustomProps } from "../../typings/discordeno.js";
|
||||
import { PermissionLevelHandlers } from "./permLevels.js";
|
||||
|
||||
export function createCommand<T extends readonly ArgumentDefinition[]>(command: Command<T>) {
|
||||
@@ -156,79 +157,79 @@ export type ConvertArgumentDefinitionsToArgs<T extends readonly ArgumentDefiniti
|
||||
UnionToIntersection<
|
||||
{
|
||||
[P in keyof T]: T[P] extends StringOptionalArgumentDefinition<infer N> // STRING
|
||||
? {
|
||||
// @ts-ignore TODO: fix this some day
|
||||
[_ in getName<N>]?: T[P]["choices"] extends readonly { name: string; value: string }[] // @ts-ignore
|
||||
? T[P]["choices"][number]["value"]
|
||||
: string;
|
||||
}
|
||||
: T[P] extends StringArgumentDefinition<infer N> ? {
|
||||
// @ts-ignore TODO: fix this some day
|
||||
[_ in getName<N>]: T[P]["choices"] extends readonly { name: string; value: string }[] // @ts-ignore
|
||||
? T[P]["choices"][number]["value"]
|
||||
: string;
|
||||
}
|
||||
// INTEGER
|
||||
: T[P] extends IntegerOptionalArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]?: T[P]["choices"] extends readonly { name: string; value: number }[] // @ts-ignore
|
||||
? T[P]["choices"][number]["value"]
|
||||
: number;
|
||||
}
|
||||
: T[P] extends IntegerArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]: T[P]["choices"] extends readonly { name: string; value: number }[] // @ts-ignore
|
||||
? T[P]["choices"][number]["value"]
|
||||
: number;
|
||||
}
|
||||
// BOOLEAN
|
||||
: T[P] extends BooleanOptionalArgumentDefinition<infer N> ? { [_ in getName<N>]?: boolean }
|
||||
: T[P] extends BooleanArgumentDefinition<infer N> ? { [_ in getName<N>]: boolean }
|
||||
// USER
|
||||
: T[P] extends UserOptionalArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]?: {
|
||||
user: User;
|
||||
member: Member;
|
||||
};
|
||||
}
|
||||
: T[P] extends UserArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]: {
|
||||
user: User;
|
||||
member: Member;
|
||||
};
|
||||
}
|
||||
// CHANNEL
|
||||
: T[P] extends ChannelOptionalArgumentDefinition<infer N> ? { [_ in getName<N>]?: Channel }
|
||||
: T[P] extends ChannelArgumentDefinition<infer N> ? { [_ in getName<N>]: Channel }
|
||||
// ROLE
|
||||
: T[P] extends RoleOptionalArgumentDefinition<infer N> ? { [_ in getName<N>]?: Role }
|
||||
: T[P] extends RoleArgumentDefinition<infer N> ? { [_ in getName<N>]: Role }
|
||||
// MENTIONABLE
|
||||
: T[P] extends MentionableOptionalArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]?:
|
||||
| Role
|
||||
| {
|
||||
user: User;
|
||||
member: Member;
|
||||
};
|
||||
}
|
||||
: T[P] extends MentionableArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]:
|
||||
| Role
|
||||
| {
|
||||
user: User;
|
||||
member: Member;
|
||||
};
|
||||
}
|
||||
// SUBCOMMAND
|
||||
: T[P] extends SubcommandArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]?: T[P]["options"] extends readonly ArgumentDefinition[] // @ts-ignore somehow this check does not work
|
||||
? ConvertArgumentDefinitionsToArgs<T[P]["options"]>
|
||||
: {};
|
||||
}
|
||||
// SUBCOMMANDGROUP
|
||||
: T[P] extends SubcommandGroupArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]?: ConvertArgumentDefinitionsToArgs<T[P]["options"]>;
|
||||
}
|
||||
: never;
|
||||
? {
|
||||
// @ts-ignore TODO: fix this some day
|
||||
[_ in getName<N>]?: T[P]["choices"] extends readonly { name: string; value: string }[] // @ts-ignore
|
||||
? T[P]["choices"][number]["value"]
|
||||
: string;
|
||||
}
|
||||
: T[P] extends StringArgumentDefinition<infer N> ? {
|
||||
// @ts-ignore TODO: fix this some day
|
||||
[_ in getName<N>]: T[P]["choices"] extends readonly { name: string; value: string }[] // @ts-ignore
|
||||
? T[P]["choices"][number]["value"]
|
||||
: string;
|
||||
}
|
||||
// INTEGER
|
||||
: T[P] extends IntegerOptionalArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]?: T[P]["choices"] extends readonly { name: string; value: number }[] // @ts-ignore
|
||||
? T[P]["choices"][number]["value"]
|
||||
: number;
|
||||
}
|
||||
: T[P] extends IntegerArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]: T[P]["choices"] extends readonly { name: string; value: number }[] // @ts-ignore
|
||||
? T[P]["choices"][number]["value"]
|
||||
: number;
|
||||
}
|
||||
// BOOLEAN
|
||||
: T[P] extends BooleanOptionalArgumentDefinition<infer N> ? { [_ in getName<N>]?: boolean }
|
||||
: T[P] extends BooleanArgumentDefinition<infer N> ? { [_ in getName<N>]: boolean }
|
||||
// USER
|
||||
: T[P] extends UserOptionalArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]?: {
|
||||
user: User;
|
||||
member: Member;
|
||||
};
|
||||
}
|
||||
: T[P] extends UserArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]: {
|
||||
user: User;
|
||||
member: Member;
|
||||
};
|
||||
}
|
||||
// CHANNEL
|
||||
: T[P] extends ChannelOptionalArgumentDefinition<infer N> ? { [_ in getName<N>]?: Channel }
|
||||
: T[P] extends ChannelArgumentDefinition<infer N> ? { [_ in getName<N>]: Channel }
|
||||
// ROLE
|
||||
: T[P] extends RoleOptionalArgumentDefinition<infer N> ? { [_ in getName<N>]?: Role }
|
||||
: T[P] extends RoleArgumentDefinition<infer N> ? { [_ in getName<N>]: Role }
|
||||
// MENTIONABLE
|
||||
: T[P] extends MentionableOptionalArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]?:
|
||||
| Role
|
||||
| {
|
||||
user: User;
|
||||
member: Member;
|
||||
};
|
||||
}
|
||||
: T[P] extends MentionableArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]:
|
||||
| Role
|
||||
| {
|
||||
user: User;
|
||||
member: Member;
|
||||
};
|
||||
}
|
||||
// SUBCOMMAND
|
||||
: T[P] extends SubcommandArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]?: T[P]["options"] extends readonly ArgumentDefinition[] // @ts-ignore somehow this check does not work
|
||||
? ConvertArgumentDefinitionsToArgs<T[P]["options"]>
|
||||
: {};
|
||||
}
|
||||
// SUBCOMMANDGROUP
|
||||
: T[P] extends SubcommandGroupArgumentDefinition<infer N> ? {
|
||||
[_ in getName<N>]?: ConvertArgumentDefinitionsToArgs<T[P]["options"]>;
|
||||
}
|
||||
: never;
|
||||
}[number]
|
||||
>
|
||||
>;
|
||||
@@ -244,7 +245,7 @@ export interface Command<T extends readonly ArgumentDefinition[]> {
|
||||
/** The options for the command, used for both slash and message commands. */
|
||||
// options?: ApplicationCommandOption[];
|
||||
options?: T;
|
||||
execute: (bot: Bot, data: Interaction, args: ConvertArgumentDefinitionsToArgs<T>) => unknown;
|
||||
execute: (bot: Bot, data: InteractionWithCustomProps, args: ConvertArgumentDefinitionsToArgs<T>) => unknown;
|
||||
subcommands?: Record<string, Omit<Command<any>, "subcommands"> & { group?: string }>;
|
||||
/** Whether the command should have a cooldown */
|
||||
cooldown?: {
|
||||
@@ -272,8 +273,8 @@ export interface Command<T extends readonly ArgumentDefinition[]> {
|
||||
acknowledge?: boolean;
|
||||
|
||||
permissionLevels?:
|
||||
| (keyof typeof PermissionLevelHandlers)[]
|
||||
| ((data: Interaction, command: Command<T>) => boolean | Promise<boolean>);
|
||||
| (keyof typeof PermissionLevelHandlers)[]
|
||||
| ((data: Interaction, command: Command<T>) => boolean | Promise<boolean>);
|
||||
botServerPermissions?: PermissionStrings[];
|
||||
botChannelPermissions?: PermissionStrings[];
|
||||
userServerPermissions?: PermissionStrings[];
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { ApplicationCommandOption, ApplicationCommandTypes, Bot } from "discordeno";
|
||||
import { DEV_SERVER_ID } from "../../../configs.js";
|
||||
import { prisma } from "../../../prisma.js";
|
||||
import { bot } from "../../bot.js";
|
||||
import COMMANDS from "../../commands/mod.js";
|
||||
import { serverLanguages, translate } from "../../languages/translate.js";
|
||||
import { 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
|
||||
|
||||
@@ -1,54 +1,12 @@
|
||||
import { getBotIdFromToken, Intents } from "discordeno";
|
||||
|
||||
// General Configurations
|
||||
/** Whether or not this process is a local development version. Change to false for the main production bot. */
|
||||
// SETUP-DD-TEMP: Change this to false in your server for production bot. Keep true in local testing.
|
||||
export const DEVELOPMENT = true;
|
||||
|
||||
/** The server id where you develop/test the bot. */
|
||||
// SETUP-DD-TEMP: Change the id to a server where you develop the bot privately.
|
||||
export const DEV_SERVER_ID: string = "";
|
||||
|
||||
/** The discord bot token, without the BOT prefix. */
|
||||
// SETUP-DD-TEMP: Add the bot token here.
|
||||
export const DISCORD_TOKEN = "";
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config()
|
||||
|
||||
/** The bot id, derived from the bot token. */
|
||||
export const BOT_ID = getBotIdFromToken(DISCORD_TOKEN);
|
||||
|
||||
// Bot Configurations
|
||||
/** The secret passcode that the bot code (event handler) is listening for. This is used to prevent someone else from trying to send malicious messages to your bot. */
|
||||
// SETUP-DD-TEMP: Add a secret passcode here.
|
||||
export const EVENT_HANDLER_AUTHORIZATION = "";
|
||||
|
||||
/** The port where the event handler is listening for events. */
|
||||
// SETUP-DD-TEMP: Set the desired port where events will be sent to be processed.
|
||||
export const EVENT_HANDLER_PORT = 8081;
|
||||
|
||||
/** The url where the bot code(event handler) will run. This is where the gateway will send its messages to. */
|
||||
// SETUP-DD-TEMP: Set the bot's url here.
|
||||
export const EVENT_HANDLER_URL = `http://localhost:${EVENT_HANDLER_PORT}`;
|
||||
|
||||
/** The full webhook url where the bot can send errors to alert you that the bot is missing translations. */
|
||||
// SETUP-DD-TEMP: Set a full discord webhook url here.
|
||||
export const MISSING_TRANSLATION_WEBHOOK = "";
|
||||
|
||||
/** The full webhook url where the bot can send errors to alert you that the bot is throwing errors. */
|
||||
// SETUP-DD-TEMP: Set a full discord webhook url here.
|
||||
export const BUGS_ERRORS_REPORT_WEBHOOK = "";
|
||||
|
||||
// Rest Proxy Configurations
|
||||
/** The authorization code that the REST proxy will check for to make sure the requests are coming from you. */
|
||||
// SETUP-DD-TEMP: Add a secret passcode here.
|
||||
export const REST_AUTHORIZATION = "";
|
||||
|
||||
/** The port that will run the REST proxy. */
|
||||
// SETUP-DD-TEMP: Choose the port number here that will be used for the REST proxy.
|
||||
export const REST_PORT = 8000;
|
||||
|
||||
/** The url where requests will be sent to from the bot. */
|
||||
// SETUP-DD-TEMP: Provide the url where you will host your REST proxy. If it is on the same server as others, you can use localhost but if it is on a separate server you should change this entirely.
|
||||
export const REST_URL = `http://localhost:${REST_PORT}`;
|
||||
export const BOT_ID = getBotIdFromToken(process.env.DISCORD_TOKEN as string);
|
||||
export const EVENT_HANDLER_URL = `http://${process.env.EVENT_HANDLER_HOST}:${process.env.EVENT_HANDLER_PORT}`;
|
||||
export const REST_URL = `http://${process.env.REST_HOST}:${process.env.REST_PORT}`;
|
||||
export const GATEWAY_URL = `http://${process.env.GATEWAY_HOST}:${process.env.GATEWAY_PORT}`;
|
||||
|
||||
// Gateway Proxy Configurations
|
||||
/** The gateway intents you would like to use. */
|
||||
@@ -69,40 +27,3 @@ export const INTENTS: Intents =
|
||||
Intents.GuildVoiceStates |
|
||||
Intents.GuildWebhooks |
|
||||
Intents.Guilds;
|
||||
|
||||
/** The amount of shards to start. Useful with multiple servers where each server is handling a portion of your bot. */
|
||||
// SETUP-DD-TEMP: To start all bots, leave it as undefined. Specify he number of shards this process should handle.
|
||||
export const TOTAL_SHARDS: number | undefined = undefined;
|
||||
|
||||
/** The amount of shards to start per worker. */
|
||||
// SETUP-DD-TEMP: Choose how many shards to start per worker. If you are not sure just stick to 16.
|
||||
export const SHARDS_PER_WORKER: number = 16;
|
||||
|
||||
/** The total amount of workers to start. Generally this should be equal to the number of cores your server has. */
|
||||
// SETUP-DD-TEMP: Choose how many workers to start up. If you are not sure, check how many cores your server has.
|
||||
export const TOTAL_WORKERS: number = 4;
|
||||
|
||||
/** The secret passcode that the gateway is listening for. This is used to prevent someone else from trying to send malicious messages to your bot. */
|
||||
// SETUP-DD-TEMP: Add a secret passcode here.
|
||||
export const GATEWAY_AUTHORIZATION = "";
|
||||
|
||||
/** The host where the gateway will run. Must follow https://nodejs.org/api/net.html#serverlistenoptions-callback. */
|
||||
// SETUP-DD-TEMP: Set the gateways's host here.
|
||||
export const GATEWAY_HOST = "localhost";
|
||||
|
||||
/** The port where the gateway will run. This is where the bot will send its messages to the gateway. */
|
||||
// SETUP-DD-TEMP: Set the gateways's port here.
|
||||
export const GATEWAY_PORT: number = 8080;
|
||||
|
||||
/** The url where the gateway will run. This is where the bot will send its messages to the gateway. */
|
||||
// SETUP-DD-TEMP: Set the gateways's url here.
|
||||
export const GATEWAY_URL = `${GATEWAY_HOST}:${GATEWAY_PORT}`;
|
||||
|
||||
// Database Configurations
|
||||
|
||||
/** These INFLUX configs are only if you wish to enable analytics. */
|
||||
// SETUP-DD-TEMP: This is optional. If you want to build analytics, add influxdb here.
|
||||
export const INFLUX_BUCKET = "";
|
||||
export const INFLUX_ORG = "";
|
||||
export const INFLUX_TOKEN = "";
|
||||
export const INFLUX_URL = "";
|
||||
|
||||
@@ -3,21 +3,21 @@ import { createLogger } from "discordeno/logger";
|
||||
import fastify from "fastify";
|
||||
import { nanoid } from "nanoid";
|
||||
import { Worker } from "worker_threads";
|
||||
import {
|
||||
DISCORD_TOKEN,
|
||||
EVENT_HANDLER_AUTHORIZATION,
|
||||
EVENT_HANDLER_URL,
|
||||
GATEWAY_AUTHORIZATION,
|
||||
GATEWAY_HOST,
|
||||
GATEWAY_PORT,
|
||||
INTENTS,
|
||||
REST_AUTHORIZATION,
|
||||
REST_URL,
|
||||
SHARDS_PER_WORKER,
|
||||
TOTAL_SHARDS,
|
||||
TOTAL_WORKERS,
|
||||
} from "../configs.js";
|
||||
import { WorkerCreateData, WorkerGetShardInfo, WorkerMessage, WorkerShardInfo, WorkerShardPayload } from "./worker.js";
|
||||
import { EVENT_HANDLER_URL, INTENTS, REST_URL } from "../configs.js";
|
||||
import { WorkerCreateData, WorkerGetShardInfo, WorkerMessage, WorkerShardInfo, WorkerShardPayload } from "./worker";
|
||||
|
||||
import dotenv from "dotenv";
|
||||
dotenv.config()
|
||||
|
||||
const DISCORD_TOKEN = process.env.DISCORD_TOKEN as string
|
||||
const EVENT_HANDLER_AUTHORIZATION = process.env.EVENT_HANDLER_AUTHORIZATION as string
|
||||
const GATEWAY_AUTHORIZATION = process.env.GATEWAY_AUTHORIZATION as string
|
||||
const GATEWAY_HOST = process.env.GATEWAY_HOST as string
|
||||
const GATEWAY_PORT = Number(process.env.GATEWAY_PORT as string)
|
||||
const REST_AUTHORIZATION = process.env.REST_AUTHORIZATION as string
|
||||
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)
|
||||
|
||||
async function main() {
|
||||
const log = createLogger({ name: "[MANAGER]" });
|
||||
@@ -45,7 +45,7 @@ async function main() {
|
||||
shardsPerWorker: SHARDS_PER_WORKER,
|
||||
totalWorkers: TOTAL_WORKERS,
|
||||
|
||||
handleDiscordPayload: () => {},
|
||||
handleDiscordPayload: () => { },
|
||||
|
||||
tellWorkerToIdentify: async (_gateway, workerId, shardId, _bucketId) => {
|
||||
log.info("TELL TO IDENTIFY", { workerId, shardId, _bucketId });
|
||||
@@ -81,7 +81,7 @@ async function main() {
|
||||
workerId,
|
||||
};
|
||||
|
||||
const worker = new Worker("./worker.js", {
|
||||
const worker = new Worker("./dist/gateway/worker.js", {
|
||||
workerData,
|
||||
});
|
||||
|
||||
|
||||
@@ -6,11 +6,12 @@ import {
|
||||
GatewayEventNames,
|
||||
Shard,
|
||||
ShardSocketRequest,
|
||||
ShardState,
|
||||
ShardState
|
||||
} from "discordeno";
|
||||
import { createLogger } from "discordeno/logger";
|
||||
import fetch from "node-fetch";
|
||||
import { parentPort, workerData } from "worker_threads";
|
||||
import { ManagerMessage } from "./index.js";
|
||||
import { ManagerMessage } from "./index";
|
||||
|
||||
if (!parentPort) {
|
||||
throw new Error("Parent port is null");
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import { Point } from "@influxdata/influxdb-client";
|
||||
import { BASE_URL, createRestManager } from "discordeno";
|
||||
import express, { Request, Response } from "express";
|
||||
import { Influx } from "../analytics";
|
||||
import { REST_URL } from '../configs';
|
||||
|
||||
import { Influx } from "../analytics.js";
|
||||
import { DISCORD_TOKEN, REST_AUTHORIZATION, REST_PORT, REST_URL } from "../configs.js";
|
||||
import dotenv from "dotenv";
|
||||
dotenv.config()
|
||||
|
||||
const DISCORD_TOKEN = process.env.DISCORD_TOKEN as string
|
||||
const REST_AUTHORIZATION = process.env.REST_AUTHORIZATION as string
|
||||
const REST_PORT = process.env.REST_PORT as string
|
||||
|
||||
const rest = createRestManager({
|
||||
token: DISCORD_TOKEN,
|
||||
@@ -55,6 +61,7 @@ if (Influx) {
|
||||
}, 30000);
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
rest.convertRestError = (errorStack, data) => {
|
||||
if (!data) return { message: errorStack.message };
|
||||
return { ...data, message: errorStack.message };
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"module": "CommonJS",
|
||||
"module": "es2020",
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"outDir": "./dist",
|
||||
@@ -10,7 +10,6 @@
|
||||
"importHelpers": true,
|
||||
"allowUnusedLabels": false,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
@@ -20,7 +19,15 @@
|
||||
"useUnknownInCatchVariables": false,
|
||||
"allowUnreachableCode": false,
|
||||
"skipLibCheck": true,
|
||||
"moduleResolution": "node"
|
||||
"moduleResolution": "node",
|
||||
},
|
||||
"include": ["./src/**/*", ".env"]
|
||||
}
|
||||
"include": [
|
||||
"./src/**/*",
|
||||
".env"
|
||||
],
|
||||
"ts-node": {
|
||||
"esm": true,
|
||||
"experimentalSpecifierResolution": "node",
|
||||
"swc": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user