Image search (v1's catch-all)
the three triggers only print the usage line; the feature is that every unrecognised /command is a search. Search + sends in cb-worker, quotas in Valkey (v1's dict was per-process), catch-all raises SkipHandler - it is registered ahead of three routers that own real commands
/qualquercoisa/anything/cualquiercosa- v1 scenarios
- —
- Ported
- 10
- Green
- 10
- Failing
- —
the three triggers only print the usage line; the feature is that every unrecognised /command is a search. Search + sends in cb-worker, quotas in Valkey (v1's dict was per-process), catch-all raises SkipHandler - it is registered ahead of three routers that own real commands
SocialContent.py:144-170What it does
Type a command the bot does not have — /french fries — and it replies with a
picture of french fries, captioned with the page the picture came from. That is
the feature: any unrecognised command is a Google image search for its own
text. /qualquercoisa, /anything and /cualquiercosa are not searches at
all; they print the usage example that explains the trick.
Behaviour that must not change
Searches are capped: 15 per person per day, 180 across the whole bot. Both are spent when you type, not when a picture arrives, so a search that gets refused still costs the bot one of its 180 — v1's arithmetic, kept. In v1 those numbers were counted separately inside each of five processes; here they are shared, so the cap finally means what it says.
Whether the search is filtered follows the group's safe-for-work setting, not a setting of its own.
A list of 49 words never searches — shell paths like etc and usr, and lone
punctuation. It exists because every unrecognised command reaches this
feature, so without it a stray / or a pasted file path would make the bot post
pictures of /tmp. A message containing //, or a command aimed at a different
bot, is ignored for the same reason.
A group with utility turned off gets silence here, not the "utility functions are off" reply its other commands send — this is the end of v1's command chain, and nothing answers past it.
How to verify it
qa/features/x_image_search.feature — ten scenarios, including one that only
checks that a real command (/isalive) still answers. That one matters more
than it looks: a catch-all that claims an update it should have passed on
silently disables every command registered after it, which is exactly what the
first version of this feature did to /random, /transcribe and
/newwelcome. Run with python scripts/cb.py test. By hand in the sandbox,
with CB_GOOGLE_SEARCH_API_KEY and CB_GOOGLE_SEARCH_CX set: /french fries
in a group.
Giveaways
two distributed tables replace Giveaways.db; v1's /giveaway never completed (json.loads on a de-quoted callback payload) and its enter button was admin-only - both fixed, see docs/contracts/x_giveaways.md; QA authored, not ported (10 scenarios)
Owner-only operations
private-chat only and gated on CB_OWNER_ID; /grupos is one paged message instead of v1's one getChat + one sendMessage per group (D11) and /broadcast is a cb-worker fan-out instead of a sleep(0.5) loop on the handler thread (D8); /stop and /restart answer a refusal rather than os._exit-ing one of N replicas - see docs/contracts/x_owner_commands.md; QA authored (9 scenarios)