@mostfeatured/dbi 0.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.
Files changed (126) hide show
  1. package/.gitattributes +2 -0
  2. package/LICENSE +674 -0
  3. package/dist/src/DBI.d.ts +78 -0
  4. package/dist/src/DBI.d.ts.map +1 -0
  5. package/dist/src/DBI.js +202 -0
  6. package/dist/src/DBI.js.map +1 -0
  7. package/dist/src/Events.d.ts +29 -0
  8. package/dist/src/Events.d.ts.map +1 -0
  9. package/dist/src/Events.js +51 -0
  10. package/dist/src/Events.js.map +1 -0
  11. package/dist/src/data/eventMap.json +234 -0
  12. package/dist/src/index.d.ts +4 -0
  13. package/dist/src/index.d.ts.map +1 -0
  14. package/dist/src/index.js +11 -0
  15. package/dist/src/index.js.map +1 -0
  16. package/dist/src/methods/hookEventListeners.d.ts +3 -0
  17. package/dist/src/methods/hookEventListeners.d.ts.map +1 -0
  18. package/dist/src/methods/hookEventListeners.js +34 -0
  19. package/dist/src/methods/hookEventListeners.js.map +1 -0
  20. package/dist/src/methods/hookInteractionListeners.d.ts +3 -0
  21. package/dist/src/methods/hookInteractionListeners.d.ts.map +1 -0
  22. package/dist/src/methods/hookInteractionListeners.js +97 -0
  23. package/dist/src/methods/hookInteractionListeners.js.map +1 -0
  24. package/dist/src/methods/publishInteractions.d.ts +4 -0
  25. package/dist/src/methods/publishInteractions.d.ts.map +1 -0
  26. package/dist/src/methods/publishInteractions.js +150 -0
  27. package/dist/src/methods/publishInteractions.js.map +1 -0
  28. package/dist/src/types/Button.d.ts +19 -0
  29. package/dist/src/types/Button.d.ts.map +1 -0
  30. package/dist/src/types/Button.js +27 -0
  31. package/dist/src/types/Button.js.map +1 -0
  32. package/dist/src/types/ChatInput/ChatInput.d.ts +15 -0
  33. package/dist/src/types/ChatInput/ChatInput.d.ts.map +1 -0
  34. package/dist/src/types/ChatInput/ChatInput.js +19 -0
  35. package/dist/src/types/ChatInput/ChatInput.js.map +1 -0
  36. package/dist/src/types/ChatInput/ChatInputOptions.d.ts +153 -0
  37. package/dist/src/types/ChatInput/ChatInputOptions.d.ts.map +1 -0
  38. package/dist/src/types/ChatInput/ChatInputOptions.js +149 -0
  39. package/dist/src/types/ChatInput/ChatInputOptions.js.map +1 -0
  40. package/dist/src/types/Event.d.ts +257 -0
  41. package/dist/src/types/Event.d.ts.map +1 -0
  42. package/dist/src/types/Event.js +21 -0
  43. package/dist/src/types/Event.js.map +1 -0
  44. package/dist/src/types/Interaction.d.ts +34 -0
  45. package/dist/src/types/Interaction.d.ts.map +1 -0
  46. package/dist/src/types/Interaction.js +25 -0
  47. package/dist/src/types/Interaction.js.map +1 -0
  48. package/dist/src/types/Locale.d.ts +19 -0
  49. package/dist/src/types/Locale.d.ts.map +1 -0
  50. package/dist/src/types/Locale.js +31 -0
  51. package/dist/src/types/Locale.js.map +1 -0
  52. package/dist/src/types/MessageContextMenu.d.ts +14 -0
  53. package/dist/src/types/MessageContextMenu.d.ts.map +1 -0
  54. package/dist/src/types/MessageContextMenu.js +17 -0
  55. package/dist/src/types/MessageContextMenu.js.map +1 -0
  56. package/dist/src/types/Modal.d.ts +19 -0
  57. package/dist/src/types/Modal.d.ts.map +1 -0
  58. package/dist/src/types/Modal.js +24 -0
  59. package/dist/src/types/Modal.js.map +1 -0
  60. package/dist/src/types/SelectMenu.d.ts +19 -0
  61. package/dist/src/types/SelectMenu.d.ts.map +1 -0
  62. package/dist/src/types/SelectMenu.js +27 -0
  63. package/dist/src/types/SelectMenu.js.map +1 -0
  64. package/dist/src/types/UserContextMenu.d.ts +14 -0
  65. package/dist/src/types/UserContextMenu.d.ts.map +1 -0
  66. package/dist/src/types/UserContextMenu.js +17 -0
  67. package/dist/src/types/UserContextMenu.js.map +1 -0
  68. package/dist/src/utils/MemoryStore.d.ts +9 -0
  69. package/dist/src/utils/MemoryStore.d.ts.map +1 -0
  70. package/dist/src/utils/MemoryStore.js +30 -0
  71. package/dist/src/utils/MemoryStore.js.map +1 -0
  72. package/dist/src/utils/customId.d.ts +7 -0
  73. package/dist/src/utils/customId.d.ts.map +1 -0
  74. package/dist/src/utils/customId.js +44 -0
  75. package/dist/src/utils/customId.js.map +1 -0
  76. package/dist/src/utils/permissions.d.ts +3 -0
  77. package/dist/src/utils/permissions.d.ts.map +1 -0
  78. package/dist/src/utils/permissions.js +9 -0
  79. package/dist/src/utils/permissions.js.map +1 -0
  80. package/dist/src/utils/recursiveImport.d.ts +2 -0
  81. package/dist/src/utils/recursiveImport.d.ts.map +1 -0
  82. package/dist/src/utils/recursiveImport.js +20 -0
  83. package/dist/src/utils/recursiveImport.js.map +1 -0
  84. package/dist/test/commands/hello world.d.ts +2 -0
  85. package/dist/test/commands/hello world.d.ts.map +1 -0
  86. package/dist/test/commands/hello world.js +46 -0
  87. package/dist/test/commands/hello world.js.map +1 -0
  88. package/dist/test/commands/stuff.d.ts +2 -0
  89. package/dist/test/commands/stuff.d.ts.map +1 -0
  90. package/dist/test/commands/stuff.js +22 -0
  91. package/dist/test/commands/stuff.js.map +1 -0
  92. package/dist/test/index.d.ts +2 -0
  93. package/dist/test/index.d.ts.map +1 -0
  94. package/dist/test/index.js +33 -0
  95. package/dist/test/index.js.map +1 -0
  96. package/dist/test/publish.d.ts +2 -0
  97. package/dist/test/publish.d.ts.map +1 -0
  98. package/dist/test/publish.js +5 -0
  99. package/dist/test/publish.js.map +1 -0
  100. package/dist/test/things/test.d.ts +2 -0
  101. package/dist/test/things/test.d.ts.map +1 -0
  102. package/dist/test/things/test.js +84 -0
  103. package/dist/test/things/test.js.map +1 -0
  104. package/package.json +40 -0
  105. package/src/DBI.ts +262 -0
  106. package/src/Events.ts +72 -0
  107. package/src/data/eventMap.json +234 -0
  108. package/src/index.ts +7 -0
  109. package/src/methods/hookEventListeners.ts +38 -0
  110. package/src/methods/hookInteractionListeners.ts +118 -0
  111. package/src/methods/publishInteractions.ts +158 -0
  112. package/src/types/Button.ts +32 -0
  113. package/src/types/ChatInput/ChatInput.ts +24 -0
  114. package/src/types/ChatInput/ChatInputOptions.ts +168 -0
  115. package/src/types/Event.ts +115 -0
  116. package/src/types/Interaction.ts +69 -0
  117. package/src/types/Locale.ts +39 -0
  118. package/src/types/MessageContextMenu.ts +23 -0
  119. package/src/types/Modal.ts +32 -0
  120. package/src/types/SelectMenu.ts +32 -0
  121. package/src/types/UserContextMenu.ts +21 -0
  122. package/src/utils/MemoryStore.ts +28 -0
  123. package/src/utils/customId.ts +35 -0
  124. package/src/utils/permissions.ts +5 -0
  125. package/src/utils/recursiveImport.ts +15 -0
  126. package/tsconfig.json +39 -0
