Configuration - gabrielg2020/10000-beers GitHub Wiki

Configuration

This guide covers all configuration options for the 10,000 Beers bot. Configuration is managed through environment variables loaded from a .env file.

Quick Reference

Variable Required Default Type
DATABASE_URL - string
WHATSAPP_GROUP_ID - string
NODE_ENV development string
LOG_LEVEL debug (dev) / info (prod) string
ADMIN_IDS - CSV string
IMAGE_STORAGE_PATH /data/images string
MAX_IMAGE_SIZE_MB 10 number
SUBMISSION_COOLDOWN_MINUTES 0 number
REPLY_ON_SUBMISSION true boolean
AI_ENABLED false boolean
AI_CONFIDENCE_THRESHOLD 0.9 number
GEMINI_API_KEY ⚠️ - string
GEMINI_MODEL gemini-1.5-flash string
GITHUB_REPO_OWNER gabrielg2020 string
GITHUB_REPO_NAME 10000-beers string
STARTUP_WAIT 0 number
PUPPETEER_EXECUTABLE_PATH auto-detected string
POSTGRES_PASSWORD 🐳 beers_dev_password string
PGADMIN_EMAIL 🐳 [email protected] string
PGADMIN_PASSWORD 🐳 admin string

Legend:

  • ✅ = Required
  • ❌ = Optional
  • ⚠️ = Required when AI_ENABLED=true
  • 🐳 = Docker only

Database Configuration

DATABASE_URL

Required: Yes Type: String Format: postgresql://username:password@host:port/database

PostgreSQL connection string for the database.

Examples:

# Docker
DATABASE_URL=postgresql://beers:password@postgres:5432/beers

# Local development
DATABASE_URL=postgresql://username:password@localhost:5432/beers

# External database
DATABASE_URL=postgresql://user:[email protected]:5432/beers_production

Validation:

  • Must start with postgresql:// or postgres://
  • Host, port, and database name are required

Notes:

  • In Docker, use hostname postgres (the service name)
  • For production, use strong passwords and consider SSL parameters: ?sslmode=require

POSTGRES_PASSWORD

Required: Docker only Type: String Default: beers_dev_password

Password for the PostgreSQL database user in Docker.

Example:

POSTGRES_PASSWORD=your_secure_password_here

Important:

  • Change this from the default in production
  • Must match the password in DATABASE_URL
  • Only used when running PostgreSQL via Docker Compose

WhatsApp Configuration

WHATSAPP_GROUP_ID

Required: Yes Type: String Format: [email protected] or 1234567890@lid

The WhatsApp group ID to monitor for beer submissions.

Examples:

# Regular group
[email protected]

# Large group/community
WHATSAPP_GROUP_ID=1234567890@lid

How to get your group ID: See Getting Started - Getting Your WhatsApp Group ID

Validation:

  • Must match pattern: \d+@(g\.us|lid|c\.us)
  • The bot will ignore messages from all other chats

ADMIN_IDS

Required: No Type: Comma-separated string Default: Empty (no admins)

WhatsApp IDs of users who can run admin commands.

Format: [email protected]

Examples:

# Single admin
[email protected]

# Multiple admins
[email protected],[email protected],[email protected]

Format guide:

Admin commands:

  • !leaderboard - Display beer leaderboard
  • !removeLast @user - Remove a user's last beer submission
  • !release - Fetch and display latest GitHub release

Notes:

  • If not set, admin commands are disabled for all users
  • No spaces between IDs in the comma-separated list

Storage Configuration

IMAGE_STORAGE_PATH

Required: No Type: String Default: /data/images

Directory path where beer images are stored.

Examples:

# Docker (recommended)
IMAGE_STORAGE_PATH=/data/images

# Local development
IMAGE_STORAGE_PATH=./data/images

# Absolute path
IMAGE_STORAGE_PATH=/var/lib/10000-beers/images

Important:

  • Directory must exist and be writable
  • For Docker, ensure volume is mounted correctly
  • Images are stored with timestamped filenames: beer_1234567890_abc123.jpg

Storage structure:

/data/images/
├── beer_1711234567_a1b2c3.jpg
├── beer_1711234890_d4e5f6.jpg
└── beer_1711235123_g7h8i9.jpg

MAX_IMAGE_SIZE_MB

Required: No Type: Number Default: 10

Maximum allowed image size in megabytes.

Examples:

