diff --git a/internal/web/service/tgbot/tgbot_delete_after_test.go b/internal/web/service/tgbot/tgbot_delete_after_test.go new file mode 100644 index 000000000..be4aa2a02 --- /dev/null +++ b/internal/web/service/tgbot/tgbot_delete_after_test.go @@ -0,0 +1,22 @@ +package tgbot + +import "testing" + +// A transient "delete after N seconds" message must not reset the conversation +// state when its timer fires: the user may have advanced to the next wizard step +// (setting a fresh state) within that window, and clearing it would silently +// drop their next input. +func TestDeleteMessageAfterDelayKeepsUserState(t *testing.T) { + userStateMgr.reset() + t.Cleanup(userStateMgr.reset) + + const chatID = int64(4242) + userStateMgr.set(chatID, "awaiting_comment") + + tg := &Tgbot{} + tg.deleteMessageAfterDelay(chatID, 1, 0) + + if st, ok := userStateMgr.get(chatID); !ok || st != "awaiting_comment" { + t.Fatalf("delayed message deletion cleared the conversation state: got (%q, %v), want (%q, true)", st, ok, "awaiting_comment") + } +} diff --git a/internal/web/service/tgbot/tgbot_send.go b/internal/web/service/tgbot/tgbot_send.go index 4578619d0..b53aa6400 100644 --- a/internal/web/service/tgbot/tgbot_send.go +++ b/internal/web/service/tgbot/tgbot_send.go @@ -228,16 +228,25 @@ func (t *Tgbot) SendMsgToTgbotDeleteAfter(chatId int64, msg string, delayInSecon return } - // Delete the sent message after the specified number of seconds - go func() { - time.Sleep(time.Duration(delayInSeconds) * time.Second) // Wait for the specified delay - t.deleteMessageTgBot(chatId, sentMsg.MessageID) // Delete the message - userStateMgr.clear(chatId) - }() + // Delete the sent message after the specified number of seconds. + go t.deleteMessageAfterDelay(chatId, sentMsg.MessageID, delayInSeconds) +} + +// deleteMessageAfterDelay waits delayInSeconds and then removes the message. It +// deliberately does not touch the conversation state: every caller that ends a +// wizard step already clears the state synchronously, and clearing it here — up +// to several seconds later — would wipe a state the user set for the next step +// in the meantime, silently dropping their following input. +func (t *Tgbot) deleteMessageAfterDelay(chatId int64, messageID, delayInSeconds int) { + time.Sleep(time.Duration(delayInSeconds) * time.Second) + t.deleteMessageTgBot(chatId, messageID) } // deleteMessageTgBot deletes a message from the chat. func (t *Tgbot) deleteMessageTgBot(chatId int64, messageID int) { + if bot == nil { + return + } params := telego.DeleteMessageParams{ ChatID: tu.ID(chatId), MessageID: messageID,