@julanzw/ttoolbox-discordjs-framework 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +675 -0
- package/README.md +77 -0
- package/dist/classes/Command.class.d.ts +169 -0
- package/dist/classes/Command.class.js +156 -0
- package/dist/classes/CommandManager.class.d.ts +69 -0
- package/dist/classes/CommandManager.class.js +149 -0
- package/dist/classes/DiscordHandler.class.d.ts +241 -0
- package/dist/classes/DiscordHandler.class.js +222 -0
- package/dist/classes/InteractionError.class.d.ts +8 -0
- package/dist/classes/InteractionError.class.js +11 -0
- package/dist/classes/ModalManager.class.d.ts +154 -0
- package/dist/classes/ModalManager.class.js +205 -0
- package/dist/classes/SubcommandGroup.class.d.ts +127 -0
- package/dist/classes/SubcommandGroup.class.js +156 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +17 -0
- package/dist/types/button.d.ts +2 -0
- package/dist/types/button.js +1 -0
- package/dist/types/channel.d.ts +2 -0
- package/dist/types/channel.js +1 -0
- package/dist/types/logger.d.ts +37 -0
- package/dist/types/logger.js +1 -0
- package/dist/types/modal.d.ts +77 -0
- package/dist/types/modal.js +1 -0
- package/dist/types/permission.d.ts +2 -0
- package/dist/types/permission.js +1 -0
- package/dist/utils/PaginatedEmbed.class.d.ts +25 -0
- package/dist/utils/PaginatedEmbed.class.js +102 -0
- package/dist/utils/TToolboxLogger.class.d.ts +176 -0
- package/dist/utils/TToolboxLogger.class.js +252 -0
- package/dist/utils/cooldown.d.ts +13 -0
- package/dist/utils/cooldown.js +43 -0
- package/dist/utils/editAndReply.d.ts +37 -0
- package/dist/utils/editAndReply.js +85 -0
- package/dist/utils/embeds.d.ts +55 -0
- package/dist/utils/embeds.js +94 -0
- package/dist/utils/formatting.d.ts +44 -0
- package/dist/utils/formatting.js +87 -0
- package/dist/utils/miliseconds.d.ts +10 -0
- package/dist/utils/miliseconds.js +11 -0
- package/dist/utils/permissions.d.ts +8 -0
- package/dist/utils/permissions.js +24 -0
- package/dist/utils/slashCommandOptions.d.ts +8 -0
- package/dist/utils/slashCommandOptions.js +11 -0
- package/package.json +50 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { MessageFlags, } from 'discord.js';
|
|
2
|
+
import { InteractionError } from '../classes/InteractionError.class.js';
|
|
3
|
+
/**
|
|
4
|
+
* Safely replies to an interaction, handling deferred/replied states.
|
|
5
|
+
*
|
|
6
|
+
* @param interaction - The interaction to reply to
|
|
7
|
+
* @param content - The message content
|
|
8
|
+
* @param ephemeral - Whether the reply should be ephemeral
|
|
9
|
+
* @param embeds - Optional embeds to include
|
|
10
|
+
* @param components - Optional components to include
|
|
11
|
+
* @param files - Optional files to attach
|
|
12
|
+
* @returns The message that was sent
|
|
13
|
+
* @throws {InteractionError} If the interaction is too old or fails
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* try {
|
|
18
|
+
* await safeReply(interaction, 'Hello!', true);
|
|
19
|
+
* } catch (err) {
|
|
20
|
+
* if (err instanceof InteractionError && err.reason === 'expired') {
|
|
21
|
+
* this.logger?.warn('Interaction expired', 'command');
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export async function safeReply(interaction, content, ephemeral = false, embeds, components, files) {
|
|
27
|
+
// Check if interaction is too old
|
|
28
|
+
const now = Date.now();
|
|
29
|
+
const threeMinutes = 3 * 60 * 1000;
|
|
30
|
+
if (now - interaction.createdTimestamp > threeMinutes) {
|
|
31
|
+
throw new InteractionError('Interaction is older than 3 minutes', interaction.id, 'expired');
|
|
32
|
+
}
|
|
33
|
+
const payload = {
|
|
34
|
+
...(content ? { content } : {}),
|
|
35
|
+
...(ephemeral ? { flags: MessageFlags.Ephemeral } : {}),
|
|
36
|
+
...(embeds ? { embeds } : {}),
|
|
37
|
+
...(components ? { components } : {}),
|
|
38
|
+
...(files ? { files } : {}),
|
|
39
|
+
};
|
|
40
|
+
try {
|
|
41
|
+
if (!interaction.replied && !interaction.deferred) {
|
|
42
|
+
await interaction.reply(payload);
|
|
43
|
+
return await interaction.fetchReply();
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
return await interaction.followUp(payload);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
throw new InteractionError(
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
52
|
+
`Failed to reply to interaction: ${err.message}`, interaction.id, 'failed');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Safely edits an interaction reply.
|
|
57
|
+
*
|
|
58
|
+
* @param interaction - The interaction to edit
|
|
59
|
+
* @param content - The new message content
|
|
60
|
+
* @param embeds - Optional embeds to include
|
|
61
|
+
* @param components - Optional components to include
|
|
62
|
+
* @returns The edited message
|
|
63
|
+
* @throws {InteractionError} If the interaction is too old or fails
|
|
64
|
+
*/
|
|
65
|
+
export async function safeEdit(interaction, content, embeds, components) {
|
|
66
|
+
// Check if interaction is too old
|
|
67
|
+
const now = Date.now();
|
|
68
|
+
const threeMinutes = 3 * 60 * 1000;
|
|
69
|
+
if (now - interaction.createdTimestamp > threeMinutes) {
|
|
70
|
+
throw new InteractionError('Interaction is older than 3 minutes', interaction.id, 'expired');
|
|
71
|
+
}
|
|
72
|
+
const editPayload = {
|
|
73
|
+
...(content ? { content } : {}),
|
|
74
|
+
...(embeds ? { embeds } : {}),
|
|
75
|
+
...(components ? { components } : {}),
|
|
76
|
+
};
|
|
77
|
+
try {
|
|
78
|
+
return await interaction.editReply(editPayload);
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
throw new InteractionError(
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
83
|
+
`Failed to edit interaction: ${err.message}`, interaction.id, 'failed');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { APIEmbedField, ColorResolvable, EmbedBuilder, ButtonStyle, ButtonBuilder, ActionRowBuilder } from 'discord.js';
|
|
2
|
+
import { PaginationButtonLocation } from '../types/button.js';
|
|
3
|
+
/**
|
|
4
|
+
* Util function for building an embed
|
|
5
|
+
*
|
|
6
|
+
* @param title - The title of the embed
|
|
7
|
+
* @param fields - The fields of the embed
|
|
8
|
+
* @param description - The description of the embed, optional
|
|
9
|
+
* @param footer - The footer of the embed, optional
|
|
10
|
+
* @param timestamp - If the embed should have a timestamp, defaults to false
|
|
11
|
+
* @param color - The color of the embed, defaults to STANDARD_COLOR
|
|
12
|
+
* @param customize - A function to customize the embed further, defaults to no customization
|
|
13
|
+
*
|
|
14
|
+
* @returns An EmbedBuilder instance with the specified properties
|
|
15
|
+
*/
|
|
16
|
+
export declare function embedBuilder({ title, fields, description, footer, timestamp, color, customize, }: {
|
|
17
|
+
title: string;
|
|
18
|
+
fields?: APIEmbedField[];
|
|
19
|
+
description?: string;
|
|
20
|
+
footer?: string;
|
|
21
|
+
timestamp?: boolean;
|
|
22
|
+
color?: ColorResolvable;
|
|
23
|
+
customize?: (embed: EmbedBuilder) => EmbedBuilder;
|
|
24
|
+
}): EmbedBuilder;
|
|
25
|
+
/**
|
|
26
|
+
* Creates a single button based on its type and config.
|
|
27
|
+
*
|
|
28
|
+
* @param type - The button type of the button (prev, next, edit, delete, etc)
|
|
29
|
+
* @param actionId - The base action ID for the button
|
|
30
|
+
* @param disabled - Whether the button should be disabled, defaults to false
|
|
31
|
+
* @param label - Optional label for the button, defaults to type-based label
|
|
32
|
+
* @param style - Optional style for the button, defaults to secondary
|
|
33
|
+
*
|
|
34
|
+
* @return A ButtonBuilder instance configured with the specified properties
|
|
35
|
+
*/
|
|
36
|
+
export declare function createButton({ type, disabled, label, style, customId, }: {
|
|
37
|
+
type: string;
|
|
38
|
+
disabled?: boolean;
|
|
39
|
+
label?: string;
|
|
40
|
+
style?: ButtonStyle;
|
|
41
|
+
customId?: string;
|
|
42
|
+
}): ButtonBuilder;
|
|
43
|
+
/**
|
|
44
|
+
* Creates an `ButtonBuilder[]` with a prev and next button (in that order).
|
|
45
|
+
*
|
|
46
|
+
* @param index - The current index of the item being paginated
|
|
47
|
+
* @param total - The total number of pages
|
|
48
|
+
*
|
|
49
|
+
* @returns An `ButtonBuilder[]` containing the buttons
|
|
50
|
+
*/
|
|
51
|
+
export declare function createPaginationButtons(index: number, total: number): ButtonBuilder[];
|
|
52
|
+
export declare function createButtonsRow(normalButtons: ButtonBuilder[], pagination?: {
|
|
53
|
+
buttons: ButtonBuilder[];
|
|
54
|
+
location: PaginationButtonLocation;
|
|
55
|
+
}): ActionRowBuilder<ButtonBuilder>;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { EmbedBuilder, ButtonStyle, ButtonBuilder, ActionRowBuilder, } from 'discord.js';
|
|
2
|
+
/**
|
|
3
|
+
* Util function for building an embed
|
|
4
|
+
*
|
|
5
|
+
* @param title - The title of the embed
|
|
6
|
+
* @param fields - The fields of the embed
|
|
7
|
+
* @param description - The description of the embed, optional
|
|
8
|
+
* @param footer - The footer of the embed, optional
|
|
9
|
+
* @param timestamp - If the embed should have a timestamp, defaults to false
|
|
10
|
+
* @param color - The color of the embed, defaults to STANDARD_COLOR
|
|
11
|
+
* @param customize - A function to customize the embed further, defaults to no customization
|
|
12
|
+
*
|
|
13
|
+
* @returns An EmbedBuilder instance with the specified properties
|
|
14
|
+
*/
|
|
15
|
+
export function embedBuilder({ title, fields, description, footer, timestamp = false, color = '#3F48CC', customize = (e) => e, }) {
|
|
16
|
+
let embed = new EmbedBuilder().setTitle(title).setColor(color);
|
|
17
|
+
if (fields && fields.length > 0)
|
|
18
|
+
embed = embed.setFields(fields);
|
|
19
|
+
if (description)
|
|
20
|
+
embed = embed.setDescription(description);
|
|
21
|
+
if (footer)
|
|
22
|
+
embed = embed.setFooter({ text: footer });
|
|
23
|
+
if (timestamp)
|
|
24
|
+
embed = embed.setTimestamp();
|
|
25
|
+
return customize(embed);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Creates a single button based on its type and config.
|
|
29
|
+
*
|
|
30
|
+
* @param type - The button type of the button (prev, next, edit, delete, etc)
|
|
31
|
+
* @param actionId - The base action ID for the button
|
|
32
|
+
* @param disabled - Whether the button should be disabled, defaults to false
|
|
33
|
+
* @param label - Optional label for the button, defaults to type-based label
|
|
34
|
+
* @param style - Optional style for the button, defaults to secondary
|
|
35
|
+
*
|
|
36
|
+
* @return A ButtonBuilder instance configured with the specified properties
|
|
37
|
+
*/
|
|
38
|
+
export function createButton({ type, disabled = false, label, style, customId, }) {
|
|
39
|
+
const button = new ButtonBuilder()
|
|
40
|
+
.setCustomId(customId ?? `${type}`)
|
|
41
|
+
.setDisabled(disabled);
|
|
42
|
+
switch (type) {
|
|
43
|
+
case 'prev':
|
|
44
|
+
return button
|
|
45
|
+
.setLabel(label ?? 'Previous')
|
|
46
|
+
.setStyle(ButtonStyle.Secondary);
|
|
47
|
+
case 'next':
|
|
48
|
+
return button.setLabel(label ?? 'Next').setStyle(ButtonStyle.Secondary);
|
|
49
|
+
case 'edit':
|
|
50
|
+
return button.setLabel(label ?? 'Edit').setStyle(ButtonStyle.Primary);
|
|
51
|
+
case 'delete':
|
|
52
|
+
return button.setLabel(label ?? 'Delete').setStyle(ButtonStyle.Danger);
|
|
53
|
+
default:
|
|
54
|
+
return button
|
|
55
|
+
.setLabel(label ?? 'Unknown')
|
|
56
|
+
.setStyle(style ?? ButtonStyle.Secondary);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Creates an `ButtonBuilder[]` with a prev and next button (in that order).
|
|
61
|
+
*
|
|
62
|
+
* @param index - The current index of the item being paginated
|
|
63
|
+
* @param total - The total number of pages
|
|
64
|
+
*
|
|
65
|
+
* @returns An `ButtonBuilder[]` containing the buttons
|
|
66
|
+
*/
|
|
67
|
+
export function createPaginationButtons(index, total) {
|
|
68
|
+
const buttons = [
|
|
69
|
+
createButton({
|
|
70
|
+
type: 'prev',
|
|
71
|
+
disabled: index === 0,
|
|
72
|
+
}),
|
|
73
|
+
createButton({
|
|
74
|
+
type: 'next',
|
|
75
|
+
disabled: index === total - 1,
|
|
76
|
+
}),
|
|
77
|
+
];
|
|
78
|
+
return buttons;
|
|
79
|
+
}
|
|
80
|
+
export function createButtonsRow(normalButtons, pagination) {
|
|
81
|
+
if (pagination && pagination.buttons.length === 2) {
|
|
82
|
+
switch (pagination.location) {
|
|
83
|
+
case 'embrace':
|
|
84
|
+
return new ActionRowBuilder().addComponents(pagination.buttons[0], ...normalButtons, pagination.buttons[1]);
|
|
85
|
+
case 'start':
|
|
86
|
+
return new ActionRowBuilder().addComponents(...pagination.buttons, ...normalButtons);
|
|
87
|
+
case 'end':
|
|
88
|
+
return new ActionRowBuilder().addComponents(...normalButtons, ...pagination.buttons);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
return new ActionRowBuilder().addComponents(...normalButtons);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Util function for formatting a `Date` like 2000-01-01 into January 1st
|
|
3
|
+
*
|
|
4
|
+
* @param date - the date that needs formatting
|
|
5
|
+
* @returns the formatted date
|
|
6
|
+
*/
|
|
7
|
+
export declare function formatDateToString(date: Date): string;
|
|
8
|
+
/**
|
|
9
|
+
* Util function to get the suffix of a number, e.g. 1st, 2nd, 3rd, 4th, etc.
|
|
10
|
+
*
|
|
11
|
+
* @param number - the number you want the suffix of
|
|
12
|
+
* @returns the suffix of the number
|
|
13
|
+
*/
|
|
14
|
+
export declare function getDaySuffix(number: number): "th" | "st" | "nd" | "rd";
|
|
15
|
+
/**
|
|
16
|
+
* Util function to format a date into a string with the DD-MM-YYYY format
|
|
17
|
+
*
|
|
18
|
+
* @param date - The date to format
|
|
19
|
+
* @returns A formatted string in the format DD-MM-YYYY
|
|
20
|
+
*/
|
|
21
|
+
export declare function formatDateToDDMMYYYY(date: Date): string;
|
|
22
|
+
/**
|
|
23
|
+
* Util function to format a date into a string with the YYYY-MM-DD HH:MM:SS format
|
|
24
|
+
* @param date - The date to format
|
|
25
|
+
* @returns A formatted string in YYYY-MM-DD HH:MM:SS format
|
|
26
|
+
*/
|
|
27
|
+
export declare function formatDateToYYYYMMDDHHMMSS(date: Date): string;
|
|
28
|
+
/**
|
|
29
|
+
* Util function to format the first letter of a string
|
|
30
|
+
* @param str - input string
|
|
31
|
+
* @returns The formatted string
|
|
32
|
+
*/
|
|
33
|
+
export declare function capitalizeFirst(input: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Formats a duration in milliseconds into a human-readable string.
|
|
36
|
+
* Examples:
|
|
37
|
+
* - 4200 -> "4s"
|
|
38
|
+
* - 65000 -> "1m 5s"
|
|
39
|
+
* - 3723000 -> "1h 2m 3s"
|
|
40
|
+
*
|
|
41
|
+
* @param ms Duration in milliseconds
|
|
42
|
+
* @returns A formatted string
|
|
43
|
+
*/
|
|
44
|
+
export declare function formatDuration(ms: number): string;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Util function for formatting a `Date` like 2000-01-01 into January 1st
|
|
3
|
+
*
|
|
4
|
+
* @param date - the date that needs formatting
|
|
5
|
+
* @returns the formatted date
|
|
6
|
+
*/
|
|
7
|
+
export function formatDateToString(date) {
|
|
8
|
+
const daySuffix = getDaySuffix(date.getDate());
|
|
9
|
+
return (date.toLocaleDateString('en-US', { month: 'long', day: 'numeric' }) +
|
|
10
|
+
daySuffix);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Util function to get the suffix of a number, e.g. 1st, 2nd, 3rd, 4th, etc.
|
|
14
|
+
*
|
|
15
|
+
* @param number - the number you want the suffix of
|
|
16
|
+
* @returns the suffix of the number
|
|
17
|
+
*/
|
|
18
|
+
export function getDaySuffix(number) {
|
|
19
|
+
if (number > 3 && number < 21)
|
|
20
|
+
return 'th';
|
|
21
|
+
switch (number % 10) {
|
|
22
|
+
case 1:
|
|
23
|
+
return 'st';
|
|
24
|
+
case 2:
|
|
25
|
+
return 'nd';
|
|
26
|
+
case 3:
|
|
27
|
+
return 'rd';
|
|
28
|
+
default:
|
|
29
|
+
return 'th';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Util function to format a date into a string with the DD-MM-YYYY format
|
|
34
|
+
*
|
|
35
|
+
* @param date - The date to format
|
|
36
|
+
* @returns A formatted string in the format DD-MM-YYYY
|
|
37
|
+
*/
|
|
38
|
+
export function formatDateToDDMMYYYY(date) {
|
|
39
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
40
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
41
|
+
const year = date.getFullYear();
|
|
42
|
+
return `${day}-${month}-${year}`;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Util function to format a date into a string with the YYYY-MM-DD HH:MM:SS format
|
|
46
|
+
* @param date - The date to format
|
|
47
|
+
* @returns A formatted string in YYYY-MM-DD HH:MM:SS format
|
|
48
|
+
*/
|
|
49
|
+
export function formatDateToYYYYMMDDHHMMSS(date) {
|
|
50
|
+
return date.toISOString().replace('T', ' ').slice(0, 19);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Util function to format the first letter of a string
|
|
54
|
+
* @param str - input string
|
|
55
|
+
* @returns The formatted string
|
|
56
|
+
*/
|
|
57
|
+
export function capitalizeFirst(input) {
|
|
58
|
+
if (!input)
|
|
59
|
+
return '';
|
|
60
|
+
const lower = input.toLowerCase();
|
|
61
|
+
return lower.charAt(0).toUpperCase() + lower.slice(1);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Formats a duration in milliseconds into a human-readable string.
|
|
65
|
+
* Examples:
|
|
66
|
+
* - 4200 -> "4s"
|
|
67
|
+
* - 65000 -> "1m 5s"
|
|
68
|
+
* - 3723000 -> "1h 2m 3s"
|
|
69
|
+
*
|
|
70
|
+
* @param ms Duration in milliseconds
|
|
71
|
+
* @returns A formatted string
|
|
72
|
+
*/
|
|
73
|
+
export function formatDuration(ms) {
|
|
74
|
+
let seconds = Math.floor(ms / 1000);
|
|
75
|
+
const hours = Math.floor(seconds / 3600);
|
|
76
|
+
seconds %= 3600;
|
|
77
|
+
const minutes = Math.floor(seconds / 60);
|
|
78
|
+
seconds %= 60;
|
|
79
|
+
const parts = [];
|
|
80
|
+
if (hours > 0)
|
|
81
|
+
parts.push(`${hours}h`);
|
|
82
|
+
if (minutes > 0)
|
|
83
|
+
parts.push(`${minutes}m`);
|
|
84
|
+
if (seconds > 0 || parts.length === 0)
|
|
85
|
+
parts.push(`${seconds}s`);
|
|
86
|
+
return parts.join(' ');
|
|
87
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common time durations in milliseconds.
|
|
3
|
+
*/
|
|
4
|
+
export var TIMES_MILISECONDS;
|
|
5
|
+
(function (TIMES_MILISECONDS) {
|
|
6
|
+
TIMES_MILISECONDS[TIMES_MILISECONDS["SECOND"] = 1000] = "SECOND";
|
|
7
|
+
TIMES_MILISECONDS[TIMES_MILISECONDS["MINUTE"] = 60000] = "MINUTE";
|
|
8
|
+
TIMES_MILISECONDS[TIMES_MILISECONDS["TEN_MINUTES"] = 600000] = "TEN_MINUTES";
|
|
9
|
+
TIMES_MILISECONDS[TIMES_MILISECONDS["HOUR"] = 6000000] = "HOUR";
|
|
10
|
+
TIMES_MILISECONDS[TIMES_MILISECONDS["DAY"] = 14400000] = "DAY";
|
|
11
|
+
})(TIMES_MILISECONDS || (TIMES_MILISECONDS = {}));
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { PermissionLevel } from '../types/permission.js';
|
|
2
|
+
/**
|
|
3
|
+
* Utility function to return the proper permission bits
|
|
4
|
+
*
|
|
5
|
+
* @param level - the PermissionLevel the bits need to be returned of. Can be an array
|
|
6
|
+
* @returns the permission's bit value or null for unrestricted
|
|
7
|
+
*/
|
|
8
|
+
export declare function getPermissionsForLevel(level: PermissionLevel): bigint | null;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { PermissionFlagsBits, PermissionsBitField } from 'discord.js';
|
|
2
|
+
/**
|
|
3
|
+
* Utility function to return the proper permission bits
|
|
4
|
+
*
|
|
5
|
+
* @param level - the PermissionLevel the bits need to be returned of. Can be an array
|
|
6
|
+
* @returns the permission's bit value or null for unrestricted
|
|
7
|
+
*/
|
|
8
|
+
export function getPermissionsForLevel(level) {
|
|
9
|
+
if (level === 'admin') {
|
|
10
|
+
return PermissionFlagsBits.Administrator;
|
|
11
|
+
}
|
|
12
|
+
if (level === 'owner' || level === 'disabled') {
|
|
13
|
+
// disable the command by default
|
|
14
|
+
return BigInt(0);
|
|
15
|
+
}
|
|
16
|
+
if (typeof level === 'bigint' || typeof level === 'number') {
|
|
17
|
+
return BigInt(level);
|
|
18
|
+
}
|
|
19
|
+
if (Array.isArray(level)) {
|
|
20
|
+
return new PermissionsBitField(level).bitfield;
|
|
21
|
+
}
|
|
22
|
+
// unrestricted
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SlashCommandBooleanOption, SlashCommandChannelOption, SlashCommandIntegerOption, SlashCommandRoleOption, SlashCommandStringOption, SlashCommandUserOption } from 'discord.js';
|
|
2
|
+
import { AllowedChannelTypeChannelOption } from '../types/channel.js';
|
|
3
|
+
export declare const userOption: (name: string, desc: string, required?: boolean) => (opt: SlashCommandUserOption) => SlashCommandUserOption;
|
|
4
|
+
export declare const integerOption: (name: string, desc: string, required?: boolean) => (opt: SlashCommandIntegerOption) => SlashCommandIntegerOption;
|
|
5
|
+
export declare const stringOption: (name: string, desc: string, required?: boolean) => (opt: SlashCommandStringOption) => SlashCommandStringOption;
|
|
6
|
+
export declare const channelOption: (name: string, desc: string, required?: boolean, channelType?: AllowedChannelTypeChannelOption | AllowedChannelTypeChannelOption[]) => (opt: SlashCommandChannelOption) => SlashCommandChannelOption;
|
|
7
|
+
export declare const roleOption: (name: string, desc: string, required?: boolean) => (opt: SlashCommandRoleOption) => SlashCommandRoleOption;
|
|
8
|
+
export declare const booleanOption: (name: string, desc: string, required?: boolean) => (opt: SlashCommandBooleanOption) => SlashCommandBooleanOption;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ChannelType, } from 'discord.js';
|
|
2
|
+
export const userOption = (name, desc, required = true) => (opt) => opt.setName(name).setDescription(desc).setRequired(required);
|
|
3
|
+
export const integerOption = (name, desc, required = true) => (opt) => opt.setName(name).setDescription(desc).setRequired(required);
|
|
4
|
+
export const stringOption = (name, desc, required = true) => (opt) => opt.setName(name).setDescription(desc).setRequired(required);
|
|
5
|
+
export const channelOption = (name, desc, required = true, channelType = [ChannelType.GuildText]) => (opt) => opt
|
|
6
|
+
.setName(name)
|
|
7
|
+
.setDescription(desc)
|
|
8
|
+
.setRequired(required)
|
|
9
|
+
.addChannelTypes(...(Array.isArray(channelType) ? channelType : [channelType]));
|
|
10
|
+
export const roleOption = (name, desc, required = true) => (opt) => opt.setName(name).setDescription(desc).setRequired(required);
|
|
11
|
+
export const booleanOption = (name, desc, required = true) => (opt) => opt.setName(name).setDescription(desc).setRequired(required);
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@julanzw/ttoolbox-discordjs-framework",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "A Discord.js command framework with built-in handlers and utilities",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md",
|
|
11
|
+
"LICENSE"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"prepublishOnly": "npm run build",
|
|
16
|
+
"dev": "tsc --watch"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"discord",
|
|
20
|
+
"discord.js",
|
|
21
|
+
"bot",
|
|
22
|
+
"framework",
|
|
23
|
+
"commands",
|
|
24
|
+
"typescript"
|
|
25
|
+
],
|
|
26
|
+
"author": "JulanZw",
|
|
27
|
+
"license": "AGPL-3.0",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/JulanZw/ttoolbox-discordjs-framework.git"
|
|
31
|
+
},
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/JulanZw/ttoolbox-discordjs-framework/issues"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/JulanZw/ttoolbox-discordjs-framework#readme",
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"discord.js": "^14.0.0"
|
|
38
|
+
},
|
|
39
|
+
"peerDependenciesMeta": {
|
|
40
|
+
"@prisma/client": {
|
|
41
|
+
"optional": true
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@prisma/client": "^6.11.1",
|
|
46
|
+
"@types/node": "^24.0.14",
|
|
47
|
+
"discord.js": "^14.21.0",
|
|
48
|
+
"typescript": "^5.8.3"
|
|
49
|
+
}
|
|
50
|
+
}
|