1+ import { drizzle } from "drizzle-orm/node-postgres" ;
2+ import { Pool } from "pg" ;
3+ import * as schema from "../lib/schema" ;
4+ import { v4 as uuidv4 } from 'uuid' ;
5+
6+ const pool = new Pool ( {
7+ connectionString : process . env . databaseUrl ,
8+ } ) ;
9+
10+ const db = drizzle ( pool , { schema } ) ;
11+
12+ const errorTypes = [
13+ 'TypeError' ,
14+ 'ReferenceError' ,
15+ 'SyntaxError' ,
16+ 'RangeError' ,
17+ 'NetworkError' ,
18+ 'DatabaseError' ,
19+ 'AuthenticationError' ,
20+ 'ValidationError' ,
21+ 'TimeoutError' ,
22+ 'PermissionError'
23+ ] ;
24+
25+ const errorMessages = [
26+ 'Cannot read property of undefined' ,
27+ 'Connection timed out' ,
28+ 'Invalid user credentials' ,
29+ 'Database connection failed' ,
30+ 'Rate limit exceeded' ,
31+ 'Insufficient permissions' ,
32+ 'Invalid input format' ,
33+ 'Resource not found' ,
34+ 'Server internal error' ,
35+ 'Memory limit exceeded' ,
36+ 'Invalid API response' ,
37+ 'File upload failed' ,
38+ 'Session expired' ,
39+ 'Token validation failed' ,
40+ 'Query execution failed' ,
41+ 'Cache miss error' ,
42+ 'Webhook delivery failed' ,
43+ 'Message sending failed' ,
44+ 'User not found' ,
45+ 'Command execution failed'
46+ ] ;
47+
48+ const commandNames = [
49+ 'start' ,
50+ 'help' ,
51+ 'settings' ,
52+ 'ai' ,
53+ 'wiki' ,
54+ 'translate' ,
55+ 'weather' ,
56+ 'news' ,
57+ 'stats' ,
58+ 'export' ,
59+ 'import' ,
60+ 'search' ,
61+ 'notify' ,
62+ 'schedule' ,
63+ 'reminder' ,
64+ 'poll' ,
65+ 'game' ,
66+ 'music' ,
67+ 'video' ,
68+ 'image'
69+ ] ;
70+
71+ const chatTypes = [ 'private' , 'group' , 'supergroup' , 'channel' ] ;
72+
73+ const telegramMethods = [
74+ 'sendMessage' ,
75+ 'sendPhoto' ,
76+ 'sendDocument' ,
77+ 'sendVideo' ,
78+ 'sendAudio' ,
79+ 'editMessageText' ,
80+ 'deleteMessage' ,
81+ 'getMe' ,
82+ 'getChat' ,
83+ 'getChatMember' ,
84+ 'setChatPermissions' ,
85+ 'answerCallbackQuery' ,
86+ 'sendPoll' ,
87+ 'sendVoice' ,
88+ 'sendLocation'
89+ ] ;
90+
91+ const telegramErrorCodes = [ 400 , 401 , 403 , 404 , 429 , 500 , 502 , 503 ] ;
92+
93+ const telegramDescriptions = [
94+ 'Bad Request: message text is empty' ,
95+ 'Unauthorized: bot token is invalid' ,
96+ 'Forbidden: bot was kicked from the group chat' ,
97+ 'Not Found: chat not found' ,
98+ 'Too Many Requests: retry after 30 seconds' ,
99+ 'Internal Server Error' ,
100+ 'Bad Gateway' ,
101+ 'Service Unavailable' ,
102+ 'Bad Request: message to edit not found' ,
103+ 'Bad Request: message can\'t be deleted' ,
104+ 'Bad Request: poll has already been closed' ,
105+ 'Bad Request: file is too big' ,
106+ 'Bad Request: wrong file identifier' ,
107+ 'Forbidden: user is deactivated' ,
108+ 'Bad Request: invalid user ID'
109+ ] ;
110+
111+ function getRandomElement < T > ( array : T [ ] ) : T {
112+ return array [ Math . floor ( Math . random ( ) * array . length ) ] ;
113+ }
114+
115+ function getRandomDate ( startDate : Date , endDate : Date ) : Date {
116+ const startTime = startDate . getTime ( ) ;
117+ const endTime = endDate . getTime ( ) ;
118+ const randomTime = startTime + Math . random ( ) * ( endTime - startTime ) ;
119+ return new Date ( randomTime ) ;
120+ }
121+
122+ function getRandomSeverity ( ) : 'info' | 'warning' | 'error' | 'critical' {
123+ const rand = Math . random ( ) ;
124+ if ( rand < 0.2 ) return 'info' ;
125+ if ( rand < 0.45 ) return 'warning' ;
126+ if ( rand < 0.85 ) return 'error' ;
127+ return 'critical' ;
128+ }
129+
130+ function generateStackTrace ( errorType : string , errorMessage : string ) : string {
131+ const functions = [
132+ 'at processTicksAndRejections (node:internal/process/task_queues:96:5)' ,
133+ 'at async handleCommand (/app/telegram/bot.ts:145:13)' ,
134+ 'at async MessageHandler.handle (/app/telegram/handlers/message.ts:78:9)' ,
135+ 'at async Bot.processUpdate (/app/node_modules/telegraf/bot.ts:234:17)' ,
136+ 'at async middleware (/app/telegram/middleware/error.ts:45:5)' ,
137+ 'at async Database.query (/app/database/client.ts:112:11)' ,
138+ 'at async Redis.get (/app/cache/redis.ts:34:7)' ,
139+ 'at async ApiClient.request (/app/api/client.ts:89:15)'
140+ ] ;
141+
142+ const stack = [ `${ errorType } : ${ errorMessage } ` ] ;
143+ const numLines = Math . floor ( Math . random ( ) * 4 ) + 3 ;
144+
145+ for ( let i = 0 ; i < numLines ; i ++ ) {
146+ stack . push ( getRandomElement ( functions ) ) ;
147+ }
148+
149+ return stack . join ( '\n ' ) ;
150+ }
151+
152+ async function generateBotErrors ( count : number ) {
153+ const errors = [ ] ;
154+ const endDate = new Date ( ) ;
155+ const startDate = new Date ( ) ;
156+ startDate . setFullYear ( startDate . getFullYear ( ) - 1 ) ;
157+
158+ for ( let i = 0 ; i < count ; i ++ ) {
159+ const errorType = getRandomElement ( errorTypes ) ;
160+ const errorMessage = getRandomElement ( errorMessages ) ;
161+ const severity = getRandomSeverity ( ) ;
162+ const isResolved = Math . random ( ) < 0.3 ;
163+ const createdAt = getRandomDate ( startDate , endDate ) ;
164+
165+ const error = {
166+ id : uuidv4 ( ) ,
167+ errorType,
168+ errorMessage : `${ errorMessage } in ${ getRandomElement ( commandNames ) } command` ,
169+ errorStack : Math . random ( ) < 0.7 ? generateStackTrace ( errorType , errorMessage ) : null ,
170+ commandName : Math . random ( ) < 0.8 ? getRandomElement ( commandNames ) : null ,
171+ chatType : Math . random ( ) < 0.9 ? getRandomElement ( chatTypes ) : null ,
172+ severity,
173+ resolved : isResolved ,
174+ createdAt,
175+ resolvedAt : isResolved ? getRandomDate ( createdAt , endDate ) : null
176+ } ;
177+
178+ errors . push ( error ) ;
179+ }
180+
181+ return errors ;
182+ }
183+
184+ async function generateTelegramErrors ( count : number ) {
185+ const errors = [ ] ;
186+ const endDate = new Date ( ) ;
187+ const startDate = new Date ( ) ;
188+ startDate . setFullYear ( startDate . getFullYear ( ) - 1 ) ;
189+
190+ for ( let i = 0 ; i < count ; i ++ ) {
191+ const isResolved = Math . random ( ) < 0.25 ;
192+ const createdAt = getRandomDate ( startDate , endDate ) ;
193+ const retryCount = Math . floor ( Math . random ( ) * 5 ) ;
194+
195+ const error = {
196+ id : `tg_${ uuidv4 ( ) } ` ,
197+ errorCode : Math . random ( ) < 0.9 ? getRandomElement ( telegramErrorCodes ) : null ,
198+ errorDescription : getRandomElement ( telegramDescriptions ) ,
199+ method : Math . random ( ) < 0.85 ? getRandomElement ( telegramMethods ) : null ,
200+ parameters : Math . random ( ) < 0.5 ? JSON . stringify ( {
201+ chat_id : Math . floor ( Math . random ( ) * 1000000 ) ,
202+ text : 'Sample message' ,
203+ parse_mode : 'Markdown'
204+ } ) : null ,
205+ retryCount,
206+ resolved : isResolved ,
207+ createdAt,
208+ lastRetryAt : retryCount > 0 ? getRandomDate ( createdAt , endDate ) : null
209+ } ;
210+
211+ errors . push ( error ) ;
212+ }
213+
214+ return errors ;
215+ }
216+
217+ async function generateCommandUsageEntries ( count : number ) {
218+ const entries = [ ] ;
219+ const endDate = new Date ( ) ;
220+ const startDate = new Date ( ) ;
221+ startDate . setFullYear ( startDate . getFullYear ( ) - 1 ) ;
222+
223+ for ( let i = 0 ; i < count ; i ++ ) {
224+ const isError = Math . random ( ) < 0.3 ;
225+ const commandName = getRandomElement ( commandNames ) ;
226+ const createdAt = getRandomDate ( startDate , endDate ) ;
227+
228+ const entry = {
229+ id : uuidv4 ( ) ,
230+ commandName,
231+ chatType : getRandomElement ( chatTypes ) ,
232+ isSuccess : ! isError ,
233+ errorMessage : isError ? getRandomElement ( errorMessages ) : null ,
234+ executionTime : Math . floor ( Math . random ( ) * 500 ) + 50 ,
235+ createdAt
236+ } ;
237+
238+ entries . push ( entry ) ;
239+ }
240+
241+ return entries ;
242+ }
243+
244+ async function insertErrors ( ) {
245+ try {
246+ console . log ( '🚀 Starting dummy error generation...\n' ) ;
247+
248+ const botErrorCount = parseInt ( process . argv [ 2 ] ) || 50 ;
249+ const telegramErrorCount = parseInt ( process . argv [ 3 ] ) || 30 ;
250+ const commandUsageCount = parseInt ( process . argv [ 4 ] ) || 100 ;
251+
252+ console . log ( `📝 Generating ${ botErrorCount } bot errors...` ) ;
253+ const botErrors = await generateBotErrors ( botErrorCount ) ;
254+
255+ console . log ( `📝 Generating ${ telegramErrorCount } Telegram errors...` ) ;
256+ const telegramErrors = await generateTelegramErrors ( telegramErrorCount ) ;
257+
258+ console . log ( `📝 Generating ${ commandUsageCount } command usage entries...` ) ;
259+ const commandUsageEntries = await generateCommandUsageEntries ( commandUsageCount ) ;
260+
261+ console . log ( '\n💾 Inserting bot errors into database...' ) ;
262+ for ( const error of botErrors ) {
263+ await db . insert ( schema . botErrorsTable ) . values ( error ) ;
264+ }
265+ console . log ( `✅ Inserted ${ botErrors . length } bot errors` ) ;
266+
267+ console . log ( '\n💾 Inserting Telegram errors into database...' ) ;
268+ for ( const error of telegramErrors ) {
269+ const { id, ...errorData } = error ;
270+ await db . insert ( schema . telegramErrorsTable ) . values ( {
271+ ...errorData ,
272+ id : id . replace ( 'tg_' , '' )
273+ } ) ;
274+ }
275+ console . log ( `✅ Inserted ${ telegramErrors . length } Telegram errors` ) ;
276+
277+ console . log ( '\n💾 Inserting command usage entries into database...' ) ;
278+ for ( const entry of commandUsageEntries ) {
279+ await db . insert ( schema . commandUsageTable ) . values ( entry ) ;
280+ }
281+ console . log ( `✅ Inserted ${ commandUsageEntries . length } command usage entries` ) ;
282+
283+ const resolvedBotErrors = botErrors . filter ( e => e . resolved ) . length ;
284+ const unresolvedBotErrors = botErrors . filter ( e => ! e . resolved ) . length ;
285+ const resolvedTelegramErrors = telegramErrors . filter ( e => e . resolved ) . length ;
286+ const unresolvedTelegramErrors = telegramErrors . filter ( e => ! e . resolved ) . length ;
287+
288+ const failedCommands = commandUsageEntries . filter ( e => ! e . isSuccess ) . length ;
289+ const successfulCommands = commandUsageEntries . filter ( e => e . isSuccess ) . length ;
290+
291+ console . log ( '\n📊 Summary:' ) ;
292+ console . log ( '─────────────────────────────────' ) ;
293+ console . log ( `Bot Errors:` ) ;
294+ console . log ( ` • Total: ${ botErrors . length } ` ) ;
295+ console . log ( ` • Resolved: ${ resolvedBotErrors } ` ) ;
296+ console . log ( ` • Unresolved: ${ unresolvedBotErrors } ` ) ;
297+ console . log ( ` • Severities:` ) ;
298+ console . log ( ` - Critical: ${ botErrors . filter ( e => e . severity === 'critical' ) . length } ` ) ;
299+ console . log ( ` - Error: ${ botErrors . filter ( e => e . severity === 'error' ) . length } ` ) ;
300+ console . log ( ` - Warning: ${ botErrors . filter ( e => e . severity === 'warning' ) . length } ` ) ;
301+ console . log ( ` - Info: ${ botErrors . filter ( e => e . severity === 'info' ) . length } ` ) ;
302+ console . log ( `\nTelegram Errors:` ) ;
303+ console . log ( ` • Total: ${ telegramErrors . length } ` ) ;
304+ console . log ( ` • Resolved: ${ resolvedTelegramErrors } ` ) ;
305+ console . log ( ` • Unresolved: ${ unresolvedTelegramErrors } ` ) ;
306+ console . log ( `\nCommand Usage:` ) ;
307+ console . log ( ` • Total: ${ commandUsageEntries . length } ` ) ;
308+ console . log ( ` • Failed: ${ failedCommands } (${ ( ( failedCommands / commandUsageEntries . length ) * 100 ) . toFixed ( 1 ) } %)` ) ;
309+ console . log ( ` • Successful: ${ successfulCommands } ` ) ;
310+
311+ console . log ( '\n✨ Done! Check the Error Review page in the WebUI to see the generated errors.' ) ;
312+
313+ } catch ( error ) {
314+ console . error ( '❌ Error generating dummy data:' , error ) ;
315+ process . exit ( 1 ) ;
316+ } finally {
317+ await pool . end ( ) ;
318+ process . exit ( 0 ) ;
319+ }
320+ }
321+
322+ if ( import . meta. main ) {
323+ insertErrors ( ) ;
324+ }
0 commit comments