diff --git a/backend/package-lock.json b/backend/package-lock.json index b1d6d1891..4ca2b90b3 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.1", "dependencies": { "@silvia-odwyer/photon-node": "^0.3.1", + "baseroo": "^1.2.0", "bufferutil": "^4.0.3", "clinic": "^13.0.0", "cors": "^2.8.5", @@ -1528,6 +1529,14 @@ "node": ">=6.0.0" } }, + "node_modules/baseroo": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/baseroo/-/baseroo-1.2.0.tgz", + "integrity": "sha512-sRLKZGqz42S+BB5uX1OGLwFB3r7a1GlL09qwd+xtb0jAiiSOHPLf/IHu/CL8NcboizJx79SOs9X7K4c8qbfXlw==", + "dependencies": { + "make-error": "^1.3.6" + } + }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -5799,6 +5808,11 @@ "semver": "bin/semver.js" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, "node_modules/manage-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/manage-path/-/manage-path-2.0.0.tgz", diff --git a/backend/package.json b/backend/package.json index 2ff53482a..50bf6a30c 100644 --- a/backend/package.json +++ b/backend/package.json @@ -30,6 +30,7 @@ }, "dependencies": { "@silvia-odwyer/photon-node": "^0.3.1", + "baseroo": "^1.2.0", "bufferutil": "^4.0.3", "clinic": "^13.0.0", "cors": "^2.8.5", diff --git a/backend/src/plugins/Tags/templateFunctions.ts b/backend/src/plugins/Tags/templateFunctions.ts index ebf1415a9..d30657e88 100644 --- a/backend/src/plugins/Tags/templateFunctions.ts +++ b/backend/src/plugins/Tags/templateFunctions.ts @@ -149,6 +149,13 @@ export const TemplateFunctions: TemplateFunction[] = [ arguments: ["number"], examples: ["floor(1.2345)"], }, + { + name: "abs", + description: "Returns the absolute of a number", + returnValue: "number", + arguments: ["number"], + examples: ["abs(-1.2345)"], + }, { name: "add", description: "Adds two or more numbers", @@ -177,6 +184,20 @@ export const TemplateFunctions: TemplateFunction[] = [ arguments: ["number1", "number2", "..."], examples: ["div(6, 2)"], }, + { + name: "sqrt", + description: "Calculates the square root of a number", + returnValue: "number", + arguments: ["number"], + examples: ["sqrt(5)"], + }, + { + name: "cbrt", + description: "Calculates the cubic root of a number", + returnValue: "number", + arguments: ["number"], + examples: ["cbrt(50)"], + }, { name: "exp", description: "Raises a number to the power of another number", @@ -184,6 +205,99 @@ export const TemplateFunctions: TemplateFunction[] = [ arguments: ["base", "power"], examples: ["exp(2, 3)"], }, + { + name: "sin", + description: "Returns the sine of a number in radians", + returnValue: "number", + arguments: ["radians"], + examples: ["sin(2)"], + }, + { + name: "sinh", + description: "Returns the hyperbolic sine of a number", + returnValue: "number", + arguments: ["number"], + examples: ["sinh(1)"], + }, + { + name: "tan", + description: "Returns the tangent of a number in radians", + returnValue: "number", + arguments: ["radians"], + examples: ["tan(1.5)"], + }, + { + name: "tanh", + description: "Returns the hyperbolic tangent of a number in radians", + returnValue: "number", + arguments: ["radians"], + examples: ["tanh(1.5)"], + }, + { + name: "cos", + description: "Returns the cosine of a number in radians", + returnValue: "number", + arguments: ["radians"], + examples: ["cos(1.5)"], + }, + { + name: "cosh", + description: "Returns the hyperbolic cosine of a number in radians", + returnValue: "number", + arguments: ["radians"], + examples: ["cosh(1.5)"], + }, + { + name: "hypot", + description: "Returns the square root of the sum of squares of it's arguments", + returnValue: "number", + arguments: ["number1", "number2", "..."], + examples: ["hypot(3, 4, 5, 6)"], + }, + { + name: "log", + description: "Returns the base e logarithm of a number", + returnValue: "number", + arguments: ["number"], + examples: ["log(3)"], + }, + { + name: "log2", + description: "Returns the base 2 logarithm of a number", + returnValue: "number", + arguments: ["number"], + examples: ["log2(3)"], + }, + { + name: "log10", + description: "Returns the base 10 logarithm of a number", + returnValue: "number", + arguments: ["number"], + examples: ["log10(3)"], + }, + { + name: "log1p", + description: "Returns the base e logarithm of a 1 + number", + returnValue: "number", + arguments: ["number"], + examples: ["log1p(3)"], + }, + { + name: "const", + description: "Get value of math constants", + returnValue: "number", + arguments: ["constant_name"], + examples: [ + "const(pi)", + "const(e)", + "const(sqrt2)", + "const(sqrt0.5)", + "const(ln10)", + "const(ln2)", + "const(log10e)", + "const(log2e)", + ], + }, { name: "cases", description: "Returns the argument at position", @@ -212,6 +326,13 @@ export const TemplateFunctions: TemplateFunction[] = [ arguments: ["string"], examples: ['trim_text("<@!344837487526412300>")'], }, + { + name: "convert_base", + description: "Converts a value from base to base", + returnValue: "string", + arguments: ["value", "origin", "dest"], + examples: ['convert_base("256", "10", "2")'], + }, { name: "tag", description: "Gets the value of another defined tag", diff --git a/backend/src/templateFormatter.ts b/backend/src/templateFormatter.ts index a69640a67..46070649f 100644 --- a/backend/src/templateFormatter.ts +++ b/backend/src/templateFormatter.ts @@ -1,3 +1,4 @@ +import { convertBase } from "baseroo"; import seedrandom from "seedrandom"; import { get, has } from "./utils"; @@ -434,6 +435,10 @@ const baseValues = { if (isNaN(arg)) return 0; return Math.ceil(parseFloat(arg)); }, + abs(arg) { + if (isNaN(arg)) return 0; + return Math.abs(parseFloat(arg)); + }, add(...args) { return args.reduce((result, arg) => { if (isNaN(arg)) return result; @@ -465,6 +470,73 @@ const baseValues = { if (isNaN(base) || isNaN(power)) return 0; return Math.pow(parseFloat(base), parseFloat(power)); }, + sqrt(arg) { + if (isNaN(arg)) return 0; + return Math.sqrt(parseFloat(arg)); + }, + cbrt(arg) { + if (isNaN(arg)) return 0; + return Math.cbrt(parseFloat(arg)); + }, + sin(radians) { + if (isNaN(radians)) return 0; + return Math.sin(parseFloat(radians)); + }, + sinh(arg) { + if (isNaN(arg)) return 0; + return Math.sinh(parseFloat(arg)); + }, + tan(arg) { + if (isNaN(arg)) return 0; + return Math.tan(parseFloat(arg)); + }, + tanh(arg) { + if (isNaN(arg)) return 0; + return Math.tanh(parseFloat(arg)); + }, + log(arg) { + if (isNaN(arg)) return 0; + return Math.log(parseFloat(arg)); + }, + log2(arg) { + if (isNaN(arg)) return 0; + return Math.log2(parseFloat(arg)); + }, + log10(arg) { + if (isNaN(arg)) return 0; + return Math.log10(parseFloat(arg)); + }, + log1p(arg) { + if (isNaN(arg)) return 0; + return Math.log1p(parseFloat(arg)); + }, + hypot(...args) { + if (!args.every((e) => !isNaN(e))) return ""; // TODO: Improve validation + return Math.hypot(...args.map((e) => parseFloat(e))); + }, + cos(arg) { + if (isNaN(arg)) return 0; + return Math.cos(parseFloat(arg)); + }, + cosh(arg) { + if (isNaN(arg)) return 0; + return Math.cosh(parseFloat(arg)); + }, + const(str) { + // math constants lmao :joy: + const math_constants = { + pi: Math.PI, + e: Math.E, + sqrt2: Math.SQRT2, + "sqrt0.5": Math.SQRT1_2, + ln10: Math.LN10, + ln2: Math.LN2, + log10e: Math.LOG10E, + log2e: Math.LOG2E, + }; + if (typeof str !== "string") return ""; + return math_constants[str.toLowerCase()] ?? ""; + }, map(obj, key) { if (Array.isArray(obj)) { return obj.map((tobj) => tobj[key]); @@ -485,6 +557,14 @@ const baseValues = { if (!str || typeof str !== "string") return ""; return str.replaceAll(/[^\d]+/g, ""); }, + convert_base(value, from, to) { + try { + // :joy: + return convertBase(value, from, to); + } catch (_) { + return ""; + } + }, }; export async function renderTemplate(