@@ -12,6 +12,7 @@ import { ServiceProvider } from '../service/database/ServiceProvider';
1212export class CopBot {
1313 private static instance : CopBot ;
1414 private _bot : Bot < Context > ;
15+ private healthCheckInterval : NodeJS . Timeout | null = null ;
1516 private constructor ( ) {
1617 this . _bot = new Bot < Context > ( Config . token ) ;
1718 }
@@ -24,6 +25,9 @@ export class CopBot {
2425 }
2526 // Stop the bot
2627 async stop ( ) : Promise < void > {
28+ if ( this . healthCheckInterval ) {
29+ clearInterval ( this . healthCheckInterval ) ;
30+ }
2731 await this . _bot . stop ( ) ;
2832 }
2933
@@ -32,7 +36,7 @@ export class CopBot {
3236 const startBot = async ( mode : string ) => {
3337 await this . _bot . start ( {
3438 drop_pending_updates : true ,
35- timeout : 60 ,
39+ timeout : 300 ,
3640 onStart : ( botInfo ) => {
3741 logger . info ( `Bot started in ${ mode } mode! Username: ${ botInfo . username } ` ) ;
3842 } ,
@@ -79,37 +83,7 @@ export class CopBot {
7983 const port = process . env . PORT || 3000 ;
8084 app . listen ( port , async ( ) => {
8185 logger . info ( `Webhook server running on port ${ port } ` ) ;
82- let webhookInfo = await this . _bot . api . getWebhookInfo ( ) ;
83- logger . info ( `Current Webhook: ${ webhookInfo . url } ` ) ;
84- const MAX_RETRIES = 5 ;
85- let retries = 0 ;
86-
87- const trySetWebhook = async ( ) => {
88- try {
89- if ( ! webhookInfo . url ) {
90- logger . warn ( 'Webhook is not set. Trying to set the webhook...' ) ;
91- await this . _bot . api . setWebhook ( webhookURL , { drop_pending_updates : true } ) ;
92- webhookInfo = await this . _bot . api . getWebhookInfo ( ) ;
93- logger . info ( `Webhook set: ${ webhookInfo . url } ` ) ;
94- } else {
95- logger . info ( 'Webhook is already set.' ) ;
96- }
97- } catch ( error : any ) {
98- retries ++ ;
99- logger . error ( `Error setting webhook (Attempt ${ retries } ): ${ error . message } ` ) ;
100- if ( retries < MAX_RETRIES ) {
101- const delay = Math . min ( 1000 * 2 ** retries , 30000 ) ; // Exponential backoff
102- logger . warn ( `Retrying in ${ delay / 1000 } seconds...` ) ;
103- await new Promise ( ( resolve ) => setTimeout ( resolve , delay ) ) ;
104- await trySetWebhook ( ) ;
105- } else {
106- logger . error ( 'Max retries reached. Could not set webhook.' ) ;
107- process . exit ( 1 ) ; // Exit after maximum retries reached
108- }
109- }
110- } ;
111-
112- await trySetWebhook ( ) ;
86+ await this . setupWebhook ( webhookURL ) ;
11387 await startBot ( mode ) ;
11488 } ) ;
11589 } catch ( err : any ) {
@@ -137,15 +111,38 @@ export class CopBot {
137111 this . _bot . catch ( async ( error : BotError < Context > ) => {
138112 if ( error . message . includes ( 'timeout' ) ) {
139113 await error . ctx . reply ( 'The request took too long to process. Please try again later.' ) ;
114+ await this . start ( ) ;
140115 }
141116 logger . error ( `Bot error occurred: ${ error . error } ` ) ;
142117 } ) ;
143118 await this . start ( ) ;
119+ // Set up periodic health checks and keep-alives
120+ this . healthCheckInterval = setInterval ( async ( ) => {
121+ try {
122+ await this . _bot . api . getMe ( ) ; // Ping Telegram to keep the connection alive
123+ const isHealthy = await ServiceProvider . getInstance ( ) . healthCheck ( ) ;
124+ if ( ! isHealthy ) {
125+ logger . warn ( 'Database health check failed. Attempting to reconnect...' ) ;
126+ await ServiceProvider . initialize ( ) ;
127+ }
128+ logger . info ( 'Bot is live' ) ;
129+ } catch ( error : any ) {
130+ logger . error ( `Health check failed: ${ error . message } ` ) ;
131+ }
132+ } , 5 * 60 * 1000 ) ; // Every 5 minutes
144133 logger . info ( 'Bot is running' ) ;
145134 }
146135 @MessageValidator ( )
147136 @SaveUserData ( )
148- async handleMessage ( ctx : Context ) { }
137+ async handleMessage ( ctx : Context ) {
138+ try {
139+ const client = await ServiceProvider . getInstance ( ) . getConnectionPool ( ) . getClient ( ) ;
140+ client . release ( ) ;
141+ } catch ( err : any ) {
142+ logger . error ( `Database error in handleMessage: ${ err . message } ` ) ;
143+ await ctx . reply ( 'Error processing your request. Please try again later.' ) ;
144+ }
145+ }
149146 @SaveUserData ( )
150147 async handleJoinNewChat ( ctx : Context ) {
151148 if ( ! ctx . message ?. text ) {
@@ -166,4 +163,38 @@ I'm here to help out and make sure everyone has a good time. Are you curious abo
166163 await reply . textReply ( message ) ;
167164 return ;
168165 }
166+ private async setupWebhook ( webhookURL : string ) : Promise < void > {
167+ const MAX_RETRIES = 5 ;
168+ let retries = 0 ;
169+
170+ while ( retries < MAX_RETRIES ) {
171+ try {
172+ // Delete existing webhook to ensure a clean state
173+ await this . _bot . api . deleteWebhook ( { drop_pending_updates : true } ) ;
174+
175+ // Set the new webhook
176+ const setWebhookResponse = await this . _bot . api . setWebhook ( webhookURL , { drop_pending_updates : true } ) ;
177+ logger . info ( `Set Webhook Response: ${ JSON . stringify ( setWebhookResponse , null , 2 ) } ` ) ;
178+
179+ // Verify webhook was set
180+ const webhookInfo = await this . _bot . api . getWebhookInfo ( ) ;
181+ logger . info ( `Webhook Info: ${ JSON . stringify ( webhookInfo , null , 2 ) } ` ) ;
182+
183+ if ( webhookInfo . url === webhookURL ) {
184+ logger . info ( 'Webhook set successfully.' ) ;
185+ return ;
186+ } else {
187+ logger . warn ( `Webhook URL mismatch. Expected: ${ webhookURL } , Got: ${ webhookInfo . url } ` ) ;
188+ }
189+ } catch ( error : any ) {
190+ retries ++ ;
191+ logger . error ( `Error setting webhook (Attempt ${ retries } ): ${ error . message } ` ) ;
192+ if ( retries === MAX_RETRIES ) {
193+ logger . error ( 'Max retries reached. Could not set webhook.' ) ;
194+ process . exit ( 1 ) ;
195+ }
196+ await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 * 2 ** retries ) ) ;
197+ }
198+ }
199+ }
169200}
0 commit comments