Skip to content

Commit

Permalink
lol
Browse files Browse the repository at this point in the history
  • Loading branch information
catplvsplus committed Jul 17, 2024
1 parent 176e3bf commit cd3c9fa
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 127 deletions.
4 changes: 2 additions & 2 deletions example/shards.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ command.name('').description('The options below are passed to reciple cli shards

process.chdir(cli.cwd);

loadEnv({ path: cli.options.env });
loadEnv({ path: cli.flags.env });

const config = (await ConfigReader.readConfigJS(cli.options.config ?? 'reciple.mjs')).config;
const config = (await ConfigReader.readConfigJS(cli.flags.config ?? 'reciple.mjs')).config;
const logsFolder = process.env.LOGS_FOLDER ?? path.join(process.cwd(), ((typeof config.logger?.logToFile !== 'function' ? config.logger?.logToFile.logsFolder : null) ?? 'logs'));

const logger = await (await createLogger({
Expand Down
59 changes: 16 additions & 43 deletions packages/reciple/src/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,28 @@

import { ContextMenuCommandBuilder, Logger, MessageCommandBuilder, SlashCommandBuilder, buildVersion } from '@reciple/core';
import { createLogger, addEventListenersToClient } from './utils/logger.js';
import { type ProcessInformation, RecipleClient, findModules } from './index.js';
import { command, cli, cliVersion, updateChecker } from './utils/cli.js';
import { RecipleClient, findModules, moduleFilesFilter } from './index.js';
import { cli, cliVersion, updateChecker } from './utils/cli.js';
import { setTimeout as setTimeoutAsync } from 'node:timers/promises';
import { existsAsync, resolveEnvProtocol } from '@reciple/utils';
import { parentPort, threadId } from 'node:worker_threads';
import { existsAsync } from '@reciple/utils';
import { parentPort } from 'node:worker_threads';
import { ConfigReader } from './classes/Config.js';
import { config as loadEnv } from 'dotenv';
import { mkdir } from 'node:fs/promises';
import { kleur } from 'fallout-utility';
import path from 'node:path';
import semver from 'semver';
import { CLI } from './classes/CLI.js';

command.parse();
await cli.parse();

if (!await existsAsync(cli.cwd)) await mkdir(cli.cwd, { recursive: true });

if (cli.cwd !== cli.nodeCwd || parentPort === null) {
process.chdir(cli.cwd);
cli.isCwdUpdated = true;
}

loadEnv({ path: cli.options.env });

let configPaths = [path.resolve('./reciple.mjs'), path.resolve('./reciple.js')];
if ((cli.cwd !== cli.processCwd && !cli.isCwdUpdated) || parentPort === null) process.chdir(cli.cwd);

const configPath = path.resolve(cli.options.config ?? 'reciple.mjs');
const isCustomPath = !configPaths.includes(configPath) || !!cli.options.config;

if (!isCustomPath) {
configPaths = configPaths.filter(p => p !== configPath);
configPaths.unshift(configPath);
} else {
configPaths = [configPath];
}
loadEnv({ path: cli.flags.env });

const configPaths = ConfigReader.resolveConfigPaths(path.resolve(cli.flags.config ?? 'reciple.mjs'))
const config = await ConfigReader.readConfigJS({ paths: configPaths }).then(c => c.config);
const logger = config.logger instanceof Logger
? config.logger
Expand All @@ -46,30 +33,25 @@ const logger = config.logger instanceof Logger

global.logger = logger ?? undefined;

if (cli.options.setup) process.exit(0);
if (cli.flags.setup) process.exit(0);
if (cli.shardmode) config.applicationCommandRegister = { ...config.applicationCommandRegister, enabled: false };
if (cli.options.token) config.token = resolveEnvProtocol(cli.options.token) ?? config.token;

config.token = cli.token ?? config.token;

const processErrorHandler = (err: any) => logger?.error(err);

process.once('uncaughtException', processErrorHandler);
process.once('unhandledRejection', processErrorHandler);

process.on('warning', warn => logger?.warn(warn));

if (cli.shardmode) {
const message: ProcessInformation = { type: 'ProcessInfo', pid: process.pid, threadId, log: cli.logPath };

if (parentPort) parentPort.postMessage(message);
if (process.send) process.send(message);
}
if (cli.shardmode) await cli.sendShardProcessInfo();

if (config.version && !semver.satisfies(cliVersion, config.version)) {
logger?.error(`Your config version doesn't support Reciple CLI v${cliVersion}`);
process.exit(1);
}

logger?.info(`Starting Reciple client v${buildVersion} - ${new Date()}`);
logger?.info(`Starting Reciple client v${buildVersion} - ${new Date().toISOString()}`);

const client = new RecipleClient(config);
global.reciple = client;
Expand All @@ -78,10 +60,8 @@ client.setLogger(logger);

addEventListenersToClient(client);

const moduleFilesFilter = (file: string) => file.endsWith('.js') || file.endsWith('.cjs') || file.endsWith('.mjs');

const modules = await client.modules.resolveModuleFiles({
files: await findModules(config.modules, (f) => moduleFilesFilter(f)),
files: await findModules(config.modules, moduleFilesFilter),
disableVersionCheck: config.modules?.disableModuleVersionCheck
});

Expand Down Expand Up @@ -125,14 +105,7 @@ client.once('ready', async () => {

process.stdin.resume();

process.once('SIGHUP', unloadModulesAndStopProcess);
process.once('SIGINT', unloadModulesAndStopProcess);
process.once('SIGQUIT', unloadModulesAndStopProcess);
process.once('SIGABRT',unloadModulesAndStopProcess);
process.once('SIGALRM', unloadModulesAndStopProcess);
process.once('SIGTERM', unloadModulesAndStopProcess);
process.once('SIGBREAK', unloadModulesAndStopProcess);
process.once('SIGUSR2', unloadModulesAndStopProcess);
CLI.addExitListener(unloadModulesAndStopProcess);

client.on('interactionCreate', interaction => {
if (interaction.isContextMenuCommand()) {
Expand Down
158 changes: 158 additions & 0 deletions packages/reciple/src/classes/CLI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import { buildVersion } from '@reciple/core';
import { resolveEnvProtocol } from '@reciple/utils';
import { Command } from 'commander';
import type { PackageJson } from 'fallout-utility';
import path from 'path';
import { isMainThread, parentPort, threadId } from 'worker_threads';
import type { ProcessInformation } from '../exports.js';

export interface CLIOptions {
packageJSON: PackageJson;
binPath: string;
logPath?: string;
cwd?: string;
}

export interface CLIFlags {
version?: string;
token?: string;
config?: string;
debugmode?: boolean;
yes?: boolean;
env?: string;
shardmode?: boolean;
setup?: boolean;
[k: string]: any;
}

export class CLI {
public packageJSON: PackageJson;
public processCwd: string;
public commander: Command;
public binPath: string;
public logPath?: string;

get name() {
return this.packageJSON.name!;
}

get description() {
return this.packageJSON.description!;
}

get version() {
return this.packageJSON.version!;
}

get args() {
return this.commander.args;
}

get flags() {
return this.commander.opts<CLIFlags>();
}

/**
* @deprecated Use `.flags` instead
*/
get options() {
return this.flags;
}

get cwd() {
return this.args[0]
? path.isAbsolute(this.args[0]) ? this.args[0] : path.join(this.processCwd, this.args[0])
: process.cwd();
}

get shardmode() {
return !!(this.options.shardmode ?? process.env.SHARDMODE);
}

get threadId() {
return !isMainThread && parentPort !== undefined ? threadId : undefined;
}

get isCwdUpdated() {
return process.cwd() !== this.processCwd;
}

/**
* @deprecated Use `.processCwd` instead
*/
get nodeCwd() {
return this.processCwd;
}

get token() {
return (this.flags.token && resolveEnvProtocol(this.flags.token)) || null;
}

constructor(options: CLIOptions) {
this.packageJSON = options.packageJSON;
this.processCwd = options.cwd ?? process.cwd();
this.commander = new Command();
this.binPath = options.binPath;
this.logPath = options.logPath;

this.commander
.name(this.name)
.description(this.description)
.version(`reciple: ${this.version}\n@reciple/client: ${buildVersion}`, '-v, --version')
.argument('[cwd]', 'Change the current working directory')
.option('-t, --token <token>', 'Replace used bot token')
.option('-c, --config <dir>', 'Set path to a config file')
.option('-D, --debugmode', 'Enable debug mode')
.option('-y, --yes', 'Agree to all Reciple confirmation prompts')
.option('--env <file>', '.env file location')
.option('--shardmode', 'Modifies some functionalities to support sharding')
.option('--setup', 'Create required config without starting the bot')
.allowUnknownOption(true);
}

public async parse(): Promise<this> {
await this.commander.parseAsync();

return this;
}

public async sendShardProcessInfo(): Promise<void> {
const message: ProcessInformation = { type: 'ProcessInfo', pid: process.pid, threadId, log: cli.logPath };

if (parentPort) parentPort.postMessage(message);
if (process.send) process.send(message);
}

public static addExitListener(listener: (signal: NodeJS.Signals) => any, once?: boolean): void {
if (!once) {
process.on('SIGHUP', listener);
process.on('SIGINT', listener);
process.on('SIGQUIT', listener);
process.on('SIGABRT', listener);
process.on('SIGALRM', listener);
process.on('SIGTERM', listener);
process.on('SIGBREAK', listener);
process.on('SIGUSR2', listener);
} else {
process.once('SIGHUP', listener);
process.once('SIGINT', listener);
process.once('SIGQUIT', listener);
process.once('SIGABRT', listener);
process.once('SIGALRM', listener);
process.once('SIGTERM', listener);
process.once('SIGBREAK', listener);
process.once('SIGUSR2', listener);
}
}

public static removeExitListener(listener: (signal: NodeJS.Signals) => any): void {
process.removeListener('SIGHUP', listener);
process.removeListener('SIGINT', listener);
process.removeListener('SIGQUIT', listener);
process.removeListener('SIGABRT', listener);
process.removeListener('SIGALRM', listener);
process.removeListener('SIGTERM', listener);
process.removeListener('SIGBREAK', listener);
process.removeListener('SIGUSR2', listener);
}
}
15 changes: 15 additions & 0 deletions packages/reciple/src/classes/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,19 @@ export class ConfigReader {

return file;
}

public static resolveConfigPaths(configPath: string): string[] {
let configPaths = [path.resolve('./reciple.mjs'), path.resolve('./reciple.js')];

const isCustomPath = !configPaths.includes(configPath) || !!cli.flags.config;

if (!isCustomPath) {
configPaths = configPaths.filter(p => p !== configPath);
configPaths.unshift(configPath);
} else {
configPaths = [configPath];
}

return configPaths;
}
}
5 changes: 3 additions & 2 deletions packages/reciple/src/exports.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@

export * from './classes/CLI.js';
export * from './classes/Config.js';
export * from './utils/modules.js';
export * from './utils/logger.js';
export * from './utils/cli.js';
export * from './utils/logger.js';
export * from './utils/modules.js';

export interface ProcessInformation {
type: 'ProcessInfo';
Expand Down
Loading

0 comments on commit cd3c9fa

Please sign in to comment.