aboutsummaryrefslogtreecommitdiff
path: root/lib/arguments
diff options
context:
space:
mode:
Diffstat (limited to 'lib/arguments')
-rw-r--r--lib/arguments/abbreviatedNumber.ts13
-rw-r--r--lib/arguments/contentWithDuration.ts5
-rw-r--r--lib/arguments/discordEmoji.ts14
-rw-r--r--lib/arguments/duration.ts5
-rw-r--r--lib/arguments/durationSeconds.ts6
-rw-r--r--lib/arguments/globalUser.ts7
-rw-r--r--lib/arguments/index.ts10
-rw-r--r--lib/arguments/messageLink.ts20
-rw-r--r--lib/arguments/permission.ts12
-rw-r--r--lib/arguments/roleWithDuration.ts17
-rw-r--r--lib/arguments/snowflake.ts8
-rw-r--r--lib/arguments/tinyColor.ts10
12 files changed, 127 insertions, 0 deletions
diff --git a/lib/arguments/abbreviatedNumber.ts b/lib/arguments/abbreviatedNumber.ts
new file mode 100644
index 0000000..a7d8ce5
--- /dev/null
+++ b/lib/arguments/abbreviatedNumber.ts
@@ -0,0 +1,13 @@
+import type { BushArgumentTypeCaster } from '#lib';
+import assert from 'assert/strict';
+import numeral from 'numeral';
+assert(typeof numeral === 'function');
+
+export const abbreviatedNumber: BushArgumentTypeCaster<number | null> = (_, phrase) => {
+ if (!phrase) return null;
+ const num = numeral(phrase?.toLowerCase()).value();
+
+ if (typeof num !== 'number' || isNaN(num)) return null;
+
+ return num;
+};
diff --git a/lib/arguments/contentWithDuration.ts b/lib/arguments/contentWithDuration.ts
new file mode 100644
index 0000000..0efba39
--- /dev/null
+++ b/lib/arguments/contentWithDuration.ts
@@ -0,0 +1,5 @@
+import { parseDuration, type BushArgumentTypeCaster, type ParsedDuration } from '#lib';
+
+export const contentWithDuration: BushArgumentTypeCaster<Promise<ParsedDuration>> = async (_, phrase) => {
+ return parseDuration(phrase);
+};
diff --git a/lib/arguments/discordEmoji.ts b/lib/arguments/discordEmoji.ts
new file mode 100644
index 0000000..92d6502
--- /dev/null
+++ b/lib/arguments/discordEmoji.ts
@@ -0,0 +1,14 @@
+import { regex, type BushArgumentTypeCaster } from '#lib';
+import type { Snowflake } from 'discord.js';
+
+export const discordEmoji: BushArgumentTypeCaster<DiscordEmojiInfo | null> = (_, phrase) => {
+ if (!phrase) return null;
+ const validEmoji: RegExpExecArray | null = regex.discordEmoji.exec(phrase);
+ if (!validEmoji || !validEmoji.groups) return null;
+ return { name: validEmoji.groups.name, id: validEmoji.groups.id };
+};
+
+export interface DiscordEmojiInfo {
+ name: string;
+ id: Snowflake;
+}
diff --git a/lib/arguments/duration.ts b/lib/arguments/duration.ts
new file mode 100644
index 0000000..09dd3d5
--- /dev/null
+++ b/lib/arguments/duration.ts
@@ -0,0 +1,5 @@
+import { parseDuration, type BushArgumentTypeCaster } from '#lib';
+
+export const duration: BushArgumentTypeCaster<number | null> = (_, phrase) => {
+ return parseDuration(phrase).duration;
+};
diff --git a/lib/arguments/durationSeconds.ts b/lib/arguments/durationSeconds.ts
new file mode 100644
index 0000000..d8d6749
--- /dev/null
+++ b/lib/arguments/durationSeconds.ts
@@ -0,0 +1,6 @@
+import { parseDuration, type BushArgumentTypeCaster } from '#lib';
+
+export const durationSeconds: BushArgumentTypeCaster<number | null> = (_, phrase) => {
+ phrase += 's';
+ return parseDuration(phrase).duration;
+};
diff --git a/lib/arguments/globalUser.ts b/lib/arguments/globalUser.ts
new file mode 100644
index 0000000..4324aa9
--- /dev/null
+++ b/lib/arguments/globalUser.ts
@@ -0,0 +1,7 @@
+import type { BushArgumentTypeCaster } from '#lib';
+import type { User } from 'discord.js';
+
+// resolve non-cached users
+export const globalUser: BushArgumentTypeCaster<Promise<User | null>> = async (message, phrase) => {
+ return message.client.users.resolve(phrase) ?? (await message.client.users.fetch(`${phrase}`).catch(() => null));
+};
diff --git a/lib/arguments/index.ts b/lib/arguments/index.ts
new file mode 100644
index 0000000..eebf0a2
--- /dev/null
+++ b/lib/arguments/index.ts
@@ -0,0 +1,10 @@
+export * from './abbreviatedNumber.js';
+export * from './contentWithDuration.js';
+export * from './discordEmoji.js';
+export * from './duration.js';
+export * from './durationSeconds.js';
+export * from './globalUser.js';
+export * from './messageLink.js';
+export * from './permission.js';
+export * from './roleWithDuration.js';
+export * from './snowflake.js';
diff --git a/lib/arguments/messageLink.ts b/lib/arguments/messageLink.ts
new file mode 100644
index 0000000..c95e42d
--- /dev/null
+++ b/lib/arguments/messageLink.ts
@@ -0,0 +1,20 @@
+import { BushArgumentTypeCaster, regex } from '#lib';
+import type { Message } from 'discord.js';
+
+export const messageLink: BushArgumentTypeCaster<Promise<Message | null>> = async (message, phrase) => {
+ const match = new RegExp(regex.messageLink).exec(phrase);
+ if (!match || !match.groups) return null;
+
+ const { guild_id, channel_id, message_id } = match.groups;
+
+ if (!guild_id || !channel_id || message_id) return null;
+
+ const guild = message.client.guilds.cache.get(guild_id);
+ if (!guild) return null;
+
+ const channel = guild.channels.cache.get(channel_id);
+ if (!channel || (!channel.isTextBased() && !channel.isThread())) return null;
+
+ const msg = await channel.messages.fetch(message_id).catch(() => null);
+ return msg;
+};
diff --git a/lib/arguments/permission.ts b/lib/arguments/permission.ts
new file mode 100644
index 0000000..98bfe74
--- /dev/null
+++ b/lib/arguments/permission.ts
@@ -0,0 +1,12 @@
+import type { BushArgumentTypeCaster } from '#lib';
+import { PermissionFlagsBits, type PermissionsString } from 'discord.js';
+
+export const permission: BushArgumentTypeCaster<PermissionsString | null> = (_, phrase) => {
+ if (!phrase) return null;
+ phrase = phrase.toUpperCase().replace(/ /g, '_');
+ if (!(phrase in PermissionFlagsBits)) {
+ return null;
+ } else {
+ return phrase as PermissionsString;
+ }
+};
diff --git a/lib/arguments/roleWithDuration.ts b/lib/arguments/roleWithDuration.ts
new file mode 100644
index 0000000..b97f205
--- /dev/null
+++ b/lib/arguments/roleWithDuration.ts
@@ -0,0 +1,17 @@
+import { Arg, BushArgumentTypeCaster, parseDuration } from '#lib';
+import type { Role } from 'discord.js';
+
+export const roleWithDuration: BushArgumentTypeCaster<Promise<RoleWithDuration | null>> = async (message, phrase) => {
+ // eslint-disable-next-line prefer-const
+ let { duration, content } = parseDuration(phrase);
+ if (content === null || content === undefined) return null;
+ content = content.trim();
+ const role = await Arg.cast('role', message, content);
+ if (!role) return null;
+ return { duration, role };
+};
+
+export interface RoleWithDuration {
+ duration: number | null;
+ role: Role | null;
+}
diff --git a/lib/arguments/snowflake.ts b/lib/arguments/snowflake.ts
new file mode 100644
index 0000000..b98a20f
--- /dev/null
+++ b/lib/arguments/snowflake.ts
@@ -0,0 +1,8 @@
+import { BushArgumentTypeCaster, regex } from '#lib';
+import type { Snowflake } from 'discord.js';
+
+export const snowflake: BushArgumentTypeCaster<Snowflake | null> = (_, phrase) => {
+ if (!phrase) return null;
+ if (regex.snowflake.test(phrase)) return phrase;
+ return null;
+};
diff --git a/lib/arguments/tinyColor.ts b/lib/arguments/tinyColor.ts
new file mode 100644
index 0000000..148c078
--- /dev/null
+++ b/lib/arguments/tinyColor.ts
@@ -0,0 +1,10 @@
+import type { BushArgumentTypeCaster } from '#lib';
+import assert from 'assert/strict';
+import tinycolorModule from 'tinycolor2';
+assert(tinycolorModule);
+
+export const tinyColor: BushArgumentTypeCaster<string | null> = (_message, phrase) => {
+ // if the phase is a number it converts it to hex incase it could be representing a color in decimal
+ const newPhase = isNaN(phrase as any) ? phrase : `#${Number(phrase).toString(16)}`;
+ return tinycolorModule(newPhase).isValid() ? newPhase : null;
+};