Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tags: Add one or two template functions #429

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
14 changes: 14 additions & 0 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion backend/src/plugins/Tags/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export function generateTemplateMarkdown(definitions: TemplateFunction[]): strin
const usage = def.signature ?? `(${def.arguments.join(", ")})`;
const examples = def.examples?.map((ex) => `> \`{${ex}}\``).join("\n") ?? null;
return trimPluginDescription(`
## ${def.name}
## ${def.name}${def.plugin ? ` (${def.plugin})` : ""}
**${def.description}**\n
__Usage__: \`{${def.name}${usage}}\`\n
${examples ? `__Examples__:\n${examples}` : ""}\n\n
Expand Down
282 changes: 282 additions & 0 deletions backend/src/plugins/Tags/templateFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,20 @@ export const TemplateFunctions: TemplateFunction[] = [
arguments: ["string"],
examples: ['upperFirst("hello World")'],
},
{
name: "strlen",
description: "Returns the length of a string argument",
returnValue: "number",
arguments: ["string"],
examples: ['strlen("Hello World")'],
},
{
name: "arrlen",
description: "Returns the length of an array argument",
returnValue: "number",
arguments: ["array"],
examples: ['arrlen(["Hello", "World"])'],
},
{
name: "rand",
description: "Returns a random number between from and to, optionally using seed",
Expand All @@ -121,6 +135,27 @@ export const TemplateFunctions: TemplateFunction[] = [
arguments: ["number", "decimalPlaces"],
examples: ["round(1.2345, 2)"],
},
{
name: "ceil",
description: "Rounds a number up to the next integer",
returnValue: "number",
arguments: ["number"],
examples: ["ceil(1.2345)"],
},
{
name: "floor",
description: "Rounds a number down to the next integer",
returnValue: "number",
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",
Expand Down Expand Up @@ -149,6 +184,120 @@ 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",
returnValue: "number",
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",
Expand All @@ -163,4 +312,137 @@ export const TemplateFunctions: TemplateFunction[] = [
arguments: ["argument1", "argument2", "..."],
examples: ['choose("Hello", "World", "!")'],
},
{
name: "map",
description: "Returns the value of the key of object, array or single value",
returnValue: "any",
arguments: ["object | array", "key"],
examples: ['map(user, "id")'],
},
{
name: "trim_text",
description: "Trims all non-numeric characters from a string",
returnValue: "string",
arguments: ["string"],
examples: ['trim_text("<@!344837487526412300>")'],
},
{
name: "convert_base",
description: "Converts a value from <origin> base to <dest> base",
returnValue: "string",
arguments: ["value", "origin", "dest"],
examples: ['convert_base("256", "10", "2")'],
},
{
name: "tag",
description: "Gets the value of another defined tag",
returnValue: "string",
arguments: ["tagName"],
examples: ['tag("tagName")'],
plugin: "tags",
},
{
name: "get",
description: "Gets the value of a saved variable",
returnValue: "any",
arguments: ["variable"],
examples: ['get("variable")'],
plugin: "tags",
},
{
name: "set",
description: "Sets the value of a saved variable",
returnValue: "none",
arguments: ["variableName", "value"],
examples: ['set("variableName", "value")'],
plugin: "tags",
},
{
name: "setr",
description: "Sets the value of a saved variable and returns it",
returnValue: "any",
arguments: ["variableName", "value"],
examples: ['setr("variableName", "value")'],
plugin: "tags",
},
{
name: "parseDateTime",
description: "Parses a date string/unix timestamp into a formated Date string",
returnValue: "string",
arguments: ["date"],
examples: ["parseDateTime(1643411583656)", 'parseDateTime("2020-01-01T00:00:00.000Z")'],
plugin: "tags",
},
{
name: "countdown",
description: "Returns a countdown string to target timestamp",
returnValue: "string",
arguments: ["timestamp"],
examples: ["countdown(1577886400000)"],
plugin: "tags",
},
{
name: "now",
description: "Returns the current timestamp",
returnValue: "number",
arguments: [],
examples: ["now()"],
plugin: "tags",
},
{
name: "timeAdd",
description: "Adds a delay to a timestamp",
returnValue: "number",
arguments: ["timestamp", "delay"],
examples: ['timeAdd(1577886400000, "1h")', 'timeAdd("1h")'],
plugin: "tags",
},
{
name: "timeSub",
description: "Subtracts a delay from a timestamp",
returnValue: "number",
arguments: ["timestamp", "delay"],
examples: ['timeSub(1577886400000, "1h")', 'timeSub("1h")'],
plugin: "tags",
},
{
name: "timeAgo",
description: "Alias for timeSub",
returnValue: "number",
arguments: ["delay"],
examples: ['timeAgo("2h")'],
plugin: "tags",
},
{
name: "formatTime",
description: "Formats a timestamp into a human readable string",
returnValue: "string",
arguments: ["timestamp", "formatStyle"],
examples: ['formatTime(now(), "YYYY-MM-DD HH")', 'formatTime(1577886400000, "YYYY-MM-DD")'],
plugin: "tags",
},
{
name: "mention",
description: "Converts a snowflake to a mention",
returnValue: "string",
arguments: ["snowflake"],
examples: ["mention('344837487526412300')"],
plugin: "tags",
},
{
name: "isMention",
description: "Checks if a string is a mention",
returnValue: "boolean",
arguments: ["string"],
examples: ['isMention("<@!344837487526412300>")'],
plugin: "tags",
},
{
name: "get_user",
description: "Tries to resolve a user from ID or mention",
returnValue: 'ResolvedUser || ""',
arguments: ["string"],
examples: ['get_user("<@!344837487526412300>")', "get_user(get_snowflake(args.0))"],
plugin: "tags",
},
];
1 change: 1 addition & 0 deletions backend/src/plugins/Tags/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export interface TemplateFunction {
returnValue: string;
signature?: string;
examples?: string[];
plugin?: string;
}

export const tagsCmd = guildPluginMessageCommand<TagsPluginType>();
Expand Down
9 changes: 8 additions & 1 deletion backend/src/plugins/Tags/util/renderTagBody.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ExtendedMatchParams, GuildPluginData } from "knub";
import { TemplateSafeValue, TemplateSafeValueContainer, renderTemplate } from "../../../templateFormatter";
import { StrictMessageContent, renderRecursively } from "../../../utils";
import { StrictMessageContent, UnknownUser, renderRecursively, resolveUser } from "../../../utils";
import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects.js";
import { TTag, TagsPluginType } from "../types";
import { findTagByName } from "./findTagByName";

Expand Down Expand Up @@ -39,6 +40,12 @@ export async function renderTagBody(
if (emptyObject[name]) return;
return !Object.hasOwn(dynamicVars, name) || dynamicVars[name] == null ? "" : dynamicVars[name];
},
async get_user(str) {
if (!str || typeof str !== "string") return "";
const resolved = await resolveUser(pluginData.client, str);
if (resolved instanceof UnknownUser) return "";
return userToTemplateSafeUser(resolved);
},
tag: async (name, ...subTagArgs) => {
if (++tagFnCallsObj.calls > MAX_TAG_FN_CALLS) return "";
if (typeof name !== "string") return "";
Expand Down
Loading
Loading