5.6 KiB
Operational Notes
This document covers runtime behaviors, limits, and maintenance considerations for operating a cg.cx instance.
Telegram API Rate Limits
The bot does not implement explicit request throttling for Telegram API calls. It relies on Teloxide's default behavior and the Telegram Bot API flood-control semantics.
- Forwarding / posting messages — Subject to standard Bot API rate limits (roughly ~30 messages/second in groups, lower in smaller chats). Rapid approval of many submissions may trigger
RetryAftererrors; the bot currently does not back off explicitly. - Banning / restricting members —
banChatMemberandrestrictChatMemberhave aggressive per-chat limits. Issuing many punishment commands in quick succession may result in temporary API rejections. - Message deletion —
deleteMessageis limited to ~300 deletions per chat per 24 hours for bots. The automatic service-message cleanup (see below) contributes to this budget.
Operational recommendation: If running in high-traffic groups, monitor bot logs for RetryAfter or 429 errors and consider spacing out bulk operations.
System Message Deletion Limits
The bot automatically deletes service messages in groups and channels to reduce noise. In handle_message_inner, the following 17 message types are detected and deleted in non-private chats:
new_chat_membersleft_chat_membernew_chat_titlenew_chat_photodelete_chat_photogroup_chat_createdsupergroup_chat_createdchannel_chat_createdmigrate_to_chat_idmigrate_from_chat_idpinned_messagevideo_chat_scheduledvideo_chat_startedvideo_chat_endedvideo_chat_participants_invitedmessage_auto_delete_timer_changedproximity_alert_triggered
Limitations:
- Some service messages (e.g.,
channel_chat_created) cannot be deleted by bots and will silently fail. The code handles this withlet _ = bot.delete_message(...).await;. - Deletion failures do not crash the bot or block subsequent message processing.
Storage & Directories
Encrypted content is organized into the following directories (configured in config/default.toml under [storage.paths]):
| Directory | Purpose |
|---|---|
data/media |
Image, video, and audio files (image/*, video/*, audio/*). |
data/documents |
All other file types (archives, binaries, etc.). |
data/text |
Plain text uploads (text/* MIME types). |
data/temp |
Temporary files during encryption and upload processing. |
data/logs |
Rolling log output from the bot and server. |
Directory creation: Both the bot and server call storage.ensure_dirs().await at startup, creating missing directories automatically.
Rolling Log Files
Both the bot (crates/cgcx-bot/src/main.rs) and the server (crates/cgcx-server/src/main.rs) use tracing-appender for daily log rotation:
tracing_appender::rolling::Builder::new()
.rotation(tracing_appender::rolling::Rotation::DAILY)
.filename_prefix(log_prefix)
.max_log_files(config.logging.max_files)
.build(log_dir)
- Rotation: Daily.
- Retention:
max_files(default:7). - Paths:
- Bot:
data/logs/cgcx-bot.log(or configuredlogging.file_path) - Server:
data/logs/cgcx-server.log
- Bot:
- Format: Plain text, ANSI colors disabled for file output.
- Fallback: If the rolling appender fails to initialize, the process falls back to console-only logging.
SQLite WAL Mode
Every database connection is opened with:
PRAGMA journal_mode = WAL;
PRAGMA foreign_keys = ON;
PRAGMA busy_timeout = 5000;
Implications:
- WAL (Write-Ahead Logging) allows readers to proceed without blocking on writers, which is important because the bot and server may share the same SQLite file.
- A
busy_timeoutof 5000 ms reduces "database is locked" errors under concurrent load. - WAL produces companion files (
db.sqlite-wal,db.sqlite-shm) in the same directory as the database. These are safe to leave in place during normal operation and are automatically checkpointed by SQLite.
Background Task Intervals
| Task | Interval | Description |
|---|---|---|
| Punishment expiration | 60 seconds | Bot task that queries punishments for expired timed bans/mutes and lifts them. |
| Orphan cleanup | 24 hours | Server task that runs FilePipeline::cleanup_orphans() to remove files belonging to deleted/blacklisted content (only if keep_content = false). |
Note: The orphan sweeper skips its first tick on startup to avoid immediate load spikes.
Frontend Chunk Size Warning
The frontend build uses Vite with its default configuration. During npm run build, Vite may emit warnings such as:
(!) Some chunks are larger than 500 kBs after minification.
- This is a non-blocking warning; the build completes successfully.
- The warning typically comes from large vendor dependencies (e.g., PDF.js, syntax highlighters).
- No custom
chunkSizeWarningLimitis configured; the default Vite behavior is accepted.
HTTP Rate Limiting (Server)
The Axum server uses tower-governor for per-IP rate limiting:
| Route Group | Config Key | Default | Burst |
|---|---|---|---|
General API (/api/health, /api/content/...) |
rate_limiting.requests_per_minute |
60 | 10 |
Password verification (POST /api/content/:cxid/verify-password) |
rate_limiting.password_attempts_per_minute |
4 | 3 |
- Exceeding the general limit returns
429 Too Many Requests. - The password endpoint has a separate, stricter limit to mitigate brute-force attacks.