tgbot_client_draft_per_admin_test.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package tgbot
  2. import (
  3. "path/filepath"
  4. "testing"
  5. "github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
  6. "github.com/mymmrac/telego"
  7. )
  8. // Regression test: keying the add-client wizard by chat alone left the two
  9. // admins of a group chat filling in one client between them.
  10. func TestAddClientDraftIsPerAdminInGroupChat(t *testing.T) {
  11. dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
  12. const (
  13. groupChat = int64(-1001234567890)
  14. adminA = int64(8101)
  15. adminB = int64(8202)
  16. )
  17. url, textsFor := draftTexts(t)
  18. swapTestBot(t, url)
  19. origRunning := isRunning
  20. t.Cleanup(func() {
  21. isRunning = origRunning
  22. userStateMgr.reset()
  23. })
  24. isRunning = true
  25. // Both admins tap in the same chat; only the sender tells them apart.
  26. tap := func(userID int64, data string) {
  27. t.Helper()
  28. (&Tgbot{}).answerCallback(&telego.CallbackQuery{
  29. ID: "q1",
  30. From: telego.User{ID: userID},
  31. Data: data,
  32. Message: &telego.Message{MessageID: 7, Chat: telego.Chat{ID: groupChat}},
  33. }, true)
  34. }
  35. tap(adminA, "add_client_to 1")
  36. emailA := cardEmail(t, lastDraftCard(t, textsFor(groupChat)))
  37. tap(adminB, "add_client_to 2")
  38. emailB := cardEmail(t, lastDraftCard(t, textsFor(groupChat)))
  39. if emailA == "" || emailA == emailB {
  40. t.Fatalf("both admins start with email %q, want one draft per admin", emailA)
  41. }
  42. // Admin A renders again, with admin B's wizard already past its start.
  43. tap(adminA, "add_client_default_traffic_exp")
  44. if got := cardEmail(t, lastDraftCard(t, textsFor(groupChat))); got != emailA {
  45. t.Errorf("admin A's card shows email %q, want its own %q from admin B's draft", got, emailA)
  46. }
  47. // The step they are each on is their own too: A's prompt must not put B into
  48. // the same step, or B's next message lands in A's wizard.
  49. tap(adminA, "add_client_ch_default_email")
  50. if st, ok := userStateMgr.get(chatUser{chatID: groupChat, userID: adminA}); !ok || st != "awaiting_email" {
  51. t.Errorf("admin A's step = %q (set: %v), want awaiting_email", st, ok)
  52. }
  53. if st, ok := userStateMgr.get(chatUser{chatID: groupChat, userID: adminB}); ok {
  54. t.Errorf("admin B's step = %q, want none: only the tapper's step may change", st)
  55. }
  56. }
  57. // The wizard's typed steps arrive as messages, and that handler is a closure no
  58. // test can drive, so pin the key it takes there: sender, not chat.
  59. func TestMessageActorSeparatesAdminsInOneChat(t *testing.T) {
  60. const (
  61. groupChat = int64(-1001234567890)
  62. adminA = int64(8101)
  63. adminB = int64(8202)
  64. )
  65. t.Cleanup(userStateMgr.reset)
  66. fromA := messageActor(telego.Message{Chat: telego.Chat{ID: groupChat}, From: &telego.User{ID: adminA}})
  67. fromB := messageActor(telego.Message{Chat: telego.Chat{ID: groupChat}, From: &telego.User{ID: adminB}})
  68. // A channel post carries no sender and must not land on an admin's step.
  69. fromChannel := messageActor(telego.Message{Chat: telego.Chat{ID: groupChat}})
  70. if want := (chatUser{chatID: groupChat, userID: adminA}); fromA != want {
  71. t.Errorf("message from admin A keyed as %+v, want %+v", fromA, want)
  72. }
  73. if fromA == fromB || fromA == fromChannel || fromB == fromChannel {
  74. t.Fatalf("keys collide: %+v, %+v, %+v", fromA, fromB, fromChannel)
  75. }
  76. userStateMgr.set(fromA, "awaiting_email")
  77. if st, ok := userStateMgr.get(fromB); ok {
  78. t.Errorf("admin B sees step %q: admin A's answer would land in B's wizard", st)
  79. }
  80. if st, ok := userStateMgr.get(fromChannel); ok {
  81. t.Errorf("a senderless post sees step %q", st)
  82. }
  83. if st, ok := userStateMgr.get(fromA); !ok || st != "awaiting_email" {
  84. t.Errorf("admin A's step = %q (set: %v), want awaiting_email", st, ok)
  85. }
  86. }