A comprehensive Telegram bot for managing a movie club with voting system, movie suggestions, session management, and scheduling. Built with Go, featuring automatic task scheduling, multi-stage Docker deployment, and rich user interactions with emoji-enhanced messages.
- Movie Suggestions: Suggest movies via Kinopoisk links or IDs
- Session Management: Create and manage viewing sessions with multiple movies
- Movie Tracking: Track suggested vs watched movies
- Custom Descriptions: Add custom descriptions to viewing sessions
- Automatic Info Fetching: Get movie details from Kinopoisk API automatically
- Selection Voting: Choose next movie to watch from suggestions
- Rating Voting: Rate movies after watching (1-10 scale)
- Automated Scheduling: Votings auto-close after specified duration
- Poll Persistence: Polls tracked in database (survives bot restarts)
- Vote Tracking: Complete vote history per user
- Session Creation: Automatically create sessions when adding movies
- Session Rescheduling: Change session dates/times
- Session Cancellation: Cancel sessions with automatic cleanup
- Recurring Schedules: Set weekly schedules for movie nights
- Automatic Task Scheduling: Auto-schedule rating votings and session completions
- Auto-Registration: Users automatically registered on first interaction
- Role-Based Access: Admin and member roles with different permissions
- Permission Middleware: Group membership and admin verification
- User Tracking: Track who suggested movies, created sessions
- Emoji-Enhanced Messages: All user-facing messages use contextual emoji
- Interactive Keyboards: Inline keyboards for selections
- Date Picker: Visual date selection for scheduling
- Paginated Lists: Paginated movie and voting lists
- State Management: FSM-based conversation flows for complex interactions
- Background Tasks: Asynq + Redis for scheduled task execution
- Telegraph Integration: Generate beautiful shareable movie lists
- Docker Support: Multi-stage builds for bot and worker
- Database Migrations: Automatic GORM migrations
- Error Handling: Comprehensive error handling with user-friendly messages
tg-bot-movieclub-go/
βββ cmd/
β βββ bot/ # Bot application entry point
β β βββ main.go
β βββ worker/ # Worker application entry point
β βββ main.go
βββ internal/
β βββ app/ # Application initialization
β β βββ app.go
β βββ config/ # Configuration management
β β βββ app.go
β β βββ config.go
β β βββ db.go
β β βββ kinopoisk.go
β β βββ redis.go
β β βββ telegram.go
β βββ db/ # Database setup and migrations
β β βββ db.go
β βββ model/ # Data models (GORM)
β β βββ movie.go # Movie entity
β β βββ session.go # Viewing session
β β βββ user.go # User and role
β β βββ voting.go # Voting entity
β β βββ vote.go # Individual vote
β β βββ poll.go # Telegram poll tracking
β β βββ poll_option.go # Poll option mapping
β β βββ schedule.go # Recurring schedule
β βββ repository/ # Database repositories
β β βββ movie_repo.go
β β βββ session_repo.go
β β βββ user_repo.go
β β βββ vote_repo.go
β β βββ voting_repo.go
β β βββ poll_repo.go
β β βββ role_repo.go
β β βββ schedule_repo.go
β βββ service/ # Business logic layer
β β βββ movie_service.go
β β βββ session_service.go
β β βββ user_service.go
β β βββ voting_service.go
β β βββ vote_service.go
β β βββ kinopoisk_service.go
β β βββ poll_service.go
β β βββ schedule_service.go
β βββ transport/telegram/ # Telegram handlers
β β βββ add_movie_to_session.go # /adds command
β β βββ remove_movie_from_session.go # /removes command
β β βββ cancel_session.go # /cancel_session command
β β βββ reshedule_session.go # /reschedule command
β β βββ custom_session_description.go # /custom command
β β βββ voting.go # /voting command
β β βββ cancel_voting.go # /cancel_voting command
β β βββ suggest_movie.go # Movie suggestion handler
β β βββ current_movies.go # /current command
β β βββ already_watched_movies.go # /watched command
β β βββ schedule.go # /schedule command
β β βββ poll_answer.go # Poll answer handler
β β βββ register_user.go # User registration
β β βββ update_chat_member.go # Member updates
β β βββ cancel.go # /cancel command
β β βββ help.go # /help command
β β βββ default.go # Default message handler
β βββ tasks/ # Background tasks (Asynq)
β β βββ queue.go # Queue setup
β β βββ finish_session.go # Session completion task
β β βββ open_rating_voting.go # Rating voting task
β β βββ close_selection_voting.go # Selection voting closure
β β βββ close_rating_voting.go # Rating voting closure
β βββ utils/ # Utilities
β βββ date/ # Date utilities
β β βββ date.go
β βββ fsm/ # Finite State Machine
β β βββ fsm.go
β βββ kinopoisk/ # Kinopoisk API client
β β βββ api.go
β β βββ parse.go
β βββ slice/ # Slice utilities
β β βββ slice.go
β βββ telegram/ # Telegram utilities
β β βββ datepicker/ # Date picker widget
β β βββ keyboard/ # Inline keyboards
β β βββ middleware/ # Auth & permissions
β βββ telegraph/ # Telegraph integration
β βββ init.go
βββ scripts/
β βββ export_movies/ # Export movies to JSON
β β βββ export_movies.go
β βββ import_movies/ # Import movies from JSON
β β βββ import_movies.go
β βββ json_to_sql/ # Generate SQL from JSON
β βββ json_to_sql.go
βββ build/ # Build artifacts directory
βββ Dockerfile # Multi-stage Docker build
βββ docker-compose.yml # Development compose
βββ docker-compose.prod.yml # Production compose with nginx
βββ Makefile # Build automation
βββ movies.json # Movie database export
βββ movies_insert.sql # SQL insert statements
βββ go.mod # Go dependencies
- Go 1.25.3 - Programming language
- Postgresql - Database (via GORM)
- Redis - Task queue backend
- Docker - Containerization
- go-telegram/bot v1.17.0 - Telegram Bot API
- GORM v1.31.1 - ORM for database operations
- Asynq v0.25.1 - Task queue and scheduler
- FSM v0.2.0 - Finite State Machine
- Telegraph Go v2.0.4 - Telegraph API client
- cleanenv v1.5.0 - Configuration management
- Make - Build automation
- Docker Compose - Local development orchestration
- Go 1.25.3 or later
- Postgresql
- Redis 6.0+ (for background tasks)
- Docker & Docker Compose (optional, for containerized deployment)
- Telegram Bot Token (from @BotFather)
- Kinopoisk API Key (from kinopoiskapiunofficial.tech)
-
Clone the repository
git clone https://github.com/Forceres/tg-bot-movieclub-go.git cd tg-bot-movieclub-go -
Install dependencies
go mod download
-
Configure environment
Create a
.envfile in the project root:# Telegram Bot Configuration TELEGRAM_BOT_TOKEN=your_bot_token_here TELEGRAM_WEBHOOK_SECRET_TOKEN=your_webhook_secret_token TELEGRAM_GROUP_ID=-100123456789 # Your group chat ID (negative for supergroups) # Database Configuration DATABASE_NAME=db.sqlite3 # Redis Configuration (for background tasks) REDIS_URL=redis://localhost:6379 # Kinopoisk API (for fetching movie data) KINOPOISK_API_KEY=your_api_key_here KINOPOISK_API_URL=https://kinopoiskapiunofficial.tech/api KINOPOISK_API_VERSION=v2.2
Get your API keys:
- Telegram Bot Token: @BotFather
- Group ID: Forward message from group to @userinfobot
- Kinopoisk API: kinopoisk.dev
-
Initialize database
Database migrations run automatically on first start via GORM AutoMigrate.
Tables created:
users- Telegram user accountsroles- User roles (seeded: ADMIN, USER)movies- Movie catalogsessions- Viewing sessionsvotings- Voting instancesvotes- Individual vote recordspolls- Telegram poll trackingpoll_options- Poll option mappingsschedules- Recurring schedule configurationmovies_sessions- Many-to-many relationship table
Optional: Import existing movies:
# From JSON go run scripts/import_movies/import_movies.go -file movies.json
Start Redis (required for background tasks):
redis-serverRun the bot:
# Using Make
make run
# Or directly with Go
go run ./cmd/bot/main.goRun the worker (in separate terminal):
go run ./cmd/worker/main.goBuild and run:
# Build both bot and worker
make build
# Run bot
./build/bot
# Run worker (in separate terminal)
./build/workerDevelopment (with docker-compose):
# Build and start all services (redis, bot, worker)
docker-compose up --build
# Run in background
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose downProduction (with nginx):
# Build and start with nginx reverse proxy
docker-compose -f docker-compose.prod.yml up --build -d
# View logs
docker-compose -f docker-compose.prod.yml logs -f
# Stop services
docker-compose -f docker-compose.prod.yml downThe Dockerfile supports building both bot and worker from the same source:
# Build bot
docker build --build-arg BUILD_TARGET=bot -t movie-club-bot .
# Build worker
docker build --build-arg BUILD_TARGET=worker -t movie-club-worker ./start- Start the bot and get welcome message/help- Show help message with all available commands/suggest- Suggest a movie (send Kinopoisk links or IDs)/current- Show current session movies/watched- Show already watched movies (paginated Telegraph list)/cancel- Cancel current operation/conversation flow
/adds <movie_ids>- Add movies to current session/removes- Remove movies from current session/cancel_session- Cancel current viewing session/reschedule- Reschedule current session date/time/custom- Set custom description for current session/voting- Create a new voting (selection or rating)/cancel_voting- Cancel active votings/schedule- View current schedule/reschedule_schedule- Update recurring schedule settings
- Admin uses
/adds <movie_ids>with Kinopoisk IDs or links - Bot fetches movie information from Kinopoisk API
- Session is created automatically (or movies added to existing)
- Bot schedules:
- Session finish task
- Rating voting tasks for each movie (opens at session end)
- Add Description:
/custom- Set custom description with max 500 chars - Reschedule:
/reschedule- Choose new date, time, and timezone - Remove Movies:
/removes- Select movies to remove from session - Cancel:
/cancel_session- Cancel session and all related tasks
-
Selection Voting (Choose next movie):
- Admin runs
/votingβ selects "Selection" - Enters title and duration (hours)
- Selects movies from paginated list
- Bot creates Telegram poll
- Poll auto-closes after duration, movie with most votes wins
- Admin runs
-
Rating Voting (Rate watched movie):
- Admin runs
/votingβ selects "Rating" - Selects watched movies from list
- Polls are created immediately (or scheduled automatically after session)
- Members rate 1-10
- Average rating is calculated and saved
- Admin runs
- User sends message with Kinopoisk links or IDs
- Bot parses links/IDs (supports multiple per message, max 5)
- Checks if movies already exist
- Fetches new movie data from Kinopoisk
- Adds movies to database with status "SUGGESTED"
# Build the bot binary
make build
# Run the bot
make run
# Format code
make fmt
# Run go vet
make vet
# Run tests
make test
# Run all checks (fmt, vet, test)
make check
# Clean build artifacts
make clean- Handlers: Keep telegram handlers focused on I/O, delegate to services
- Services: Implement business logic, coordinate between repositories
- Repositories: Keep data access logic isolated, use interfaces
- Models: Define GORM entities with proper relationships
- Middleware: Add authentication/authorization logic
- Tasks: Keep background tasks idempotent and retryable
- Create handler in
internal/transport/telegram/ - Implement service logic in
internal/service/ - Add repository methods if needed in
internal/repository/ - Register handler in
internal/app/app.go - Add middleware if admin-only
- Update this README with command documentation
- Create task file in
internal/tasks/ - Define payload struct and enqueue function
- Implement processor function
- Register in worker's main.go
- Enqueue from handler/service where needed
- users: Telegram users (ID, username, first name, last name)
- roles: User roles (ADMIN, USER) - seeded automatically
- movies: Movie information
- ID (Kinopoisk ID), Title, Description, Directors
- Year, Countries, Genres, Link, Duration
- IMDBRating, Rating (calculated from votes)
- Status (SUGGESTED/WATCHED), WatchCount
- FinishedAt, SuggestedAt, SuggestedBy
- sessions: Movie viewing sessions
- FinishedAt (Unix timestamp)
- Status (ONGOING/FINISHED/CANCELLED)
- Description (custom description)
- CreatedBy (user ID)
- votings: Voting sessions
- Title, Status (ACTIVE/CLOSED/CANCELLED)
- Type (SELECTION/RATING), CreatedBy
- SessionID (optional link to session)
- votes: Individual votes
- UserID, VotingID, MovieID
- Value (for rating votes: 1-10)
- polls: Telegram poll tracking (persistence across restarts)
- PollID (Telegram poll ID)
- MessageID, ChatID, VotingID
- poll_options: Maps poll options to movies/votings
- PollID, OptionID, MovieID, VotingID
- schedules: Recurring schedule configuration
- Weekday (1-7), Hour, Minute
- Location (timezone), IsActive, Description
users βββ roles (many-to-one)
users βββ movies (one-to-many, via SuggestedBy)
users βββ sessions (one-to-many, via CreatedBy)
users βββ votings (one-to-many, via CreatedBy)
users βββ votes (one-to-many)
movies ββ sessions (many-to-many via movies_sessions)
movies βββ votes (one-to-many)
movies βββ poll_options (one-to-many)
sessions βββ votings (one-to-many)
votings βββ votes (one-to-many)
votings βββ polls (one-to-many)
polls βββ poll_options (one-to-many)
Export all movies from database to movies.json:
go run scripts/export_movies/export_movies.goImport movies from JSON file to database:
go run scripts/import_movies/import_movies.go -file movies.jsonConvert movies.json to SQL INSERT statements in movies_insert.sql:
go run scripts/json_to_sql/json_to_sql.goThe project follows clean architecture principles:
-
Transport Layer (
internal/transport/telegram/):- Telegram update handlers
- Command routing
- Message formatting with emoji
- Inline keyboard management
-
Service Layer (
internal/service/):- Business logic implementation
- Data validation
- Cross-repository coordination
- External API integration (Kinopoisk, Telegraph)
-
Repository Layer (
internal/repository/):- Data access abstraction
- GORM database operations
- Interface-based design for testability
-
Model Layer (
internal/model/):- GORM entity definitions
- Database schema structure
- Entity relationships
Uses Finite State Machine for complex conversation flows:
- Default State: Normal command handling
- Voting Creation Flow: Type β Title β Duration β Movies selection
- Session Management: Date β Time β Location selection
- Custom Description: Description input and validation
- Movie/Voting Removal: List display β Index input β Confirmation
States tracked per user with data persistence across interactions.
Architecture: Separate bot and worker processes
Bot Process (cmd/bot/):
- Handles Telegram updates
- Enqueues background tasks
- Inspects task status
Worker Process (cmd/worker/):
- Processes queued tasks
- Executes scheduled jobs
- Manages task retry logic
Task Types:
- FinishSession: Closes session at scheduled time
- OpenRatingVoting: Creates rating polls when session ends
- CloseSelectionVoting: Closes selection voting, determines winner
- CloseRatingVoting: Closes rating poll, calculates average
Scheduling:
- Tasks scheduled with
ProcessInduration - Unique task IDs prevent duplicates
- Task inspection for status checking
- Task deletion on session cancellation
Permission Middleware (utils/telegram/middleware/):
CheckIfInGroup: Verifies group membership, auto-registers new usersCheckIfAdmin: Verifies admin permissions- Role detection based on Telegram administrator status
- Automatic role assignment (USER/ADMIN)
Multi-Stage Build (Dockerfile):
- Build stage: Go 1.25.3-alpine with CGO for Postgres
- Runtime stage: Minimal alpine with ca-certificates
- Build target selection via
BUILD_TARGETarg (bot/worker)
Orchestration:
docker-compose.prod.yml: Production without services
- Verify bot token in
.envis correct - Check group ID is correct (negative number for supergroups)
- Ensure bot is added to the group and has message access
- Check bot logs for errors
- User needs to be registered first (send any message)
- Admin commands require Telegram administrator status
- Check middleware is properly applied
- Ensure Redis is running and accessible
- Verify worker process is started
- Check Redis URL in
.envis correct - Review worker logs for task processing
- Ensure SQLite CGO support is enabled during build
- Check file permissions on
db.sqlite3 - Verify migrations completed (check logs on first start)
- Ensure ports 6379 (redis) are available
- Check
.envfile is in same directory as docker-compose.yml - Verify Docker has sufficient resources allocated
- Check logs:
docker-compose logs -f
Contributions are welcome! Please follow these steps:
-
Fork the repository
git clone https://github.com/YOUR_USERNAME/tg-bot-movieclub-go.git
-
Create a feature branch
git checkout -b feature/amazing-feature
-
Make your changes
- Follow existing code style
- Add emoji to user-facing messages
- Write clear commit messages
- Update documentation if needed
-
Test your changes
make check
-
Commit and push
git commit -m 'β¨ Add amazing feature' git push origin feature/amazing-feature -
Open a Pull Request
- Describe your changes clearly
- Reference any related issues
- Wait for review
- β¨
:sparkles:- New feature - π
:bug:- Bug fix - π
:memo:- Documentation - β»οΈ
:recycle:- Refactoring - π¨
:art:- UI/formatting improvements - β‘
:zap:- Performance improvements - π§
:wrench:- Configuration changes
This project is licensed under the MIT License.
Forceres
- GitHub: @Forceres
- β Movie suggestions and management
- β Session creation and scheduling
- β Selection and rating votings
- β Background task scheduling
- β Admin/user role system
- β Auto-registration
- β Emoji-enhanced messages
- β Docker deployment
- Custom voting types
- Integration with streaming services
- Movie trailer embedding
- Discussion threads per movie
- Voting result analytics
This project is built with these amazing open-source libraries:
- go-telegram/bot - Telegram Bot API wrapper with comprehensive support
- GORM - Fantastic ORM library for Go with auto-migrations
- Asynq - Reliable task queue and scheduler built on Redis
- go-telegram/fsm - State machine for conversation flows
- go-telegram/ui - UI components including paginator
- Telegraph Go - Telegraph API client for content publishing
- cleanenv - Clean and elegant environment configuration
- Kinopoisk Unofficial API - Movie data source
Special thanks to all contributors and the Go community!