@discordanalytics/core 2.8.2 → 2.9.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.
@@ -0,0 +1,202 @@
1
+ //#region src/types.d.ts
2
+ declare const ApiEndpoints: {
3
+ BASE_URL: string;
4
+ EDIT_SETTINGS_URL: string;
5
+ EDIT_STATS_URL: string;
6
+ EVENT_URL: string;
7
+ };
8
+ declare const ErrorCodes: {
9
+ INVALID_CLIENT_TYPE: string;
10
+ CLIENT_NOT_READY: string;
11
+ INVALID_RESPONSE: string;
12
+ INVALID_API_TOKEN: string;
13
+ DATA_NOT_SENT: string;
14
+ SUSPENDED_BOT: string;
15
+ INSTANCE_NOT_INITIALIZED: string;
16
+ INVALID_EVENTS_COUNT: string;
17
+ INVALID_VALUE_TYPE: string;
18
+ INVALID_EVENT_KEY: string;
19
+ MAX_RETRIES_EXCEEDED: string;
20
+ };
21
+ type Locale = 'id' | 'en-US' | 'en-GB' | 'bg' | 'zh-CN' | 'zh-TW' | 'hr' | 'cs' | 'da' | 'nl' | 'fi' | 'fr' | 'de' | 'el' | 'hi' | 'hu' | 'it' | 'ja' | 'ko' | 'lt' | 'no' | 'pl' | 'pt-BR' | 'ro' | 'ru' | 'es-ES' | 'sv-SE' | 'th' | 'tr' | 'uk' | 'vi';
22
+ declare enum InteractionType {
23
+ Ping = 1,
24
+ ApplicationCommand = 2,
25
+ MessageComponent = 3,
26
+ ApplicationCommandAutocomplete = 4,
27
+ ModalSubmit = 5
28
+ }
29
+ declare enum ApplicationCommandType {
30
+ ChatInputCommand = 1,
31
+ UserCommand = 2,
32
+ MessageCommand = 3
33
+ }
34
+ interface InteractionData {
35
+ commandType?: ApplicationCommandType;
36
+ name: string;
37
+ number: number;
38
+ type: InteractionType;
39
+ }
40
+ interface LocaleData {
41
+ locale: Locale;
42
+ number: number;
43
+ }
44
+ interface GuildData {
45
+ guildId: string;
46
+ icon: string | null;
47
+ interactions: number;
48
+ members: number;
49
+ name: string;
50
+ }
51
+ interface GuildMembersData {
52
+ little: number;
53
+ medium: number;
54
+ big: number;
55
+ huge: number;
56
+ }
57
+ interface UsersTypeData {
58
+ admin: number;
59
+ moderator: number;
60
+ newMember: number;
61
+ other: number;
62
+ privateMessage: number;
63
+ }
64
+ interface StatsData {
65
+ date: string;
66
+ addedGuilds: number;
67
+ customEvents: Record<string, number>;
68
+ guilds: GuildData[];
69
+ guildCount: number;
70
+ guildLocales: LocaleData[];
71
+ guildMembers: GuildMembersData;
72
+ interactions: InteractionData[];
73
+ interactionsLocales: LocaleData[];
74
+ removedGuilds: number;
75
+ userCount: number;
76
+ userInstallCount: number;
77
+ usersType: UsersTypeData;
78
+ }
79
+ interface AnalyticsOptions<TClient = unknown> {
80
+ client: TClient;
81
+ api_key: string;
82
+ api_url?: string;
83
+ sharded?: boolean;
84
+ debug?: boolean;
85
+ }
86
+ type TrackGuildType = 'create' | 'delete';
87
+ //#endregion
88
+ //#region src/index.d.ts
89
+ /**
90
+ * DiscordAnalytics Base Class
91
+ * @class AnalyticsBase
92
+ * @description Base class for DiscordAnalytics
93
+ * @param {string} api_key The API key for DiscordAnalytics
94
+ * @param {boolean} debug Optional flag to enable debug mode /!\ MUST BE USED ONLY FOR DEBUGGING PURPOSES
95
+ * @returns {AnalyticsBase} An instance of the AnalyticsBase class
96
+ * @example
97
+ * const analytics = new AnalyticsBase('YOUR_API_KEY');
98
+ * analytics.sendStats('YOUR_CLIENT_ID', 0, 0);
99
+ */
100
+ declare class AnalyticsBase {
101
+ private readonly _api_key;
102
+ private readonly _headers;
103
+ private readonly debug_mode;
104
+ readonly _api_url: string;
105
+ stats_data: StatsData;
106
+ client_id: string;
107
+ constructor(api_key: string, api_url?: string, debug?: boolean);
108
+ debug(...args: unknown[]): void;
109
+ error(content: unknown, exit?: boolean): void;
110
+ /**
111
+ * Custom events
112
+ * /!\ Advanced users only
113
+ * /!\ You need to initialize the class first
114
+ * @param event_key The event key to track
115
+ * @returns {CustomEvent} The CustomEvent instance
116
+ * @example
117
+ * const event = analytics.events('my_custom_event');
118
+ * event.increment(1);
119
+ * event.decrement(1);
120
+ * event.set(10);
121
+ */
122
+ events(event_key: string): CustomEvent;
123
+ updateOrInsert<T>(array: T[], match: (item: T) => boolean, update: (item: T) => void, insert: () => T): void;
124
+ calculateGuildMembers(guildMembers: number[]): {
125
+ little: number;
126
+ medium: number;
127
+ big: number;
128
+ huge: number;
129
+ };
130
+ /**
131
+ * Track guilds
132
+ * /!\ Advanced users only
133
+ * /!\ You need to initialize the class first
134
+ * @param {TrackGuildType} type 'create' if the event is guildCreate and 'delete' if is guildDelete
135
+ */
136
+ trackGuilds(type: TrackGuildType): void;
137
+ /**
138
+ * API call with retries
139
+ * @param method The HTTP method to use (GET, POST, PUT, DELETE)
140
+ * @param url The URL to call
141
+ * @param body The body to send (optional)
142
+ * @param max_retries The maximum number of retries (default: 5)
143
+ * @param backoff_factor The backoff factor to use (default: 0.5)
144
+ * @returns {Promise<void | Response>} The response from the API
145
+ */
146
+ api_call_with_retries(method: string, endpoint: string, body?: string, max_retries?: number, backoff_factor?: number): Promise<void | Response>;
147
+ updateBotInformations(username: string, framework: string, version: string, avatar: string | null): Promise<void>;
148
+ /**
149
+ * Send stats to the API
150
+ * @param client_id The client ID of the bot
151
+ * @param guild_count The number of guilds the bot is in (default: 0)
152
+ * @param user_count The number of users the bot is in (default: 0)
153
+ * @param user_install_count The number of user installs (default: 0)
154
+ * @param guild_members The number of members in each guild (optional)
155
+ * @returns {Promise<void>} A promise that resolves when the stats are sent
156
+ */
157
+ sendStats(client_id: string, guild_count?: number, user_count?: number, user_install_count?: number, guild_members?: number[]): Promise<void>;
158
+ }
159
+ /**
160
+ * CustomEvent class
161
+ * @class CustomEvent
162
+ * @description Class for custom events
163
+ * @param {AnalyticsBase} analytics The AnalyticsBase instance
164
+ * @param {string} event_key The event key to track
165
+ * @returns {CustomEvent} An instance of the CustomEvent class
166
+ * @example
167
+ * const event = analytics.events('my_custom_event');
168
+ * event.increment(1);
169
+ * event.decrement(1);
170
+ * event.set(10);
171
+ * event.get();
172
+ */
173
+ declare class CustomEvent {
174
+ private readonly _analytics;
175
+ private readonly _event_key;
176
+ private _last_action;
177
+ constructor(analytics: AnalyticsBase, event_key: string);
178
+ private ensure;
179
+ /**
180
+ * Increment the event by a value
181
+ * @param value The value to increment the event by (default: 1)
182
+ */
183
+ increment(value?: number): void;
184
+ /**
185
+ * Decrement the event by a value
186
+ * @param value The value to decrement the event by (default: 1)
187
+ */
188
+ decrement(value?: number): void;
189
+ /**
190
+ * Set the event to a value
191
+ * @param value The value to set the event to
192
+ */
193
+ set(value: number): void;
194
+ /**
195
+ * Get the event value
196
+ * @returns {number} The event value
197
+ */
198
+ get(): number;
199
+ }
200
+ //#endregion
201
+ export { AnalyticsBase, AnalyticsOptions, ApiEndpoints, ApplicationCommandType, CustomEvent, ErrorCodes, GuildData, GuildMembersData, InteractionData, InteractionType, Locale, LocaleData, StatsData, TrackGuildType, UsersTypeData };
202
+ //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs ADDED
@@ -0,0 +1,297 @@
1
+ //#region src/types.ts
2
+ const ApiEndpoints = {
3
+ BASE_URL: "https://discordanalytics.xyz/api",
4
+ EDIT_SETTINGS_URL: `/bots/{id}`,
5
+ EDIT_STATS_URL: `/bots/{id}/stats`,
6
+ EVENT_URL: `/bots/{id}/events/{event}`
7
+ };
8
+ const ErrorCodes = {
9
+ INVALID_CLIENT_TYPE: "Invalid client type, please use a valid client.",
10
+ CLIENT_NOT_READY: "Client is not ready, please start the client first.",
11
+ INVALID_RESPONSE: "Invalid response from the API, please try again later.",
12
+ INVALID_API_TOKEN: "Invalid API token, please get one at " + ApiEndpoints.BASE_URL.split("/api")[0] + " and try again.",
13
+ DATA_NOT_SENT: "Data cannot be sent to the API, I will try again in a minute.",
14
+ SUSPENDED_BOT: "Your bot has been suspended, please check your mailbox for more information.",
15
+ INSTANCE_NOT_INITIALIZED: "It seem that you didn't initialize your instance. Please check the docs for more informations.",
16
+ INVALID_EVENTS_COUNT: "invalid events count",
17
+ INVALID_VALUE_TYPE: "invalid value type",
18
+ INVALID_EVENT_KEY: "invalid event key",
19
+ MAX_RETRIES_EXCEEDED: "Max retries exceeded, please check your network connection or the API status."
20
+ };
21
+ let InteractionType = /* @__PURE__ */ function(InteractionType) {
22
+ InteractionType[InteractionType["Ping"] = 1] = "Ping";
23
+ InteractionType[InteractionType["ApplicationCommand"] = 2] = "ApplicationCommand";
24
+ InteractionType[InteractionType["MessageComponent"] = 3] = "MessageComponent";
25
+ InteractionType[InteractionType["ApplicationCommandAutocomplete"] = 4] = "ApplicationCommandAutocomplete";
26
+ InteractionType[InteractionType["ModalSubmit"] = 5] = "ModalSubmit";
27
+ return InteractionType;
28
+ }({});
29
+ let ApplicationCommandType = /* @__PURE__ */ function(ApplicationCommandType) {
30
+ ApplicationCommandType[ApplicationCommandType["ChatInputCommand"] = 1] = "ChatInputCommand";
31
+ ApplicationCommandType[ApplicationCommandType["UserCommand"] = 2] = "UserCommand";
32
+ ApplicationCommandType[ApplicationCommandType["MessageCommand"] = 3] = "MessageCommand";
33
+ return ApplicationCommandType;
34
+ }({});
35
+ //#endregion
36
+ //#region src/index.ts
37
+ /**
38
+ * DiscordAnalytics Base Class
39
+ * @class AnalyticsBase
40
+ * @description Base class for DiscordAnalytics
41
+ * @param {string} api_key The API key for DiscordAnalytics
42
+ * @param {boolean} debug Optional flag to enable debug mode /!\ MUST BE USED ONLY FOR DEBUGGING PURPOSES
43
+ * @returns {AnalyticsBase} An instance of the AnalyticsBase class
44
+ * @example
45
+ * const analytics = new AnalyticsBase('YOUR_API_KEY');
46
+ * analytics.sendStats('YOUR_CLIENT_ID', 0, 0);
47
+ */
48
+ var AnalyticsBase = class {
49
+ constructor(api_key, api_url = ApiEndpoints.BASE_URL, debug = false) {
50
+ this.debug_mode = false;
51
+ this.stats_data = {
52
+ date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
53
+ addedGuilds: 0,
54
+ customEvents: {},
55
+ guilds: [],
56
+ guildCount: 0,
57
+ guildLocales: [],
58
+ guildMembers: {
59
+ little: 0,
60
+ medium: 0,
61
+ big: 0,
62
+ huge: 0
63
+ },
64
+ interactions: [],
65
+ interactionsLocales: [],
66
+ removedGuilds: 0,
67
+ userCount: 0,
68
+ userInstallCount: 0,
69
+ usersType: {
70
+ admin: 0,
71
+ moderator: 0,
72
+ newMember: 0,
73
+ other: 0,
74
+ privateMessage: 0
75
+ }
76
+ };
77
+ this.client_id = "";
78
+ this._api_key = api_key;
79
+ this._api_url = api_url;
80
+ this.debug_mode = debug;
81
+ this._headers = {
82
+ "Content-Type": "application/json",
83
+ Authorization: `Bot ${this._api_key}`
84
+ };
85
+ }
86
+ debug(...args) {
87
+ if (this.debug_mode) console.debug(...args);
88
+ }
89
+ error(content, exit = false) {
90
+ console.error(content);
91
+ if (exit) process.exit(1);
92
+ }
93
+ /**
94
+ * Custom events
95
+ * /!\ Advanced users only
96
+ * /!\ You need to initialize the class first
97
+ * @param event_key The event key to track
98
+ * @returns {CustomEvent} The CustomEvent instance
99
+ * @example
100
+ * const event = analytics.events('my_custom_event');
101
+ * event.increment(1);
102
+ * event.decrement(1);
103
+ * event.set(10);
104
+ */
105
+ events(event_key) {
106
+ this.debug(`[DISCORDANALYTICS] Getting event ${event_key}`);
107
+ if (typeof event_key !== "string") throw new Error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_VALUE_TYPE}`);
108
+ return new CustomEvent(this, event_key);
109
+ }
110
+ updateOrInsert(array, match, update, insert) {
111
+ const item = array.find(match);
112
+ if (item) update(item);
113
+ else array.push(insert());
114
+ }
115
+ calculateGuildMembers(guildMembers) {
116
+ return guildMembers.reduce((acc, count) => {
117
+ if (count <= 100) acc.little++;
118
+ else if (count <= 500) acc.medium++;
119
+ else if (count <= 1500) acc.big++;
120
+ else acc.huge++;
121
+ return acc;
122
+ }, {
123
+ little: 0,
124
+ medium: 0,
125
+ big: 0,
126
+ huge: 0
127
+ });
128
+ }
129
+ /**
130
+ * Track guilds
131
+ * /!\ Advanced users only
132
+ * /!\ You need to initialize the class first
133
+ * @param {TrackGuildType} type 'create' if the event is guildCreate and 'delete' if is guildDelete
134
+ */
135
+ trackGuilds(type) {
136
+ this.debug(`[DISCORDANALYTICS] trackGuilds(${type}) triggered`);
137
+ if (type === "create") this.stats_data.addedGuilds++;
138
+ else this.stats_data.removedGuilds++;
139
+ }
140
+ /**
141
+ * API call with retries
142
+ * @param method The HTTP method to use (GET, POST, PUT, DELETE)
143
+ * @param url The URL to call
144
+ * @param body The body to send (optional)
145
+ * @param max_retries The maximum number of retries (default: 5)
146
+ * @param backoff_factor The backoff factor to use (default: 0.5)
147
+ * @returns {Promise<void | Response>} The response from the API
148
+ */
149
+ async api_call_with_retries(method, endpoint, body, max_retries = 5, backoff_factor = .5) {
150
+ let retries = 0;
151
+ let response;
152
+ while (retries < max_retries) try {
153
+ response = await fetch(this._api_url + endpoint, {
154
+ method,
155
+ headers: this._headers,
156
+ body
157
+ });
158
+ if (response.ok) return response;
159
+ else if (response.status === 401) return this.error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_API_TOKEN}`);
160
+ else if (response.status === 423) return this.error(`[DISCORDANALYTICS] ${ErrorCodes.SUSPENDED_BOT}`);
161
+ else if (response.status === 404 && endpoint.includes("events")) return this.error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_EVENT_KEY}`, true);
162
+ else if (response.status !== 200) return this.error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_RESPONSE}`);
163
+ } catch (error) {
164
+ retries++;
165
+ const retry_after = Math.pow(2, retries) * backoff_factor;
166
+ this.error(`[DISCORDANALYTICS] Error: ${error}. Retrying in ${retry_after} seconds...`);
167
+ if (retries >= max_retries) return this.error(`[DISCORDANALYTICS] ${ErrorCodes.MAX_RETRIES_EXCEEDED}`);
168
+ await new Promise((resolve) => setTimeout(resolve, retry_after * 1e3));
169
+ }
170
+ }
171
+ async updateBotInformations(username, framework, version, avatar) {
172
+ const endpoint = ApiEndpoints.EDIT_SETTINGS_URL.replace("{id}", this.client_id);
173
+ const body = JSON.stringify({
174
+ avatar,
175
+ framework,
176
+ username,
177
+ version
178
+ });
179
+ await this.api_call_with_retries("PATCH", endpoint, body);
180
+ }
181
+ /**
182
+ * Send stats to the API
183
+ * @param client_id The client ID of the bot
184
+ * @param guild_count The number of guilds the bot is in (default: 0)
185
+ * @param user_count The number of users the bot is in (default: 0)
186
+ * @param user_install_count The number of user installs (default: 0)
187
+ * @param guild_members The number of members in each guild (optional)
188
+ * @returns {Promise<void>} A promise that resolves when the stats are sent
189
+ */
190
+ async sendStats(client_id, guild_count = 0, user_count = 0, user_install_count = 0, guild_members = []) {
191
+ this.debug("[DISCORDANALYTICS] Sending stats...");
192
+ const endpoint = ApiEndpoints.EDIT_STATS_URL.replace("{id}", client_id);
193
+ const body = JSON.stringify(this.stats_data);
194
+ await this.api_call_with_retries("POST", endpoint, body);
195
+ this.debug("[DISCORDANALYTICS] Stats sent to the API", body);
196
+ this.stats_data = {
197
+ date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
198
+ addedGuilds: 0,
199
+ customEvents: this.stats_data.customEvents,
200
+ guilds: [],
201
+ guildCount: guild_count,
202
+ guildLocales: [],
203
+ guildMembers: this.calculateGuildMembers(guild_members),
204
+ interactions: [],
205
+ interactionsLocales: [],
206
+ removedGuilds: 0,
207
+ userCount: user_count,
208
+ userInstallCount: user_install_count,
209
+ usersType: {
210
+ admin: 0,
211
+ moderator: 0,
212
+ newMember: 0,
213
+ other: 0,
214
+ privateMessage: 0
215
+ }
216
+ };
217
+ }
218
+ };
219
+ /**
220
+ * CustomEvent class
221
+ * @class CustomEvent
222
+ * @description Class for custom events
223
+ * @param {AnalyticsBase} analytics The AnalyticsBase instance
224
+ * @param {string} event_key The event key to track
225
+ * @returns {CustomEvent} An instance of the CustomEvent class
226
+ * @example
227
+ * const event = analytics.events('my_custom_event');
228
+ * event.increment(1);
229
+ * event.decrement(1);
230
+ * event.set(10);
231
+ * event.get();
232
+ */
233
+ var CustomEvent = class {
234
+ constructor(analytics, event_key) {
235
+ this._analytics = analytics;
236
+ this._event_key = event_key;
237
+ this._last_action = "";
238
+ this.ensure();
239
+ }
240
+ async ensure() {
241
+ if (typeof this._analytics.stats_data.customEvents[this._event_key] !== "number" && process.env.NODE_ENV === "production") {
242
+ this._analytics.debug(`[DISCORDANALYTICS] Fetching value for event ${this._event_key}`);
243
+ const endpoint = ApiEndpoints.EVENT_URL.replace("{id}", this._analytics.client_id).replace("{event}", this._event_key);
244
+ const res = await this._analytics.api_call_with_retries("GET", endpoint);
245
+ if (res instanceof Response && this._last_action !== "set") {
246
+ const data = await res.json();
247
+ this._analytics.stats_data.customEvents[this._event_key] = (this._analytics.stats_data.customEvents[this._event_key] || 0) + (data.currentValue || 0);
248
+ }
249
+ this._analytics.debug(`[DISCORDANALYTICS] Value fetched for event ${this._event_key}`);
250
+ }
251
+ }
252
+ /**
253
+ * Increment the event by a value
254
+ * @param value The value to increment the event by (default: 1)
255
+ */
256
+ increment(value = 1) {
257
+ this._analytics.debug(`[DISCORDANALYTICS] Incrementing event ${this._event_key} by ${value}`);
258
+ if (typeof value !== "number") throw new Error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_VALUE_TYPE}`);
259
+ if (value < 0) throw new Error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_EVENTS_COUNT}`);
260
+ this._analytics.stats_data.customEvents[this._event_key] = (this._analytics.stats_data.customEvents[this._event_key] || 0) + value;
261
+ this._last_action = "increment";
262
+ }
263
+ /**
264
+ * Decrement the event by a value
265
+ * @param value The value to decrement the event by (default: 1)
266
+ */
267
+ decrement(value = 1) {
268
+ this._analytics.debug(`[DISCORDANALYTICS] Decrementing event ${this._event_key} by ${value}`);
269
+ if (typeof value !== "number") throw new Error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_VALUE_TYPE}`);
270
+ if (value < 0 || this.get() - value < 0) throw new Error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_EVENTS_COUNT}`);
271
+ this._analytics.stats_data.customEvents[this._event_key] -= value;
272
+ this._last_action = "decrement";
273
+ }
274
+ /**
275
+ * Set the event to a value
276
+ * @param value The value to set the event to
277
+ */
278
+ set(value) {
279
+ this._analytics.debug(`[DISCORDANALYTICS] Setting event ${this._event_key} to ${value}`);
280
+ if (typeof value !== "number") throw new Error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_VALUE_TYPE}`);
281
+ if (value < 0) throw new Error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_EVENTS_COUNT}`);
282
+ this._analytics.stats_data.customEvents[this._event_key] = value;
283
+ this._last_action = "set";
284
+ }
285
+ /**
286
+ * Get the event value
287
+ * @returns {number} The event value
288
+ */
289
+ get() {
290
+ this._analytics.debug(`[DISCORDANALYTICS] Getting event ${this._event_key}`);
291
+ return this._analytics.stats_data.customEvents[this._event_key];
292
+ }
293
+ };
294
+ //#endregion
295
+ export { AnalyticsBase, ApiEndpoints, ApplicationCommandType, CustomEvent, ErrorCodes, InteractionType };
296
+
297
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/types.ts","../src/index.ts"],"sourcesContent":["export const ApiEndpoints = {\n BASE_URL: 'https://discordanalytics.xyz/api',\n EDIT_SETTINGS_URL: `/bots/{id}`,\n EDIT_STATS_URL: `/bots/{id}/stats`,\n EVENT_URL: `/bots/{id}/events/{event}`,\n};\n\nexport const ErrorCodes = {\n INVALID_CLIENT_TYPE: 'Invalid client type, please use a valid client.',\n CLIENT_NOT_READY: 'Client is not ready, please start the client first.',\n INVALID_RESPONSE: 'Invalid response from the API, please try again later.',\n INVALID_API_TOKEN:\n 'Invalid API token, please get one at ' +\n ApiEndpoints.BASE_URL.split('/api')[0] +\n ' and try again.',\n DATA_NOT_SENT: 'Data cannot be sent to the API, I will try again in a minute.',\n SUSPENDED_BOT: 'Your bot has been suspended, please check your mailbox for more information.',\n INSTANCE_NOT_INITIALIZED:\n \"It seem that you didn't initialize your instance. Please check the docs for more informations.\",\n INVALID_EVENTS_COUNT: 'invalid events count',\n INVALID_VALUE_TYPE: 'invalid value type',\n INVALID_EVENT_KEY: 'invalid event key',\n MAX_RETRIES_EXCEEDED:\n 'Max retries exceeded, please check your network connection or the API status.',\n};\n\nexport type Locale =\n | 'id'\n | 'en-US'\n | 'en-GB'\n | 'bg'\n | 'zh-CN'\n | 'zh-TW'\n | 'hr'\n | 'cs'\n | 'da'\n | 'nl'\n | 'fi'\n | 'fr'\n | 'de'\n | 'el'\n | 'hi'\n | 'hu'\n | 'it'\n | 'ja'\n | 'ko'\n | 'lt'\n | 'no'\n | 'pl'\n | 'pt-BR'\n | 'ro'\n | 'ru'\n | 'es-ES'\n | 'sv-SE'\n | 'th'\n | 'tr'\n | 'uk'\n | 'vi';\n\nexport enum InteractionType {\n Ping = 1,\n ApplicationCommand = 2,\n MessageComponent = 3,\n ApplicationCommandAutocomplete = 4,\n ModalSubmit = 5,\n}\n\nexport enum ApplicationCommandType {\n ChatInputCommand = 1,\n UserCommand = 2,\n MessageCommand = 3,\n}\n\nexport interface InteractionData {\n commandType?: ApplicationCommandType;\n name: string;\n number: number;\n type: InteractionType;\n}\n\nexport interface LocaleData {\n locale: Locale;\n number: number;\n}\n\nexport interface GuildData {\n guildId: string;\n icon: string | null;\n interactions: number;\n members: number;\n name: string;\n}\n\nexport interface GuildMembersData {\n little: number;\n medium: number;\n big: number;\n huge: number;\n}\n\nexport interface UsersTypeData {\n admin: number;\n moderator: number;\n newMember: number;\n other: number;\n privateMessage: number;\n}\n\nexport interface StatsData {\n date: string;\n addedGuilds: number;\n customEvents: Record<string, number>;\n guilds: GuildData[];\n guildCount: number;\n guildLocales: LocaleData[];\n guildMembers: GuildMembersData;\n interactions: InteractionData[];\n interactionsLocales: LocaleData[];\n removedGuilds: number;\n userCount: number;\n userInstallCount: number;\n usersType: UsersTypeData;\n}\n\nexport interface AnalyticsOptions<TClient = unknown> {\n client: TClient;\n api_key: string;\n api_url?: string;\n sharded?: boolean;\n debug?: boolean;\n}\n\nexport type TrackGuildType = 'create' | 'delete';\n","import { ApiEndpoints, ErrorCodes, StatsData, TrackGuildType } from './types';\n\n/**\n * DiscordAnalytics Base Class\n * @class AnalyticsBase\n * @description Base class for DiscordAnalytics\n * @param {string} api_key The API key for DiscordAnalytics\n * @param {boolean} debug Optional flag to enable debug mode /!\\ MUST BE USED ONLY FOR DEBUGGING PURPOSES\n * @returns {AnalyticsBase} An instance of the AnalyticsBase class\n * @example\n * const analytics = new AnalyticsBase('YOUR_API_KEY');\n * analytics.sendStats('YOUR_CLIENT_ID', 0, 0);\n */\nexport class AnalyticsBase {\n private readonly _api_key: string;\n private readonly _headers: { 'Content-Type': string; Authorization: string };\n private readonly debug_mode: boolean = false;\n public readonly _api_url: string;\n public stats_data: StatsData = {\n date: new Date().toISOString().slice(0, 10),\n addedGuilds: 0,\n customEvents: {},\n guilds: [],\n guildCount: 0,\n guildLocales: [],\n guildMembers: {\n little: 0,\n medium: 0,\n big: 0,\n huge: 0,\n },\n interactions: [],\n interactionsLocales: [],\n removedGuilds: 0,\n userCount: 0,\n userInstallCount: 0,\n usersType: {\n admin: 0,\n moderator: 0,\n newMember: 0,\n other: 0,\n privateMessage: 0,\n },\n };\n public client_id: string = '';\n\n constructor(api_key: string, api_url: string = ApiEndpoints.BASE_URL, debug: boolean = false) {\n this._api_key = api_key;\n this._api_url = api_url;\n this.debug_mode = debug;\n this._headers = {\n 'Content-Type': 'application/json',\n Authorization: `Bot ${this._api_key}`,\n };\n }\n\n public debug(...args: unknown[]): void {\n if (this.debug_mode) console.debug(...args);\n }\n\n public error(content: unknown, exit: boolean = false): void {\n console.error(content);\n if (exit) process.exit(1);\n }\n\n /**\n * Custom events\n * /!\\ Advanced users only\n * /!\\ You need to initialize the class first\n * @param event_key The event key to track\n * @returns {CustomEvent} The CustomEvent instance\n * @example\n * const event = analytics.events('my_custom_event');\n * event.increment(1);\n * event.decrement(1);\n * event.set(10);\n */\n public events(event_key: string): CustomEvent {\n this.debug(`[DISCORDANALYTICS] Getting event ${event_key}`);\n\n if (typeof event_key !== 'string')\n throw new Error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_VALUE_TYPE}`);\n\n return new CustomEvent(this, event_key);\n }\n\n public updateOrInsert<T>(\n array: T[],\n match: (item: T) => boolean,\n update: (item: T) => void,\n insert: () => T,\n ): void {\n const item = array.find(match);\n if (item) update(item);\n else array.push(insert());\n }\n\n public calculateGuildMembers(guildMembers: number[]): {\n little: number;\n medium: number;\n big: number;\n huge: number;\n } {\n return guildMembers.reduce(\n (acc, count) => {\n if (count <= 100) acc.little++;\n else if (count <= 500) acc.medium++;\n else if (count <= 1500) acc.big++;\n else acc.huge++;\n return acc;\n },\n { little: 0, medium: 0, big: 0, huge: 0 },\n );\n }\n\n /**\n * Track guilds\n * /!\\ Advanced users only\n * /!\\ You need to initialize the class first\n * @param {TrackGuildType} type 'create' if the event is guildCreate and 'delete' if is guildDelete\n */\n public trackGuilds(type: TrackGuildType): void {\n this.debug(`[DISCORDANALYTICS] trackGuilds(${type}) triggered`);\n if (type === 'create') this.stats_data.addedGuilds++;\n else this.stats_data.removedGuilds++;\n }\n\n /**\n * API call with retries\n * @param method The HTTP method to use (GET, POST, PUT, DELETE)\n * @param url The URL to call\n * @param body The body to send (optional)\n * @param max_retries The maximum number of retries (default: 5)\n * @param backoff_factor The backoff factor to use (default: 0.5)\n * @returns {Promise<void | Response>} The response from the API\n */\n public async api_call_with_retries(\n method: string,\n endpoint: string,\n body?: string,\n max_retries: number = 5,\n backoff_factor: number = 0.5,\n ): Promise<void | Response> {\n let retries = 0;\n let response: Response;\n\n while (retries < max_retries) {\n try {\n response = await fetch(this._api_url + endpoint, {\n method,\n headers: this._headers,\n body,\n });\n\n if (response.ok) return response;\n else if (response.status === 401)\n return this.error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_API_TOKEN}`);\n else if (response.status === 423)\n return this.error(`[DISCORDANALYTICS] ${ErrorCodes.SUSPENDED_BOT}`);\n else if (response.status === 404 && endpoint.includes('events'))\n return this.error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_EVENT_KEY}`, true);\n else if (response.status !== 200)\n return this.error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_RESPONSE}`);\n } catch (error) {\n retries++;\n const retry_after = Math.pow(2, retries) * backoff_factor;\n this.error(`[DISCORDANALYTICS] Error: ${error}. Retrying in ${retry_after} seconds...`);\n if (retries >= max_retries)\n return this.error(`[DISCORDANALYTICS] ${ErrorCodes.MAX_RETRIES_EXCEEDED}`);\n await new Promise((resolve) => setTimeout(resolve, retry_after * 1000));\n }\n }\n }\n\n public async updateBotInformations(\n username: string,\n framework: string,\n version: string,\n avatar: string | null,\n ): Promise<void> {\n const endpoint = ApiEndpoints.EDIT_SETTINGS_URL.replace('{id}', this.client_id);\n const body = JSON.stringify({\n avatar,\n framework,\n username,\n version,\n });\n await this.api_call_with_retries('PATCH', endpoint, body);\n }\n\n /**\n * Send stats to the API\n * @param client_id The client ID of the bot\n * @param guild_count The number of guilds the bot is in (default: 0)\n * @param user_count The number of users the bot is in (default: 0)\n * @param user_install_count The number of user installs (default: 0)\n * @param guild_members The number of members in each guild (optional)\n * @returns {Promise<void>} A promise that resolves when the stats are sent\n */\n public async sendStats(\n client_id: string,\n guild_count: number = 0,\n user_count: number = 0,\n user_install_count: number = 0,\n guild_members: number[] = [],\n ): Promise<void> {\n this.debug('[DISCORDANALYTICS] Sending stats...');\n\n const endpoint = ApiEndpoints.EDIT_STATS_URL.replace('{id}', client_id);\n const body = JSON.stringify(this.stats_data);\n\n await this.api_call_with_retries('POST', endpoint, body);\n\n this.debug('[DISCORDANALYTICS] Stats sent to the API', body);\n\n this.stats_data = {\n date: new Date().toISOString().slice(0, 10),\n addedGuilds: 0,\n customEvents: this.stats_data.customEvents,\n guilds: [],\n guildCount: guild_count,\n guildLocales: [],\n guildMembers: this.calculateGuildMembers(guild_members),\n interactions: [],\n interactionsLocales: [],\n removedGuilds: 0,\n userCount: user_count,\n userInstallCount: user_install_count,\n usersType: {\n admin: 0,\n moderator: 0,\n newMember: 0,\n other: 0,\n privateMessage: 0,\n },\n };\n }\n}\n\n/**\n * CustomEvent class\n * @class CustomEvent\n * @description Class for custom events\n * @param {AnalyticsBase} analytics The AnalyticsBase instance\n * @param {string} event_key The event key to track\n * @returns {CustomEvent} An instance of the CustomEvent class\n * @example\n * const event = analytics.events('my_custom_event');\n * event.increment(1);\n * event.decrement(1);\n * event.set(10);\n * event.get();\n */\nexport class CustomEvent {\n private readonly _analytics: AnalyticsBase;\n private readonly _event_key: string;\n private _last_action: string;\n\n constructor(analytics: AnalyticsBase, event_key: string) {\n this._analytics = analytics;\n this._event_key = event_key;\n this._last_action = '';\n\n this.ensure();\n }\n\n private async ensure() {\n if (\n typeof this._analytics.stats_data.customEvents[this._event_key] !== 'number' &&\n process.env.NODE_ENV === 'production'\n ) {\n this._analytics.debug(`[DISCORDANALYTICS] Fetching value for event ${this._event_key}`);\n const endpoint = ApiEndpoints.EVENT_URL.replace('{id}', this._analytics.client_id).replace(\n '{event}',\n this._event_key,\n );\n const res = await this._analytics.api_call_with_retries('GET', endpoint);\n\n if (res instanceof Response && this._last_action !== 'set') {\n const data: { currentValue?: number } = await res.json();\n this._analytics.stats_data.customEvents[this._event_key] =\n (this._analytics.stats_data.customEvents[this._event_key] || 0) +\n (data.currentValue || 0);\n }\n this._analytics.debug(`[DISCORDANALYTICS] Value fetched for event ${this._event_key}`);\n }\n }\n\n /**\n * Increment the event by a value\n * @param value The value to increment the event by (default: 1)\n */\n public increment(value: number = 1): void {\n this._analytics.debug(`[DISCORDANALYTICS] Incrementing event ${this._event_key} by ${value}`);\n\n if (typeof value !== 'number')\n throw new Error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_VALUE_TYPE}`);\n\n if (value < 0) throw new Error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_EVENTS_COUNT}`);\n\n this._analytics.stats_data.customEvents[this._event_key] =\n (this._analytics.stats_data.customEvents[this._event_key] || 0) + value;\n this._last_action = 'increment';\n }\n\n /**\n * Decrement the event by a value\n * @param value The value to decrement the event by (default: 1)\n */\n public decrement(value: number = 1): void {\n this._analytics.debug(`[DISCORDANALYTICS] Decrementing event ${this._event_key} by ${value}`);\n\n if (typeof value !== 'number')\n throw new Error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_VALUE_TYPE}`);\n\n if (value < 0 || this.get() - value < 0)\n throw new Error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_EVENTS_COUNT}`);\n\n this._analytics.stats_data.customEvents[this._event_key] -= value;\n this._last_action = 'decrement';\n }\n\n /**\n * Set the event to a value\n * @param value The value to set the event to\n */\n public set(value: number): void {\n this._analytics.debug(`[DISCORDANALYTICS] Setting event ${this._event_key} to ${value}`);\n\n if (typeof value !== 'number')\n throw new Error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_VALUE_TYPE}`);\n\n if (value < 0) throw new Error(`[DISCORDANALYTICS] ${ErrorCodes.INVALID_EVENTS_COUNT}`);\n\n this._analytics.stats_data.customEvents[this._event_key] = value;\n this._last_action = 'set';\n }\n\n /**\n * Get the event value\n * @returns {number} The event value\n */\n public get(): number {\n this._analytics.debug(`[DISCORDANALYTICS] Getting event ${this._event_key}`);\n\n return this._analytics.stats_data.customEvents[this._event_key];\n }\n}\n\nexport * from './types';\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,12 +1,27 @@
1
1
  {
2
2
  "name": "@discordanalytics/core",
3
- "version": "2.8.2",
3
+ "version": "2.9.1",
4
4
  "description": "Core package to work with Discord Analytics",
5
+ "license": "LGPL-2.1-only",
5
6
  "files": [
6
7
  "dist"
7
8
  ],
8
- "main": "dist/index.js",
9
- "types": "dist/index.d.ts",
9
+ "type": "module",
10
+ "main": "dist/index.cjs",
11
+ "module": "dist/index.mjs",
12
+ "types": "dist/index.d.mts",
13
+ "exports": {
14
+ ".": {
15
+ "import": {
16
+ "types": "./dist/index.d.mts",
17
+ "default": "./dist/index.mjs"
18
+ },
19
+ "require": {
20
+ "types": "./dist/index.d.cts",
21
+ "default": "./dist/index.cjs"
22
+ }
23
+ }
24
+ },
10
25
  "author": "Discord Analytics",
11
26
  "homepage": "https://discordanalytics.xyz",
12
27
  "readme": "README.md",
@@ -18,10 +33,11 @@
18
33
  "url": "https://github.com/DiscordAnalytics/node-package/issues"
19
34
  },
20
35
  "devDependencies": {
21
- "@types/node": "*",
22
- "typescript": "*"
36
+ "@types/node": "22.15.2",
37
+ "tsdown": "0.22.1",
38
+ "typescript": "6.0.3"
23
39
  },
24
40
  "scripts": {
25
- "build": "tsc"
41
+ "build": "tsdown"
26
42
  }
27
43
  }