Files
tiennm99 53e569ca12 feat(blacklist): add /blacklist shorthand and /whitelist_rnd
/blacklist is the short form of the two read commands: bare it lists both
lists like /blacklist_rules, and given text it judges that text like
/blacklist_check. Both long names stay for when the intent should be
explicit. An argument of only whitespace is not an argument, so it lists.

/whitelist_rnd returns one whitelist entry chosen at random, and says the
list is empty rather than answering with nothing. It reads only the
whitelist, and only for the calling topic.

The six existing command descriptions are shortened alongside. /help
renders as one un-chunked message pinned at 4096 runes, and two more
commands pushed it to 4123; the shorter wording brings it to 4049. That
ceiling is a shared limit this module did not create, and it will bind again
on the next command added anywhere in the repo.
2026-09-15 13:58:45 +07:00

103 lines
4.9 KiB
Markdown

# Blacklist
The `blacklist` module lets a chat keep a list of forbidden text and a list of
exceptions, then ask whether a given text is blocked.
| Command | Parameters | What it does |
|---|---|---|
| `/blacklist` | `[text...]` | Bare, lists both lists; with text, judges it |
| `/blacklist_add` | `[text...]` | Adds text to the blacklist, or the message you replied to |
| `/blacklist_del` | `<text...>` | Removes text from the blacklist |
| `/whitelist_add` | `[text...]` | Adds an exception, or the message you replied to |
| `/whitelist_del` | `<text...>` | Removes an exception |
| `/blacklist_rules` | — | Lists both lists in one message |
| `/blacklist_check` | `<text...>` | Judges a text against both lists |
| `/whitelist_rnd` | — | Returns one whitelist entry at random |
All are public and single-shot.
`/blacklist` is the short form of the two read commands: on its own it does what
`/blacklist_rules` does, and given text it does what `/blacklist_check` does. Nothing is
lost by using it — the long names remain for when the intent should be explicit.
`/whitelist_rnd` returns a single whitelist entry chosen at random, and says so plainly when
the whitelist is empty rather than answering with nothing.
## The bot does not police the chat
This is the first thing to know, because the module's name promises something it
deliberately does not do. Nothing happens automatically. The bot never reads
ordinary messages, never deletes anything, and never warns or restricts anyone.
The lists sit inert until `/blacklist_check` asks about a specific text.
Automatic moderation would need three things this bot does not have: a
message-level hook in the dispatcher, privacy mode disabled in BotFather so
Telegram delivers ordinary group messages at all, and admin rights with
permission to delete in every group. All three are out of scope by choice.
## Lists belong to a topic, not to the bot
Each thread keeps its own two lists. In a forum supergroup, entries added in one
topic are invisible in the next. A non-forum group has one set of lists; a
private chat with the bot has its own, shared with nobody.
This is the most common surprise: running `/blacklist_check` in the wrong topic
gives a different answer than the same command one topic over, and it is not a
bug. Every reply says "in this topic" for that reason.
Within a thread, anyone can add and anyone can remove — including entries
someone else added. The lists belong to the conversation, so the permission to
edit them does too. A per-owner rule would strand entries whose author has left
the group.
## How the whitelist works
The whitelist is not a second independent list. It is an exception layer over
the blacklist, and it rescues a match only when it **covers** that match in the
text being checked.
With `ass` blacklisted and `assassin` whitelisted:
| Checked text | Verdict | Why |
|---|---|---|
| `assassin` | Allowed | The whitelist entry spans the whole match |
| `dumbass` | Blacklisted | Nothing whitelisted covers this `ass` |
| `I met an assassin, dumbass` | **Blacklisted** | The first match is rescued; the second is not |
The third row is the one worth remembering. A whitelist entry does not make a
whole message safe — it only rescues the occurrences it actually contains.
## Matching
Matching is by substring, after the text is normalized:
- **Case does not matter.** `Cat`, `CAT` and `cat` are one rule.
- **Spacing does not matter.** `cat dog` and `cat dog` are one rule, and a
newline is just a space.
- **Diacritics do matter.** `ma`, `má` and `mà` are three separate entries. To
catch all three, add all three.
- **The same word matches across devices.** Vietnamese typed on an iPhone and on
an Android phone can differ in how the accents are encoded; normalization
resolves that, so the two forms match each other.
- **Full-width and other presentation variants fold** onto their plain forms.
`/blacklist_check` accepts text of any length. Entries themselves are capped at
200 bytes — roughly 200 plain letters, or about 65 Vietnamese characters.
## Listing
Every `/blacklist_add`, `/blacklist_del`, `/whitelist_add` and `/whitelist_del` answers with
the current contents of the list it touched, so you see the result without running anything
else. That includes the two outcomes that change nothing — text already present, or text that
was not there to remove — since those are exactly the moments you want to see what the list
actually holds. A whitelist command shows the whitelist; a blacklist command shows the
blacklist.
`/blacklist_rules` prints both lists in one message, each with its entry count,
showing entries as they were typed rather than in the normalized form. Each
entry is tappable to copy, ready to paste into a `_del` command.
Telegram caps a message at 4096 characters. A list longer than that is trimmed
with a count of what was left out; both headings always appear, so a long
blacklist never hides the whitelist entirely.