TekstoBot is a WhatsApp processing service that utilizes Artificial Intelligence to automatically transcribe speech to text (STT), with support for local Whisper servers and Cloudflare Workers AI.
- Audio Transcription: Receive voice messages and get the corresponding text
via local Whisper or Cloudflare Workers AI (
whisper-large-v3-turbo). - Administrative Dashboard: Web interface to manage authorized numbers, view history, and monitor connection status.
- Whitelist: Only authorized numbers in the database can interact with the bot.
- Asynchronous Processing: Uses goroutines and worker pools to ensure the bot remains responsive.
- Language: Go (Golang)
- Database: PostgreSQL
- WhatsApp Integration: whatsmeow
- AI (STT): faster-whisper-server (via Podman/Docker) or Cloudflare Workers AI
- Frontend: Go
html/template, HTMX and Tailwind CSS
- Go 1.21+ installed.
- PostgreSQL running locally.
- Podman (or Docker) for local Whisper server mode.
- psql (PostgreSQL client) to run migrations via Makefile.
- For Cloudflare mode: Cloudflare account with Workers AI enabled, account ID, and API token.
For the voice transcription (make whisper) to natively access your GPU through
Podman using CDI mapping:
-
Add the official NVIDIA repository:
curl -s -L https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo | \ sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo -
Install the Toolkit:
sudo dnf install -y nvidia-container-toolkit
-
Generate Hardware Descriptors (CDI) so Podman recognizes the environment:
sudo mkdir -p /etc/cdi sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml
-
Clone the repository:
git clone <repo-url> cd tekstobot
-
Configure the environment variables:
cp .env.example .env # Edit the .env file with your database credentials -
Install dependencies:
go mod tidy
TekstoBot supports two transcription backends:
TRANSCRIBER_BACKEND=local(default): usesWHISPER_URL.TRANSCRIBER_BACKEND=cloudflare: uses Cloudflare Workers AI endpoint@cf/openai/whisper-large-v3-turbo.
Example local configuration:
TRANSCRIBER_BACKEND=local
WHISPER_URL=http://localhost:8000
WHISPER_HEALTH_INTERVAL=30Example Cloudflare configuration:
TRANSCRIBER_BACKEND=cloudflare
CLOUDFLARE_ACCOUNT_ID=<your-account-id>
CLOUDFLARE_API_TOKEN=<your-api-token>
# Optional ISO 639-1 language code. Leave empty for auto-detection.
CLOUDFLARE_WHISPER_LANGUAGE=enWhen Cloudflare backend is selected, CLOUDFLARE_ACCOUNT_ID and
CLOUDFLARE_API_TOKEN are required and validated during startup.
TekstoBot supports OpenID Connect (OIDC) to protect the administrative dashboard.
This is disabled by default (OIDC_ENABLED=false). When enabled, all dashboard
routes and media files require a valid session.
OIDC_ENABLED: Set totrueto enable authentication.OIDC_ISSUER_URL: The base URL of your OIDC provider.OIDC_CLIENT_ID: The Client ID generated by your provider.OIDC_CLIENT_SECRET: The Client Secret generated by your provider.OIDC_REDIRECT_URL: The callback URL (e.g.,http://localhost:8080/auth/callback).OIDC_SESSION_TTL: Session duration in hours (default:24).
To use Pocket ID as your provider:
- In Pocket ID Admin, create a new client.
- Set the Redirect URL to your TekstoBot callback address.
- Add the following to your
.env:
OIDC_ENABLED=true
OIDC_ISSUER_URL=https://id.yourdomain.com
OIDC_CLIENT_ID=0123456789abcdef
OIDC_CLIENT_SECRET=your_pocket_id_secret
OIDC_REDIRECT_URL=http://localhost:8080/auth/callback
OIDC_SESSION_TTL=24The project uses a Makefile to simplify common commands:
-
Run Migrations:
make migrate-up
-
Start Whisper (Audio AI, local backend only):
make whisper
-
Run the Bot:
make run
-
Access the Dashboard: Open your browser at
http://localhost:8080(or the port defined in your.env).
Run make to see the list of available commands:
make build: Build the binary.make release: Build the optimized binary for production.make package: Generate the RPM package using nfpm.make run: Run the project locally.make whisper: Start the Whisper container via Podman.make whisper-stop: Stop and remove the Whisper container.make migrate-up: Run up migrations.make migrate-down: Rollback migrations.make check: Run build and import checks.
- Endpoint used by TekstoBot:
POST /client/v4/accounts/{ACCOUNT_ID}/ai/run/@cf/openai/whisper-large-v3-turbo - Authentication:
Authorization: Bearer <CLOUDFLARE_API_TOKEN> - Input format: base64-encoded audio bytes.
Cloudflare Workers AI limits and pricing are managed by Cloudflare and can change over time. At the time of writing:
- Automatic Speech Recognition default rate limit: 720 requests/minute.
whisper-large-v3-turbopricing is charged by audio minute.
Always verify the latest values in Cloudflare docs:
- Startup fails with missing Cloudflare credentials: set
CLOUDFLARE_ACCOUNT_IDandCLOUDFLARE_API_TOKEN. - 401/403 errors: verify token validity, scopes, and account ID.
- 429 errors / throttling: request rate exceeded; apply retry/backoff in your deployment workflow and monitor usage.
- Transcription errors in UI: detailed backend errors are stored and shown in media history to aid diagnosis.
For production environments on AlmaLinux/RHEL, TekstoBot can be installed as an RPM package that automatically manages the Whisper and Bot containers via Podman Quadlets and systemd.
Ensure you have the nfpm utility installed to generate the package:
# Example nfpm installation (Go-based tool)
go install github.com/goreleaser/nfpm/v2/cmd/nfpm@latest# Build the optimized binary and generate the RPM
make package
# Install the generated package
sudo dnf install ./tekstobot.rpmThe RPM post-install script detects if NVIDIA support is present on the host.
- With GPU: Whisper starts using the
cudaimage and CDI mapping. - Without GPU: Whisper automatically falls back to
cpumode.
Services are managed by systemd. On each start or restart of tekstobot, systemd
reads TRANSCRIBER_BACKEND from /etc/tekstobot.env and either starts the local
Whisper Quadlet (local) or stops it (cloudflare) so you do not need a separate
sync step.
# Configure your .env (required before starting)
sudo cp /etc/tekstobot.env.example /etc/tekstobot.env
sudo vi /etc/tekstobot.env
# Enable and start TekstoBot
sudo systemctl enable --now tekstobot
# Follow the logs
sudo journalctl -u tekstobot -fTRANSCRIBER_BACKEND=local: the Podman Whisper service is started before the bot.TRANSCRIBER_BACKEND=cloudflare: the local Whisper service is stopped and not used; configure Cloudflare credentials in the same file.
After changing TRANSCRIBER_BACKEND (or other settings), run
sudo systemctl restart tekstobot to apply them.
This project is under the MIT license. See the LICENSE file for details.