250 lines
9.1 KiB
JavaScript
250 lines
9.1 KiB
JavaScript
const assert = require("assert");
|
|
const placeholders = require("../src/services/placeholders");
|
|
const { getSetting, setSetting } = require("../src/services/settings");
|
|
|
|
const {
|
|
placeholders: placeholderMap,
|
|
fieldPolicies
|
|
} = placeholders._internals;
|
|
|
|
placeholderMap.clear();
|
|
fieldPolicies.clear();
|
|
placeholders.registerCorePlaceholders();
|
|
placeholders.registerFieldPolicy({
|
|
field_id: "okf.markdown",
|
|
label: "OKF Markdown",
|
|
field_type: "okf_markdown",
|
|
output_audience: "user",
|
|
min_editor_role: "user",
|
|
allowed_namespaces: [],
|
|
max_sensitivity: "admin"
|
|
});
|
|
|
|
const user = { id: "user-1", username: "Viewer", isAdmin: false, isMod: false };
|
|
const mod = { id: "mod-1", username: "Mod", isAdmin: false, isMod: true };
|
|
const admin = { id: "admin-1", username: "Admin", isAdmin: true, isMod: true };
|
|
|
|
let catalog = placeholders.catalog({
|
|
fieldId: "core.custom_commands.static_response",
|
|
user: mod,
|
|
outputAudience: "user"
|
|
});
|
|
assert(catalog.placeholders.some((entry) => entry.token === "{{core.main.bot_name}}"));
|
|
assert(catalog.placeholders.some((entry) => entry.token === "{{user.public.display_name}}"));
|
|
assert(catalog.placeholders.some((entry) => entry.token === "{{core.command.rng}}"));
|
|
|
|
const customValidation = placeholders.validateCustomPlaceholders([
|
|
{ name: "stream.title", value: "Friday stream", visibility: "user", description: "Current stream title" },
|
|
{ name: "staff.note", value: "Internal note", visibility: "mod" },
|
|
{ name: "admin.internal_note", value: "Admin only", visibility: "admin" }
|
|
]);
|
|
assert.equal(customValidation.ok, true);
|
|
assert.equal(placeholders.validateCustomPlaceholders([{ name: "Bad Name", value: "no" }]).ok, false);
|
|
assert.equal(placeholders.validateCustomPlaceholders([{ name: "same", value: "one" }, { name: "same", value: "two" }]).ok, false);
|
|
assert.equal(placeholders.validateCustomPlaceholders([{ name: "service.api_key", value: "do-not-store", visibility: "admin" }]).ok, false);
|
|
assert.equal(placeholders.validateCustomPlaceholders([{ name: "missing.visibility", value: "no" }]).ok, false);
|
|
placeholders.registerCustomPlaceholders(customValidation.definitions);
|
|
catalog = placeholders.catalog({
|
|
fieldId: "core.custom_commands.static_response",
|
|
user: mod,
|
|
outputAudience: "user"
|
|
});
|
|
assert(catalog.placeholders.some((entry) => entry.token === "{{custom.stream.title}}"));
|
|
assert.equal(catalog.placeholders.some((entry) => entry.token === "{{custom.staff.note}}"), false);
|
|
|
|
placeholders.registerPlaceholder({
|
|
id: "core.main.admin_note",
|
|
namespace: "core.main",
|
|
label: "Admin note",
|
|
sensitivity: "admin",
|
|
min_editor_role: "admin",
|
|
min_viewer_role: "admin",
|
|
allowed_field_types: ["command_response"],
|
|
resolver: () => "hidden"
|
|
});
|
|
|
|
catalog = placeholders.catalog({
|
|
fieldId: "core.custom_commands.static_response",
|
|
user: admin,
|
|
outputAudience: "user"
|
|
});
|
|
assert.equal(catalog.placeholders.some((entry) => entry.token === "{{core.main.admin_note}}"), false);
|
|
|
|
const invalid = placeholders.validateTemplate({
|
|
fieldId: "core.custom_commands.static_response",
|
|
template: "Hello {{core.main.admin_note}}",
|
|
user: admin,
|
|
outputAudience: "user"
|
|
});
|
|
assert.equal(invalid.ok, false);
|
|
assert.equal(invalid.errors[0].reason, "viewer_role_forbidden");
|
|
|
|
(async () => {
|
|
const rendered = await placeholders.renderTemplate({
|
|
fieldId: "core.custom_commands.static_response",
|
|
template: "Hi {{user.public.display_name}}, prefix is {{core.main.command_prefix}}.",
|
|
user,
|
|
outputAudience: "user",
|
|
runtimeContext: {
|
|
runtime: true,
|
|
user: { displayName: "SammyCat" }
|
|
}
|
|
});
|
|
assert.equal(rendered.ok, true);
|
|
assert.match(rendered.rendered, /^Hi SammyCat, prefix is .+\.$/);
|
|
|
|
const randomRendered = await placeholders.renderTemplate({
|
|
fieldId: "core.custom_commands.static_response",
|
|
template: "Rolled {{core.command.rng}}",
|
|
user: mod,
|
|
outputAudience: "user",
|
|
runtimeContext: { runtime: true, command: { rng: 42 } }
|
|
});
|
|
assert.equal(randomRendered.rendered, "Rolled 42");
|
|
|
|
const customRendered = await placeholders.renderTemplate({
|
|
fieldId: "core.custom_commands.static_response",
|
|
template: "Now: {{custom.stream.title}}",
|
|
user: mod,
|
|
outputAudience: "user",
|
|
runtimeContext: { runtime: true }
|
|
});
|
|
assert.equal(customRendered.rendered, "Now: Friday stream");
|
|
const hiddenCustom = await placeholders.renderTemplate({
|
|
fieldId: "core.custom_commands.static_response",
|
|
template: "{{custom.staff.note}}",
|
|
user: admin,
|
|
outputAudience: "user",
|
|
runtimeContext: { runtime: true },
|
|
fallback: "[hidden]"
|
|
});
|
|
assert.equal(hiddenCustom.rendered, "[hidden]");
|
|
|
|
const previousGuildId = getSetting("discord_guild_id", "");
|
|
try {
|
|
setSetting("discord_guild_id", "guild-1");
|
|
placeholders.registerPlatformPlaceholders({
|
|
discordClient: {
|
|
guilds: {
|
|
cache: new Map([
|
|
["guild-1", {
|
|
name: "Cozy Carnage",
|
|
memberCount: 42,
|
|
createdAt: new Date("2025-01-01T00:00:00.000Z"),
|
|
channels: { cache: new Map([
|
|
["text", { type: 0 }],
|
|
["voice", { type: 2 }]
|
|
]) },
|
|
roles: { cache: new Map([["role", {}]]) },
|
|
emojis: { cache: new Map([["emoji", {}]]) },
|
|
premiumSubscriptionCount: 3
|
|
}]
|
|
])
|
|
}
|
|
}
|
|
});
|
|
const platformCatalog = placeholders.catalog({
|
|
fieldId: "okf.markdown",
|
|
user: admin,
|
|
outputAudience: "user"
|
|
});
|
|
assert(platformCatalog.placeholders.some((entry) => entry.token === "{{platform.discord.guild.member_count}}"));
|
|
assert(platformCatalog.placeholders.some((entry) => entry.token === "{{platform.discord.guild.data_status}}"));
|
|
|
|
const platformRendered = await placeholders.renderTemplate({
|
|
fieldId: "okf.markdown",
|
|
template: "Discord has {{platform.discord.guild.member_count}} members ({{platform.discord.guild.data_status}}).",
|
|
user: admin,
|
|
outputAudience: "user",
|
|
runtimeContext: { runtime: true }
|
|
});
|
|
assert.equal(platformRendered.rendered, "Discord has 42 members (live_cache).");
|
|
|
|
const missingPlatformRendered = await placeholders.renderTemplate({
|
|
fieldId: "okf.markdown",
|
|
template: "Twitch: {{platform.twitch.channel.data_status}}; YouTube: {{platform.youtube.channel.data_status}}.",
|
|
user: admin,
|
|
outputAudience: "user",
|
|
runtimeContext: { runtime: true }
|
|
});
|
|
assert.match(missingPlatformRendered.rendered, /^Twitch: (unavailable|configured_not_connected); YouTube: (unavailable|configured_not_connected)\.$/);
|
|
} finally {
|
|
setSetting("discord_guild_id", previousGuildId);
|
|
}
|
|
|
|
placeholders.registerPlaceholder({
|
|
id: "okf.admin.secret",
|
|
namespace: "okf.admin",
|
|
label: "Admin secret",
|
|
sensitivity: "admin",
|
|
min_editor_role: "admin",
|
|
min_viewer_role: "admin",
|
|
allowed_field_types: ["okf_markdown"],
|
|
resolver: () => "secret"
|
|
});
|
|
const userVisibleAdminPlaceholder = placeholders.validateTemplate({
|
|
fieldId: "okf.markdown",
|
|
template: "{{okf.admin.secret}}",
|
|
user: admin,
|
|
outputAudience: "user"
|
|
});
|
|
assert.equal(userVisibleAdminPlaceholder.ok, false);
|
|
assert.equal(userVisibleAdminPlaceholder.errors[0].reason, "viewer_role_forbidden");
|
|
|
|
placeholders.registerFieldPolicy({
|
|
field_id: "test.async",
|
|
label: "Async renderer test",
|
|
field_type: "test_text",
|
|
output_audience: "user",
|
|
min_editor_role: "user",
|
|
allowed_namespaces: ["test"],
|
|
max_sensitivity: "public_safe"
|
|
});
|
|
let duplicateCalls = 0;
|
|
placeholders.registerPlaceholder({
|
|
id: "test.duplicate",
|
|
namespace: "test",
|
|
label: "Duplicate token",
|
|
allowed_field_types: ["test_text"],
|
|
resolver: async () => (++duplicateCalls === 1 ? "{{test.duplicate}}" : "second")
|
|
});
|
|
placeholders.registerPlaceholder({
|
|
id: "test.failed",
|
|
namespace: "test",
|
|
label: "Failed token",
|
|
allowed_field_types: ["test_text"],
|
|
resolver: async () => { throw new Error("simulated failure"); }
|
|
});
|
|
placeholders.registerPlaceholder({
|
|
id: "test.slow",
|
|
namespace: "test",
|
|
label: "Slow token",
|
|
allowed_field_types: ["test_text"],
|
|
resolver: () => new Promise(() => {})
|
|
});
|
|
placeholders.registerPlaceholder({
|
|
id: "test.unavailable",
|
|
namespace: "test",
|
|
label: "Unavailable token",
|
|
allowed_field_types: ["test_text"],
|
|
available: () => false,
|
|
resolver: () => "must-not-render"
|
|
});
|
|
const deterministic = await placeholders.renderTemplate({
|
|
fieldId: "test.async",
|
|
template: "{{test.duplicate}}{{test.duplicate}}|{{test.failed}}|{{test.unavailable}}|{{test.slow}}",
|
|
user,
|
|
outputAudience: "user",
|
|
runtimeContext: { runtime: true, placeholder_timeout_ms: 50 },
|
|
fallback: "[safe]"
|
|
});
|
|
assert.equal(deterministic.rendered, "{{test.duplicate}}second|[safe]|[safe]|[safe]");
|
|
assert(deterministic.errors.some((entry) => entry.reason === "resolver_failed"));
|
|
assert(deterministic.errors.some((entry) => entry.reason === "placeholder_unavailable"));
|
|
assert(deterministic.errors.some((entry) => entry.reason === "resolver_timeout"));
|
|
console.log("Placeholder verification passed.");
|
|
})().catch((error) => {
|
|
console.error(error);
|
|
process.exit(1);
|
|
});
|