- Fix 'string(d)' int-to-rune conversion in rpg_test.go by using fmt.Sprintf - Fix ComputeDailyTotals dayStart logic: initial state should be StateWorking when dayStart > 0, correctly counting work from dayStart to first out event - Update README project structure to reflect new domain/handler/repo layout - Implement missing achievements: rpg_pioneer (on RPG enable) and salary_setter (on first rate set) - Add tryUnlockAchievement helper to Handler
92 lines
2.5 KiB
Go
92 lines
2.5 KiB
Go
package handler
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/go-telegram/bot/models"
|
|
|
|
"worktimeBot/internal/domain"
|
|
)
|
|
|
|
// handleNote handles /note [YYYY-MM-DD] HH:MM <text> command.
|
|
func (h *Handler) handleNote(ctx context.Context, msg *models.Message, user *domain.User) {
|
|
loc := h.loadLocation(user.Timezone)
|
|
parts := strings.Fields(msg.Text)
|
|
if len(parts) < 3 {
|
|
h.promptForNote(ctx, msg, user)
|
|
return
|
|
}
|
|
|
|
var dateStr string
|
|
var timeStr string
|
|
var noteParts []string
|
|
|
|
if len(parts[1]) == 10 && parts[1][4] == '-' && parts[1][7] == '-' {
|
|
dateStr = parts[1]
|
|
timeStr = parts[2]
|
|
noteParts = parts[3:]
|
|
} else {
|
|
dateStr = time.Now().In(loc).Format(domain.DateLayout)
|
|
timeStr = parts[1]
|
|
noteParts = parts[2:]
|
|
}
|
|
|
|
if len(noteParts) == 0 {
|
|
h.promptForNote(ctx, msg, user)
|
|
return
|
|
}
|
|
|
|
events, err := h.Repo.EventsForDayByDate(user.ID, dateStr)
|
|
if err != nil || len(events) == 0 {
|
|
h.sendText(ctx, msg.Chat.ID, "No events found for that day")
|
|
return
|
|
}
|
|
|
|
var targetEvent *domain.Event
|
|
for i := range events {
|
|
t := time.Unix(events[i].OccurredAt, 0).In(loc).Format(domain.TimeLayout)
|
|
if t == timeStr {
|
|
targetEvent = &events[i]
|
|
break
|
|
}
|
|
}
|
|
if targetEvent == nil {
|
|
h.sendText(ctx, msg.Chat.ID, "No event found at that time")
|
|
return
|
|
}
|
|
|
|
note := domain.SanitizeNote(strings.Join(noteParts, " "))
|
|
if err := h.Repo.SetEventNote(targetEvent.ID, note); err != nil {
|
|
h.sendText(ctx, msg.Chat.ID, "Error saving note")
|
|
return
|
|
}
|
|
h.sendText(ctx, msg.Chat.ID, "Note saved")
|
|
}
|
|
|
|
func (h *Handler) promptForNote(ctx context.Context, msg *models.Message, user *domain.User) {
|
|
h.sendText(ctx, msg.Chat.ID, "Usage: /note [YYYY-MM-DD] HH:MM <text>\nUse the History menu to add notes visually.")
|
|
}
|
|
|
|
// handleEdit handles /edit YYYY-MM-DD command.
|
|
func (h *Handler) handleEdit(ctx context.Context, msg *models.Message, user *domain.User) {
|
|
date := strings.TrimSpace(strings.TrimPrefix(msg.Text, "/edit"))
|
|
if date == "" {
|
|
h.sendText(ctx, msg.Chat.ID, "Usage: /edit YYYY-MM-DD (your calendar type)")
|
|
return
|
|
}
|
|
if len(date) != 10 || date[4] != '-' || date[7] != '-' {
|
|
h.sendText(ctx, msg.Chat.ID, "Invalid date. Use: /edit YYYY-MM-DD (your calendar type)")
|
|
return
|
|
}
|
|
_, m, d := domain.ParseGregorianDateKey(date)
|
|
if m < 1 || m > 12 || d < 1 || d > 31 {
|
|
h.sendText(ctx, msg.Chat.ID, "Invalid date.")
|
|
return
|
|
}
|
|
loc := h.loadLocation(user.Timezone)
|
|
date = domain.UserDateToGregorian(date, user.Calendar)
|
|
h.sendDayView(ctx, msg.Chat.ID, 0, user, date, loc, true)
|
|
}
|