Files
worktimeBot/README.md
db123 7dbd9fda12
All checks were successful
CI / build (push) Successful in 48s
feat: add /setcalendar command, store tests, and improve error handling
- Add /setcalendar command for calendar type parity (Settings UI)
- Add 17 store tests covering all repository methods
- Add handler tests for formatDuration, fmtHHMM, fmtDDHHMM
- Add domain tests for BurnoutLevel.String, NavMonth, FormatSalary
- Fix silent error discarding in save* helpers (log write failures)
- Fix computeAndAwardXP error handling instead of discarding
- Wrap critical store.go SQL errors with fmt.Errorf context
- Update README commands table with /setcalendar
2026-06-25 15:56:00 +03:30

11 KiB
Raw Permalink Blame History

WorkTime Bot

CI

A Telegram time-tracking bot with RPG progression system, WorkTime League, salary estimation, burnout assessment, and multi-calendar support (Gregorian, Jalali/Persian, Hijri). Clock in/out, track work types, mark day off, get daily reports, browse and edit history by month, and export monthly .xlsx reports.

Quick Start

cp .env.example .env
# edit .env — set BOT_TOKEN and BOT_ALLOWED_USERS
docker compose up -d

Environment Variables

Variable Default Purpose
BOT_TOKEN Telegram Bot API token (required)
BOT_ALLOWED_USERS (all) Comma-separated Telegram user IDs (empty = allow all)
HTTP_PROXY Outbound HTTP proxy for Telegram API
HTTPS_PROXY Outbound HTTPS proxy for Telegram API
DB_PATH db.sqlite3 Path to SQLite database file
BOT_WEBHOOK_URL Set for webhook mode (omit for long-polling)
BOT_LISTEN :8080 Listen address for webhook mode
BOT_TLS_CERT TLS certificate path (webhook HTTPS)
BOT_TLS_KEY TLS key path (webhook HTTPS)

Calendar Support

Users can choose between three calendars via Settings:

  • Gregorian — standard international calendar
  • Jalali (Persian/Solar Hijri) — official calendar of Iran and Afghanistan
  • Hijri (Islamic lunar) — used in many Muslim-majority countries

The history view, export month picker, and date displays all adapt to the user's chosen calendar. The /export and /edit commands accept dates in the user's calendar. Internally, all dates are stored as Gregorian.

Features

RPG Progression System

Every second of tracked work earns XP. Level up as you accumulate XP with a quadratic curve. Maintain consecutive workdays to build a streak for bonus XP.

Feature Details
XP rate 1 XP per second worked
Level curve totalXP(n) = n * (n + 1) * 50 (Level 10 = 5,500 XP, Level 27 = 37,800 XP)
Streak bonus streak × 50 XP per session, capped at 1,000 XP
Achievements 12 achievements for milestones (early bird, night owl, streaks, hours, levels, overtime, weekend warrior)

Use /rpg to view your stats and achievements. Enable/disable via Settings or /rpgtoggle.

WorkTime League

Compete with other users on the leaderboard. Sortable by XP, Level, Streak, or Hours. Opt in via Settings or /leaguetoggle. Users without a display name appear as "Anonymous".

Salary Estimation

Estimate monthly earnings based on tracked work time. Configure your hourly rate with /setrate <amount> and currency symbol with /setcurrency <symbol> <code>. View the estimate with /salary.

Burnout Assessment

Get a 0-100 burnout score based on consecutive workdays, long hours, late-night sessions, break ratio, and work volume trends. Use /burnout.

Inline History Editing

Browse past days with the History button, then tap any event to edit its time, type, work type, or note. Add missing events or delete incorrect ones. Changes are reflected immediately in XP, streaks, and totals.

Work Types

Categorize your work sessions (e.g., Remote, Onsite, Meeting). The current work type is assigned to new clock-ins. Change via the inline menu or /worktype.

Usage

Persistent reply keyboard at the bottom of the chat: Clock In / Clock Out

Inline menu on /start:

Button Action
Clock In / Clock Out Record work event
Report Today's work & break summary
Export Pick a month → download .xlsx
History Browse past days in calendar view
Work Type Switch work type (Remote/Onsite)
Day Off Mark today as day off
RPG / Achievements View RPG stats and achievements
League View leaderboard
Salary View monthly salary estimate
Burnout View burnout assessment
Settings Timezone, calendar, accent, more

