fix: address audit findings — nil pointers, timezone bug, dead code, tests, README

- Fix nil pointer dereference in clock.go (guard GetOrCreateSettings and
  GetOrCreateRPGStats errors before accessing fields)
- Fix timezone bug in handleSetBreakMsg (was using system time.Now()
  instead of user's configured timezone)
- Remove dead code: sendExportMonthPicker (unused wrapper)
- Simplify xpForWorkSeconds (xpPerSecond=1, inline to just return sec)
- Extract computeStreakFromDates as pure testable function from
  recalcAggregates; add 6 tests covering empty, current, gaps,
  no-today, long streak, longest-not-current edge cases
- Update README with full feature documentation: RPG, League, Salary,
  Burnout, Work Types, Inline History Editing, all missing commands
This commit is contained in:
2026-06-25 02:25:13 +03:30
parent 5cd811e057
commit af23f80fbb
6 changed files with 207 additions and 72 deletions

View File

@@ -64,24 +64,26 @@ func (h *Handler) clockOut(chatID int64) (string, error) {
text := fmt.Sprintf("clocked out at %s", now.Format(TimeLayout))
// Award XP and update streaks if RPG enabled
st, _ := h.DB.GetOrCreateSettings(user.ID)
if st.RPGEnabled {
st, err := h.DB.GetOrCreateSettings(user.ID)
if err == nil && st.RPGEnabled {
sessionWork := now.Unix() - last.OccurredAt
today := now.Format(DateLayout)
isWeekend := now.Weekday() == time.Saturday || now.Weekday() == time.Sunday
stats, _ := h.DB.GetOrCreateRPGStats(user.ID)
h.updateStreak(stats, user.ID, today)
xp, leveledUp, newLevel, _ := h.computeAndAwardXP(stats, user.ID, sessionWork, stats.CurrentStreak, today)
totalHours := float64(stats.TotalWorkSeconds) / secondsPerHour
unlocked := h.checkAchievements(user.ID, stats, sessionWork, today, isWeekend, totalHours)
stats, err := h.DB.GetOrCreateRPGStats(user.ID)
if err == nil {
h.updateStreak(stats, user.ID, today)
xp, leveledUp, newLevel, _ := h.computeAndAwardXP(stats, user.ID, sessionWork, stats.CurrentStreak, today)
totalHours := float64(stats.TotalWorkSeconds) / secondsPerHour
unlocked := h.checkAchievements(user.ID, stats, sessionWork, today, isWeekend, totalHours)
text += fmt.Sprintf("\n\n+%d XP (Lv.%d)", xp, newLevel)
if leveledUp {
text += "\nLevel up!"
}
for _, a := range unlocked {
text += fmt.Sprintf("\nAchievement: %s", a)
text += fmt.Sprintf("\n\n+%d XP (Lv.%d)", xp, newLevel)
if leveledUp {
text += "\nLevel up!"
}
for _, a := range unlocked {
text += fmt.Sprintf("\nAchievement: %s", a)
}
}
}