Add counterparty requirements#853
Conversation
WalkthroughThis PR introduces configurable counterparty requirements (minimum account age and minimum completed orders) for order takers. It adds a schema field, enforcement in order-taking flows, a rejection message, new settings commands, environment variables, and localized text across all supported languages. ChangesCounterparty Requirements Feature
Estimated code review effort: 3 (Moderate) | ~25 minutes Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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.
Actionable comments posted: 11
🧹 Nitpick comments (3)
bot/modules/orders/takeOrder.ts (1)
161-188: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider adding unit tests for
meetsCounterpartyRequirements.This is a new enforcement gate affecting both buy/sell take flows, but no tests are included covering the age/order-count thresholds, the 0-disables-check behavior, or the missing-
counterparty_requirementsfallback.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@bot/modules/orders/takeOrder.ts` around lines 161 - 188, Add unit tests for meetsCounterpartyRequirements in takeOrder.ts to cover the new gate behavior in both buy/sell take flows. Verify the min_days_using_bot and min_completed_orders thresholds block and allow correctly, confirm 0 disables each check, and ensure the function returns true when orderCreator.counterparty_requirements is missing. Use mocks for getUserAge and messages.notMeetingRequirementsMessage to assert the right branch behavior.bot/modules/user/scenes/settings.ts (2)
154-155: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winLocal variable naming: use camelCase instead of snake_case.
min_days/min_ordersare local variables, not schema fields; per repo guidelines TS variables should use camelCase (e.g.minDays,minOrders).As per coding guidelines,
**/*.{ts,tsx}: "Use camelCase for functions and variables."Also applies to: 202-204
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@bot/modules/user/scenes/settings.ts` around lines 154 - 155, The local variables in the settings scene are using snake_case instead of the repo’s required camelCase style. Update the variable names in the parsing/validation logic in the settings flow, including the `min_days` and `min_orders` values around the `parseInt` checks in `settings.ts`, to use camelCase such as `minDays` and `minOrders`, and make sure any subsequent references in the same methods are renamed consistently.Source: Coding guidelines
144-243: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate logic between
counterpartyageandcounterpartyordershandlers.Both handlers share nearly identical parse/validate/cap/save/feedback structure, differing only in the target field, i18n keys, and env var. Extracting a shared factory would reduce future divergence risk (e.g. if validation logic needs to change, it'd need updating in two places).
♻️ Proposed refactor sketch
const createRequirementCommand = ( command: string, field: 'min_days_using_bot' | 'min_completed_orders', envVar: string, defaultMax: number, updatedI18nKey: string, paramName: string, ) => async (ctx: CommunityContext) => { try { await ctx.deleteMessage(); const state = ctx.scene.state as CommunityWizardState; if (ctx.message === undefined || !('text' in ctx.message)) throw new Error('ctx.message is undefined'); const [, raw] = ctx.message.text.trim().split(' '); const value = parseInt(raw, 10); if (isNaN(value) || value < 0) throw new Error('NotValidNumber'); const max = readNonNegativeInt(process.env[envVar], defaultMax); if (value > max) { state.error = { i18n: 'invalid_range', command, max }; return await updateMessage(ctx); } const user = state.user; if (!user.counterparty_requirements) { user.counterparty_requirements = { min_days_using_bot: 0, min_completed_orders: 0, }; } user.counterparty_requirements[field] = value; await user.save(); state.feedback = { i18n: updatedI18nKey, [paramName]: value }; await updateMessage(ctx); } catch (err) { logger.error(err); (ctx.scene.state as CommunityWizardState).error = { i18n: err instanceof Error && err.message === 'NotValidNumber' ? 'invalid_number' : 'generic_error', }; await updateMessage(ctx); } }; scene.command('counterpartyage', resetMessage, createRequirementCommand( '/counterpartyage', 'min_days_using_bot', 'MAX_COUNTERPARTY_AGE_REQUIREMENT', 30, 'counterpartyage_updated', 'days', )); scene.command('counterpartyorders', resetMessage, createRequirementCommand( '/counterpartyorders', 'min_completed_orders', 'MAX_COUNTERPARTY_ORDERS_REQUIREMENT', 10, 'counterpartyorders_updated', 'orders', ));🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@bot/modules/user/scenes/settings.ts` around lines 144 - 243, The `counterpartyage` and `counterpartyorders` handlers in `scene.command(...)` duplicate the same parse/validate/cap/save/feedback flow, so extract that shared logic into a reusable factory/helper and have both commands call it with their specific command name, target field, env var, max default, and i18n key. Use the existing `CommunityContext`, `CommunityWizardState`, `readNonNegativeInt`, and `updateMessage` flow as the shared core, and keep only the per-command differences in the thin wrappers to avoid future drift.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@bot/modules/user/scenes/settings.ts`:
- Around line 12-15: The helper readNonNegativeInt currently treats a blank
string as 0 because Number('') returns 0, so blank env vars like
MAX_COUNTERPARTY_AGE_REQUIREMENT will bypass the fallback. Update
readNonNegativeInt in settings.ts to explicitly treat undefined and
empty/whitespace-only strings as missing and return the fallback before calling
Number, while keeping the integer/non-negative validation for real values.
In `@locales/de.yaml`:
- Around line 254-257: The /settings help text is using escaped angle brackets,
so the placeholder names will show incorrectly under Markdown parsing. Update
the localized strings in the German locale for the counterparty requirement
commands to use raw <Tage> and <Aufträge> text, matching how bot/messages.ts
sends help with parse_mode: Markdown.
In `@locales/en.yaml`:
- Around line 258-262: The /help text in the locales/en.yaml entry is using
escaped placeholders for the counterparty commands, so ctx.reply with Markdown
will render them literally. Update the help strings for the /counterpartyage and
/counterpartyorders entries in the localized help content to use raw angle
brackets (<days> and <orders>) so the placeholders display consistently with the
rest of the help text.
In `@locales/es.yaml`:
- Around line 652-667: The Spanish locale strings in es.yaml mix voseo with the
file’s otherwise consistent tuteo. Update the messages in this block, especially
not_meeting_requirements and invalid_range, to use the same tuteo register as
the rest of the locale entries. Keep the wording natural and consistent with
existing strings like the ones used in the main bot flow, and verify any nearby
related messages in the same counterparty requirements section for the same
mismatch.
In `@locales/fa.yaml`:
- Around line 286-289: The help text in the locale entry for the /settings
commands is using escaped placeholders like <روز> and <سفارش> while
the message is sent with parse_mode Markdown, so update this block to use the
same raw angle-bracket placeholders used elsewhere. Make the change in the help
text content itself and mirror it in the duplicated help block below, keeping
the command names /counterpartyage, /counterpartyorders, and /resetrequirements
unchanged.
In `@locales/fr.yaml`:
- Around line 648-663: The order-flow strings in locales/fr.yaml mix formal and
informal address, so update the affected translation keys to match the existing
“tu” register used elsewhere in the order-taking flow. Specifically, revise
not_meeting_requirements and invalid_range to use informal phrasing consistent
with messages like the self-order warning, and keep the wording aligned with the
existing counterparty-related keys in this section.
In `@locales/it.yaml`:
- Around line 254-257: The settings help text in the locale entry contains
unescaped placeholder brackets, so the HTML-rendered `user_settings` view may
treat them as tags. Update the affected help strings in the `locales/it.yaml`
settings section so the `/setaddress` placeholder and the other command
placeholders use `<...>` consistently, matching the existing escaped
format used by the surrounding help text.
In `@locales/ko.yaml`:
- Around line 255-258: The `/help` text in the Korean locale is using escaped
angle-bracket placeholders, so update the help strings under the counterparty
requirements section to use raw placeholder syntax consistent with the rest of
the help output. Adjust the localized entries in the relevant translation block
so `/counterpartyage` and `/counterpartyorders` display placeholders like `<일>`
and `<주문>` when rendered by the help formatter.
In `@locales/pt.yaml`:
- Around line 255-258: The /help text in the localization entry uses escaped
angle brackets for the /counterpartyage and /counterpartyorders placeholders,
which will render incorrectly under Markdown parsing. Update the strings in the
Portuguese locale so the help content uses plain angle brackets for the
placeholder names, keeping the surrounding text in the same localized section.
In `@locales/ru.yaml`:
- Around line 253-256: The help text in the ru locale uses HTML entities for the
parameter placeholders, which will be shown literally under Markdown parsing.
Update the localized strings around the counterparty settings help entries in
locales/ru.yaml to use raw angle brackets for the placeholders in the same style
as the other /help lines, keeping the existing command names like
/counterpartyage, /counterpartyorders, and /resetrequirements unchanged.
In `@locales/uk.yaml`:
- Around line 253-256: The Ukrainian help text is using HTML-escaped placeholder
brackets, so `/counterpartyage` and `/counterpartyorders` will render
incorrectly under the Markdown help flow. Update the `help` entry in
`locales/uk.yaml` to use plain angle brackets for the placeholders, keeping the
existing command wording intact so `ctx.i18n.t('help')` in `bot/messages.ts`
displays them correctly.
---
Nitpick comments:
In `@bot/modules/orders/takeOrder.ts`:
- Around line 161-188: Add unit tests for meetsCounterpartyRequirements in
takeOrder.ts to cover the new gate behavior in both buy/sell take flows. Verify
the min_days_using_bot and min_completed_orders thresholds block and allow
correctly, confirm 0 disables each check, and ensure the function returns true
when orderCreator.counterparty_requirements is missing. Use mocks for getUserAge
and messages.notMeetingRequirementsMessage to assert the right branch behavior.
In `@bot/modules/user/scenes/settings.ts`:
- Around line 154-155: The local variables in the settings scene are using
snake_case instead of the repo’s required camelCase style. Update the variable
names in the parsing/validation logic in the settings flow, including the
`min_days` and `min_orders` values around the `parseInt` checks in
`settings.ts`, to use camelCase such as `minDays` and `minOrders`, and make sure
any subsequent references in the same methods are renamed consistently.
- Around line 144-243: The `counterpartyage` and `counterpartyorders` handlers
in `scene.command(...)` duplicate the same parse/validate/cap/save/feedback
flow, so extract that shared logic into a reusable factory/helper and have both
commands call it with their specific command name, target field, env var, max
default, and i18n key. Use the existing `CommunityContext`,
`CommunityWizardState`, `readNonNegativeInt`, and `updateMessage` flow as the
shared core, and keep only the per-command differences in the thin wrappers to
avoid future drift.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: c1cb1e76-aef4-45cf-9bec-8391fcdf00dc
📒 Files selected for processing (15)
.env-samplebot/messages.tsbot/modules/orders/takeOrder.tsbot/modules/user/scenes/settings.tslocales/de.yamllocales/en.yamllocales/es.yamllocales/fa.yamllocales/fr.yamllocales/it.yamllocales/ko.yamllocales/pt.yamllocales/ru.yamllocales/uk.yamlmodels/user.ts
| const readNonNegativeInt = (value: string | undefined, fallback: number) => { | ||
| const parsed = Number(value); | ||
| return Number.isInteger(parsed) && parsed >= 0 ? parsed : fallback; | ||
| }; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Blank env var silently sets max to 0 instead of falling back.
Number('') evaluates to 0, and Number.isInteger(0) is true, so readNonNegativeInt('', 30) returns 0 rather than the intended fallback. Given this repo's convention of leaving env vars blank to mean "use default" (e.g. DISABLE_LN_ADDRESS=, MONITOR_URL=''), an operator blanking MAX_COUNTERPARTY_AGE_REQUIREMENT would unexpectedly disable any positive requirement setting instead of falling back to 30.
🐛 Proposed fix
const readNonNegativeInt = (value: string | undefined, fallback: number) => {
- const parsed = Number(value);
+ if (value === undefined || value.trim() === '') return fallback;
+ const parsed = Number(value);
return Number.isInteger(parsed) && parsed >= 0 ? parsed : fallback;
};📝 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. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const readNonNegativeInt = (value: string | undefined, fallback: number) => { | |
| const parsed = Number(value); | |
| return Number.isInteger(parsed) && parsed >= 0 ? parsed : fallback; | |
| }; | |
| const readNonNegativeInt = (value: string | undefined, fallback: number) => { | |
| if (value === undefined || value.trim() === '') return fallback; | |
| const parsed = Number(value); | |
| return Number.isInteger(parsed) && parsed >= 0 ? parsed : fallback; | |
| }; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@bot/modules/user/scenes/settings.ts` around lines 12 - 15, The helper
readNonNegativeInt currently treats a blank string as 0 because Number('')
returns 0, so blank env vars like MAX_COUNTERPARTY_AGE_REQUIREMENT will bypass
the fallback. Update readNonNegativeInt in settings.ts to explicitly treat
undefined and empty/whitespace-only strings as missing and return the fallback
before calling Number, while keeping the integer/non-negative validation for
real values.
| Innerhalb von /settings kannst du Gegenpartei-Anforderungen konfigurieren: | ||
| /counterpartyage <Tage> - Legt das Mindestalter (in Tagen) für die Gegenpartei fest | ||
| /counterpartyorders <Aufträge> - Legt die Mindestanzahl abgeschlossener Aufträge für die Gegenpartei fest | ||
| /resetrequirements - Setzt die Anforderungen auf Standardwerte zurück |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
fd messages.ts
rg -n "'help'" -g '*.ts' -B5 -A10Repository: lnp2pBot/bot
Length of output: 364
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- bot/messages.ts outline ---'
ast-grep outline bot/messages.ts --view expanded || true
echo '--- search for help key usage ---'
rg -n "\"help\"|'help'|help:" bot/messages.ts bot -g '*.ts'
echo '--- search for parse_mode in message sending paths ---'
rg -n "parse_mode|sendMessage|replyWith|reply_text|reply_text|format" bot -g '*.ts'Repository: lnp2pBot/bot
Length of output: 15890
Use raw angle brackets in the /settings help text
bot/messages.ts sends help with parse_mode: 'Markdown', so <Tage> and <Aufträge> in locales/de.yaml:254-257 will render literally instead of as <Tage> / <Aufträge>.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@locales/de.yaml` around lines 254 - 257, The /settings help text is using
escaped angle brackets, so the placeholder names will show incorrectly under
Markdown parsing. Update the localized strings in the German locale for the
counterparty requirement commands to use raw <Tage> and <Aufträge> text,
matching how bot/messages.ts sends help with parse_mode: Markdown.
| While in /settings you can configure counterparty requirements: | ||
| /counterpartyage <days> - Sets the minimum account age (in days) required for the counterparty to take your orders | ||
| /counterpartyorders <orders> - Sets the minimum number of completed orders required for the counterparty | ||
| /resetrequirements - Resets counterparty requirements to default | ||
| /listorders - Use this command to list all your pending transactions |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the target locale block and surrounding context
sed -n '245,275p' locales/en.yaml
# Find the same counterparty help text in other locales
rg -n "counterpartyage|counterpartyorders|resetrequirements|listorders" locales -g '*.yaml'
# Find where the help text is rendered/sent and any parse_mode handling
rg -n "parse_mode|help.*send|sendMessage|/help|counterpartyage|counterpartyorders" -g '*.{ts,js,tsx,jsx,py,go,rs}' .Repository: lnp2pBot/bot
Length of output: 23206
Use raw angle brackets for /help placeholders locales/en.yaml:259-260
ctx.reply(..., { parse_mode: 'Markdown' }) will show <days> / <orders> literally; use <days> / <orders> here to match the rest of the help text.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@locales/en.yaml` around lines 258 - 262, The /help text in the
locales/en.yaml entry is using escaped placeholders for the counterparty
commands, so ctx.reply with Markdown will render them literally. Update the help
strings for the /counterpartyage and /counterpartyorders entries in the
localized help content to use raw angle brackets (<days> and <orders>) so the
placeholders display consistently with the rest of the help text.
| <strong>Requisitos de contraparte</strong> | ||
| Antigüedad mínima: ${min_days_using_bot} días | ||
| Órdenes mínimas completadas: ${min_completed_orders} | ||
|
|
||
| <strong># AYUDA</strong> | ||
| /setnpub <npub> - Configura la llave pública de Nostr. | ||
| /counterpartyage <días> - Establece la antigüedad mínima (en días) para la contraparte. | ||
| /counterpartyorders <órdenes> - Establece el mínimo de órdenes completadas para la contraparte. | ||
| /resetrequirements - Restablece los requisitos de contraparte al valor por defecto. | ||
| /exit - para salir del asistente. | ||
| not_meeting_requirements: No cumplís los requisitos de la contraparte para tomar esta orden. | ||
| counterpartyage_updated: Requisito de antigüedad de contraparte actualizado a ${days} días. | ||
| counterpartyorders_updated: Requisito de órdenes completadas de contraparte actualizado a ${orders}. | ||
| requirements_reset: Los requisitos de contraparte han sido restablecidos al valor por defecto. | ||
| invalid_number: Número inválido. | ||
| invalid_range: Valor inválido para ${command}, por favor elegí un número en el rango [0 - ${max}]. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Voseo forms inconsistent with rest of file (tuteo).
"No cumplís..." (line 662) and "elegí" (line 667) are voseo conjugations, while the rest of es.yaml consistently uses tuteo (e.g. "No puedes tomar tu propia orden", line 308). This reads as a jarring register switch for users.
💡 Proposed fix
-not_meeting_requirements: No cumplís los requisitos de la contraparte para tomar esta orden.
+not_meeting_requirements: No cumples los requisitos de la contraparte para tomar esta orden.
...
-invalid_range: Valor inválido para ${command}, por favor elegí un número en el rango [0 - ${max}].
+invalid_range: Valor inválido para ${command}, por favor elige un número en el rango [0 - ${max}].📝 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. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <strong>Requisitos de contraparte</strong> | |
| Antigüedad mínima: ${min_days_using_bot} días | |
| Órdenes mínimas completadas: ${min_completed_orders} | |
| <strong># AYUDA</strong> | |
| /setnpub <npub> - Configura la llave pública de Nostr. | |
| /counterpartyage <días> - Establece la antigüedad mínima (en días) para la contraparte. | |
| /counterpartyorders <órdenes> - Establece el mínimo de órdenes completadas para la contraparte. | |
| /resetrequirements - Restablece los requisitos de contraparte al valor por defecto. | |
| /exit - para salir del asistente. | |
| not_meeting_requirements: No cumplís los requisitos de la contraparte para tomar esta orden. | |
| counterpartyage_updated: Requisito de antigüedad de contraparte actualizado a ${days} días. | |
| counterpartyorders_updated: Requisito de órdenes completadas de contraparte actualizado a ${orders}. | |
| requirements_reset: Los requisitos de contraparte han sido restablecidos al valor por defecto. | |
| invalid_number: Número inválido. | |
| invalid_range: Valor inválido para ${command}, por favor elegí un número en el rango [0 - ${max}]. | |
| <strong>Requisitos de contraparte</strong> | |
| Antigüedad mínima: ${min_days_using_bot} días | |
| Órdenes mínimas completadas: ${min_completed_orders} | |
| <strong># AYUDA</strong> | |
| /setnpub <npub> - Configura la llave pública de Nostr. | |
| /counterpartyage <días> - Establece la antigüedad mínima (en días) para la contraparte. | |
| /counterpartyorders <órdenes> - Establece el mínimo de órdenes completadas para la contraparte. | |
| /resetrequirements - Restablece los requisitos de contraparte al valor por defecto. | |
| /exit - para salir del asistente. | |
| not_meeting_requirements: No cumples los requisitos de la contraparte para tomar esta orden. | |
| counterpartyage_updated: Requisito de antigüedad de contraparte actualizado a ${days} días. | |
| counterpartyorders_updated: Requisito de órdenes completadas de contraparte actualizado a ${orders}. | |
| requirements_reset: Los requisitos de contraparte han sido restablecidos al valor por defecto. | |
| invalid_number: Número inválido. | |
| invalid_range: Valor inválido para ${command}, por favor elige un número en el rango [0 - ${max}]. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@locales/es.yaml` around lines 652 - 667, The Spanish locale strings in
es.yaml mix voseo with the file’s otherwise consistent tuteo. Update the
messages in this block, especially not_meeting_requirements and invalid_range,
to use the same tuteo register as the rest of the locale entries. Keep the
wording natural and consistent with existing strings like the ones used in the
main bot flow, and verify any nearby related messages in the same counterparty
requirements section for the same mismatch.
| در /settings میتوانید الزامات طرف مقابل را تنظیم کنید: | ||
| /counterpartyage <روز> - حداقل سابقه (به روز) برای طرف مقابل | ||
| /counterpartyorders <سفارش> - حداقل تعداد سفارشهای تکمیل شده برای طرف مقابل | ||
| /resetrequirements - بازگرداندن الزامات به مقادیر پیشفرض |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the relevant translation block and nearby help text usage.
git ls-files 'locales/fa.yaml' 'locales/*.yaml' 'locales/*.yml' | sed -n '1,120p'
printf '\n--- fa.yaml around target lines ---\n'
sed -n '270,300p' locales/fa.yaml
printf '\n--- search for help rendering / parse mode references ---\n'
rg -n "parse_mode|help:" -S . --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**'
printf '\n--- compare angle-bracket usage in locales ---\n'
rg -n "<|<_[^>]+_>|<[^>]+>" locales -SRepository: lnp2pBot/bot
Length of output: 50368
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Find the code path that sends/prints the help text and whether it escapes HTML.
rg -n "counterpartyage|counterpartyorders|resetrequirements|/help" -S . --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**'
# If translations are stored in YAML only, inspect surrounding help keys in a representative locale.
fd -a 'en.yaml|en.yml|fa.yaml|fa.yml' locales .Repository: lnp2pBot/bot
Length of output: 13533
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map the translation file and locate the runtime path that emits the help text.
ast-grep outline locales/fa.yaml --view expanded || true
printf '\n--- exact target lines ---\n'
sed -n '280,295p' locales/fa.yaml
printf '\n--- runtime references for the help locale key/text ---\n'
rg -n "counterpartyage|counterpartyorders|resetrequirements|help:" -S . --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**'
printf '\n--- parse mode / escaping helpers ---\n'
rg -n "parse_mode|escapeHtml|escape_markdown|markdownv2|HTML" -S . --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**'Repository: lnp2pBot/bot
Length of output: 14749
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the exact help block and any usage of HTML entities in the same section.
nl -ba locales/fa.yaml | sed -n '278,292p'
printf '\n--- all entity-escaped placeholders in locales/fa.yaml ---\n'
rg -n "<[^&]+>" locales/fa.yaml -n -S
printf '\n--- nearby keys in other locales for the same command names ---\n'
for f in $(git ls-files 'locales/*.y*ml'); do
if rg -q "counterpartyage|counterpartyorders|resetrequirements" "$f"; then
echo "== $f =="
rg -n "counterpartyage|counterpartyorders|resetrequirements|<|<_" "$f" -n -S
fi
doneRepository: lnp2pBot/bot
Length of output: 190
🌐 Web query:
Telegram Bot API Markdown parse_mode HTML entities < display literally
💡 Result:
To display a literal < character in a Telegram Bot API message, the method depends on whether you are using MarkdownV2 or HTML parse modes [1][2][3]. For MarkdownV2: To display a literal < character (or any other reserved character) in MarkdownV2 mode, you must escape it with a preceding backslash (\) [2][4][5]. The required sequence is: \< In MarkdownV2, all 18 reserved characters (_, *, [, ], (, ), ~, `, >, #, +, -, =, |, {, }, ., !) must be escaped with a backslash when used in plain text [11][13]. If you place the character inside a pre or code block, only the backtick (`) and backslash (\) characters require escaping [4][5]. For HTML: To display a literal < character in HTML mode, you must replace it with the HTML entity [2][6][3]: < In HTML mode, the Telegram Bot API requires that all <, >, and & symbols that are not part of a valid HTML tag must be replaced with their corresponding HTML entities (<, >, and &) to ensure the message is parsed correctly [2][6][7]. Summary Table: Parse Mode | Syntax for literal < --- | --- MarkdownV2 | \< HTML | < Top results: [1][2][4][5]
Citations:
- 1: https://core.telegram.org/bots/api
- 2: https://docs.rs/teloxide/latest/teloxide/types/enum.ParseMode.html
- 3: https://core.telegram.org/bots/update56kabdkb12ibuisabdubodbasbdaosd
- 4: https://tgkit.io/markdown-v2-escaper/
- 5: https://botnamefinder.com/blog/telegram-markdownv2-escape-characters
- 6: https://docs.rs/teloxide-core/latest/teloxide_core/types/enum.ParseMode.html
- 7: https://tgrm.oss.hagever.com/types/Telegram.ParseMode.html
🌐 Web query:
Telegram Bot API Markdown parse mode does it decode HTML entities like < and >
💡 Result:
No, the Telegram Bot API "Markdown" and "MarkdownV2" parse modes do not decode HTML entities like < and > [1][2][3]. These parse modes are specifically designed to interpret their own unique syntax for text formatting (such as bold or italic) and do not process HTML entities [1][4][3]. When using "Markdown" or "MarkdownV2," any literal ampersands or entity-like strings will be treated as plain text unless they conflict with the specific formatting syntax of those modes [1][3]. In contrast, HTML entities are a specific feature of the "HTML" parse mode [1][2]. When using the "HTML" parse mode, the Telegram Bot API supports a limited set of named HTML entities (<, >, &, and ") and all numerical HTML entities [5][2][3]. In this mode, symbols like <, >, and & must be properly escaped using these entities to ensure the message is parsed correctly [2][3].
Citations:
- 1: https://core.telegram.org/bots/update56kabdkb12ibuisabdubodbasbdaosd
- 2: https://docs.rs/teloxide/latest/teloxide/types/enum.ParseMode.html
- 3: https://docs.rs/teloxide-core/latest/teloxide_core/types/enum.ParseMode.html
- 4: https://tgrm.oss.hagever.com/types/Telegram.ParseMode.html
- 5: https://grammy.dev/ref/types/parsemode
Use raw placeholders in the help text <روز> and <سفارش> are sent with parse_mode: 'Markdown', so Telegram will show the entities literally. Replace them with the same raw angle-bracket placeholders used elsewhere in this help text, including the duplicated help block below.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@locales/fa.yaml` around lines 286 - 289, The help text in the locale entry
for the /settings commands is using escaped placeholders like <روز> and
<سفارش> while the message is sent with parse_mode Markdown, so update this
block to use the same raw angle-bracket placeholders used elsewhere. Make the
change in the help text content itself and mirror it in the duplicated help
block below, keeping the command names /counterpartyage, /counterpartyorders,
and /resetrequirements unchanged.
| In /settings puoi configurare i requisiti della controparte: | ||
| /counterpartyage <giorni> - Imposta l'età minima (in giorni) richiesta per la controparte | ||
| /counterpartyorders <ordini> - Imposta il numero minimo di ordini completati richiesti per la controparte | ||
| /resetrequirements - Ripristina i requisiti ai valori predefiniti |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== relevant locale excerpt =="
nl -ba locales/it.yaml | sed -n '245,265p'
echo
echo "== search for related help text and /setaddress examples =="
rg -n --no-heading '/setaddress|counterpartyage|counterpartyorders|resetrequirements|/help' . --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**'
echo
echo "== locate locale usage/rendering code =="
rg -n --no-heading 'locales/it.yaml|yaml|parse_mode|MarkdownV2|HTML|help text|command help|/help' . --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**'Repository: lnp2pBot/bot
Length of output: 220
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== relevant locale excerpt =="
sed -n '245,265p' locales/it.yaml | cat -n
echo
echo "== search for related help text and examples =="
rg -n --no-heading '/setaddress|counterpartyage|counterpartyorders|resetrequirements|/help' . \
--glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**'
echo
echo "== locate locale usage/rendering code =="
rg -n --no-heading 'locales/it.yaml|parse_mode|MarkdownV2|HTML|help text|command help|/help' . \
--glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**'Repository: lnp2pBot/bot
Length of output: 23393
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== it.yaml context around the reviewed block =="
sed -n '640,660p' locales/it.yaml | cat -n
echo
echo "== help command implementation =="
sed -n '910,935p' bot/messages.ts | cat -n
echo
echo "== locale loading / interpolation path =="
rg -n --no-heading 'i18n|yaml|parse_mode: '"'"'Markdown'"'"'|ctx\.i18n\.t\(' . \
--glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**'Repository: lnp2pBot/bot
Length of output: 50370
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '60,105p' bot/modules/user/scenes/settings.ts | cat -nRepository: lnp2pBot/bot
Length of output: 2041
Escape the help placeholders in the HTML-rendered settings text. locales/it.yaml:251,255-256 should use <...> consistently; raw angle brackets in /setaddress will be treated as HTML tags in user_settings.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@locales/it.yaml` around lines 254 - 257, The settings help text in the locale
entry contains unescaped placeholder brackets, so the HTML-rendered
`user_settings` view may treat them as tags. Update the affected help strings in
the `locales/it.yaml` settings section so the `/setaddress` placeholder and the
other command placeholders use `<...>` consistently, matching the existing
escaped format used by the surrounding help text.
| /settings 안에서 거래 상대방 요구 사항을 설정할 수 있습니다: | ||
| /counterpartyage <일> - 거래 상대방의 최소 가입 기간(일)을 설정합니다 | ||
| /counterpartyorders <주문> - 거래 상대방의 최소 완료 주문 수를 설정합니다 | ||
| /resetrequirements - 요구 사항을 기본값으로 초기화합니다 |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the relevant section of locales/ko.yaml with line numbers.
sed -n '240,270p' locales/ko.yaml | cat -n
printf '\n----\n'
# Look for similar placeholder formatting in this locale file and nearby sibling locale files.
rg -n "<|<_|<[^=]" locales/ko.yaml locales/*.yaml | sed -n '1,120p'Repository: lnp2pBot/bot
Length of output: 14300
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Find where locale help text is consumed and whether HTML escaping is expected.
rg -n "help: \||counterpartyage|parse_mode|escapeHTML|html" -t js -t ts -t tsx -t yml -t yaml . | sed -n '1,200p'
printf '\n----\n'
# Inspect relevant i18n/message formatting code if present.
git ls-files | rg '(^|/)(src|lib|bot|locales|translations)/' | sed -n '1,200p'Repository: lnp2pBot/bot
Length of output: 178
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Search the repository for locale/message rendering and HTML parsing behavior.
rg -n "parse_mode|escapeHTML|html|counterpartyage|help: \|" . | sed -n '1,220p'
printf '\n----\n'
# List likely source files so the consumer of locales can be inspected next.
git ls-files | rg '(^|/)(src|lib|bot|locales|translations|app|commands)/|(^|/)(package\.json|README\.md)$' | sed -n '1,220p'Repository: lnp2pBot/bot
Length of output: 10104
Use raw angle-bracket placeholders in /help
/help is sent as Markdown, so <일> / <주문> will render literally instead of as <일> / <주문>. Use the same placeholder style as the rest of the help text.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@locales/ko.yaml` around lines 255 - 258, The `/help` text in the Korean
locale is using escaped angle-bracket placeholders, so update the help strings
under the counterparty requirements section to use raw placeholder syntax
consistent with the rest of the help output. Adjust the localized entries in the
relevant translation block so `/counterpartyage` and `/counterpartyorders`
display placeholders like `<일>` and `<주문>` when rendered by the help formatter.
| Dentro de /settings você pode configurar os requisitos de contraparte: | ||
| /counterpartyage <dias> - Define a antiguidade mínima (em dias) exigida para a contraparte | ||
| /counterpartyorders <ordens> - Define o número mínimo de ordens concluídas exigido para a contraparte | ||
| /resetrequirements - Redefine os requisitos para os valores padrão |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate help-message generation and parse_mode usage.
git ls-files | rg '(^|/)(settings|help|locales|bot|telegram).*\.ts$|(^|/).*\.tsx$|(^|/).*\.js$|(^|/).*\.py$|(^|/)locales/pt\.yaml$' || true
printf '\n== parse_mode references ==\n'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' 'parse_mode|parseMode|reply\(|replyText|editMessageText|sendMessage|/help|help:' .
printf '\n== pt.yaml help block ==\n'
sed -n '235,270p' locales/pt.yaml
printf '\n== surrounding code around message sending ==\n'
# Show only concise contexts for likely message-sending files if found.
for f in $(rg -l --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' 'parse_mode|parseMode|/help|help:' . | head -n 20); do
echo "--- $f ---"
sed -n '1,240p' "$f" | rg -n 'parse_mode|parseMode|/help|help:|reply\(|editMessageText|sendMessage|replyText' -n || true
doneRepository: lnp2pBot/bot
Length of output: 43409
Use plain angle brackets in the /help text. /help is sent with parse_mode: 'Markdown', so <dias> and <ordens> will render literally.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@locales/pt.yaml` around lines 255 - 258, The /help text in the localization
entry uses escaped angle brackets for the /counterpartyage and
/counterpartyorders placeholders, which will render incorrectly under Markdown
parsing. Update the strings in the Portuguese locale so the help content uses
plain angle brackets for the placeholder names, keeping the surrounding text in
the same localized section.
| В /settings можно настроить требования к контрагенту: | ||
| /counterpartyage <дней> - Устанавливает минимальный возраст (в днях) для контрагента | ||
| /counterpartyorders <ордеров> - Устанавливает минимальное количество выполненных ордеров для контрагента | ||
| /resetrequirements - Сбрасывает требования до значений по умолчанию |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'Files mentioning help command or parse_mode:\n'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \
'(parse_mode|ParseMode|/help|help:)' .
printf '\nPotential locale/message senders:\n'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \
'(locales/ru\.yaml|locales/.*\.yaml|t\(|translate|i18n|replyWith|sendMessage|ctx\.reply|help)' .Repository: lnp2pBot/bot
Length of output: 50369
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Narrow search to likely bot source files and locale references
fd -a -t f . .Repository: lnp2pBot/bot
Length of output: 9367
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Find the /help handler and the locale loading path.
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \
'(/help|help:|parse_mode|ParseMode|i18n|locales)' .Repository: lnp2pBot/bot
Length of output: 50368
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate the help command implementation and how localized help text is sent.
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \
'(/help|help:|parse_mode|ParseMode|sendMessage|replyWithHTML|replyWithMarkdown|ctx\.reply\()' .Repository: lnp2pBot/bot
Length of output: 34328
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Search for the specific locale key and any handler that renders it.
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \
'help:\s*$|/help|locales/ru\.yaml|counterpartyage|counterpartyorders|setaddress|parse_mode' .Repository: lnp2pBot/bot
Length of output: 15595
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# List likely source files so the help handler can be inspected in a follow-up.
git ls-files | rg '(^|/)(src|app|bot|commands|locales)/.*\.(ts|js|tsx|jsx|yaml|yml)$'Repository: lnp2pBot/bot
Length of output: 1941
Replace the HTML entities in locales/ru.yaml. /help is sent with parse_mode: 'Markdown', so <дней> and <ордеров> will show up literally; use raw angle brackets to match the other help lines.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@locales/ru.yaml` around lines 253 - 256, The help text in the ru locale uses
HTML entities for the parameter placeholders, which will be shown literally
under Markdown parsing. Update the localized strings around the counterparty
settings help entries in locales/ru.yaml to use raw angle brackets for the
placeholders in the same style as the other /help lines, keeping the existing
command names like /counterpartyage, /counterpartyorders, and /resetrequirements
unchanged.
| У /settings можна налаштувати вимоги до контрагента: | ||
| /counterpartyage <днів> - Встановлює мінімальний вік (у днях) для контрагента | ||
| /counterpartyorders <ордерів> - Встановлює мінімальну кількість виконаних ордерів для контрагента | ||
| /resetrequirements - Скидає вимоги до значень за замовчуванням |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Find help command implementation and parse_mode usage.
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/.git/**' \
'parse_mode|ParseMode|/help|help:' .
# Locate locale references for the Ukrainian help text.
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/.git/**' \
'locales/uk.yaml|counterpartyage|counterpartyorders|resetrequirements|setaddress' .
# Show concise file list for likely command handlers and locale files.
git ls-files | rg '(^|/)(locales/uk\.yaml|.*help.*|.*command.*|.*bot.*|.*telegram.*|.*locale.*)$'Repository: lnp2pBot/bot
Length of output: 21373
Use plain angle brackets in the Ukrainian /help text
bot/messages.ts sends ctx.i18n.t('help') with parse_mode: 'Markdown', so <днів> / <ордерів> will render literally instead of as placeholders.
Proposed fix
- /counterpartyage <днів> - Встановлює мінімальний вік (у днях) для контрагента
- /counterpartyorders <ордерів> - Встановлює мінімальну кількість виконаних ордерів для контрагента
+ /counterpartyage <днів> - Встановлює мінімальний вік (у днях) для контрагента
+ /counterpartyorders <ордерів> - Встановлює мінімальну кількість виконаних ордерів для контрагента📝 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. Thoroughly test & benchmark the code to ensure it meets the requirements.
| У /settings можна налаштувати вимоги до контрагента: | |
| /counterpartyage <днів> - Встановлює мінімальний вік (у днях) для контрагента | |
| /counterpartyorders <ордерів> - Встановлює мінімальну кількість виконаних ордерів для контрагента | |
| /resetrequirements - Скидає вимоги до значень за замовчуванням | |
| У /settings можна налаштувати вимоги до контрагента: | |
| /counterpartyage <днів> - Встановлює мінімальний вік (у днях) для контрагента | |
| /counterpartyorders <ордерів> - Встановлює мінімальну кількість виконаних ордерів для контрагента | |
| /resetrequirements - Скидає вимоги до значень за замовчуванням |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@locales/uk.yaml` around lines 253 - 256, The Ukrainian help text is using
HTML-escaped placeholder brackets, so `/counterpartyage` and
`/counterpartyorders` will render incorrectly under the Markdown help flow.
Update the `help` entry in `locales/uk.yaml` to use plain angle brackets for the
placeholders, keeping the existing command wording intact so
`ctx.i18n.t('help')` in `bot/messages.ts` displays them correctly.
Continues #827
Summary by CodeRabbit
New Features
Bug Fixes
Documentation