mirror of
https://github.com/tiennm99/tiennm99bot.git
synced 2026-10-11 03:13:46 +00:00
feat(blacklist): add per-topic text deny-list with whitelist exceptions
Six public commands let any member of a chat curate two lists of text and ask whether a given text is blocked: /blacklist_add, /blacklist_del, /whitelist_add, /whitelist_del, /blacklist_rules and /blacklist_check. The module is passive. It never reads ordinary chat messages and never deletes, warns or restricts anyone; the lists stay inert until /blacklist_check asks about a specific text. Scope is one forum topic, keyed (Chat.ID, MessageThreadID) and gated on IsTopicMessage so a reply chain in a plain supergroup does not become its own unreachable scope. A plain group, a DM and a forum's General topic all resolve to one chat-wide list. Matching is substring, after NFKC composition, case folding and whitespace collapse. Diacritics stay significant, so ma, má and mà are three entries. A whitelist entry rescues a blacklist match only when it spans that match, which is what keeps "I met an assassin, dumbass" blocked. Entry text is percent-encoded before it becomes a storage key, since keys forbid '/' and cap at 1500 bytes, and is capped at 200 bytes before and after normalization because NFKC can expand as well as contract. /blacklist_rules reads each list with Scan, so listing costs one round trip per list rather than a Get per entry.
This commit is contained in:
1 parent
d2272bd84d
commit
e5125fcd93
20 files changed
+2161
-1
No files matched your search
@@ -0,0 +1,86 @@
|
||||
# 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_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 |
|
||||
|
||||
All are public and single-shot.
|
||||
|
||||
## 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
|
||||
|
||||
`/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.
|
||||
Reference in new issue
Block a user