Commands

Command Action
/start Show inline menu
/settings Open settings menu
/clockin Record clock-in
/clockout Record clock-out
/worktype Change current work type
/report Today's work & break summary
/dayoff Toggle today as day off
/export [YYYY-MM] Export monthly report (optional YYYY-MM in your calendar)
/summary [YYYY-MM] Show monthly summary (optional YYYY-MM)
/history View calendar history (inline menu also)
/edit YYYY-MM-DD View/edit events for a specific date
/note [DATE] HH:MM <text> Set note for an event at a specific time
/settimezone <IANA> Set timezone (e.g. Asia/Tehran)
/setcalendar <type> Set calendar type (gregorian, jalali, hijri)
/setbreak <minutes> Set minimum break threshold (0-480, default 5)
/setaccent Select export accent color
/setreporttime HH:MM Set daily auto-report time
/reporttoggle Enable/disable daily auto-report
/rpg View RPG stats
/rpgtoggle Enable/disable RPG system
/league View WorkTime League leaderboard
/leaguetoggle Opt in/out of the league
/salary View monthly salary estimate
/setrate <amount> Set hourly rate for salary estimation
/setcurrency <sym> <code> Set currency (e.g. $ USD, T Toman, € EUR)
/burnout View burnout assessment
/setusername <name> Set display name for the league

Daily Report

A daily summary is sent automatically at the user's configured report time (default 23:00). The scheduler checks every 30 seconds.

How Break Time Works

The gap between a clock-out and the next clock-in is counted as break. Gaps shorter than the min break threshold (default 5 minutes) are absorbed into work time. Use /setbreak <minutes> to adjust per day (0-480).

09:00 Clock In     → work starts
12:00 Clock Out    → work: 3h, break starts
13:00 Clock In     → break: 1h, work resumes
17:00 Clock Out    → work: 4h
                    total: 7h work, 1h break

Export

The /export command opens a month picker. Select any month in your calendar and download an .xlsx file with columns: Date, Clock In, Clock Out, Type, Work, Break.

Four color themes are available in settings: Ocean, Beach, Rose, Catppuccin.

Project Structure

├── cmd/bot/
│   ├── main.go              Entrypoint, polling/webhook, scheduler
│   └── webhook.go           Webhook mode with TLS support
├── internal/
│   ├── domain/              Pure business logic, no external dependencies
│   │   ├── types.go         Core domain types (User, Event, Day, RPGStats, ...)
│   │   ├── constants.go     App-wide constants and thresholds
│   │   ├── dateutil.go      Gregorian/Jalali/Hijri calendar conversions
│   │   ├── totals.go        Break/work computation state machine
│   │   ├── rpg.go           XP curves, levels, streaks
│   │   ├── burnout.go       Burnout trend computation
│   │   ├── salary.go        Salary estimation, currency helpers
│   │   └── sanitize.go      Input sanitization helpers
│   ├── handler/             Telegram bot handlers (one per feature)
│   │   ├── handler.go       Core handler, routing, helpers
│   │   ├── clock.go         Clock in/out, day off, report
│   │   ├── calendar.go      History view and inline event editing
│   │   ├── export.go        Excel (.xlsx) report generation
│   │   ├── rpg.go           RPG stats, achievements, aggregates
│   │   ├── league.go        WorkTime League leaderboard
│   │   ├── salary.go        Salary estimation view
│   │   ├── burnout.go       Burnout assessment view
│   │   ├── settings.go      Settings menu with inline pickers
│   │   ├── summary.go       Monthly summary
│   │   ├── report.go        Daily report builder, status text
│   │   ├── note.go          Note command, edit command
│   │   ├── worktype.go      Work type selection
│   │   └── keyboard.go      Inline keyboard builders
│   └── repo/                Data access layer
│       ├── interface.go     Repository interface
│       ├── store.go         SQLite implementation
│       └── migrations.go    Goose-managed migration runner
│       └── migrations/      SQL migration files
│           ├── 001_init.sql Initial schema
│           └── 002_features.sql RPG, achievements, user_settings
├── .gitea/workflows/
│   └── ci.yml               Gitea Actions CI
├── Dockerfile
├── docker-compose.yml
├── Makefile
├── .env.example
└── README.md

Build & Run

# Local (requires Go 1.26+ and CGo-free SQLite)
make run

# Docker
docker compose up -d --build