3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-05-10 12:25:02 +00:00

Use server timezone and date formats in case summaries. Link to cases in case log channel from case summaries.

This commit is contained in:
Dragory 2020-08-10 03:18:34 +03:00
parent 638f9685b1
commit eb203a3b7a
No known key found for this signature in database
GPG key ID: 5F387BA66DF8AAC1
9 changed files with 178 additions and 62 deletions

View file

@ -158,32 +158,4 @@ export class GuildCases extends BaseGuildRepository {
case_id: caseId,
});
}
// TODO: Move this to the cases plugin, use server timezone + date formats
getSummaryText(theCase: Case) {
const firstNote = theCase.notes[0];
let reason = firstNote ? firstNote.body : "";
if (reason.length > CASE_SUMMARY_REASON_MAX_LENGTH) {
const match = reason.slice(CASE_SUMMARY_REASON_MAX_LENGTH, 100).match(/(?:[.,!?\s]|$)/);
const nextWhitespaceIndex = match ? CASE_SUMMARY_REASON_MAX_LENGTH + match.index : CASE_SUMMARY_REASON_MAX_LENGTH;
if (nextWhitespaceIndex < reason.length) {
reason = reason.slice(0, nextWhitespaceIndex - 1) + "...";
}
}
reason = disableLinkPreviews(reason);
const timestamp = moment.utc(theCase.created_at, DBDateFormat).format("YYYY-MM-DD");
let line = `\`[${timestamp}]\` \`Case #${theCase.case_number}\` __${CaseTypes[theCase.type]}__ ${reason}`;
if (theCase.notes.length > 1) {
line += ` *(+${theCase.notes.length - 1} ${theCase.notes.length === 2 ? "note" : "notes"})*`;
}
if (theCase.is_hidden) {
line += " *(hidden)*";
}
return line;
}
}

View file

