feat: add support for failed withdrawal payment notifications with retry options and localization Summary#793
feat: add support for failed withdrawal payment notifications with retry options and localization Summary#793Matobi98 wants to merge 1 commit intolnp2pBot:mainfrom
Conversation
…try options and localization
WalkthroughThis PR refines pending payment handling for earnings and withdrawals by filtering expired invoices from duplication checks, adding inline "withdraw earnings" action buttons to failure and expiration notifications, and introducing a specialized Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
jobs/pending_payments.ts (1)
198-216:⚠️ Potential issue | 🟠 MajorMissing
returnafter the expired-invoice notification — fall-through causes duplicate user message and a misleading error log.Unlike the analogous expired-invoice branch in
attemptPendingPayments(lines 61–70), this block doesn'treturnafter sending the message. Execution continues into the community fetch and theelsebranch (becausepayment.confirmed_atis falsy on an expired-invoice object):
pending.last_erroris set to'PAYMENT_FAILED'and aWithdraw failed after N attemptserror is logged, even though the real cause is expiration.- If this happens on the attempt where
pending.attempts >= PAYMENT_ATTEMPTS, the user receives two Telegram messages (invoice_expired_earningsfollowed bypending_payment_failed_earnings), both carrying the samewithdraw_earningsinline button — a confusing UX that this PR amplifies by adding the second button.🛠️ Proposed fix
if (!!payment && payment.is_expired) { pending.is_invoice_expired = true; - await bot.telegram.sendMessage( + await bot.telegram.sendMessage( user.tg_id, i18nCtx.t('invoice_expired_earnings'), { reply_markup: { inline_keyboard: [ [ { text: i18nCtx.t('withdraw_earnings'), callback_data: `withdrawEarnings_${pending.community_id}`, }, ], ], }, }, ); + return; }Note that
pending.save()will still run infinally, sois_invoice_expired = trueis persisted as intended.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@jobs/pending_payments.ts` around lines 198 - 216, The expired-invoice branch is missing a return, so after setting pending.is_invoice_expired and calling bot.telegram.sendMessage it falls through and executes the failure/else logic; fix by adding an early return immediately after the bot.telegram.sendMessage call in the block that sets pending.is_invoice_expired so execution exits the surrounding function (ensuring pending.save() in the finally still runs) to prevent setting pending.last_error, logging a PAYMENT_FAILED, and sending the duplicate pending_payment_failed_earnings message.
🧹 Nitpick comments (1)
jobs/pending_payments.ts (1)
200-214: Extract the duplicated "withdraw earnings" inline keyboard.The same
reply_markupobject is constructed in both notification paths. A small helper keeps the two flows in sync if the button text/callback shape ever changes.♻️ Suggested helper
const withdrawEarningsKeyboard = (i18nCtx: I18nContext, communityId: unknown) => ({ reply_markup: { inline_keyboard: [[ { text: i18nCtx.t('withdraw_earnings'), callback_data: `withdrawEarnings_${communityId}`, }, ]], }, });Then use it at both call sites:
await bot.telegram.sendMessage( user.tg_id, i18nCtx.t('invoice_expired_earnings'), withdrawEarningsKeyboard(i18nCtx, pending.community_id), );Also applies to: 257-274
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@jobs/pending_payments.ts` around lines 200 - 214, Extract the duplicated reply_markup into a small helper (e.g., withdrawEarningsKeyboard) that accepts (i18nCtx, communityId) and returns the inline keyboard object; replace the inline reply_markup passed to bot.telegram.sendMessage in the invoice_expired_earnings path (the sendMessage call using user.tg_id and i18nCtx.t('invoice_expired_earnings')) and the other sendMessage call at the other location (lines ~257-274) to use withdrawEarningsKeyboard(i18nCtx, pending.community_id) so both flows share the same button text and callback_data construction.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@jobs/pending_payments.ts`:
- Around line 198-216: The expired-invoice branch is missing a return, so after
setting pending.is_invoice_expired and calling bot.telegram.sendMessage it falls
through and executes the failure/else logic; fix by adding an early return
immediately after the bot.telegram.sendMessage call in the block that sets
pending.is_invoice_expired so execution exits the surrounding function (ensuring
pending.save() in the finally still runs) to prevent setting pending.last_error,
logging a PAYMENT_FAILED, and sending the duplicate
pending_payment_failed_earnings message.
---
Nitpick comments:
In `@jobs/pending_payments.ts`:
- Around line 200-214: Extract the duplicated reply_markup into a small helper
(e.g., withdrawEarningsKeyboard) that accepts (i18nCtx, communityId) and returns
the inline keyboard object; replace the inline reply_markup passed to
bot.telegram.sendMessage in the invoice_expired_earnings path (the sendMessage
call using user.tg_id and i18nCtx.t('invoice_expired_earnings')) and the other
sendMessage call at the other location (lines ~257-274) to use
withdrawEarningsKeyboard(i18nCtx, pending.community_id) so both flows share the
same button text and callback_data construction.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: c79f792a-69ac-4b64-afe7-fa1a8076e002
📒 Files selected for processing (12)
bot/modules/community/scenes.tsjobs/pending_payments.tslocales/de.yamllocales/en.yamllocales/es.yamllocales/fa.yamllocales/fr.yamllocales/it.yamllocales/ko.yamllocales/pt.yamllocales/ru.yamllocales/uk.yaml
Summary
When a community earnings withdrawal fails (expired invoice or repeated payment failure), the bot now:
- Sends a dedicated notification instead of the generic order payment failure message
Changes
jobs/pending_payments.ts: separate notification path for community earnings failures with inline retry buttonbot/modules/community/scenes.ts: filter outis_invoice_expired: trueinvoices from the pending payments querylocales/*.yaml(10 languages): newpending_payment_failed_earningsandwithdraw_earningskeysTest plan
withdrawEarnings_<community_id>callbackpending_payment_failedmessage still works for regular order paymentsSummary by CodeRabbit
Bug Fixes
New Features