# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is a microservices-based Telegram bot system for text monitoring and notifications. The system consists of 4 main services that communicate via RabbitMQ: - **telegram-listener**: Scans open Telegram channels and chats for messages - **telegram-client**: Bot interface for user interactions - **text-matcher**: Matches incoming messages against user subscriptions - **users**: Manages users and their preferences **Important:** This repository is the parent project containing all services as **git submodules**. Each service (telegram-listener, telegram-client, text-matcher, users) is a separate repository added as a submodule. Git tags are created at the parent repository level, which triggers the Drone CI/CD pipeline to automatically build and publish NuGet packages with versions based on the git tag. ## Architecture The services follow a message bus pattern using RabbitMQ for async communication: - TelegramListener publishes: - **MessageReceived** events (for new messages) - **MessageEdited** events (for edited messages) - TextMatcher subscribes to MessageReceived and MessageEdited, stores match history in database, and publishes: - TextSubscriptionMatched events (for first-time matches) - TextSubscriptionUpdated events (for updates to previously matched messages) - TelegramClient subscribes to both TextSubscriptionMatched and TextSubscriptionUpdated events and notifies users **Note:** WTelegram sends both `UpdateNewChannelMessage` and `UpdateEditChannelMessage` for the same message. TelegramListener publishes separate events to avoid duplicate notifications downstream. Each service follows Clean Architecture with separate projects for: - Host (API/entry point) - AppServices (business logic) - Core (shared utilities) - Api.Contracts (REST API contracts) - Async.Api.Contracts (event contracts) - Persistence (database layer, where applicable) - Migrator (database migrations, where applicable) ## Development Commands ### Running the System ```bash # Start all services with Docker Compose docker-compose up # Start individual services for development cd telegram-client && dotnet run --project src/Nocr.TelegramClient.Host cd telegram-listener && dotnet run --project src/Nocr.TelegramListener.Host cd text-matcher && dotnet run --project src/Nocr.TextMatcher.Host cd users && dotnet run --project src/Nocr.Users.Host ``` ### Building ```bash # Build individual services cd && dotnet build # Build specific projects dotnet build src/Nocr..Host ``` ### Testing ```bash # Run unit tests (only text-matcher has tests currently) cd text-matcher && dotnet test ``` ### Database Migrations For text-matcher and users services: ```bash # Add new migration (from service root directory) cd text-matcher && ./src/Nocr.TextMatcher.Migrator/AddMigration.sh MyMigrationName cd users && ./src/Nocr.Users.Migrator/AddMigration.sh MyMigrationName # Apply migrations (handled automatically by migrator containers in docker-compose) ``` ## Configuration **📖 See [CONFIGURATION.md](CONFIGURATION.md) for detailed configuration guide.** ### Quick Start The system uses ASP.NET Core's layered configuration with **Environment Variables having highest priority**. **Configuration priority (lowest → highest):** 1. `appsettings.json` (base settings, committed) 2. `appsettings.{Environment}.json` (environment-specific, some committed via `.example` files) 3. User Secrets (Development only) 4. **Environment Variables (ALWAYS WINS)** ### Three Deployment Modes 1. **VS Code (Local Development)** - Copy `appsettings.Development.json.example` → `appsettings.Development.json` in each service - Or use environment variables in `.vscode/launch.json` - Start infrastructure: `docker-compose up nocr-rabbitmq nocr-text-matcher-db nocr-users-db -d` 2. **Docker Compose (Local Full Stack)** - Copy `.nocr.env.example` → `.nocr.env` in project root - Fill in your Telegram API credentials and Bot token - Run: `docker-compose up` 3. **Kubernetes (Production)** - Create K8s Secrets (do NOT use `.nocr.env`) - Reference secrets in deployment manifests via `envFrom` ### Debug Mode Enable configuration debug logging on startup: ```bash export NOCR_DEBUG_MODE=true ``` This prints masked configuration values to help troubleshoot issues. ### Important Notes - ❌ **Never commit secrets** - use `.example` files as templates - ✅ Environment variables override all appsettings files - ✅ All services use `.example` files for documentation - ✅ Docker Compose uses `.nocr.env` file (gitignored) ## Service Ports When running with docker-compose: - telegram-client: 5050 (http://localhost:5050/health) - telegram-listener: 5040 (http://localhost:5040/health) - text-matcher: 5041 (http://localhost:5041/health) - users: 5042 (http://localhost:5042/health) - RabbitMQ: 5672 (AMQP), 15672 (Management UI - http://localhost:15672, admin/admin) - MariaDB: 3316 (text-matcher), 3326 (users) ## Key Technologies - .NET 8 - ASP.NET Core Web APIs - Entity Framework Core with MariaDB - WTelegramClient for Telegram API - Rebus for message bus (RabbitMQ) - Docker & Docker Compose for containerization - Drone CI/CD on Kubernetes ## CI/CD Pipeline **📖 See [_deploy/README.md](_deploy/README.md) for full CI/CD documentation.** The project uses Drone CI with 5 specialized pipelines: ### 1. Feature Validation (`feature/*`, `fix/*` branches) - Triggered on push to feature/fix branches - Runs build + tests with Testcontainers support - Provides fast feedback before merge - Duration: ~3-5 minutes ### 2. Main Validation (`main` branch) - Triggered on push to main - Same checks as feature validation - Ensures main branch stays healthy - Duration: ~3-5 minutes ### 3. Contracts-Only Publish (tags with `contracts_only:`) - Triggered by tag + commit message containing `contracts_only:` - Publishes NuGet contracts without building Docker images - Fast iteration on contract changes - Duration: ~2 minutes - Example: `git commit -m "contracts_only:telegram_listener - Add MessageEdited event"` ### 4. Full Release (clean tags) - Triggered by tag without special markers - Complete release cycle: 1. Publish all NuGet contracts (parallel) 2. Build all Docker images with Kaniko (parallel, after contracts) 3. Deploy to Kubernetes (automatic for `v*` tags) - Duration: ~8-10 minutes - Example: `git tag v1.3.0` ### 5. Deploy-Only (tags with `deploy_only:`) - Triggered by tag + commit message containing `deploy_only:` - Skips building, only deploys existing images - Useful for rollbacks and hotfixes - Duration: ~1 minute - Example: `git commit --allow-empty -m "deploy_only: Deploy v1.2.9"` ### Deployment Scripts Located in `_deploy/scripts/`: - **deploy.sh** - Deploy services to Kubernetes with health checks - **rollback.sh** - Rollback deployments to previous version - **health-check.sh** - Check health of all services ### Key Optimizations - **Shared NuGet cache** across pipeline steps (~60% faster builds) - **Parallel execution** for independent operations - **Proper dependency order**: Contracts → Images → Deploy - **Kaniko layer caching** for faster Docker builds - **Docker-in-Docker** support for Testcontainers in tests