discord-voice-tracker 1.0.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.
@@ -0,0 +1,266 @@
1
+ import { GuildMember, VoiceBasedChannel, PermissionResolvable } from 'discord.js';
2
+ /**
3
+ * Configuration options for the VoiceManager
4
+ */
5
+ export interface VoiceManagerOptions {
6
+ /** Storage adapter to use */
7
+ storage: StorageAdapter;
8
+ /** Check interval in milliseconds (default: 5000) */
9
+ checkInterval?: number;
10
+ /** Enable debug logging */
11
+ debug?: boolean;
12
+ /** Default configuration for new guilds */
13
+ defaultConfig?: Partial<GuildConfig>;
14
+ }
15
+ /**
16
+ * Guild-specific configuration
17
+ */
18
+ export interface GuildConfig {
19
+ /** Guild ID */
20
+ guildId: string;
21
+ /** Track bots */
22
+ trackBots: boolean;
23
+ /** Track all voice channels */
24
+ trackAllChannels: boolean;
25
+ /** Specific channel IDs to track (if trackAllChannels is false) */
26
+ channelIds: string[];
27
+ /** Track muted users */
28
+ trackMuted: boolean;
29
+ /** Track deafened users */
30
+ trackDeafened: boolean;
31
+ /** Minimum users in channel to start tracking */
32
+ minUsersToTrack: number;
33
+ /** Maximum users in channel to track (0 = unlimited) */
34
+ maxUsersToTrack: number;
35
+ /** Permissions that exempt users from tracking */
36
+ exemptPermissions: PermissionResolvable[];
37
+ /** XP to award per check */
38
+ xpPerCheck: number;
39
+ /** Voice time to add per check (milliseconds) */
40
+ voiceTimePerCheck: number;
41
+ /** Level calculation multiplier */
42
+ levelMultiplier: number;
43
+ /** Enable XP/leveling system */
44
+ enableLeveling: boolean;
45
+ /** Enable voice time tracking */
46
+ enableVoiceTime: boolean;
47
+ /** Custom channel filter function */
48
+ channelFilter?: (channel: VoiceBasedChannel) => boolean | Promise<boolean>;
49
+ /** Custom member filter function */
50
+ memberFilter?: (member: GuildMember) => boolean | Promise<boolean>;
51
+ }
52
+ /**
53
+ * User voice data
54
+ */
55
+ export interface UserData {
56
+ /** User ID */
57
+ userId: string;
58
+ /** Guild ID */
59
+ guildId: string;
60
+ /** Total voice time in milliseconds */
61
+ totalVoiceTime: number;
62
+ /** Current XP */
63
+ xp: number;
64
+ /** Current level */
65
+ level: number;
66
+ /** Voice time per channel */
67
+ channels: ChannelData[];
68
+ /** Last seen timestamp */
69
+ lastSeen: Date;
70
+ /** Current streak (consecutive days) */
71
+ streak: number;
72
+ /** Total sessions */
73
+ totalSessions: number;
74
+ /** Custom user data */
75
+ metadata?: Record<string, any>;
76
+ }
77
+ /**
78
+ * Channel-specific voice data
79
+ */
80
+ export interface ChannelData {
81
+ /** Channel ID */
82
+ channelId: string;
83
+ /** Voice time in this channel (milliseconds) */
84
+ voiceTime: number;
85
+ /** Number of sessions in this channel */
86
+ sessions: number;
87
+ /** Last activity timestamp */
88
+ lastActivity: Date;
89
+ }
90
+ /**
91
+ * Voice session data
92
+ */
93
+ export interface SessionData {
94
+ /** Session ID */
95
+ sessionId: string;
96
+ /** User ID */
97
+ userId: string;
98
+ /** Guild ID */
99
+ guildId: string;
100
+ /** Channel ID */
101
+ channelId: string;
102
+ /** Session start time */
103
+ startTime: Date;
104
+ /** Session end time */
105
+ endTime?: Date;
106
+ /** Duration in milliseconds */
107
+ duration?: number;
108
+ /** XP earned in this session */
109
+ xpEarned: number;
110
+ /** Was user muted */
111
+ wasMuted: boolean;
112
+ /** Was user deafened */
113
+ wasDeafened: boolean;
114
+ }
115
+ /**
116
+ * Guild data container
117
+ */
118
+ export interface GuildData {
119
+ /** Guild ID */
120
+ guildId: string;
121
+ /** Guild configuration */
122
+ config: GuildConfig;
123
+ /** All users in this guild */
124
+ users: Map<string, UserData>;
125
+ /** Last updated timestamp */
126
+ lastUpdated: Date;
127
+ }
128
+ /**
129
+ * Leaderboard entry
130
+ */
131
+ export interface LeaderboardEntry {
132
+ /** User ID */
133
+ userId: string;
134
+ /** Guild ID */
135
+ guildId: string;
136
+ /** Total voice time */
137
+ voiceTime: number;
138
+ /** XP */
139
+ xp: number;
140
+ /** Level */
141
+ level: number;
142
+ /** Rank */
143
+ rank: number;
144
+ }
145
+ /**
146
+ * Statistics for a user or guild
147
+ */
148
+ export interface Statistics {
149
+ /** Total voice time */
150
+ totalVoiceTime: number;
151
+ /** Total XP */
152
+ totalXp: number;
153
+ /** Average session duration */
154
+ avgSessionDuration: number;
155
+ /** Total sessions */
156
+ totalSessions: number;
157
+ /** Most active channel */
158
+ mostActiveChannel?: string;
159
+ /** Daily breakdown */
160
+ dailyStats: DailyStats[];
161
+ }
162
+ /**
163
+ * Daily statistics
164
+ */
165
+ export interface DailyStats {
166
+ /** Date */
167
+ date: string;
168
+ /** Voice time that day */
169
+ voiceTime: number;
170
+ /** XP earned that day */
171
+ xp: number;
172
+ /** Sessions that day */
173
+ sessions: number;
174
+ }
175
+ /**
176
+ * Storage adapter interface
177
+ */
178
+ export interface StorageAdapter {
179
+ /** Initialize the storage */
180
+ init(): Promise<void>;
181
+ /** Get guild data */
182
+ getGuild(guildId: string): Promise<GuildData | null>;
183
+ /** Save guild data */
184
+ saveGuild(guildData: GuildData): Promise<void>;
185
+ /** Delete guild data */
186
+ deleteGuild(guildId: string): Promise<void>;
187
+ /** Get user data */
188
+ getUser(guildId: string, userId: string): Promise<UserData | null>;
189
+ /** Save user data */
190
+ saveUser(guildId: string, userData: UserData): Promise<void>;
191
+ /** Delete user data */
192
+ deleteUser(guildId: string, userId: string): Promise<void>;
193
+ /** Get all guilds */
194
+ getAllGuilds(): Promise<GuildData[]>;
195
+ /** Get leaderboard */
196
+ getLeaderboard(guildId: string, sortBy: 'voiceTime' | 'xp' | 'level', limit: number, offset: number): Promise<LeaderboardEntry[]>;
197
+ /** Save session */
198
+ saveSession(session: SessionData): Promise<void>;
199
+ /** Get user sessions */
200
+ getSessions(guildId: string, userId: string, limit?: number): Promise<SessionData[]>;
201
+ /** Close storage connection */
202
+ close(): Promise<void>;
203
+ }
204
+ /**
205
+ * Event types
206
+ */
207
+ export interface VoiceEvents {
208
+ /** User gained voice time */
209
+ voiceTimeGained: (userData: UserData, gained: number) => void;
210
+ /** User gained XP */
211
+ xpGained: (userData: UserData, gained: number) => void;
212
+ /** User leveled up */
213
+ levelUp: (userData: UserData, oldLevel: number, newLevel: number) => void;
214
+ /** User started voice session */
215
+ sessionStart: (session: SessionData) => void;
216
+ /** User ended voice session */
217
+ sessionEnd: (session: SessionData) => void;
218
+ /** Guild configuration updated */
219
+ configUpdated: (guildId: string, config: GuildConfig) => void;
220
+ /** Error occurred */
221
+ error: (error: Error) => void;
222
+ /** Debug message */
223
+ debug: (message: string) => void;
224
+ }
225
+ /**
226
+ * Update options for user data
227
+ */
228
+ export interface UserUpdateOptions {
229
+ /** Add voice time */
230
+ addVoiceTime?: number;
231
+ /** Add XP */
232
+ addXp?: number;
233
+ /** Set level */
234
+ setLevel?: number;
235
+ /** Update metadata */
236
+ metadata?: Record<string, any>;
237
+ }
238
+ /**
239
+ * Query options for leaderboard
240
+ */
241
+ export interface LeaderboardOptions {
242
+ /** Sort by field */
243
+ sortBy?: 'voiceTime' | 'xp' | 'level';
244
+ /** Limit results */
245
+ limit?: number;
246
+ /** Offset for pagination */
247
+ offset?: number;
248
+ /** Filter by minimum level */
249
+ minLevel?: number;
250
+ /** Filter by minimum XP */
251
+ minXp?: number;
252
+ }
253
+ /**
254
+ * Migration data structure
255
+ */
256
+ export interface MigrationData {
257
+ /** Version migrating from */
258
+ fromVersion: string;
259
+ /** Version migrating to */
260
+ toVersion: string;
261
+ /** Guild data to migrate */
262
+ guilds: any[];
263
+ /** Timestamp */
264
+ timestamp: Date;
265
+ }
266
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ // src/types/index.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";AAAA,qBAAqB"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * XP and Level calculation utility
3
+ */
4
+ export declare class XPCalculator {
5
+ /**
6
+ * Calculate level from XP
7
+ * Formula: level = multiplier * sqrt(xp)
8
+ */
9
+ calculateLevel(xp: number, multiplier?: number): number;
10
+ /**
11
+ * Calculate XP needed for a specific level
12
+ */
13
+ calculateXPForLevel(level: number, multiplier?: number): number;
14
+ /**
15
+ * Calculate XP needed to reach next level
16
+ */
17
+ calculateXPToNextLevel(currentXP: number, multiplier?: number): number;
18
+ /**
19
+ * Calculate progress percentage to next level
20
+ */
21
+ calculateLevelProgress(currentXP: number, multiplier?: number): number;
22
+ /**
23
+ * Format voice time to readable string
24
+ */
25
+ formatVoiceTime(milliseconds: number): string;
26
+ /**
27
+ * Calculate average session duration
28
+ */
29
+ calculateAverageSessionDuration(totalVoiceTime: number, totalSessions: number): number;
30
+ }
31
+ //# sourceMappingURL=Calculator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Calculator.d.ts","sourceRoot":"","sources":["../../src/utils/Calculator.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,YAAY;IACvB;;;OAGG;IACH,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,GAAE,MAAY,GAAG,MAAM;IAI5D;;OAEG;IACH,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,GAAE,MAAY,GAAG,MAAM;IAIpE;;OAEG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,GAAE,MAAY,GAAG,MAAM;IAM3E;;OAEG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,GAAE,MAAY,GAAG,MAAM;IAS3E;;OAEG;IACH,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAiB7C;;OAEG;IACH,+BAA+B,CAC7B,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,MAAM,GACpB,MAAM;CAIV"}
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.XPCalculator = void 0;
4
+ /**
5
+ * XP and Level calculation utility
6
+ */
7
+ class XPCalculator {
8
+ /**
9
+ * Calculate level from XP
10
+ * Formula: level = multiplier * sqrt(xp)
11
+ */
12
+ calculateLevel(xp, multiplier = 0.1) {
13
+ return Math.floor(multiplier * Math.sqrt(xp));
14
+ }
15
+ /**
16
+ * Calculate XP needed for a specific level
17
+ */
18
+ calculateXPForLevel(level, multiplier = 0.1) {
19
+ return Math.pow(level / multiplier, 2);
20
+ }
21
+ /**
22
+ * Calculate XP needed to reach next level
23
+ */
24
+ calculateXPToNextLevel(currentXP, multiplier = 0.1) {
25
+ const currentLevel = this.calculateLevel(currentXP, multiplier);
26
+ const nextLevelXP = this.calculateXPForLevel(currentLevel + 1, multiplier);
27
+ return nextLevelXP - currentXP;
28
+ }
29
+ /**
30
+ * Calculate progress percentage to next level
31
+ */
32
+ calculateLevelProgress(currentXP, multiplier = 0.1) {
33
+ const currentLevel = this.calculateLevel(currentXP, multiplier);
34
+ const currentLevelXP = this.calculateXPForLevel(currentLevel, multiplier);
35
+ const nextLevelXP = this.calculateXPForLevel(currentLevel + 1, multiplier);
36
+ const progress = (currentXP - currentLevelXP) / (nextLevelXP - currentLevelXP);
37
+ return Math.round(progress * 100);
38
+ }
39
+ /**
40
+ * Format voice time to readable string
41
+ */
42
+ formatVoiceTime(milliseconds) {
43
+ const seconds = Math.floor(milliseconds / 1000);
44
+ const minutes = Math.floor(seconds / 60);
45
+ const hours = Math.floor(minutes / 60);
46
+ const days = Math.floor(hours / 24);
47
+ if (days > 0) {
48
+ return `${days}d ${hours % 24}h ${minutes % 60}m`;
49
+ }
50
+ else if (hours > 0) {
51
+ return `${hours}h ${minutes % 60}m`;
52
+ }
53
+ else if (minutes > 0) {
54
+ return `${minutes}m ${seconds % 60}s`;
55
+ }
56
+ else {
57
+ return `${seconds}s`;
58
+ }
59
+ }
60
+ /**
61
+ * Calculate average session duration
62
+ */
63
+ calculateAverageSessionDuration(totalVoiceTime, totalSessions) {
64
+ if (totalSessions === 0)
65
+ return 0;
66
+ return totalVoiceTime / totalSessions;
67
+ }
68
+ }
69
+ exports.XPCalculator = XPCalculator;
70
+ //# sourceMappingURL=Calculator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Calculator.js","sourceRoot":"","sources":["../../src/utils/Calculator.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,MAAa,YAAY;IACvB;;;OAGG;IACH,cAAc,CAAC,EAAU,EAAE,aAAqB,GAAG;QACjD,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,KAAa,EAAE,aAAqB,GAAG;QACzD,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,sBAAsB,CAAC,SAAiB,EAAE,aAAqB,GAAG;QAChE,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QAChE,MAAM,WAAW,GAAG,IAAI,CAAC,mBAAmB,CAAC,YAAY,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC;QAC3E,OAAO,WAAW,GAAG,SAAS,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,sBAAsB,CAAC,SAAiB,EAAE,aAAqB,GAAG;QAChE,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QAChE,MAAM,cAAc,GAAG,IAAI,CAAC,mBAAmB,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QAC1E,MAAM,WAAW,GAAG,IAAI,CAAC,mBAAmB,CAAC,YAAY,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC;QAE3E,MAAM,QAAQ,GAAG,CAAC,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,WAAW,GAAG,cAAc,CAAC,CAAC;QAC/E,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,eAAe,CAAC,YAAoB;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;QAEpC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,KAAK,KAAK,GAAG,EAAE,KAAK,OAAO,GAAG,EAAE,GAAG,CAAC;QACpD,CAAC;aAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACrB,OAAO,GAAG,KAAK,KAAK,OAAO,GAAG,EAAE,GAAG,CAAC;QACtC,CAAC;aAAM,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,GAAG,OAAO,KAAK,OAAO,GAAG,EAAE,GAAG,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,OAAO,GAAG,CAAC;QACvB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,+BAA+B,CAC7B,cAAsB,EACtB,aAAqB;QAErB,IAAI,aAAa,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QAClC,OAAO,cAAc,GAAG,aAAa,CAAC;IACxC,CAAC;CACF;AAnED,oCAmEC"}
@@ -0,0 +1,9 @@
1
+ export declare class Logger {
2
+ private debugEnabled;
3
+ constructor(debug?: boolean);
4
+ log(message: string, ...args: any[]): void;
5
+ error(message: string, error?: any): void;
6
+ warn(message: string, ...args: any[]): void;
7
+ debug(message: string, ...args: any[]): void;
8
+ }
9
+ //# sourceMappingURL=Logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../../src/utils/Logger.ts"],"names":[],"mappings":"AAAA,qBAAa,MAAM;IACjB,OAAO,CAAC,YAAY,CAAU;gBAElB,KAAK,GAAE,OAAe;IAIlC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI1C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,GAAG,IAAI;IAIzC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI3C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;CAK7C"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Logger = void 0;
4
+ class Logger {
5
+ debugEnabled;
6
+ constructor(debug = false) {
7
+ this.debugEnabled = debug;
8
+ }
9
+ log(message, ...args) {
10
+ console.log(`[VoiceTracker] ${message}`, ...args);
11
+ }
12
+ error(message, error) {
13
+ console.error(`[VoiceTracker ERROR] ${message}`, error);
14
+ }
15
+ warn(message, ...args) {
16
+ console.warn(`[VoiceTracker WARN] ${message}`, ...args);
17
+ }
18
+ debug(message, ...args) {
19
+ if (this.debugEnabled) {
20
+ console.log(`[VoiceTracker DEBUG] ${message}`, ...args);
21
+ }
22
+ }
23
+ }
24
+ exports.Logger = Logger;
25
+ //# sourceMappingURL=Logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.js","sourceRoot":"","sources":["../../src/utils/Logger.ts"],"names":[],"mappings":";;;AAAA,MAAa,MAAM;IACT,YAAY,CAAU;IAE9B,YAAY,QAAiB,KAAK;QAChC,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;IAC5B,CAAC;IAED,GAAG,CAAC,OAAe,EAAE,GAAG,IAAW;QACjC,OAAO,CAAC,GAAG,CAAC,kBAAkB,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,KAAW;QAChC,OAAO,CAAC,KAAK,CAAC,wBAAwB,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,GAAG,IAAW;QAClC,OAAO,CAAC,IAAI,CAAC,uBAAuB,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IAC1D,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,GAAG,IAAW;QACnC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,wBAAwB,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;CACF;AAxBD,wBAwBC"}
@@ -0,0 +1,19 @@
1
+ import { GuildConfig } from '../types';
2
+ /**
3
+ * Input validation utility
4
+ */
5
+ export declare class Validator {
6
+ /**
7
+ * Validate guild configuration
8
+ */
9
+ static validateGuildConfig(config: Partial<GuildConfig>): string[];
10
+ /**
11
+ * Validate user ID (Discord snowflake)
12
+ */
13
+ static validateSnowflake(id: string): boolean;
14
+ /**
15
+ * Validate pagination parameters
16
+ */
17
+ static validatePagination(limit: number, offset: number): string[];
18
+ }
19
+ //# sourceMappingURL=Validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Validator.d.ts","sourceRoot":"","sources":["../../src/utils/Validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC;;GAEG;AACH,qBAAa,SAAS;IACpB;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,MAAM,EAAE;IA2ClE;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI7C;;OAEG;IACH,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;CAanE"}
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Validator = void 0;
4
+ /**
5
+ * Input validation utility
6
+ */
7
+ class Validator {
8
+ /**
9
+ * Validate guild configuration
10
+ */
11
+ static validateGuildConfig(config) {
12
+ const errors = [];
13
+ if (config.minUsersToTrack !== undefined && config.minUsersToTrack < 0) {
14
+ errors.push('minUsersToTrack must be >= 0');
15
+ }
16
+ if (config.maxUsersToTrack !== undefined && config.maxUsersToTrack < 0) {
17
+ errors.push('maxUsersToTrack must be >= 0');
18
+ }
19
+ if (config.minUsersToTrack !== undefined &&
20
+ config.maxUsersToTrack !== undefined &&
21
+ config.maxUsersToTrack > 0 &&
22
+ config.minUsersToTrack > config.maxUsersToTrack) {
23
+ errors.push('minUsersToTrack cannot be greater than maxUsersToTrack');
24
+ }
25
+ if (config.xpPerCheck !== undefined && config.xpPerCheck < 0) {
26
+ errors.push('xpPerCheck must be >= 0');
27
+ }
28
+ if (config.voiceTimePerCheck !== undefined && config.voiceTimePerCheck < 0) {
29
+ errors.push('voiceTimePerCheck must be >= 0');
30
+ }
31
+ if (config.levelMultiplier !== undefined && config.levelMultiplier <= 0) {
32
+ errors.push('levelMultiplier must be > 0');
33
+ }
34
+ if (config.channelIds !== undefined && !Array.isArray(config.channelIds)) {
35
+ errors.push('channelIds must be an array');
36
+ }
37
+ if (config.exemptPermissions !== undefined && !Array.isArray(config.exemptPermissions)) {
38
+ errors.push('exemptPermissions must be an array');
39
+ }
40
+ return errors;
41
+ }
42
+ /**
43
+ * Validate user ID (Discord snowflake)
44
+ */
45
+ static validateSnowflake(id) {
46
+ return /^\d{17,19}$/.test(id);
47
+ }
48
+ /**
49
+ * Validate pagination parameters
50
+ */
51
+ static validatePagination(limit, offset) {
52
+ const errors = [];
53
+ if (limit < 1 || limit > 100) {
54
+ errors.push('limit must be between 1 and 100');
55
+ }
56
+ if (offset < 0) {
57
+ errors.push('offset must be >= 0');
58
+ }
59
+ return errors;
60
+ }
61
+ }
62
+ exports.Validator = Validator;
63
+ //# sourceMappingURL=Validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Validator.js","sourceRoot":"","sources":["../../src/utils/Validator.ts"],"names":[],"mappings":";;;AAEA;;GAEG;AACH,MAAa,SAAS;IACpB;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,MAA4B;QACrD,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,IAAI,MAAM,CAAC,eAAe,KAAK,SAAS,IAAI,MAAM,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;YACvE,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,MAAM,CAAC,eAAe,KAAK,SAAS,IAAI,MAAM,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;YACvE,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC9C,CAAC;QAED,IACE,MAAM,CAAC,eAAe,KAAK,SAAS;YACpC,MAAM,CAAC,eAAe,KAAK,SAAS;YACpC,MAAM,CAAC,eAAe,GAAG,CAAC;YAC1B,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,EAC/C,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAC;QACxE,CAAC;QAED,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,IAAI,MAAM,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;YAC7D,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACzC,CAAC;QAED,IAAI,MAAM,CAAC,iBAAiB,KAAK,SAAS,IAAI,MAAM,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC;YAC3E,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAChD,CAAC;QAED,IAAI,MAAM,CAAC,eAAe,KAAK,SAAS,IAAI,MAAM,CAAC,eAAe,IAAI,CAAC,EAAE,CAAC;YACxE,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAC7C,CAAC;QAED,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;YACzE,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAC7C,CAAC;QAED,IAAI,MAAM,CAAC,iBAAiB,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACvF,MAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,EAAU;QACjC,OAAO,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,kBAAkB,CAAC,KAAa,EAAE,MAAc;QACrD,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAtED,8BAsEC"}
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "discord-voice-tracker",
3
+ "version": "1.0.0",
4
+ "description": "Modern voice activity tracking for Discord bots with XP, leveling, and comprehensive statistics",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist/**/*",
9
+ "README.md",
10
+ "LICENSE"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "dev": "tsc --watch",
15
+ "test": "jest",
16
+ "test:watch": "jest --watch",
17
+ "test:coverage": "jest --coverage",
18
+ "lint": "eslint src/**/*.ts",
19
+ "lint:fix": "eslint src/**/*.ts --fix",
20
+ "format": "prettier --write \"src/**/*.ts\"",
21
+ "prepublishOnly": "npm run build",
22
+ "prepare": "npm run build"
23
+ },
24
+ "keywords": [
25
+ "discord",
26
+ "discord.js",
27
+ "voice",
28
+ "voice-tracking",
29
+ "voice-time",
30
+ "tracking",
31
+ "bot",
32
+ "discord-bot",
33
+ "leveling",
34
+ "xp",
35
+ "leaderboard",
36
+ "statistics",
37
+ "analytics",
38
+ "voice-chat",
39
+ "mongodb",
40
+ "typescript"
41
+ ],
42
+ "author": "Async",
43
+ "license": "MIT",
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "https://github.com/Instinzts/discord-voice-tracker.git"
47
+ },
48
+ "bugs": {
49
+ "url": "https://github.com/Instinzts/discord-voice-tracker/issues"
50
+ },
51
+ "homepage": "https://github.com/Instinzts/discord-voice-tracker#readme",
52
+ "peerDependencies": {
53
+ "discord.js": "^14.0.0"
54
+ },
55
+ "dependencies": {},
56
+ "optionalDependencies": {
57
+ "mongodb": "^7.0.0"
58
+ },
59
+ "devDependencies": {
60
+ "@types/jest": "^30.0.0",
61
+ "@types/node": "^25.0.10",
62
+ "@typescript-eslint/eslint-plugin": "^8.53.1",
63
+ "@typescript-eslint/parser": "^8.53.1",
64
+ "discord.js": "^14.25.1",
65
+ "dotenv": "^17.2.3",
66
+ "eslint": "^9.39.2",
67
+ "jest": "^30.2.0",
68
+ "mongodb": "^7.0.0",
69
+ "prettier": "^3.8.1",
70
+ "ts-jest": "^29.4.6",
71
+ "typescript": "^5.9.3"
72
+ },
73
+ "engines": {
74
+ "node": ">=18.0.0"
75
+ }
76
+ }