Skip to content

feat: allow /block and /unblock by numeric Telegram ID (#701)#774

Open
ToRyVand wants to merge 2 commits intolnp2pBot:mainfrom
ToRyVand:feat/issue-701-block-by-id
Open

feat: allow /block and /unblock by numeric Telegram ID (#701)#774
ToRyVand wants to merge 2 commits intolnp2pBot:mainfrom
ToRyVand:feat/issue-701-block-by-id

Conversation

@ToRyVand
Copy link
Copy Markdown

@ToRyVand ToRyVand commented Mar 30, 2026

Closes #701

Problem
The /block command only accepted @username. An impersonator can remove
their Telegram username at any time, making them immune to blocking. The
Telegram user ID is a permanent numeric identifier that cannot be changed.

Solution

  • /block <ID> and /unblock <ID> now accept a numeric Telegram user ID
    in addition to @username
  • /blocklist displays ID: <tg_id> for blocked users with no username
  • Added isValidBlockTarget() input validation in the command router
  • Added invalid_block_target locale key in all 10 supported languages

Tests
12 new unit tests added in tests/bot/modules/block/commands.spec.ts.
All 98 tests pass.

Usage

/block @spammer ← unchanged
/block 123456789 ← NEW: block by Telegram ID
/unblock 123456789 ← NEW: unblock by Telegram ID

Summary by CodeRabbit

  • New Features
    • Block/unblock commands now accept either @usernames or numeric Telegram user IDs; blocklist shows numeric IDs when usernames are unavailable and reports unknown IDs.
  • Documentation
    • Added "invalid block target" validation messages in 10 languages to guide correct @username or numeric ID input.
  • Tests
    • New test suite covering block, unblock, and blocklist scenarios (username/ID resolution, not-found, already-blocked, orders-in-process, empty and mixed blocklists).

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 30, 2026

Walkthrough

The PR extends block/unblock commands to accept either @username or numeric Telegram IDs, adds input validation and resolution to User records, surfaces unknown blocked IDs in the blocklist output, adds localized validation messages, and introduces tests covering the new behaviors.

Changes

Cohort / File(s) Summary
Block command logic
bot/modules/block/commands.ts, bot/modules/block/index.ts
Added resolveUser(arg) and isValidBlockTarget(arg); changed block/unblock handlers to accept target: string; validate target format in routing and resolve to User before existing block/unblock flows.
Blocklist message rendering
bot/modules/block/messages.ts
blocklistMessage signature updated to accept unknownIds: string[] = []; empty-state logic refined and output now includes unresolved numeric IDs as ID: <tg_id>.
Localization
locales/de.yaml, locales/en.yaml, locales/es.yaml, locales/fa.yaml, locales/fr.yaml, locales/it.yaml, locales/ko.yaml, locales/pt.yaml, locales/ru.yaml, locales/uk.yaml
Added invalid_block_target translation key in each locale to report invalid block/unblock targets (requires @username or numeric Telegram ID).
Tests
tests/bot/modules/block/commands.spec.ts
New comprehensive test suite for block, unblock, and blocklist: verifies target resolution by @username or numeric tg_id, validation failures, block/unblock success and failure paths, order-in-process rejection, duplicate-block rejection, and blocklist handling of unknown IDs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • grunch
  • Catrya

Poem

🐰 I hop the paths of block and unblock,
I sniff a @name or count a numeric pluck,
When ghosts of IDs appear in the list,
I whisper validation in ten tongues, missed? no—persist!
Hooray — resolved, listed, and tucked with luck.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately describes the main change: enabling /block and /unblock commands to accept numeric Telegram IDs in addition to usernames.
Linked Issues check ✅ Passed All coding requirements from issue #701 are met: block/unblock by numeric Telegram ID is implemented, blocklist displays IDs for users without usernames, and input validation is in place.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #701: command enhancements, input validation, blocklist display improvements, localization, and comprehensive tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@bot/modules/block/index.ts`:
- Around line 13-16: The block command handler silently calls next() when the
target fails validation; update the bot.command('block', userMiddleware, async
(ctx, next) => { ... }) flow so that when args.length !== 2 or
isValidBlockTarget(args[1]) is false you send the user the localized error
message (use the existing invalid_block_target locale key) instead of silently
calling next(); keep the existing successful path that calls commands.block(ctx,
args[1]) and only call next() for unrelated messages.

In `@locales/fa.yaml`:
- Line 660: The localization key invalid_block_target is still in English;
replace its value with a Persian translation so the fa locale is
consistent—update the locales/fa.yaml entry for invalid_block_target to a
Persian sentence conveying "Please provide a valid `@username` or numeric Telegram
user ID" (e.g., a concise, natural Persian equivalent) while preserving YAML
quoting and formatting.

In `@locales/ko.yaml`:
- Line 658: The locale key invalid_block_target in locales/ko.yaml is still in
English; replace its value with a Korean translation such as "유효한 `@사용자명` 또는 숫자형
텔레그램 사용자 ID를 입력하세요" so the validation message is consistent for Korean users and
keep the key name invalid_block_target unchanged.

In `@locales/ru.yaml`:
- Line 661: Translate the new localization key invalid_block_target in
locales/ru.yaml into Russian and replace the English string "Please provide a
valid `@username` or numeric Telegram user ID" with an appropriate Russian
translation (keeping placeholders/formatting if any); locate the key
invalid_block_target in the file and update its value to the Russian text so the
Russian locale remains consistent.

In `@locales/uk.yaml`:
- Line 657: The localization key invalid_block_target contains an English
message; replace its value with the Ukrainian translation so the key reads with
the provided Ukrainian text (e.g., the suggested "Будь ласка, вкажіть дійсний
`@username` або числовий Telegram ID") in locales/uk.yaml to ensure the string is
localized for Ukrainian users.
🪄 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: 290c7765-f79f-495a-ad8b-8ab62f82a46f

📥 Commits

Reviewing files that changed from the base of the PR and between d06a24d and d3fa436.

📒 Files selected for processing (14)
  • bot/modules/block/commands.ts
  • bot/modules/block/index.ts
  • bot/modules/block/messages.ts
  • locales/de.yaml
  • locales/en.yaml
  • locales/es.yaml
  • locales/fa.yaml
  • locales/fr.yaml
  • locales/it.yaml
  • locales/ko.yaml
  • locales/pt.yaml
  • locales/ru.yaml
  • locales/uk.yaml
  • tests/bot/modules/block/commands.spec.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@locales/ko.yaml`:
- Line 691: The locale key invalid_block_target is defined but never used;
update the /block and /unblock command handlers so when isValidBlockTarget(...)
returns false they send the localized error message instead of silently doing
return next(): call the codepath that sends a user-facing reply (using the
existing localization function or ctx.reply/t(...) pattern used elsewhere) with
the invalid_block_target string, then return next(); alternatively, if you
prefer removing dead strings, delete invalid_block_target from all locale files
instead—refer to isValidBlockTarget, the /block and /unblock handlers, and the
existing next() return sites to implement this change.
🪄 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: 7ab7d287-9d11-4ba9-bda1-1eff88920045

📥 Commits

Reviewing files that changed from the base of the PR and between d3fa436 and ebdf3f1.

📒 Files selected for processing (11)
  • bot/modules/block/commands.ts
  • locales/de.yaml
  • locales/en.yaml
  • locales/es.yaml
  • locales/fa.yaml
  • locales/fr.yaml
  • locales/it.yaml
  • locales/ko.yaml
  • locales/pt.yaml
  • locales/ru.yaml
  • locales/uk.yaml
✅ Files skipped from review due to trivial changes (9)
  • locales/en.yaml
  • locales/de.yaml
  • locales/es.yaml
  • locales/fr.yaml
  • locales/pt.yaml
  • locales/fa.yaml
  • locales/uk.yaml
  • locales/ru.yaml
  • locales/it.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • bot/modules/block/commands.ts

locales/ko.yaml Outdated
user_blocked: User successfully blocked
user_unblocked: User successfully unblocked
blocklist_empty: You do not have any blocked user
invalid_block_target: "Please provide a valid @username or numeric Telegram user ID"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for any usage of 'invalid_block_target' in the codebase
echo "=== Searching for 'invalid_block_target' usage in code files ==="
rg -n --type=ts --type=js "invalid_block_target" -C3

echo ""
echo "=== Checking if i18n.t() or ctx.i18n.t() calls reference this key ==="
rg -nP "i18n\.t\(['\"]invalid_block_target" 

echo ""
echo "=== Checking block module for any message sending on validation failure ==="
ast-grep --pattern $'if ($_ || !isValidBlockTarget($_)) {
  $$$
}'

Repository: lnp2pBot/bot

Length of output: 268


🏁 Script executed:

cat -n locales/ko.yaml | sed -n '685,695p'

Repository: lnp2pBot/bot

Length of output: 913


🏁 Script executed:

rg -A20 "isValidBlockTarget" bot/modules/block/

Repository: lnp2pBot/bot

Length of output: 1703


🏁 Script executed:

git ls-files | grep -E "(block|locale)" | head -20

Repository: lnp2pBot/bot

Length of output: 391


🏁 Script executed:

rg "invalid_block_target" locales/

Repository: lnp2pBot/bot

Length of output: 1132


Remove unused locale key invalid_block_target.

This locale key is defined in all 10 locale files but never referenced in the code. The /block and /unblock command handlers silently skip with return next() when validation fails, instead of sending this error message to the user.

Either implement the error message feedback when isValidBlockTarget() returns false, or remove the dead locale strings.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@locales/ko.yaml` at line 691, The locale key invalid_block_target is defined
but never used; update the /block and /unblock command handlers so when
isValidBlockTarget(...) returns false they send the localized error message
instead of silently doing return next(): call the codepath that sends a
user-facing reply (using the existing localization function or ctx.reply/t(...)
pattern used elsewhere) with the invalid_block_target string, then return
next(); alternatively, if you prefer removing dead strings, delete
invalid_block_target from all locale files instead—refer to isValidBlockTarget,
the /block and /unblock handlers, and the existing next() return sites to
implement this change.

ToRyVand added 2 commits April 1, 2026 00:43
- Add resolveUser() helper that accepts @username or numeric tg_id
- Update block/unblock/blocklist commands to use resolveUser
- Show 'ID: <tg_id>' in /blocklist for users without a username
- Add isValidBlockTarget() validation in command router
- Add invalid_block_target locale key in all 10 supported languages
- Add unit tests covering all new and existing block command flows
- Use invalid_block_target locale key instead of silently calling next()
  when the argument is neither @username nor numeric ID
- Add Persian, Korean, Russian and Ukrainian translations for
  invalid_block_target key
@ToRyVand ToRyVand force-pushed the feat/issue-701-block-by-id branch from fa17cd0 to e5a8c57 Compare April 1, 2026 05:44
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
bot/modules/block/commands.ts (1)

101-107: Optional: deduplicate unresolved IDs before passing to the message layer.

If duplicate block records ever exist, unknownIds can repeat in output. Deduping here keeps /blocklist cleaner.

Proposed refinement
-  const foundIds = new Set(usersBlocked.map(u => u.tg_id));
-  const unknownIds = tgIdBlocks.filter((id: string) => !foundIds.has(id));
+  const uniqueBlockedIds = [...new Set(tgIdBlocks)];
+  const foundIds = new Set(usersBlocked.map(u => u.tg_id));
+  const unknownIds = uniqueBlockedIds.filter((id: string) => !foundIds.has(id));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bot/modules/block/commands.ts` around lines 101 - 107, unknownIds may contain
duplicates if tgIdBlocks has repeated ids; deduplicate before calling
messages.blocklistMessage to avoid repeated unresolved entries. Replace the
current unknownIds computation by filtering tgIdBlocks into a deduped list
(e.g., track seen ids with a Set) so the final unknownIds passed to
messages.blocklistMessage is unique while still using the existing symbols
tgIdBlocks, foundIds, and usersBlocked.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@bot/modules/block/commands.ts`:
- Around line 101-107: unknownIds may contain duplicates if tgIdBlocks has
repeated ids; deduplicate before calling messages.blocklistMessage to avoid
repeated unresolved entries. Replace the current unknownIds computation by
filtering tgIdBlocks into a deduped list (e.g., track seen ids with a Set) so
the final unknownIds passed to messages.blocklistMessage is unique while still
using the existing symbols tgIdBlocks, foundIds, and usersBlocked.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 332b0d99-1a6f-4c5a-b46c-9f709841d688

📥 Commits

Reviewing files that changed from the base of the PR and between ebdf3f1 and e5a8c57.

📒 Files selected for processing (14)
  • bot/modules/block/commands.ts
  • bot/modules/block/index.ts
  • bot/modules/block/messages.ts
  • locales/de.yaml
  • locales/en.yaml
  • locales/es.yaml
  • locales/fa.yaml
  • locales/fr.yaml
  • locales/it.yaml
  • locales/ko.yaml
  • locales/pt.yaml
  • locales/ru.yaml
  • locales/uk.yaml
  • tests/bot/modules/block/commands.spec.ts
✅ Files skipped from review due to trivial changes (11)
  • locales/en.yaml
  • locales/fr.yaml
  • locales/pt.yaml
  • locales/de.yaml
  • locales/it.yaml
  • locales/ru.yaml
  • bot/modules/block/index.ts
  • locales/fa.yaml
  • locales/es.yaml
  • locales/uk.yaml
  • tests/bot/modules/block/commands.spec.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • locales/ko.yaml
  • bot/modules/block/messages.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bloqueo del ID del Usuario usurpador de identidad

1 participant