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.
This commit is contained in:
109
README.md
109
README.md
@@ -1,6 +1,6 @@
|
||||
# WorkTime Bot
|
||||
|
||||
A single-user Telegram time-tracking bot. Clock in/out, toggle remote/onsite, mark day off, get daily reports, and export monthly Excel reports.
|
||||
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
|
||||
|
||||
@@ -10,43 +10,69 @@ cp .env.example .env
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Purpose |
|
||||
| ------------------- | ----------------------------------------------------------- |
|
||||
| `BOT_TOKEN` | Telegram Bot API token (required) |
|
||||
| `BOT_ALLOWED_USERS` | Comma-separated Telegram user IDs (empty = allow all) |
|
||||
| `HTTPS_PROXY` | Outbound proxy for Telegram API (e.g. `http://proxy:10808`) |
|
||||
| `DB_PATH` | Path to SQLite database (default: `db.sqlite3`) |
|
||||
| `BOT_WEBHOOK_URL` | Set for webhook mode (omit for polling) |
|
||||
| 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: `Clock In` / `Clock Out`
|
||||
**Persistent reply keyboard** at the bottom of the chat: `Clock In` / `Clock Out`
|
||||
|
||||
**Inline menu** on `/start`:
|
||||
|
||||
- Clock In / Clock Out
|
||||
- Report / Export
|
||||
- Toggle Remote/Onsite / Day Off
|
||||
| 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 |
|
||||
| `Clock In` or `/clockin` | Record clock-in |
|
||||
| `Clock Out` or `/clockout` | Record clock-out |
|
||||
| `/remote` | Toggle remote/onsite mode |
|
||||
| `/report` | Today's work & break summary |
|
||||
| `/export` | Monthly `.xlsx` report |
|
||||
| `/dayoff` | Toggle today as day off |
|
||||
| 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 is sent automatically at 23:00.
|
||||
## 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:
|
||||
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
|
||||
@@ -56,20 +82,43 @@ The gap between a clock-out and the next clock-in is counted as break:
|
||||
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, webhook.go
|
||||
├── cmd/bot/
|
||||
│ ├── main.go Entrypoint, polling/webhook, scheduler
|
||||
│ └── webhook.go Webhook mode with TLS support
|
||||
├── internal/
|
||||
│ ├── bot/ handlers, export, totals
|
||||
│ └── db/ SQLite store
|
||||
├── db/schema.sql Database schema
|
||||
│ ├── 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
|
||||
├── docker-compose.yml
|
||||
├── Makefile
|
||||
├── .env.example
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Build
|
||||
## Build & Run
|
||||
|
||||
```bash
|
||||
# Local (requires Go 1.26+ and CGo-free SQLite)
|
||||
make run
|
||||
|
||||
# Docker
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user