mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-05-10 12:25:02 +00:00
Add time_and_date plugin. Use it for timezones and date formats around the bot.
This commit is contained in:
parent
cffb0dbd6b
commit
4ae8cf85a3
67 changed files with 543 additions and 177 deletions
|
@ -6,6 +6,7 @@ import { GuildLogs } from "src/data/GuildLogs";
|
|||
import { onMessageCreate } from "./util/onMessageCreate";
|
||||
import { onMessageDelete } from "./util/onMessageDelete";
|
||||
import { onMessageDeleteBulk } from "./util/onMessageDeleteBulk";
|
||||
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
const defaultOptions: PluginOptions<AutoDeletePluginType> = {
|
||||
config: {
|
||||
|
@ -22,6 +23,7 @@ export const AutoDeletePlugin = zeppelinPlugin<AutoDeletePluginType>()("auto_del
|
|||
configurationGuide: "Maximum deletion delay is currently 5 minutes",
|
||||
},
|
||||
|
||||
dependencies: [TimeAndDatePlugin],
|
||||
configSchema: ConfigSchema,
|
||||
defaultOptions,
|
||||
|
||||
|
|
|
@ -5,13 +5,14 @@ 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";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
export async function deleteNextItem(pluginData: PluginData<AutoDeletePluginType>) {
|
||||
const [itemToDelete] = pluginData.state.deletionQueue.splice(0, 1);
|
||||
if (!itemToDelete) return;
|
||||
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
|
||||
pluginData.state.guildLogs.ignoreLog(LogType.MESSAGE_DELETE, itemToDelete.message.id);
|
||||
pluginData.client.deleteMessage(itemToDelete.message.channel_id, itemToDelete.message.id).catch(logger.warn);
|
||||
|
||||
|
@ -19,9 +20,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 = inGuildTz(pluginData, moment.utc(itemToDelete.message.data.timestamp, "x")).format(
|
||||
getDateFormat(pluginData, "pretty_datetime"),
|
||||
);
|
||||
const messageDate = timeAndDate
|
||||
.inGuildTz(moment.utc(itemToDelete.message.data.timestamp, "x"))
|
||||
.format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
|
||||
pluginData.state.guildLogs.log(LogType.MESSAGE_DELETE_AUTO, {
|
||||
message: itemToDelete.message,
|
||||
|
|
|
@ -12,6 +12,8 @@ import { getCaseTypeAmountForUserId } from "./functions/getCaseTypeAmountForUser
|
|||
import { getCaseEmbed } from "./functions/getCaseEmbed";
|
||||
import { trimPluginDescription } from "../../utils";
|
||||
import { getCaseSummary } from "./functions/getCaseSummary";
|
||||
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
|
||||
import { mapToPublicFn } from "../../pluginUtils";
|
||||
|
||||
const defaultOptions = {
|
||||
config: {
|
||||
|
@ -33,6 +35,7 @@ export const CasesPlugin = zeppelinPlugin<CasesPluginType>()("cases", {
|
|||
`),
|
||||
},
|
||||
|
||||
dependencies: [TimeAndDatePlugin],
|
||||
configSchema: ConfigSchema,
|
||||
defaultOptions,
|
||||
|
||||
|
@ -61,17 +64,8 @@ export const CasesPlugin = zeppelinPlugin<CasesPluginType>()("cases", {
|
|||
};
|
||||
},
|
||||
|
||||
getCaseEmbed(pluginData) {
|
||||
return (caseOrCaseId: Case | number) => {
|
||||
return getCaseEmbed(pluginData, caseOrCaseId);
|
||||
};
|
||||
},
|
||||
|
||||
getCaseSummary(pluginData) {
|
||||
return (caseOrCaseId: Case | number, withLinks = false) => {
|
||||
return getCaseSummary(pluginData, caseOrCaseId, withLinks);
|
||||
};
|
||||
},
|
||||
getCaseEmbed: mapToPublicFn(getCaseEmbed),
|
||||
getCaseSummary: mapToPublicFn(getCaseSummary),
|
||||
},
|
||||
|
||||
onLoad(pluginData) {
|
||||
|
|
|
@ -6,17 +6,19 @@ import { PluginData, helpers } from "knub";
|
|||
import { CasesPluginType } from "../types";
|
||||
import { resolveCaseId } from "./resolveCaseId";
|
||||
import { chunkLines, chunkMessageLines, emptyEmbedValue, messageLink } from "../../../utils";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
import { getDateFormat } from "../../../utils/dateFormats";
|
||||
import { getCaseColor } from "./getCaseColor";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
export async function getCaseEmbed(
|
||||
pluginData: PluginData<CasesPluginType>,
|
||||
caseOrCaseId: Case | number,
|
||||
requestMemberId?: string,
|
||||
): Promise<AdvancedMessageContent> {
|
||||
const theCase = await pluginData.state.cases.with("notes").find(resolveCaseId(caseOrCaseId));
|
||||
if (!theCase) return null;
|
||||
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
|
||||
const createdAt = moment.utc(theCase.created_at);
|
||||
const actionTypeStr = CaseTypes[theCase.type].toUpperCase();
|
||||
|
||||
|
@ -26,10 +28,14 @@ export async function getCaseEmbed(
|
|||
let modName = theCase.mod_name;
|
||||
if (theCase.mod_id) modName += `\n<@!${theCase.mod_id}>`;
|
||||
|
||||
const createdAtWithTz = requestMemberId
|
||||
? await timeAndDate.inMemberTz(requestMemberId, createdAt)
|
||||
: timeAndDate.inGuildTz(createdAt);
|
||||
|
||||
const embed: any = {
|
||||
title: `${actionTypeStr} - Case #${theCase.case_number}`,
|
||||
footer: {
|
||||
text: `Case created on ${inGuildTz(pluginData, createdAt).format(getDateFormat(pluginData, "pretty_datetime"))}`,
|
||||
text: `Case created on ${createdAtWithTz.format(timeAndDate.getDateFormat("pretty_datetime"))}`,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
|
@ -56,7 +62,7 @@ export async function getCaseEmbed(
|
|||
embed.color = getCaseColor(pluginData, theCase.type);
|
||||
|
||||
if (theCase.notes.length) {
|
||||
theCase.notes.forEach((note: any) => {
|
||||
for (const note of theCase.notes) {
|
||||
const noteDate = moment.utc(note.created_at);
|
||||
let noteBody = note.body.trim();
|
||||
if (noteBody === "") {
|
||||
|
@ -67,7 +73,10 @@ 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"));
|
||||
const noteDateWithTz = requestMemberId
|
||||
? await timeAndDate.inMemberTz(requestMemberId, noteDate)
|
||||
: timeAndDate.inGuildTz(noteDate);
|
||||
const prettyNoteDate = noteDateWithTz.format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
embed.fields.push({
|
||||
name: `${note.mod_name} at ${prettyNoteDate}:`,
|
||||
value: chunks[i],
|
||||
|
@ -79,7 +88,7 @@ export async function getCaseEmbed(
|
|||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
embed.fields.push({
|
||||
name: "!!! THIS CASE HAS NO NOTES !!!",
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
import { PluginData } from "knub";
|
||||
import { CasesPluginType } from "../types";
|
||||
import { convertDelayStringToMS, DAYS, disableLinkPreviews, emptyEmbedValue, messageLink } from "../../../utils";
|
||||
import { DBDateFormat, getDateFormat } from "../../../utils/dateFormats";
|
||||
import {
|
||||
convertDelayStringToMS,
|
||||
DAYS,
|
||||
DBDateFormat,
|
||||
disableLinkPreviews,
|
||||
emptyEmbedValue,
|
||||
messageLink,
|
||||
} from "../../../utils";
|
||||
import { CaseTypes, CaseTypeToName } from "../../../data/CaseTypes";
|
||||
import moment from "moment-timezone";
|
||||
import { Case } from "../../../data/entities/Case";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import { humanizeDurationShort } from "../../../humanizeDurationShort";
|
||||
import { caseAbbreviations } from "../caseAbbreviations";
|
||||
import { getCaseIcon } from "./getCaseIcon";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
const CASE_SUMMARY_REASON_MAX_LENGTH = 300;
|
||||
const INCLUDE_MORE_NOTES_THRESHOLD = 20;
|
||||
|
@ -21,8 +27,10 @@ export async function getCaseSummary(
|
|||
pluginData: PluginData<CasesPluginType>,
|
||||
caseOrCaseId: Case | number,
|
||||
withLinks = false,
|
||||
requestMemberId?: string,
|
||||
) {
|
||||
const config = pluginData.config.get();
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
|
||||
const caseId = caseOrCaseId instanceof Case ? caseOrCaseId.id : caseOrCaseId;
|
||||
const theCase = await pluginData.state.cases.with("notes").find(caseId);
|
||||
|
@ -50,9 +58,12 @@ export async function getCaseSummary(
|
|||
const timestamp = moment.utc(theCase.created_at, DBDateFormat);
|
||||
const relativeTimeCutoff = convertDelayStringToMS(config.relative_time_cutoff);
|
||||
const useRelativeTime = config.show_relative_times && Date.now() - timestamp.valueOf() < relativeTimeCutoff;
|
||||
const timestampWithTz = requestMemberId
|
||||
? await timeAndDate.inMemberTz(requestMemberId, timestamp)
|
||||
: timeAndDate.inGuildTz(timestamp);
|
||||
const prettyTimestamp = useRelativeTime
|
||||
? moment.utc().to(timestamp)
|
||||
: inGuildTz(pluginData, timestamp).format(getDateFormat(pluginData, "date"));
|
||||
: timestampWithTz.format(timeAndDate.getDateFormat("date"));
|
||||
|
||||
const icon = getCaseIcon(pluginData, theCase.type);
|
||||
|
||||
|
|
|
@ -2,9 +2,12 @@ import { zeppelinPlugin } from "../ZeppelinPluginBlueprint";
|
|||
import { ChannelArchiverPluginType } from "./types";
|
||||
import { ArchiveChannelCmd } from "./commands/ArchiveChannelCmd";
|
||||
import * as t from "io-ts";
|
||||
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
export const ChannelArchiverPlugin = zeppelinPlugin<ChannelArchiverPluginType>()("channel_archiver", {
|
||||
showInDocs: false,
|
||||
|
||||
dependencies: [TimeAndDatePlugin],
|
||||
configSchema: t.type({}),
|
||||
|
||||
// prettier-ignore
|
||||
|
|
|
@ -4,8 +4,7 @@ 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";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
const MAX_ARCHIVED_MESSAGES = 5000;
|
||||
const MAX_MESSAGES_PER_FETCH = 100;
|
||||
|
@ -98,7 +97,8 @@ export const ArchiveChannelCmd = channelArchiverCmd({
|
|||
|
||||
archiveLines.reverse();
|
||||
|
||||
const nowTs = inGuildTz(pluginData).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
const nowTs = timeAndDate.inGuildTz().format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
|
||||
let result = `Archived ${archiveLines.length} messages from #${args.channel.name} at ${nowTs}`;
|
||||
result += `\n\n${archiveLines.join("\n")}\n`;
|
||||
|
|
|
@ -22,6 +22,7 @@ import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners";
|
|||
import { disableCodeBlocks } from "../../utils";
|
||||
import { logger } from "../../logger";
|
||||
import { CasesPlugin } from "../Cases/CasesPlugin";
|
||||
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
const defaultOptions: PluginOptions<LogsPluginType> = {
|
||||
config: {
|
||||
|
@ -49,7 +50,7 @@ export const LogsPlugin = zeppelinPlugin<LogsPluginType>()("logs", {
|
|||
prettyName: "Logs",
|
||||
},
|
||||
|
||||
dependencies: [CasesPlugin],
|
||||
dependencies: [TimeAndDatePlugin, CasesPlugin],
|
||||
configSchema: ConfigSchema,
|
||||
defaultOptions,
|
||||
|
||||
|
|
|
@ -13,7 +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";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
export async function getLogMessage(
|
||||
pluginData: PluginData<LogsPluginType>,
|
||||
|
@ -88,7 +88,10 @@ export async function getLogMessage(
|
|||
|
||||
const timestampFormat = config.format.timestamp;
|
||||
if (timestampFormat) {
|
||||
const timestamp = inGuildTz(pluginData).format(timestampFormat);
|
||||
const timestamp = pluginData
|
||||
.getPlugin(TimeAndDatePlugin)
|
||||
.inGuildTz()
|
||||
.format(timestampFormat);
|
||||
formatted = `\`[${timestamp}]\` ${formatted}`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +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";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
export async function onMessageDelete(pluginData: PluginData<LogsPluginType>, savedMessage: SavedMessage) {
|
||||
const user = await resolveUser(pluginData.client, savedMessage.user_id);
|
||||
|
@ -24,9 +24,10 @@ export async function onMessageDelete(pluginData: PluginData<LogsPluginType>, sa
|
|||
{
|
||||
user: stripObjectToScalars(user),
|
||||
channel: stripObjectToScalars(channel),
|
||||
messageDate: inGuildTz(pluginData, moment.utc(savedMessage.data.timestamp, "x")).format(
|
||||
pluginData.config.get().format.timestamp,
|
||||
),
|
||||
messageDate: pluginData
|
||||
.getPlugin(TimeAndDatePlugin)
|
||||
.inGuildTz(moment.utc(savedMessage.data.timestamp, "x"))
|
||||
.format(pluginData.config.get().format.timestamp),
|
||||
message: savedMessage,
|
||||
},
|
||||
savedMessage.id,
|
||||
|
|
|
@ -35,6 +35,7 @@ import { banUserId } from "./functions/banUserId";
|
|||
import { MassmuteCmd } from "./commands/MassmuteCmd";
|
||||
import { trimPluginDescription } from "../../utils";
|
||||
import { DeleteCaseCmd } from "./commands/DeleteCaseCmd";
|
||||
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
const defaultOptions = {
|
||||
config: {
|
||||
|
@ -103,11 +104,10 @@ export const ModActionsPlugin = zeppelinPlugin<ModActionsPluginType>()("mod_acti
|
|||
`),
|
||||
},
|
||||
|
||||
dependencies: [TimeAndDatePlugin, CasesPlugin, MutesPlugin],
|
||||
configSchema: ConfigSchema,
|
||||
defaultOptions,
|
||||
|
||||
dependencies: [CasesPlugin, MutesPlugin],
|
||||
|
||||
events: [
|
||||
CreateBanCaseOnManualBanEvt,
|
||||
CreateUnbanCaseOnManualUnbanEvt,
|
||||
|
|
|
@ -23,7 +23,7 @@ export const CaseCmd = modActionsCommand({
|
|||
}
|
||||
|
||||
const casesPlugin = pluginData.getPlugin(CasesPlugin);
|
||||
const embed = await casesPlugin.getCaseEmbed(theCase.id);
|
||||
const embed = await casesPlugin.getCaseEmbed(theCase.id, msg.author.id);
|
||||
msg.channel.createMessage(embed);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -36,7 +36,7 @@ export const CasesModCmd = modActionsCommand({
|
|||
sendErrorMessage(pluginData, msg.channel, `No cases by **${modName}**`);
|
||||
} else {
|
||||
const casesPlugin = pluginData.getPlugin(CasesPlugin);
|
||||
const lines = await asyncMap(recentCases, c => casesPlugin.getCaseSummary(c, true));
|
||||
const lines = await asyncMap(recentCases, c => casesPlugin.getCaseSummary(c, true, msg.author.id));
|
||||
const prefix = getGuildPrefix(pluginData);
|
||||
const embed: EmbedOptions = {
|
||||
author: {
|
||||
|
|
|
@ -67,7 +67,7 @@ export const CasesUserCmd = modActionsCommand({
|
|||
} else {
|
||||
// Compact view (= regular message with a preview of each case)
|
||||
const casesPlugin = pluginData.getPlugin(CasesPlugin);
|
||||
const lines = await asyncMap(casesToDisplay, c => casesPlugin.getCaseSummary(c, true));
|
||||
const lines = await asyncMap(casesToDisplay, c => casesPlugin.getCaseSummary(c, true, msg.author.id));
|
||||
|
||||
const prefix = getGuildPrefix(pluginData);
|
||||
const linesPerChunk = 15;
|
||||
|
|
|
@ -8,8 +8,7 @@ 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";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
export const DeleteCaseCmd = modActionsCommand({
|
||||
trigger: ["delete_case", "deletecase"],
|
||||
|
@ -54,7 +53,9 @@ export const DeleteCaseCmd = modActionsCommand({
|
|||
}
|
||||
|
||||
const deletedByName = `${message.author.username}#${message.author.discriminator}`;
|
||||
const deletedAt = inGuildTz(pluginData).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
const deletedAt = timeAndDate.inGuildTz().format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
|
||||
await pluginData.state.cases.softDelete(
|
||||
theCase.id,
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import { command } from "knub";
|
||||
import { IMuteWithDetails, MutesPluginType } from "../types";
|
||||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||
import { isFullMessage, MINUTES, noop, resolveMember } from "../../../utils";
|
||||
import { DBDateFormat, 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",
|
||||
|
|
|
@ -12,6 +12,7 @@ import { ScheduledPostsShowCmd } from "./commands/ScheduledPostsShowCmd";
|
|||
import { ScheduledPostsListCmd } from "./commands/ScheduledPostsListCmd";
|
||||
import { ScheduledPostsDeleteCmd } from "./commands/SchedluedPostsDeleteCmd";
|
||||
import { scheduledPostLoop } from "./util/scheduledPostLoop";
|
||||
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
const defaultOptions: PluginOptions<PostPluginType> = {
|
||||
config: {
|
||||
|
@ -33,6 +34,7 @@ export const PostPlugin = zeppelinPlugin<PostPluginType>()("post", {
|
|||
prettyName: "Post",
|
||||
},
|
||||
|
||||
dependencies: [TimeAndDatePlugin],
|
||||
configSchema: ConfigSchema,
|
||||
defaultOptions,
|
||||
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
import { postCmd } from "../types";
|
||||
import { trimLines, sorter, disableCodeBlocks, deactivateMentions, createChunkedMessage } from "src/utils";
|
||||
import {
|
||||
trimLines,
|
||||
sorter,
|
||||
disableCodeBlocks,
|
||||
deactivateMentions,
|
||||
createChunkedMessage,
|
||||
DBDateFormat,
|
||||
} from "src/utils";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import moment from "moment-timezone";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
import { DBDateFormat, getDateFormat } from "../../../utils/dateFormats";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
const SCHEDULED_POST_PREVIEW_TEXT_LENGTH = 50;
|
||||
|
||||
|
@ -31,9 +37,10 @@ export const ScheduledPostsListCmd = postCmd({
|
|||
.replace(/\s+/g, " ")
|
||||
.slice(0, SCHEDULED_POST_PREVIEW_TEXT_LENGTH);
|
||||
|
||||
const prettyPostAt = inGuildTz(pluginData, moment.utc(p.post_at, DBDateFormat)).format(
|
||||
getDateFormat(pluginData, "pretty_datetime"),
|
||||
);
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
const prettyPostAt = timeAndDate
|
||||
.inGuildTz(moment.utc(p.post_at, DBDateFormat))
|
||||
.format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
const parts = [`\`#${i++}\` \`[${prettyPostAt}]\` ${previewText}${isTruncated ? "..." : ""}`];
|
||||
if (p.attachments.length) parts.push("*(with attachment)*");
|
||||
if (p.content.embed) parts.push("*(embed)*");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Message, Channel, TextChannel } from "eris";
|
||||
import { StrictMessageContent, errorMessage, stripObjectToScalars, MINUTES } from "src/utils";
|
||||
import { StrictMessageContent, errorMessage, stripObjectToScalars, MINUTES, DBDateFormat } from "src/utils";
|
||||
import moment from "moment-timezone";
|
||||
import { LogType } from "src/data/LogType";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
|
@ -8,7 +8,7 @@ import { PluginData } from "knub";
|
|||
import { PostPluginType } from "../types";
|
||||
import { parseScheduleTime } from "./parseScheduleTime";
|
||||
import { postMessage } from "./postMessage";
|
||||
import { DBDateFormat, getDateFormat } from "../../../utils/dateFormats";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
const MIN_REPEAT_TIME = 5 * MINUTES;
|
||||
const MAX_REPEAT_TIME = Math.pow(2, 32);
|
||||
|
@ -54,7 +54,7 @@ export async function actualPostCmd(
|
|||
let postAt;
|
||||
if (opts.schedule) {
|
||||
// Schedule the post to be posted later
|
||||
postAt = parseScheduleTime(pluginData, opts.schedule);
|
||||
postAt = await parseScheduleTime(pluginData, msg.author.id, opts.schedule);
|
||||
if (!postAt) {
|
||||
return sendErrorMessage(pluginData, msg.channel, "Invalid schedule time");
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ export async function actualPostCmd(
|
|||
let repeatDetailsStr: string = null;
|
||||
|
||||
if (opts["repeat-until"]) {
|
||||
repeatUntil = parseScheduleTime(pluginData, opts["repeat-until"]);
|
||||
repeatUntil = await parseScheduleTime(pluginData, msg.author.id, opts["repeat-until"]);
|
||||
|
||||
// Invalid time
|
||||
if (!repeatUntil) {
|
||||
|
@ -109,6 +109,8 @@ export async function actualPostCmd(
|
|||
: `every ${humanizeDuration(opts.repeat)}, ${repeatTimes} times in total`;
|
||||
}
|
||||
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
|
||||
// Save schedule/repeat information in DB
|
||||
if (postAt) {
|
||||
if (postAt < moment.utc()) {
|
||||
|
@ -140,9 +142,9 @@ export async function actualPostCmd(
|
|||
pluginData.state.logs.log(LogType.SCHEDULED_REPEATED_MESSAGE, {
|
||||
author: stripObjectToScalars(msg.author),
|
||||
channel: stripObjectToScalars(targetChannel),
|
||||
datetime: postAt.format(getDateFormat(pluginData, "pretty_datetime")),
|
||||
date: postAt.format(getDateFormat(pluginData, "date")),
|
||||
time: postAt.format(getDateFormat(pluginData, "time")),
|
||||
datetime: postAt.format(timeAndDate.getDateFormat("pretty_datetime")),
|
||||
date: postAt.format(timeAndDate.getDateFormat("date")),
|
||||
time: postAt.format(timeAndDate.getDateFormat("time")),
|
||||
repeatInterval: humanizeDuration(opts.repeat),
|
||||
repeatDetails: repeatDetailsStr,
|
||||
});
|
||||
|
@ -150,9 +152,9 @@ export async function actualPostCmd(
|
|||
pluginData.state.logs.log(LogType.SCHEDULED_MESSAGE, {
|
||||
author: stripObjectToScalars(msg.author),
|
||||
channel: stripObjectToScalars(targetChannel),
|
||||
datetime: postAt.format(getDateFormat(pluginData, "pretty_datetime")),
|
||||
date: postAt.format(getDateFormat(pluginData, "date")),
|
||||
time: postAt.format(getDateFormat(pluginData, "time")),
|
||||
datetime: postAt.format(timeAndDate.getDateFormat("pretty_datetime")),
|
||||
date: postAt.format(timeAndDate.getDateFormat("date")),
|
||||
time: postAt.format(timeAndDate.getDateFormat("time")),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -166,9 +168,9 @@ export async function actualPostCmd(
|
|||
pluginData.state.logs.log(LogType.REPEATED_MESSAGE, {
|
||||
author: stripObjectToScalars(msg.author),
|
||||
channel: stripObjectToScalars(targetChannel),
|
||||
datetime: postAt.format(getDateFormat(pluginData, "pretty_datetime")),
|
||||
date: postAt.format(getDateFormat(pluginData, "date")),
|
||||
time: postAt.format(getDateFormat(pluginData, "time")),
|
||||
datetime: postAt.format(timeAndDate.getDateFormat("pretty_datetime")),
|
||||
date: postAt.format(timeAndDate.getDateFormat("date")),
|
||||
time: postAt.format(timeAndDate.getDateFormat("time")),
|
||||
repeatInterval: humanizeDuration(opts.repeat),
|
||||
repeatDetails: repeatDetailsStr,
|
||||
});
|
||||
|
@ -177,7 +179,7 @@ export async function actualPostCmd(
|
|||
// Bot reply schenanigans
|
||||
let successMessage = opts.schedule
|
||||
? `Message scheduled to be posted in <#${targetChannel.id}> on ${postAt.format(
|
||||
getDateFormat(pluginData, "pretty_datetime"),
|
||||
timeAndDate.getDateFormat("pretty_datetime"),
|
||||
)}`
|
||||
: `Message posted in <#${targetChannel.id}>`;
|
||||
|
||||
|
@ -185,7 +187,7 @@ export async function actualPostCmd(
|
|||
successMessage += `. Message will be automatically reposted every ${humanizeDuration(opts.repeat)}`;
|
||||
|
||||
if (repeatUntil) {
|
||||
successMessage += ` until ${repeatUntil.format(getDateFormat(pluginData, "pretty_datetime"))}`;
|
||||
successMessage += ` until ${repeatUntil.format(timeAndDate.getDateFormat("pretty_datetime"))}`;
|
||||
} else if (repeatTimes) {
|
||||
successMessage += `, ${repeatTimes} times in total`;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import moment, { Moment } from "moment-timezone";
|
||||
import { convertDelayStringToMS } from "src/utils";
|
||||
import { PluginData } from "knub";
|
||||
import { getGuildTz } from "../../../utils/timezones";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
// 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);
|
||||
export async function parseScheduleTime(pluginData: PluginData<any>, memberId: string, str: string): Promise<Moment> {
|
||||
const tz = await pluginData.getPlugin(TimeAndDatePlugin).getMemberTz(memberId);
|
||||
|
||||
const dt1 = moment.tz(str, "YYYY-MM-DD HH:mm:ss", tz);
|
||||
if (dt1 && dt1.isValid()) return dt1;
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import { PluginData } from "knub";
|
||||
import { PostPluginType } from "../types";
|
||||
import { logger } from "src/logger";
|
||||
import { stripObjectToScalars, SECONDS } from "src/utils";
|
||||
import { stripObjectToScalars, SECONDS, DBDateFormat } 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;
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import { postDueRemindersLoop } from "./utils/postDueRemindersLoop";
|
|||
import { RemindCmd } from "./commands/RemindCmd";
|
||||
import { RemindersCmd } from "./commands/RemindersCmd";
|
||||
import { RemindersDeleteCmd } from "./commands/RemindersDeleteCmd";
|
||||
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
const defaultOptions: PluginOptions<RemindersPluginType> = {
|
||||
config: {
|
||||
|
@ -27,6 +28,7 @@ export const RemindersPlugin = zeppelinPlugin<RemindersPluginType>()("reminders"
|
|||
prettyName: "Reminders",
|
||||
},
|
||||
|
||||
dependencies: [TimeAndDatePlugin],
|
||||
configSchema: ConfigSchema,
|
||||
defaultOptions,
|
||||
|
||||
|
|
|
@ -4,8 +4,7 @@ import { convertDelayStringToMS, messageLink } 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";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
export const RemindCmd = remindersCommand({
|
||||
trigger: ["remind", "remindme"],
|
||||
|
@ -18,8 +17,10 @@ export const RemindCmd = remindersCommand({
|
|||
},
|
||||
|
||||
async run({ message: msg, args, pluginData }) {
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
|
||||
const now = moment.utc();
|
||||
const tz = getGuildTz(pluginData);
|
||||
const tz = await timeAndDate.getMemberTz(msg.author.id);
|
||||
|
||||
let reminderTime: moment.Moment;
|
||||
if (args.time.match(/^\d{4}-\d{1,2}-\d{1,2}$/)) {
|
||||
|
@ -62,7 +63,10 @@ export const RemindCmd = remindersCommand({
|
|||
|
||||
const msUntilReminder = reminderTime.diff(now);
|
||||
const timeUntilReminder = humanizeDuration(msUntilReminder, { largest: 2, round: true });
|
||||
const prettyReminderTime = inGuildTz(pluginData, reminderTime).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const prettyReminderTime = (await timeAndDate.inMemberTz(msg.author.id, reminderTime)).format(
|
||||
pluginData.getPlugin(TimeAndDatePlugin).getDateFormat("pretty_datetime"),
|
||||
);
|
||||
|
||||
sendSuccessMessage(
|
||||
pluginData,
|
||||
msg.channel,
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { remindersCommand } from "../types";
|
||||
import { sendErrorMessage } from "src/pluginUtils";
|
||||
import { createChunkedMessage, sorter } from "src/utils";
|
||||
import { createChunkedMessage, DBDateFormat, 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";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
export const RemindersCmd = remindersCommand({
|
||||
trigger: "reminders",
|
||||
|
@ -17,6 +16,8 @@ export const RemindersCmd = remindersCommand({
|
|||
return;
|
||||
}
|
||||
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
|
||||
reminders.sort(sorter("remind_at"));
|
||||
const longestNum = (reminders.length + 1).toString().length;
|
||||
const lines = Array.from(reminders.entries()).map(([i, reminder]) => {
|
||||
|
@ -25,9 +26,9 @@ export const RemindersCmd = remindersCommand({
|
|||
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 });
|
||||
const prettyRemindAt = inGuildTz(pluginData, moment.utc(reminder.remind_at, DBDateFormat)).format(
|
||||
getDateFormat(pluginData, "pretty_datetime"),
|
||||
);
|
||||
const prettyRemindAt = timeAndDate
|
||||
.inGuildTz(moment.utc(reminder.remind_at, DBDateFormat))
|
||||
.format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
return `\`${paddedNum}.\` \`${prettyRemindAt} (${result})\` ${reminder.body}`;
|
||||
});
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import { SavedMessage } from "src/data/entities/SavedMessage";
|
|||
import { RecentActionType, TBaseSingleSpamConfig, SpamPluginType } from "../types";
|
||||
import moment from "moment-timezone";
|
||||
import { MuteResult } from "src/plugins/Mutes/types";
|
||||
import { convertDelayStringToMS, trimLines, stripObjectToScalars, resolveMember, noop } from "src/utils";
|
||||
import { convertDelayStringToMS, trimLines, stripObjectToScalars, resolveMember, noop, DBDateFormat } from "src/utils";
|
||||
import { LogType } from "src/data/LogType";
|
||||
import { CaseTypes } from "src/data/CaseTypes";
|
||||
import { logger } from "src/logger";
|
||||
|
@ -14,7 +14,6 @@ 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>,
|
||||
|
|
|
@ -15,7 +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";
|
||||
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
const defaultOptions: PluginOptions<TagsPluginType> = {
|
||||
config: {
|
||||
|
@ -77,7 +77,9 @@ export const TagsPlugin = zeppelinPlugin<TagsPluginType>()("tags", {
|
|||
state.onMessageDeleteFn = msg => onMessageDelete(pluginData, msg);
|
||||
state.savedMessages.events.on("delete", state.onMessageDeleteFn);
|
||||
|
||||
const tz = getGuildTz(pluginData);
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
|
||||
const tz = timeAndDate.getGuildTz();
|
||||
state.tagFunctions = {
|
||||
parseDateTime(str) {
|
||||
if (typeof str === "number") {
|
||||
|
@ -154,13 +156,13 @@ export const TagsPlugin = zeppelinPlugin<TagsPluginType>()("tags", {
|
|||
|
||||
formatTime(time, format) {
|
||||
const parsed = this.parseDateTime(time);
|
||||
return inGuildTz(parsed).format(format);
|
||||
return timeAndDate.inGuildTz(parsed).format(format);
|
||||
},
|
||||
|
||||
discordDateFormat(time) {
|
||||
const parsed = time ? this.parseDateTime(time) : Date.now();
|
||||
|
||||
return inGuildTz(parsed).format("YYYY-MM-DD");
|
||||
return timeAndDate.inGuildTz(parsed).format("YYYY-MM-DD");
|
||||
},
|
||||
|
||||
mention: input => {
|
||||
|
|
50
backend/src/plugins/TimeAndDate/TimeAndDatePlugin.ts
Normal file
50
backend/src/plugins/TimeAndDate/TimeAndDatePlugin.ts
Normal file
|
@ -0,0 +1,50 @@
|
|||
import { zeppelinPlugin } from "../ZeppelinPluginBlueprint";
|
||||
import { ConfigSchema, TimeAndDatePluginType } from "./types";
|
||||
import { GuildMemberTimezones } from "../../data/GuildMemberTimezones";
|
||||
import { PluginOptions } from "knub";
|
||||
import { SetTimezoneCmd } from "./commands/SetTimezoneCmd";
|
||||
import { ViewTimezoneCmd } from "./commands/ViewTimezoneCmd";
|
||||
import { defaultDateFormats } from "./defaultDateFormats";
|
||||
import { Tail } from "../../utils/typeUtils";
|
||||
import { inGuildTz } from "./functions/inGuildTz";
|
||||
import { mapToPublicFn } from "../../pluginUtils";
|
||||
import { getGuildTz } from "./functions/getGuildTz";
|
||||
import { getMemberTz } from "./functions/getMemberTz";
|
||||
import { getDateFormat } from "./functions/getDateFormat";
|
||||
import { inMemberTz } from "./functions/inMemberTz";
|
||||
|
||||
const defaultOptions: PluginOptions<TimeAndDatePluginType> = {
|
||||
config: {
|
||||
timezone: "Etc/UTC",
|
||||
can_set_timezone: false,
|
||||
date_formats: defaultDateFormats,
|
||||
},
|
||||
|
||||
overrides: [
|
||||
{
|
||||
level: ">=50",
|
||||
config: {
|
||||
can_set_timezone: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const TimeAndDatePlugin = zeppelinPlugin<TimeAndDatePluginType>()("time_and_date", {
|
||||
configSchema: ConfigSchema,
|
||||
defaultOptions,
|
||||
|
||||
commands: [SetTimezoneCmd, ViewTimezoneCmd],
|
||||
|
||||
public: {
|
||||
getGuildTz: mapToPublicFn(getGuildTz),
|
||||
inGuildTz: mapToPublicFn(inGuildTz),
|
||||
getMemberTz: mapToPublicFn(getMemberTz),
|
||||
inMemberTz: mapToPublicFn(inMemberTz),
|
||||
getDateFormat: mapToPublicFn(getDateFormat),
|
||||
},
|
||||
|
||||
onLoad(pluginData) {
|
||||
pluginData.state.memberTimezones = GuildMemberTimezones.getGuildInstance(pluginData.guild.id);
|
||||
},
|
||||
});
|
17
backend/src/plugins/TimeAndDate/commands/SetTimezoneCmd.ts
Normal file
17
backend/src/plugins/TimeAndDate/commands/SetTimezoneCmd.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { timeAndDateCmd } from "../types";
|
||||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||
import { sendSuccessMessage } from "../../../pluginUtils";
|
||||
|
||||
export const SetTimezoneCmd = timeAndDateCmd({
|
||||
trigger: "timezone",
|
||||
permission: "can_set_timezone",
|
||||
|
||||
signature: {
|
||||
timezone: ct.timezone(),
|
||||
},
|
||||
|
||||
async run({ pluginData, message, args }) {
|
||||
await pluginData.state.memberTimezones.set(message.author.id, args.timezone);
|
||||
sendSuccessMessage(pluginData, message.channel, `Your timezone is now set to **${args.timezone}**`);
|
||||
},
|
||||
});
|
23
backend/src/plugins/TimeAndDate/commands/ViewTimezoneCmd.ts
Normal file
23
backend/src/plugins/TimeAndDate/commands/ViewTimezoneCmd.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { timeAndDateCmd } from "../types";
|
||||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||
import { sendSuccessMessage } from "../../../pluginUtils";
|
||||
import { getMemberTz } from "../functions/getMemberTz";
|
||||
import { getGuildTz } from "../functions/getGuildTz";
|
||||
|
||||
export const ViewTimezoneCmd = timeAndDateCmd({
|
||||
trigger: "timezone",
|
||||
permission: "can_set_timezone",
|
||||
|
||||
signature: {},
|
||||
|
||||
async run({ pluginData, message, args }) {
|
||||
const memberTimezone = await pluginData.state.memberTimezones.get(message.author.id);
|
||||
if (memberTimezone) {
|
||||
message.channel.createMessage(`Your timezone is currently set to **${memberTimezone.timezone}**`);
|
||||
return;
|
||||
}
|
||||
|
||||
const serverTimezone = getGuildTz(pluginData);
|
||||
message.channel.createMessage(`Your timezone is currently set to **${serverTimezone}** (server default)`);
|
||||
},
|
||||
});
|
5
backend/src/plugins/TimeAndDate/defaultDateFormats.ts
Normal file
5
backend/src/plugins/TimeAndDate/defaultDateFormats.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
export const defaultDateFormats = {
|
||||
date: "MMM D, YYYY",
|
||||
time: "H:mm",
|
||||
pretty_datetime: "MMM D, YYYY [at] H:mm z",
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
import { PluginData } from "knub";
|
||||
import { defaultDateFormats } from "../defaultDateFormats";
|
||||
|
||||
export function getDateFormat(pluginData: PluginData<any>, formatName: keyof typeof defaultDateFormats) {
|
||||
return pluginData.config.get().date_formats?.[formatName] || defaultDateFormats[formatName];
|
||||
}
|
7
backend/src/plugins/TimeAndDate/functions/getGuildTz.ts
Normal file
7
backend/src/plugins/TimeAndDate/functions/getGuildTz.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { PluginData } from "knub";
|
||||
import { ZeppelinGuildConfig } from "../../../types";
|
||||
import { TimeAndDatePluginType } from "../types";
|
||||
|
||||
export function getGuildTz(pluginData: PluginData<TimeAndDatePluginType>) {
|
||||
return pluginData.config.get().timezone;
|
||||
}
|
8
backend/src/plugins/TimeAndDate/functions/getMemberTz.ts
Normal file
8
backend/src/plugins/TimeAndDate/functions/getMemberTz.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { PluginData } from "knub";
|
||||
import { TimeAndDatePluginType } from "../types";
|
||||
import { getGuildTz } from "./getGuildTz";
|
||||
|
||||
export async function getMemberTz(pluginData: PluginData<TimeAndDatePluginType>, memberId: string) {
|
||||
const memberTz = await pluginData.state.memberTimezones.get(memberId);
|
||||
return memberTz?.timezone || getGuildTz(pluginData);
|
||||
}
|
17
backend/src/plugins/TimeAndDate/functions/inGuildTz.ts
Normal file
17
backend/src/plugins/TimeAndDate/functions/inGuildTz.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { PluginData } from "knub";
|
||||
import { TimeAndDatePluginType } from "../types";
|
||||
import moment from "moment-timezone";
|
||||
import { getGuildTz } from "./getGuildTz";
|
||||
|
||||
export function inGuildTz(pluginData: PluginData<TimeAndDatePluginType>, input?: moment.Moment | number) {
|
||||
let momentObj: moment.Moment;
|
||||
if (typeof input === "number") {
|
||||
momentObj = moment.utc(input, "x");
|
||||
} else if (moment.isMoment(input)) {
|
||||
momentObj = input.clone();
|
||||
} else {
|
||||
momentObj = moment.utc();
|
||||
}
|
||||
|
||||
return momentObj.tz(getGuildTz(pluginData));
|
||||
}
|
22
backend/src/plugins/TimeAndDate/functions/inMemberTz.ts
Normal file
22
backend/src/plugins/TimeAndDate/functions/inMemberTz.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { PluginData } from "knub";
|
||||
import { TimeAndDatePluginType } from "../types";
|
||||
import moment from "moment-timezone";
|
||||
import { getGuildTz } from "./getGuildTz";
|
||||
import { getMemberTz } from "./getMemberTz";
|
||||
|
||||
export async function inMemberTz(
|
||||
pluginData: PluginData<TimeAndDatePluginType>,
|
||||
memberId: string,
|
||||
input?: moment.Moment | number,
|
||||
) {
|
||||
let momentObj: moment.Moment;
|
||||
if (typeof input === "number") {
|
||||
momentObj = moment.utc(input, "x");
|
||||
} else if (moment.isMoment(input)) {
|
||||
momentObj = input.clone();
|
||||
} else {
|
||||
momentObj = moment.utc();
|
||||
}
|
||||
|
||||
return momentObj.tz(await getMemberTz(pluginData, memberId));
|
||||
}
|
22
backend/src/plugins/TimeAndDate/types.ts
Normal file
22
backend/src/plugins/TimeAndDate/types.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import * as t from "io-ts";
|
||||
import { tNullable, tPartialDictionary } from "../../utils";
|
||||
import { BasePluginType, command } from "knub";
|
||||
import { GuildMemberTimezones } from "../../data/GuildMemberTimezones";
|
||||
import { tValidTimezone } from "../../utils/tValidTimezone";
|
||||
import { defaultDateFormats } from "./defaultDateFormats";
|
||||
|
||||
export const ConfigSchema = t.type({
|
||||
timezone: tValidTimezone,
|
||||
date_formats: tNullable(tPartialDictionary(t.keyof(defaultDateFormats), t.string)),
|
||||
can_set_timezone: t.boolean,
|
||||
});
|
||||
export type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
|
||||
|
||||
export interface TimeAndDatePluginType extends BasePluginType {
|
||||
config: TConfigSchema;
|
||||
state: {
|
||||
memberTimezones: GuildMemberTimezones;
|
||||
};
|
||||
}
|
||||
|
||||
export const timeAndDateCmd = command<TimeAndDatePluginType>();
|
|
@ -33,6 +33,7 @@ import { MessageInfoCmd } from "./commands/MessageInfoCmd";
|
|||
import { InfoCmd } from "./commands/InfoCmd";
|
||||
import { SnowflakeInfoCmd } from "./commands/SnowflakeInfoCmd";
|
||||
import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners";
|
||||
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
const defaultOptions: PluginOptions<UtilityPluginType> = {
|
||||
config: {
|
||||
|
@ -101,6 +102,7 @@ export const UtilityPlugin = zeppelinPlugin<UtilityPluginType>()("utility", {
|
|||
prettyName: "Utility",
|
||||
},
|
||||
|
||||
dependencies: [TimeAndDatePlugin],
|
||||
configSchema: ConfigSchema,
|
||||
defaultOptions,
|
||||
|
||||
|
|
|
@ -6,9 +6,8 @@ import humanizeDuration from "humanize-duration";
|
|||
import LCL from "last-commit-log";
|
||||
import path from "path";
|
||||
import moment from "moment-timezone";
|
||||
import { getGuildTz, inGuildTz } from "../../../utils/timezones";
|
||||
import { rootDir } from "../../../paths";
|
||||
import { getDateFormat } from "../../../utils/dateFormats";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
export const AboutCmd = utilityCmd({
|
||||
trigger: "about",
|
||||
|
@ -16,6 +15,8 @@ export const AboutCmd = utilityCmd({
|
|||
permission: "can_about",
|
||||
|
||||
async run({ message: msg, pluginData }) {
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
|
||||
const uptime = getCurrentUptime();
|
||||
const prettyUptime = humanizeDuration(uptime, { largest: 2, round: true });
|
||||
|
||||
|
@ -30,9 +31,9 @@ export const AboutCmd = utilityCmd({
|
|||
let version;
|
||||
|
||||
if (lastCommit) {
|
||||
lastUpdate = inGuildTz(pluginData, moment.utc(lastCommit.committer.date, "X")).format(
|
||||
getDateFormat(pluginData, "pretty_datetime"),
|
||||
);
|
||||
lastUpdate = timeAndDate
|
||||
.inGuildTz(moment.utc(lastCommit.committer.date, "X"))
|
||||
.format(pluginData.getPlugin(TimeAndDatePlugin).getDateFormat("pretty_datetime"));
|
||||
version = lastCommit.shortHash;
|
||||
} else {
|
||||
lastUpdate = "?";
|
||||
|
@ -52,7 +53,7 @@ export const AboutCmd = utilityCmd({
|
|||
["Last update", lastUpdate],
|
||||
["Version", version],
|
||||
["API latency", `${shard.latency}ms`],
|
||||
["Server timezone", getGuildTz(pluginData)],
|
||||
["Server timezone", timeAndDate.getGuildTz()],
|
||||
];
|
||||
|
||||
const loadedPlugins = Array.from(
|
||||
|
|
|
@ -32,7 +32,7 @@ export const InfoCmd = utilityCmd({
|
|||
const channelId = getChannelId(value);
|
||||
const channel = channelId && pluginData.guild.channels.get(channelId);
|
||||
if (channel) {
|
||||
const embed = await getChannelInfoEmbed(pluginData, channelId);
|
||||
const embed = await getChannelInfoEmbed(pluginData, channelId, message.author.id);
|
||||
if (embed) {
|
||||
message.channel.createMessage({ embed });
|
||||
return;
|
||||
|
@ -42,7 +42,7 @@ export const InfoCmd = utilityCmd({
|
|||
// 2. Server
|
||||
const guild = pluginData.client.guilds.get(value);
|
||||
if (guild) {
|
||||
const embed = await getServerInfoEmbed(pluginData, value);
|
||||
const embed = await getServerInfoEmbed(pluginData, value, message.author.id);
|
||||
if (embed) {
|
||||
message.channel.createMessage({ embed });
|
||||
return;
|
||||
|
@ -52,7 +52,7 @@ export const InfoCmd = utilityCmd({
|
|||
// 3. User
|
||||
const user = await resolveUser(pluginData.client, value);
|
||||
if (user) {
|
||||
const embed = await getUserInfoEmbed(pluginData, user.id, Boolean(args.compact));
|
||||
const embed = await getUserInfoEmbed(pluginData, user.id, Boolean(args.compact), message.author.id);
|
||||
if (embed) {
|
||||
message.channel.createMessage({ embed });
|
||||
return;
|
||||
|
@ -63,7 +63,12 @@ export const InfoCmd = utilityCmd({
|
|||
const messageTarget = await resolveMessageTarget(pluginData, value);
|
||||
if (messageTarget) {
|
||||
if (canReadChannel(messageTarget.channel, message.member)) {
|
||||
const embed = await getMessageInfoEmbed(pluginData, messageTarget.channel.id, messageTarget.messageId);
|
||||
const embed = await getMessageInfoEmbed(
|
||||
pluginData,
|
||||
messageTarget.channel.id,
|
||||
messageTarget.messageId,
|
||||
message.author.id,
|
||||
);
|
||||
if (embed) {
|
||||
message.channel.createMessage({ embed });
|
||||
return;
|
||||
|
@ -87,7 +92,7 @@ export const InfoCmd = utilityCmd({
|
|||
// 6. Server again (fallback for discovery servers)
|
||||
const serverPreview = getGuildPreview(pluginData.client, value).catch(() => null);
|
||||
if (serverPreview) {
|
||||
const embed = await getServerInfoEmbed(pluginData, value);
|
||||
const embed = await getServerInfoEmbed(pluginData, value, message.author.id);
|
||||
if (embed) {
|
||||
message.channel.createMessage({ embed });
|
||||
return;
|
||||
|
@ -96,7 +101,7 @@ export const InfoCmd = utilityCmd({
|
|||
|
||||
// 7. Arbitrary ID
|
||||
if (isValidSnowflake(value)) {
|
||||
const embed = getSnowflakeInfoEmbed(pluginData, value, true);
|
||||
const embed = await getSnowflakeInfoEmbed(pluginData, value, true, message.author.id);
|
||||
message.channel.createMessage({ embed });
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,12 @@ export const MessageInfoCmd = utilityCmd({
|
|||
return;
|
||||
}
|
||||
|
||||
const embed = await getMessageInfoEmbed(pluginData, args.message.channel.id, args.message.messageId);
|
||||
const embed = await getMessageInfoEmbed(
|
||||
pluginData,
|
||||
args.message.channel.id,
|
||||
args.message.messageId,
|
||||
message.author.id,
|
||||
);
|
||||
if (!embed) {
|
||||
sendErrorMessage(pluginData, message.channel, "Unknown message");
|
||||
return;
|
||||
|
|
|
@ -15,7 +15,7 @@ export const ServerCmd = utilityCmd({
|
|||
|
||||
async run({ message, pluginData, args }) {
|
||||
const serverId = args.serverId || pluginData.guild.id;
|
||||
const serverInfoEmbed = await getServerInfoEmbed(pluginData, serverId);
|
||||
const serverInfoEmbed = await getServerInfoEmbed(pluginData, serverId, message.author.id);
|
||||
if (!serverInfoEmbed) {
|
||||
sendErrorMessage(pluginData, message.channel, "Could not find information for that server");
|
||||
return;
|
||||
|
|
|
@ -14,8 +14,8 @@ export const SnowflakeInfoCmd = utilityCmd({
|
|||
id: ct.anyId(),
|
||||
},
|
||||
|
||||
run({ message, args, pluginData }) {
|
||||
const embed = getSnowflakeInfoEmbed(pluginData, args.id);
|
||||
async run({ message, args, pluginData }) {
|
||||
const embed = await getSnowflakeInfoEmbed(pluginData, args.id, false, message.author.id);
|
||||
message.channel.createMessage({ embed });
|
||||
},
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ export const UserInfoCmd = utilityCmd({
|
|||
|
||||
async run({ message, args, pluginData }) {
|
||||
const userId = args.user?.id || message.author.id;
|
||||
const embed = await getUserInfoEmbed(pluginData, userId, args.compact);
|
||||
const embed = await getUserInfoEmbed(pluginData, userId, args.compact, message.author.id);
|
||||
if (!embed) {
|
||||
sendErrorMessage(pluginData, message.channel, "User not found");
|
||||
return;
|
||||
|
|
|
@ -4,8 +4,7 @@ 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";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
const TEXT_CHANNEL_ICON =
|
||||
"https://cdn.discordapp.com/attachments/740650744830623756/740656843545772062/text-channel.png";
|
||||
|
@ -17,6 +16,7 @@ const ANNOUNCEMENT_CHANNEL_ICON =
|
|||
export async function getChannelInfoEmbed(
|
||||
pluginData: PluginData<UtilityPluginType>,
|
||||
channelId: string,
|
||||
requestMemberId?: string,
|
||||
): Promise<EmbedOptions | null> {
|
||||
const channel = pluginData.guild.channels.get(channelId);
|
||||
if (!channel) {
|
||||
|
@ -58,7 +58,11 @@ export async function getChannelInfoEmbed(
|
|||
}
|
||||
|
||||
const createdAt = moment.utc(channel.createdAt, "x");
|
||||
const prettyCreatedAt = inGuildTz(pluginData, createdAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
const tzCreatedAt = requestMemberId
|
||||
? await timeAndDate.inMemberTz(requestMemberId, createdAt)
|
||||
: timeAndDate.inGuildTz(createdAt);
|
||||
const prettyCreatedAt = tzCreatedAt.format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
const channelAge = humanizeDuration(Date.now() - channel.createdAt, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
|
|
|
@ -5,8 +5,7 @@ import moment from "moment-timezone";
|
|||
import humanizeDuration from "humanize-duration";
|
||||
import { chunkMessageLines, messageLink, preEmbedPadding, trimEmptyLines, trimLines } from "../../../utils";
|
||||
import { getDefaultPrefix } from "knub/dist/commands/commandUtils";
|
||||
import { inGuildTz } from "../../../utils/timezones";
|
||||
import { getDateFormat } from "../../../utils/dateFormats";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
const MESSAGE_ICON = "https://cdn.discordapp.com/attachments/740650744830623756/740685652152025088/message.png";
|
||||
|
||||
|
@ -14,12 +13,15 @@ export async function getMessageInfoEmbed(
|
|||
pluginData: PluginData<UtilityPluginType>,
|
||||
channelId: string,
|
||||
messageId: string,
|
||||
requestMemberId?: string,
|
||||
): Promise<EmbedOptions | null> {
|
||||
const message = await pluginData.client.getMessage(channelId, messageId).catch(() => null);
|
||||
if (!message) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
|
||||
const embed: EmbedOptions = {
|
||||
fields: [],
|
||||
};
|
||||
|
@ -30,14 +32,20 @@ export async function getMessageInfoEmbed(
|
|||
};
|
||||
|
||||
const createdAt = moment.utc(message.createdAt, "x");
|
||||
const prettyCreatedAt = inGuildTz(pluginData, createdAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const tzCreatedAt = requestMemberId
|
||||
? await timeAndDate.inMemberTz(requestMemberId, createdAt)
|
||||
: timeAndDate.inGuildTz(createdAt);
|
||||
const prettyCreatedAt = tzCreatedAt.format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
const messageAge = humanizeDuration(Date.now() - message.createdAt, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
});
|
||||
|
||||
const editedAt = message.editedTimestamp && moment.utc(message.editedTimestamp, "x");
|
||||
const prettyEditedAt = inGuildTz(pluginData, editedAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const tzEditedAt = requestMemberId
|
||||
? await timeAndDate.inMemberTz(requestMemberId, editedAt)
|
||||
: timeAndDate.inGuildTz(editedAt);
|
||||
const prettyEditedAt = tzEditedAt.format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
const editAge =
|
||||
message.editedTimestamp &&
|
||||
humanizeDuration(Date.now() - message.editedTimestamp, {
|
||||
|
@ -75,18 +83,20 @@ export async function getMessageInfoEmbed(
|
|||
});
|
||||
|
||||
const authorCreatedAt = moment.utc(message.author.createdAt, "x");
|
||||
const prettyAuthorCreatedAt = inGuildTz(pluginData, authorCreatedAt).format(
|
||||
getDateFormat(pluginData, "pretty_datetime"),
|
||||
);
|
||||
const tzAuthorCreatedAt = requestMemberId
|
||||
? await timeAndDate.inMemberTz(requestMemberId, authorCreatedAt)
|
||||
: timeAndDate.inGuildTz(authorCreatedAt);
|
||||
const prettyAuthorCreatedAt = tzAuthorCreatedAt.format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
const authorAccountAge = humanizeDuration(Date.now() - message.author.createdAt, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
});
|
||||
|
||||
const authorJoinedAt = message.member && moment.utc(message.member.joinedAt, "x");
|
||||
const prettyAuthorJoinedAt = inGuildTz(pluginData, authorJoinedAt).format(
|
||||
getDateFormat(pluginData, "pretty_datetime"),
|
||||
);
|
||||
const tzAuthorJoinedAt = requestMemberId
|
||||
? await timeAndDate.inMemberTz(requestMemberId, authorJoinedAt)
|
||||
: timeAndDate.inGuildTz(authorJoinedAt);
|
||||
const prettyAuthorJoinedAt = tzAuthorJoinedAt.format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
const authorServerAge =
|
||||
message.member &&
|
||||
humanizeDuration(Date.now() - message.member.joinedAt, {
|
||||
|
|
|
@ -5,12 +5,12 @@ 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";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
export async function getServerInfoEmbed(
|
||||
pluginData: PluginData<UtilityPluginType>,
|
||||
serverId: string,
|
||||
requestMemberId?: string,
|
||||
): Promise<EmbedOptions> {
|
||||
const thisServer = serverId === pluginData.guild.id ? pluginData.guild : null;
|
||||
const [restGuild, guildPreview] = await Promise.all([
|
||||
|
@ -39,8 +39,12 @@ export async function getServerInfoEmbed(
|
|||
};
|
||||
|
||||
// BASIC INFORMATION
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
const createdAt = moment.utc((guildPreview || restGuild).createdAt, "x");
|
||||
const prettyCreatedAt = inGuildTz(pluginData, createdAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const tzCreatedAt = requestMemberId
|
||||
? await timeAndDate.inMemberTz(requestMemberId, createdAt)
|
||||
: timeAndDate.inGuildTz(createdAt);
|
||||
const prettyCreatedAt = tzCreatedAt.format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
const serverAge = humanizeDuration(moment.utc().valueOf() - createdAt.valueOf(), {
|
||||
largest: 2,
|
||||
round: true,
|
||||
|
|
|
@ -6,16 +6,16 @@ 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";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
const SNOWFLAKE_ICON = "https://cdn.discordapp.com/attachments/740650744830623756/742020790471491668/snowflake.png";
|
||||
|
||||
export function getSnowflakeInfoEmbed(
|
||||
export async function getSnowflakeInfoEmbed(
|
||||
pluginData: PluginData<UtilityPluginType>,
|
||||
snowflake: string,
|
||||
showUnknownWarning = false,
|
||||
): EmbedOptions {
|
||||
requestMemberId?: string,
|
||||
): Promise<EmbedOptions> {
|
||||
const embed: EmbedOptions = {
|
||||
fields: [],
|
||||
};
|
||||
|
@ -30,9 +30,13 @@ export function getSnowflakeInfoEmbed(
|
|||
"This is a valid [snowflake ID](https://discord.com/developers/docs/reference#snowflakes), but I don't know what it's for.";
|
||||
}
|
||||
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
const createdAtMS = snowflakeToTimestamp(snowflake);
|
||||
const createdAt = moment.utc(createdAtMS, "x");
|
||||
const prettyCreatedAt = inGuildTz(pluginData, createdAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const tzCreatedAt = requestMemberId
|
||||
? await timeAndDate.inMemberTz(requestMemberId, createdAt)
|
||||
: timeAndDate.inGuildTz(createdAt);
|
||||
const prettyCreatedAt = tzCreatedAt.format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
const snowflakeAge = humanizeDuration(Date.now() - createdAtMS, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
|
|
|
@ -14,13 +14,13 @@ import {
|
|||
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";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
export async function getUserInfoEmbed(
|
||||
pluginData: PluginData<UtilityPluginType>,
|
||||
userId: string,
|
||||
compact = false,
|
||||
requestMemberId?: string,
|
||||
): Promise<EmbedOptions | null> {
|
||||
const user = await resolveUser(pluginData.client, userId);
|
||||
if (!user || user instanceof UnknownUser) {
|
||||
|
@ -33,6 +33,8 @@ export async function getUserInfoEmbed(
|
|||
fields: [],
|
||||
};
|
||||
|
||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||
|
||||
embed.author = {
|
||||
name: `User: ${user.username}#${user.discriminator}`,
|
||||
};
|
||||
|
@ -41,7 +43,10 @@ export async function getUserInfoEmbed(
|
|||
embed.author.icon_url = avatarURL;
|
||||
|
||||
const createdAt = moment.utc(user.createdAt, "x");
|
||||
const prettyCreatedAt = inGuildTz(pluginData, createdAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const tzCreatedAt = requestMemberId
|
||||
? await timeAndDate.inMemberTz(requestMemberId, createdAt)
|
||||
: timeAndDate.inGuildTz(createdAt);
|
||||
const prettyCreatedAt = tzCreatedAt.format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
const accountAge = humanizeDuration(moment.utc().valueOf() - user.createdAt, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
|
@ -57,7 +62,10 @@ export async function getUserInfoEmbed(
|
|||
});
|
||||
if (member) {
|
||||
const joinedAt = moment.utc(member.joinedAt, "x");
|
||||
const prettyJoinedAt = inGuildTz(pluginData, joinedAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const tzJoinedAt = requestMemberId
|
||||
? await timeAndDate.inMemberTz(requestMemberId, joinedAt)
|
||||
: timeAndDate.inGuildTz(joinedAt);
|
||||
const prettyJoinedAt = tzJoinedAt.format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
const joinAge = humanizeDuration(moment.utc().valueOf() - member.joinedAt, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
|
@ -85,7 +93,10 @@ export async function getUserInfoEmbed(
|
|||
|
||||
if (member) {
|
||||
const joinedAt = moment.utc(member.joinedAt, "x");
|
||||
const prettyJoinedAt = inGuildTz(pluginData, joinedAt).format(getDateFormat(pluginData, "pretty_datetime"));
|
||||
const tzJoinedAt = requestMemberId
|
||||
? await timeAndDate.inMemberTz(requestMemberId, joinedAt)
|
||||
: timeAndDate.inGuildTz(joinedAt);
|
||||
const prettyJoinedAt = tzJoinedAt.format(timeAndDate.getDateFormat("pretty_datetime"));
|
||||
const joinAge = humanizeDuration(moment.utc().valueOf() - member.joinedAt, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
|
|
|
@ -31,6 +31,7 @@ import { CompanionChannelsPlugin } from "./CompanionChannels/CompanionChannelsPl
|
|||
import { CustomEventsPlugin } from "./CustomEvents/CustomEventsPlugin";
|
||||
import { BotControlPlugin } from "./BotControl/BotControlPlugin";
|
||||
import { GuildAccessMonitorPlugin } from "./GuildAccessMonitor/GuildAccessMonitorPlugin";
|
||||
import { TimeAndDatePlugin } from "./TimeAndDate/TimeAndDatePlugin";
|
||||
|
||||
// prettier-ignore
|
||||
export const guildPlugins: Array<ZeppelinPluginBlueprint<any>> = [
|
||||
|
@ -63,6 +64,7 @@ export const guildPlugins: Array<ZeppelinPluginBlueprint<any>> = [
|
|||
AutomodPlugin,
|
||||
CompanionChannelsPlugin,
|
||||
CustomEventsPlugin,
|
||||
TimeAndDatePlugin,
|
||||
];
|
||||
|
||||
// prettier-ignore
|
||||
|
@ -79,5 +81,6 @@ export const baseGuildPlugins: Array<ZeppelinPluginBlueprint<any>> = [
|
|||
NameHistoryPlugin,
|
||||
CasesPlugin,
|
||||
MutesPlugin,
|
||||
TimeAndDatePlugin,
|
||||
// TODO: Replace these with proper dependencies
|
||||
];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue