- HTML 88.3%
- TypeScript 11.6%
| .vscode | ||
| scripts | ||
| searxng | ||
| src | ||
| .dockerignore | ||
| .editorconfig | ||
| .env.example | ||
| .gitignore | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| eslint.config.mjs | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| tsconfig.json | ||
imager-bot
Telegram inline image-search bot. Type @yourbot cats in any chat to get a
photo grid.
Sources
Tried in priority order; the first to return usable results wins. A provider
still running after a 2s hedge delay no longer blocks the walk — the next one
starts alongside it and whichever answers first wins. A provider with no
configuration disables itself and is skipped. Per-provider durations are logged
([chain] name: N results in Xms) so slow sources are visible.
- SearXNG — self-hosted metasearch, fans out to Google, Bing, DuckDuckGo and Yandex Images at once. Also proxies every image so Telegram can fetch it.
- Brave Images API — optional, set
BRAVE_API_KEY. - DuckDuckGo — no key required.
- Yandex Images — last resort, HTML scrape.
Quick start
cp .env.example .env
echo "SEARXNG_SECRET=$(openssl rand -hex 32)" >> .env
# put your @BotFather token in BOT_TOKEN
docker compose up -d
Then send /setinline to @BotFather and pick this bot
so inline mode is enabled.
Local development
pnpm install
docker compose up -d searxng
pnpm dev
Configuration
| Variable | Required | Default | Purpose |
|---|---|---|---|
BOT_TOKEN |
yes | — | @BotFather token |
SAFESEARCH |
no | strict |
strict, moderate, or off |
SEARXNG_URL |
no | — | internal API origin, enables the SearXNG provider |
SEARXNG_PUBLIC_URL |
no | SEARXNG_URL |
public origin for image-proxy links — must be reachable by Telegram's servers or inline results fail with WEBDOCUMENT_URL_INVALID |
SEARXNG_SECRET |
no | — | must match SearXNG's server.secret_key |
BRAVE_API_KEY |
no | — | enables the Brave provider |
SEARXNG_URL and SEARXNG_SECRET must both be set for SearXNG to activate.
Commands
pnpm dev— watch modepnpm start— production runpnpm test— run testspnpm lint:fix— lint and auto-fix
Notes
Scraped providers (DuckDuckGo, Yandex) use undocumented endpoints and will break
when those change. The recorded fixtures under
src/providers/__fixtures__/ are what turn that breakage into a failing test —
re-record them when a provider starts returning nothing.