diff --git a/.gitignore b/.gitignore index 2c45399..05833ae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target/ -node_modules/ \ No newline at end of file +node_modules/ +config/discord-bot.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index b6f94cc..0ba7509 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,10 +5,10 @@ "name": "Build and Run", "type": "node", "request": "launch", - "program": "${workspaceFolder}/target/_.js", + "program": "${workspaceFolder}/target/_.cjs", "preLaunchTask": "build", "skipFiles": ["/**"], - "outFiles": ["${workspaceFolder}/target/**/*.js"] + "outFiles": ["${workspaceFolder}/target/**/*.cjs"] } ], "tasks": [ diff --git a/build/api.js b/build/api.js index 446bf20..afa6360 100644 --- a/build/api.js +++ b/build/api.js @@ -31,7 +31,7 @@ const CompileToTargetError = { export const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); export const target_directory_path = path.join(__dirname, "../target/"); -export const target_file_name = "_.js"; +export const target_file_name = "_.cjs"; export const target_path = path.join(target_directory_path, target_file_name); export const package_path = path.join(__dirname, "../package.json"); @@ -129,6 +129,8 @@ export function compile_to_target() { bundle: true, entryPoints: [ package_json.main ], outfile: target_path, - platform: "node" + platform: "node", + format: "cjs", + external: [ "deasync" ] }); } \ No newline at end of file diff --git a/config/discord-bot.ts b/config/discord-bot.ts index 1f98c49..0ccf373 100644 --- a/config/discord-bot.ts +++ b/config/discord-bot.ts @@ -1,4 +1,4 @@ -import * config from "../source/discord-bot/config"; +import * as config from "../source/discord-bot/config"; export const data: config.Config_Interface = { discord: { diff --git a/package-lock.json b/package-lock.json index a71e04c..4e19b62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,8 @@ "dependencies": { "@discordjs/builders": "^1.6.5", "@discordjs/rest": "^2.0.1", + "@types/deasync": "^0.1.2", + "deasync": "^0.1.28", "discord.js": "^14.13.0", "esbuild": "^0.19.3", "mongoose": "^7.5.2" @@ -157,6 +159,11 @@ "npm": ">=7.0.0" } }, + "node_modules/@types/deasync": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@types/deasync/-/deasync-0.1.2.tgz", + "integrity": "sha512-sCBFlGCEmZMPS06wdnQELcYzyUYio2K1Hp6g0fjJSKP1jkGKQpIdjRNUQAvdSCCJCWxIMCkX2CL7pi4BCm8Ydg==" + }, "node_modules/@types/node": { "version": "20.6.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.2.tgz", @@ -193,6 +200,14 @@ "npm": ">=7.0.0" } }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, "node_modules/bson": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.0.tgz", @@ -212,6 +227,19 @@ "node": ">=10.16.0" } }, + "node_modules/deasync": { + "version": "0.1.28", + "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.28.tgz", + "integrity": "sha512-QqLF6inIDwiATrfROIyQtwOQxjZuek13WRYZ7donU5wJPLoP67MnYxA6QtqdvdBy2mMqv5m3UefBVdJjvevOYg==", + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^1.7.1" + }, + "engines": { + "node": ">=0.11.0" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -303,6 +331,11 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, "node_modules/ip": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", @@ -431,6 +464,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==" + }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", diff --git a/package.json b/package.json index 2e72986..abf21a4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "poixpixel-discord-bot", "version": "1.0.0", - "main": "./source/discord-bot/discord-bot.ts", + "main": "./source/discord-bot.ts", "author": "Poixpixel", "license": "ISC", "type": "module", @@ -13,6 +13,8 @@ "dependencies": { "@discordjs/builders": "^1.6.5", "@discordjs/rest": "^2.0.1", + "@types/deasync": "^0.1.2", + "deasync": "^0.1.28", "discord.js": "^14.13.0", "esbuild": "^0.19.3", "mongoose": "^7.5.2" @@ -21,4 +23,4 @@ "@types/node": "^20.6.1", "typescript": "^5.2.2" } -} \ No newline at end of file +} diff --git a/source/config.ts b/source/config.ts new file mode 100644 index 0000000..e6679b7 --- /dev/null +++ b/source/config.ts @@ -0,0 +1,27 @@ +import * as l_util from "./util"; + +export class Config { + public readonly defaulted: Config_Interface; + #real: Config_Interface; + + public events = { + change: [] as unknown as (() => {})[] + }; + + constructor( + defaulted: Config_Interface, + real: Config_Interface + ) { + this.defaulted = defaulted; + this.#real = l_util.object.merge.recursive_merge(defaulted, real); + } + + public set real(new_real: Config_Interface) { + this.#real = l_util.object.merge.recursive_merge(this.defaulted, new_real); + this.events.change.forEach((event_callback: any) => event_callback()); + } + + public get real() { + return this.#real; + } +} \ No newline at end of file diff --git a/source/discord-bot.ts b/source/discord-bot.ts new file mode 100644 index 0000000..fc2be33 --- /dev/null +++ b/source/discord-bot.ts @@ -0,0 +1,24 @@ +import * as config from "./discord-bot/config"; +import * as l_config from "./config"; +import * as l_discord from "./discord"; +import * as l_util from "./util"; +import * as c_discord_bot from "../config/discord-bot"; + +export class DiscordBot extends l_discord.Bot { + public static config: l_config.Config; + public static discord_bot: l_discord.Bot; + + static main( + p_config: config.Config_Interface + ) { + this.config = new l_config.Config( + config.defaulted, + p_config + ); + + this.discord_bot = new l_discord.Bot(this.config.real.discord); + this.discord_bot.running = true; + } +} + +DiscordBot.main(c_discord_bot.data); \ No newline at end of file diff --git a/source/discord-bot/commands/ping.ts b/source/discord-bot/commands/ping.ts deleted file mode 100644 index e69de29..0000000 diff --git a/source/discord-bot/config.ts b/source/discord-bot/config.ts index b82dab5..7fcd9ce 100644 --- a/source/discord-bot/config.ts +++ b/source/discord-bot/config.ts @@ -1,10 +1,15 @@ +import * as l_discord from "../discord"; + export interface Config_Interface { - discord: { - api_key: string; - application_client_id: string; - guild_id: string; - }; - storage: { - - } + discord: l_discord.Config_Interface; + storage?: {} } + +export const defaulted: Config_Interface = { + discord: { + api_key: "", + application_client_id: "", + guild_id: "" + }, + storage: {} +} \ No newline at end of file diff --git a/source/discord-bot/discord-bot.ts b/source/discord-bot/discord-bot.ts deleted file mode 100644 index 9c34517..0000000 --- a/source/discord-bot/discord-bot.ts +++ /dev/null @@ -1,2 +0,0 @@ -import * as config from "./config"; -import * as discord from "./discord"; \ No newline at end of file diff --git a/source/discord-bot/discord.ts b/source/discord-bot/discord.ts deleted file mode 100644 index e69de29..0000000 diff --git a/source/discord-bot/discord/command.ts b/source/discord-bot/discord/command.ts deleted file mode 100644 index e69de29..0000000 diff --git a/source/discord.ts b/source/discord.ts new file mode 100644 index 0000000..002479d --- /dev/null +++ b/source/discord.ts @@ -0,0 +1,66 @@ +import * as discord from "discord.js"; +import * as l_config from "./config"; +import * as l_util from "./util"; +import * as deasync from "deasync"; + +export interface Config_Interface { + api_key?: string; + application_client_id?: string; + guild_id?: string; +} + +const defaulted_config: Config_Interface = { + api_key: "", + application_client_id: "", + guild_id: "" +} + +export class Bot extends l_util.Runable { + public readonly config: l_config.Config; + public readonly client: discord.Client; + + constructor( + config: Config_Interface + ) { + super(); + + this.config = new l_config.Config( + defaulted_config, + config + ); + + let intents: discord.GatewayIntentBits[] = []; + Object.keys(discord.GatewayIntentBits).forEach((intent_key: any) => intents.push(discord.GatewayIntentBits[intent_key] as any)); + + this.client = new discord.Client({ + intents + }); + } + + on_run(): void { + let done = false; + let error = false; + + this.client.once(discord.Events.ClientReady, () => { + done = true; + }); + + this.client.login(this.config.real.api_key); + + while (!done) { deasync.sleep(100); } + + if (error) { + console.error("FAILED TO LOGIN"); + } else { + console.log("ONLINE"); + } + } + + on_terminate(): void { + + } +} + +export class Command { + +} \ No newline at end of file diff --git a/source/util.ts b/source/util.ts new file mode 100644 index 0000000..57cd6b5 --- /dev/null +++ b/source/util.ts @@ -0,0 +1,17 @@ +export * as object from "./util/object"; + +export abstract class Runable { + #running = false; + + abstract on_run(): void; + abstract on_terminate(): void; + + public set running(value: boolean) { + if (value && !this.#running) this.on_run(); + else if (!value && this.#running) this.on_terminate(); + } + + public get running() { + return this.#running; + } +} \ No newline at end of file diff --git a/source/util/object.ts b/source/util/object.ts new file mode 100644 index 0000000..2dd1d6c --- /dev/null +++ b/source/util/object.ts @@ -0,0 +1 @@ +export * as merge from "./object/merge"; \ No newline at end of file diff --git a/source/util/object/merge.ts b/source/util/object/merge.ts new file mode 100644 index 0000000..28d8696 --- /dev/null +++ b/source/util/object/merge.ts @@ -0,0 +1,16 @@ +export function recursive_merge( + defaulted: any, + target: any +) { + let output = defaulted; + + Object.keys(target).forEach((target_key) => { + if (typeof target_key != "object") { + output[target_key] = target[target_key]; + } else { + output[target_key] = recursive_merge(defaulted[target_key], target[target_key]); + } + }); + + return output; +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index f4255fb..54a61c8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -26,7 +26,7 @@ /* Modules */ "module": "esnext", /* Specify what module code is generated. */ - "rootDir": "./src", /* Specify the root folder within your source files. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ @@ -55,7 +55,7 @@ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - "outDir": "./dist", /* Specify an output folder for all emitted files. */ + // "outDir": "./dist", /* Specify an output folder for all emitted files. */ // "removeComments": true, /* Disable emitting comments. */ // "noEmit": true, /* Disable emitting files from a compilation. */ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ diff --git a/yarn.lock b/yarn.lock index 320ab8f..c395e6c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -92,6 +92,11 @@ resolved "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.1.tgz" integrity sha512-BxcYGzgEsdlG0dKAyOm0ehLGm2CafIrfQTZGWgkfKYbj+pNNsorZ7EotuZukc2MT70E0UbppVbtpBrqpzVzjNA== +"@types/deasync@^0.1.2": + version "0.1.2" + resolved "https://registry.npmjs.org/@types/deasync/-/deasync-0.1.2.tgz" + integrity sha512-sCBFlGCEmZMPS06wdnQELcYzyUYio2K1Hp6g0fjJSKP1jkGKQpIdjRNUQAvdSCCJCWxIMCkX2CL7pi4BCm8Ydg== + "@types/node@*", "@types/node@^20.6.1": version "20.6.2" resolved "https://registry.npmjs.org/@types/node/-/node-20.6.2.tgz" @@ -122,6 +127,13 @@ resolved "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.2.2.tgz" integrity sha512-HIzRG7sy88UZjBJamssEczH5q7t5+axva19UbZLO6u0ySbYPrwzWiXBcC0WuHyhKKoeCyneH+FvYzKQq/zTtkQ== +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + bson@^5.4.0: version "5.5.0" resolved "https://registry.npmjs.org/bson/-/bson-5.5.0.tgz" @@ -134,6 +146,14 @@ busboy@^1.6.0: dependencies: streamsearch "^1.1.0" +deasync@^0.1.28: + version "0.1.28" + resolved "https://registry.npmjs.org/deasync/-/deasync-0.1.28.tgz" + integrity sha512-QqLF6inIDwiATrfROIyQtwOQxjZuek13WRYZ7donU5wJPLoP67MnYxA6QtqdvdBy2mMqv5m3UefBVdJjvevOYg== + dependencies: + bindings "^1.5.0" + node-addon-api "^1.7.1" + debug@4.x: version "4.3.4" resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" @@ -199,6 +219,11 @@ fast-deep-equal@^3.1.3: resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + ip@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz" @@ -283,6 +308,11 @@ ms@2.1.3: resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +node-addon-api@^1.7.1: + version "1.7.2" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz" + integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg== + punycode@^2.1.1: version "2.3.0" resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz"