- Notifications
You must be signed in to change notification settings - Fork 1
Bot #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bot #37
Conversation
Fix bug in AuthServices.refresh
Add endpoint to set on call status on/off
Update CHANGELOG
* Bot (#20) * Add chatbot flows, Add bot.qr.png to .gitignore * Fetch bot menus and answers from DB * Auth fix (#22) * Fix double refresh hanging the server * 🧹 Clean up * Add console.error() to exitLog * Testing (#24) * Add role to player on PlayersDAO.upsert * Add tests * Alquimia (#25) * Add alquimia payment verification * Update seed.sql * Comment out services.old.ts * Remove Player from DepositDAO.create() * Remove Player from DepositDAO.create() * Alquimia (#26) * Fix deposit test * Look for deposits 24 hours into the past * Fix tests * Update deposit on /transactions/deposit/:id (#27) * Alquimia sync (#28) * Update deposit on /transactions/deposit/:id * Sync deposits from Alquimia DB to local on FinanceServices.verifyPayment() * Set deposit status to rejected if not found * Change integer incremental IDs to string UUIDs * Modify endpoints to use only GET and POST methods (#29) * Modify endpoints to use only GET and POST methods * Misc (#30) * Add endpoint to show Alquimia bank details, Configure cors for development, Update deposit instead of create when existing tracking key found in request * Add ALLOWED_ORIGIN to .env * origin source * lint --------- Co-authored-by: Alpha Dev <alphadev@MacBook-Pro-de-Gonzalo.local> --------- Co-authored-by: Alpha Dev <alphadev@MacBook-Pro-de-Gonzalo.local> --------- Co-authored-by: Alpha Dev <alphadev@MacBook-Pro-de-Gonzalo.local> * Deposit flow (#31) * Create CasinoCoinsService to handle coin transfers, Improve FinanceService.confirmDeposit error handling, Remove paid_at and coins_transfered from Deposit model, add casinoTokenService.login() call to seed.ts, Improve Notify error handling, Improve TransactionsDAO error handling, Turn Player.balance_currency into a required field, Swap Transaction.status with Transaction.ok * Update .gitignore * Fix bug in FinanceServices.alquimiaDepositLookup (#32) * Fix bug in FinanceServices.alquimiaDepositLookup * Improve bank-account request validator * Fix bank-account test * fix cashout validation * Add rate limiter to POST /transactions/deposit/:id? (#33) * Deposit (#34) * Improve DepositDAO.authorizeConfirmation, Give agent role permission to confirm deposit, Remove TransactionsController.deleteDeposit, Fixed finalizeDeposit logic to not send coins on confirmed deposits, Add optional id to GET /agent/depoists to retreive individual depoist, Rename /agent/deposits/complete to /agent/pending/depoists * Update README * Payment throttling (#35) * Update dependecies, Restrict withdrawals to 1 every 24 hours * Update CHANGELOG * update bankNumber validation * Logging (#36) * Add logtailLogger, Fix bug in AuthServices.refresh * Update CHANGELOG * Update CONFIG.LOG.CODES * Bot (#37) * Add logtailLogger, Fix bug in AuthServices.refresh * Update CHANGELOG * Update CONFIG.LOG.CODES * Update USER_ALREADY_EXISTS error description * Add on call bot flows, Add endpoint to set on call status on/off * Rename table BOT_MESSAGES to BOT_FLOWS * Update REAMDE, Update CHANGELOG * Improve seed.ts * Update CHANGELOG * Add GET /agent/on-call endpoint * Update README with on call endpoints * Add tests for on-call endpoints * Move test agent creds to .env --------- Co-authored-by: AlphaDev87 <155021991+AlphaDev87@users.noreply.github.com> --------- Co-authored-by: Rodrigo Alvarez <65652568+alvarezrrj@users.noreply.github.com> Co-authored-by: Alpha Dev <alphadev@MacBook-Pro-de-Gonzalo.local>
| @coderabbitai review |
WalkthroughThe recent update introduces a new on-call feature for agents, allowing them to set and view their on-call status through newly added API endpoints. The database schema and related data access objects have been adjusted accordingly, including renaming tables and adding new columns. Tests ensure the functionality works as expected, and the frontend now includes routes for easy interaction with these new features. Changes
Recent Review DetailsConfiguration used: CodeRabbit UI Files ignored due to path filters (1)
Files selected for processing (14)
Additional comments not posted (12)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configration File ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
| static async setOnCallBotFlow(active: boolean): Promise<void> { | ||
| await BotFlowsDAO.setOnCall(active); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure robustness by adding error handling for the setOnCallBotFlow method.
static async setOnCallBotFlow(active: boolean): Promise<void> { + try { await BotFlowsDAO.setOnCall(active); + } catch (error) { + console.error("Failed to set on-call status:", error); + throw new CustomError({ code: "database_error", description: "Failed to update on-call status" }); + } }Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
| static async setOnCallBotFlow(active: boolean): Promise<void> { | |
| await BotFlowsDAO.setOnCall(active); | |
| } | |
| static async setOnCallBotFlow(active: boolean): Promise<void> { | |
| try { | |
| await BotFlowsDAO.setOnCall(active); | |
| } catch (error) { | |
| console.error("Failed to set on-call status:", error); | |
| throw new CustomError({ code: "database_error", description: "Failed to update on-call status" }); | |
| } | |
| } |
| static async getOnCallStatus(): Promise<boolean> { | ||
| const botFlow = await BotFlowsDAO.findOnCallFlow(); | ||
| | ||
| return !!botFlow; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add error handling to the getOnCallStatus method to improve reliability.
static async getOnCallStatus(): Promise<boolean> { + try { const botFlow = await BotFlowsDAO.findOnCallFlow(); + return !!botFlow; + } catch (error) { + console.error("Failed to retrieve on-call status:", error); + throw new CustomError({ code: "database_error", description: "Failed to retrieve on-call status" }); + } }Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
| static async getOnCallStatus(): Promise<boolean> { | |
| const botFlow = await BotFlowsDAO.findOnCallFlow(); | |
| return !!botFlow; | |
| } | |
| static async getOnCallStatus(): Promise<boolean> { | |
| try { | |
| const botFlow = await BotFlowsDAO.findOnCallFlow(); | |
| return !!botFlow; | |
| } catch (error) { | |
| console.error("Failed to retrieve on-call status:", error); | |
| throw new CustomError({ code: "database_error", description: "Failed to retrieve on-call status" }); | |
| } | |
| } |
| for (let i = 1; i < (regularFlow.menus as string[][]).length; i++) { | ||
| // @ts-ignore | ||
| const flow = createSubMenu(regularFlow.menus[i], regularFlow.messages[i]); | ||
| submenus.push(flow); | ||
| } | ||
| for (let i = 1; i < (onCallFlow.menus as string[][][]).length; i++) { | ||
| // @ts-ignore | ||
| const flow = createSubMenu(onCallFlow.menus[i], onCallFlow.messages[i]); | ||
| onCallSubmenus.push(flow); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider removing @ts-ignore and properly typing the variables to avoid potential runtime errors.
| .addAction(async (_ctx, { flowDynamic }) => { | ||
| const weAreOnCall = await BotFlowsDAO.findOnCallFlow(); | ||
| // @ts-ignore | ||
| const mainMenu = weAreOnCall ? onCallFlow.menus[0] : regularFlow.menus[0]; | ||
| await flowDynamic(mainMenu.join("\n")); | ||
| }) | ||
| .addAction( | ||
| { capture: true }, | ||
| async (ctx, { gotoFlow, fallBack, state }) => { | ||
| const mainMenuOptions = botMenus[0].filter((option) => | ||
| const weAreOnCall = await BotFlowsDAO.findOnCallFlow(); | ||
| // @ts-ignore | ||
| const menus = ( | ||
| weAreOnCall ? onCallFlow.menus : regularFlow.menus | ||
| ) as string[][]; | ||
| const mainMenuOptions = menus[0].filter((option) => | ||
| /\*\d+/.test(option), | ||
| ); | ||
| const subflows = weAreOnCall ? onCallSubmenus : submenus; | ||
| | ||
| const choice = Math.round(Number(ctx.body.trim())); | ||
| | ||
| if (choice > 0 && choice <= mainMenuOptions.length) { | ||
| await gotoFlow(submenus[choice - 1]); | ||
| await gotoFlow(subflows[choice - 1]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add error handling to asynchronous operations in the main menu logic to prevent unhandled promise rejections.
.addAction(async (_ctx, { flowDynamic }) => { + try { const weAreOnCall = await BotFlowsDAO.findOnCallFlow(); const mainMenu = weAreOnCall ? onCallFlow.menus[0] : regularFlow.menus[0]; await flowDynamic(mainMenu.join("\n")); + } catch (error) { + console.error("Failed to fetch or process main menu:", error); + throw new CustomError({ code: "flow_error", description: "Failed to process main menu" }); + } })Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
| .addAction(async (_ctx, { flowDynamic }) => { | |
| const weAreOnCall = await BotFlowsDAO.findOnCallFlow(); | |
| // @ts-ignore | |
| const mainMenu = weAreOnCall ? onCallFlow.menus[0] : regularFlow.menus[0]; | |
| await flowDynamic(mainMenu.join("\n")); | |
| }) | |
| .addAction( | |
| { capture: true }, | |
| async (ctx, { gotoFlow, fallBack, state }) => { | |
| const mainMenuOptions = botMenus[0].filter((option) => | |
| const weAreOnCall = await BotFlowsDAO.findOnCallFlow(); | |
| // @ts-ignore | |
| const menus = ( | |
| weAreOnCall ? onCallFlow.menus : regularFlow.menus | |
| ) as string[][]; | |
| const mainMenuOptions = menus[0].filter((option) => | |
| /\*\d+/.test(option), | |
| ); | |
| const subflows = weAreOnCall ? onCallSubmenus : submenus; | |
| const choice = Math.round(Number(ctx.body.trim())); | |
| if (choice > 0 && choice <= mainMenuOptions.length) { | |
| await gotoFlow(submenus[choice - 1]); | |
| await gotoFlow(subflows[choice - 1]); | |
| .addAction(async (_ctx, { flowDynamic }) => { | |
| try { | |
| const weAreOnCall = await BotFlowsDAO.findOnCallFlow(); | |
| // @ts-ignore | |
| const mainMenu = weAreOnCall ? onCallFlow.menus[0] : regularFlow.menus[0]; | |
| await flowDynamic(mainMenu.join("\n")); | |
| } catch (error) { | |
| console.error("Failed to fetch or process main menu:", error); | |
| throw new CustomError({ code: "flow_error", description: "Failed to process main menu" }); | |
| } | |
| }) | |
| .addAction( | |
| { capture: true }, | |
| async (ctx, { gotoFlow, fallBack, state }) => { | |
| const weAreOnCall = await BotFlowsDAO.findOnCallFlow(); | |
| // @ts-ignore | |
| const menus = ( | |
| weAreOnCall ? onCallFlow.menus : regularFlow.menus | |
| ) as string[][]; | |
| const mainMenuOptions = menus[0].filter((option) => | |
| /\*\d+/.test(option), | |
| ); | |
| const subflows = weAreOnCall ? onCallSubmenus : submenus; | |
| const choice = Math.round(Number(ctx.body.trim())); | |
| if (choice > 0 && choice <= mainMenuOptions.length) { | |
| await gotoFlow(subflows[choice - 1]); |
| export class BotFlowsDAO { | ||
| static async findOnCallFlow(): Promise<BotFlow | null> { | ||
| try { | ||
| return await prisma.botFlow.findFirst({ | ||
| where: { on_call: true, active: true }, | ||
| }); | ||
| } catch (e) { | ||
| throw e; | ||
| } finally { | ||
| prisma.$disconnect(); | ||
| } | ||
| } | ||
| static async setOnCall(active: boolean): Promise<void> { | ||
| try { | ||
| await prisma.botFlow.updateMany({ | ||
| where: { on_call: true }, | ||
| data: { active }, | ||
| }); | ||
| } catch (e) { | ||
| throw e; | ||
| } finally { | ||
| prisma.$disconnect(); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using context management for Prisma connections to ensure cleaner and safer handling of database connections.
- prisma.$disconnect(); + // Use Prisma middleware or context techniques for connection managementCommittable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
| export class BotFlowsDAO { | |
| static async findOnCallFlow(): Promise<BotFlow | null> { | |
| try { | |
| return await prisma.botFlow.findFirst({ | |
| where: { on_call: true, active: true }, | |
| }); | |
| } catch (e) { | |
| throw e; | |
| } finally { | |
| prisma.$disconnect(); | |
| } | |
| } | |
| static async setOnCall(active: boolean): Promise<void> { | |
| try { | |
| await prisma.botFlow.updateMany({ | |
| where: { on_call: true }, | |
| data: { active }, | |
| }); | |
| } catch (e) { | |
| throw e; | |
| } finally { | |
| prisma.$disconnect(); | |
| } | |
| } | |
| export class BotFlowsDAO { | |
| static async findOnCallFlow(): Promise<BotFlow | null> { | |
| try { | |
| return await prisma.botFlow.findFirst({ | |
| where: { on_call: true, active: true }, | |
| }); | |
| } catch (e) { | |
| throw e; | |
| } finally { | |
| // Use Prisma middleware or context techniques for connection management | |
| } | |
| } | |
| static async setOnCall(active: boolean): Promise<void> { | |
| try { | |
| await prisma.botFlow.updateMany({ | |
| where: { on_call: true }, | |
| data: { active }, | |
| }); | |
| } catch (e) { | |
| throw e; | |
| } finally { | |
| // Use Prisma middleware or context techniques for connection management | |
| } | |
| } |
| - `seed.ts` now tries to find users on db before requesting details. | ||
| - `seed.ts` now inserts bot flows into db. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Start sentences with an uppercase letter in the changelog for consistency and professionalism.
- `seed.ts` now tries to find users on db before requesting details. + `Seed.ts` now tries to find users on db before requesting details. - `seed.ts` now inserts bot flows into db. + `Seed.ts` now inserts bot flows into db.Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
| - `seed.ts` now tries to find users on db before requesting details. | |
| - `seed.ts` now inserts bot flows into db. | |
| - `Seed.ts` now tries to find users on db before requesting details. | |
| - `Seed.ts` now inserts bot flows into db. |
| static async setOnCallBotFlow(req: Req, res: Res, next: NextFn) { | ||
| try { | ||
| const { active } = req.body; | ||
| | ||
| await AgentServices.setOnCallBotFlow(active); | ||
| | ||
| res.status(OK).send(); | ||
| } catch (error) { | ||
| next(error); | ||
| } | ||
| } | ||
| | ||
| static async getOnCallStatus(_req: Req, res: Res, next: NextFn) { | ||
| try { | ||
| const onCall: boolean = await AgentServices.getOnCallStatus(); | ||
| | ||
| res.status(OK).json(apiResponse(onCall)); | ||
| } catch (error) { | ||
| next(error); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add API documentation comments to the new methods for better clarity and maintainability.
+ /** + * Sets the on-call bot flow based on the active status. + * @param req The request object. + * @param res The response object. + * @param next The next middleware function. + */ + /** + * Retrieves the current on-call status. + * @param req The request object. + * @param res The response object. + * @param next The next middleware function. + */Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
| static async setOnCallBotFlow(req: Req, res: Res, next: NextFn) { | |
| try { | |
| const { active } = req.body; | |
| await AgentServices.setOnCallBotFlow(active); | |
| res.status(OK).send(); | |
| } catch (error) { | |
| next(error); | |
| } | |
| } | |
| static async getOnCallStatus(_req: Req, res: Res, next: NextFn) { | |
| try { | |
| const onCall: boolean = await AgentServices.getOnCallStatus(); | |
| res.status(OK).json(apiResponse(onCall)); | |
| } catch (error) { | |
| next(error); | |
| } | |
| } | |
| /** | |
| * Sets the on-call bot flow based on the active status. | |
| * @param req The request object. | |
| * @param res The response object. | |
| * @param next The next middleware function. | |
| */ | |
| static async setOnCallBotFlow(req: Req, res: Res, next: NextFn) { | |
| try { | |
| const { active } = req.body; | |
| await AgentServices.setOnCallBotFlow(active); | |
| res.status(OK).send(); | |
| } catch (error) { | |
| next(error); | |
| } | |
| } | |
| /** | |
| * Retrieves the current on-call status. | |
| * @param req The request object. | |
| * @param res The response object. | |
| * @param next The next middleware function. | |
| */ | |
| static async getOnCallStatus(_req: Req, res: Res, next: NextFn) { | |
| try { | |
| const onCall: boolean = await AgentServices.getOnCallStatus(); | |
| res.status(OK).json(apiResponse(onCall)); | |
| } catch (error) { | |
| next(error); | |
| } | |
| } |
Description
Algunos cambios para que el bot use distintos flujos dependiendo de si alguien está de guardia
Mejoras en seed.ts:
/src/chatbot/messages.ts