Skip to content

Forceres/tg-bot-movieclub-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

102 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🎬 Movie Club Telegram Bot

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.

✨ Features

πŸŽ₯ Movie Management

  • 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

πŸ—³οΈ Voting System

  • 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 & Schedule Management

  • 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

πŸ‘₯ User Management

  • 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

🎨 User Experience

  • 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

πŸ”§ Technical Features

  • 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

πŸ—οΈ Project Structure

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

�️ Technology Stack

Core

  • Go 1.25.3 - Programming language
  • Postgresql - Database (via GORM)
  • Redis - Task queue backend
  • Docker - Containerization

Libraries & Frameworks

  • 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

Development Tools

  • Make - Build automation
  • Docker Compose - Local development orchestration

οΏ½πŸ“‹ Prerequisites

  • 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)

πŸš€ Installation

  1. Clone the repository

    git clone https://github.com/Forceres/tg-bot-movieclub-go.git
    cd tg-bot-movieclub-go
  2. Install dependencies

    go mod download
  3. Configure environment

    Create a .env file 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:

  4. Initialize database

    Database migrations run automatically on first start via GORM AutoMigrate.

    Tables created:

    • users - Telegram user accounts
    • roles - User roles (seeded: ADMIN, USER)
    • movies - Movie catalog
    • sessions - Viewing sessions
    • votings - Voting instances
    • votes - Individual vote records
    • polls - Telegram poll tracking
    • poll_options - Poll option mappings
    • schedules - Recurring schedule configuration
    • movies_sessions - Many-to-many relationship table

    Optional: Import existing movies:

    # From JSON
    go run scripts/import_movies/import_movies.go -file movies.json

🎯 Usage

Running Locally

Start Redis (required for background tasks):

redis-server

Run the bot:

# Using Make
make run

# Or directly with Go
go run ./cmd/bot/main.go

Run the worker (in separate terminal):

go run ./cmd/worker/main.go

Build and run:

# Build both bot and worker
make build

# Run bot
./build/bot

# Run worker (in separate terminal)
./build/worker

Running with Docker

Development (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 down

Production (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 down

Docker Build Targets

The 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 .

Bot Commands

User Commands

  • /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

Admin Commands

  • /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

Workflows

Creating a Viewing Session

  1. Admin uses /adds <movie_ids> with Kinopoisk IDs or links
  2. Bot fetches movie information from Kinopoisk API
  3. Session is created automatically (or movies added to existing)
  4. Bot schedules:
    • Session finish task
    • Rating voting tasks for each movie (opens at session end)

Managing Sessions

  • 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

Creating Votings

  1. 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
  2. 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

Suggesting Movies

  1. User sends message with Kinopoisk links or IDs
  2. Bot parses links/IDs (supports multiple per message, max 5)
  3. Checks if movies already exist
  4. Fetches new movie data from Kinopoisk
  5. Adds movies to database with status "SUGGESTED"

πŸ› οΈ Development

Available Make Commands

# 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

Code Structure Guidelines

  • 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

Adding New Commands

  1. Create handler in internal/transport/telegram/
  2. Implement service logic in internal/service/
  3. Add repository methods if needed in internal/repository/
  4. Register handler in internal/app/app.go
  5. Add middleware if admin-only
  6. Update this README with command documentation

Adding Background Tasks

  1. Create task file in internal/tasks/
  2. Define payload struct and enqueue function
  3. Implement processor function
  4. Register in worker's main.go
  5. Enqueue from handler/service where needed

πŸ“Š Database Schema

Core Tables

  • 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

Relationships

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)

πŸ”§ Utilities & Scripts

Export Movies to JSON

Export all movies from database to movies.json:

go run scripts/export_movies/export_movies.go

Import Movies from JSON

Import movies from JSON file to database:

go run scripts/import_movies/import_movies.go -file movies.json

Generate SQL INSERT Statements

Convert movies.json to SQL INSERT statements in movies_insert.sql:

go run scripts/json_to_sql/json_to_sql.go

πŸ—οΈ Architecture

Layered Architecture

The project follows clean architecture principles:

  1. Transport Layer (internal/transport/telegram/):

    • Telegram update handlers
    • Command routing
    • Message formatting with emoji
    • Inline keyboard management
  2. Service Layer (internal/service/):

    • Business logic implementation
    • Data validation
    • Cross-repository coordination
    • External API integration (Kinopoisk, Telegraph)
  3. Repository Layer (internal/repository/):

    • Data access abstraction
    • GORM database operations
    • Interface-based design for testability
  4. Model Layer (internal/model/):

    • GORM entity definitions
    • Database schema structure
    • Entity relationships

State Management (FSM)

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.

Background Task System

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:

  1. FinishSession: Closes session at scheduled time
  2. OpenRatingVoting: Creates rating polls when session ends
  3. CloseSelectionVoting: Closes selection voting, determines winner
  4. CloseRatingVoting: Closes rating poll, calculates average

Scheduling:

  • Tasks scheduled with ProcessIn duration
  • Unique task IDs prevent duplicates
  • Task inspection for status checking
  • Task deletion on session cancellation

Middleware System

Permission Middleware (utils/telegram/middleware/):

  • CheckIfInGroup: Verifies group membership, auto-registers new users
  • CheckIfAdmin: Verifies admin permissions
  • Role detection based on Telegram administrator status
  • Automatic role assignment (USER/ADMIN)

Docker Architecture

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_TARGET arg (bot/worker)

Orchestration:

  • docker-compose.prod.yml: Production without services

πŸ› Troubleshooting

Bot doesn't respond

  • Verify bot token in .env is 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

"No permission" errors

  • User needs to be registered first (send any message)
  • Admin commands require Telegram administrator status
  • Check middleware is properly applied

Background tasks not running

  • Ensure Redis is running and accessible
  • Verify worker process is started
  • Check Redis URL in .env is correct
  • Review worker logs for task processing

Database errors

  • Ensure SQLite CGO support is enabled during build
  • Check file permissions on db.sqlite3
  • Verify migrations completed (check logs on first start)

Docker issues

  • Ensure ports 6379 (redis) are available
  • Check .env file is in same directory as docker-compose.yml
  • Verify Docker has sufficient resources allocated
  • Check logs: docker-compose logs -f

🀝 Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository

    git clone https://github.com/YOUR_USERNAME/tg-bot-movieclub-go.git
  2. Create a feature branch

    git checkout -b feature/amazing-feature
  3. Make your changes

    • Follow existing code style
    • Add emoji to user-facing messages
    • Write clear commit messages
    • Update documentation if needed
  4. Test your changes

    make check
  5. Commit and push

    git commit -m '✨ Add amazing feature'
    git push origin feature/amazing-feature
  6. Open a Pull Request

    • Describe your changes clearly
    • Reference any related issues
    • Wait for review

Commit Message Guidelines

  • ✨ :sparkles: - New feature
  • πŸ› :bug: - Bug fix
  • πŸ“ :memo: - Documentation
  • ♻️ :recycle: - Refactoring
  • 🎨 :art: - UI/formatting improvements
  • ⚑ :zap: - Performance improvements
  • πŸ”§ :wrench: - Configuration changes

πŸ“ License

This project is licensed under the MIT License.

πŸ‘€ Author

Forceres

�️ Roadmap

Current Features (v1.0)

  • βœ… 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

Under Consideration

  • Custom voting types
  • Integration with streaming services
  • Movie trailer embedding
  • Discussion threads per movie
  • Voting result analytics

οΏ½πŸ™ Acknowledgments

This project is built with these amazing open-source libraries:

Special thanks to all contributors and the Go community!

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages