Add support for server-specific timezone and date format settings
This commit is contained in:
parent
ddbbc543c2
commit
c67a1df11d
51 changed files with 326 additions and 168 deletions
|
@ -5,6 +5,8 @@ import { LogType } from "src/data/LogType";
|
|||
import { stripObjectToScalars, resolveUser } from "src/utils";
|
||||
import { logger } from "src/logger";
|
||||
import { scheduleNextDeletion } from "./scheduleNextDeletion";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
import { getDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
export async function deleteNextItem(pluginData: PluginData<AutoDeletePluginType>) {
|
||||
const [itemToDelete] = pluginData.state.deletionQueue.splice(0, 1);
|
||||
|
@ -17,7 +19,9 @@ export async function deleteNextItem(pluginData: PluginData<AutoDeletePluginType
|
|||
|
||||
const user = await resolveUser(pluginData.client, itemToDelete.message.user_id);
|
||||
const channel = pluginData.guild.channels.get(itemToDelete.message.channel_id);
|
||||
const messageDate = moment(itemToDelete.message.data.timestamp, "x").format("YYYY-MM-DD HH:mm:ss");
|
||||
const messageDate = inGuildTz(pluginData, moment.utc(itemToDelete.message.data.timestamp, "x")).format(
|
||||
getDateFormat(pluginData, "pretty_datetime"),
|
||||
);
|
||||
|
||||
pluginData.state.guildLogs.log(LogType.MESSAGE_DELETE_AUTO, {
|
||||
message: itemToDelete.message,
|
||||
|
|
|
@ -7,6 +7,8 @@ import { CasesPluginType } from "../types";
|
|||
import { CaseTypeColors } from "../../../data/CaseTypeColors";
|
||||
import { resolveCaseId } from "./resolveCaseId";
|
||||
import { chunkLines, chunkMessageLines, emptyEmbedValue } from "../../../utils";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
import { getDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
export async function getCaseEmbed(
|
||||
pluginData: PluginData<CasesPluginType>,
|
||||
|
@ -15,7 +17,7 @@ export async function getCaseEmbed(
|
|||
const theCase = await pluginData.state.cases.with("notes").find(resolveCaseId(caseOrCaseId));
|
||||
if (!theCase) return null;
|
||||
|
||||
const createdAt = moment(theCase.created_at);
|
||||
const createdAt = moment.utc(theCase.created_at);
|
||||
const actionTypeStr = CaseTypes[theCase.type].toUpperCase();
|
||||
|
||||
let userName = theCase.user_name;
|
||||
|
@ -27,7 +29,7 @@ export async function getCaseEmbed(
|
|||
const embed: any = {
|
||||
title: `${actionTypeStr} - Case #${theCase.case_number}`,
|
||||
footer: {
|
||||
text: `Case created at ${createdAt.format("YYYY-MM-DD [at] HH:mm")}`,
|
||||
text: `Case created on ${inGuildTz(pluginData, createdAt).format(getDateFormat(pluginData, "pretty_datetime"))}`,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
|
@ -57,7 +59,7 @@ export async function getCaseEmbed(
|
|||
|
||||
if (theCase.notes.length) {
|
||||
theCase.notes.forEach((note: any) => {
|
||||
const noteDate = moment(note.created_at);
|
||||
const noteDate = moment.utc(note.created_at);
|
||||
let noteBody = note.body.trim();
|
||||
if (noteBody === "") {
|
||||
noteBody = emptyEmbedValue;
|
||||
|
@ -67,8 +69,9 @@ export async function getCaseEmbed(
|
|||
|
||||
for (let i = 0; i < chunks.length; i++) {
|
||||
if (i === 0) {
|
||||
const prettyNoteDate = inGuildTz(pluginData, noteDate).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
embed.fields.push({
|
||||
name: `${note.mod_name} at ${noteDate.format("YYYY-MM-DD [at] HH:mm")}:`,
|
||||
name: `${note.mod_name} at ${prettyNoteDate}:`,
|
||||
value: chunks[i],
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -4,6 +4,8 @@ import { isOwner, sendErrorMessage } from "src/pluginUtils";
|
|||
import { confirm, SECONDS, noop } from "src/utils";
|
||||
import moment from "moment-timezone";
|
||||
import { rehostAttachment } from "../rehostAttachment";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
import { getDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
const MAX_ARCHIVED_MESSAGES = 5000;
|
||||
const MAX_MESSAGES_PER_FETCH = 100;
|
||||
|
@ -96,7 +98,7 @@ export const ArchiveChannelCmd = channelArchiverCmd({
|
|||
|
||||
archiveLines.reverse();
|
||||
|
||||
const nowTs = moment().format("YYYY-MM-DD HH:mm:ss");
|
||||
const nowTs = inGuildTz(pluginData).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
|
||||
let result = `Archived ${archiveLines.length} messages from #${args.channel.name} at ${nowTs}`;
|
||||
result += `\n\n${archiveLines.join("\n")}\n`;
|
||||
|
@ -104,7 +106,7 @@ export const ArchiveChannelCmd = channelArchiverCmd({
|
|||
progressMsg.delete().catch(noop);
|
||||
msg.channel.createMessage("Archive created!", {
|
||||
file: Buffer.from(result),
|
||||
name: `archive-${args.channel.name}-${moment().format("YYYY-MM-DD-HH-mm-ss")}.txt`,
|
||||
name: `archive-${args.channel.name}-${moment.utc().format("YYYY-MM-DD-HH-mm-ss")}.txt`,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
@ -21,7 +21,7 @@ export const FollowCmd = locateUserCommand({
|
|||
|
||||
async run({ message: msg, args, pluginData }) {
|
||||
const time = args.duration || 10 * MINUTES;
|
||||
const alertTime = moment().add(time, "millisecond");
|
||||
const alertTime = moment.utc().add(time, "millisecond");
|
||||
const body = args.reminder || "None";
|
||||
const active = args.active || false;
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ const defaultOptions: PluginOptions<LogsPluginType> = {
|
|||
config: {
|
||||
channels: {},
|
||||
format: {
|
||||
timestamp: "YYYY-MM-DD HH:mm:ss",
|
||||
timestamp: "YYYY-MM-DD HH:mm:ss z",
|
||||
...DefaultLogMessages,
|
||||
},
|
||||
ping_user: true,
|
||||
|
|
|
@ -11,8 +11,8 @@ export const LogsGuildMemberAddEvt = logsEvent({
|
|||
const pluginData = meta.pluginData;
|
||||
const member = meta.args.member;
|
||||
|
||||
const newThreshold = moment().valueOf() - 1000 * 60 * 60;
|
||||
const accountAge = humanizeDuration(moment().valueOf() - member.createdAt, {
|
||||
const newThreshold = moment.utc().valueOf() - 1000 * 60 * 60;
|
||||
const accountAge = humanizeDuration(moment.utc().valueOf() - member.createdAt, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
});
|
||||
|
|
|
@ -13,6 +13,7 @@ import { SavedMessage } from "src/data/entities/SavedMessage";
|
|||
import { renderTemplate, TemplateParseError } from "src/templateFormatter";
|
||||
import { logger } from "src/logger";
|
||||
import moment from "moment-timezone";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
|
||||
export async function getLogMessage(
|
||||
pluginData: PluginData<LogsPluginType>,
|
||||
|
@ -87,7 +88,7 @@ export async function getLogMessage(
|
|||
|
||||
const timestampFormat = config.format.timestamp;
|
||||
if (timestampFormat) {
|
||||
const timestamp = moment().format(timestampFormat);
|
||||
const timestamp = inGuildTz(pluginData).format(timestampFormat);
|
||||
formatted = `\`[${timestamp}]\` ${formatted}`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import { LogType } from "src/data/LogType";
|
|||
import moment from "moment-timezone";
|
||||
import { PluginData } from "knub";
|
||||
import { LogsPluginType } from "../types";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
|
||||
export async function onMessageDelete(pluginData: PluginData<LogsPluginType>, savedMessage: SavedMessage) {
|
||||
const user = await resolveUser(pluginData.client, savedMessage.user_id);
|
||||
|
@ -23,7 +24,9 @@ export async function onMessageDelete(pluginData: PluginData<LogsPluginType>, sa
|
|||
{
|
||||
user: stripObjectToScalars(user),
|
||||
channel: stripObjectToScalars(channel),
|
||||
messageDate: moment(savedMessage.data.timestamp, "x").format(pluginData.config.get().format.timestamp),
|
||||
messageDate: inGuildTz(pluginData, moment.utc(savedMessage.data.timestamp, "x")).format(
|
||||
pluginData.config.get().format.timestamp,
|
||||
),
|
||||
message: savedMessage,
|
||||
},
|
||||
savedMessage.id,
|
||||
|
|
|
@ -8,6 +8,8 @@ import { SECONDS, stripObjectToScalars, trimLines } from "../../../utils";
|
|||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { LogType } from "../../../data/LogType";
|
||||
import moment from "moment-timezone";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
import { getDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
export const DeleteCaseCmd = modActionsCommand({
|
||||
trigger: ["delete_case", "deletecase"],
|
||||
|
@ -52,7 +54,7 @@ export const DeleteCaseCmd = modActionsCommand({
|
|||
}
|
||||
|
||||
const deletedByName = `${message.author.username}#${message.author.discriminator}`;
|
||||
const deletedAt = moment().format(`MMM D, YYYY [at] H:mm [UTC]`);
|
||||
const deletedAt = inGuildTz(pluginData).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
|
||||
await pluginData.state.cases.softDelete(
|
||||
theCase.id,
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { command } from "knub";
|
||||
import { IMuteWithDetails, MutesPluginType } from "../types";
|
||||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||
import { DBDateFormat, isFullMessage, MINUTES, noop, resolveMember } from "../../../utils";
|
||||
import { isFullMessage, MINUTES, noop, resolveMember } from "../../../utils";
|
||||
import moment from "moment-timezone";
|
||||
import { humanizeDurationShort } from "../../../humanizeDurationShort";
|
||||
import { getBaseUrl } from "../../../pluginUtils";
|
||||
import { DBDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
export const MutesCmd = command<MutesPluginType>()({
|
||||
trigger: "mutes",
|
||||
|
@ -70,7 +71,8 @@ export const MutesCmd = command<MutesPluginType>()({
|
|||
|
||||
// Filter: mute age
|
||||
if (args.age) {
|
||||
const cutoff = moment()
|
||||
const cutoff = moment
|
||||
.utc()
|
||||
.subtract(args.age, "ms")
|
||||
.format(DBDateFormat);
|
||||
filteredMutes = filteredMutes.filter(m => m.created_at <= cutoff);
|
||||
|
@ -119,14 +121,14 @@ export const MutesCmd = command<MutesPluginType>()({
|
|||
let line = `<@!${mute.user_id}> (**${username}**, \`${mute.user_id}\`) 📋 ${caseName}`;
|
||||
|
||||
if (mute.expires_at) {
|
||||
const timeUntilExpiry = moment().diff(moment(mute.expires_at, DBDateFormat));
|
||||
const timeUntilExpiry = moment.utc().diff(moment.utc(mute.expires_at, DBDateFormat));
|
||||
const humanizedTime = humanizeDurationShort(timeUntilExpiry, { largest: 2, round: true });
|
||||
line += ` ⏰ Expires in ${humanizedTime}`;
|
||||
} else {
|
||||
line += ` ⏰ Indefinite`;
|
||||
}
|
||||
|
||||
const timeFromMute = moment(mute.created_at, DBDateFormat).diff(moment());
|
||||
const timeFromMute = moment.utc(mute.created_at, DBDateFormat).diff(moment.utc());
|
||||
const humanizedTimeFromMute = humanizeDurationShort(timeFromMute, { largest: 2, round: true });
|
||||
line += ` 🕒 Muted ${humanizedTimeFromMute} ago`;
|
||||
|
||||
|
@ -184,7 +186,7 @@ export const MutesCmd = command<MutesPluginType>()({
|
|||
listMessage.edit("No active mutes!");
|
||||
}
|
||||
} else if (args.export) {
|
||||
const archiveId = await pluginData.state.archives.create(lines.join("\n"), moment().add(1, "hour"));
|
||||
const archiveId = await pluginData.state.archives.create(lines.join("\n"), moment.utc().add(1, "hour"));
|
||||
const baseUrl = getBaseUrl(pluginData);
|
||||
const url = await pluginData.state.archives.getUrl(baseUrl, archiveId);
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { postCmd } from "../types";
|
||||
import { trimLines, sorter, disableCodeBlocks, deactivateMentions, createChunkedMessage } from "src/utils";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import moment from "moment-timezone";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
import { DBDateFormat, getDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
const SCHEDULED_POST_PREVIEW_TEXT_LENGTH = 50;
|
||||
|
||||
|
@ -28,7 +31,10 @@ export const ScheduledPostsListCmd = postCmd({
|
|||
.replace(/\s+/g, " ")
|
||||
.slice(0, SCHEDULED_POST_PREVIEW_TEXT_LENGTH);
|
||||
|
||||
const parts = [`\`#${i++}\` \`[${p.post_at}]\` ${previewText}${isTruncated ? "..." : ""}`];
|
||||
const prettyPostAt = inGuildTz(pluginData, moment.utc(p.post_at, DBDateFormat)).format(
|
||||
getDateFormat(pluginData, "pretty_datetime"),
|
||||
);
|
||||
const parts = [`\`#${i++}\` \`[${prettyPostAt}]\` ${previewText}${isTruncated ? "..." : ""}`];
|
||||
if (p.attachments.length) parts.push("*(with attachment)*");
|
||||
if (p.content.embed) parts.push("*(embed)*");
|
||||
if (p.repeat_until) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Message, Channel, TextChannel } from "eris";
|
||||
import { StrictMessageContent, errorMessage, DBDateFormat, stripObjectToScalars, MINUTES } from "src/utils";
|
||||
import { StrictMessageContent, errorMessage, stripObjectToScalars, MINUTES } from "src/utils";
|
||||
import moment from "moment-timezone";
|
||||
import { LogType } from "src/data/LogType";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
|
@ -8,10 +8,11 @@ import { PluginData } from "knub";
|
|||
import { PostPluginType } from "../types";
|
||||
import { parseScheduleTime } from "./parseScheduleTime";
|
||||
import { postMessage } from "./postMessage";
|
||||
import { DBDateFormat, getDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
const MIN_REPEAT_TIME = 5 * MINUTES;
|
||||
const MAX_REPEAT_TIME = Math.pow(2, 32);
|
||||
const MAX_REPEAT_UNTIL = moment().add(100, "years");
|
||||
const MAX_REPEAT_UNTIL = moment.utc().add(100, "years");
|
||||
|
||||
export async function actualPostCmd(
|
||||
pluginData: PluginData<PostPluginType>,
|
||||
|
@ -53,12 +54,12 @@ export async function actualPostCmd(
|
|||
let postAt;
|
||||
if (opts.schedule) {
|
||||
// Schedule the post to be posted later
|
||||
postAt = parseScheduleTime(opts.schedule);
|
||||
postAt = parseScheduleTime(pluginData, opts.schedule);
|
||||
if (!postAt) {
|
||||
return sendErrorMessage(pluginData, msg.channel, "Invalid schedule time");
|
||||
}
|
||||
} else if (opts.repeat) {
|
||||
postAt = moment().add(opts.repeat, "ms");
|
||||
postAt = moment.utc().add(opts.repeat, "ms");
|
||||
}
|
||||
|
||||
// For repeated posts, make sure repeat-until or repeat-times is specified
|
||||
|
@ -67,13 +68,13 @@ export async function actualPostCmd(
|
|||
let repeatDetailsStr: string = null;
|
||||
|
||||
if (opts["repeat-until"]) {
|
||||
repeatUntil = parseScheduleTime(opts["repeat-until"]);
|
||||
repeatUntil = parseScheduleTime(pluginData, opts["repeat-until"]);
|
||||
|
||||
// Invalid time
|
||||
if (!repeatUntil) {
|
||||
return sendErrorMessage(pluginData, msg.channel, "Invalid time specified for -repeat-until");
|
||||
}
|
||||
if (repeatUntil.isBefore(moment())) {
|
||||
if (repeatUntil.isBefore(moment.utc())) {
|
||||
return sendErrorMessage(pluginData, msg.channel, "You can't set -repeat-until in the past");
|
||||
}
|
||||
if (repeatUntil.isAfter(MAX_REPEAT_UNTIL)) {
|
||||
|
@ -110,7 +111,7 @@ export async function actualPostCmd(
|
|||
|
||||
// Save schedule/repeat information in DB
|
||||
if (postAt) {
|
||||
if (postAt < moment()) {
|
||||
if (postAt < moment.utc()) {
|
||||
return sendErrorMessage(pluginData, msg.channel, "Post can't be scheduled to be posted in the past");
|
||||
}
|
||||
|
||||
|
@ -120,10 +121,18 @@ export async function actualPostCmd(
|
|||
channel_id: targetChannel.id,
|
||||
content,
|
||||
attachments: msg.attachments,
|
||||
post_at: postAt.format(DBDateFormat),
|
||||
post_at: postAt
|
||||
.clone()
|
||||
.tz("Etc/UTC")
|
||||
.format(DBDateFormat),
|
||||
enable_mentions: opts["enable-mentions"],
|
||||
repeat_interval: opts.repeat,
|
||||
repeat_until: repeatUntil ? repeatUntil.format(DBDateFormat) : null,
|
||||
repeat_until: repeatUntil
|
||||
? repeatUntil
|
||||
.clone()
|
||||
.tz("Etc/UTC")
|
||||
.format(DBDateFormat)
|
||||
: null,
|
||||
repeat_times: repeatTimes ?? null,
|
||||
});
|
||||
|
||||
|
@ -131,8 +140,9 @@ export async function actualPostCmd(
|
|||
pluginData.state.logs.log(LogType.SCHEDULED_REPEATED_MESSAGE, {
|
||||
author: stripObjectToScalars(msg.author),
|
||||
channel: stripObjectToScalars(targetChannel),
|
||||
date: postAt.format("YYYY-MM-DD"),
|
||||
time: postAt.format("HH:mm:ss"),
|
||||
datetime: postAt.format(getDateFormat(pluginData, "pretty_datetime")),
|
||||
date: postAt.format(getDateFormat(pluginData, "date")),
|
||||
time: postAt.format(getDateFormat(pluginData, "time")),
|
||||
repeatInterval: humanizeDuration(opts.repeat),
|
||||
repeatDetails: repeatDetailsStr,
|
||||
});
|
||||
|
@ -140,8 +150,9 @@ export async function actualPostCmd(
|
|||
pluginData.state.logs.log(LogType.SCHEDULED_MESSAGE, {
|
||||
author: stripObjectToScalars(msg.author),
|
||||
channel: stripObjectToScalars(targetChannel),
|
||||
date: postAt.format("YYYY-MM-DD"),
|
||||
time: postAt.format("HH:mm:ss"),
|
||||
datetime: postAt.format(getDateFormat(pluginData, "pretty_datetime")),
|
||||
date: postAt.format(getDateFormat(pluginData, "date")),
|
||||
time: postAt.format(getDateFormat(pluginData, "time")),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -155,8 +166,9 @@ export async function actualPostCmd(
|
|||
pluginData.state.logs.log(LogType.REPEATED_MESSAGE, {
|
||||
author: stripObjectToScalars(msg.author),
|
||||
channel: stripObjectToScalars(targetChannel),
|
||||
date: postAt.format("YYYY-MM-DD"),
|
||||
time: postAt.format("HH:mm:ss"),
|
||||
datetime: postAt.format(getDateFormat(pluginData, "pretty_datetime")),
|
||||
date: postAt.format(getDateFormat(pluginData, "date")),
|
||||
time: postAt.format(getDateFormat(pluginData, "time")),
|
||||
repeatInterval: humanizeDuration(opts.repeat),
|
||||
repeatDetails: repeatDetailsStr,
|
||||
});
|
||||
|
@ -164,14 +176,16 @@ export async function actualPostCmd(
|
|||
|
||||
// Bot reply schenanigans
|
||||
let successMessage = opts.schedule
|
||||
? `Message scheduled to be posted in <#${targetChannel.id}> on ${postAt.format("YYYY-MM-DD [at] HH:mm:ss")} (UTC)`
|
||||
? `Message scheduled to be posted in <#${targetChannel.id}> on ${postAt.format(
|
||||
getDateFormat(pluginData, "pretty_datetime"),
|
||||
)}`
|
||||
: `Message posted in <#${targetChannel.id}>`;
|
||||
|
||||
if (opts.repeat) {
|
||||
successMessage += `. Message will be automatically reposted every ${humanizeDuration(opts.repeat)}`;
|
||||
|
||||
if (repeatUntil) {
|
||||
successMessage += ` until ${repeatUntil.format("YYYY-MM-DD [at] HH:mm:ss")} (UTC)`;
|
||||
successMessage += ` until ${repeatUntil.format(getDateFormat(pluginData, "pretty_datetime"))}`;
|
||||
} else if (repeatTimes) {
|
||||
successMessage += `, ${repeatTimes} times in total`;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,36 @@
|
|||
import moment, { Moment } from "moment-timezone";
|
||||
import { convertDelayStringToMS } from "src/utils";
|
||||
import { PluginData } from "knub";
|
||||
import { getGuildTz } from "../../../utils/timezones";
|
||||
|
||||
export function parseScheduleTime(str): Moment {
|
||||
const dt1 = moment(str, "YYYY-MM-DD HH:mm:ss");
|
||||
// TODO: Extract out of the Post plugin, use everywhere with a date input
|
||||
export function parseScheduleTime(pluginData: PluginData<any>, str: string): Moment {
|
||||
const tz = getGuildTz(pluginData);
|
||||
|
||||
const dt1 = moment.tz(str, "YYYY-MM-DD HH:mm:ss", tz);
|
||||
if (dt1 && dt1.isValid()) return dt1;
|
||||
|
||||
const dt2 = moment(str, "YYYY-MM-DD HH:mm");
|
||||
const dt2 = moment.tz(str, "YYYY-MM-DD HH:mm", tz);
|
||||
if (dt2 && dt2.isValid()) return dt2;
|
||||
|
||||
const date = moment(str, "YYYY-MM-DD");
|
||||
const date = moment.tz(str, "YYYY-MM-DD", tz);
|
||||
if (date && date.isValid()) return date;
|
||||
|
||||
const t1 = moment(str, "HH:mm:ss");
|
||||
const t1 = moment.tz(str, "HH:mm:ss", tz);
|
||||
if (t1 && t1.isValid()) {
|
||||
if (t1.isBefore(moment())) t1.add(1, "day");
|
||||
if (t1.isBefore(moment.utc())) t1.add(1, "day");
|
||||
return t1;
|
||||
}
|
||||
|
||||
const t2 = moment(str, "HH:mm");
|
||||
const t2 = moment.tz(str, "HH:mm", tz);
|
||||
if (t2 && t2.isValid()) {
|
||||
if (t2.isBefore(moment())) t2.add(1, "day");
|
||||
if (t2.isBefore(moment.utc())) t2.add(1, "day");
|
||||
return t2;
|
||||
}
|
||||
|
||||
const delayStringMS = convertDelayStringToMS(str, "m");
|
||||
if (delayStringMS) {
|
||||
return moment().add(delayStringMS, "ms");
|
||||
return moment.tz(tz).add(delayStringMS, "ms");
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import { PluginData } from "knub";
|
||||
import { PostPluginType } from "../types";
|
||||
import { logger } from "src/logger";
|
||||
import { stripObjectToScalars, DBDateFormat, SECONDS } from "src/utils";
|
||||
import { stripObjectToScalars, SECONDS } from "src/utils";
|
||||
import { LogType } from "src/data/LogType";
|
||||
import moment from "moment-timezone";
|
||||
import { TextChannel, User } from "eris";
|
||||
import { postMessage } from "./postMessage";
|
||||
import { DBDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
const SCHEDULED_POST_CHECK_INTERVAL = 5 * SECONDS;
|
||||
|
||||
|
@ -49,10 +50,10 @@ export async function scheduledPostLoop(pluginData: PluginData<PostPluginType>)
|
|||
let shouldClear = true;
|
||||
|
||||
if (post.repeat_interval) {
|
||||
const nextPostAt = moment().add(post.repeat_interval, "ms");
|
||||
const nextPostAt = moment.utc().add(post.repeat_interval, "ms");
|
||||
|
||||
if (post.repeat_until) {
|
||||
const repeatUntil = moment(post.repeat_until, DBDateFormat);
|
||||
const repeatUntil = moment.utc(post.repeat_until, DBDateFormat);
|
||||
if (nextPostAt.isSameOrBefore(repeatUntil)) {
|
||||
await pluginData.state.scheduledPosts.update(post.id, {
|
||||
post_at: nextPostAt.format(DBDateFormat),
|
||||
|
|
|
@ -4,6 +4,8 @@ import { convertDelayStringToMS } from "src/utils";
|
|||
import humanizeDuration from "humanize-duration";
|
||||
import { sendErrorMessage, sendSuccessMessage } from "src/pluginUtils";
|
||||
import { remindersCommand } from "../types";
|
||||
import { getGuildTz, inGuildTz } from "../../../utils/timezones";
|
||||
import { getDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
export const RemindCmd = remindersCommand({
|
||||
trigger: ["remind", "remindme"],
|
||||
|
@ -16,19 +18,20 @@ export const RemindCmd = remindersCommand({
|
|||
},
|
||||
|
||||
async run({ message: msg, args, pluginData }) {
|
||||
const now = moment();
|
||||
const now = moment.utc();
|
||||
const tz = getGuildTz(pluginData);
|
||||
|
||||
let reminderTime;
|
||||
let reminderTime: moment.Moment;
|
||||
if (args.time.match(/^\d{4}-\d{1,2}-\d{1,2}$/)) {
|
||||
// Date in YYYY-MM-DD format, remind at current time on that date
|
||||
reminderTime = moment(args.time, "YYYY-M-D").set({
|
||||
reminderTime = moment.tz(args.time, "YYYY-M-D", tz).set({
|
||||
hour: now.hour(),
|
||||
minute: now.minute(),
|
||||
second: now.second(),
|
||||
});
|
||||
} else if (args.time.match(/^\d{4}-\d{1,2}-\d{1,2}T\d{2}:\d{2}$/)) {
|
||||
// Date and time in YYYY-MM-DD[T]HH:mm format
|
||||
reminderTime = moment(args.time, "YYYY-M-D[T]HH:mm").second(0);
|
||||
reminderTime = moment.tz(args.time, "YYYY-M-D[T]HH:mm", tz).second(0);
|
||||
} else {
|
||||
// "Delay string" i.e. e.g. "2h30m"
|
||||
const ms = convertDelayStringToMS(args.time);
|
||||
|
@ -37,7 +40,7 @@ export const RemindCmd = remindersCommand({
|
|||
return;
|
||||
}
|
||||
|
||||
reminderTime = moment().add(ms, "millisecond");
|
||||
reminderTime = moment.utc().add(ms, "millisecond");
|
||||
}
|
||||
|
||||
if (!reminderTime.isValid() || reminderTime.isBefore(now)) {
|
||||
|
@ -50,17 +53,21 @@ export const RemindCmd = remindersCommand({
|
|||
await pluginData.state.reminders.add(
|
||||
msg.author.id,
|
||||
msg.channel.id,
|
||||
reminderTime.format("YYYY-MM-DD HH:mm:ss"),
|
||||
reminderTime
|
||||
.clone()
|
||||
.tz("Etc/UTC")
|
||||
.format("YYYY-MM-DD HH:mm:ss"),
|
||||
reminderBody,
|
||||
moment().format("YYYY-MM-DD HH:mm:ss"),
|
||||
moment.utc().format("YYYY-MM-DD HH:mm:ss"),
|
||||
);
|
||||
|
||||
const msUntilReminder = reminderTime.diff(now);
|
||||
const timeUntilReminder = humanizeDuration(msUntilReminder, { largest: 2, round: true });
|
||||
const prettyReminderTime = inGuildTz(pluginData, reminderTime).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
sendSuccessMessage(
|
||||
pluginData,
|
||||
msg.channel,
|
||||
`I will remind you in **${timeUntilReminder}** at **${reminderTime.format("YYYY-MM-DD, HH:mm")}**`,
|
||||
`I will remind you in **${timeUntilReminder}** at **${prettyReminderTime}**`,
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -3,6 +3,8 @@ import { sendErrorMessage } from "src/pluginUtils";
|
|||
import { createChunkedMessage, sorter } from "src/utils";
|
||||
import moment from "moment-timezone";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
import { DBDateFormat, getDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
export const RemindersCmd = remindersCommand({
|
||||
trigger: "reminders",
|
||||
|
@ -20,10 +22,13 @@ export const RemindersCmd = remindersCommand({
|
|||
const lines = Array.from(reminders.entries()).map(([i, reminder]) => {
|
||||
const num = i + 1;
|
||||
const paddedNum = num.toString().padStart(longestNum, " ");
|
||||
const target = moment(reminder.remind_at, "YYYY-MM-DD HH:mm:ss");
|
||||
const diff = target.diff(moment());
|
||||
const target = moment.utc(reminder.remind_at, "YYYY-MM-DD HH:mm:ss");
|
||||
const diff = target.diff(moment.utc());
|
||||
const result = humanizeDuration(diff, { largest: 2, round: true });
|
||||
return `\`${paddedNum}.\` \`${reminder.remind_at} (${result})\` ${reminder.body}`;
|
||||
const prettyRemindAt = inGuildTz(pluginData, moment.utc(reminder.remind_at, DBDateFormat)).format(
|
||||
getDateFormat(pluginData, "pretty_datetime"),
|
||||
);
|
||||
return `\`${paddedNum}.\` \`${prettyRemindAt} (${result})\` ${reminder.body}`;
|
||||
});
|
||||
|
||||
createChunkedMessage(msg.channel, lines.join("\n"));
|
||||
|
|
|
@ -16,9 +16,9 @@ export async function postDueRemindersLoop(pluginData: PluginData<RemindersPlugi
|
|||
if (channel && channel instanceof TextChannel) {
|
||||
try {
|
||||
// Only show created at date if one exists
|
||||
if (moment(reminder.created_at).isValid()) {
|
||||
const target = moment();
|
||||
const diff = target.diff(moment(reminder.created_at, "YYYY-MM-DD HH:mm:ss"));
|
||||
if (moment.utc(reminder.created_at).isValid()) {
|
||||
const target = moment.utc();
|
||||
const diff = target.diff(moment.utc(reminder.created_at, "YYYY-MM-DD HH:mm:ss"));
|
||||
const result = humanizeDuration(diff, { largest: 2, round: true });
|
||||
await channel.createMessage(
|
||||
disableLinkPreviews(
|
||||
|
|
|
@ -14,6 +14,7 @@ import { getRecentActionCount } from "./getRecentActionCount";
|
|||
import { getRecentActions } from "./getRecentActions";
|
||||
import { clearRecentUserActions } from "./clearRecentUserActions";
|
||||
import { saveSpamArchives } from "./saveSpamArchives";
|
||||
import { DBDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
export async function logAndDetectMessageSpam(
|
||||
pluginData: PluginData<SpamPluginType>,
|
||||
|
@ -36,7 +37,7 @@ export async function logAndDetectMessageSpam(
|
|||
|
||||
pluginData.state.spamDetectionQueue = pluginData.state.spamDetectionQueue.then(
|
||||
async () => {
|
||||
const timestamp = moment(savedMessage.posted_at).valueOf();
|
||||
const timestamp = moment.utc(savedMessage.posted_at, DBDateFormat).valueOf();
|
||||
const member = await resolveMember(pluginData.client, pluginData.guild, savedMessage.user_id);
|
||||
|
||||
// Log this action...
|
||||
|
|
|
@ -5,7 +5,7 @@ import { getBaseUrl } from "src/pluginUtils";
|
|||
const SPAM_ARCHIVE_EXPIRY_DAYS = 90;
|
||||
|
||||
export async function saveSpamArchives(pluginData, savedMessages: SavedMessage[]) {
|
||||
const expiresAt = moment().add(SPAM_ARCHIVE_EXPIRY_DAYS, "days");
|
||||
const expiresAt = moment.utc().add(SPAM_ARCHIVE_EXPIRY_DAYS, "days");
|
||||
const archiveId = await pluginData.state.archives.createFromSavedMessages(savedMessages, pluginData.guild, expiresAt);
|
||||
|
||||
return pluginData.state.archives.getUrl(getBaseUrl(pluginData), archiveId);
|
||||
|
|
|
@ -13,8 +13,6 @@ export async function saveMessageToStarboard(
|
|||
const channel = pluginData.guild.channels.get(starboard.channel_id);
|
||||
if (!channel) return;
|
||||
|
||||
const time = moment(msg.timestamp, "x").format("YYYY-MM-DD [at] HH:mm:ss [UTC]");
|
||||
|
||||
const embed: Embed = {
|
||||
footer: {
|
||||
text: `#${(msg.channel as GuildChannel).name}`,
|
||||
|
|
|
@ -15,6 +15,7 @@ import { TagSourceCmd } from "./commands/TagSourceCmd";
|
|||
import moment from "moment-timezone";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import { convertDelayStringToMS } from "../../utils";
|
||||
import { getGuildTz, inGuildTz } from "../../utils/timezones";
|
||||
|
||||
const defaultOptions: PluginOptions<TagsPluginType> = {
|
||||
config: {
|
||||
|
@ -76,6 +77,7 @@ export const TagsPlugin = zeppelinPlugin<TagsPluginType>()("tags", {
|
|||
state.onMessageDeleteFn = msg => onMessageDelete(pluginData, msg);
|
||||
state.savedMessages.events.on("delete", state.onMessageDeleteFn);
|
||||
|
||||
const tz = getGuildTz(pluginData);
|
||||
state.tagFunctions = {
|
||||
parseDateTime(str) {
|
||||
if (typeof str === "number") {
|
||||
|
@ -86,13 +88,13 @@ export const TagsPlugin = zeppelinPlugin<TagsPluginType>()("tags", {
|
|||
return Date.now();
|
||||
}
|
||||
|
||||
return moment(str, "YYYY-MM-DD HH:mm:ss").valueOf();
|
||||
return moment.tz(str, "YYYY-MM-DD HH:mm:ss", tz).valueOf();
|
||||
},
|
||||
|
||||
countdown(toDate) {
|
||||
const target = moment(this.parseDateTime(toDate));
|
||||
const target = moment.utc(this.parseDateTime(toDate), "x");
|
||||
|
||||
const now = moment();
|
||||
const now = moment.utc();
|
||||
if (!target.isValid()) return "";
|
||||
|
||||
const diff = target.diff(now);
|
||||
|
@ -119,7 +121,8 @@ export const TagsPlugin = zeppelinPlugin<TagsPluginType>()("tags", {
|
|||
}
|
||||
|
||||
const delayMS = convertDelayStringToMS(delay);
|
||||
return moment(reference)
|
||||
return moment
|
||||
.utc(reference, "x")
|
||||
.add(delayMS)
|
||||
.valueOf();
|
||||
},
|
||||
|
@ -139,7 +142,8 @@ export const TagsPlugin = zeppelinPlugin<TagsPluginType>()("tags", {
|
|||
}
|
||||
|
||||
const delayMS = convertDelayStringToMS(delay);
|
||||
return moment(reference)
|
||||
return moment
|
||||
.utc(reference, "x")
|
||||
.subtract(delayMS)
|
||||
.valueOf();
|
||||
},
|
||||
|
@ -150,13 +154,13 @@ export const TagsPlugin = zeppelinPlugin<TagsPluginType>()("tags", {
|
|||
|
||||
formatTime(time, format) {
|
||||
const parsed = this.parseDateTime(time);
|
||||
return moment(parsed).format(format);
|
||||
return inGuildTz(parsed).format(format);
|
||||
},
|
||||
|
||||
discordDateFormat(time) {
|
||||
const parsed = time ? this.parseDateTime(time) : Date.now();
|
||||
|
||||
return moment(parsed).format("YYYY-MM-DD");
|
||||
return inGuildTz(parsed).format("YYYY-MM-DD");
|
||||
},
|
||||
|
||||
mention: input => {
|
||||
|
|
|
@ -32,7 +32,7 @@ export const TagSourceCmd = tagsCmd({
|
|||
return;
|
||||
}
|
||||
|
||||
const archiveId = await pluginData.state.archives.create(tag.body, moment().add(10, "minutes"));
|
||||
const archiveId = await pluginData.state.archives.create(tag.body, moment.utc().add(10, "minutes"));
|
||||
const url = pluginData.state.archives.getUrl(getBaseUrl(pluginData), archiveId);
|
||||
|
||||
msg.channel.createMessage(`Tag source:\n${url}`);
|
||||
|
|
|
@ -6,6 +6,7 @@ import humanizeDuration from "humanize-duration";
|
|||
import LCL from "last-commit-log";
|
||||
import path from "path";
|
||||
import moment from "moment-timezone";
|
||||
import { getGuildTz } from "../../../utils/timezones";
|
||||
|
||||
export const AboutCmd = utilityCmd({
|
||||
trigger: "about",
|
||||
|
@ -29,7 +30,7 @@ export const AboutCmd = utilityCmd({
|
|||
let version;
|
||||
|
||||
if (lastCommit) {
|
||||
lastUpdate = moment(lastCommit.committer.date, "X").format("LL [at] H:mm [(UTC)]");
|
||||
lastUpdate = moment.utc(lastCommit.committer.date, "X").format("LL [at] H:mm z");
|
||||
version = lastCommit.shortHash;
|
||||
} else {
|
||||
lastUpdate = "?";
|
||||
|
@ -49,6 +50,7 @@ export const AboutCmd = utilityCmd({
|
|||
["Last update", lastUpdate],
|
||||
["Version", version],
|
||||
["API latency", `${shard.latency}ms`],
|
||||
["Server timezone", getGuildTz(pluginData)],
|
||||
];
|
||||
|
||||
const loadedPlugins = Array.from(
|
||||
|
|
|
@ -40,7 +40,7 @@ export const SourceCmd = utilityCmd({
|
|||
|
||||
const source = `${textSource}\n\nSource:\n\n${fullSource}`;
|
||||
|
||||
const archiveId = await pluginData.state.archives.create(source, moment().add(1, "hour"));
|
||||
const archiveId = await pluginData.state.archives.create(source, moment.utc().add(1, "hour"));
|
||||
const baseUrl = getBaseUrl(pluginData);
|
||||
const url = pluginData.state.archives.getUrl(baseUrl, archiveId);
|
||||
cmdMessage.channel.createMessage(`Message source: ${url}`);
|
||||
|
|
|
@ -4,6 +4,8 @@ import { Constants, EmbedOptions } from "eris";
|
|||
import moment from "moment-timezone";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import { formatNumber, preEmbedPadding, trimLines } from "../../../utils";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
import { getDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
const TEXT_CHANNEL_ICON =
|
||||
"https://cdn.discordapp.com/attachments/740650744830623756/740656843545772062/text-channel.png";
|
||||
|
@ -55,7 +57,8 @@ export async function getChannelInfoEmbed(
|
|||
channelName = `#${channel.name}`;
|
||||
}
|
||||
|
||||
const createdAt = moment(channel.createdAt, "x");
|
||||
const createdAt = moment.utc(channel.createdAt, "x");
|
||||
const prettyCreatedAt = inGuildTz(pluginData, createdAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const channelAge = humanizeDuration(Date.now() - channel.createdAt, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
|
@ -69,7 +72,7 @@ export async function getChannelInfoEmbed(
|
|||
value: trimLines(`
|
||||
Name: **${channelName}**
|
||||
ID: \`${channel.id}\`
|
||||
Created: **${channelAge} ago** (\`${createdAt.format("MMM D, YYYY [at] H:mm [UTC]")}\`)
|
||||
Created: **${channelAge} ago** (\`${prettyCreatedAt}\`)
|
||||
Type: **${channelType}**
|
||||
${showMention ? `Mention: <#${channel.id}>` : ""}
|
||||
`),
|
||||
|
|
|
@ -43,7 +43,7 @@ export async function getInviteInfoEmbed(
|
|||
}
|
||||
|
||||
const serverCreatedAtTimestamp = snowflakeToTimestamp(invite.guild.id);
|
||||
const serverCreatedAt = moment(serverCreatedAtTimestamp, "x");
|
||||
const serverCreatedAt = moment.utc(serverCreatedAtTimestamp, "x");
|
||||
const serverAge = humanizeDuration(Date.now() - serverCreatedAtTimestamp, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
|
@ -66,7 +66,7 @@ export async function getInviteInfoEmbed(
|
|||
: `#${invite.channel.name}`;
|
||||
|
||||
const channelCreatedAtTimestamp = snowflakeToTimestamp(invite.channel.id);
|
||||
const channelCreatedAt = moment(channelCreatedAtTimestamp, "x");
|
||||
const channelCreatedAt = moment.utc(channelCreatedAtTimestamp, "x");
|
||||
const channelAge = humanizeDuration(Date.now() - channelCreatedAtTimestamp, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
|
@ -117,7 +117,7 @@ export async function getInviteInfoEmbed(
|
|||
}
|
||||
|
||||
const channelCreatedAtTimestamp = snowflakeToTimestamp(invite.channel.id);
|
||||
const channelCreatedAt = moment(channelCreatedAtTimestamp, "x");
|
||||
const channelCreatedAt = moment.utc(channelCreatedAtTimestamp, "x");
|
||||
const channelAge = humanizeDuration(Date.now() - channelCreatedAtTimestamp, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
|
|
|
@ -5,6 +5,8 @@ import moment from "moment-timezone";
|
|||
import humanizeDuration from "humanize-duration";
|
||||
import { chunkMessageLines, preEmbedPadding, trimEmptyLines, trimLines } from "../../../utils";
|
||||
import { getDefaultPrefix } from "knub/dist/commands/commandUtils";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
import { getDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
const MESSAGE_ICON = "https://cdn.discordapp.com/attachments/740650744830623756/740685652152025088/message.png";
|
||||
|
||||
|
@ -27,13 +29,15 @@ export async function getMessageInfoEmbed(
|
|||
icon_url: MESSAGE_ICON,
|
||||
};
|
||||
|
||||
const createdAt = moment(message.createdAt, "x");
|
||||
const createdAt = moment.utc(message.createdAt, "x");
|
||||
const prettyCreatedAt = inGuildTz(pluginData, createdAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const messageAge = humanizeDuration(Date.now() - message.createdAt, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
});
|
||||
|
||||
const editedAt = message.editedTimestamp && moment(message.editedTimestamp, "x");
|
||||
const editedAt = message.editedTimestamp && moment.utc(message.editedTimestamp, "x");
|
||||
const prettyEditedAt = inGuildTz(pluginData, editedAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const editAge =
|
||||
message.editedTimestamp &&
|
||||
humanizeDuration(Date.now() - message.editedTimestamp, {
|
||||
|
@ -62,8 +66,8 @@ export async function getMessageInfoEmbed(
|
|||
ID: \`${message.id}\`
|
||||
Channel: <#${message.channel.id}>
|
||||
Channel ID: \`${message.channel.id}\`
|
||||
Created: **${messageAge} ago** (\`${createdAt.format("MMM D, YYYY [at] H:mm [UTC]")}\`)
|
||||
${editedAt ? `Edited at: **${editAge} ago** (\`${editedAt.format("MMM D, YYYY [at] H:mm [UTC]")}\`)` : ""}
|
||||
Created: **${messageAge} ago** (\`${prettyCreatedAt}\`)
|
||||
${editedAt ? `Edited at: **${editAge} ago** (\`${prettyEditedAt}\`)` : ""}
|
||||
Type: **${type}**
|
||||
Link: [**Go to message ➔**](https://discord.com/channels/${pluginData.guild.id}/${message.channel.id}/${
|
||||
message.id
|
||||
|
@ -72,13 +76,19 @@ export async function getMessageInfoEmbed(
|
|||
),
|
||||
});
|
||||
|
||||
const authorCreatedAt = moment(message.author.createdAt);
|
||||
const authorCreatedAt = moment.utc(message.author.createdAt, "x");
|
||||
const prettyAuthorCreatedAt = inGuildTz(pluginData, authorCreatedAt).format(
|
||||
getDateFormat(pluginData, "pretty_datetime"),
|
||||
);
|
||||
const authorAccountAge = humanizeDuration(Date.now() - message.author.createdAt, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
});
|
||||
|
||||
const authorJoinedAt = message.member && moment(message.member.joinedAt);
|
||||
const authorJoinedAt = message.member && moment.utc(message.member.joinedAt, "x");
|
||||
const prettyAuthorJoinedAt = inGuildTz(pluginData, authorJoinedAt).format(
|
||||
getDateFormat(pluginData, "pretty_datetime"),
|
||||
);
|
||||
const authorServerAge =
|
||||
message.member &&
|
||||
humanizeDuration(Date.now() - message.member.joinedAt, {
|
||||
|
@ -91,12 +101,8 @@ export async function getMessageInfoEmbed(
|
|||
value: trimLines(`
|
||||
Name: **${message.author.username}#${message.author.discriminator}**
|
||||
ID: \`${message.author.id}\`
|
||||
Created: **${authorAccountAge} ago** (\`${authorCreatedAt.format("MMM D, YYYY [at] H:mm [UTC]")}\`)
|
||||
${
|
||||
authorJoinedAt
|
||||
? `Joined: **${authorServerAge} ago** (\`${authorJoinedAt.format("MMM D, YYYY [at] H:mm [UTC]")}\`)`
|
||||
: ""
|
||||
}
|
||||
Created: **${authorAccountAge} ago** (\`${prettyAuthorCreatedAt}\`)
|
||||
${authorJoinedAt ? `Joined: **${authorServerAge} ago** (\`${prettyAuthorJoinedAt}\`)` : ""}
|
||||
Mention: <@!${message.author.id}>
|
||||
`),
|
||||
});
|
||||
|
|
|
@ -5,6 +5,8 @@ import { CategoryChannel, EmbedOptions, Guild, RESTChannelInvite, TextChannel, V
|
|||
import moment from "moment-timezone";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import { getGuildPreview } from "./getGuildPreview";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
import { getDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
export async function getServerInfoEmbed(
|
||||
pluginData: PluginData<UtilityPluginType>,
|
||||
|
@ -37,14 +39,15 @@ export async function getServerInfoEmbed(
|
|||
};
|
||||
|
||||
// BASIC INFORMATION
|
||||
const createdAt = moment((guildPreview || restGuild).createdAt);
|
||||
const serverAge = humanizeDuration(moment().valueOf() - createdAt.valueOf(), {
|
||||
const createdAt = moment.utc((guildPreview || restGuild).createdAt, "x");
|
||||
const prettyCreatedAt = inGuildTz(pluginData, createdAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const serverAge = humanizeDuration(moment.utc().valueOf() - createdAt.valueOf(), {
|
||||
largest: 2,
|
||||
round: true,
|
||||
});
|
||||
|
||||
const basicInformation = [];
|
||||
basicInformation.push(`Created: **${serverAge} ago** (${createdAt.format("YYYY-MM-DD[T]HH:mm:ss")})`);
|
||||
basicInformation.push(`Created: **${serverAge} ago** (${prettyCreatedAt})`);
|
||||
|
||||
if (thisServer) {
|
||||
const owner = await resolveUser(pluginData.client, thisServer.ownerID);
|
||||
|
|
|
@ -6,6 +6,8 @@ import moment from "moment-timezone";
|
|||
import { CaseTypes } from "src/data/CaseTypes";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import { snowflakeToTimestamp } from "../../../utils/snowflakeToTimestamp";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
import { getDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
const SNOWFLAKE_ICON = "https://cdn.discordapp.com/attachments/740650744830623756/742020790471491668/snowflake.png";
|
||||
|
||||
|
@ -29,7 +31,8 @@ export function getSnowflakeInfoEmbed(
|
|||
}
|
||||
|
||||
const createdAtMS = snowflakeToTimestamp(snowflake);
|
||||
const createdAt = moment(createdAtMS, "x");
|
||||
const createdAt = moment.utc(createdAtMS, "x");
|
||||
const prettyCreatedAt = inGuildTz(pluginData, createdAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const snowflakeAge = humanizeDuration(Date.now() - createdAtMS, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
|
@ -37,7 +40,7 @@ export function getSnowflakeInfoEmbed(
|
|||
|
||||
embed.fields.push({
|
||||
name: preEmbedPadding + "Basic information",
|
||||
value: `Created: **${snowflakeAge} ago** (\`${createdAt.format("MMM D, YYYY [at] H:mm [UTC]")}\`)`,
|
||||
value: `Created: **${snowflakeAge} ago** (\`${prettyCreatedAt}\`)`,
|
||||
});
|
||||
|
||||
return embed;
|
||||
|
|
|
@ -5,6 +5,8 @@ import { UnknownUser, trimLines, embedPadding, resolveMember, resolveUser, preEm
|
|||
import moment from "moment-timezone";
|
||||
import { CaseTypes } from "src/data/CaseTypes";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
import { getDateFormat } from "../../../utils/dateFormats";
|
||||
|
||||
export async function getUserInfoEmbed(
|
||||
pluginData: PluginData<UtilityPluginType>,
|
||||
|
@ -29,8 +31,9 @@ export async function getUserInfoEmbed(
|
|||
const avatarURL = user.avatarURL || user.defaultAvatarURL;
|
||||
embed.author.icon_url = avatarURL;
|
||||
|
||||
const createdAt = moment(user.createdAt);
|
||||
const accountAge = humanizeDuration(moment().valueOf() - user.createdAt, {
|
||||
const createdAt = moment.utc(user.createdAt, "x");
|
||||
const prettyCreatedAt = inGuildTz(pluginData, createdAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const accountAge = humanizeDuration(moment.utc().valueOf() - user.createdAt, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
});
|
||||
|
@ -40,16 +43,17 @@ export async function getUserInfoEmbed(
|
|||
name: preEmbedPadding + "User information",
|
||||
value: trimLines(`
|
||||
Profile: <@!${user.id}>
|
||||
Created: **${accountAge} ago** (\`${createdAt.format("MMM D, YYYY")}\`)
|
||||
Created: **${accountAge} ago** (\`${prettyCreatedAt}\`)
|
||||
`),
|
||||
});
|
||||
if (member) {
|
||||
const joinedAt = moment(member.joinedAt);
|
||||
const joinAge = humanizeDuration(moment().valueOf() - member.joinedAt, {
|
||||
const joinedAt = moment.utc(member.joinedAt, "x");
|
||||
const prettyJoinedAt = inGuildTz(pluginData, joinedAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const joinAge = humanizeDuration(moment.utc().valueOf() - member.joinedAt, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
});
|
||||
embed.fields[0].value += `\nJoined: **${joinAge} ago** (\`${joinedAt.format("MMM D, YYYY")}\`)`;
|
||||
embed.fields[0].value += `\nJoined: **${joinAge} ago** (\`${prettyJoinedAt}\`)`;
|
||||
} else {
|
||||
embed.fields.push({
|
||||
name: preEmbedPadding + "!! NOTE !!",
|
||||
|
@ -65,14 +69,15 @@ export async function getUserInfoEmbed(
|
|||
value: trimLines(`
|
||||
Name: **${user.username}#${user.discriminator}**
|
||||
ID: \`${user.id}\`
|
||||
Created: **${accountAge} ago** (\`${createdAt.format("MMM D, YYYY [at] H:mm [UTC]")}\`)
|
||||
Created: **${accountAge} ago** (\`${prettyCreatedAt}\`)
|
||||
Mention: <@!${user.id}>
|
||||
`),
|
||||
});
|
||||
|
||||
if (member) {
|
||||
const joinedAt = moment(member.joinedAt);
|
||||
const joinAge = humanizeDuration(moment().valueOf() - member.joinedAt, {
|
||||
const joinedAt = moment.utc(member.joinedAt, "x");
|
||||
const prettyJoinedAt = inGuildTz(pluginData, joinedAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const joinAge = humanizeDuration(moment.utc().valueOf() - member.joinedAt, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
});
|
||||
|
@ -81,7 +86,7 @@ export async function getUserInfoEmbed(
|
|||
embed.fields.push({
|
||||
name: preEmbedPadding + "Member information",
|
||||
value: trimLines(`
|
||||
Joined: **${joinAge} ago** (\`${joinedAt.format("MMM D, YYYY [at] H:mm [UTC]")}\`)
|
||||
Joined: **${joinAge} ago** (\`${prettyJoinedAt}\`)
|
||||
${roles.length > 0 ? "Roles: " + roles.map(r => r.name).join(", ") : ""}
|
||||
`),
|
||||
});
|
||||
|
|
|
@ -214,7 +214,7 @@ export async function archiveSearch(
|
|||
|
||||
${resultList}
|
||||
`),
|
||||
moment().add(1, "hour"),
|
||||
moment.utc().add(1, "hour"),
|
||||
);
|
||||
|
||||
const baseUrl = getBaseUrl(pluginData);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue