Bläddra i källkod

fix(tgbot): stop auto-deleted messages from resetting wizard state

SendMsgToTgbotDeleteAfter spawns a goroutine that, after the display delay,
deleted the transient message and then unconditionally cleared the chat's
conversation state. Every caller that ends a wizard step already clears the
state synchronously, so that call was redundant — and harmful: if within
the delay the user advanced to the next step (a callback sets a fresh
awaiting_* state), the late goroutine wiped it, and the user's next message
fell through unrecognized, silently dropping their input.

Move the delayed deletion into deleteMessageAfterDelay, which only removes
the message and no longer touches the conversation state. Guard
deleteMessageTgBot against a nil bot so the deletion path is unit-testable.
MHSanaei 1 dag sedan
förälder
incheckning
588a524fa5

+ 22 - 0
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")
+	}
+}

+ 15 - 6
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,