A Discord bot for issue tracking and bug reporting built with Go, following clean architecture principles.
This project follows Clean Architecture with clear separation of concerns:
fix-track-bot/
βββ internal/
β βββ domain/ # Business entities and rules
β β βββ issue.go # Issue entity and business rules
β β βββ interfaces.go # Repository and service interfaces
β β βββ errors.go # Domain-specific errors
β βββ repository/ # Data access layer
β β βββ issue_repository.go # Issue database operations
β β βββ database.go # Database connection and migrations
β βββ service/ # Business logic layer
β β βββ issue_service.go # Issue business logic
β βββ transport/ # External interfaces
β β βββ discord/ # Discord bot handlers
β β βββ handler.go # Discord event handlers
β β βββ commands.go # Slash command management
β βββ config/ # Configuration management
β βββ config.go # Application configuration
βββ pkg/
β βββ logger/ # Logging utilities
β βββ logger.go # Structured logging with Zap
βββ data/ # Database files (SQLite)
βββ config.example.yaml # Example configuration file
βββ main.go # Application entry point
βββ go.mod # Go module dependencies
- Domain Layer: Contains business entities (
Issue), interfaces, and domain-specific errors - Repository Layer: Handles database operations and data persistence
- Service Layer: Implements business logic and orchestrates domain operations
- Transport Layer: Handles external communication (Discord interactions)
- Config Layer: Manages application configuration and environment variables
- β Channel registration with customer and project information
- β Issue creation via Discord slash commands
- β Issue tracking with unique IDs
- β Thread-based discussions for each issue
- β Priority levels (Low, Medium, High) with visual indicators
- β Issue status management (Open, Closed)
- β Issue listing and searching by channel
- β Detailed issue status checking with partial ID support
- β Interactive priority setting via dropdown menus
- β Comprehensive help system
- β Structured logging with Zap
- β Database persistence with GORM (SQLite)
- β Clean architecture with dependency injection
- β Proper error handling and validation
Copy config.example.yaml to config.yaml and configure:
app:
name: "fix-track-bot"
version: "1.0.0"
environment: "development"
debug: true
discord:
token: "your_discord_bot_token_here"
prefix: "!"
database:
driver: "sqlite"
file_path: "./data/fix-track.db"
logger:
level: "info"
environment: "development"
output_paths:
- "stdout"You can also use environment variables:
export DISCORD_TOKEN="your_discord_bot_token_here"
export DATABASE_FILE_PATH="./data/fix-track.db"
export LOG_LEVEL="info"-
Clone and Setup
git clone <repository> cd fix-track-bot make setup # Copies environment file
-
Configure Environment
# Edit .env file and set your Discord bot token nano .env # Set DISCORD_TOKEN=your_actual_bot_token
-
Start Services
make docker-up # This starts PostgreSQL and the bot -
View Logs
make docker-logs
-
Install Dependencies
go mod tidy
-
Start PostgreSQL
# Option A: Use Docker for just PostgreSQL docker-compose up -d postgres # Option B: Install PostgreSQL locally # Create database: fix_track # Create user: fix_track_user
-
Configure the Bot
cp config.example.yaml config.yaml # Edit config.yaml with your Discord bot token and database settings -
Run the Bot
go run main.go
make help # Show all available commands
make docker-up # Start all services
make docker-down # Stop all services
make docker-logs # View service logs
make build # Build the application
make test # Run tests- Create a new application at Discord Developer Portal
- Create a bot user and copy the token
- Enable the following bot permissions:
- Send Messages
- Use Slash Commands
- Create Public Threads
- Manage Threads
- Embed Links
- Invite the bot to your server with the required permissions
/register- Register the current channel for issue tracking with customer and project information/issue- Create a new issue with a modal form/issues- List all issues in the current channel (shows up to 10 most recent)/issue-status <id>- Check the status of a specific issue (accepts full UUID or first 8 characters)/help- Show comprehensive help information
- Register the channel using
/registerwith customer name and project name - Use
/issueto create a new issue - Fill out the modal with title, description, and optional image URL
- The bot creates a thread for discussion
- Set priority using the dropdown menu in the thread
- Close issues using the "π Close Issue" button
This project follows Go best practices and clean architecture principles:
- Idiomatic Go: Following Effective Go guidelines
- Clean Architecture: Separation of concerns across layers
- SOLID Principles: Single responsibility, dependency inversion
- Error Handling: Proper error wrapping and context
- Logging: Structured logging with correlation IDs
- Testing: Unit tests with mocks (testify/mockery)
go test ./...golangci-lint runThe bot uses PostgreSQL with a normalized schema supporting multi-tenancy:
Customers (Organizations)
βββ Projects (Customer Projects)
β βββ Channels (Discord Channel Registrations)
β βββ Issues (Bug Reports/Features)
βββ Users (Customer Users)
- Customers can have multiple Projects and Users
- Projects belong to one Customer and can have multiple Channels and Issues
- Users can belong to one Customer (or be system users)
- Channels are registered for one Project by one User
- Issues are reported in one Project by one User
CREATE TABLE customers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
contact_email VARCHAR(255),
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);CREATE TABLE projects (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
customer_id UUID NOT NULL REFERENCES customers(id),
name VARCHAR(255) NOT NULL,
description TEXT,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
customer_id UUID REFERENCES customers(id),
name VARCHAR(255),
email VARCHAR(255),
discord_id VARCHAR(100) UNIQUE,
role VARCHAR(20) DEFAULT 'customer',
created_at TIMESTAMPTZ DEFAULT now()
);CREATE TABLE channels (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
project_id UUID NOT NULL REFERENCES projects(id),
channel_id VARCHAR(100) NOT NULL UNIQUE,
guild_id VARCHAR(100) NOT NULL,
registered_by UUID NOT NULL REFERENCES users(id),
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);CREATE TABLE issues (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
project_id UUID NOT NULL REFERENCES projects(id),
reporter_id UUID NOT NULL REFERENCES users(id),
assignee_id UUID REFERENCES users(id),
title VARCHAR(255) NOT NULL,
description TEXT NOT NULL,
image_url VARCHAR(500),
priority VARCHAR(10) DEFAULT 'medium',
status VARCHAR(10) DEFAULT 'open',
channel_id VARCHAR(100), -- Discord channel ID (optional)
thread_id VARCHAR(100),
message_id VARCHAR(100),
public_hash VARCHAR(100) UNIQUE, -- For public links
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now(),
closed_at TIMESTAMPTZ
);When using Docker Compose, the PostgreSQL database is automatically set up with:
- Database:
fix_track - User:
fix_track_user - Password:
fix_track_password - Port:
5432(mapped to host)
# Reset database (destroys all data)
make db-reset
# Connect to PostgreSQL (when running in Docker)
docker exec -it fix-track-postgres psql -U fix_track_user -d fix_track
# View database logs
docker-compose logs postgres
# Backup database
docker exec fix-track-postgres pg_dump -U fix_track_user fix_track > backup.sql
# Restore database
docker exec -i fix-track-postgres psql -U fix_track_user -d fix_track < backup.sqlThe application automatically runs GORM auto-migrations on startup, creating:
channelstable for channel registrationsissuestable for issue tracking
- Fork the repository
- Create a feature branch
- Follow the coding standards
- Write tests for new functionality
- Submit a pull request
This project is licensed under the MIT License.