# Default (10 MB)
MAX_IMAGE_SIZE_MB=10

# Smaller limit for bandwidth constraints
MAX_IMAGE_SIZE_MB=5

# Larger limit for high-quality images
MAX_IMAGE_SIZE_MB=20

Notes:

  • Images larger than this limit are rejected
  • Consider your storage capacity and network bandwidth
  • WhatsApp typically compresses images, so large limits may not be necessary

Bot Behaviour Configuration

SUBMISSION_COOLDOWN_MINUTES

Required: No Type: Number Default: 0 (no cooldown)

Minimum minutes between beer submissions for a single user.

Examples:

# No cooldown (default)
SUBMISSION_COOLDOWN_MINUTES=0

# 5-minute cooldown
SUBMISSION_COOLDOWN_MINUTES=5

# 1-hour cooldown
SUBMISSION_COOLDOWN_MINUTES=60

Use cases:

  • Prevent spam submissions
  • Enforce realistic drinking pace
  • Reduce database load

Notes:

  • Set to 0 to disable cooldown checking
  • Cooldown is per-user, not global
  • Admin commands bypass cooldown

REPLY_ON_SUBMISSION

Required: No Type: Boolean Default: true

Whether the bot sends a WhatsApp reply message when a beer is successfully submitted.

Examples:

# Send replies (default)
REPLY_ON_SUBMISSION=true

# Silent mode (no replies)
REPLY_ON_SUBMISSION=false

Reply message format:

🍺 Beer logged! Total: 42 beers

Use cases:

  • Disable for less intrusive operation
  • Enable for user feedback and confirmation

Application Configuration

NODE_ENV

Required: No Type: String Default: development Values: development, production, test

Execution environment for the application.

Examples:

# Development
NODE_ENV=development

# Production
NODE_ENV=production

# Testing
NODE_ENV=test

Effects:

  • Development: Pretty logging, verbose output, hot reload
  • Production: JSON logging, optimised performance, error handling
  • Test: Minimal logging, test database, mocked dependencies

Notes:

  • Automatically set by npm scripts (npm run dev → development, npm start → production)
  • Changes default LOG_LEVEL

LOG_LEVEL

Required: No Type: String Default: debug (development) / info (production) Values: debug, info, warn, error

Logging verbosity level.

Examples:

# Verbose logging (development)
LOG_LEVEL=debug

# Standard logging (production)
LOG_LEVEL=info

# Warnings and errors only
LOG_LEVEL=warn

# Errors only
LOG_LEVEL=error

Log level hierarchy:

  • debug - All logs including detailed debugging information
  • info - Informational messages, warnings, and errors
  • warn - Warnings and errors only
  • error - Errors only

Notes:

  • Use debug for development and troubleshooting
  • Use info for production
  • Use error to minimise log volume

STARTUP_WAIT

Required: No Type: Number Default: 0

Seconds to wait before initialising the WhatsApp client.

Examples:

# No wait (default)
STARTUP_WAIT=0

# Wait 10 seconds
STARTUP_WAIT=10

Use cases:

  • Ensure database is ready before connecting
  • Synchronise startup with other services
  • Debug startup issues

PUPPETEER_EXECUTABLE_PATH

Required: No Type: String Default: Auto-detected

Path to the Chromium executable for Puppeteer.

Examples:

# Docker (automatically set)
PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium

# macOS
PUPPETEER_EXECUTABLE_PATH=/Applications/Chromium.app/Contents/MacOS/Chromium

# Linux
PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser

Notes:

  • Usually auto-detected and doesn't need to be set
  • Required if Chromium is installed in a non-standard location
  • Docker image includes Chromium at /usr/bin/chromium

AI Configuration

AI_ENABLED

Required: No Type: Boolean Default: false

Enable AI-powered beer classification using Google Gemini.

Examples:

# Disabled (default)
AI_ENABLED=false

# Enabled
AI_ENABLED=true

When enabled:

  • Images are sent to Google Gemini for classification
  • Beer type is detected: can, bottle, or draught
  • Confidence score is stored in the database

Notes:

  • Requires GEMINI_API_KEY when enabled
  • Adds latency to submissions (~1-3 seconds)
  • See AI Classification below

AI_CONFIDENCE_THRESHOLD

Required: No Type: Number Default: 0.9 Range: 0.0 to 1.0

Minimum confidence score required for AI classification to be considered valid.