@ -11,6 +11,7 @@ import { CaseTypes } from "../../data/CaseTypes";
import { getCaseTypeAmountForUserId } from "./functions/getCaseTypeAmountForUserId";
import { getCaseEmbed } from "./functions/getCaseEmbed";
import { trimPluginDescription } from "../../utils";
import { getCaseSummary } from "./functions/getCaseSummary";
const defaultOptions = {
config: {
@ -61,6 +62,12 @@ export const CasesPlugin = zeppelinPlugin<CasesPluginType>()("cases", {
return getCaseEmbed(pluginData, caseOrCaseId);
};
},
getCaseSummary(pluginData) {
return (caseOrCaseId: Case | number, withLinks = false) => {
return getCaseSummary(pluginData, caseOrCaseId, withLinks);
};
},
},
onLoad(pluginData) {

View file

@ -0,0 +1,56 @@
import { PluginData } from "knub";
import { CasesPluginType } from "../types";
import { disableLinkPreviews } from "../../../utils";
import { DBDateFormat, getDateFormat } from "../../../utils/dateFormats";
import { CaseTypes } from "../../../data/CaseTypes";
import moment from "moment-timezone";
import { Case } from "../../../data/entities/Case";
import { inGuildTz } from "../../../utils/timezones";
const CASE_SUMMARY_REASON_MAX_LENGTH = 300;
export async function getCaseSummary(
pluginData: PluginData<CasesPluginType>,
caseOrCaseId: Case | number,
withLinks = false,
) {
const caseId = caseOrCaseId instanceof Case ? caseOrCaseId.id : caseOrCaseId;
const theCase = await pluginData.state.cases.with("notes").find(caseId);
const firstNote = theCase.notes[0];
let reason = firstNote ? firstNote.body : "";
if (reason.length > CASE_SUMMARY_REASON_MAX_LENGTH) {
const match = reason.slice(CASE_SUMMARY_REASON_MAX_LENGTH, 100).match(/(?:[.,!?\s]|$)/);
const nextWhitespaceIndex = match ? CASE_SUMMARY_REASON_MAX_LENGTH + match.index : CASE_SUMMARY_REASON_MAX_LENGTH;
if (nextWhitespaceIndex < reason.length) {
reason = reason.slice(0, nextWhitespaceIndex - 1) + "...";
}
}
reason = disableLinkPreviews(reason);
const timestamp = moment.utc(theCase.created_at, DBDateFormat);
const prettyTimestamp = inGuildTz(pluginData, timestamp).format(getDateFormat(pluginData, "date"));
let caseTitle = `\`Case #${theCase.case_number}\``;
if (withLinks && theCase.log_message_id) {
const [channelId, messageId] = theCase.log_message_id.split("-");
caseTitle = `[${caseTitle}](https://discord.com/channels/${pluginData.guild.id}/${channelId}/${messageId})`;
} else {
caseTitle = `\`${caseTitle}\``;
}
const caseType = `__${CaseTypes[theCase.type]}__`;
let line = `\`[${prettyTimestamp}]\` ${caseTitle} ${caseType} ${reason}`;
if (theCase.notes.length > 1) {
line += ` *(+${theCase.notes.length - 1} ${theCase.notes.length === 2 ? "note" : "notes"})*`;
}
if (theCase.is_hidden) {
line += " *(hidden)*";
}
return line;
}

View file

@ -21,6 +21,7 @@ import { getLogMessage } from "./util/getLogMessage";
import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners";
import { disableCodeBlocks } from "../../utils";
import { logger } from "../../logger";
import { CasesPlugin } from "../Cases/CasesPlugin";
const defaultOptions: PluginOptions<LogsPluginType> = {
config: {
@ -48,6 +49,7 @@ export const LogsPlugin = zeppelinPlugin<LogsPluginType>()("logs", {
prettyName: "Logs",
},
dependencies: [CasesPlugin],
configSchema: ConfigSchema,
defaultOptions,

View file

@ -3,6 +3,7 @@ import { stripObjectToScalars } from "src/utils";
import { LogType } from "src/data/LogType";
import moment from "moment-timezone";
import humanizeDuration from "humanize-duration";
import { CasesPlugin } from "../../Cases/CasesPlugin";
export const LogsGuildMemberAddEvt = logsEvent({
event: "guildMemberAdd",
@ -29,8 +30,9 @@ export const LogsGuildMemberAddEvt = logsEvent({
if (cases.length) {
const recentCaseLines = [];
const recentCases = cases.slice(0, 2);
const casesPlugin = pluginData.getPlugin(CasesPlugin);
for (const theCase of recentCases) {
recentCaseLines.push(pluginData.state.cases.getSummaryText(theCase));
recentCaseLines.push(await casesPlugin.getCaseSummary(theCase, true));
}
let recentCaseSummary = recentCaseLines.join("\n");

View file

@ -1,7 +1,13 @@
import { modActionsCommand } from "../types";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage } from "../../../pluginUtils";
import { trimLines, createChunkedMessage } from "src/utils";
import { trimLines, createChunkedMessage, emptyEmbedValue } from "src/utils";
import { CasesPlugin } from "../../Cases/CasesPlugin";
import { asyncMap } from "../../../utils/async";
import { EmbedOptions } from "eris";
import { getChunkedEmbedFields } from "../../../utils/getChunkedEmbedFields";
import { getDefaultPrefix } from "knub/dist/commands/commandUtils";
import { getGuildPrefix } from "../../../utils/getGuildPrefix";
const opts = {
mod: ct.member({ option: true }),
@ -28,16 +34,26 @@ export const CasesModCmd = modActionsCommand({
if (recentCases.length === 0) {
sendErrorMessage(pluginData, msg.channel, `No cases by **${modName}**`);
} else {
const lines = recentCases.map(c => pluginData.state.cases.getSummaryText(c));
const finalMessage = trimLines(`
Most recent 5 cases by **${modName}**:
${lines.join("\n")}
Use the \`case <num>\` command to see more info about individual cases
Use the \`cases <user>\` command to see a specific user's cases
`);
createChunkedMessage(msg.channel, finalMessage);
const casesPlugin = pluginData.getPlugin(CasesPlugin);
const lines = await asyncMap(recentCases, c => casesPlugin.getCaseSummary(c, true));
const prefix = getGuildPrefix(pluginData);
const embed: EmbedOptions = {
author: {
name: `Most recent 5 cases by ${modName}`,
icon_url: mod ? mod.avatarURL || mod.defaultAvatarURL : undefined,
},
fields: [
...getChunkedEmbedFields(emptyEmbedValue, lines.join("\n")),
{
name: emptyEmbedValue,
value: trimLines(`
Use \`${prefix}case <num>\` to see more information about an individual case
Use \`${prefix}cases <user>\` to see a specific user's cases
`),
},
],
};
msg.channel.createMessage({ embed });
}
},
});

View file

@ -2,7 +2,19 @@ import { modActionsCommand } from "../types";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage } from "../../../pluginUtils";
import { CasesPlugin } from "src/plugins/Cases/CasesPlugin";
import { UnknownUser, multiSorter, trimLines, createChunkedMessage, resolveUser } from "src/utils";
import {
UnknownUser,
multiSorter,
trimLines,
createChunkedMessage,
resolveUser,
emptyEmbedValue,
chunkArray,
} from "src/utils";
import { getGuildPrefix } from "../../../utils/getGuildPrefix";
import { EmbedOptions, User } from "eris";
import { getChunkedEmbedFields } from "../../../utils/getChunkedEmbedFields";
import { asyncMap } from "../../../utils/async";
const opts = {
expand: ct.bool({ option: true, isSwitch: true, shortcut: "e" }),
@ -54,30 +66,50 @@ export const CasesUserCmd = modActionsCommand({
}
} else {
// Compact view (= regular message with a preview of each case)
const lines = [];
for (const theCase of casesToDisplay) {
theCase.notes.sort(multiSorter(["created_at", "id"]));
const caseSummary = pluginData.state.cases.getSummaryText(theCase);
lines.push(caseSummary);
}
const casesPlugin = pluginData.getPlugin(CasesPlugin);
const lines = await asyncMap(casesToDisplay, c => casesPlugin.getCaseSummary(c, true));
if (!args.hidden && hiddenCases.length) {
if (hiddenCases.length === 1) {
lines.push(`*+${hiddenCases.length} hidden case, use "-hidden" to show it*`);
} else {
lines.push(`*+${hiddenCases.length} hidden cases, use "-hidden" to show them*`);
const prefix = getGuildPrefix(pluginData);
const linesPerChunk = 15;
const lineChunks = chunkArray(lines, linesPerChunk);
const footerField = {
name: emptyEmbedValue,
value: trimLines(`
Use \`${prefix}case <num>\` to see more information about an individual case
`),
};
for (const [i, linesInChunk] of lineChunks.entries()) {
const isLastChunk = i === lineChunks.length - 1;
if (isLastChunk && !args.hidden && hiddenCases.length) {
if (hiddenCases.length === 1) {
linesInChunk.push(`*+${hiddenCases.length} hidden case, use "-hidden" to show it*`);
} else {
linesInChunk.push(`*+${hiddenCases.length} hidden cases, use "-hidden" to show them*`);
}
}
const chunkStart = i * linesPerChunk + 1;
const chunkEnd = Math.min((i + 1) * linesPerChunk, lines.length);
const embed: EmbedOptions = {
author: {
name:
lineChunks.length === 1
? `Cases for ${userName} (${lines.length} total)`
: `Cases ${chunkStart}${chunkEnd} of ${lines.length} for ${userName}`,
icon_url: user instanceof User ? user.avatarURL || user.defaultAvatarURL : undefined,
},
fields: [
...getChunkedEmbedFields(emptyEmbedValue, linesInChunk.join("\n")),
...(isLastChunk ? [footerField] : []),
],
};
msg.channel.createMessage({ embed });
}
const finalMessage = trimLines(`
Cases for **${userName}**:
${lines.join("\n")}
Use the \`case <num>\` command to see more info about individual cases
`);
createChunkedMessage(msg.channel, finalMessage);
}
}
},

View file

@ -0,0 +1,23 @@
import { EmbedField } from "eris";
import { chunkMessageLines, emptyEmbedValue } from "../utils";
export function getChunkedEmbedFields(name: string, value: string, inline?: boolean): EmbedField[] {
const fields: EmbedField[] = [];
const chunks = chunkMessageLines(value, 1014);
for (let i = 0; i < chunks.length; i++) {
if (i === 0) {
fields.push({
name,
value: chunks[i],
});
} else {
fields.push({
name: emptyEmbedValue,
value: chunks[i],
});
}
}
return fields;
}

View file

@ -0,0 +1,6 @@
import { PluginData } from "knub";
import { getDefaultPrefix } from "knub/dist/commands/commandUtils";
export function getGuildPrefix(pluginData: PluginData<any>) {
return pluginData.guildConfig.prefix || getDefaultPrefix(pluginData.client);
}