argus-discord-analytics 0.1.0

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/README.md ADDED
@@ -0,0 +1,173 @@
1
+ # @argus/sdk
2
+
3
+ The all-seeing analytics SDK for Discord bots. Track commands, errors, and custom events with ease.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @argus/sdk
9
+ # or
10
+ yarn add @argus/sdk
11
+ # or
12
+ pnpm add @argus/sdk
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { Argus } from '@argus/sdk';
19
+ import { Client, GatewayIntentBits } from 'discord.js';
20
+
21
+ // Initialize Argus with your API key
22
+ const argus = new Argus({
23
+ apiKey: 'arg_live_your_api_key_here',
24
+ endpoint: 'https://your-app.vercel.app', // Your Argus deployment URL
25
+ debug: process.env.NODE_ENV === 'development',
26
+ });
27
+
28
+ const client = new Client({
29
+ intents: [GatewayIntentBits.Guilds],
30
+ });
31
+
32
+ // Auto-track all interactions
33
+ client.on('interactionCreate', (interaction) => {
34
+ argus.track(interaction);
35
+ });
36
+
37
+ // Track errors
38
+ client.on('error', (error) => {
39
+ argus.trackError(error);
40
+ });
41
+
42
+ // Graceful shutdown
43
+ process.on('SIGINT', async () => {
44
+ await argus.shutdown();
45
+ process.exit(0);
46
+ });
47
+
48
+ client.login(process.env.DISCORD_TOKEN);
49
+ ```
50
+
51
+ ## Configuration
52
+
53
+ ```typescript
54
+ const argus = new Argus({
55
+ // Required: Your Argus API key
56
+ apiKey: 'arg_live_xxxxxxxxxxxx',
57
+
58
+ // Optional: API endpoint (defaults to http://localhost:3000)
59
+ endpoint: 'https://your-app.vercel.app',
60
+
61
+ // Optional: Enable debug logging (default: false)
62
+ debug: true,
63
+
64
+ // Optional: Number of events before auto-flush (default: 10)
65
+ batchSize: 10,
66
+
67
+ // Optional: Flush interval in milliseconds (default: 10000)
68
+ flushInterval: 10000,
69
+
70
+ // Optional: Hash user IDs for privacy (default: true)
71
+ hashUserIds: true,
72
+ });
73
+ ```
74
+
75
+ ## API
76
+
77
+ ### `argus.track(interaction)`
78
+
79
+ Track a Discord.js interaction automatically. Extracts command name, server ID, and user ID.
80
+
81
+ ```typescript
82
+ client.on('interactionCreate', (interaction) => {
83
+ argus.track(interaction);
84
+ });
85
+ ```
86
+
87
+ ### `argus.trackEvent(type, name, options?)`
88
+
89
+ Track a custom event.
90
+
91
+ ```typescript
92
+ argus.trackEvent('command', '/play', {
93
+ serverId: '123456789',
94
+ userId: '987654321',
95
+ metadata: { song: 'Never Gonna Give You Up' },
96
+ });
97
+
98
+ argus.trackEvent('custom', 'playlist_created', {
99
+ serverId: '123456789',
100
+ metadata: { playlistName: 'My Playlist', songCount: 10 },
101
+ });
102
+ ```
103
+
104
+ ### `argus.trackError(error, options?)`
105
+
106
+ Track an error with optional context.
107
+
108
+ ```typescript
109
+ try {
110
+ await someRiskyOperation();
111
+ } catch (error) {
112
+ argus.trackError(error, {
113
+ command: '/play',
114
+ serverId: interaction.guildId,
115
+ userId: interaction.user.id,
116
+ });
117
+ }
118
+ ```
119
+
120
+ ### `argus.flush()`
121
+
122
+ Manually flush all queued events to the server.
123
+
124
+ ```typescript
125
+ await argus.flush();
126
+ ```
127
+
128
+ ### `argus.shutdown()`
129
+
130
+ Gracefully shutdown the Argus instance, flushing any remaining events.
131
+
132
+ ```typescript
133
+ process.on('SIGINT', async () => {
134
+ await argus.shutdown();
135
+ process.exit(0);
136
+ });
137
+ ```
138
+
139
+ ## Privacy
140
+
141
+ By default, Argus hashes user IDs before sending them to the server. This allows you to track unique users without storing their actual Discord IDs.
142
+
143
+ To disable hashing:
144
+
145
+ ```typescript
146
+ const argus = new Argus({
147
+ apiKey: 'your_api_key',
148
+ hashUserIds: false,
149
+ });
150
+ ```
151
+
152
+ ## REST API Alternative
153
+
154
+ If you're not using Node.js, you can send events directly to the API:
155
+
156
+ ```bash
157
+ curl -X POST https://your-app.vercel.app/api/events \
158
+ -H "Authorization: Bearer arg_live_your_api_key" \
159
+ -H "Content-Type: application/json" \
160
+ -d '{
161
+ "events": [{
162
+ "type": "command",
163
+ "name": "/play",
164
+ "serverId": "123456789",
165
+ "userHash": "abc123",
166
+ "timestamp": 1640000000000
167
+ }]
168
+ }'
169
+ ```
170
+
171
+ ## License
172
+
173
+ MIT
@@ -0,0 +1,251 @@
1
+ /**
2
+ * Argus SDK - The all-seeing analytics for Discord bots
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * import { Argus } from '@argus/sdk';
7
+ *
8
+ * const argus = new Argus('arg_live_xxxxxxxxxxxx');
9
+ *
10
+ * // Auto-track all interactions
11
+ * client.on('interactionCreate', (interaction) => {
12
+ * argus.track(interaction);
13
+ * });
14
+ *
15
+ * // Track server joins/leaves
16
+ * client.on('guildCreate', (guild) => {
17
+ * argus.trackServer('join', { serverId: guild.id, memberCount: guild.memberCount });
18
+ * });
19
+ *
20
+ * // Track revenue
21
+ * argus.trackRevenue({ source: 'patreon', amount: 500, tier: 'Premium' });
22
+ * ```
23
+ */
24
+ interface ArgusConfig {
25
+ /** Your Argus API key (starts with arg_live_ or arg_test_) */
26
+ apiKey: string;
27
+ /** API endpoint (defaults to http://localhost:3000) */
28
+ endpoint?: string;
29
+ /** Enable debug logging */
30
+ debug?: boolean;
31
+ /** Batch size before sending (default: 10) */
32
+ batchSize?: number;
33
+ /** Flush interval in ms (default: 10000) */
34
+ flushInterval?: number;
35
+ /** Whether to hash user IDs for privacy (default: true) */
36
+ hashUserIds?: boolean;
37
+ /** Heartbeat interval in ms (default: 30000) */
38
+ heartbeatInterval?: number;
39
+ }
40
+ interface TrackEvent {
41
+ type: 'command' | 'error' | 'custom';
42
+ name: string;
43
+ serverId?: string;
44
+ userId?: string;
45
+ metadata?: Record<string, unknown>;
46
+ timestamp?: number;
47
+ latencyMs?: number;
48
+ }
49
+ interface HeartbeatConfig {
50
+ /** Heartbeat interval in ms (default: 30000) */
51
+ interval?: number;
52
+ /** Include latency measurement */
53
+ measureLatency?: boolean;
54
+ }
55
+ interface ServerEvent {
56
+ type: 'server';
57
+ eventType: 'join' | 'leave';
58
+ serverId: string;
59
+ memberCount?: number;
60
+ timestamp: number;
61
+ }
62
+ interface RevenueEvent {
63
+ type: 'revenue';
64
+ source: string;
65
+ amount: number;
66
+ currency: string;
67
+ userId?: string;
68
+ userHash?: string;
69
+ tier?: string;
70
+ timestamp: number;
71
+ }
72
+ /**
73
+ * Argus - The all-seeing analytics for Discord bots
74
+ */
75
+ declare class Argus {
76
+ private apiKey;
77
+ private endpoint;
78
+ private debug;
79
+ private batchSize;
80
+ private flushInterval;
81
+ private hashUserIds;
82
+ private heartbeatInterval;
83
+ private queue;
84
+ private serverQueue;
85
+ private revenueQueue;
86
+ private flushTimer;
87
+ private heartbeatTimer;
88
+ private botId;
89
+ private isHeartbeatEnabled;
90
+ private commandStartTimes;
91
+ constructor(apiKeyOrConfig: string | ArgusConfig);
92
+ private log;
93
+ private startFlushTimer;
94
+ /**
95
+ * Track a Discord.js interaction automatically
96
+ * Extracts command name, server ID, and user ID from the interaction
97
+ */
98
+ track(interaction: {
99
+ commandName?: string;
100
+ customId?: string;
101
+ guildId?: string | null;
102
+ user?: {
103
+ id: string;
104
+ };
105
+ type?: number;
106
+ }): void;
107
+ /**
108
+ * Track a custom event
109
+ */
110
+ trackEvent(type: 'command' | 'error' | 'custom', name: string, options?: {
111
+ serverId?: string;
112
+ userId?: string;
113
+ metadata?: Record<string, unknown>;
114
+ }): void;
115
+ /**
116
+ * Track an error
117
+ */
118
+ trackError(error: Error | string, options?: {
119
+ command?: string;
120
+ serverId?: string;
121
+ userId?: string;
122
+ metadata?: Record<string, unknown>;
123
+ }): void;
124
+ /**
125
+ * Track server join or leave events
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * // When bot joins a server
130
+ * client.on('guildCreate', (guild) => {
131
+ * argus.trackServer('join', {
132
+ * serverId: guild.id,
133
+ * memberCount: guild.memberCount
134
+ * });
135
+ * });
136
+ *
137
+ * // When bot leaves/is kicked from a server
138
+ * client.on('guildDelete', (guild) => {
139
+ * argus.trackServer('leave', { serverId: guild.id });
140
+ * });
141
+ * ```
142
+ */
143
+ trackServer(eventType: 'join' | 'leave', options: {
144
+ serverId: string;
145
+ memberCount?: number;
146
+ }): void;
147
+ /**
148
+ * Track revenue events from Patreon, Ko-fi, Stripe, or custom sources
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * // Track a Patreon pledge
153
+ * argus.trackRevenue({
154
+ * source: 'patreon',
155
+ * amount: 500, // $5.00 in cents
156
+ * userId: 'discord_user_id', // optional
157
+ * tier: 'Premium'
158
+ * });
159
+ *
160
+ * // Track a Ko-fi donation
161
+ * argus.trackRevenue({
162
+ * source: 'kofi',
163
+ * amount: 300,
164
+ * currency: 'USD'
165
+ * });
166
+ * ```
167
+ */
168
+ trackRevenue(options: {
169
+ source: 'patreon' | 'kofi' | 'stripe' | 'custom' | string;
170
+ amount: number;
171
+ currency?: string;
172
+ userId?: string;
173
+ tier?: string;
174
+ }): void;
175
+ /**
176
+ * Manually flush all queued events
177
+ */
178
+ flush(): Promise<void>;
179
+ private flushCommandEvents;
180
+ private flushServerEvents;
181
+ private flushRevenueEvents;
182
+ /**
183
+ * Set the bot ID for all future events
184
+ */
185
+ setBotId(botId: string): void;
186
+ /**
187
+ * Start sending heartbeat pings to monitor bot uptime
188
+ *
189
+ * @example
190
+ * ```typescript
191
+ * // Start with default 30 second interval
192
+ * argus.startHeartbeat();
193
+ *
194
+ * // Or customize the interval
195
+ * argus.startHeartbeat({ interval: 60000 }); // 1 minute
196
+ * ```
197
+ */
198
+ startHeartbeat(config?: HeartbeatConfig): void;
199
+ /**
200
+ * Stop sending heartbeat pings
201
+ */
202
+ stopHeartbeat(): void;
203
+ /**
204
+ * Send a single heartbeat ping
205
+ */
206
+ private sendHeartbeat;
207
+ /**
208
+ * Start timing a command execution
209
+ * Call this at the beginning of your command handler
210
+ *
211
+ * @example
212
+ * ```typescript
213
+ * client.on('interactionCreate', async (interaction) => {
214
+ * const timerId = argus.startTimer(interaction.id);
215
+ *
216
+ * try {
217
+ * await handleCommand(interaction);
218
+ * } finally {
219
+ * argus.endTimer(timerId, interaction);
220
+ * }
221
+ * });
222
+ * ```
223
+ */
224
+ startTimer(id: string): string;
225
+ /**
226
+ * End timing and track the command with latency
227
+ */
228
+ endTimer(timerId: string, interaction: {
229
+ commandName?: string;
230
+ customId?: string;
231
+ guildId?: string | null;
232
+ user?: {
233
+ id: string;
234
+ };
235
+ type?: number;
236
+ }): void;
237
+ /**
238
+ * Track an event with latency measurement
239
+ */
240
+ trackEventWithLatency(type: 'command' | 'error' | 'custom', name: string, latencyMs: number, options?: {
241
+ serverId?: string;
242
+ userId?: string;
243
+ metadata?: Record<string, unknown>;
244
+ }): void;
245
+ /**
246
+ * Shutdown the Argus instance, flushing any remaining events
247
+ */
248
+ shutdown(): Promise<void>;
249
+ }
250
+
251
+ export { Argus, type ArgusConfig, type HeartbeatConfig, type RevenueEvent, type ServerEvent, type TrackEvent, Argus as default };
@@ -0,0 +1,251 @@
1
+ /**
2
+ * Argus SDK - The all-seeing analytics for Discord bots
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * import { Argus } from '@argus/sdk';
7
+ *
8
+ * const argus = new Argus('arg_live_xxxxxxxxxxxx');
9
+ *
10
+ * // Auto-track all interactions
11
+ * client.on('interactionCreate', (interaction) => {
12
+ * argus.track(interaction);
13
+ * });
14
+ *
15
+ * // Track server joins/leaves
16
+ * client.on('guildCreate', (guild) => {
17
+ * argus.trackServer('join', { serverId: guild.id, memberCount: guild.memberCount });
18
+ * });
19
+ *
20
+ * // Track revenue
21
+ * argus.trackRevenue({ source: 'patreon', amount: 500, tier: 'Premium' });
22
+ * ```
23
+ */
24
+ interface ArgusConfig {
25
+ /** Your Argus API key (starts with arg_live_ or arg_test_) */
26
+ apiKey: string;
27
+ /** API endpoint (defaults to http://localhost:3000) */
28
+ endpoint?: string;
29
+ /** Enable debug logging */
30
+ debug?: boolean;
31
+ /** Batch size before sending (default: 10) */
32
+ batchSize?: number;
33
+ /** Flush interval in ms (default: 10000) */
34
+ flushInterval?: number;
35
+ /** Whether to hash user IDs for privacy (default: true) */
36
+ hashUserIds?: boolean;
37
+ /** Heartbeat interval in ms (default: 30000) */
38
+ heartbeatInterval?: number;
39
+ }
40
+ interface TrackEvent {
41
+ type: 'command' | 'error' | 'custom';
42
+ name: string;
43
+ serverId?: string;
44
+ userId?: string;
45
+ metadata?: Record<string, unknown>;
46
+ timestamp?: number;
47
+ latencyMs?: number;
48
+ }
49
+ interface HeartbeatConfig {
50
+ /** Heartbeat interval in ms (default: 30000) */
51
+ interval?: number;
52
+ /** Include latency measurement */
53
+ measureLatency?: boolean;
54
+ }
55
+ interface ServerEvent {
56
+ type: 'server';
57
+ eventType: 'join' | 'leave';
58
+ serverId: string;
59
+ memberCount?: number;
60
+ timestamp: number;
61
+ }
62
+ interface RevenueEvent {
63
+ type: 'revenue';
64
+ source: string;
65
+ amount: number;
66
+ currency: string;
67
+ userId?: string;
68
+ userHash?: string;
69
+ tier?: string;
70
+ timestamp: number;
71
+ }
72
+ /**
73
+ * Argus - The all-seeing analytics for Discord bots
74
+ */
75
+ declare class Argus {
76
+ private apiKey;
77
+ private endpoint;
78
+ private debug;
79
+ private batchSize;
80
+ private flushInterval;
81
+ private hashUserIds;
82
+ private heartbeatInterval;
83
+ private queue;
84
+ private serverQueue;
85
+ private revenueQueue;
86
+ private flushTimer;
87
+ private heartbeatTimer;
88
+ private botId;
89
+ private isHeartbeatEnabled;
90
+ private commandStartTimes;
91
+ constructor(apiKeyOrConfig: string | ArgusConfig);
92
+ private log;
93
+ private startFlushTimer;
94
+ /**
95
+ * Track a Discord.js interaction automatically
96
+ * Extracts command name, server ID, and user ID from the interaction
97
+ */
98
+ track(interaction: {
99
+ commandName?: string;
100
+ customId?: string;
101
+ guildId?: string | null;
102
+ user?: {
103
+ id: string;
104
+ };
105
+ type?: number;
106
+ }): void;
107
+ /**
108
+ * Track a custom event
109
+ */
110
+ trackEvent(type: 'command' | 'error' | 'custom', name: string, options?: {
111
+ serverId?: string;
112
+ userId?: string;
113
+ metadata?: Record<string, unknown>;
114
+ }): void;
115
+ /**
116
+ * Track an error
117
+ */
118
+ trackError(error: Error | string, options?: {
119
+ command?: string;
120
+ serverId?: string;
121
+ userId?: string;
122
+ metadata?: Record<string, unknown>;
123
+ }): void;
124
+ /**
125
+ * Track server join or leave events
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * // When bot joins a server
130
+ * client.on('guildCreate', (guild) => {
131
+ * argus.trackServer('join', {
132
+ * serverId: guild.id,
133
+ * memberCount: guild.memberCount
134
+ * });
135
+ * });
136
+ *
137
+ * // When bot leaves/is kicked from a server
138
+ * client.on('guildDelete', (guild) => {
139
+ * argus.trackServer('leave', { serverId: guild.id });
140
+ * });
141
+ * ```
142
+ */
143
+ trackServer(eventType: 'join' | 'leave', options: {
144
+ serverId: string;
145
+ memberCount?: number;
146
+ }): void;
147
+ /**
148
+ * Track revenue events from Patreon, Ko-fi, Stripe, or custom sources
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * // Track a Patreon pledge
153
+ * argus.trackRevenue({
154
+ * source: 'patreon',
155
+ * amount: 500, // $5.00 in cents
156
+ * userId: 'discord_user_id', // optional
157
+ * tier: 'Premium'
158
+ * });
159
+ *
160
+ * // Track a Ko-fi donation
161
+ * argus.trackRevenue({
162
+ * source: 'kofi',
163
+ * amount: 300,
164
+ * currency: 'USD'
165
+ * });
166
+ * ```
167
+ */
168
+ trackRevenue(options: {
169
+ source: 'patreon' | 'kofi' | 'stripe' | 'custom' | string;
170
+ amount: number;
171
+ currency?: string;
172
+ userId?: string;
173
+ tier?: string;
174
+ }): void;
175
+ /**
176
+ * Manually flush all queued events
177
+ */
178
+ flush(): Promise<void>;
179
+ private flushCommandEvents;
180
+ private flushServerEvents;
181
+ private flushRevenueEvents;
182
+ /**
183
+ * Set the bot ID for all future events
184
+ */
185
+ setBotId(botId: string): void;
186
+ /**
187
+ * Start sending heartbeat pings to monitor bot uptime
188
+ *
189
+ * @example
190
+ * ```typescript
191
+ * // Start with default 30 second interval
192
+ * argus.startHeartbeat();
193
+ *
194
+ * // Or customize the interval
195
+ * argus.startHeartbeat({ interval: 60000 }); // 1 minute
196
+ * ```
197
+ */
198
+ startHeartbeat(config?: HeartbeatConfig): void;
199
+ /**
200
+ * Stop sending heartbeat pings
201
+ */
202
+ stopHeartbeat(): void;
203
+ /**
204
+ * Send a single heartbeat ping
205
+ */
206
+ private sendHeartbeat;
207
+ /**
208
+ * Start timing a command execution
209
+ * Call this at the beginning of your command handler
210
+ *
211
+ * @example
212
+ * ```typescript
213
+ * client.on('interactionCreate', async (interaction) => {
214
+ * const timerId = argus.startTimer(interaction.id);
215
+ *
216
+ * try {
217
+ * await handleCommand(interaction);
218
+ * } finally {
219
+ * argus.endTimer(timerId, interaction);
220
+ * }
221
+ * });
222
+ * ```
223
+ */
224
+ startTimer(id: string): string;
225
+ /**
226
+ * End timing and track the command with latency
227
+ */
228
+ endTimer(timerId: string, interaction: {
229
+ commandName?: string;
230
+ customId?: string;
231
+ guildId?: string | null;
232
+ user?: {
233
+ id: string;
234
+ };
235
+ type?: number;
236
+ }): void;
237
+ /**
238
+ * Track an event with latency measurement
239
+ */
240
+ trackEventWithLatency(type: 'command' | 'error' | 'custom', name: string, latencyMs: number, options?: {
241
+ serverId?: string;
242
+ userId?: string;
243
+ metadata?: Record<string, unknown>;
244
+ }): void;
245
+ /**
246
+ * Shutdown the Argus instance, flushing any remaining events
247
+ */
248
+ shutdown(): Promise<void>;
249
+ }
250
+
251
+ export { Argus, type ArgusConfig, type HeartbeatConfig, type RevenueEvent, type ServerEvent, type TrackEvent, Argus as default };