Skip to content

Commit

Permalink
feat: macros
Browse files Browse the repository at this point in the history
  • Loading branch information
Cyberghxst committed Nov 10, 2024
1 parent a6d29d1 commit da71061
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 4 deletions.
11 changes: 11 additions & 0 deletions src/classes/AoiBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const {
EventstoFile
} = require("../utils/Constants.js");
const Database = require("./Database.js");
const { MacrosManager } = require("./Macros.js");
const CacheManager = require("./CacheManager.js");
const { CommandManager } = require("./Commands.js");
const { Group } = require("@aoijs/aoi.structures");
Expand Down Expand Up @@ -55,6 +56,7 @@ class BaseClient extends Client {
this.cacheManager = new CacheManager(this);

this.variableManager = new VariableManager(this);
this.macros = new MacrosManager();

if (
options.disableAoiDB !== true &&
Expand Down Expand Up @@ -119,6 +121,15 @@ class BaseClient extends Client {
loader.load(this.cmd, directory, debug);
}

/**
* Adds many macros to the manager.
* @param {import("..").MacroOptions[]} macros - The macros to be added.
* @returns {void}
*/
macro(...macros) {
this.macros.addMany([...macros]);
}

status(...statuses) {
for (const status of statuses) {
status.type =
Expand Down
20 changes: 16 additions & 4 deletions src/classes/Commands.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
const { hasMacros, resolveMacros } = require("./Macros");
const { Group } = require("@aoijs/aoi.structures");

class Command {
/**
* Creates a new instance of the `Command` class.
* @param {import("..").BaseCommand} data - The command data.
* @param {import("..").AoiClient} client - The AoiClient instance.
*/
constructor(data = {}, client) {
this.__client__ = client;
if (typeof data.code === "string") {
this.code = data.code;
} else {
if (typeof data.code !== "string") {
throw new TypeError(`Missing or invalid 'code' property in '${data.name}' command \n Path: '${data.__path__}'`);
}

this.__client__ = client;

if (hasMacros(client.macros.list(), data.code)) {
data.code = resolveMacros(client.macros.toArray(), data.code);
}

this.code = data.code;

Object.entries(data).forEach(([key, value]) => (this[key] = value));
this.functions = this.serializeFunctions();
this.codeLines = this.serializeCode();
Expand Down
109 changes: 109 additions & 0 deletions src/classes/Macros.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
class MacrosManager {
/**
* @type {Map<string, import("..").MacroOptions>}
*/
cache = new Map();

/**
* Adds a macro to the manager.
* @param {import("..").MacroOptions} macro - The macro to be added.
* @returns {this}
*/
add(macro) {
macro.name = macro.name.startsWith("#")
? macro.name.slice(1)
: macro.name;

this.cache.set(macro.name, macro);

return this;
}

/**
* Adds many macros to the manager.
* @param {import("..").MacroOptions[]} macros - The macros to be added.
* @returns {this}
*/
addMany(macros) {
for (const macro of macros) {
this.add(macro);
}
return this;
}

/**
* Get a macro.
* @param {string | ((macro: import("..").MacroOptions) => boolean)} name - The name of the macro.
* @returns {?import("..").MacroOptions}
*/
get(name) {
if (typeof name === "string") return this.cache.get(name) || null;

return this.toArray().find(name) || null;
}

/**
* Return the list of cached macro names.
* @returns {string[]}
*/
list() {
return [...this.cache.keys()];
}

/**
* Return an array of cached macros.
* @returns {import("..").MacroOptions[]}
*/
toArray() {
return [...this.cache.values()];
}
};

/**
* Creates a pattern to match the cached macros.
* @param {string[]} names - The names of the macros.
* @returns {RegExp}
*/
function createMacrosPattern(names) {
return new RegExp(`#(${names.join("|")})`, "g");
};

/**
* Check whether the given code has macros inside.
* @param {string[]} names - The names of the cached macros.
* @param {string} code - The code to be tested.
* @returns {boolean}
*/
function hasMacros(names, code) {
return Array.isArray(code.match(createMacrosPattern(names)))
};

/**
* Resolve the macros in the command code with actual code.
* @param {import("..").MacroOptions[]} macros - The cached macros.
* @param {string} code - The code to be resolved.
* @returns {string}
*/
function resolveMacros(macros, code) {
const matchedMacros = [...new Set(code.match(createMacrosPattern(macros.map(m => m.name))) ?? [])];
let newCode = code;

for (const matchedMacro of matchedMacros) {
newCode = newCode.replace(
createMacrosPattern(
[matchedMacro.slice(1)]
),
macros.find(
macro => macro.name === matchedMacro.slice(1)
)?.code || ""
);
}

return newCode;
};

module.exports = {
hasMacros,
MacrosManager,
resolveMacros
};
40 changes: 40 additions & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,12 @@ export declare class BaseClient extends Client {
interactionManager: InteractionManager;
cacheManager: CacheManager;
variableManager: any;
macros: MacrosManager;
prefix: string | string[];
db: KeyValue | Transmitter;
statuses: Group;
constructor(options: ClientOptions);
macro(...macros: MacroOptions[]): void;
status(...statuses: StatusOption[]): void;
loadCommands(directory: string, debug?: boolean): void;
variables(data: Record<string, unknown>, table?: string): void;
Expand Down Expand Up @@ -534,4 +536,42 @@ export interface Data<T extends Record<string, unknown> = Record<string, unknown
interpreter: Interpreter;
client: AoiClient;
embed: EmbedBuilder;
}

/**
* An structure representing a macro.
*/
export interface MacroOptions {
/**
* The name of this macro (without #).
*/
name: string;
/**
* The code of this macro.
*/
code: string;
}

export declare class MacrosManager {
cache: Map<string, MacroOptions>;
/**
* Adds a macro to the manager.
*/
add(macro: MacroOptions): this;
/**
* Adds many macros to the manager.
*/
addMany(macros: MacroOptions[]): this;
/**
* Get a macro.
*/
get(name: string | ((macro: MacroOptions) => boolean)): MacroOptions | null;
/**
* Return the list of cached macro names.
*/
list(): string[];
/**
* Return an array of cached macros.
*/
toArray(): MacroOptions[];
}

0 comments on commit da71061

Please sign in to comment.