@@ -0,0 +1,118 @@
1
+ import { DBI } from "../DBI";
2
+ import Discord from "discord.js";
3
+ import { parseCustomId } from "../utils/customId";
4
+
5
+ export function hookInteractionListeners(dbi: DBI): () => any {
6
+ async function handle(inter: Discord.Interaction<Discord.CacheType>) {
7
+
8
+ const dbiInter =
9
+ dbi.data.interactions.find(i => {
10
+ let isUsesCustomId = (inter.isButton() || inter.isSelectMenu() || inter.isModalSubmit());
11
+ let parsedId = isUsesCustomId ? parseCustomId(dbi, (inter as any).customId) : null;
12
+ return (
13
+ (
14
+ i.type == "ChatInput"
15
+ && (inter.isChatInputCommand() || inter.isAutocomplete())
16
+ && i.name == [inter.commandName, inter.options.getSubcommandGroup(false), inter.options.getSubcommand(false)].filter(i => !!i).join(" ")
17
+ )
18
+ ||
19
+ (
20
+ (i.type == "MessageContextMenu" || i.type == "UserContextMenu")
21
+ && (inter.isMessageContextMenuCommand() || inter.isUserContextMenuCommand())
22
+ && inter.commandName == i.name
23
+ )
24
+ ||
25
+ (
26
+ (i.type == "Button" || i.type == "SelectMenu" || i.type == "Modal")
27
+ && isUsesCustomId
28
+ && parsedId.name == i.name
29
+ )
30
+ )
31
+ });
32
+
33
+ if (!dbiInter) return;
34
+
35
+ if (inter.isAutocomplete()) {
36
+ let focussed = inter.options.getFocused(true);
37
+ let option = (dbiInter.options as any[]).find(i => i.name == focussed.name);
38
+ if (option?.onComplete) {
39
+ let response = await option.onComplete({
40
+ value: focussed.value,
41
+ interaction: inter,
42
+ dbi
43
+ });
44
+ await inter.respond(response);
45
+ }
46
+ return;
47
+ }
48
+
49
+ let userLocaleName = inter.locale.split("-")[0];
50
+ let userLocale = dbi.data.locales.has(userLocaleName) ? dbi.data.locales.get(userLocaleName) : dbi.data.locales.get(dbi.config.defaults.locale);
51
+
52
+ let guildLocaleName = inter.guild ? inter.guild.preferredLocale.split("-")[0] : null;
53
+ let guildLocale = guildLocaleName ? (dbi.data.locales.has(guildLocaleName) ? dbi.data.locales.get(guildLocaleName) : dbi.data.locales.get(dbi.config.defaults.locale)) : null;
54
+
55
+ let locale = {
56
+ user: userLocale,
57
+ guild: guildLocale
58
+ };
59
+
60
+ let data = (inter.isButton() || inter.isSelectMenu() || inter.isModalSubmit()) ? parseCustomId(dbi, inter.customId).data : undefined;
61
+
62
+ let rateLimitKeyMap = {
63
+ "User": `${inter.user.id}`,
64
+ "Channel": `${inter.channelId || "Channel"}`,
65
+ "Guild": `${inter.guildId || "Guild"}`,
66
+ "Member": `${inter.user.id}_${inter.guildId || "Guild"}`,
67
+ "Message": `${(inter as any)?.message?.id}`
68
+ }
69
+
70
+ for (const type in rateLimitKeyMap) {
71
+ let key = `RateLimit:${rateLimitKeyMap[type]}`;
72
+ let val = await dbi.config.store.get(key);
73
+ if (val && Date.now() > val.at + val.duration) {
74
+ await dbi.config.store.del(key);
75
+ val = null;
76
+ }
77
+ if (val) {
78
+ dbi.events.trigger("interactionRateLimit", {
79
+ dbi,
80
+ interaction: inter,
81
+ locale,
82
+ data,
83
+ rateLimit: {
84
+ type: key,
85
+ ...val
86
+ }
87
+ })
88
+ return;
89
+ }
90
+ }
91
+
92
+ async function setRateLimit(type: string, duration: number) {
93
+ await dbi.config.store.set(`RateLimit:${rateLimitKeyMap[type]}`, { at: Date.now(), duration });
94
+ }
95
+
96
+ let other = {};
97
+
98
+ if (!(await dbi.events.trigger("beforeInteraction", { dbi, interaction: inter, locale, setRateLimit, data, other }))) return;
99
+
100
+ await dbiInter.onExecute({
101
+ dbi,
102
+ // @ts-ignore
103
+ interaction: inter as any,
104
+ locale,
105
+ setRateLimit,
106
+ data,
107
+ other
108
+ });
109
+
110
+ dbi.events.trigger("afterInteraction", { dbi, interaction: inter, locale, setRateLimit, data, other });
111
+ }
112
+
113
+ dbi.client.on("interactionCreate", handle);
114
+
115
+ return () => {
116
+ dbi.client.off("interactionCreate", handle);
117
+ };
118
+ }
@@ -0,0 +1,158 @@
1
+ import Discord from "discord.js";
2
+ import { DBIChatInput } from "../types/ChatInput/ChatInput";
3
+ import { REST } from "@discordjs/rest";
4
+ import { Routes, RESTGetAPIUserResult, RESTPutAPIApplicationCommandsJSONBody, ApplicationCommandType, ApplicationCommandOptionType } from "discord-api-types/v9";
5
+ import { reducePermissions } from "../utils/permissions";
6
+ import snakecaseKeys from "snakecase-keys";
7
+
8
+ const PUBLISHABLE_TYPES = ["ChatInput", "UserContextMenu", "MessageContextMenu"];
9
+
10
+ export async function publishInteractions(
11
+ clientToken: string,
12
+ interactions: Discord.Collection<string, DBIChatInput>,
13
+ publishType: "Guild" | "Global",
14
+ guildId?: string
15
+ ) {
16
+ interactions = interactions.filter(i => PUBLISHABLE_TYPES.includes(i.type));
17
+
18
+ const rest = new REST({ version: "9" });
19
+ rest.setToken(clientToken);
20
+
21
+ const me: RESTGetAPIUserResult = await rest.get(Routes.user()) as any;
22
+
23
+ const body: RESTPutAPIApplicationCommandsJSONBody =
24
+ interactions.reduce((all, current) => {
25
+ switch (current.type) {
26
+ case "ChatInput": {
27
+ let nameSplitted = current.name.split(" ");
28
+ switch (nameSplitted.length) {
29
+ case 1: {
30
+ all.push({
31
+ type: ApplicationCommandType.ChatInput,
32
+ description: current.description,
33
+ name: nameSplitted[0],
34
+ default_member_permissions: reducePermissions(current.defaultMemberPermissions).toString(),
35
+ dm_permission: current.directMessages,
36
+ options: snakecaseKeys(current.options || [])
37
+ });
38
+ break;
39
+ }
40
+ case 2: {
41
+ let baseItem = all.find(i => i.name == current.name.split(" ")[0] && i.type == "ChatInput");
42
+ let option = {
43
+ type: ApplicationCommandOptionType.Subcommand,
44
+ name: nameSplitted[1],
45
+ description: current.description,
46
+ default_member_permissions: reducePermissions(current.defaultMemberPermissions).toString(),
47
+ dm_permission: current.directMessages,
48
+ options: snakecaseKeys(current.options || [])
49
+ };
50
+ if (!baseItem) {
51
+ all.push({
52
+ type: ApplicationCommandType.ChatInput,
53
+ name: nameSplitted[0],
54
+ description: "...",
55
+ options: [
56
+ option
57
+ ]
58
+ });
59
+ } else {
60
+ baseItem.options.push(option);
61
+ }
62
+ break;
63
+ }
64
+ case 3: {
65
+ let level1Item = all.find(i => i.name == current.name.split(" ")[0] && i.type == "ChatInput");
66
+ if (!level1Item) {
67
+ all.push({
68
+ type: ApplicationCommandType.ChatInput,
69
+ name: nameSplitted[0],
70
+ description: "...",
71
+ options: [
72
+ {
73
+ type: ApplicationCommandOptionType.SubcommandGroup,
74
+ name: nameSplitted[1],
75
+ description: "...",
76
+ options: [
77
+ {
78
+ type: ApplicationCommandOptionType.Subcommand,
79
+ name: nameSplitted[2],
80
+ description: current.description,
81
+ default_member_permissions: reducePermissions(current.defaultMemberPermissions).toString(),
82
+ dm_permission: current.directMessages,
83
+ options: snakecaseKeys(current.options || [])
84
+ }
85
+ ]
86
+ }
87
+ ]
88
+ });
89
+ } else {
90
+ let level2Item = level1Item.options.find(i => i.name == current.name.split(" ")[1] && i.type == "ChatInput");
91
+ if (!level2Item) {
92
+ level1Item.options.push({
93
+ type: ApplicationCommandOptionType.SubcommandGroup,
94
+ name: nameSplitted[1],
95
+ description: "...",
96
+ options: [
97
+ {
98
+ type: ApplicationCommandOptionType.Subcommand,
99
+ name: nameSplitted[2],
100
+ description: current.description,
101
+ default_member_permissions: reducePermissions(current.defaultMemberPermissions).toString(),
102
+ dm_permission: current.directMessages,
103
+ options: snakecaseKeys(current.options || [])
104
+ }
105
+ ]
106
+ })
107
+ } else {
108
+ level2Item.options.push({
109
+ type: ApplicationCommandOptionType.Subcommand,
110
+ name: nameSplitted[2],
111
+ description: current.description,
112
+ default_member_permissions: reducePermissions(current.defaultMemberPermissions).toString(),
113
+ dm_permission: current.directMessages,
114
+ options: snakecaseKeys(current.options || [])
115
+ });
116
+ }
117
+ }
118
+ break;
119
+ }
120
+ }
121
+ break;
122
+ }
123
+ case "MessageContextMenu": {
124
+ all.push({
125
+ type: ApplicationCommandType.Message,
126
+ name: current.name,
127
+ default_member_permissions: reducePermissions(current.defaultMemberPermissions).toString(),
128
+ dm_permission: current.directMessages
129
+ });
130
+ break;
131
+ }
132
+ case "UserContextMenu": {
133
+ all.push({
134
+ type: ApplicationCommandType.User,
135
+ name: current.name,
136
+ default_member_permissions: reducePermissions(current.defaultMemberPermissions).toString(),
137
+ dm_permission: current.directMessages
138
+ });
139
+ break;
140
+ }
141
+ }
142
+
143
+ return all;
144
+ }, []);
145
+
146
+
147
+ switch (publishType) {
148
+ case "Global": {
149
+ await rest.put(Routes.applicationGuildCommands(me.id, guildId), { body });
150
+ break;
151
+ }
152
+ case "Guild": {
153
+ await rest.put(Routes.applicationCommands(me.id), { body });
154
+ break;
155
+ }
156
+ }
157
+
158
+ }
@@ -0,0 +1,32 @@
1
+ import Discord from "discord.js";
2
+ import { DBI } from "../DBI";
3
+ import { DBIBaseInteraction, IDBIBaseExecuteCtx } from "./Interaction";
4
+ import { customIdBuilder } from "../utils/customId";
5
+
6
+ export interface IDBIButtonExecuteCtx extends IDBIBaseExecuteCtx {
7
+ interaction: Discord.ButtonInteraction<Discord.CacheType>;
8
+ data: ({ [key: string]: any, $ref: string, $unRef(): boolean } | string | number)[];
9
+ }
10
+
11
+ export type TDBIButtonOmitted = Omit<DBIButton, "type" | "description" | "dbi" | "toJSON">;
12
+
13
+ export class DBIButton extends DBIBaseInteraction {
14
+ constructor(dbi: DBI, args: TDBIButtonOmitted) {
15
+ super(dbi, {
16
+ ...(args as any),
17
+ type: "Button",
18
+ });
19
+ }
20
+
21
+ declare options: Omit<Discord.ButtonComponentData, "customId" | "type">;
22
+
23
+ override onExecute(ctx: IDBIButtonExecuteCtx): Promise<any> | any { };
24
+
25
+ toJSON(...customData: (string | number | object)[]): Discord.ButtonComponentData {
26
+ return {
27
+ ...this.options,
28
+ customId: customIdBuilder(this.dbi, this.name, customData),
29
+ type: Discord.ComponentType.Button
30
+ } as any;
31
+ };
32
+ }
@@ -0,0 +1,24 @@
1
+ import Discord from "discord.js";
2
+ import { DBI } from "../../DBI";
3
+ import { DBIBaseInteraction, IDBIBaseExecuteCtx } from "../Interaction";
4
+
5
+ export interface IDBIChatInputExecuteCtx extends IDBIBaseExecuteCtx {
6
+ interaction: Discord.ChatInputCommandInteraction<Discord.CacheType>;
7
+ }
8
+
9
+ export type TDBIChatInputOmitted = Omit<DBIChatInput, "type" | "dbi">;
10
+
11
+ export class DBIChatInput extends DBIBaseInteraction {
12
+ constructor(dbi: DBI, cfg: TDBIChatInputOmitted) {
13
+ super(dbi, {
14
+ ...(cfg as any),
15
+ type: "ChatInput",
16
+ name: cfg.name.toLowerCase(),
17
+ options: Array.isArray(cfg.options) ? cfg.options : []
18
+ });
19
+ }
20
+ directMessages?: boolean;
21
+ defaultMemberPermissions?: Discord.PermissionsString[];
22
+ declare options?: any[];
23
+ override onExecute(ctx: IDBIChatInputExecuteCtx) {}
24
+ }
@@ -0,0 +1,168 @@
1
+ import Discord from "discord.js";
2
+ import { IDBIBaseExecuteCtx } from "../Interaction";
3
+
4
+ type TValueName<T> = { value: T, name: string };
5
+ type TNameDescription = { name: string, description: string, required?: boolean };
6
+
7
+ type TMinMaxLength = { maxLength?: number, minLength?: number };
8
+ type TMinMaxValue = { maxValue?: number, minValue?: number };
9
+
10
+ export interface IDBICompleteCtx extends IDBIBaseExecuteCtx {
11
+ interaction: Discord.AutocompleteInteraction;
12
+ value: string | number;
13
+ }
14
+
15
+ export class DBIChatInputOptions {
16
+ static stringAutocomplete(cfg: TNameDescription & TMinMaxLength & { onComplete(ctx: IDBICompleteCtx): Promise<TValueName<string>[]> }) {
17
+ return {
18
+ type: Discord.ApplicationCommandOptionType.String,
19
+ name: cfg.name,
20
+ autocomplete: true,
21
+ onComplete: cfg.onComplete,
22
+ description: cfg.description,
23
+ maxLength: cfg.maxLength,
24
+ minLength: cfg.minLength,
25
+ required: cfg.required
26
+ };
27
+ }
28
+ static stringChoices(cfg: TNameDescription & TMinMaxLength & { choices: TValueName<string>[] }) {
29
+ return {
30
+ type: Discord.ApplicationCommandOptionType.String,
31
+ name: cfg.name,
32
+ choices: cfg.choices,
33
+ description: cfg.description,
34
+ maxLength: cfg.maxLength,
35
+ minLength: cfg.minLength,
36
+ required: cfg.required
37
+ };
38
+ }
39
+
40
+ static string(cfg: TNameDescription & TMinMaxLength) {
41
+ return {
42
+ type: Discord.ApplicationCommandOptionType.String,
43
+ name: cfg.name,
44
+ description: cfg.description,
45
+ maxLength: cfg.maxLength,
46
+ minLength: cfg.minLength,
47
+ required: cfg.required
48
+ };
49
+ }
50
+
51
+ static numberAutocomplete(cfg: TNameDescription & TMinMaxValue & { onComplete(ctx: IDBICompleteCtx): Promise<TValueName<number>[]> }) {
52
+ return {
53
+ type: Discord.ApplicationCommandOptionType.Number,
54
+ name: cfg.name,
55
+ autocomplete: true,
56
+ onComplete: cfg.onComplete,
57
+ description: cfg.description,
58
+ maxValue: cfg.maxValue,
59
+ minValue: cfg.minValue,
60
+ required: cfg.required
61
+ };
62
+ }
63
+
64
+ static numberChoices(cfg: TNameDescription & TMinMaxValue & { choices: TValueName<number>[] }) {
65
+ return {
66
+ type: Discord.ApplicationCommandOptionType.Number,
67
+ name: cfg.name,
68
+ choices: cfg.choices,
69
+ description: cfg.description,
70
+ maxValue: cfg.maxValue,
71
+ minValue: cfg.minValue,
72
+ required: cfg.required
73
+ };
74
+ }
75
+
76
+ static number(cfg: TNameDescription & TMinMaxValue) {
77
+ return {
78
+ type: Discord.ApplicationCommandOptionType.Number,
79
+ name: cfg.name,
80
+ description: cfg.description,
81
+ maxValue: cfg.maxValue,
82
+ minValue: cfg.minValue,
83
+ required: cfg.required
84
+ };
85
+ }
86
+
87
+ static integerAutocomplete(cfg: TNameDescription & TMinMaxValue & { onComplete(ctx: IDBICompleteCtx): Promise<TValueName<number>[]> }) {
88
+ return {
89
+ type: Discord.ApplicationCommandOptionType.Integer,
90
+ name: cfg.name,
91
+ autocomplete: true,
92
+ onComplete: cfg.onComplete,
93
+ description: cfg.description,
94
+ maxValue: cfg.maxValue,
95
+ minValue: cfg.minValue,
96
+ required: cfg.required
97
+ };
98
+ }
99
+
100
+ static integerChoices(cfg: TNameDescription & TMinMaxValue & { choices: TValueName<number>[] }) {
101
+ return {
102
+ type: Discord.ApplicationCommandOptionType.Integer,
103
+ name: cfg.name,
104
+ choices: cfg.choices,
105
+ description: cfg.description,
106
+ maxValue: cfg.maxValue,
107
+ minValue: cfg.minValue,
108
+ required: cfg.required
109
+ };
110
+ }
111
+
112
+ static integer(cfg: TNameDescription & TMinMaxValue) {
113
+ return {
114
+ type: Discord.ApplicationCommandOptionType.Integer,
115
+ name: cfg.name,
116
+ description: cfg.description,
117
+ maxValue: cfg.maxValue,
118
+ minValue: cfg.minValue,
119
+ required: cfg.required
120
+ };
121
+ }
122
+
123
+ static boolean(cfg: TNameDescription) {
124
+ return {
125
+ type: Discord.ApplicationCommandOptionType.Boolean,
126
+ name: cfg.name,
127
+ description: cfg.description,
128
+ required: cfg.required
129
+ };
130
+ }
131
+
132
+ static attachment(cfg: TNameDescription) {
133
+ return {
134
+ type: Discord.ApplicationCommandOptionType.Attachment,
135
+ name: cfg.name,
136
+ description: cfg.description,
137
+ required: cfg.required
138
+ };
139
+ }
140
+
141
+ static channel(cfg: TNameDescription & { channelTypes: Discord.ChannelType[] }) {
142
+ return {
143
+ type: Discord.ApplicationCommandOptionType.Channel,
144
+ name: cfg.name,
145
+ description: cfg.description,
146
+ channelTypes: cfg.channelTypes,
147
+ required: cfg.required
148
+ };
149
+ }
150
+
151
+ static mentionable(cfg: TNameDescription) {
152
+ return {
153
+ type: Discord.ApplicationCommandOptionType.Mentionable,
154
+ name: cfg.name,
155
+ description: cfg.description,
156
+ required: cfg.required
157
+ };
158
+ }
159
+
160
+ static user(cfg: TNameDescription) {
161
+ return {
162
+ type: Discord.ApplicationCommandOptionType.User,
163
+ name: cfg.name,
164
+ description: cfg.description,
165
+ required: cfg.required
166
+ };
167
+ }
168
+ }
@@ -0,0 +1,115 @@
1
+ import Discord from "discord.js";
2
+ import { DBI } from "../DBI";
3
+
4
+ export interface ClientEvents {
5
+ applicationCommandPermissionsUpdate: { data: Discord.ApplicationCommandPermissionsUpdateData };
6
+ cacheSweep: { message: string };
7
+ channelCreate: { channel: Discord.NonThreadGuildBasedChannel };
8
+ channelDelete: { channel: Discord.DMChannel | Discord.NonThreadGuildBasedChannel };
9
+ channelPinsUpdate: { channel: Discord.TextBasedChannel, date: Date };
10
+ channelUpdate: {
11
+ oldChannel: Discord.DMChannel | Discord.NonThreadGuildBasedChannel,
12
+ newChannel: Discord.DMChannel | Discord.NonThreadGuildBasedChannel,
13
+ };
14
+ debug: { message: string };
15
+ warn: { message: string };
16
+ emojiCreate: { emoji: Discord.GuildEmoji };
17
+ emojiDelete: { emoji: Discord.GuildEmoji };
18
+ emojiUpdate: { oldEmoji: Discord.GuildEmoji, newEmoji: Discord.GuildEmoji };
19
+ error: { error: Error };
20
+ guildBanAdd: { ban: Discord.GuildBan };
21
+ guildBanRemove: { ban: Discord.GuildBan };
22
+ guildCreate: { guild: Discord.Guild };
23
+ guildDelete: { guild: Discord.Guild };
24
+ guildUnavailable: { guild: Discord.Guild };
25
+ guildIntegrationsUpdate: { guild: Discord.Guild };
26
+ guildMemberAdd: { member: Discord.GuildMember };
27
+ guildMemberAvailable: { member: Discord.GuildMember | Discord.PartialGuildMember };
28
+ guildMemberRemove: { member: Discord.GuildMember | Discord.PartialGuildMember };
29
+ guildMembersChunk: {
30
+ members: Discord.Collection<Discord.Snowflake, Discord.GuildMember>,
31
+ guild: Discord.Guild,
32
+ data: { count: number; index: number; nonce: string | undefined },
33
+ };
34
+ guildMemberUpdate: { oldMember: Discord.GuildMember | Discord.PartialGuildMember, newMember: Discord.GuildMember };
35
+ guildUpdate: { oldGuild: Discord.Guild, newGuild: Discord.Guild };
36
+ inviteCreate: { invite: Discord.Invite };
37
+ inviteDelete: { invite: Discord.Invite };
38
+ messageCreate: { message: Discord.Message };
39
+ messageDelete: { message: Discord.Message | Discord.PartialMessage };
40
+ messageReactionRemoveAll: {
41
+ message: Discord.Message | Discord.PartialMessage,
42
+ reactions: Discord.Collection<string | Discord.Snowflake, Discord.MessageReaction>,
43
+ };
44
+ messageReactionRemoveEmoji: { reaction: Discord.MessageReaction | Discord.PartialMessageReaction };
45
+ messageDeleteBulk: { messages: Discord.Collection<Discord.Snowflake, Discord.Message | Discord.PartialMessage>, channel: Discord.TextBasedChannel };
46
+ messageReactionAdd: { reaction: Discord.MessageReaction | Discord.PartialMessageReaction, user: Discord.User | Discord.PartialUser };
47
+ messageReactionRemove: { reaction: Discord.MessageReaction | Discord.PartialMessageReaction, user: Discord.User | Discord.PartialUser };
48
+ messageUpdate: { oldMessage: Discord.Message | Discord.PartialMessage, newMessage: Discord.Message | Discord.PartialMessage };
49
+ presenceUpdate: { oldPresence: Discord.Presence | null, newPresence: Discord.Presence };
50
+ ready: { client: Discord.Client<true> };
51
+ invalidated: {};
52
+ roleCreate: { role: Discord.Role };
53
+ roleDelete: { role: Discord.Role };
54
+ roleUpdate: { oldRole: Discord.Role, newRole: Discord.Role };
55
+ threadCreate: { thread: Discord.AnyThreadChannel, newlyCreated: boolean };
56
+ threadDelete: { thread: Discord.AnyThreadChannel };
57
+ threadListSync: { threads: Discord.Collection<Discord.Snowflake, Discord.AnyThreadChannel>, guild: Discord.Guild };
58
+ threadMemberUpdate: { oldMember: Discord.ThreadMember, newMember: Discord.ThreadMember };
59
+ threadMembersUpdate: {
60
+ addedMembers: Discord.Collection<Discord.Snowflake, Discord.ThreadMember>,
61
+ removedMembers: Discord.Collection<Discord.Snowflake, Discord.ThreadMember | Discord.PartialThreadMember>,
62
+ thread: Discord.AnyThreadChannel,
63
+ };
64
+ threadUpdate: { oldThread: Discord.AnyThreadChannel, newThread: Discord.AnyThreadChannel };
65
+ typingStart: { typing: Discord.Typing };
66
+ userUpdate: { oldUser: Discord.User | Discord.PartialUser, newUser: Discord.User };
67
+ voiceStateUpdate: { oldState: Discord.VoiceState, newState: Discord.VoiceState };
68
+ webhookUpdate: { channel: Discord.TextChannel | Discord.NewsChannel | Discord.VoiceChannel };
69
+ interactionCreate: { interaction: Discord.Interaction };
70
+ shardDisconnect: { closeEvent: Discord.CloseEvent, shardId: number };
71
+ shardError: { error: Error, shardId: number };
72
+ shardReady: { shardId: number, unavailableGuilds: Set<Discord.Snowflake> | undefined };
73
+ shardReconnecting: { shardId: number };
74
+ shardResume: { shardId: number, replayedEvents: number };
75
+ stageInstanceCreate: { stageInstance: Discord.StageInstance };
76
+ stageInstanceUpdate: { oldStageInstance: Discord.StageInstance | null, newStageInstance: Discord.StageInstance };
77
+ stageInstanceDelete: { stageInstance: Discord.StageInstance };
78
+ stickerCreate: { sticker: Discord.Sticker };
79
+ stickerDelete: { sticker: Discord.Sticker };
80
+ stickerUpdate: { oldSticker: Discord.Sticker, newSticker: Discord.Sticker };
81
+ guildScheduledEventCreate: { guildScheduledEvent: Discord.GuildScheduledEvent };
82
+ guildScheduledEventUpdate: {
83
+ oldGuildScheduledEvent: Discord.GuildScheduledEvent | null,
84
+ newGuildScheduledEvent: Discord.GuildScheduledEvent,
85
+ };
86
+ guildScheduledEventDelete: { guildScheduledEvent: Discord.GuildScheduledEvent };
87
+ guildScheduledEventUserAdd: { guildScheduledEvent: Discord.GuildScheduledEvent, user: Discord.User };
88
+ guildScheduledEventUserRemove: { guildScheduledEvent: Discord.GuildScheduledEvent, user: Discord.User };
89
+ }
90
+
91
+ export type DBIEventCombinations = {
92
+ [K in keyof ClientEvents]: {
93
+ name: K,
94
+ onExecute: (ctx: ClientEvents[K] & { other: Record<string, any> }) => Promise<any> | any
95
+ }
96
+ }[keyof ClientEvents];
97
+
98
+ export type TDBIEventOmitted = Omit<DBIEvent, "type" | "name" | "onExecute" | "client" | "dbi"> & DBIEventCombinations;
99
+
100
+ export class DBIEvent {
101
+ readonly type: "Event";
102
+ other?: Record<string, any>;
103
+ id?: string;
104
+ name: string;
105
+ onExecute: (...args: any[]) => any;
106
+ dbi: DBI;
107
+ constructor(dbi: DBI, cfg: TDBIEventOmitted) {
108
+ this.dbi = dbi;
109
+ this.type = "Event";
110
+ this.id = cfg.id;
111
+ this.other = cfg.other;
112
+ this.name = cfg.name;
113
+ this.onExecute = cfg.onExecute;
114
+ }
115
+ }
@@ -0,0 +1,69 @@
1
+ import Discord from "discord.js";
2
+ import { DBI } from "../DBI";
3
+ import { DBILocale } from "./Locale";
4
+
5
+ export interface IDBIBaseExecuteCtx {
6
+ interaction:
7
+ | Discord.ChatInputCommandInteraction
8
+ | Discord.UserContextMenuCommandInteraction
9
+ | Discord.MessageContextMenuCommandInteraction
10
+ | Discord.ModalSubmitInteraction
11
+ | Discord.AutocompleteInteraction
12
+ | Discord.SelectMenuInteraction
13
+ | Discord.ButtonInteraction;
14
+ locale: {
15
+ user: DBILocale,
16
+ guild?: DBILocale
17
+ }
18
+ dbi: DBI;
19
+ setRateLimit(type: TDBIRateLimitTypes, duration: number): Promise<any>;
20
+ other: Record<string, any>;
21
+ }
22
+
23
+ export type TDBIInteractionTypes =
24
+ | "ChatInput"
25
+ | "UserContextMenu"
26
+ | "MessageContextMenu"
27
+ | "Modal"
28
+ | "Autocomplete"
29
+ | "SelectMenu"
30
+ | "Button";
31
+
32
+ export type TDBIRateLimitTypes =
33
+ | "User"
34
+ | "Channel"
35
+ | "Guild"
36
+ | "Member"
37
+ | "Message";
38
+
39
+
40
+ export type DBIRateLimit = {
41
+ type: TDBIRateLimitTypes;
42
+ /**
43
+ * Duration in milliseconds.
44
+ */
45
+ duration: number;
46
+ }
47
+
48
+ export class DBIBaseInteraction {
49
+ constructor(dbi: DBI, cfg: Omit<DBIBaseInteraction, "dbi">) {
50
+ this.dbi = dbi;
51
+ this.name = cfg.name;
52
+ this.description = cfg.description;
53
+ this.onExecute = cfg.onExecute;
54
+ this.type = cfg.type;
55
+ this.options = cfg.options;
56
+ this.other = cfg.other;
57
+ }
58
+
59
+ dbi: DBI;
60
+ name: string;
61
+ description: string;
62
+ readonly type: TDBIInteractionTypes;
63
+ options?: any | any[];
64
+ other?: Record<string, any>;
65
+ rateLimits?: DBIRateLimit[];
66
+ onExecute(ctx: IDBIBaseExecuteCtx): Promise<any> | any {
67
+
68
+ }
69
+ }