Skip to content

Commit e03c9c4

Browse files
committed
refactor(bot): bot code to improve reliability and logging`
`src/bot/index.ts`: - Added health check interval to keep the bot connection alive - Improved error handling for database connections in `handleMessage` and `handleJoinNewChat`
1 parent bcd6957 commit e03c9c4

2 files changed

Lines changed: 64 additions & 35 deletions

File tree

src/bot/index.ts

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { ServiceProvider } from '../service/database/ServiceProvider';
1212
export 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
}

src/bot/service/admin/Warn.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,6 @@ export class WarnService {
140140
});
141141
}
142142
}
143-
console.log('usersWithWarnings', JSON.stringify(usersWithWarnings, null, 2));
144-
145143
// Generate structured output
146144
let output = `**Group Warning Report**\n`;
147145
output += `Group ID: ${groupId}\n\n`;

0 commit comments

Comments
 (0)