Add !slowmode command

This commit is contained in:
Dragory 2020-08-09 17:28:21 +03:00
parent 2d8decdb4f
commit 5215dd0738
No known key found for this signature in database
GPG key ID: 5F387BA66DF8AAC1
10 changed files with 122 additions and 2 deletions

View file

@ -1,10 +1,14 @@
import {
channelMentionRegex,
convertDelayStringToMS,
disableCodeBlocks,
disableInlineCode,
isSnowflake,
isValidSnowflake,
resolveMember,
resolveUser,
resolveUserId,
roleMentionRegex,
UnknownUser,
} from "./utils";
import { GuildChannel, Member, TextChannel, User } from "eris";
@ -63,6 +67,23 @@ export const commandTypes = {
return result;
},
async anyId(value: string, context: CommandContext<any>) {
const userId = resolveUserId(context.pluginData.client, value);
if (userId) return userId;
const channelIdMatch = value.match(channelMentionRegex);
if (channelIdMatch) return channelIdMatch[1];
const roleIdMatch = value.match(roleMentionRegex);
if (roleIdMatch) return roleIdMatch[1];
if (isValidSnowflake(value)) {
return value;
}
throw new TypeConversionError(`Could not parse ID: \`${disableInlineCode(value)}\``);
},
};
export const commandTypeHelpers = {
@ -73,4 +94,5 @@ export const commandTypeHelpers = {
resolvedUserLoose: createTypeHelper<Promise<User | UnknownUser>>(commandTypes.resolvedUserLoose),
resolvedMember: createTypeHelper<Promise<Member | null>>(commandTypes.resolvedMember),
messageTarget: createTypeHelper<Promise<MessageTarget>>(commandTypes.messageTarget),
anyId: createTypeHelper<Promise<string>>(commandTypes.anyId),
};

View file

@ -31,6 +31,7 @@ import { InviteInfoCmd } from "./commands/InviteInfoCmd";
import { ChannelInfoCmd } from "./commands/ChannelInfoCmd";
import { MessageInfoCmd } from "./commands/MessageInfoCmd";
import { InfoCmd } from "./commands/InfoCmd";
import { SnowflakeInfoCmd } from "./commands/SnowflakeInfoCmd";
const defaultOptions: PluginOptions<UtilityPluginType> = {
config: {
@ -44,6 +45,7 @@ const defaultOptions: PluginOptions<UtilityPluginType> = {
can_channelinfo: false,
can_messageinfo: false,
can_userinfo: false,
can_snowflake: false,
can_reload_guild: false,
can_nickname: false,
can_ping: false,
@ -71,6 +73,7 @@ const defaultOptions: PluginOptions<UtilityPluginType> = {
can_channelinfo: true,
can_messageinfo: true,
can_userinfo: true,
can_snowflake: true,
can_nickname: true,
can_vcmove: true,
can_help: true,
@ -124,6 +127,7 @@ export const UtilityPlugin = zeppelinPlugin<UtilityPluginType>()("utility", {
ChannelInfoCmd,
MessageInfoCmd,
InfoCmd,
SnowflakeInfoCmd,
],
onLoad(pluginData) {

View file

@ -2,7 +2,7 @@ import { utilityCmd } from "../types";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage } from "../../../pluginUtils";
import { getInviteInfoEmbed } from "../functions/getInviteInfoEmbed";
import { parseInviteCodeInput, resolveInvite, resolveUser } from "../../../utils";
import { isValidSnowflake, parseInviteCodeInput, resolveInvite, resolveUser } from "../../../utils";
import { getUserInfoEmbed } from "../functions/getUserInfoEmbed";
import { resolveMessageTarget } from "../../../utils/resolveMessageTarget";
import { canReadChannel } from "../../../utils/canReadChannel";
@ -11,6 +11,7 @@ import { getChannelInfoEmbed } from "../functions/getChannelInfoEmbed";
import { getServerInfoEmbed } from "../functions/getServerInfoEmbed";
import { getChannelId } from "knub/dist/utils";
import { getGuildPreview } from "../functions/getGuildPreview";
import { getSnowflakeInfoEmbed } from "../functions/getSnowflakeInfoEmbed";
export const InfoCmd = utilityCmd({
trigger: "info",
@ -93,6 +94,13 @@ export const InfoCmd = utilityCmd({
}
}
// 7. Arbitrary ID
if (isValidSnowflake(value)) {
const embed = getSnowflakeInfoEmbed(pluginData, value, true);
message.channel.createMessage({ embed });
return;
}
// 7. No can do
sendErrorMessage(pluginData, message.channel, "Could not find anything with that value");
},

View file

@ -0,0 +1,21 @@
import { utilityCmd } from "../types";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage } from "../../../pluginUtils";
import { getChannelInfoEmbed } from "../functions/getChannelInfoEmbed";
import { getSnowflakeInfoEmbed } from "../functions/getSnowflakeInfoEmbed";
export const SnowflakeInfoCmd = utilityCmd({
trigger: ["snowflake", "snowflakeinfo"],
description: "Show information about a snowflake ID",
usage: "!snowflake 534722016549404673",
permission: "can_snowflake",
signature: {
id: ct.anyId(),
},
run({ message, args, pluginData }) {
const embed = getSnowflakeInfoEmbed(pluginData, args.id);
message.channel.createMessage({ embed });
},
});

View file

@ -0,0 +1,44 @@
import { Message, GuildTextableChannel, EmbedOptions } from "eris";
import { PluginData } from "knub";
import { UtilityPluginType } from "../types";
import { UnknownUser, trimLines, embedPadding, resolveMember, resolveUser, preEmbedPadding } from "src/utils";
import moment from "moment-timezone";
import { CaseTypes } from "src/data/CaseTypes";
import humanizeDuration from "humanize-duration";
import { snowflakeToTimestamp } from "../../../utils/snowflakeToTimestamp";
const SNOWFLAKE_ICON = "https://cdn.discordapp.com/attachments/740650744830623756/742020790471491668/snowflake.png";
export function getSnowflakeInfoEmbed(
pluginData: PluginData<UtilityPluginType>,
snowflake: string,
showUnknownWarning = false,
): EmbedOptions {
const embed: EmbedOptions = {
fields: [],
};
embed.author = {
name: `Snowflake: ${snowflake}`,
icon_url: SNOWFLAKE_ICON,
};
if (showUnknownWarning) {
embed.description =
"This is a valid [snowflake ID](https://discord.com/developers/docs/reference#snowflakes), but I don't know what it's for.";
}
const createdAtMS = snowflakeToTimestamp(snowflake);
const createdAt = moment(createdAtMS, "x");
const snowflakeAge = humanizeDuration(Date.now() - createdAtMS, {
largest: 2,
round: true,
});
embed.fields.push({
name: preEmbedPadding + "Basic information",
value: `Created: **${snowflakeAge} ago** (\`${createdAt.format("MMM D, YYYY [at] H:mm [UTC]")}\`)`,
});
return embed;
}

View file

@ -17,6 +17,7 @@ export const ConfigSchema = t.type({
can_channelinfo: t.boolean,
can_messageinfo: t.boolean,
can_userinfo: t.boolean,
can_snowflake: t.boolean,
can_reload_guild: t.boolean,
can_nickname: t.boolean,
can_ping: t.boolean,

View file

@ -58,6 +58,19 @@ export const WEEKS = 7 * 24 * HOURS;
export const EMPTY_CHAR = "\u200b";
// https://discord.com/developers/docs/reference#snowflakes
export const MIN_SNOWFLAKE = 0b000000000000000000000000000000000000000000_00001_00001_000000000001;
// 0b111111111111111111111111111111111111111111_11111_11111_111111111111 without _ which BigInt doesn't support
export const MAX_SNOWFLAKE = BigInt("0b1111111111111111111111111111111111111111111111111111111111111111");
const snowflakePattern = /^[1-9]\d+$/;
export function isValidSnowflake(str: string) {
if (!str.match(snowflakePattern)) return false;
if (parseInt(str, 10) < MIN_SNOWFLAKE) return false;
if (BigInt(str) > MAX_SNOWFLAKE) return false;
return true;
}
export const DISCORD_HTTP_ERROR_NAME = "DiscordHTTPError";
export const DISCORD_REST_ERROR_NAME = "DiscordRESTError";

View file

@ -1,7 +1,13 @@
import { isValidSnowflake } from "../utils";
/**
* @return Unix timestamp in milliseconds
*/
export function snowflakeToTimestamp(snowflake: string) {
if (!isValidSnowflake(snowflake)) {
throw new Error(`Invalid snowflake: ${snowflake}`);
}
// https://discord.com/developers/docs/reference#snowflakes-snowflake-id-format-structure-left-to-right
return Number(BigInt(snowflake) >> 22n) + 1420070400000;
return Number(BigInt(snowflake) >> 22n) + 1_420_070_400_000;
}