dashboard v1
This commit is contained in:
1 parent
57d420a9f4
commit
22c33c0f7a
66 files changed
+6100
-465
No files matched your search
@@ -0,0 +1,269 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const PLACEHOLDER_PATTERNS = [
|
||||
/ROLE_ID/i,
|
||||
/CHANNEL_ID/i,
|
||||
/CATEGORY_ID/i,
|
||||
/TAG_ID/i,
|
||||
/FORUM_CHANNEL_ID/i,
|
||||
/BOT_TOKEN/i,
|
||||
/MODEL_API_KEY/i,
|
||||
/PASTEBIN_API_KEY/i,
|
||||
/YOUR_/i,
|
||||
/PUT_RANDOM_STRING/i,
|
||||
/example\.com/i,
|
||||
];
|
||||
|
||||
function isEmpty(value) {
|
||||
if (value == null) return true;
|
||||
if (typeof value === "boolean") return false;
|
||||
if (typeof value === "number") return false;
|
||||
return String(value).trim() === "";
|
||||
}
|
||||
|
||||
function isPlaceholder(value) {
|
||||
if (isEmpty(value)) return true;
|
||||
const s = String(value).trim();
|
||||
return PLACEHOLDER_PATTERNS.some((p) => p.test(s));
|
||||
}
|
||||
|
||||
function isDiscordId(value) {
|
||||
return /^\d{17,20}$/.test(String(value).trim());
|
||||
}
|
||||
|
||||
function isConfiguredId(value) {
|
||||
return isDiscordId(value) && !isPlaceholder(value);
|
||||
}
|
||||
|
||||
function isValidToken(value) {
|
||||
if (isPlaceholder(value)) return false;
|
||||
const s = String(value).trim();
|
||||
return s.length >= 50 && s.includes(".");
|
||||
}
|
||||
|
||||
function scoreChecks(checks) {
|
||||
const total = checks.length;
|
||||
const passed = checks.filter((c) => c.ok).length;
|
||||
|
||||
if (total === 0) {
|
||||
return { status: "done", subtitle: "Ready", passed: 0, total: 0 };
|
||||
}
|
||||
|
||||
if (passed === 0) {
|
||||
const hint = checks.find((c) => !c.ok)?.hint ?? "Not configured yet";
|
||||
return { status: "todo", subtitle: hint, passed, total };
|
||||
}
|
||||
|
||||
if (passed === total) {
|
||||
return { status: "done", subtitle: "Configured and ready", passed, total };
|
||||
}
|
||||
|
||||
const next = checks.find((c) => !c.ok);
|
||||
return {
|
||||
status: "progress",
|
||||
subtitle: next?.hint ?? `${passed} of ${total} steps complete`,
|
||||
passed,
|
||||
total,
|
||||
};
|
||||
}
|
||||
|
||||
function evaluateTickets(supportbot, ticketPanel) {
|
||||
const ticket = supportbot?.Ticket ?? {};
|
||||
const ticketType = String(ticket.TicketType || "channels").toLowerCase();
|
||||
|
||||
return scoreChecks([
|
||||
{
|
||||
ok: ticketPanel?.Panel === true,
|
||||
hint: "Enable the ticket panel",
|
||||
},
|
||||
{
|
||||
ok: isConfiguredId(ticket.TicketHome),
|
||||
hint: "Set TicketHome channel ID",
|
||||
},
|
||||
{
|
||||
ok:
|
||||
ticketType !== "channels" ||
|
||||
isConfiguredId(ticket.TicketChannelsCategory),
|
||||
hint: "Set ticket category ID",
|
||||
},
|
||||
{
|
||||
ok: !isPlaceholder(ticketPanel?.Button?.Text),
|
||||
hint: "Configure panel button text",
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
function evaluateSupportbot(supportbot) {
|
||||
const roles = supportbot?.Roles?.StaffMember ?? {};
|
||||
const welcome = supportbot?.Welcome ?? {};
|
||||
|
||||
return scoreChecks([
|
||||
{ ok: isValidToken(supportbot?.General?.Token), hint: "Add your bot token" },
|
||||
{
|
||||
ok:
|
||||
isConfiguredId(roles.Staff) ||
|
||||
isConfiguredId(roles.Admin) ||
|
||||
isConfiguredId(roles.Moderator),
|
||||
hint: "Set staff role IDs",
|
||||
},
|
||||
{
|
||||
ok: !welcome.Enabled || isConfiguredId(welcome.Channel),
|
||||
hint: "Set welcome channel ID",
|
||||
},
|
||||
{
|
||||
ok: !isPlaceholder(supportbot?.Activity?.Status),
|
||||
hint: "Set bot activity status",
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
function evaluateTranscripts(supportbot, transcriptCount) {
|
||||
const ticketReady = isConfiguredId(supportbot?.Ticket?.TicketHome);
|
||||
|
||||
if (!ticketReady) {
|
||||
return {
|
||||
status: "todo",
|
||||
subtitle: "Set up tickets first",
|
||||
passed: 0,
|
||||
total: 2,
|
||||
};
|
||||
}
|
||||
|
||||
if (transcriptCount > 0) {
|
||||
return {
|
||||
status: "done",
|
||||
subtitle: `${transcriptCount} transcript${transcriptCount === 1 ? "" : "s"} saved`,
|
||||
passed: 2,
|
||||
total: 2,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
status: "progress",
|
||||
subtitle: "Close tickets to generate transcripts",
|
||||
passed: 1,
|
||||
total: 2,
|
||||
};
|
||||
}
|
||||
|
||||
function evaluateSuggestions(supportbot) {
|
||||
const sug = supportbot?.Suggestions ?? {};
|
||||
const mode = String(sug.Mode || "Channel").toLowerCase();
|
||||
|
||||
const channelOk =
|
||||
mode === "forum"
|
||||
? isConfiguredId(sug.ForumChannel)
|
||||
: isConfiguredId(sug.Channel);
|
||||
|
||||
return scoreChecks([
|
||||
{
|
||||
ok: channelOk,
|
||||
hint:
|
||||
mode === "forum"
|
||||
? "Set suggestions forum channel"
|
||||
: "Set suggestions channel ID",
|
||||
},
|
||||
{
|
||||
ok: !isPlaceholder(sug.UpvoteEmoji) && !isPlaceholder(sug.DownvoteEmoji),
|
||||
hint: "Configure voting emojis",
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
function evaluateAi(supportbotAi) {
|
||||
if (supportbotAi?.Enabled !== true) {
|
||||
return {
|
||||
status: "progress",
|
||||
subtitle: "AI is disabled in config",
|
||||
passed: 0,
|
||||
total: 3,
|
||||
};
|
||||
}
|
||||
|
||||
return scoreChecks([
|
||||
{
|
||||
ok: !isPlaceholder(supportbotAi?.General?.Model_API_Key),
|
||||
hint: "Add your model API key",
|
||||
},
|
||||
{
|
||||
ok: isConfiguredId(supportbotAi?.Channels?.AIChannel),
|
||||
hint: "Set AI channel ID",
|
||||
},
|
||||
{
|
||||
ok: !isPlaceholder(supportbotAi?.General?.Model),
|
||||
hint: "Choose an AI model",
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
function evaluateCommands(commands) {
|
||||
const entries = Object.entries(commands || {}).filter(
|
||||
([, v]) => v && typeof v === "object" && "Enabled" in v,
|
||||
);
|
||||
|
||||
if (!entries.length) {
|
||||
return { status: "todo", subtitle: "No commands configured", passed: 0, total: 0 };
|
||||
}
|
||||
|
||||
const enabled = entries.filter(([, v]) => v.Enabled !== false).length;
|
||||
const total = entries.length;
|
||||
const ratio = enabled / total;
|
||||
|
||||
if (ratio >= 0.85) {
|
||||
return {
|
||||
status: "done",
|
||||
subtitle: `${enabled} of ${total} commands enabled`,
|
||||
passed: enabled,
|
||||
total,
|
||||
};
|
||||
}
|
||||
|
||||
if (enabled === 0) {
|
||||
return {
|
||||
status: "todo",
|
||||
subtitle: "Enable slash commands",
|
||||
passed: 0,
|
||||
total,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
status: "progress",
|
||||
subtitle: `${enabled} of ${total} commands enabled`,
|
||||
passed: enabled,
|
||||
total,
|
||||
};
|
||||
}
|
||||
|
||||
function countTranscripts() {
|
||||
const dir = path.resolve(__dirname, "../Data/Transcripts");
|
||||
if (!fs.existsSync(dir)) return 0;
|
||||
return fs
|
||||
.readdirSync(dir)
|
||||
.filter((f) => f.endsWith("-transcript.html")).length;
|
||||
}
|
||||
|
||||
function evaluateAllModules(configStore, options = {}) {
|
||||
const supportbot = configStore.supportbot;
|
||||
const ticketPanel = configStore.ticketPanel;
|
||||
const supportbotAi = configStore.supportbotAi;
|
||||
const commands = configStore.commands;
|
||||
const transcriptCount =
|
||||
options.transcriptCount ?? countTranscripts();
|
||||
|
||||
return {
|
||||
tickets: evaluateTickets(supportbot, ticketPanel),
|
||||
supportbot: evaluateSupportbot(supportbot),
|
||||
transcripts: evaluateTranscripts(supportbot, transcriptCount),
|
||||
suggestions: evaluateSuggestions(supportbot),
|
||||
ai: evaluateAi(supportbotAi),
|
||||
commands: evaluateCommands(commands),
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
evaluateAllModules,
|
||||
isPlaceholder,
|
||||
isConfiguredId,
|
||||
};
|
||||
Reference in new issue
Block a user