Skip to content

Commit 6d5ecde

Browse files
committed
feat: show relative timestamps for cases and mod actions
1 parent 6795bf7 commit 6d5ecde

5 files changed

Lines changed: 64 additions & 14 deletions

File tree

backend/src/plugins/Cases/functions/getCaseEmbed.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,15 @@ export async function getCaseEmbed(
4040
const createdAtWithTz = requestMemberId
4141
? await timeAndDate.inMemberTz(requestMemberId, createdAt)
4242
: timeAndDate.inGuildTz(createdAt);
43+
const createdAtTs = Math.ceil(createdAt.valueOf() / 1000);
44+
const createdAtRelative = `<t:${createdAtTs}:R>`;
4345

4446
const embed: any = {
4547
title: `${actionTypeStr} - Case #${theCase.case_number}`,
4648
footer: {
47-
text: `Case created on ${createdAtWithTz.format(timeAndDate.getDateFormat("pretty_datetime"))}`,
49+
text: `Case created on ${createdAtWithTz.format(
50+
timeAndDate.getDateFormat("pretty_datetime"),
51+
)} (${createdAtRelative})`,
4852
},
4953
fields: [
5054
{

backend/src/plugins/ModActions/commands/ban/actualBanCmd.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,25 @@ export async function actualBanCmd(
9797
}
9898

9999
// Create a new case for the updated ban since we never stored the old case id and log the action
100+
const expiryTimestamp = time && time > 0 ? Math.ceil((Date.now() + time) / 1000) : null;
101+
const expiryRelative = expiryTimestamp ? `<t:${expiryTimestamp}:R>` : null;
102+
const noteDetails: string[] = [];
103+
if (time && time > 0) {
104+
noteDetails.push(`Ban updated to ${humanizeDuration(time)}`);
105+
if (expiryRelative) {
106+
noteDetails.push(`Expires ${expiryRelative}`);
107+
}
108+
} else {
109+
noteDetails.push("Ban updated to indefinite");
110+
}
111+
100112
const casesPlugin = pluginData.getPlugin(CasesPlugin);
101113
const createdCase = await casesPlugin.createCase({
102114
modId: mod.id,
103115
type: CaseTypes.Ban,
104116
userId: user.id,
105117
reason: formattedReason,
106-
noteDetails: [`Ban updated to ${time ? humanizeDuration(time) : "indefinite"}`],
118+
noteDetails,
107119
});
108120
if (time) {
109121
pluginData.getPlugin(LogsPlugin).logMemberTimedBan({
@@ -124,7 +136,7 @@ export async function actualBanCmd(
124136

125137
pluginData.state.common.sendSuccessMessage(
126138
context,
127-
`Ban updated to ${time ? "expire in " + humanizeDuration(time) + " from now" : "indefinite"}`,
139+
`Ban updated to ${time && expiryRelative ? `expire ${expiryRelative}` : "indefinite"}`,
128140
);
129141
lock.unlock();
130142
return;
@@ -171,6 +183,9 @@ export async function actualBanCmd(
171183
return;
172184
}
173185

186+
const banExpiryTimestamp = time && time > 0 ? Math.ceil((Date.now() + time) / 1000) : null;
187+
const banExpiryRelative = banExpiryTimestamp ? `<t:${banExpiryTimestamp}:R>` : null;
188+
174189
let forTime = "";
175190
if (time && time > 0) {
176191
forTime = `for ${humanizeDuration(time)} `;
@@ -185,6 +200,10 @@ export async function actualBanCmd(
185200
response = `Member forcebanned ${forTime}(Case #${banResult.case.case_number})`;
186201
}
187202

203+
if (banExpiryRelative) {
204+
response += ` ⏰ ${banExpiryRelative}`;
205+
}
206+
188207
lock.unlock();
189208
pluginData.state.common.sendSuccessMessage(context, response);
190209
}

backend/src/plugins/ModActions/functions/banUserId.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ export async function banUserId(
133133

134134
const tempbanLock = await pluginData.locks.acquire(`tempban-${user.id}`);
135135
const existingTempban = await pluginData.state.tempbans.findExistingTempbanForUserId(user.id);
136+
const banExpiresAt = banTime && banTime > 0 ? Date.now() + banTime : null;
137+
const banExpiryTimestamp = banExpiresAt ? Math.ceil(banExpiresAt / 1000) : null;
138+
const banExpiryRelative = banExpiryTimestamp ? `<t:${banExpiryTimestamp}:R>` : null;
136139
if (banTime && banTime > 0) {
137140
const selfId = pluginData.client.user!.id;
138141
if (existingTempban) {
@@ -151,9 +154,17 @@ export async function banUserId(
151154

152155
const noteDetails: string[] = [];
153156
const timeUntilUnban = banTime ? humanizeDuration(banTime) : "indefinite";
154-
const timeDetails = `Banned ${banTime ? `for ${timeUntilUnban}` : "indefinitely"}`;
155-
if (notifyResult.text) noteDetails.push(ucfirst(notifyResult.text));
156-
noteDetails.push(timeDetails);
157+
if (notifyResult.text) {
158+
noteDetails.push(ucfirst(notifyResult.text));
159+
}
160+
if (banTime && banTime > 0) {
161+
noteDetails.push(`Banned for ${timeUntilUnban}`);
162+
if (banExpiryRelative) {
163+
noteDetails.push(`Expires ${banExpiryRelative}`);
164+
}
165+
} else {
166+
noteDetails.push("Banned indefinitely");
167+
}
157168

158169
const createdCase = await casesPlugin.createCase({
159170
...(banOptions.caseArgs || {}),

backend/src/plugins/Mutes/commands/MutesCmd.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,16 +130,14 @@ export const MutesCmd = mutesCmd({
130130
let line = `<@!${mute.user_id}> (**${username}**, \`${mute.user_id}\`) 📋 ${caseName}`;
131131

132132
if (mute.expires_at) {
133-
const timeUntilExpiry = moment.utc().diff(moment.utc(mute.expires_at, DBDateFormat));
134-
const humanizedTime = humanizeDurationShort(timeUntilExpiry, { largest: 2, round: true });
135-
line += ` ⏰ Expires in ${humanizedTime}`;
133+
const expiresAtTs = Math.ceil(moment.utc(mute.expires_at).valueOf() / 1000);
134+
line += ` ⏰ Expires <t:${expiresAtTs}:R>`;
136135
} else {
137136
line += ` ⏰ Indefinite`;
138137
}
139138

140-
const timeFromMute = moment.utc(mute.created_at, DBDateFormat).diff(moment.utc());
141-
const humanizedTimeFromMute = humanizeDurationShort(timeFromMute, { largest: 2, round: true });
142-
line += ` 🕒 Muted ${humanizedTimeFromMute} ago`;
139+
const mutedAtTs = Math.ceil(moment.utc(mute.created_at).valueOf() / 1000);
140+
line += ` 🕒 Muted <t:${mutedAtTs}:R>`;
143141

144142
if (mute.banned) {
145143
line += ` 🔨 Banned`;

backend/src/plugins/Mutes/functions/muteUser.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export async function muteUser(
4646
const muteType = getDefaultMuteType(pluginData);
4747
const muteExpiresAt = muteTime ? Date.now() + muteTime : null;
4848
const timeoutUntil = getTimeoutExpiryTime(muteExpiresAt);
49+
const muteExpiryTimestamp = muteExpiresAt ? Math.ceil(muteExpiresAt / 1000) : null;
50+
const muteExpiryRelative = muteExpiryTimestamp ? `<t:${muteExpiryTimestamp}:R>` : null;
4951

5052
// No mod specified -> mark Zeppelin as the mod
5153
if (!muteOptions.caseArgs?.modId) {
@@ -245,7 +247,15 @@ export async function muteUser(
245247

246248
if (theCase) {
247249
// Update old case
248-
const noteDetails = [`Mute updated to ${muteTime ? timeUntilUnmuteStr : "indefinite"}`];
250+
const noteDetails: string[] = [];
251+
if (muteTime) {
252+
noteDetails.push(`Mute updated to ${timeUntilUnmuteStr}`);
253+
if (muteExpiryRelative) {
254+
noteDetails.push(`Expires ${muteExpiryRelative}`);
255+
}
256+
} else {
257+
noteDetails.push("Mute updated to indefinite");
258+
}
249259
const reasons = reason ? [reason] : [""]; // Empty string so that there is a case update even without reason
250260

251261
if (muteOptions.caseArgs?.extraNotes) {
@@ -263,7 +273,15 @@ export async function muteUser(
263273
}
264274
} else {
265275
// Create new case
266-
const noteDetails = [`Muted ${muteTime ? `for ${timeUntilUnmuteStr}` : "indefinitely"}`];
276+
const noteDetails: string[] = [];
277+
if (muteTime) {
278+
noteDetails.push(`Muted for ${timeUntilUnmuteStr}`);
279+
if (muteExpiryRelative) {
280+
noteDetails.push(`Expires ${muteExpiryRelative}`);
281+
}
282+
} else {
283+
noteDetails.push("Muted indefinitely");
284+
}
267285
if (notifyResult.text) {
268286
noteDetails.push(ucfirst(notifyResult.text));
269287
}

0 commit comments

Comments
 (0)