logs: add support for embeds in log formats

This commit is contained in:
Dragory 2020-07-30 02:21:31 +03:00
parent b6b4154b2d
commit 8b22ce267d
No known key found for this signature in database
GPG key ID: 5F387BA66DF8AAC1
3 changed files with 75 additions and 54 deletions

View file

@ -5,6 +5,7 @@ import { GuildLogs } from "src/data/GuildLogs";
import { GuildSavedMessages } from "src/data/GuildSavedMessages"; import { GuildSavedMessages } from "src/data/GuildSavedMessages";
import { GuildArchives } from "src/data/GuildArchives"; import { GuildArchives } from "src/data/GuildArchives";
import { GuildCases } from "src/data/GuildCases"; import { GuildCases } from "src/data/GuildCases";
import { tMessageContent } from "../../utils";
const LogChannel = t.partial({ const LogChannel = t.partial({
include: t.array(t.string), include: t.array(t.string),
@ -20,14 +21,16 @@ export type TLogChannel = t.TypeOf<typeof LogChannel>;
const LogChannelMap = t.record(t.string, LogChannel); const LogChannelMap = t.record(t.string, LogChannel);
export type TLogChannelMap = t.TypeOf<typeof LogChannelMap>; export type TLogChannelMap = t.TypeOf<typeof LogChannelMap>;
const tLogFormats = t.intersection([
t.record(t.string, t.union([t.string, tMessageContent])),
t.type({
timestamp: t.string,
}),
]);
export const ConfigSchema = t.type({ export const ConfigSchema = t.type({
channels: LogChannelMap, channels: LogChannelMap,
format: t.intersection([ format: tLogFormats,
t.record(t.string, t.string),
t.type({
timestamp: t.string,
}),
]),
ping_user: t.boolean, ping_user: t.boolean,
}); });
export type TConfigSchema = t.TypeOf<typeof ConfigSchema>; export type TConfigSchema = t.TypeOf<typeof ConfigSchema>;

View file

@ -1,7 +1,14 @@
import { PluginData } from "knub"; import { PluginData } from "knub";
import { LogsPluginType } from "../types"; import { LogsPluginType } from "../types";
import { LogType } from "src/data/LogType"; import { LogType } from "src/data/LogType";
import { verboseUserMention, verboseUserName, verboseChannelMention, messageSummary, resolveMember } from "src/utils"; import {
verboseUserMention,
verboseUserName,
verboseChannelMention,
messageSummary,
resolveMember,
renderRecursively,
} from "src/utils";
import { SavedMessage } from "src/data/entities/SavedMessage"; import { SavedMessage } from "src/data/entities/SavedMessage";
import { renderTemplate, TemplateParseError } from "src/templateFormatter"; import { renderTemplate, TemplateParseError } from "src/templateFormatter";
import { logger } from "src/logger"; import { logger } from "src/logger";
@ -12,53 +19,55 @@ export async function getLogMessage(pluginData: PluginData<LogsPluginType>, type
const format = config.format[LogType[type]] || ""; const format = config.format[LogType[type]] || "";
if (format === "") return; if (format === "") return;
let formatted; const values = {
try { ...data,
const values = { userMention: async inputUserOrMember => {
...data, if (!inputUserOrMember) return "";
userMention: async inputUserOrMember => {
if (!inputUserOrMember) return "";
const usersOrMembers = Array.isArray(inputUserOrMember) ? inputUserOrMember : [inputUserOrMember]; const usersOrMembers = Array.isArray(inputUserOrMember) ? inputUserOrMember : [inputUserOrMember];
const mentions = []; const mentions = [];
for (const userOrMember of usersOrMembers) { for (const userOrMember of usersOrMembers) {
let user; let user;
let member; let member;
if (userOrMember.user) { if (userOrMember.user) {
member = userOrMember; member = userOrMember;
user = member.user; user = member.user;
} else { } else {
user = userOrMember; user = userOrMember;
member = await resolveMember(pluginData.client, pluginData.guild, user.id); member = await resolveMember(pluginData.client, pluginData.guild, user.id);
}
const memberConfig = pluginData.config.getMatchingConfig({ member, userId: user.id }) || ({} as any);
mentions.push(memberConfig.ping_user ? verboseUserMention(user) : verboseUserName(user));
} }
return mentions.join(", "); const memberConfig = pluginData.config.getMatchingConfig({ member, userId: user.id }) || ({} as any);
},
channelMention: channel => { mentions.push(memberConfig.ping_user ? verboseUserMention(user) : verboseUserName(user));
if (!channel) return ""; }
return verboseChannelMention(channel);
}, return mentions.join(", ");
messageSummary: (msg: SavedMessage) => { },
if (!msg) return ""; channelMention: channel => {
return messageSummary(msg); if (!channel) return "";
}, return verboseChannelMention(channel);
},
messageSummary: (msg: SavedMessage) => {
if (!msg) return "";
return messageSummary(msg);
},
};
if (type === LogType.BOT_ALERT) {
const valuesWithoutTmplEval = { ...values };
values.tmplEval = str => {
return renderTemplate(str, valuesWithoutTmplEval);
}; };
}
if (type === LogType.BOT_ALERT) { const renderLogString = str => renderTemplate(str, values);
const valuesWithoutTmplEval = { ...values };
values.tmplEval = str => {
return renderTemplate(str, valuesWithoutTmplEval);
};
}
formatted = await renderTemplate(format, values); let formatted;
try {
formatted = typeof format === "string" ? await renderLogString(format) : renderRecursively(format, renderLogString);
} catch (e) { } catch (e) {
if (e instanceof TemplateParseError) { if (e instanceof TemplateParseError) {
logger.error(`Error when parsing template:\nError: ${e.message}\nTemplate: ${format}`); logger.error(`Error when parsing template:\nError: ${e.message}\nTemplate: ${format}`);
@ -68,13 +77,15 @@ export async function getLogMessage(pluginData: PluginData<LogsPluginType>, type
} }
} }
formatted = formatted.trim(); if (typeof formatted === "string") {
formatted = formatted.trim();
const timestampFormat = config.format.timestamp; const timestampFormat = config.format.timestamp;
if (timestampFormat) { if (timestampFormat) {
const timestamp = moment().format(timestampFormat); const timestamp = moment().format(timestampFormat);
return `\`[${timestamp}]\` ${formatted}`; formatted = `\`[${timestamp}]\` ${formatted}`;
} else { }
return formatted;
} }
return formatted;
} }

View file

@ -59,7 +59,14 @@ export async function log(pluginData: PluginData<LogsPluginType>, type: LogType,
const message = await getLogMessage(pluginData, type, data); const message = await getLogMessage(pluginData, type, data);
if (message) { if (message) {
const batched = opts.batched ?? true; // Default to batched unless explicitly disabled // For non-string log messages (i.e. embeds) batching or chunking is not possible, so send them immediately
if (typeof message !== "string") {
await channel.createMessage(message).catch(noop);
return;
}
// Default to batched unless explicitly disabled
const batched = opts.batched ?? true;
const batchTime = opts.batch_time ?? 1000; const batchTime = opts.batch_time ?? 1000;
if (batched) { if (batched) {