Examples:

# High confidence required (default)
AI_CONFIDENCE_THRESHOLD=0.9

# Medium confidence
AI_CONFIDENCE_THRESHOLD=0.7

# Low confidence (more permissive)
AI_CONFIDENCE_THRESHOLD=0.5

How it works:

  • Gemini returns a confidence score (0.0 to 1.0)
  • If score ≥ threshold, classification is accepted
  • If score < threshold, beer type is set to null

Recommended values:

  • 0.9 - High accuracy, some beers may not be classified
  • 0.7 - Balanced accuracy and coverage
  • 0.5 - More classifications, lower accuracy

GEMINI_API_KEY

Required: When AI_ENABLED=true Type: String Default: None

Google Gemini API key for AI classification.

Example:

GEMINI_API_KEY=AIzaSyABC123def456GHI789jkl012MNO345pqr

How to get an API key:

  1. Visit Google AI Studio
  2. Create a new API key
  3. Copy it to your .env file

Notes:

  • Keep this secret and never commit to version control
  • API usage may incur costs (check Google's pricing)
  • Free tier available for testing

GEMINI_MODEL

Required: No Type: String Default: gemini-1.5-flash

Google Gemini model to use for classification.

Examples:

# Fast and efficient (default)
GEMINI_MODEL=gemini-1.5-flash

# More accurate but slower
GEMINI_MODEL=gemini-1.5-pro

# Latest model
GEMINI_MODEL=gemini-2.0-flash-exp

Model comparison:

  • gemini-1.5-flash - Fast, low-cost, good accuracy
  • gemini-1.5-pro - Slower, higher cost, better accuracy
  • gemini-2.0-flash-exp - Experimental, performance varies

Notes:


GitHub Configuration

GITHUB_REPO_OWNER

Required: No Type: String Default: gabrielg2020

GitHub repository owner (username or organisation) for the !release command.

Examples:

# Default (this project)
GITHUB_REPO_OWNER=gabrielg2020

# Custom repository
GITHUB_REPO_OWNER=your-username

Notes:

  • Used by the !release admin command to fetch release information
  • Must be a valid GitHub username or organisation
  • Repository must be public (or provide authentication)

GITHUB_REPO_NAME

Required: No Type: String Default: 10000-beers

GitHub repository name for the !release command.

Examples:

# Default (this project)
GITHUB_REPO_NAME=10000-beers

# Custom repository
GITHUB_REPO_NAME=your-repo-name

Notes:

  • Used by the !release admin command to fetch release information
  • Must match the actual repository name on GitHub
  • Combined with GITHUB_REPO_OWNER to form: https://github.com/{owner}/{name}

Usage:

The !release command fetches release information from:

https://api.github.com/repos/{GITHUB_REPO_OWNER}/{GITHUB_REPO_NAME}/releases/latest

See Commands - !release for command usage.


Docker-Only Configuration

PGADMIN_EMAIL

Required: No (Docker only) Type: String Default: [email protected]

Login email for pgAdmin web interface.

Example:

[email protected]

PGADMIN_PASSWORD

Required: No (Docker only) Type: String Default: admin

Login password for pgAdmin web interface.

Example:

PGADMIN_PASSWORD=secure_pgadmin_password

Access pgAdmin: Navigate to http://localhost:5050 and use these credentials.


Configuration Examples

Development (Docker)

# Database
POSTGRES_PASSWORD=dev_password
DATABASE_URL=postgresql://beers:dev_password@postgres:5432/beers

# WhatsApp
[email protected]
[email protected]

# Storage
IMAGE_STORAGE_PATH=/data/images
MAX_IMAGE_SIZE_MB=10

# Bot
SUBMISSION_COOLDOWN_MINUTES=0
REPLY_ON_SUBMISSION=true

# Application
NODE_ENV=development
LOG_LEVEL=debug

# AI (disabled for development)
AI_ENABLED=false

# GitHub
GITHUB_REPO_OWNER=gabrielg2020
GITHUB_REPO_NAME=10000-beers

# pgAdmin
[email protected]
PGADMIN_PASSWORD=admin

Production (Docker)

# Database (use strong password!)
POSTGRES_PASSWORD=your_strong_secure_password_here
DATABASE_URL=postgresql://beers:your_strong_secure_password_here@postgres:5432/beers

# WhatsApp
[email protected]
[email protected],[email protected]

# Storage
IMAGE_STORAGE_PATH=/data/images
MAX_IMAGE_SIZE_MB=10

# Bot
SUBMISSION_COOLDOWN_MINUTES=5
REPLY_ON_SUBMISSION=true

# Application
NODE_ENV=production
LOG_LEVEL=info

# AI
AI_ENABLED=true
AI_CONFIDENCE_THRESHOLD=0.9
GEMINI_API_KEY=AIzaSyABC123def456GHI789jkl012MNO345pqr
GEMINI_MODEL=gemini-1.5-flash

# GitHub
GITHUB_REPO_OWNER=gabrielg2020
GITHUB_REPO_NAME=10000-beers

Local Development (Non-Docker)

# Database
DATABASE_URL=postgresql://username:password@localhost:5432/beers

# WhatsApp
[email protected]
[email protected]

# Storage
IMAGE_STORAGE_PATH=./data/images
MAX_IMAGE_SIZE_MB=10

# Bot
SUBMISSION_COOLDOWN_MINUTES=0
REPLY_ON_SUBMISSION=true

# Application
NODE_ENV=development
LOG_LEVEL=debug

# AI (disabled for development)
AI_ENABLED=false

# GitHub
GITHUB_REPO_OWNER=gabrielg2020
GITHUB_REPO_NAME=10000-beers

Configuration Validation

The bot validates all configuration on startup. If validation fails, it will log the errors and exit.

Common validation errors:

Invalid DATABASE_URL

ConfigValidationError: Invalid configuration
Invalid fields: database.url (must start with postgresql:// or postgres://)

Fix: Ensure your database URL starts with postgresql://

Invalid WHATSAPP_GROUP_ID

ConfigValidationError: Invalid configuration
Invalid fields: whatsapp.groupId (must be in format: [email protected] or 1234567890@lid)

Fix: Check your group ID format (see Getting Started)

Missing GEMINI_API_KEY with AI enabled

ConfigValidationError: Invalid configuration
Invalid fields: ai.geminiApiKey (required when AI is enabled)

Fix: Add GEMINI_API_KEY to your .env file or set AI_ENABLED=false


AI Classification Flow

When AI_ENABLED=true, the submission flow includes AI classification:

  1. User sends image to WhatsApp group
  2. Bot downloads and validates image
  3. Image is sent to Gemini API with classification prompt
  4. Gemini returns: isValid, beerType, confidence
  5. If confidence >= AI_CONFIDENCE_THRESHOLD:
    • Beer type is saved (can, bottle, or draught)
    • Confidence score is stored
  6. If confidence < AI_CONFIDENCE_THRESHOLD:
    • Beer type is saved as null
    • Submission is still accepted

Classification prompt: See src/system_instruction.md for the full AI prompt.


Security Best Practices

Protect Sensitive Data

Never commit these to version control:

  • GEMINI_API_KEY
  • POSTGRES_PASSWORD
  • DATABASE_URL (if it contains passwords)

Use .env files:

# Add to .gitignore
echo ".env" >> .gitignore

Use Strong Passwords

For production:

  • POSTGRES_PASSWORD - Use 20+ character random string
  • PGADMIN_PASSWORD - Use strong password if exposing pgAdmin

Restrict Admin Access

Only add trusted users to ADMIN_IDS:

# Good: Only trusted admins
[email protected]

# Bad: Too many admins
[email protected],[email protected],[email protected],[email protected]

Use Environment-Specific Files

Create separate .env files for each environment:

  • .env.development
  • .env.production
  • .env.test

Load the appropriate file based on NODE_ENV.


Troubleshooting Configuration Issues

Bot doesn't respond to messages

Check:

  1. WHATSAPP_GROUP_ID matches your group's ID
  2. Bot is connected (check logs for "Client is ready!")
  3. Session is authenticated

Images not saving

Check:

  1. IMAGE_STORAGE_PATH directory exists
  2. Directory is writable
  3. MAX_IMAGE_SIZE_MB is not too small

AI classification not working

Check:

  1. AI_ENABLED=true
  2. GEMINI_API_KEY is set and valid
  3. API quota is not exceeded
  4. Check logs for AI service errors

Database connection failed

Check:

  1. DATABASE_URL format is correct
  2. PostgreSQL is running
  3. Database credentials are correct
  4. Network connectivity (for remote databases)

Next Steps