Skip to content

Commit ae82067

Browse files
committed
feat(decorators): implement Catch decorator for centralized error handling in async methods
- Add `Catch` decorator: - Handles errors in decorated asynchronous methods. - Supports custom error responses via the `ErrorResponse` type. - Integrates `grammy` context (`Context`) to send user-friendly error messages in bot interactions. - Logs errors with detailed metadata, including the target class, method, and error category. - Automatically handles specific errors (e.g., `bot was kicked`) by cleaning up group data via the `GroupService`. - Utilize `ServiceProvider` to retrieve necessary services dynamically. - Improve system reliability by ensuring consistent error handling and user feedback in case of failures.
1 parent a02deef commit ae82067

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

src/decorators/Catch.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { Context } from 'grammy';
2+
import { ErrorResponse } from '../types/ResponseTypes';
3+
import logger from '../utils/logger';
4+
import { ServiceProvider } from '../service/database/ServiceProvider';
5+
export function Catch(customResponse?: ErrorResponse) {
6+
return function (target: any, propKey: string, descriptor: PropertyDescriptor) {
7+
const originalMethod = descriptor.value;
8+
descriptor.value = async function (...args: any[]) {
9+
const ctx: Context = (this as any)?.ctx || args[0];
10+
try {
11+
return await originalMethod.apply(this, args);
12+
} catch (error: any) {
13+
if (error.error_code === 403 && error.description.includes('bot was kicked')) {
14+
const chatId = error.payload?.chat_id;
15+
logger.warn(`[Warning] Bot was kicked from a group (chat_id: ${error.payload.chat_id}). Skipping.`);
16+
const service = ServiceProvider.getInstance();
17+
const groupService = await service.getGroupService();
18+
await groupService.delete(chatId);
19+
return;
20+
}
21+
// Custom response or default error message
22+
const errorResponse: ErrorResponse = customResponse || {
23+
message: error.message,
24+
statusCode: error.statusCode || 500,
25+
category: 'General',
26+
};
27+
logger.error(`[Category: ${errorResponse.category}] Error in ${target.constructor.name}.${propKey}(): ${error.message}`);
28+
// Send the error message to the user (if context is available)
29+
if (ctx && typeof ctx.reply === 'function') {
30+
await ctx.reply(errorResponse.message);
31+
}
32+
throw error;
33+
}
34+
};
35+
36+
return descriptor;
37+
};
38+
}

0 commit comments

Comments
 (0)