Add !slowmode command
This commit is contained in:
parent
2d8decdb4f
commit
5215dd0738
10 changed files with 122 additions and 2 deletions
BIN
assets/icons/snowflake.png
Normal file
BIN
assets/icons/snowflake.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
1
assets/icons/snowflake.svg
Normal file
1
assets/icons/snowflake.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#88C9F9" d="M19 27.586V8.415l4.828-4.829s.707-.707 0-1.415c-.707-.707-1.414 0-1.414 0L19 5.586V1s0-1-1-1-1 1-1 1v4.586l-3.414-3.415s-.707-.707-1.414 0c-.707.708 0 1.415 0 1.415L17 8.415v19.171l-4.828 4.828s-.707.707 0 1.414 1.414 0 1.414 0L17 30.414V35s0 1 1 1 1-1 1-1v-4.586l3.414 3.414s.707.707 1.414 0 0-1.414 0-1.414L19 27.586z"/><path fill="#88C9F9" d="M34.622 20.866c-.259-.966-1.225-.707-1.225-.707l-6.595 1.767-16.603-9.586-1.767-6.595s-.259-.966-1.225-.707C6.24 5.297 6.5 6.263 6.5 6.263l1.25 4.664-3.972-2.294s-.866-.5-1.366.366c-.5.866.366 1.366.366 1.366l3.971 2.293-4.664 1.249s-.967.259-.707 1.225c.259.967 1.225.708 1.225.708l6.596-1.767 16.603 9.586 1.767 6.596s.259.966 1.225.707c.966-.26.707-1.225.707-1.225l-1.25-4.664 3.972 2.293s.867.5 1.367-.365c.5-.867-.367-1.367-.367-1.367l-3.971-2.293 4.663-1.249c0-.001.966-.26.707-1.226z"/><path fill="#88C9F9" d="M33.915 13.907l-4.664-1.25 3.972-2.293s.867-.501.367-1.367c-.501-.867-1.367-.366-1.367-.366l-3.971 2.292 1.249-4.663s.259-.966-.707-1.225c-.966-.259-1.225.707-1.225.707l-1.767 6.595-16.604 9.589-6.594-1.768s-.966-.259-1.225.707c-.26.967.707 1.225.707 1.225l4.663 1.249-3.971 2.293s-.865.501-.365 1.367c.5.865 1.365.365 1.365.365l3.972-2.293-1.25 4.663s-.259.967.707 1.225c.967.26 1.226-.706 1.226-.706l1.768-6.597 16.604-9.585 6.595 1.768s.966.259 1.225-.707c.255-.967-.71-1.225-.71-1.225z"/></svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -1,10 +1,14 @@
|
||||||
import {
|
import {
|
||||||
|
channelMentionRegex,
|
||||||
convertDelayStringToMS,
|
convertDelayStringToMS,
|
||||||
disableCodeBlocks,
|
disableCodeBlocks,
|
||||||
disableInlineCode,
|
disableInlineCode,
|
||||||
isSnowflake,
|
isSnowflake,
|
||||||
|
isValidSnowflake,
|
||||||
resolveMember,
|
resolveMember,
|
||||||
resolveUser,
|
resolveUser,
|
||||||
|
resolveUserId,
|
||||||
|
roleMentionRegex,
|
||||||
UnknownUser,
|
UnknownUser,
|
||||||
} from "./utils";
|
} from "./utils";
|
||||||
import { GuildChannel, Member, TextChannel, User } from "eris";
|
import { GuildChannel, Member, TextChannel, User } from "eris";
|
||||||
|
@ -63,6 +67,23 @@ export const commandTypes = {
|
||||||
|
|
||||||
return result;
|
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 = {
|
export const commandTypeHelpers = {
|
||||||
|
@ -73,4 +94,5 @@ export const commandTypeHelpers = {
|
||||||
resolvedUserLoose: createTypeHelper<Promise<User | UnknownUser>>(commandTypes.resolvedUserLoose),
|
resolvedUserLoose: createTypeHelper<Promise<User | UnknownUser>>(commandTypes.resolvedUserLoose),
|
||||||
resolvedMember: createTypeHelper<Promise<Member | null>>(commandTypes.resolvedMember),
|
resolvedMember: createTypeHelper<Promise<Member | null>>(commandTypes.resolvedMember),
|
||||||
messageTarget: createTypeHelper<Promise<MessageTarget>>(commandTypes.messageTarget),
|
messageTarget: createTypeHelper<Promise<MessageTarget>>(commandTypes.messageTarget),
|
||||||
|
anyId: createTypeHelper<Promise<string>>(commandTypes.anyId),
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,6 +31,7 @@ import { InviteInfoCmd } from "./commands/InviteInfoCmd";
|
||||||
import { ChannelInfoCmd } from "./commands/ChannelInfoCmd";
|
import { ChannelInfoCmd } from "./commands/ChannelInfoCmd";
|
||||||
import { MessageInfoCmd } from "./commands/MessageInfoCmd";
|
import { MessageInfoCmd } from "./commands/MessageInfoCmd";
|
||||||
import { InfoCmd } from "./commands/InfoCmd";
|
import { InfoCmd } from "./commands/InfoCmd";
|
||||||
|
import { SnowflakeInfoCmd } from "./commands/SnowflakeInfoCmd";
|
||||||
|
|
||||||
const defaultOptions: PluginOptions<UtilityPluginType> = {
|
const defaultOptions: PluginOptions<UtilityPluginType> = {
|
||||||
config: {
|
config: {
|
||||||
|
@ -44,6 +45,7 @@ const defaultOptions: PluginOptions<UtilityPluginType> = {
|
||||||
can_channelinfo: false,
|
can_channelinfo: false,
|
||||||
can_messageinfo: false,
|
can_messageinfo: false,
|
||||||
can_userinfo: false,
|
can_userinfo: false,
|
||||||
|
can_snowflake: false,
|
||||||
can_reload_guild: false,
|
can_reload_guild: false,
|
||||||
can_nickname: false,
|
can_nickname: false,
|
||||||
can_ping: false,
|
can_ping: false,
|
||||||
|
@ -71,6 +73,7 @@ const defaultOptions: PluginOptions<UtilityPluginType> = {
|
||||||
can_channelinfo: true,
|
can_channelinfo: true,
|
||||||
can_messageinfo: true,
|
can_messageinfo: true,
|
||||||
can_userinfo: true,
|
can_userinfo: true,
|
||||||
|
can_snowflake: true,
|
||||||
can_nickname: true,
|
can_nickname: true,
|
||||||
can_vcmove: true,
|
can_vcmove: true,
|
||||||
can_help: true,
|
can_help: true,
|
||||||
|
@ -124,6 +127,7 @@ export const UtilityPlugin = zeppelinPlugin<UtilityPluginType>()("utility", {
|
||||||
ChannelInfoCmd,
|
ChannelInfoCmd,
|
||||||
MessageInfoCmd,
|
MessageInfoCmd,
|
||||||
InfoCmd,
|
InfoCmd,
|
||||||
|
SnowflakeInfoCmd,
|
||||||
],
|
],
|
||||||
|
|
||||||
onLoad(pluginData) {
|
onLoad(pluginData) {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { utilityCmd } from "../types";
|
||||||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||||
import { sendErrorMessage } from "../../../pluginUtils";
|
import { sendErrorMessage } from "../../../pluginUtils";
|
||||||
import { getInviteInfoEmbed } from "../functions/getInviteInfoEmbed";
|
import { getInviteInfoEmbed } from "../functions/getInviteInfoEmbed";
|
||||||
import { parseInviteCodeInput, resolveInvite, resolveUser } from "../../../utils";
|
import { isValidSnowflake, parseInviteCodeInput, resolveInvite, resolveUser } from "../../../utils";
|
||||||
import { getUserInfoEmbed } from "../functions/getUserInfoEmbed";
|
import { getUserInfoEmbed } from "../functions/getUserInfoEmbed";
|
||||||
import { resolveMessageTarget } from "../../../utils/resolveMessageTarget";
|
import { resolveMessageTarget } from "../../../utils/resolveMessageTarget";
|
||||||
import { canReadChannel } from "../../../utils/canReadChannel";
|
import { canReadChannel } from "../../../utils/canReadChannel";
|
||||||
|
@ -11,6 +11,7 @@ import { getChannelInfoEmbed } from "../functions/getChannelInfoEmbed";
|
||||||
import { getServerInfoEmbed } from "../functions/getServerInfoEmbed";
|
import { getServerInfoEmbed } from "../functions/getServerInfoEmbed";
|
||||||
import { getChannelId } from "knub/dist/utils";
|
import { getChannelId } from "knub/dist/utils";
|
||||||
import { getGuildPreview } from "../functions/getGuildPreview";
|
import { getGuildPreview } from "../functions/getGuildPreview";
|
||||||
|
import { getSnowflakeInfoEmbed } from "../functions/getSnowflakeInfoEmbed";
|
||||||
|
|
||||||
export const InfoCmd = utilityCmd({
|
export const InfoCmd = utilityCmd({
|
||||||
trigger: "info",
|
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
|
// 7. No can do
|
||||||
sendErrorMessage(pluginData, message.channel, "Could not find anything with that value");
|
sendErrorMessage(pluginData, message.channel, "Could not find anything with that value");
|
||||||
},
|
},
|
||||||
|
|
21
backend/src/plugins/Utility/commands/SnowflakeInfoCmd.ts
Normal file
21
backend/src/plugins/Utility/commands/SnowflakeInfoCmd.ts
Normal 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 });
|
||||||
|
},
|
||||||
|
});
|
|
@ -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;
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ export const ConfigSchema = t.type({
|
||||||
can_channelinfo: t.boolean,
|
can_channelinfo: t.boolean,
|
||||||
can_messageinfo: t.boolean,
|
can_messageinfo: t.boolean,
|
||||||
can_userinfo: t.boolean,
|
can_userinfo: t.boolean,
|
||||||
|
can_snowflake: t.boolean,
|
||||||
can_reload_guild: t.boolean,
|
can_reload_guild: t.boolean,
|
||||||
can_nickname: t.boolean,
|
can_nickname: t.boolean,
|
||||||
can_ping: t.boolean,
|
can_ping: t.boolean,
|
||||||
|
|
|
@ -58,6 +58,19 @@ export const WEEKS = 7 * 24 * HOURS;
|
||||||
|
|
||||||
export const EMPTY_CHAR = "\u200b";
|
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_HTTP_ERROR_NAME = "DiscordHTTPError";
|
||||||
export const DISCORD_REST_ERROR_NAME = "DiscordRESTError";
|
export const DISCORD_REST_ERROR_NAME = "DiscordRESTError";
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
|
import { isValidSnowflake } from "../utils";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Unix timestamp in milliseconds
|
* @return Unix timestamp in milliseconds
|
||||||
*/
|
*/
|
||||||
export function snowflakeToTimestamp(snowflake: string) {
|
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
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue