An asynchronous Discord chatbot that integrates Discord with the SberCloud Demo Boltalka / ruGPT-3 conversational API and keeps a separate persistent conversation history for each user.
The project demonstrates async Python application design, third-party API integration, PostgreSQL persistence, repository abstractions, Docker-based deployment, and integration testing.
- Asynchronous Discord bot built with Hikari
- Async HTTP integration with the external conversational model via
aiohttp - Persistent per-user dialogue context stored in PostgreSQL
- Asynchronous database access with SQLAlchemy and
asyncpg - Configurable channels in which the bot can answer without an explicit mention;
- Normalization of Discord mentions, roles, channels, timestamps, and custom emoji before sending text to the model
- Graceful handling of validation and upstream API errors
- Docker image and Docker Compose configuration for the bot + PostgreSQL
- Asynchronous integration tests for the dialogue repository
- TOML-based application configuration
flowchart LR
U[Discord user] --> D[Discord / Hikari]
D --> E[BoltalkaEvents]
E --> R[Dialog repository]
R <--> P[(PostgreSQL)]
E --> A[BoltalkaAPI]
A --> S[SberCloud Demo Boltalka API]
S --> A
A --> E
E --> D
The message handler loads the user's previous dialogue context from PostgreSQL, appends the new request, sends the resulting context to the external model API, stores the request/response pair, and replies in Discord.
The database layer is exposed through an abstract dialogue-query interface, keeping persistence concerns separate from Discord event handling.
- Python 3.10
- asyncio
- Hikari
- aiohttp
- SQLAlchemy
- asyncpg
- PostgreSQL 14
- Poetry
- Docker / Docker Compose
.
├── src/discoboltalka/
│ ├── api/
│ │ ├── adapters/ # PostgreSQL tables and Discord adapters
│ │ ├── events/ # Discord event handling
│ │ ├── modules/ # External Boltalka API client
│ │ └── query_apis/ # Persistence interfaces and implementations
│ └── app/
│ ├── config/ # TOML configuration loader and models
│ ├── logic.py # Application startup / dependency wiring
│ └── providers.py # PostgreSQL session provider
├── tests/ # Async database integration tests
├── docker_composes/
│ ├── production.yml
│ └── tests.yml
├── config.example.toml
├── Dockerfile
└── pyproject.toml
Copy the example configuration and provide your Discord bot token:
cp config.example.toml config.tomlExample:
[bot]
token = "YOUR_DISCORD_BOT_TOKEN"
[boltalka]
client_name = "Discoboltalka"
[message_event]
channels_for_conversation = [
123456789012345678,
]
[postgres]
database_name = "discoboltalka"
user = "discoboltalka_user"
password = "change-me"
host = "postgresql:5432"channels_for_conversation is optional. Outside the configured channels, the bot responds when it is mentioned.
The production Compose file expects the application configuration at:
work_dir/production/config.toml
Prepare it:
mkdir -p work_dir/production
cp config.example.toml work_dir/production/config.tomlEdit work_dir/production/config.toml, then start the bot and PostgreSQL:
docker compose -f docker_composes/production.yml up --build -dView logs:
docker compose -f docker_composes/production.yml logs -f discoboltalkaStop the stack:
docker compose -f docker_composes/production.yml downThe project uses Poetry and targets Python 3.10.
poetry install
cp config.example.toml config.toml
poetry run discoboltalkaWhen running outside Docker, point postgres.host in config.toml to your PostgreSQL instance.
The repository contains asynchronous integration tests for the PostgreSQL-backed dialogue repository.
Start the test database:
docker compose -f docker_composes/tests.yml up -dInstall the project and run the test suite:
poetry install
poetry run python -m unittest discover -s testsStop the test database afterwards:
docker compose -f docker_composes/tests.yml downFrom a software-engineering perspective, the project focuses on:
- Asynchronous I/O across Discord, HTTP, and PostgreSQL
- Separation between transport/event handling, external API integration, and persistence
- Dependency wiring without coupling the Discord event layer directly to SQLAlchemy
- Persistent user-specific conversational context
- Containerized application deployment with an external database
Distributed under the MIT License.

