- JavaScript 89.9%
- Python 8.1%
- Dockerfile 2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
The service, its systemd unit and paths on the deployed container keep the vomit-proxy name; only the repo and docs change. Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
| convert | ||
| deploy | ||
| fixtures | ||
| test | ||
| .env.example | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
| server.js | ||
vommet-proxy
Third-party request proxy for Vommet, the LLM-assisted fork of the Commet Matrix client. The client never talks to Tenor, Klipy, Signal or Telegram directly; it talks to this, so API keys and the Telegram bot token stay server-side and the user's IP never reaches those services.
Derived from commetchat/proxy
(AGPL-3.0, a Cloudflare Worker), ported to a plain Node 20+ service with no
dependencies so it runs in a container. Route shapes are identical to
upstream's, so the client's GIF picker and Signal importer work unchanged. The
Telegram routes are new. Do not point a client at proxy.commet.chat; that
is Commet's infrastructure, not ours.
Routes
| Route | Upstream | Notes |
|---|---|---|
GET /healthz |
– | {"ok":true} |
GET /proxy/tenor/api/v2/search?q=… |
tenor.googleapis.com | only q forwarded, key appended |
GET /proxy/tenor/media/<path> |
media.tenor.com | passthrough |
GET /proxy/klipy/api/v2/search?q=… |
api.klipy.com | only q forwarded, key appended |
GET /proxy/klipy/media/<path> |
static.klipy.com | passthrough |
GET /proxy/signal/stickers/<pack>/… |
cdn-ca.signal.org | passthrough of encrypted pack data; the client holds the key |
GET /proxy/telegram/stickers/<set_name> |
Bot API getStickerSet |
normalised JSON, see below |
GET /proxy/telegram/media/<file_id> |
Bot API getFile + download |
streamed with a real Content-Type |
GET /proxy/telegram/media/<file_id>?as=webp |
same | animated stickers converted to animated WebP (cached) |
A route whose key or token is not configured answers 503.
Telegram sticker set shape
{
"name": "FoxPack",
"title": "Fox Pack",
"sticker_type": "regular",
"cover": "/proxy/telegram/media/<file_id>",
"stickers": [
{ "id": "<file_unique_id>", "file_id": "…", "emoji": "🦊", "width": 512, "height": 512,
"animated": false, "format": "webp", "source_format": "webp",
"url": "/proxy/telegram/media/<file_id>" },
{ "id": "…", "file_id": "…", "emoji": "😺", "width": 256, "height": 256,
"animated": true, "format": "webp", "source_format": "tgs",
"url": "/proxy/telegram/media/<file_id>?as=webp" }
]
}
source_format is Telegram's own format: webp (static), tgs (gzipped Lottie
animation) or webm (video sticker); animated is true for the latter two.
When STICKER_CONVERTER is set (the Docker image and the systemd unit both set
it), animated stickers are listed as "format": "webp" with a ?as=webp URL,
and the proxy converts them to animated WebP on first request: 256 px, at
most 20 fps, quality 60 by default (STICKER_SIZE, STICKER_FPS,
STICKER_QUALITY). A typical Lottie sticker converts in about a second to
roughly 400 KB; video stickers are usually far smaller. Results are cached on
disk by Telegram's stable file id, at most CONVERT_CONCURRENCY conversions
run at once, concurrent requests for the same sticker share one job, and the
cache is capped at CACHE_MAX_MB (default 2048) by evicting the least recently
served stickers.
Transparency is preserved. Without a converter, animated stickers are listed in
their original format and ?as=webp answers 501.
The converter (convert/convert_sticker.py) uses rlottie-python + Pillow for
tgs and ffmpeg (libvpx + libwebp) for webm. This is why the proxy is a
container rather than a Cloudflare Worker like upstream's.
Run
Without Docker (systemd): see deploy/vomit-proxy.service; the header lists the
four commands. The service reads /etc/vomit-proxy.env (mode 600).
With Docker:
cp .env.example .env # fill in keys
docker compose up -d --build
curl -s localhost:8788/healthz
Publish 127.0.0.1:8788 as https://proxy.nether.im via cloudflared or any
reverse proxy. The client's proxy_url preference (default proxy.nether.im
in Vommet) must point at that hostname; the client always uses HTTPS.
Develop
node --test # offline; every upstream is a local stub
PORT=8788 TELEGRAM_BOT_TOKEN=… node server.js
License
AGPL-3.0-only, same as the proxy it is derived from.