Skip to content

Commit cec2be9

Browse files
authored
Improvements to Track (#83)
- Don't count multiple Track calls on the same message as separate reports - Fix emoji rendering, at least for same-server emoji - Move reaction tracking to thread: Much clearer, and lets us track reactions over time <img width="568" alt="Screenshot 2024-10-24 at 10 40 38 AM" src="https://github.com/user-attachments/assets/bcd9f2d5-cd55-40cf-aa1c-9dbf6655f1c6">
1 parent 1be964d commit cec2be9

File tree

2 files changed

+64
-43
lines changed

2 files changed

+64
-43
lines changed

app/helpers/discord.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@ export const describeReactions = (
107107
title: "Reactions",
108108
fields: reactions.map((r) => ({
109109
name: "",
110-
value: `${r.count} ${r.emoji.name}`,
110+
value: `${r.count} ${
111+
r.emoji.id ? `<:${r.emoji.name}:${r.emoji.id}>` : r.emoji.name
112+
}`,
111113
inline: true,
112114
})),
113115
};

app/helpers/modLog.ts

+61-42
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,23 @@ export const reportUser = async ({
9191
// If we already logged for ~ this message, post to the existing thread
9292
const { logMessage: cachedMessage, logs } = cached;
9393

94+
let thread = cachedMessage.thread;
95+
if (!thread || !cachedMessage.hasThread) {
96+
thread = await makeLogThread(cachedMessage, message.author);
97+
}
98+
99+
if (cached.logs.some((l) => l.message.id === message.id)) {
100+
// If we've already logged exactly this message, don't log it again as a
101+
// separate report.
102+
const latestReport = await thread.send(makeReportMessage(newReport));
103+
return {
104+
warnings: logs.length,
105+
message: cachedMessage,
106+
latestReport,
107+
thread,
108+
};
109+
}
110+
94111
const newLogs = logs.concat([newReport]);
95112
cachedWarnings.set(simplifiedContent, {
96113
logMessage: cachedMessage,
@@ -99,57 +116,60 @@ export const reportUser = async ({
99116

100117
const warnings = newLogs.length;
101118

102-
let thread = cachedMessage.thread;
103-
if (!thread || !cachedMessage.hasThread) {
104-
thread = await makeLogThread(cachedMessage, message.author);
105-
}
106-
107119
const [latestReport] = await Promise.all([
108-
thread.send({ content: makeReportString(newReport) }),
120+
thread.send(makeReportMessage(newReport)),
109121
cachedMessage.edit(
110122
cachedMessage.content
111123
?.replace(/warned \d times/, `warned ${cachedWarnings.size} times`)
112124
.replace(/in \d channels/, `in ${warnings} channels`) || "",
113125
),
114126
]);
115127
return { warnings, message: cachedMessage, latestReport, thread };
116-
} else {
117-
// If this is new, send a new message
118-
const { modLog: modLogId } = await fetchSettings(guild, [SETTINGS.modLog]);
119-
const modLog = await guild.channels.fetch(modLogId);
120-
if (!modLog) {
121-
throw new Error("Channel configured for use as mod log not found");
122-
}
123-
if (modLog.type !== ChannelType.GuildText) {
124-
throw new Error(
125-
"Invalid channel configured for use as mod log, must be guild text",
126-
);
127-
}
128-
const newLogs: Report[] = [{ message, reason, staff }];
128+
}
129129

130-
const logBody = await constructLog({
131-
extra,
132-
logs: newLogs,
133-
previousWarnings: cachedWarnings,
134-
staff,
135-
});
130+
// If this is new, send a new message
131+
const { modLog: modLogId } = await fetchSettings(guild, [SETTINGS.modLog]);
132+
const modLog = await guild.channels.fetch(modLogId);
133+
if (!modLog) {
134+
throw new Error("Channel configured for use as mod log not found");
135+
}
136+
if (modLog.type !== ChannelType.GuildText) {
137+
throw new Error(
138+
"Invalid channel configured for use as mod log, must be guild text",
139+
);
140+
}
141+
const newLogs: Report[] = [{ message, reason, staff }];
136142

137-
const warningMessage = await modLog.send(logBody);
138-
const thread = await makeLogThread(warningMessage, message.author);
139-
const latestReport = await thread.send(makeReportString(newReport));
143+
const logBody = await constructLog({
144+
extra,
145+
logs: newLogs,
146+
previousWarnings: cachedWarnings,
147+
staff,
148+
});
140149

141-
cachedWarnings.set(simplifiedContent, {
142-
logMessage: warningMessage,
143-
logs: newLogs,
144-
});
145-
return { warnings: 1, message: warningMessage, latestReport, thread };
146-
}
150+
const warningMessage = await modLog.send(logBody);
151+
const thread = await makeLogThread(warningMessage, message.author);
152+
const latestReport = await thread.send(makeReportMessage(newReport));
153+
154+
cachedWarnings.set(simplifiedContent, {
155+
logMessage: warningMessage,
156+
logs: newLogs,
157+
});
158+
return { warnings: 1, message: warningMessage, latestReport, thread };
147159
};
148160

149-
const makeReportString = ({ message, reason, staff }: Report) =>
150-
`- ${constructDiscordLink(message)} ${staff ? ` ${staff.username} ` : ""}${
151-
ReadableReasons[reason]
152-
}`;
161+
const makeReportMessage = ({ message, reason, staff }: Report) => {
162+
const embeds = [describeReactions(message.reactions.cache)].filter(
163+
(e): e is APIEmbed => Boolean(e),
164+
);
165+
166+
return {
167+
content: `- ${constructDiscordLink(message)} ${
168+
staff ? ` ${staff.username} ` : ""
169+
}${ReadableReasons[reason]}`,
170+
embeds: embeds.length === 0 ? undefined : embeds,
171+
};
172+
};
153173

154174
const constructLog = async ({
155175
logs,
@@ -201,10 +221,9 @@ const constructLog = async ({
201221
);
202222
}
203223

204-
const embeds = [
205-
describeAttachments(message.attachments),
206-
describeReactions(message.reactions.cache),
207-
].filter((e): e is APIEmbed => Boolean(e));
224+
const embeds = [describeAttachments(message.attachments)].filter(
225+
(e): e is APIEmbed => Boolean(e),
226+
);
208227

209228
return {
210229
content: truncateMessage(`${preface}

0 commit comments

Comments
 (0)