fix: unsilence all error returns from SQL Exec, Bot API calls, and migrations

This commit is contained in:
2026-06-24 20:03:24 +03:30
parent 4165839477
commit e7e4dc7bfe
8 changed files with 227 additions and 193 deletions

View File

@@ -4,11 +4,11 @@ import (
"context"
"database/sql"
"fmt"
"log/slog"
"strconv"
"strings"
"time"
bot "github.com/go-telegram/bot"
"github.com/go-telegram/bot/models"
"worktimeBot/internal/db"
@@ -21,7 +21,7 @@ func (h *Handler) handleHistoryMsg(ctx context.Context, msg *models.Message) {
// historyCallback opens or refreshes the calendar view (inline).
func (h *Handler) historyCallback(ctx context.Context, chatID int64, msgID int, callbackID string) {
defer h.Bot.AnswerCallbackQuery(ctx, &bot.AnswerCallbackQueryParams{CallbackQueryID: callbackID})
defer h.answerCb(ctx, callbackID)
h.editCalendar(ctx, chatID, msgID, 0, 0)
}
@@ -53,7 +53,7 @@ func (h *Handler) handleEditMsg(ctx context.Context, msg *models.Message) {
// handleHistoryCallback routes calendar-related callback data to the right handler.
func (h *Handler) handleHistoryCallback(ctx context.Context, chatID int64, msgID int, callbackID, data string) {
defer h.Bot.AnswerCallbackQuery(ctx, &bot.AnswerCallbackQueryParams{CallbackQueryID: callbackID})
defer h.answerCb(ctx, callbackID)
user, err := h.getOrCreateUser(chatID)
if err != nil {
return
@@ -256,10 +256,15 @@ func (h *Handler) editCalendar(ctx context.Context, chatID int64, msgID int, yea
if err == nil {
for rows.Next() {
var d string
rows.Scan(&d)
if err := rows.Scan(&d); err != nil {
slog.Error("failed to scan day row", "error", err)
continue
}
hasEvent[d] = true
}
rows.Close()
if err := rows.Close(); err != nil {
slog.Error("failed to close rows", "error", err)
}
}
kbRows := [][]models.InlineKeyboardButton{}
@@ -325,9 +330,7 @@ func (h *Handler) editCalendarYearPicker(ctx context.Context, chatID int64, msgI
backData := fmt.Sprintf("cal_years_back_%d_%d", refY, refM)
navSuffix := fmt.Sprintf("_%d_%d", refY, refM)
kb := buildYearPicker("cal_", backData, navSuffix, centerYear)
h.Bot.EditMessageText(ctx, &bot.EditMessageTextParams{
ChatID: chatID, MessageID: msgID, Text: "Select year:", ReplyMarkup: &kb,
})
h.editText(ctx, chatID, msgID, "Select year:", &kb)
}
// editDayView opens an existing message as a day view.
@@ -416,12 +419,17 @@ func (h *Handler) editEventType(ctx context.Context, chatID int64, msgID int, us
{Text: "Back", CallbackData: fmt.Sprintf("back_day_%d", eventID)},
})
kb := models.InlineKeyboardMarkup{InlineKeyboard: kbRows}
h.Bot.EditMessageText(ctx, &bot.EditMessageTextParams{ChatID: chatID, MessageID: msgID, Text: text, ReplyMarkup: &kb})
h.editText(ctx, chatID, msgID, text, &kb)
}
// setEventWorkType updates an event's work type and returns to the day view.
func (h *Handler) setEventWorkType(ctx context.Context, chatID int64, msgID int, user *db.User, eventID, workTypeID int64, loc *time.Location) {
h.DB.DB().Exec("UPDATE events SET work_type_id=? WHERE id=?", workTypeID, eventID)
_, err := h.DB.DB().Exec("UPDATE events SET work_type_id=? WHERE id=?", workTypeID, eventID)
if err != nil {
slog.Error("failed to update event work type", "event_id", eventID, "error", err)
h.sendDayView(ctx, chatID, msgID, user, "", loc, false)
return
}
event, err := h.getEventByID(user.ID, eventID)
if err != nil {
return
@@ -467,7 +475,7 @@ func (h *Handler) editEventTime(ctx context.Context, chatID int64, msgID int, us
func(hh int) string { return fmt.Sprintf("edittm_%d_%02d", eventID, hh) },
fmt.Sprintf("back_day_%d", eventID),
)
h.Bot.EditMessageText(ctx, &bot.EditMessageTextParams{ChatID: chatID, MessageID: msgID, Text: "Select hour:", ReplyMarkup: &kb})
h.editText(ctx, chatID, msgID, "Select hour:", &kb)
}
// editEventTimeMin shows a minute picker (15-min intervals) after hour selection.
@@ -476,7 +484,7 @@ func (h *Handler) editEventTimeMin(ctx context.Context, chatID int64, msgID int,
func(mm int) string { return fmt.Sprintf("edittm_%d_%02d_%02d", eventID, hh, mm) },
fmt.Sprintf("edit_time_%d", eventID),
)
h.Bot.EditMessageText(ctx, &bot.EditMessageTextParams{ChatID: chatID, MessageID: msgID, Text: fmt.Sprintf("Select minute for hour %02d:", hh), ReplyMarkup: &kb})
h.editText(ctx, chatID, msgID, fmt.Sprintf("Select minute for hour %02d:", hh), &kb)
}
// editEventTimeSet applies a new time to an event, checking for overlaps.
@@ -528,19 +536,24 @@ func (h *Handler) editEventTimeSet(ctx context.Context, chatID int64, msgID int,
}
for i := 1; i < len(sorted); i++ {
if sorted[i].typ == sorted[i-1].typ {
h.Bot.EditMessageText(ctx, &bot.EditMessageTextParams{ChatID: chatID, MessageID: msgID, Text: "Edit rejected: overlapping events. Two consecutive events must be different types (in/out)."})
h.editText(ctx, chatID, msgID, "Edit rejected: overlapping events. Two consecutive events must be different types (in/out).", nil)
return
}
}
}
h.DB.DB().Exec("UPDATE events SET occurred_at=? WHERE id=?", newTime.Unix(), eventID)
_, err = h.DB.DB().Exec("UPDATE events SET occurred_at=? WHERE id=?", newTime.Unix(), eventID)
if err != nil {
slog.Error("failed to update event occurred_at", "event_id", eventID, "error", err)
h.sendDayView(ctx, chatID, msgID, user, date, loc, false)
return
}
h.sendDayView(ctx, chatID, msgID, user, date, loc, false)
}
// acknowledgeCallback sends an empty acknowledgement for a callback query.
func (h *Handler) acknowledgeCallback(ctx context.Context, chatID int64, msgID int) {
h.Bot.AnswerCallbackQuery(ctx, &bot.AnswerCallbackQueryParams{CallbackQueryID: fmt.Sprintf("cb_%d_%d", chatID, msgID)})
h.answerCb(ctx, fmt.Sprintf("cb_%d_%d", chatID, msgID))
}
// promptNote asks the user to type a note for the event, then re-renders the day view.
@@ -560,10 +573,7 @@ func (h *Handler) promptNote(ctx context.Context, chatID int64, msgID int, user
{{Text: "Cancel", CallbackData: fmt.Sprintf("note_cancel_%d", eventID)}},
},
}
h.Bot.EditMessageText(ctx, &bot.EditMessageTextParams{
ChatID: chatID, MessageID: msgID,
Text: fmt.Sprintf("Send the note for event at %s:", t), ReplyMarkup: &kb,
})
h.editText(ctx, chatID, msgID, fmt.Sprintf("Send the note for event at %s:", t), &kb)
}
// deleteEventPrompt asks the user to confirm event deletion.
@@ -576,7 +586,7 @@ func (h *Handler) deleteEventPrompt(ctx context.Context, chatID int64, msgID int
},
},
}
h.Bot.EditMessageText(ctx, &bot.EditMessageTextParams{ChatID: chatID, MessageID: msgID, Text: "Delete this event?", ReplyMarkup: &kb})
h.editText(ctx, chatID, msgID, "Delete this event?", &kb)
}
// deleteEventConfirm deletes an event and warns if the timeline becomes invalid.
@@ -588,7 +598,12 @@ func (h *Handler) deleteEventConfirm(ctx context.Context, chatID int64, msgID in
t := time.Unix(event.OccurredAt, 0).In(loc)
date := t.Format("2006-01-02")
h.DB.DB().Exec("DELETE FROM events WHERE id=?", eventID)
_, err = h.DB.DB().Exec("DELETE FROM events WHERE id=?", eventID)
if err != nil {
slog.Error("failed to delete event", "event_id", eventID, "error", err)
h.sendDayView(ctx, chatID, msgID, user, date, loc, false)
return
}
// Warn if consecutive events now have the same type
events, err := h.DB.EventsForDayByDate(user.ID, date)
@@ -641,9 +656,7 @@ func (h *Handler) addEventTime(ctx context.Context, chatID int64, msgID int, use
func(hh int) string { return fmt.Sprintf("addtm_%s_%s_%02d", eventType, date, hh) },
"cal_day_"+date,
)
h.Bot.EditMessageText(ctx, &bot.EditMessageTextParams{
ChatID: chatID, MessageID: msgID, Text: fmt.Sprintf("Select hour for %s event:", eventType), ReplyMarkup: &kb,
})
h.editText(ctx, chatID, msgID, fmt.Sprintf("Select hour for %s event:", eventType), &kb)
}
// addEventTimeMin shows a minute picker (15-min intervals) after hour selection for adding an event.
@@ -652,9 +665,7 @@ func (h *Handler) addEventTimeMin(ctx context.Context, chatID int64, msgID int,
func(mm int) string { return fmt.Sprintf("addtm_%s_%s_%02d_%02d", eventType, date, hh, mm) },
"add"+eventType+"_"+date,
)
h.Bot.EditMessageText(ctx, &bot.EditMessageTextParams{
ChatID: chatID, MessageID: msgID, Text: fmt.Sprintf("Select minute for hour %02d:", hh), ReplyMarkup: &kb,
})
h.editText(ctx, chatID, msgID, fmt.Sprintf("Select minute for hour %02d:", hh), &kb)
}
// addEventDo creates a new event at the specified time and returns to the day view.