@discordanalytics/discordjs 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.
- package/LICENSE +412 -247
- package/README.md +10 -6
- package/dist/index.cjs +131 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +59 -0
- package/dist/index.d.mts +60 -0
- package/dist/index.mjs +131 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +23 -7
- package/dist/index.d.ts +0 -54
- package/dist/index.js +0 -175
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# DiscordAnalytics for Discord.js
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
|
+
|
|
4
5
|
This package is a wrapper for the Discord Analytics API made for Discord.js. It allows you to track events and send them to the Discord Analytics API.
|
|
5
6
|
|
|
6
7
|
## Installation
|
|
8
|
+
|
|
7
9
|
```bash
|
|
8
10
|
npm install @discordanalytics/discordjs
|
|
9
11
|
# or
|
|
@@ -13,18 +15,20 @@ pnpm add @discordanalytics/discordjs
|
|
|
13
15
|
```
|
|
14
16
|
|
|
15
17
|
## Usage
|
|
16
|
-
|
|
18
|
+
|
|
19
|
+
> **Note:** To use Discord Analytics, you need to have an API key. Check the docs for more informations : https://discordanalytics.xyz/docs/get-started/bot-registration
|
|
17
20
|
|
|
18
21
|
### Example
|
|
22
|
+
|
|
19
23
|
```js
|
|
20
24
|
// Import Discord.js's client and intents
|
|
21
|
-
const { Client, IntentsBitField } = require(
|
|
25
|
+
const { Client, IntentsBitField } = require('discord.js');
|
|
22
26
|
// import discord-analytics
|
|
23
|
-
const { default: DiscordAnalytics } = require(
|
|
27
|
+
const { default: DiscordAnalytics } = require('@discordanalytics/discordjs');
|
|
24
28
|
|
|
25
29
|
// Create Discord client
|
|
26
30
|
const client = new Client({
|
|
27
|
-
intents: [IntentsBitField.Flags.Guilds] // This intent is required
|
|
31
|
+
intents: [IntentsBitField.Flags.Guilds], // This intent is required
|
|
28
32
|
});
|
|
29
33
|
|
|
30
34
|
// Create Discord Analytics instance
|
|
@@ -32,14 +36,14 @@ const client = new Client({
|
|
|
32
36
|
const analytics = new DiscordAnalytics({
|
|
33
37
|
client: client,
|
|
34
38
|
api_key: 'YOUR_API_KEY',
|
|
35
|
-
sharded: false // Set it to true if your bot use shards
|
|
39
|
+
sharded: false, // Set it to true if your bot use shards
|
|
36
40
|
});
|
|
37
41
|
|
|
38
42
|
// start tracking selected events
|
|
39
43
|
|
|
40
44
|
// When Discord client is ready
|
|
41
45
|
client.on('clientReady', async () => {
|
|
42
|
-
console.log(
|
|
46
|
+
console.log('Bot is ready!');
|
|
43
47
|
await analytics.init(); // Initialize the analytics
|
|
44
48
|
analytics.trackEvents(); // Start tracking events
|
|
45
49
|
});
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
let _discordanalytics_core = require("@discordanalytics/core");
|
|
2
|
+
//#region package.json
|
|
3
|
+
var version = "2.9.1";
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/index.ts
|
|
6
|
+
/**
|
|
7
|
+
* @class DiscordAnalytics
|
|
8
|
+
* @description The Discord.js class for the DiscordAnalytics library.
|
|
9
|
+
* @param {AnalyticsOptions} options Configuration options.
|
|
10
|
+
* @property {Client} options.client The Discord.js client to track events for.
|
|
11
|
+
* @property {string} options.api_key The API token for DiscordAnalytics.
|
|
12
|
+
* @property {boolean} options.sharded Whether the Discord.js client is sharded.
|
|
13
|
+
* @property {boolean} options.debug Enable or not the debug mode /!\ MUST BE USED ONLY FOR DEVELOPMENT PURPOSES /!\
|
|
14
|
+
* @example
|
|
15
|
+
* const { default: DiscordAnalytics } = require('discord-analytics/discordjs');
|
|
16
|
+
* const { Client, IntentsBitField } = require('discord.js');
|
|
17
|
+
* const client = new Client({
|
|
18
|
+
* intents: [IntentsBitField.Flags.Guilds]
|
|
19
|
+
* })
|
|
20
|
+
* client.on('ready', () => {
|
|
21
|
+
* const analytics = new DiscordAnalytics({
|
|
22
|
+
* client: client,
|
|
23
|
+
* api_key: 'YOUR_API_TOKEN'
|
|
24
|
+
* });
|
|
25
|
+
* analytics.init();
|
|
26
|
+
* analytics.trackEvents();
|
|
27
|
+
* });
|
|
28
|
+
* client.login('YOUR_BOT_TOKEN');
|
|
29
|
+
* @link https://discordanalytics.xyz/docs/main/get-started/installation/discord.js Check docs for more informations about advanced usages
|
|
30
|
+
*/
|
|
31
|
+
var DiscordAnalytics = class extends _discordanalytics_core.AnalyticsBase {
|
|
32
|
+
constructor(options) {
|
|
33
|
+
super(options.api_key, options.api_url, options.debug);
|
|
34
|
+
this._sharded = false;
|
|
35
|
+
this._isReady = false;
|
|
36
|
+
this._client = options.client;
|
|
37
|
+
this._sharded = options.sharded || false;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Initialize DiscordAnalytics on your bot
|
|
41
|
+
* /!\ Advanced users only
|
|
42
|
+
* /!\ Required to use DiscordAnalytics
|
|
43
|
+
* /!\ Must be used when the client is ready (recommended to use in ready event to prevent problems)
|
|
44
|
+
*/
|
|
45
|
+
async init() {
|
|
46
|
+
if (process.env.NODE_ENV !== "production") return console.log("[DISCORDANALYTICS] NODE_ENV != 'production', initialization skipped");
|
|
47
|
+
if (!this._client.user) return console.log("[DISCORDANALYTICS] client is not ready, initialization skipped");
|
|
48
|
+
this.client_id = this._client.user.id;
|
|
49
|
+
await this.updateBotInformations(this._client.user.username, "discord.js", version, this._client.user.avatar);
|
|
50
|
+
this.debug("[DISCORDANALYTICS] Instance successfully initialized");
|
|
51
|
+
this._isReady = true;
|
|
52
|
+
const fast_mode = process.argv[2] === "--fast";
|
|
53
|
+
this.debug(`[DISCORDANALYTICS] Fast mode is ${fast_mode ? "enabled" : "disabled"}. Stats will be sent every ${fast_mode ? "30s" : "5min"}.`);
|
|
54
|
+
setInterval(async () => {
|
|
55
|
+
this.debug("[DISCORDANALYTICS] Sending stats...");
|
|
56
|
+
const guildCount = this._sharded ? (await this._client.shard?.broadcastEval((c) => c.guilds.cache.size))?.reduce((a, b) => a + b, 0) || 0 : this._client.guilds.cache.size;
|
|
57
|
+
const userCount = this._sharded ? (await this._client.shard?.broadcastEval((c) => c.guilds.cache.reduce((a, g) => a + (g.memberCount || 0), 0)))?.reduce((a, b) => a + b, 0) || 0 : this._client.guilds.cache.reduce((a, g) => a + (g.memberCount || 0), 0);
|
|
58
|
+
const userInstallCount = this._sharded ? (await this._client.shard?.broadcastEval((c) => c.application.approximateUserInstallCount))?.reduce((a, b) => a + b, 0) || 0 : this._client.application.approximateUserInstallCount || 0;
|
|
59
|
+
const guildMembers = !this._sharded ? this._client.guilds.cache.map((guild) => guild.memberCount) : (await this._client.shard?.broadcastEval((c) => c.guilds.cache.map((guild) => guild.memberCount)))?.flat() ?? [];
|
|
60
|
+
const guildLocales = [];
|
|
61
|
+
this._client.guilds.cache.map((current) => guildLocales.find((x) => x.locale === current.preferredLocale) ? ++guildLocales.find((x) => x.locale === current.preferredLocale).number : guildLocales.push({
|
|
62
|
+
locale: current.preferredLocale,
|
|
63
|
+
number: 1
|
|
64
|
+
}));
|
|
65
|
+
this.stats_data.guildLocales = guildLocales;
|
|
66
|
+
await this.sendStats(this._client.user.id, guildCount, userCount, userInstallCount, guildMembers);
|
|
67
|
+
}, fast_mode ? 3e4 : 3e5);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Track interactions
|
|
71
|
+
* /!\ Advanced users only
|
|
72
|
+
* /!\ You need to initialize the class first
|
|
73
|
+
* @param interaction BaseInteraction class and its extensions only
|
|
74
|
+
* @param interactionNameResolver A function that will resolve the name of the interaction
|
|
75
|
+
*/
|
|
76
|
+
async trackInteractions(interaction, interactionNameResolver) {
|
|
77
|
+
this.debug(`[DISCORDANALYTICS] trackInteractions(${interaction.type}) triggered`);
|
|
78
|
+
if (!this._isReady) return this.error(_discordanalytics_core.ErrorCodes.INSTANCE_NOT_INITIALIZED);
|
|
79
|
+
this.updateOrInsert(this.stats_data.interactionsLocales, (x) => x.locale === interaction.locale, (x) => x.number++, () => ({
|
|
80
|
+
locale: interaction.locale,
|
|
81
|
+
number: 1
|
|
82
|
+
}));
|
|
83
|
+
if (interaction.type === _discordanalytics_core.InteractionType.ApplicationCommand) {
|
|
84
|
+
const commandType = interaction.command ? interaction.command.type : _discordanalytics_core.ApplicationCommandType.ChatInputCommand;
|
|
85
|
+
const commandName = interactionNameResolver ? interactionNameResolver(interaction) : interaction.commandName;
|
|
86
|
+
this.updateOrInsert(this.stats_data.interactions, (x) => x.name === commandName && x.type === interaction.type && x.commandType === commandType, (x) => x.number++, () => ({
|
|
87
|
+
name: commandName,
|
|
88
|
+
number: 1,
|
|
89
|
+
type: interaction.type,
|
|
90
|
+
commandType
|
|
91
|
+
}));
|
|
92
|
+
} else if (interaction.type === _discordanalytics_core.InteractionType.MessageComponent || interaction.type === _discordanalytics_core.InteractionType.ModalSubmit) {
|
|
93
|
+
const interactionName = interactionNameResolver ? interactionNameResolver(interaction) : interaction.customId;
|
|
94
|
+
this.updateOrInsert(this.stats_data.interactions, (x) => x.name === interactionName && x.type === interaction.type, (x) => x.number++, () => ({
|
|
95
|
+
name: interactionName,
|
|
96
|
+
number: 1,
|
|
97
|
+
type: interaction.type
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
this.updateOrInsert(this.stats_data.guilds, (x) => x.guildId === (interaction.guild ? interaction.guild.id : "dm"), (x) => x.interactions++, () => ({
|
|
101
|
+
guildId: interaction.guild ? interaction.guild.id : "dm",
|
|
102
|
+
name: interaction.guild ? interaction.guild.name : "DM",
|
|
103
|
+
icon: interaction.guild && interaction.guild.icon,
|
|
104
|
+
interactions: 1,
|
|
105
|
+
members: interaction.guild ? interaction.guild.memberCount : 0
|
|
106
|
+
}));
|
|
107
|
+
const oneWeekAgo = /* @__PURE__ */ new Date();
|
|
108
|
+
oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);
|
|
109
|
+
if (!interaction.inGuild() || !interaction.guild) ++this.stats_data.usersType.privateMessage;
|
|
110
|
+
else if (interaction.member && interaction.memberPermissions.has(8n) || interaction.memberPermissions.has(32n)) ++this.stats_data.usersType.admin;
|
|
111
|
+
else if (interaction.member && interaction.memberPermissions.has(8192n) || interaction.memberPermissions.has(2n) || interaction.memberPermissions.has(4n) || interaction.memberPermissions.has(4194304n) || interaction.memberPermissions.has(8388608n) || interaction.memberPermissions.has(16777216n) || interaction.memberPermissions.has(1099511627776n)) ++this.stats_data.usersType.moderator;
|
|
112
|
+
else if (interaction.member && interaction.member.joinedAt && interaction.member.joinedAt > oneWeekAgo) ++this.stats_data.usersType.newMember;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Let DiscordAnalytics declare the events necessary for its operation.
|
|
116
|
+
* /!\ Not recommended for big bots
|
|
117
|
+
* /!\ Not compatible with other functions
|
|
118
|
+
* @param interactionNameResolver A function that will resolve the name of the interaction
|
|
119
|
+
*/
|
|
120
|
+
trackEvents(interactionNameResolver) {
|
|
121
|
+
this.debug("[DISCORDANALYTICS] trackEvents() triggered");
|
|
122
|
+
if (!this._isReady) return this.error(_discordanalytics_core.ErrorCodes.INSTANCE_NOT_INITIALIZED);
|
|
123
|
+
this._client.on("interactionCreate", async (interaction) => await this.trackInteractions(interaction, interactionNameResolver));
|
|
124
|
+
this._client.on("guildCreate", () => this.trackGuilds("create"));
|
|
125
|
+
this._client.on("guildDelete", () => this.trackGuilds("delete"));
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
//#endregion
|
|
129
|
+
module.exports = DiscordAnalytics;
|
|
130
|
+
|
|
131
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["AnalyticsBase","npmPackageData.version","ErrorCodes","InteractionType","ApplicationCommandType"],"sources":["../package.json","../src/index.ts"],"sourcesContent":["","import {\n AnalyticsBase,\n ApplicationCommandType,\n AnalyticsOptions,\n ErrorCodes,\n InteractionType,\n LocaleData,\n Locale,\n InteractionData,\n GuildData,\n} from '@discordanalytics/core';\nimport type { CacheType, Client, GuildMember, Interaction } from 'discord.js';\nimport npmPackageData from '../package.json';\n\n/**\n * @class DiscordAnalytics\n * @description The Discord.js class for the DiscordAnalytics library.\n * @param {AnalyticsOptions} options Configuration options.\n * @property {Client} options.client The Discord.js client to track events for.\n * @property {string} options.api_key The API token for DiscordAnalytics.\n * @property {boolean} options.sharded Whether the Discord.js client is sharded.\n * @property {boolean} options.debug Enable or not the debug mode /!\\ MUST BE USED ONLY FOR DEVELOPMENT PURPOSES /!\\\n * @example\n * const { default: DiscordAnalytics } = require('discord-analytics/discordjs');\n * const { Client, IntentsBitField } = require('discord.js');\n * const client = new Client({\n * intents: [IntentsBitField.Flags.Guilds]\n * })\n * client.on('ready', () => {\n * const analytics = new DiscordAnalytics({\n * client: client,\n * api_key: 'YOUR_API_TOKEN'\n * });\n * analytics.init();\n * analytics.trackEvents();\n * });\n * client.login('YOUR_BOT_TOKEN');\n * @link https://discordanalytics.xyz/docs/main/get-started/installation/discord.js Check docs for more informations about advanced usages\n */\nexport default class DiscordAnalytics extends AnalyticsBase {\n private readonly _client: Client;\n private readonly _sharded: boolean = false;\n private _isReady: boolean = false;\n\n constructor(options: AnalyticsOptions<Client>) {\n super(options.api_key, options.api_url, options.debug);\n this._client = options.client;\n this._sharded = options.sharded || false;\n }\n\n /**\n * Initialize DiscordAnalytics on your bot\n * /!\\ Advanced users only\n * /!\\ Required to use DiscordAnalytics\n * /!\\ Must be used when the client is ready (recommended to use in ready event to prevent problems)\n */\n public async init(): Promise<void> {\n if (process.env.NODE_ENV !== 'production')\n return console.log(\"[DISCORDANALYTICS] NODE_ENV != 'production', initialization skipped\");\n\n if (!this._client.user)\n return console.log('[DISCORDANALYTICS] client is not ready, initialization skipped');\n\n this.client_id = this._client.user.id;\n\n await this.updateBotInformations(\n this._client.user.username,\n 'discord.js',\n npmPackageData.version,\n this._client.user.avatar,\n );\n\n this.debug('[DISCORDANALYTICS] Instance successfully initialized');\n this._isReady = true;\n\n const fast_mode = process.argv[2] === '--fast';\n this.debug(\n `[DISCORDANALYTICS] Fast mode is ${fast_mode ? 'enabled' : 'disabled'}. Stats will be sent every ${fast_mode ? '30s' : '5min'}.`,\n );\n\n setInterval(\n async () => {\n this.debug('[DISCORDANALYTICS] Sending stats...');\n\n const guildCount = this._sharded\n ? (await this._client.shard?.broadcastEval((c) => c.guilds.cache.size))?.reduce(\n (a: number, b: number) => a + b,\n 0,\n ) || 0\n : this._client.guilds.cache.size;\n\n const userCount = this._sharded\n ? (\n await this._client.shard?.broadcastEval((c) =>\n c.guilds.cache.reduce((a: number, g) => a + (g.memberCount || 0), 0),\n )\n )?.reduce((a: number, b: number) => a + b, 0) || 0\n : this._client.guilds.cache.reduce((a: number, g) => a + (g.memberCount || 0), 0);\n\n const userInstallCount = this._sharded\n ? (\n await this._client.shard?.broadcastEval(\n (c) => c.application!.approximateUserInstallCount,\n )\n )?.reduce((a, b) => a! + b!, 0) || 0\n : this._client.application!.approximateUserInstallCount || 0;\n\n const guildMembers: number[] = !this._sharded\n ? this._client.guilds.cache.map((guild) => guild.memberCount)\n : ((\n await this._client.shard?.broadcastEval((c) =>\n c.guilds.cache.map((guild) => guild.memberCount),\n )\n )?.flat() ?? []);\n\n const guildLocales: LocaleData[] = [];\n this._client.guilds.cache.map((current) =>\n guildLocales.find((x) => x.locale === current.preferredLocale)\n ? ++guildLocales.find((x) => x.locale === current.preferredLocale)!.number\n : guildLocales.push({ locale: current.preferredLocale as Locale, number: 1 }),\n );\n\n this.stats_data.guildLocales = guildLocales;\n\n await this.sendStats(\n this._client.user!.id,\n guildCount,\n userCount,\n userInstallCount,\n guildMembers,\n );\n },\n fast_mode ? 30000 : 300000,\n );\n }\n\n /**\n * Track interactions\n * /!\\ Advanced users only\n * /!\\ You need to initialize the class first\n * @param interaction BaseInteraction class and its extensions only\n * @param interactionNameResolver A function that will resolve the name of the interaction\n */\n public async trackInteractions(\n interaction: Interaction<CacheType>,\n interactionNameResolver?: (interaction: Interaction<CacheType>) => string,\n ): Promise<void> {\n this.debug(`[DISCORDANALYTICS] trackInteractions(${interaction.type}) triggered`);\n if (!this._isReady) return this.error(ErrorCodes.INSTANCE_NOT_INITIALIZED);\n\n this.updateOrInsert(\n this.stats_data.interactionsLocales,\n (x) => x.locale === interaction.locale,\n (x) => x.number++,\n (): LocaleData => ({ locale: interaction.locale as Locale, number: 1 }),\n );\n\n if (interaction.type === InteractionType.ApplicationCommand) {\n const commandType = interaction.command\n ? interaction.command.type\n : ApplicationCommandType.ChatInputCommand;\n const commandName = interactionNameResolver\n ? interactionNameResolver(interaction)\n : interaction.commandName;\n this.updateOrInsert(\n this.stats_data.interactions,\n (x) =>\n x.name === commandName && x.type === interaction.type && x.commandType === commandType,\n (x) => x.number++,\n (): InteractionData => ({\n name: commandName,\n number: 1,\n type: interaction.type,\n commandType: commandType as ApplicationCommandType,\n }),\n );\n } else if (\n interaction.type === InteractionType.MessageComponent ||\n interaction.type === InteractionType.ModalSubmit\n ) {\n const interactionName = interactionNameResolver\n ? interactionNameResolver(interaction)\n : interaction.customId;\n this.updateOrInsert(\n this.stats_data.interactions,\n (x) => x.name === interactionName && x.type === interaction.type,\n (x) => x.number++,\n (): InteractionData => ({\n name: interactionName,\n number: 1,\n type: interaction.type,\n }),\n );\n }\n\n this.updateOrInsert(\n this.stats_data.guilds,\n (x) => x.guildId === (interaction.guild ? interaction.guild.id : 'dm'),\n (x) => x.interactions++,\n (): GuildData => ({\n guildId: interaction.guild ? interaction.guild.id : 'dm',\n name: interaction.guild ? interaction.guild.name : 'DM',\n icon: interaction.guild && interaction.guild.icon,\n interactions: 1,\n members: interaction.guild ? interaction.guild.memberCount : 0,\n }),\n );\n\n const oneWeekAgo = new Date();\n oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);\n\n if (!interaction.inGuild() || !interaction.guild) ++this.stats_data.usersType.privateMessage;\n else if (\n (interaction.member && interaction.memberPermissions.has(8n)) ||\n interaction.memberPermissions.has(32n)\n )\n ++this.stats_data.usersType.admin;\n else if (\n (interaction.member && interaction.memberPermissions.has(8192n)) ||\n interaction.memberPermissions.has(2n) ||\n interaction.memberPermissions.has(4n) ||\n interaction.memberPermissions.has(4194304n) ||\n interaction.memberPermissions.has(8388608n) ||\n interaction.memberPermissions.has(16777216n) ||\n interaction.memberPermissions.has(1099511627776n)\n )\n ++this.stats_data.usersType.moderator;\n else if (\n interaction.member &&\n (interaction.member as GuildMember).joinedAt &&\n (interaction.member as GuildMember).joinedAt! > oneWeekAgo\n )\n ++this.stats_data.usersType.newMember;\n }\n\n /**\n * Let DiscordAnalytics declare the events necessary for its operation.\n * /!\\ Not recommended for big bots\n * /!\\ Not compatible with other functions\n * @param interactionNameResolver A function that will resolve the name of the interaction\n */\n public trackEvents(\n interactionNameResolver?: (interaction: Interaction<CacheType>) => string,\n ): void {\n this.debug('[DISCORDANALYTICS] trackEvents() triggered');\n if (!this._isReady) return this.error(ErrorCodes.INSTANCE_NOT_INITIALIZED);\n\n this._client.on(\n 'interactionCreate',\n async (interaction) => await this.trackInteractions(interaction, interactionNameResolver),\n );\n this._client.on('guildCreate', () => this.trackGuilds('create'));\n this._client.on('guildDelete', () => this.trackGuilds('delete'));\n }\n}\n"],"mappings":"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"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { AnalyticsBase, AnalyticsOptions } from "@discordanalytics/core";
|
|
2
|
+
import { CacheType, Client, Interaction } from "discord.js";
|
|
3
|
+
|
|
4
|
+
//#region src/index.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* @class DiscordAnalytics
|
|
7
|
+
* @description The Discord.js class for the DiscordAnalytics library.
|
|
8
|
+
* @param {AnalyticsOptions} options Configuration options.
|
|
9
|
+
* @property {Client} options.client The Discord.js client to track events for.
|
|
10
|
+
* @property {string} options.api_key The API token for DiscordAnalytics.
|
|
11
|
+
* @property {boolean} options.sharded Whether the Discord.js client is sharded.
|
|
12
|
+
* @property {boolean} options.debug Enable or not the debug mode /!\ MUST BE USED ONLY FOR DEVELOPMENT PURPOSES /!\
|
|
13
|
+
* @example
|
|
14
|
+
* const { default: DiscordAnalytics } = require('discord-analytics/discordjs');
|
|
15
|
+
* const { Client, IntentsBitField } = require('discord.js');
|
|
16
|
+
* const client = new Client({
|
|
17
|
+
* intents: [IntentsBitField.Flags.Guilds]
|
|
18
|
+
* })
|
|
19
|
+
* client.on('ready', () => {
|
|
20
|
+
* const analytics = new DiscordAnalytics({
|
|
21
|
+
* client: client,
|
|
22
|
+
* api_key: 'YOUR_API_TOKEN'
|
|
23
|
+
* });
|
|
24
|
+
* analytics.init();
|
|
25
|
+
* analytics.trackEvents();
|
|
26
|
+
* });
|
|
27
|
+
* client.login('YOUR_BOT_TOKEN');
|
|
28
|
+
* @link https://discordanalytics.xyz/docs/main/get-started/installation/discord.js Check docs for more informations about advanced usages
|
|
29
|
+
*/
|
|
30
|
+
declare class DiscordAnalytics extends AnalyticsBase {
|
|
31
|
+
private readonly _client;
|
|
32
|
+
private readonly _sharded;
|
|
33
|
+
private _isReady;
|
|
34
|
+
constructor(options: AnalyticsOptions<Client>);
|
|
35
|
+
/**
|
|
36
|
+
* Initialize DiscordAnalytics on your bot
|
|
37
|
+
* /!\ Advanced users only
|
|
38
|
+
* /!\ Required to use DiscordAnalytics
|
|
39
|
+
* /!\ Must be used when the client is ready (recommended to use in ready event to prevent problems)
|
|
40
|
+
*/
|
|
41
|
+
init(): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Track interactions
|
|
44
|
+
* /!\ Advanced users only
|
|
45
|
+
* /!\ You need to initialize the class first
|
|
46
|
+
* @param interaction BaseInteraction class and its extensions only
|
|
47
|
+
* @param interactionNameResolver A function that will resolve the name of the interaction
|
|
48
|
+
*/
|
|
49
|
+
trackInteractions(interaction: Interaction<CacheType>, interactionNameResolver?: (interaction: Interaction<CacheType>) => string): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Let DiscordAnalytics declare the events necessary for its operation.
|
|
52
|
+
* /!\ Not recommended for big bots
|
|
53
|
+
* /!\ Not compatible with other functions
|
|
54
|
+
* @param interactionNameResolver A function that will resolve the name of the interaction
|
|
55
|
+
*/
|
|
56
|
+
trackEvents(interactionNameResolver?: (interaction: Interaction<CacheType>) => string): void;
|
|
57
|
+
}
|
|
58
|
+
export = DiscordAnalytics;
|
|
59
|
+
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { AnalyticsBase, AnalyticsOptions } from "@discordanalytics/core";
|
|
2
|
+
import { CacheType, Client, Interaction } from "discord.js";
|
|
3
|
+
|
|
4
|
+
//#region src/index.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* @class DiscordAnalytics
|
|
7
|
+
* @description The Discord.js class for the DiscordAnalytics library.
|
|
8
|
+
* @param {AnalyticsOptions} options Configuration options.
|
|
9
|
+
* @property {Client} options.client The Discord.js client to track events for.
|
|
10
|
+
* @property {string} options.api_key The API token for DiscordAnalytics.
|
|
11
|
+
* @property {boolean} options.sharded Whether the Discord.js client is sharded.
|
|
12
|
+
* @property {boolean} options.debug Enable or not the debug mode /!\ MUST BE USED ONLY FOR DEVELOPMENT PURPOSES /!\
|
|
13
|
+
* @example
|
|
14
|
+
* const { default: DiscordAnalytics } = require('discord-analytics/discordjs');
|
|
15
|
+
* const { Client, IntentsBitField } = require('discord.js');
|
|
16
|
+
* const client = new Client({
|
|
17
|
+
* intents: [IntentsBitField.Flags.Guilds]
|
|
18
|
+
* })
|
|
19
|
+
* client.on('ready', () => {
|
|
20
|
+
* const analytics = new DiscordAnalytics({
|
|
21
|
+
* client: client,
|
|
22
|
+
* api_key: 'YOUR_API_TOKEN'
|
|
23
|
+
* });
|
|
24
|
+
* analytics.init();
|
|
25
|
+
* analytics.trackEvents();
|
|
26
|
+
* });
|
|
27
|
+
* client.login('YOUR_BOT_TOKEN');
|
|
28
|
+
* @link https://discordanalytics.xyz/docs/main/get-started/installation/discord.js Check docs for more informations about advanced usages
|
|
29
|
+
*/
|
|
30
|
+
declare class DiscordAnalytics extends AnalyticsBase {
|
|
31
|
+
private readonly _client;
|
|
32
|
+
private readonly _sharded;
|
|
33
|
+
private _isReady;
|
|
34
|
+
constructor(options: AnalyticsOptions<Client>);
|
|
35
|
+
/**
|
|
36
|
+
* Initialize DiscordAnalytics on your bot
|
|
37
|
+
* /!\ Advanced users only
|
|
38
|
+
* /!\ Required to use DiscordAnalytics
|
|
39
|
+
* /!\ Must be used when the client is ready (recommended to use in ready event to prevent problems)
|
|
40
|
+
*/
|
|
41
|
+
init(): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Track interactions
|
|
44
|
+
* /!\ Advanced users only
|
|
45
|
+
* /!\ You need to initialize the class first
|
|
46
|
+
* @param interaction BaseInteraction class and its extensions only
|
|
47
|
+
* @param interactionNameResolver A function that will resolve the name of the interaction
|
|
48
|
+
*/
|
|
49
|
+
trackInteractions(interaction: Interaction<CacheType>, interactionNameResolver?: (interaction: Interaction<CacheType>) => string): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Let DiscordAnalytics declare the events necessary for its operation.
|
|
52
|
+
* /!\ Not recommended for big bots
|
|
53
|
+
* /!\ Not compatible with other functions
|
|
54
|
+
* @param interactionNameResolver A function that will resolve the name of the interaction
|
|
55
|
+
*/
|
|
56
|
+
trackEvents(interactionNameResolver?: (interaction: Interaction<CacheType>) => string): void;
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
export { DiscordAnalytics as default };
|
|
60
|
+
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { AnalyticsBase, ApplicationCommandType, ErrorCodes, InteractionType } from "@discordanalytics/core";
|
|
2
|
+
//#region package.json
|
|
3
|
+
var version = "2.9.1";
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/index.ts
|
|
6
|
+
/**
|
|
7
|
+
* @class DiscordAnalytics
|
|
8
|
+
* @description The Discord.js class for the DiscordAnalytics library.
|
|
9
|
+
* @param {AnalyticsOptions} options Configuration options.
|
|
10
|
+
* @property {Client} options.client The Discord.js client to track events for.
|
|
11
|
+
* @property {string} options.api_key The API token for DiscordAnalytics.
|
|
12
|
+
* @property {boolean} options.sharded Whether the Discord.js client is sharded.
|
|
13
|
+
* @property {boolean} options.debug Enable or not the debug mode /!\ MUST BE USED ONLY FOR DEVELOPMENT PURPOSES /!\
|
|
14
|
+
* @example
|
|
15
|
+
* const { default: DiscordAnalytics } = require('discord-analytics/discordjs');
|
|
16
|
+
* const { Client, IntentsBitField } = require('discord.js');
|
|
17
|
+
* const client = new Client({
|
|
18
|
+
* intents: [IntentsBitField.Flags.Guilds]
|
|
19
|
+
* })
|
|
20
|
+
* client.on('ready', () => {
|
|
21
|
+
* const analytics = new DiscordAnalytics({
|
|
22
|
+
* client: client,
|
|
23
|
+
* api_key: 'YOUR_API_TOKEN'
|
|
24
|
+
* });
|
|
25
|
+
* analytics.init();
|
|
26
|
+
* analytics.trackEvents();
|
|
27
|
+
* });
|
|
28
|
+
* client.login('YOUR_BOT_TOKEN');
|
|
29
|
+
* @link https://discordanalytics.xyz/docs/main/get-started/installation/discord.js Check docs for more informations about advanced usages
|
|
30
|
+
*/
|
|
31
|
+
var DiscordAnalytics = class extends AnalyticsBase {
|
|
32
|
+
constructor(options) {
|
|
33
|
+
super(options.api_key, options.api_url, options.debug);
|
|
34
|
+
this._sharded = false;
|
|
35
|
+
this._isReady = false;
|
|
36
|
+
this._client = options.client;
|
|
37
|
+
this._sharded = options.sharded || false;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Initialize DiscordAnalytics on your bot
|
|
41
|
+
* /!\ Advanced users only
|
|
42
|
+
* /!\ Required to use DiscordAnalytics
|
|
43
|
+
* /!\ Must be used when the client is ready (recommended to use in ready event to prevent problems)
|
|
44
|
+
*/
|
|
45
|
+
async init() {
|
|
46
|
+
if (process.env.NODE_ENV !== "production") return console.log("[DISCORDANALYTICS] NODE_ENV != 'production', initialization skipped");
|
|
47
|
+
if (!this._client.user) return console.log("[DISCORDANALYTICS] client is not ready, initialization skipped");
|
|
48
|
+
this.client_id = this._client.user.id;
|
|
49
|
+
await this.updateBotInformations(this._client.user.username, "discord.js", version, this._client.user.avatar);
|
|
50
|
+
this.debug("[DISCORDANALYTICS] Instance successfully initialized");
|
|
51
|
+
this._isReady = true;
|
|
52
|
+
const fast_mode = process.argv[2] === "--fast";
|
|
53
|
+
this.debug(`[DISCORDANALYTICS] Fast mode is ${fast_mode ? "enabled" : "disabled"}. Stats will be sent every ${fast_mode ? "30s" : "5min"}.`);
|
|
54
|
+
setInterval(async () => {
|
|
55
|
+
this.debug("[DISCORDANALYTICS] Sending stats...");
|
|
56
|
+
const guildCount = this._sharded ? (await this._client.shard?.broadcastEval((c) => c.guilds.cache.size))?.reduce((a, b) => a + b, 0) || 0 : this._client.guilds.cache.size;
|
|
57
|
+
const userCount = this._sharded ? (await this._client.shard?.broadcastEval((c) => c.guilds.cache.reduce((a, g) => a + (g.memberCount || 0), 0)))?.reduce((a, b) => a + b, 0) || 0 : this._client.guilds.cache.reduce((a, g) => a + (g.memberCount || 0), 0);
|
|
58
|
+
const userInstallCount = this._sharded ? (await this._client.shard?.broadcastEval((c) => c.application.approximateUserInstallCount))?.reduce((a, b) => a + b, 0) || 0 : this._client.application.approximateUserInstallCount || 0;
|
|
59
|
+
const guildMembers = !this._sharded ? this._client.guilds.cache.map((guild) => guild.memberCount) : (await this._client.shard?.broadcastEval((c) => c.guilds.cache.map((guild) => guild.memberCount)))?.flat() ?? [];
|
|
60
|
+
const guildLocales = [];
|
|
61
|
+
this._client.guilds.cache.map((current) => guildLocales.find((x) => x.locale === current.preferredLocale) ? ++guildLocales.find((x) => x.locale === current.preferredLocale).number : guildLocales.push({
|
|
62
|
+
locale: current.preferredLocale,
|
|
63
|
+
number: 1
|
|
64
|
+
}));
|
|
65
|
+
this.stats_data.guildLocales = guildLocales;
|
|
66
|
+
await this.sendStats(this._client.user.id, guildCount, userCount, userInstallCount, guildMembers);
|
|
67
|
+
}, fast_mode ? 3e4 : 3e5);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Track interactions
|
|
71
|
+
* /!\ Advanced users only
|
|
72
|
+
* /!\ You need to initialize the class first
|
|
73
|
+
* @param interaction BaseInteraction class and its extensions only
|
|
74
|
+
* @param interactionNameResolver A function that will resolve the name of the interaction
|
|
75
|
+
*/
|
|
76
|
+
async trackInteractions(interaction, interactionNameResolver) {
|
|
77
|
+
this.debug(`[DISCORDANALYTICS] trackInteractions(${interaction.type}) triggered`);
|
|
78
|
+
if (!this._isReady) return this.error(ErrorCodes.INSTANCE_NOT_INITIALIZED);
|
|
79
|
+
this.updateOrInsert(this.stats_data.interactionsLocales, (x) => x.locale === interaction.locale, (x) => x.number++, () => ({
|
|
80
|
+
locale: interaction.locale,
|
|
81
|
+
number: 1
|
|
82
|
+
}));
|
|
83
|
+
if (interaction.type === InteractionType.ApplicationCommand) {
|
|
84
|
+
const commandType = interaction.command ? interaction.command.type : ApplicationCommandType.ChatInputCommand;
|
|
85
|
+
const commandName = interactionNameResolver ? interactionNameResolver(interaction) : interaction.commandName;
|
|
86
|
+
this.updateOrInsert(this.stats_data.interactions, (x) => x.name === commandName && x.type === interaction.type && x.commandType === commandType, (x) => x.number++, () => ({
|
|
87
|
+
name: commandName,
|
|
88
|
+
number: 1,
|
|
89
|
+
type: interaction.type,
|
|
90
|
+
commandType
|
|
91
|
+
}));
|
|
92
|
+
} else if (interaction.type === InteractionType.MessageComponent || interaction.type === InteractionType.ModalSubmit) {
|
|
93
|
+
const interactionName = interactionNameResolver ? interactionNameResolver(interaction) : interaction.customId;
|
|
94
|
+
this.updateOrInsert(this.stats_data.interactions, (x) => x.name === interactionName && x.type === interaction.type, (x) => x.number++, () => ({
|
|
95
|
+
name: interactionName,
|
|
96
|
+
number: 1,
|
|
97
|
+
type: interaction.type
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
this.updateOrInsert(this.stats_data.guilds, (x) => x.guildId === (interaction.guild ? interaction.guild.id : "dm"), (x) => x.interactions++, () => ({
|
|
101
|
+
guildId: interaction.guild ? interaction.guild.id : "dm",
|
|
102
|
+
name: interaction.guild ? interaction.guild.name : "DM",
|
|
103
|
+
icon: interaction.guild && interaction.guild.icon,
|
|
104
|
+
interactions: 1,
|
|
105
|
+
members: interaction.guild ? interaction.guild.memberCount : 0
|
|
106
|
+
}));
|
|
107
|
+
const oneWeekAgo = /* @__PURE__ */ new Date();
|
|
108
|
+
oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);
|
|
109
|
+
if (!interaction.inGuild() || !interaction.guild) ++this.stats_data.usersType.privateMessage;
|
|
110
|
+
else if (interaction.member && interaction.memberPermissions.has(8n) || interaction.memberPermissions.has(32n)) ++this.stats_data.usersType.admin;
|
|
111
|
+
else if (interaction.member && interaction.memberPermissions.has(8192n) || interaction.memberPermissions.has(2n) || interaction.memberPermissions.has(4n) || interaction.memberPermissions.has(4194304n) || interaction.memberPermissions.has(8388608n) || interaction.memberPermissions.has(16777216n) || interaction.memberPermissions.has(1099511627776n)) ++this.stats_data.usersType.moderator;
|
|
112
|
+
else if (interaction.member && interaction.member.joinedAt && interaction.member.joinedAt > oneWeekAgo) ++this.stats_data.usersType.newMember;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Let DiscordAnalytics declare the events necessary for its operation.
|
|
116
|
+
* /!\ Not recommended for big bots
|
|
117
|
+
* /!\ Not compatible with other functions
|
|
118
|
+
* @param interactionNameResolver A function that will resolve the name of the interaction
|
|
119
|
+
*/
|
|
120
|
+
trackEvents(interactionNameResolver) {
|
|
121
|
+
this.debug("[DISCORDANALYTICS] trackEvents() triggered");
|
|
122
|
+
if (!this._isReady) return this.error(ErrorCodes.INSTANCE_NOT_INITIALIZED);
|
|
123
|
+
this._client.on("interactionCreate", async (interaction) => await this.trackInteractions(interaction, interactionNameResolver));
|
|
124
|
+
this._client.on("guildCreate", () => this.trackGuilds("create"));
|
|
125
|
+
this._client.on("guildDelete", () => this.trackGuilds("delete"));
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
//#endregion
|
|
129
|
+
export { DiscordAnalytics as default };
|
|
130
|
+
|
|
131
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["npmPackageData.version"],"sources":["../package.json","../src/index.ts"],"sourcesContent":["","import {\n AnalyticsBase,\n ApplicationCommandType,\n AnalyticsOptions,\n ErrorCodes,\n InteractionType,\n LocaleData,\n Locale,\n InteractionData,\n GuildData,\n} from '@discordanalytics/core';\nimport type { CacheType, Client, GuildMember, Interaction } from 'discord.js';\nimport npmPackageData from '../package.json';\n\n/**\n * @class DiscordAnalytics\n * @description The Discord.js class for the DiscordAnalytics library.\n * @param {AnalyticsOptions} options Configuration options.\n * @property {Client} options.client The Discord.js client to track events for.\n * @property {string} options.api_key The API token for DiscordAnalytics.\n * @property {boolean} options.sharded Whether the Discord.js client is sharded.\n * @property {boolean} options.debug Enable or not the debug mode /!\\ MUST BE USED ONLY FOR DEVELOPMENT PURPOSES /!\\\n * @example\n * const { default: DiscordAnalytics } = require('discord-analytics/discordjs');\n * const { Client, IntentsBitField } = require('discord.js');\n * const client = new Client({\n * intents: [IntentsBitField.Flags.Guilds]\n * })\n * client.on('ready', () => {\n * const analytics = new DiscordAnalytics({\n * client: client,\n * api_key: 'YOUR_API_TOKEN'\n * });\n * analytics.init();\n * analytics.trackEvents();\n * });\n * client.login('YOUR_BOT_TOKEN');\n * @link https://discordanalytics.xyz/docs/main/get-started/installation/discord.js Check docs for more informations about advanced usages\n */\nexport default class DiscordAnalytics extends AnalyticsBase {\n private readonly _client: Client;\n private readonly _sharded: boolean = false;\n private _isReady: boolean = false;\n\n constructor(options: AnalyticsOptions<Client>) {\n super(options.api_key, options.api_url, options.debug);\n this._client = options.client;\n this._sharded = options.sharded || false;\n }\n\n /**\n * Initialize DiscordAnalytics on your bot\n * /!\\ Advanced users only\n * /!\\ Required to use DiscordAnalytics\n * /!\\ Must be used when the client is ready (recommended to use in ready event to prevent problems)\n */\n public async init(): Promise<void> {\n if (process.env.NODE_ENV !== 'production')\n return console.log(\"[DISCORDANALYTICS] NODE_ENV != 'production', initialization skipped\");\n\n if (!this._client.user)\n return console.log('[DISCORDANALYTICS] client is not ready, initialization skipped');\n\n this.client_id = this._client.user.id;\n\n await this.updateBotInformations(\n this._client.user.username,\n 'discord.js',\n npmPackageData.version,\n this._client.user.avatar,\n );\n\n this.debug('[DISCORDANALYTICS] Instance successfully initialized');\n this._isReady = true;\n\n const fast_mode = process.argv[2] === '--fast';\n this.debug(\n `[DISCORDANALYTICS] Fast mode is ${fast_mode ? 'enabled' : 'disabled'}. Stats will be sent every ${fast_mode ? '30s' : '5min'}.`,\n );\n\n setInterval(\n async () => {\n this.debug('[DISCORDANALYTICS] Sending stats...');\n\n const guildCount = this._sharded\n ? (await this._client.shard?.broadcastEval((c) => c.guilds.cache.size))?.reduce(\n (a: number, b: number) => a + b,\n 0,\n ) || 0\n : this._client.guilds.cache.size;\n\n const userCount = this._sharded\n ? (\n await this._client.shard?.broadcastEval((c) =>\n c.guilds.cache.reduce((a: number, g) => a + (g.memberCount || 0), 0),\n )\n )?.reduce((a: number, b: number) => a + b, 0) || 0\n : this._client.guilds.cache.reduce((a: number, g) => a + (g.memberCount || 0), 0);\n\n const userInstallCount = this._sharded\n ? (\n await this._client.shard?.broadcastEval(\n (c) => c.application!.approximateUserInstallCount,\n )\n )?.reduce((a, b) => a! + b!, 0) || 0\n : this._client.application!.approximateUserInstallCount || 0;\n\n const guildMembers: number[] = !this._sharded\n ? this._client.guilds.cache.map((guild) => guild.memberCount)\n : ((\n await this._client.shard?.broadcastEval((c) =>\n c.guilds.cache.map((guild) => guild.memberCount),\n )\n )?.flat() ?? []);\n\n const guildLocales: LocaleData[] = [];\n this._client.guilds.cache.map((current) =>\n guildLocales.find((x) => x.locale === current.preferredLocale)\n ? ++guildLocales.find((x) => x.locale === current.preferredLocale)!.number\n : guildLocales.push({ locale: current.preferredLocale as Locale, number: 1 }),\n );\n\n this.stats_data.guildLocales = guildLocales;\n\n await this.sendStats(\n this._client.user!.id,\n guildCount,\n userCount,\n userInstallCount,\n guildMembers,\n );\n },\n fast_mode ? 30000 : 300000,\n );\n }\n\n /**\n * Track interactions\n * /!\\ Advanced users only\n * /!\\ You need to initialize the class first\n * @param interaction BaseInteraction class and its extensions only\n * @param interactionNameResolver A function that will resolve the name of the interaction\n */\n public async trackInteractions(\n interaction: Interaction<CacheType>,\n interactionNameResolver?: (interaction: Interaction<CacheType>) => string,\n ): Promise<void> {\n this.debug(`[DISCORDANALYTICS] trackInteractions(${interaction.type}) triggered`);\n if (!this._isReady) return this.error(ErrorCodes.INSTANCE_NOT_INITIALIZED);\n\n this.updateOrInsert(\n this.stats_data.interactionsLocales,\n (x) => x.locale === interaction.locale,\n (x) => x.number++,\n (): LocaleData => ({ locale: interaction.locale as Locale, number: 1 }),\n );\n\n if (interaction.type === InteractionType.ApplicationCommand) {\n const commandType = interaction.command\n ? interaction.command.type\n : ApplicationCommandType.ChatInputCommand;\n const commandName = interactionNameResolver\n ? interactionNameResolver(interaction)\n : interaction.commandName;\n this.updateOrInsert(\n this.stats_data.interactions,\n (x) =>\n x.name === commandName && x.type === interaction.type && x.commandType === commandType,\n (x) => x.number++,\n (): InteractionData => ({\n name: commandName,\n number: 1,\n type: interaction.type,\n commandType: commandType as ApplicationCommandType,\n }),\n );\n } else if (\n interaction.type === InteractionType.MessageComponent ||\n interaction.type === InteractionType.ModalSubmit\n ) {\n const interactionName = interactionNameResolver\n ? interactionNameResolver(interaction)\n : interaction.customId;\n this.updateOrInsert(\n this.stats_data.interactions,\n (x) => x.name === interactionName && x.type === interaction.type,\n (x) => x.number++,\n (): InteractionData => ({\n name: interactionName,\n number: 1,\n type: interaction.type,\n }),\n );\n }\n\n this.updateOrInsert(\n this.stats_data.guilds,\n (x) => x.guildId === (interaction.guild ? interaction.guild.id : 'dm'),\n (x) => x.interactions++,\n (): GuildData => ({\n guildId: interaction.guild ? interaction.guild.id : 'dm',\n name: interaction.guild ? interaction.guild.name : 'DM',\n icon: interaction.guild && interaction.guild.icon,\n interactions: 1,\n members: interaction.guild ? interaction.guild.memberCount : 0,\n }),\n );\n\n const oneWeekAgo = new Date();\n oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);\n\n if (!interaction.inGuild() || !interaction.guild) ++this.stats_data.usersType.privateMessage;\n else if (\n (interaction.member && interaction.memberPermissions.has(8n)) ||\n interaction.memberPermissions.has(32n)\n )\n ++this.stats_data.usersType.admin;\n else if (\n (interaction.member && interaction.memberPermissions.has(8192n)) ||\n interaction.memberPermissions.has(2n) ||\n interaction.memberPermissions.has(4n) ||\n interaction.memberPermissions.has(4194304n) ||\n interaction.memberPermissions.has(8388608n) ||\n interaction.memberPermissions.has(16777216n) ||\n interaction.memberPermissions.has(1099511627776n)\n )\n ++this.stats_data.usersType.moderator;\n else if (\n interaction.member &&\n (interaction.member as GuildMember).joinedAt &&\n (interaction.member as GuildMember).joinedAt! > oneWeekAgo\n )\n ++this.stats_data.usersType.newMember;\n }\n\n /**\n * Let DiscordAnalytics declare the events necessary for its operation.\n * /!\\ Not recommended for big bots\n * /!\\ Not compatible with other functions\n * @param interactionNameResolver A function that will resolve the name of the interaction\n */\n public trackEvents(\n interactionNameResolver?: (interaction: Interaction<CacheType>) => string,\n ): void {\n this.debug('[DISCORDANALYTICS] trackEvents() triggered');\n if (!this._isReady) return this.error(ErrorCodes.INSTANCE_NOT_INITIALIZED);\n\n this._client.on(\n 'interactionCreate',\n async (interaction) => await this.trackInteractions(interaction, interactionNameResolver),\n );\n this._client.on('guildCreate', () => this.trackGuilds('create'));\n this._client.on('guildDelete', () => this.trackGuilds('delete'));\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACuCA,IAAqB,mBAArB,cAA8C,cAAc;CAK1D,YAAY,SAAmC;EAC7C,MAAM,QAAQ,SAAS,QAAQ,SAAS,QAAQ,KAAK;kBAJlB;kBACT;EAI1B,KAAK,UAAU,QAAQ;EACvB,KAAK,WAAW,QAAQ,WAAW;CACrC;;;;;;;CAQA,MAAa,OAAsB;EACjC,IAAI,QAAQ,IAAI,aAAa,cAC3B,OAAO,QAAQ,IAAI,qEAAqE;EAE1F,IAAI,CAAC,KAAK,QAAQ,MAChB,OAAO,QAAQ,IAAI,gEAAgE;EAErF,KAAK,YAAY,KAAK,QAAQ,KAAK;EAEnC,MAAM,KAAK,sBACT,KAAK,QAAQ,KAAK,UAClB,cACAA,SACA,KAAK,QAAQ,KAAK,MACpB;EAEA,KAAK,MAAM,sDAAsD;EACjE,KAAK,WAAW;EAEhB,MAAM,YAAY,QAAQ,KAAK,OAAO;EACtC,KAAK,MACH,mCAAmC,YAAY,YAAY,WAAW,6BAA6B,YAAY,QAAQ,OAAO,EAChI;EAEA,YACE,YAAY;GACV,KAAK,MAAM,qCAAqC;GAEhD,MAAM,aAAa,KAAK,YACnB,MAAM,KAAK,QAAQ,OAAO,eAAe,MAAM,EAAE,OAAO,MAAM,IAAI,IAAI,QACpE,GAAW,MAAc,IAAI,GAC9B,CACF,KAAK,IACL,KAAK,QAAQ,OAAO,MAAM;GAE9B,MAAM,YAAY,KAAK,YAEjB,MAAM,KAAK,QAAQ,OAAO,eAAe,MACvC,EAAE,OAAO,MAAM,QAAQ,GAAW,MAAM,KAAK,EAAE,eAAe,IAAI,CAAC,CACrE,IACC,QAAQ,GAAW,MAAc,IAAI,GAAG,CAAC,KAAK,IACjD,KAAK,QAAQ,OAAO,MAAM,QAAQ,GAAW,MAAM,KAAK,EAAE,eAAe,IAAI,CAAC;GAElF,MAAM,mBAAmB,KAAK,YAExB,MAAM,KAAK,QAAQ,OAAO,eACvB,MAAM,EAAE,YAAa,2BACxB,IACC,QAAQ,GAAG,MAAM,IAAK,GAAI,CAAC,KAAK,IACnC,KAAK,QAAQ,YAAa,+BAA+B;GAE7D,MAAM,eAAyB,CAAC,KAAK,WACjC,KAAK,QAAQ,OAAO,MAAM,KAAK,UAAU,MAAM,WAAW,KAExD,MAAM,KAAK,QAAQ,OAAO,eAAe,MACvC,EAAE,OAAO,MAAM,KAAK,UAAU,MAAM,WAAW,CACjD,IACC,KAAK,KAAK,CAAC;GAElB,MAAM,eAA6B,CAAC;GACpC,KAAK,QAAQ,OAAO,MAAM,KAAK,YAC7B,aAAa,MAAM,MAAM,EAAE,WAAW,QAAQ,eAAe,IACzD,EAAE,aAAa,MAAM,MAAM,EAAE,WAAW,QAAQ,eAAe,EAAG,SAClE,aAAa,KAAK;IAAE,QAAQ,QAAQ;IAA2B,QAAQ;GAAE,CAAC,CAChF;GAEA,KAAK,WAAW,eAAe;GAE/B,MAAM,KAAK,UACT,KAAK,QAAQ,KAAM,IACnB,YACA,WACA,kBACA,YACF;EACF,GACA,YAAY,MAAQ,GACtB;CACF;;;;;;;;CASA,MAAa,kBACX,aACA,yBACe;EACf,KAAK,MAAM,wCAAwC,YAAY,KAAK,YAAY;EAChF,IAAI,CAAC,KAAK,UAAU,OAAO,KAAK,MAAM,WAAW,wBAAwB;EAEzE,KAAK,eACH,KAAK,WAAW,sBACf,MAAM,EAAE,WAAW,YAAY,SAC/B,MAAM,EAAE,iBACU;GAAE,QAAQ,YAAY;GAAkB,QAAQ;EAAE,EACvE;EAEA,IAAI,YAAY,SAAS,gBAAgB,oBAAoB;GAC3D,MAAM,cAAc,YAAY,UAC5B,YAAY,QAAQ,OACpB,uBAAuB;GAC3B,MAAM,cAAc,0BAChB,wBAAwB,WAAW,IACnC,YAAY;GAChB,KAAK,eACH,KAAK,WAAW,eACf,MACC,EAAE,SAAS,eAAe,EAAE,SAAS,YAAY,QAAQ,EAAE,gBAAgB,cAC5E,MAAM,EAAE,iBACe;IACtB,MAAM;IACN,QAAQ;IACR,MAAM,YAAY;IACL;GACf,EACF;EACF,OAAO,IACL,YAAY,SAAS,gBAAgB,oBACrC,YAAY,SAAS,gBAAgB,aACrC;GACA,MAAM,kBAAkB,0BACpB,wBAAwB,WAAW,IACnC,YAAY;GAChB,KAAK,eACH,KAAK,WAAW,eACf,MAAM,EAAE,SAAS,mBAAmB,EAAE,SAAS,YAAY,OAC3D,MAAM,EAAE,iBACe;IACtB,MAAM;IACN,QAAQ;IACR,MAAM,YAAY;GACpB,EACF;EACF;EAEA,KAAK,eACH,KAAK,WAAW,SACf,MAAM,EAAE,aAAa,YAAY,QAAQ,YAAY,MAAM,KAAK,QAChE,MAAM,EAAE,uBACS;GAChB,SAAS,YAAY,QAAQ,YAAY,MAAM,KAAK;GACpD,MAAM,YAAY,QAAQ,YAAY,MAAM,OAAO;GACnD,MAAM,YAAY,SAAS,YAAY,MAAM;GAC7C,cAAc;GACd,SAAS,YAAY,QAAQ,YAAY,MAAM,cAAc;EAC/D,EACF;EAEA,MAAM,6BAAa,IAAI,KAAK;EAC5B,WAAW,QAAQ,WAAW,QAAQ,IAAI,CAAC;EAE3C,IAAI,CAAC,YAAY,QAAQ,KAAK,CAAC,YAAY,OAAO,EAAE,KAAK,WAAW,UAAU;OACzE,IACF,YAAY,UAAU,YAAY,kBAAkB,IAAI,EAAE,KAC3D,YAAY,kBAAkB,IAAI,GAAG,GAErC,EAAE,KAAK,WAAW,UAAU;OACzB,IACF,YAAY,UAAU,YAAY,kBAAkB,IAAI,KAAK,KAC9D,YAAY,kBAAkB,IAAI,EAAE,KACpC,YAAY,kBAAkB,IAAI,EAAE,KACpC,YAAY,kBAAkB,IAAI,QAAQ,KAC1C,YAAY,kBAAkB,IAAI,QAAQ,KAC1C,YAAY,kBAAkB,IAAI,SAAS,KAC3C,YAAY,kBAAkB,IAAI,cAAc,GAEhD,EAAE,KAAK,WAAW,UAAU;OACzB,IACH,YAAY,UACX,YAAY,OAAuB,YACnC,YAAY,OAAuB,WAAY,YAEhD,EAAE,KAAK,WAAW,UAAU;CAChC;;;;;;;CAQA,YACE,yBACM;EACN,KAAK,MAAM,4CAA4C;EACvD,IAAI,CAAC,KAAK,UAAU,OAAO,KAAK,MAAM,WAAW,wBAAwB;EAEzE,KAAK,QAAQ,GACX,qBACA,OAAO,gBAAgB,MAAM,KAAK,kBAAkB,aAAa,uBAAuB,CAC1F;EACA,KAAK,QAAQ,GAAG,qBAAqB,KAAK,YAAY,QAAQ,CAAC;EAC/D,KAAK,QAAQ,GAAG,qBAAqB,KAAK,YAAY,QAAQ,CAAC;CACjE;AACF"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@discordanalytics/discordjs",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.1",
|
|
4
4
|
"description": "Discord.js package for working with Discord Analytics",
|
|
5
|
+
"license": "LGPL-2.1-only",
|
|
5
6
|
"files": [
|
|
6
7
|
"dist"
|
|
7
8
|
],
|
|
8
|
-
"
|
|
9
|
-
"
|
|
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,17 +33,18 @@
|
|
|
18
33
|
"url": "https://github.com/DiscordAnalytics/node-package/issues"
|
|
19
34
|
},
|
|
20
35
|
"dependencies": {
|
|
21
|
-
"@discordanalytics/core": "2.
|
|
36
|
+
"@discordanalytics/core": "2.9.1"
|
|
22
37
|
},
|
|
23
38
|
"devDependencies": {
|
|
24
|
-
"discord.js": "14.
|
|
25
|
-
"
|
|
39
|
+
"discord.js": "14.26.4",
|
|
40
|
+
"tsdown": "0.22.1",
|
|
41
|
+
"typescript": "6.0.3"
|
|
26
42
|
},
|
|
27
43
|
"peerDependencies": {
|
|
28
44
|
"discord.js": "14.x"
|
|
29
45
|
},
|
|
30
46
|
"scripts": {
|
|
31
47
|
"prebuild": "pnpm --filter @discordanalytics/core build",
|
|
32
|
-
"build": "
|
|
48
|
+
"build": "tsdown"
|
|
33
49
|
}
|
|
34
50
|
}
|
package/dist/index.d.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { AnalyticsBase, AnalyticsOptions } from '@discordanalytics/core';
|
|
2
|
-
/**
|
|
3
|
-
* @class DiscordAnalytics
|
|
4
|
-
* @description The Discord.js class for the DiscordAnalytics library.
|
|
5
|
-
* @param {AnalyticsOptions} options Configuration options.
|
|
6
|
-
* @property {any} options.client The Discord.js client to track events for.
|
|
7
|
-
* @property {string} options.api_key The API token for DiscordAnalytics.
|
|
8
|
-
* @property {boolean} options.sharded Whether the Discord.js client is sharded.
|
|
9
|
-
* @property {boolean} options.debug Enable or not the debug mode /!\ MUST BE USED ONLY FOR DEVELOPMENT PURPOSES /!\
|
|
10
|
-
* @example
|
|
11
|
-
* const { default: DiscordAnalytics } = require('discord-analytics/discordjs');
|
|
12
|
-
* const { Client, IntentsBitField } = require('discord.js');
|
|
13
|
-
* const client = new Client({
|
|
14
|
-
* intents: [IntentsBitField.Flags.Guilds]
|
|
15
|
-
* })
|
|
16
|
-
* client.on('ready', () => {
|
|
17
|
-
* const analytics = new DiscordAnalytics({
|
|
18
|
-
* client: client,
|
|
19
|
-
* api_key: 'YOUR_API_TOKEN'
|
|
20
|
-
* });
|
|
21
|
-
* analytics.init();
|
|
22
|
-
* analytics.trackEvents();
|
|
23
|
-
* });
|
|
24
|
-
* client.login('YOUR_BOT_TOKEN');
|
|
25
|
-
* @link https://discordanalytics.xyz/docs/main/get-started/installation/discord.js Check docs for more informations about advanced usages
|
|
26
|
-
*/
|
|
27
|
-
export default class DiscordAnalytics extends AnalyticsBase {
|
|
28
|
-
private readonly _client;
|
|
29
|
-
private readonly _sharded;
|
|
30
|
-
private _isReady;
|
|
31
|
-
constructor(options: AnalyticsOptions);
|
|
32
|
-
/**
|
|
33
|
-
* Initialize DiscordAnalytics on your bot
|
|
34
|
-
* /!\ Advanced users only
|
|
35
|
-
* /!\ Required to use DiscordAnalytics
|
|
36
|
-
* /!\ Must be used when the client is ready (recommended to use in ready event to prevent problems)
|
|
37
|
-
*/
|
|
38
|
-
init(): Promise<void>;
|
|
39
|
-
/**
|
|
40
|
-
* Track interactions
|
|
41
|
-
* /!\ Advanced users only
|
|
42
|
-
* /!\ You need to initialize the class first
|
|
43
|
-
* @param interaction BaseInteraction class and its extensions only
|
|
44
|
-
* @param interactionNameResolver A function that will resolve the name of the interaction
|
|
45
|
-
*/
|
|
46
|
-
trackInteractions(interaction: any, interactionNameResolver?: (interaction: any) => string): Promise<void>;
|
|
47
|
-
/**
|
|
48
|
-
* Let DiscordAnalytics declare the events necessary for its operation.
|
|
49
|
-
* /!\ Not recommended for big bots
|
|
50
|
-
* /!\ Not compatible with other functions
|
|
51
|
-
* @param interactionNameResolver A function that will resolve the name of the interaction
|
|
52
|
-
*/
|
|
53
|
-
trackEvents(interactionNameResolver?: (interaction: any) => string): void;
|
|
54
|
-
}
|