Skip to content

Commit c5d5f29

Browse files
committed
feat: updated code with various changes to improve functionality and error handling
1 parent 75e7e7d commit c5d5f29

4 files changed

Lines changed: 77 additions & 41 deletions

File tree

src/bot/handlers/GenerateCommands.ts

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,46 @@ import { CommandName, COMMANDS } from '../../utils';
33
import { GeneralCommands } from '../../bot/commands/genearl/GeneralCommands';
44
import { UserCommands } from '../commands/user/UserCommands';
55
import { AdminCommands } from '../commands/admin/AdminCommands';
6+
import logger from '../../utils/logger';
67
export class GenerateCommand {
78
private bot: Bot;
89
constructor(bot: Bot) {
910
this.bot = bot;
1011
}
1112

1213
private registerCommand(name: CommandName) {
13-
// Safely access the command handler on GeneralCommands
14-
const generalCommandHandler = (GeneralCommands as any)[name];
15-
const userCommandHandler = (UserCommands as any)[name];
16-
const adminCommandsHandler = (AdminCommands as any)[name];
17-
if (generalCommandHandler) {
18-
this.bot.command(name, generalCommandHandler.bind(GeneralCommands));
19-
} else if (userCommandHandler) {
20-
this.bot.command(name, userCommandHandler.bind(UserCommands));
21-
} else if (adminCommandsHandler) {
22-
this.bot.command(name, adminCommandsHandler.bind(AdminCommands));
14+
try {
15+
// Safely access the command handler from the appropriate module
16+
const generalCommandHandler = (GeneralCommands as any)[name];
17+
const userCommandHandler = (UserCommands as any)[name];
18+
const adminCommandHandler = (AdminCommands as any)[name];
19+
20+
if (generalCommandHandler) {
21+
this.bot.command(name, generalCommandHandler.bind(GeneralCommands));
22+
} else if (userCommandHandler) {
23+
this.bot.command(name, userCommandHandler.bind(UserCommands));
24+
} else if (adminCommandHandler) {
25+
this.bot.command(name, adminCommandHandler.bind(AdminCommands));
26+
} else {
27+
logger.warn(`Command not found in any module: ${name}`);
28+
}
29+
} catch (error: any) {
30+
logger.error(`Error registering command "${name}": ${error.message}`);
2331
}
2432
}
2533

2634
/**
2735
* Registers all commands defined in COMMANDS.
2836
*/
2937
generate() {
30-
COMMANDS.forEach((command) => this.registerCommand(command));
38+
logger.info('Starting command generation.');
39+
try {
40+
COMMANDS.forEach((command) => {
41+
this.registerCommand(command);
42+
});
43+
logger.info('All commands have been registered successfully.');
44+
} catch (error: any) {
45+
logger.error(`Error during command generation: ${error.message}`);
46+
}
3147
}
3248
}

src/bot/index.ts

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as express from 'express';
88
import { BotReply } from '../utils/chat/BotReply';
99
import logger from '../utils/logger';
1010
import { limit } from '@grammyjs/ratelimiter';
11+
import { ServiceProvider } from '../service/database/ServiceProvider';
1112
export class CopBot {
1213
private static instance: CopBot;
1314
private _bot: Bot<Context>;
@@ -52,16 +53,18 @@ export class CopBot {
5253
const app = express();
5354
app.use(express.json());
5455
app.post(webhookPath, async (req, res) => {
55-
setImmediate(async () => {
56-
try {
57-
await webhookCallback(this._bot, 'express')(req, res);
58-
} catch (error: any) {
59-
logger.error(`Error processing update:${error}`);
60-
return;
61-
}
62-
});
56+
res.sendStatus(200);
57+
try {
58+
await webhookCallback(this._bot, 'express')(req, res);
59+
} catch (error: any) {
60+
logger.error(`Error processing update : ${error.message}`);
61+
return;
62+
}
63+
});
64+
app.get('/health', async (_, res) => {
65+
const isHealthy = await ServiceProvider.getInstance().healthCheck();
66+
res.status(isHealthy ? 200 : 500).send(isHealthy ? 'OK' : 'Database not reachable');
6367
});
64-
6568
const port = process.env.PORT || 3000;
6669
app.listen(port, async () => {
6770
logger.info(`Webhook server running on port ${port}`);
@@ -74,7 +77,7 @@ export class CopBot {
7477
try {
7578
if (!webhookInfo.url) {
7679
logger.warn('Webhook is not set. Trying to set the webhook...');
77-
await this._bot.api.setWebhook(webhookURL, { max_connections: 100 });
80+
await this._bot.api.setWebhook(webhookURL, { drop_pending_updates: true });
7881
webhookInfo = await this._bot.api.getWebhookInfo();
7982
logger.info(`Webhook set: ${webhookInfo.url}`);
8083
} else {
@@ -96,6 +99,7 @@ export class CopBot {
9699
};
97100

98101
await trySetWebhook();
102+
await startBot(mode);
99103
});
100104
} catch (err: any) {
101105
console.error('Error setting up webhook:', err);
@@ -112,6 +116,11 @@ export class CopBot {
112116
}
113117
async initial(): Promise<void> {
114118
new GenerateCommand(this._bot).generate();
119+
this._bot.use(
120+
limit({
121+
onLimitExceeded: (ctx) => ctx.reply('Too many requests! Please slow down.'),
122+
})
123+
);
115124
this._bot.on('my_chat_member', (ctx) => this.handleJoinNewChat(ctx));
116125
this._bot.on('message', (ctx) => this.handleMessage(ctx));
117126
this._bot.catch(async (error: BotError<Context>) => {
@@ -120,11 +129,6 @@ export class CopBot {
120129
}
121130
logger.error(`Bot error occurred: ${error.error}`);
122131
});
123-
this._bot.use(
124-
limit({
125-
onLimitExceeded: (ctx) => ctx.reply('Too many requests! Please slow down.'),
126-
})
127-
);
128132
await this.start();
129133
logger.info('Bot is running');
130134
}

src/database/ConnectionPool.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ export class ConnectionPool {
77
constructor() {
88
const connectionString = this.getConnectionString();
99
this._isProduction = Config.environment;
10-
this._pool = new Pool({
11-
connectionString,
12-
ssl: this._isProduction === 'production' ? { rejectUnauthorized: false } : false,
13-
});
10+
this._pool = this.initializePool(connectionString);
1411
}
1512
@Catch({
1613
message: 'Failed to connect to the database. Please check your credentials or network connection.',
@@ -20,20 +17,19 @@ export class ConnectionPool {
2017
async connect(): Promise<void> {
2118
try {
2219
const client = await this._pool.connect();
23-
client.release(); // Verify and release immediately
20+
client.release(); // Connection successful
2421
} catch (error: any) {
2522
console.error('Database connection error:', error.message);
2623
if (error.code === '3D000') {
2724
console.log(`Database does not exist. Creating database ${Config.database.databaseName}...`);
2825
await this.createDatabase();
2926
await this._pool.end(); // End the current pool connection
3027
const newConnectionString = this.getConnectionString();
31-
this._pool = new Pool({
32-
connectionString: newConnectionString,
33-
ssl: this._isProduction === 'production' ? { rejectUnauthorized: false } : false,
34-
});
28+
this._pool = this.initializePool(newConnectionString);
3529
console.log('Retrying connection after creating the database...');
3630
await this._pool.connect();
31+
} else {
32+
console.error('Unexpected error connecting to the database:', error);
3733
}
3834
}
3935
}
@@ -54,6 +50,9 @@ export class ConnectionPool {
5450
try {
5551
await client.query(`CREATE DATABASE "${databaseName}"`);
5652
console.log(`Database "${databaseName}" created successfully.`);
53+
} catch (error: any) {
54+
console.error('Failed to create database:', error.message);
55+
throw error; // Re-throw the error for better logging and troubleshooting
5756
} finally {
5857
await client.end();
5958
}
@@ -69,4 +68,10 @@ export class ConnectionPool {
6968
async close(): Promise<void> {
7069
await this._pool.end();
7170
}
71+
private initializePool(connectionString: string): Pool {
72+
return new Pool({
73+
connectionString,
74+
ssl: this._isProduction === 'production' ? { rejectUnauthorized: false } : false,
75+
});
76+
}
7277
}

src/service/database/ServiceProvider.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,23 @@ export class ServiceProvider {
4747
const client = await this.getPoolClint();
4848
return new UserService(client);
4949
}
50-
async getRulesService(){
51-
const client = await this.getPoolClint()
52-
return new GroupRuleService(client)
50+
async getRulesService() {
51+
const client = await this.getPoolClint();
52+
return new GroupRuleService(client);
53+
}
54+
async getWarnsService() {
55+
const clint = await this.getPoolClint();
56+
return new WarningDatabaseService(clint);
5357
}
54-
async getWarnsService(){
55-
const clint = await this.getPoolClint()
56-
return new WarningDatabaseService(clint)
58+
async healthCheck(): Promise<boolean> {
59+
try {
60+
const client = await this.getPoolClint();
61+
client.release();
62+
console.log('Database is healthy.');
63+
return true;
64+
} catch (err: any) {
65+
console.error('Database health check failed:', err.message);
66+
return false;
67+
}
5768
}
5869
}

0 commit comments

Comments
 (0)