xernerx 0.1.120-beta.2 → 0.1.120-beta.21

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 (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +52 -0
  3. package/dist/main.cjs +1269 -266
  4. package/dist/main.cjs.map +1 -1
  5. package/dist/main.d.cts +651 -116
  6. package/dist/main.d.ts +651 -116
  7. package/dist/main.js +1257 -247
  8. package/dist/main.js.map +1 -1
  9. package/package.json +31 -18
  10. package/src/build/XernerxBaseBuilder.ts +21 -0
  11. package/src/build/XernerxEventBuilder.ts +39 -0
  12. package/src/build/XernerxMessageCommandBuilder.ts +60 -0
  13. package/src/build/XernerxSlashCommandBuilder.ts +290 -0
  14. package/src/client/XernerxClient.ts +173 -151
  15. package/src/client/XernerxShardClient.ts +89 -0
  16. package/src/events/clientReady.ts +96 -0
  17. package/src/events/entitlementCreate.ts +15 -0
  18. package/src/events/interactionCreate.ts +36 -0
  19. package/src/events/messageCreate.ts +60 -0
  20. package/src/events/messageDelete.ts +41 -0
  21. package/src/events/messageUpdate.ts +60 -0
  22. package/src/events/slashCommandInteraction.ts +55 -0
  23. package/src/handler/CommandHandler.ts +132 -0
  24. package/src/handler/EventHandler.ts +45 -0
  25. package/src/handler/Handler.ts +98 -0
  26. package/src/interfaces/XernerxClientOptions.ts +13 -0
  27. package/src/interfaces/XernerxClientStats.ts +15 -0
  28. package/src/interfaces/XernerxEventBuilderOptions.ts +9 -0
  29. package/src/interfaces/XernerxMessageCommandBuilderOptions.ts +8 -0
  30. package/src/interfaces/XernerxMessageCommandHandlerOptions.ts +15 -0
  31. package/src/interfaces/XernerxShardClientOptions.ts +5 -0
  32. package/src/interfaces/XernerxSlashCommand.ts +19 -0
  33. package/src/interfaces/XernerxSlashCommandBuilderOptions.ts +70 -0
  34. package/src/interfaces/XernerxSlashCommandHandlerOptions.ts +5 -0
  35. package/src/main.ts +21 -7
  36. package/src/model/XernerxGuild.ts +13 -0
  37. package/src/model/XernerxInteractionArguments.ts +92 -0
  38. package/src/model/XernerxMonitisation.ts +73 -0
  39. package/src/model/XernerxUser.ts +82 -0
  40. package/src/tools/XernerxBase.ts +16 -0
  41. package/src/tools/XernerxError.ts +16 -0
  42. package/src/tools/XernerxInfo.ts +13 -0
  43. package/src/tools/XernerxInitial.ts +28 -0
  44. package/src/tools/XernerxSuccess.ts +13 -0
  45. package/src/tools/XernerxWarn.ts +13 -0
  46. package/src/types/Events.d.ts +21 -0
  47. package/src/types/Interaction.d.ts +90 -0
  48. package/src/types/Message.d.ts +16 -0
  49. package/src/util/XernerxInteractionUtil.ts +82 -0
  50. package/src/util/XernerxMessageUtil.ts +105 -0
  51. package/src/util/XernerxUtil.ts +47 -0
  52. package/src/validators/XernerxBaseValidator.ts +82 -0
  53. package/src/validators/XernerxSlashCommandValidator.ts +11 -0
  54. package/dist/main.global.js +0 -88544
  55. package/dist/main.global.js.map +0 -1
  56. package/src/base/XernerxContextCommand.ts +0 -24
  57. package/src/base/XernerxEvent.ts +0 -21
  58. package/src/base/XernerxInhibitor.ts +0 -21
  59. package/src/base/XernerxMessageCommand.ts +0 -24
  60. package/src/base/XernerxSlashCommand.ts +0 -26
  61. package/src/handlers/CommandHandler.ts +0 -31
  62. package/src/handlers/Handler.ts +0 -57
  63. package/src/tools/XernerxLog.ts +0 -58
  64. package/src/types/interfaces.ts +0 -25
  65. package/src/types/types.ts +0 -29
  66. package/src/util/ClientUtil.ts +0 -29
  67. package/src/util/Util.ts +0 -11
  68. package/src/util/prompts.ts +0 -120
@@ -0,0 +1,290 @@
1
+ /** @format */
2
+
3
+ import { z } from 'zod';
4
+ import {
5
+ ApplicationIntegrationType,
6
+ ChannelType,
7
+ InteractionContextType,
8
+ Locale,
9
+ PermissionFlags,
10
+ PermissionFlagsBits,
11
+ Permissions,
12
+ RestOrArray,
13
+ SlashCommandBooleanOption,
14
+ SlashCommandBuilder,
15
+ SlashCommandChannelOption,
16
+ SlashCommandIntegerOption,
17
+ SlashCommandMentionableOption,
18
+ SlashCommandNumberOption,
19
+ SlashCommandRoleOption,
20
+ SlashCommandStringOption,
21
+ SlashCommandSubcommandBuilder,
22
+ SlashCommandSubcommandGroupBuilder,
23
+ SlashCommandUserOption,
24
+ } from 'discord.js';
25
+
26
+ import { XernerxWarn } from '../tools/XernerxWarn.js';
27
+ import {
28
+ XernerxSlashCommandBuilderGroup,
29
+ XernerxSlashCommandBuilderOption,
30
+ XernerxSlashCommandBuilderOptions,
31
+ XernerxSlashCommandBuilderSubcommand,
32
+ } from '../interfaces/XernerxSlashCommandBuilderOptions.js';
33
+ import { XernerxBaseBuilder } from './XernerxBaseBuilder.js';
34
+ import { XernerxSlashCommand, XernerxSlashCommandAutocomplete } from '../interfaces/XernerxSlashCommand.js';
35
+
36
+ export class XernerxSlashCommandBuilder extends XernerxBaseBuilder {
37
+ // Discord
38
+ declare public readonly name: string;
39
+ declare public readonly description: string;
40
+ declare public readonly integration: RestOrArray<InteractionContextType>;
41
+ declare public readonly data: SlashCommandBuilder;
42
+ declare public readonly options: Array<XernerxSlashCommandBuilderOption>;
43
+ declare public readonly subcommands: Array<XernerxSlashCommandBuilderSubcommand>;
44
+ declare public readonly groups: Array<XernerxSlashCommandBuilderGroup>;
45
+
46
+ // Xernerx
47
+ declare public readonly premium?: boolean;
48
+ declare public readonly defer?: boolean;
49
+ declare public readonly deploy?: { global?: boolean; guilds?: Array<string> | string };
50
+ declare public readonly info?: string;
51
+ declare public readonly usage?: string;
52
+ declare public readonly category?: string;
53
+ declare public readonly cooldown?: number;
54
+ declare public readonly permissions: { client: Permissions | number | bigint | null; user: Permissions | number | bigint | null };
55
+ declare public readonly strict?: { owner?: boolean; users?: Array<string>; channels?: Array<string>; guilds?: Array<string>; types?: ChannelType };
56
+ declare public readonly ignore?: { owner?: boolean; users?: Array<string>; channels?: Array<string>; guilds?: Array<string>; types?: ChannelType };
57
+
58
+ // Static
59
+ declare public readonly filetype: 'XernerxSlashCommand';
60
+
61
+ constructor(id: string, options: XernerxSlashCommandBuilderOptions) {
62
+ super(id, options);
63
+
64
+ options = z
65
+ .object({
66
+ // Discord
67
+ name: z.string(),
68
+ locales: z.record(z.string(), z.object({ name: z.string(), description: z.string() })).optional(),
69
+ description: z.string(),
70
+ contexts: z.array(z.custom<keyof typeof InteractionContextType>()).default(['Guild']),
71
+ integration: z.array(z.custom<keyof typeof ApplicationIntegrationType>()).default(['GuildInstall']),
72
+ nsfw: z.boolean().default(false),
73
+ options: z.any(),
74
+ subcommands: z.any(),
75
+ groups: z.any(),
76
+
77
+ // Xernerx
78
+ premium: z.boolean().default(false),
79
+ defer: z.boolean().default(false),
80
+ deploy: z.object({ global: z.boolean().default(true), guilds: z.string().or(z.array(z.string())).default([]) }).optional(),
81
+ info: z.string().optional(),
82
+ usage: z.string().optional(),
83
+ category: z.string().optional(),
84
+ cooldown: z.number().min(0).default(0),
85
+ strict: z
86
+ .object({
87
+ owner: z.boolean().default(false),
88
+ users: z.array(z.string()).default([]),
89
+ channels: z.array(z.string()).default([]),
90
+ guilds: z.array(z.string()).default([]),
91
+ types: z.enum(ChannelType).optional(),
92
+ })
93
+ .optional(),
94
+ ignore: z
95
+ .object({
96
+ owner: z.boolean().default(false),
97
+ users: z.array(z.string()).default([]),
98
+ channels: z.array(z.string()).default([]),
99
+ guilds: z.array(z.string()).default([]),
100
+ types: z.enum(ChannelType).optional(),
101
+ })
102
+ .optional(),
103
+ permissions: z
104
+ .object({
105
+ client: z
106
+ .union([z.array(z.custom<keyof PermissionFlags>()), z.number(), z.bigint()])
107
+ .nullable()
108
+ .default(null),
109
+ user: z
110
+ .union([z.array(z.custom<keyof PermissionFlags>()), z.number(), z.bigint()])
111
+ .nullable()
112
+ .default(null),
113
+ })
114
+ .default({ client: null, user: null }),
115
+ })
116
+ .parse(options);
117
+
118
+ this.name = options.name;
119
+
120
+ this.description = options.description;
121
+
122
+ this.info = options.info;
123
+
124
+ this.usage = options.usage;
125
+
126
+ this.category = options.category;
127
+
128
+ this.cooldown = options.cooldown;
129
+
130
+ this.premium = options.premium || false;
131
+
132
+ this.defer = options.defer;
133
+
134
+ this.deploy = {
135
+ global: options.deploy?.global ?? true,
136
+ guilds: typeof options.deploy?.guilds == 'string' ? [options.deploy.guilds] : options.deploy?.guilds || [],
137
+ };
138
+
139
+ this.filetype = 'XernerxSlashCommand';
140
+
141
+ this.permissions = options.permissions as typeof this.permissions;
142
+
143
+ this.strict = options.strict;
144
+
145
+ this.ignore = options.ignore;
146
+
147
+ this.data = new SlashCommandBuilder();
148
+
149
+ this.data.setName(this.name);
150
+
151
+ this.data.setDescription(this.description);
152
+
153
+ this.data.setContexts(...(options.contexts?.map((context) => InteractionContextType[context as keyof typeof InteractionContextType]) || [InteractionContextType.Guild]));
154
+
155
+ this.data.setIntegrationTypes(
156
+ ...(options.integration?.map((integration) => ApplicationIntegrationType[integration as keyof typeof ApplicationIntegrationType]) || [ApplicationIntegrationType.GuildInstall])
157
+ );
158
+
159
+ if (Array.isArray(options.permissions?.user))
160
+ this.data.setDefaultMemberPermissions(options.permissions?.user?.map((permission) => PermissionFlagsBits[permission as keyof PermissionFlags]).reduce((a, b) => (a += b)));
161
+ else this.data.setDefaultMemberPermissions(options.permissions?.user || null);
162
+
163
+ this.data.setNSFW(options.nsfw || false);
164
+
165
+ for (const locale of Object.entries(options.locales || [])) {
166
+ this.data.setNameLocalization(locale[0] as Locale, locale[1].name);
167
+ this.data.setDescriptionLocalization(locale[0] as Locale, locale[1].description);
168
+ }
169
+
170
+ if (options.options && options?.options?.length > 0) {
171
+ this.addArguments(this.data, options.options);
172
+
173
+ this.options = options.options;
174
+ }
175
+
176
+ if (options.subcommands && options?.subcommands?.length > 0) {
177
+ this.addSubcommands(this.data, options.subcommands);
178
+
179
+ this.subcommands = options.subcommands;
180
+ }
181
+
182
+ if (options.groups && options?.groups?.length > 0) {
183
+ this.addSubcommandGroups(options.groups);
184
+
185
+ this.groups = options.groups;
186
+ }
187
+
188
+ this.client = this.client;
189
+ }
190
+
191
+ /**
192
+ * Handles the autocomplete functionality for a slash command.
193
+ *
194
+ * @param args - The arguments for the autocomplete function, which include the context and options for the command.
195
+ * @returns A promise that resolves to either void or any value, depending on the implementation.
196
+ */
197
+ public async autocomplete(args: XernerxSlashCommandAutocomplete): Promise<void | any> {}
198
+
199
+ /**
200
+ * Evaluates conditions for executing a slash command.
201
+ *
202
+ * @param args - The arguments for the conditions function, which include the context and options for the command.
203
+ * @returns A promise that resolves to either void or any value, depending on the implementation.
204
+ */
205
+ public async conditions(args: XernerxSlashCommand): Promise<void | any> {}
206
+
207
+ /**
208
+ * Executes the slash command.
209
+ *
210
+ * @param args - The arguments for the exec function, which include the context and options for the command.
211
+ * @returns A promise that resolves to either void or any value, depending on the implementation.
212
+ */
213
+ public async exec(args: XernerxSlashCommand): Promise<void | any> {
214
+ new XernerxWarn(`${this.id} has no exec function, command will not respond.`);
215
+ }
216
+
217
+ private addArguments(command: SlashCommandBuilder | SlashCommandSubcommandBuilder, args: Array<XernerxSlashCommandBuilderOption>) {
218
+ for (const argument of args) {
219
+ let slashCommandArgumentType: string = `${argument.type.charAt(0).toUpperCase()}${argument.type.slice(1).toLowerCase()}`;
220
+
221
+ (command[`add${slashCommandArgumentType as UpperCasedSlashCommandArgumentOptions}Option`] as Function)((option: SlashCommandOption) => {
222
+ option
223
+ .setName(argument.name)
224
+ .setDescription(argument.description)
225
+ .setRequired(argument.required || false);
226
+
227
+ for (const locale of Object.entries(argument.locales || [])) {
228
+ option.setNameLocalization(locale[0] as Locale, locale[1].name);
229
+ option.setDescriptionLocalization(locale[0] as Locale, locale[1].description);
230
+ }
231
+
232
+ if (slashCommandArgumentType === 'String') {
233
+ if (argument.choices) {
234
+ for (const choice of argument.choices) {
235
+ const locales = choice?.locales;
236
+
237
+ (option as SlashCommandStringOption).addChoices({ ...choice, name_localizations: locales });
238
+ }
239
+ }
240
+
241
+ if (argument.maxLength) (option as SlashCommandStringOption).setMaxLength(argument.maxLength);
242
+ if (argument.minLength) (option as SlashCommandStringOption).setMinLength(argument.minLength);
243
+
244
+ (option as SlashCommandStringOption).setAutocomplete(argument.autocomplete || false);
245
+ }
246
+
247
+ return option;
248
+ });
249
+ }
250
+ }
251
+
252
+ private addSubcommands(method: SlashCommandBuilder | SlashCommandSubcommandGroupBuilder, subcommands: Array<XernerxSlashCommandBuilderSubcommand>) {
253
+ for (const subcommand of subcommands) {
254
+ let sub = new SlashCommandSubcommandBuilder().setName(subcommand.name).setDescription(subcommand.description);
255
+
256
+ for (const locale of Object.entries(subcommand.locales || [])) {
257
+ sub.setNameLocalization(locale[0] as Locale, locale[1].name);
258
+ sub.setDescriptionLocalization(locale[0] as Locale, locale[1].description);
259
+ }
260
+
261
+ if (subcommand.options && subcommand?.options?.length > 0) this.addArguments(sub, subcommand.options);
262
+
263
+ method.addSubcommand(sub);
264
+ }
265
+ }
266
+
267
+ /**
268
+ * Adds subcommand groups to the slash command builder.
269
+ *
270
+ * @param groups - An array of subcommand groups to be added. Each group contains a name, description, locales, and subcommands.
271
+ */
272
+ private addSubcommandGroups(groups: Array<XernerxSlashCommandBuilderGroup>) {
273
+ for (const group of groups) {
274
+ let subcommandGroup = new SlashCommandSubcommandGroupBuilder().setName(group.name).setDescription(group.description);
275
+
276
+ for (const locale of Object.entries(group.locales || [])) {
277
+ subcommandGroup.setNameLocalization(locale[0] as Locale, locale[1].name);
278
+ subcommandGroup.setDescriptionLocalization(locale[0] as Locale, locale[1].description);
279
+ }
280
+
281
+ if (group.subcommands?.length > 0) this.addSubcommands(subcommandGroup, group.subcommands);
282
+
283
+ this.data.addSubcommandGroup(subcommandGroup);
284
+ }
285
+ }
286
+ }
287
+
288
+ type UpperCasedSlashCommandArgumentOptions = 'Attachment' | 'Boolean' | 'Channel' | 'Integer' | 'Mentionable' | 'Number' | 'Role' | 'String' | 'User';
289
+ type SlashCommandOption = SlashCommandOptionChoices | SlashCommandBooleanOption | SlashCommandUserOption | SlashCommandChannelOption | SlashCommandRoleOption | SlashCommandMentionableOption;
290
+ type SlashCommandOptionChoices = SlashCommandStringOption | SlashCommandNumberOption | SlashCommandIntegerOption;
@@ -1,151 +1,173 @@
1
- /** @format */
2
-
3
- import * as Discord from 'discord.js';
4
- import { z } from 'zod';
5
-
6
- import { start } from '../util/prompts.js';
7
- import { XernerxStats } from '../types/interfaces.js';
8
- import { CommandHandler } from '../handlers/CommandHandler.js';
9
- import { XernerxMessageCommand } from '../base/XernerxMessageCommand.js';
10
- import { XernerxSlashCommand } from '../main.js';
11
- import { XernerxContextCommand } from '../base/XernerxContextCommand.js';
12
- import { XernerxEvent } from '../base/XernerxEvent.js';
13
- import { XernerxInhibitor } from '../base/XernerxInhibitor.js';
14
- import XernerxLog from '../tools/XernerxLog.js';
15
- import sharpyy from 'sharpyy';
16
- import { ClientUtil } from '../util/ClientUtil.js';
17
-
18
- export class XernerxClient<T = {}> extends Discord.Client {
19
- public declare readonly settings;
20
- public declare readonly stats: XernerxStats;
21
- public declare readonly modules: {
22
- commandHandler: CommandHandler;
23
- options: {
24
- message?: { global?: boolean };
25
- slash?: { global?: boolean };
26
- context?: { global?: boolean };
27
- };
28
- };
29
- public declare readonly util: ClientUtil;
30
- public declare readonly commands;
31
- public declare readonly events;
32
- public declare readonly inhibitors;
33
-
34
- constructor(DiscordOptions: any, XernerxOptions: any, config: T) {
35
- super(DiscordOptions);
36
-
37
- this.settings = z
38
- .object({
39
- // required settings
40
- token: z.string(),
41
-
42
- // optional settings
43
- global: z.boolean().default(false),
44
- owners: z.array(z.string()).default([]),
45
- guilds: z.array(z.string()).default([]),
46
-
47
- // dev settings
48
- debug: z.boolean().default(false),
49
- })
50
- .parse({ ...XernerxOptions, ...config });
51
-
52
- this.stats = {
53
- guilds: null,
54
- users: null,
55
- shardId: null,
56
- shardCount: null,
57
- shards: null,
58
- voteCount: null,
59
- votes: null,
60
- };
61
-
62
- this.util = new ClientUtil(this);
63
-
64
- start(this);
65
-
66
- this.modules = {
67
- commandHandler: new CommandHandler(this),
68
-
69
- options: {},
70
- };
71
-
72
- this.commands = {
73
- message: new Discord.Collection() as Discord.Collection<string, XernerxMessageCommand>,
74
- slash: new Discord.Collection() as Discord.Collection<string, XernerxSlashCommand>,
75
- context: new Discord.Collection() as Discord.Collection<string, XernerxContextCommand>,
76
- stats: {
77
- slash: {
78
- local: 0,
79
- global: 0,
80
- },
81
- message: {
82
- local: 0,
83
- global: 0,
84
- },
85
- context: {
86
- local: 0,
87
- global: 0,
88
- },
89
- },
90
- };
91
-
92
- this.events = new Discord.Collection() as Discord.Collection<string, XernerxEvent>;
93
- this.inhibitors = new Discord.Collection() as Discord.Collection<string, XernerxInhibitor>;
94
-
95
- this.connect();
96
- }
97
-
98
- private async connect() {
99
- // slash cmds
100
- this.deploy();
101
-
102
- // login
103
- this.login(this.settings.token);
104
- }
105
-
106
- private async deploy() {
107
- this.once('ready', async (client) => {
108
- const commands: { local: Array<XernerxSlashCommand | XernerxContextCommand>; global: Array<XernerxSlashCommand | XernerxContextCommand> } = { local: [], global: [] };
109
-
110
- if (this.settings.global) {
111
- if (!this.modules.options.slash?.global) commands.global.push(...(this.commands.slash as any));
112
- else {
113
- commands.global.push(...(this.commands.slash.filter((c) => c.global) as any));
114
-
115
- commands.local.push(...(this.commands.slash.filter((c) => !c.global) as any));
116
- }
117
-
118
- if (!this.modules.options.context?.global) commands.global.push(...(this.commands.context as any));
119
- else {
120
- commands.global.push(...(this.commands.context.filter((c) => c.global) as any));
121
-
122
- commands.local.push(...(this.commands.context.filter((c) => !c.global) as any));
123
- }
124
- } else commands.local.push(...(this.commands.context as any), ...(this.commands.slash as any));
125
-
126
- for (const id of this.settings.guilds) {
127
- const guild = await this.guilds.fetch(id);
128
-
129
- if (!commands.local.length) break;
130
-
131
- if (this.settings.debug) XernerxLog.debug(`Attempting to deploy commands to guild: ${sharpyy(guild.name, 'txBlue')}`);
132
-
133
- this.rest.put(Discord.Routes.applicationGuildCommands(client.user.id, id), { body: (commands.local as any).map(([id, command]: any) => command.toJSON()) });
134
-
135
- await XernerxLog.box(
136
- (commands.local as any).map(([id]: [string]) => sharpyy(id, 'txYellow')).join(', '),
137
- 'red',
138
- `Deployed ${sharpyy('local', 'txRed', 'bold')} commands in ${sharpyy(guild.name, 'txBlue')}`
139
- );
140
- }
141
-
142
- if (this.settings.global) {
143
- if (this.settings.debug) XernerxLog.debug(`Attempting to deploy commands globally`);
144
-
145
- this.rest.put(Discord.Routes.applicationCommands(client.user.id), { body: [] });
146
-
147
- await XernerxLog.box((commands.global as any).map(([id]: [string]) => sharpyy(id, 'txYellow')).join(', '), 'green', `Deployed ${sharpyy('global', 'txGreen', 'bold')} commands`);
148
- }
149
- });
150
- }
151
- }
1
+ /** @format */
2
+
3
+ import { Client, ClientOptions, Collection, RESTGetAPISKUsResult } from 'discord.js';
4
+ import sharpyy from 'sharpyy';
5
+ import { ClusterClient, DjsDiscordClient, getInfo } from 'discord-hybrid-sharding';
6
+ import z from 'zod';
7
+
8
+ import { XernerxClientOptions } from '../interfaces/XernerxClientOptions.js';
9
+ import { XernerxInfo } from '../tools/XernerxInfo.js';
10
+ import { XernerxClientStats } from '../interfaces/XernerxClientStats.js';
11
+ import { XernerxInitial } from '../tools/XernerxInitial.js';
12
+ import { XernerxError } from '../tools/XernerxError.js';
13
+ import { XernerxSuccess } from '../tools/XernerxSuccess.js';
14
+ import { XernerxMonitisation } from '../model/XernerxMonitisation.js';
15
+ import { EventHandler } from '../handler/EventHandler.js';
16
+ import { XernerxEventBuilder } from '../build/XernerxEventBuilder.js';
17
+ import { CommandHandler } from '../handler/CommandHandler.js';
18
+ import { XernerxMessageCommandBuilder } from '../build/XernerxMessageCommandBuilder.js';
19
+ import { XernerxMessageCommandHandlerOptions } from '../interfaces/XernerxMessageCommandHandlerOptions.js';
20
+ import { XernerxSlashCommandHandlerOptions } from '../interfaces/XernerxSlashCommandHandlerOptions.js';
21
+ import { XernerxSlashCommandBuilder } from '../build/XernerxSlashCommandBuilder.js';
22
+
23
+ export class XernerxClient extends Client {
24
+ // Config
25
+ declare public readonly token: string;
26
+ declare public readonly sharded: boolean;
27
+ declare public readonly settings: XernerxClientOptions;
28
+ declare public readonly premium: {
29
+ owners?: boolean;
30
+ consume?: boolean;
31
+ synchronize?: boolean;
32
+ };
33
+
34
+ // Setup
35
+ declare public readonly monitisation: { skus: RESTGetAPISKUsResult };
36
+ declare public readonly stats: XernerxClientStats;
37
+ declare public readonly cluster: ClusterClient | null;
38
+ declare public readonly cache: { messages: Collection<string, string>; slash: Collection<string, string> };
39
+ declare public readonly handler: { message: XernerxMessageCommandHandlerOptions; slash: XernerxSlashCommandHandlerOptions };
40
+
41
+ // Collections
42
+ declare public readonly commands: {
43
+ message: Collection<string, XernerxMessageCommandBuilder>;
44
+ slash: Collection<string, XernerxSlashCommandBuilder>;
45
+ };
46
+ declare public readonly events: Collection<string, XernerxEventBuilder>;
47
+
48
+ // Handlers
49
+ declare public readonly modules: { eventHandler: EventHandler; commandHandler: CommandHandler };
50
+
51
+ constructor(options: ClientOptions & XernerxClientOptions) {
52
+ try {
53
+ options.shards = getInfo().SHARD_LIST;
54
+ options.shardCount = getInfo().TOTAL_SHARDS;
55
+ } catch {
56
+ new XernerxInitial('Client');
57
+ }
58
+
59
+ super(options);
60
+
61
+ this.settings = z
62
+ .object({
63
+ token: z.string(),
64
+ global: z.boolean().default(false),
65
+ guildId: z.string().or(z.array(z.string()).max(5)).default([]),
66
+ owners: z.string().or(z.array(z.string()).max(5)).default([]),
67
+ premium: z
68
+ .object({
69
+ owners: z.boolean().default(true),
70
+ consume: z.boolean().default(true),
71
+ synchronize: z.boolean().default(true),
72
+ })
73
+ .optional(),
74
+ })
75
+ .parse(options);
76
+
77
+ this.sharded = options.shardCount ? true : false;
78
+ this.token = options.token as string;
79
+
80
+ this.settings.guildId = typeof this.settings.guildId == 'string' ? [this.settings.guildId] : this.settings.guildId;
81
+ this.settings.owners = typeof this.settings.owners == 'string' ? [this.settings.owners] : this.settings.owners;
82
+
83
+ this.premium = this.settings.premium || {
84
+ owners: true,
85
+ consume: true,
86
+ synchronize: true,
87
+ };
88
+
89
+ delete this.settings.premium;
90
+
91
+ this.monitisation = { skus: [] };
92
+
93
+ this.stats = {
94
+ onlineSince: Number(new Date()),
95
+ guildCount: null,
96
+ userCount: null,
97
+ shardCount: null,
98
+ voteCount: null,
99
+ shard: null,
100
+ };
101
+
102
+ this.cache = { messages: new Collection(), slash: new Collection() };
103
+
104
+ this.handler = {
105
+ message: { directory: null },
106
+ slash: { directory: null },
107
+ };
108
+
109
+ this.commands = { message: new Collection(), slash: new Collection() };
110
+
111
+ this.events = new Collection();
112
+
113
+ if (this.sharded) this.cluster = new ClusterClient(this as unknown as DjsDiscordClient);
114
+
115
+ this.modules = { eventHandler: new EventHandler(this), commandHandler: new CommandHandler(this) };
116
+ }
117
+
118
+ /**
119
+ * Connects the client to Discord and initializes various client statistics and handlers.
120
+ *
121
+ * @returns A promise that resolves when the client successfully logs in, or rejects with an error message if the login fails.
122
+ */
123
+ async connect() {
124
+ new XernerxInfo(`${this.cluster ? `${sharpyy(`Shard ${this.cluster.id}`, 'txCyan')} | ` : ''}Connecting...`);
125
+
126
+ this.on('clientReady', async (client) => {
127
+ this.monitisation.skus = await new XernerxMonitisation(client).sku();
128
+
129
+ /** When the client is sharded */
130
+ if (this.sharded && this.cluster) {
131
+ this.stats.shard = {
132
+ shardId: this.cluster.id,
133
+ onlineSince: Number(new Date()),
134
+ guildCount: null,
135
+ userCount: null,
136
+ };
137
+
138
+ setInterval(async () => {
139
+ if (!this.cluster || !this.stats.shard) return;
140
+
141
+ this.stats.guildCount = (await this.cluster.broadcastEval('this.guilds.cache.size')).reduce((a, b) => a + b, 0);
142
+ this.stats.userCount = (await this.cluster.broadcastEval('this.guilds.cache.map((a) => a.memberCount).reduce((a, b) => a + b, 0)')).reduce((a, b) => a + b, 0);
143
+ this.stats.shardCount = getInfo().TOTAL_SHARDS;
144
+ this.stats.shard.guildCount = client.guilds.cache.size;
145
+ this.stats.voteCount = 0;
146
+ this.stats.shard.userCount = client.guilds.cache.map((a) => a.memberCount).reduce((a, b) => a + b, 0);
147
+ }, 1000);
148
+
149
+ await new Promise((resolve) => setTimeout(resolve, 2000));
150
+
151
+ new XernerxSuccess(
152
+ `${sharpyy(`Shard ${this.cluster.id}`, 'txCyan')} | Signed in as ${sharpyy(client.user?.tag, 'txBlue')}, watching ${sharpyy(String(this.stats.shard?.guildCount?.toLocaleString()), 'txCyan')} guilds and users: ${sharpyy(String(this.stats.shard?.userCount?.toLocaleString()), 'txCyan')}`
153
+ );
154
+ } else {
155
+ /** When the client is standalone */
156
+ setInterval(() => {
157
+ this.stats.guildCount = client.guilds.cache.size;
158
+ this.stats.userCount = client.guilds.cache.map((a) => a.memberCount).reduce((a, b) => a + b, 0);
159
+ this.stats.voteCount = 0;
160
+ this.stats.shardCount = 0;
161
+ }, 1000);
162
+
163
+ await new Promise((resolve) => setTimeout(resolve, 2000));
164
+
165
+ new XernerxSuccess(
166
+ `Signed in as ${sharpyy(client.user?.tag, 'txBlue')}, watching ${sharpyy(String(this.stats.guildCount?.toLocaleString()), 'txCyan')} guilds and users: ${sharpyy(String(this.stats.userCount?.toLocaleString()), 'txCyan')}`
167
+ );
168
+ }
169
+ });
170
+
171
+ return await this.login(this.token).catch((error) => new XernerxError(error.message, 1));
172
+ }
173
+ }