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:
2026-06-24 11:21:54 +03:30
parent f89f5607aa
commit d8599657f4
8 changed files with 193 additions and 122 deletions

View File

@@ -1,6 +1,9 @@
package bot
import "fmt"
import (
"fmt"
"time"
)
var gregMonthDays = []int{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
var jalaliMonthDays = []int{31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29}
@@ -303,20 +306,6 @@ func userDateToGregorian(dateStr, cal string) string {
return fmt.Sprintf("%04d-%02d-%02d", y, m, d)
}
// userYearMonthToGregorian converts a (year, month) in the user's calendar
// to the corresponding Gregorian (year, month). The day is assumed to be 1.
func userYearMonthToGregorian(year, month int, cal string) (int, int) {
switch cal {
case "jalali":
gy, gm, _ := jalaliToGregorian(year, month, 1)
return gy, gm
case "hijri":
gy, gm, _ := hijriToGregorian(year, month, 1)
return gy, gm
}
return year, month
}
// monthGregorianRange returns the Gregorian start and end date strings
// for a given calendar month (cal=gregorian|jalali|hijri).
func monthGregorianRange(cal string, year, month int) (start, end string) {
@@ -340,3 +329,12 @@ func monthGregorianRange(cal string, year, month int) (start, end string) {
}
return
}
// loadLocation loads a timezone, falling back to UTC on error.
func loadLocation(tz string) *time.Location {
loc, err := time.LoadLocation(tz)
if err != nil {
return time.UTC
}
return loc
}