db123 d8599657f4 refactor: export full Gregorian range, add timezone fallback, cleanup rate limit, configurable schema path
- GenerateMonthlyReport now takes explicit Gregorian start/end range,
  computed via monthGregorianRange, so Jalali/Hijri months spanning
  two Gregorian months are fully covered in exports.
- Added loadLocation helper (UTC fallback on error) and replaced all
  11 ignored-error call sites in handlers + export.
- Added periodicCleanup goroutine in NewHandler to prevent unbounded
  growth of the rateLimit map.
- schemaPath is now read from SCHEMA_PATH env var (init), defaulting
  to /app/db/schema.sql.
- Migrated sendDayView to use sendOrEdit helper, removing duplicated
  send/edit branching.
- Removed dead code: userYearMonthToGregorian (unused), the old
  startOffset function (replaced).
- Updated README with calendar docs, new env vars, full project tree.
- Updated .env.example and docker-compose.yml with SCHEMA_PATH.
- Simplified Makefile: added fmt, tidy, check, run-dev targets;
  removed broken Make-glob prerequisite pattern.
2026-06-24 11:21:54 +03:30

WorkTime Bot

A single-user Telegram time-tracking bot with multi-calendar support (Gregorian, Jalali/Persian, Hijri). Clock in/out, toggle remote/onsite, mark day off, get daily reports at a configurable time, browse 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
SCHEMA_PATH /app/db/schema.sql Path to SQL schema 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.

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
Toggle Remote/Onsite Switch work type
Day Off Mark today as day off
Settings Timezone, accent, calendar type

Commands

Command Action
/start Show inline menu
/clockin Record clock-in
/clockout Record clock-out
/remote Toggle remote/onsite
/report Today's work & break summary
/export Export this month (optional YYYY-MM in your calendar)
/dayoff Toggle today as day off
/edit YYYY-MM-DD View/edit events for a specific date
/settimezone <IANA> Set timezone (e.g. Asia/Tehran)
/settings Open settings menu

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.

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/
│   ├── bot/
│   │   ├── handlers.go      Message/callback routing, views, menu builders
│   │   ├── totals.go        Break/work computation state machine
│   │   ├── export.go        Excel (.xlsx) report generation
│   │   └── dateutil.go      Gregorian/Jalali/Hijri conversions & calendars
│   └── db/
│       └── store.go         SQLite store with auto-migration
├── db/
│   └── schema.sql           Database schema
├── .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
Description
No description provided
Readme 375 KiB
Languages
Go 99.6%
Makefile 0.2%
Dockerfile 0.2%