From bc8a7d88692da080f30a7c42417abb046df7a4f9 Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Fri, 9 Oct 2026 17:23:17 +0700 Subject: [PATCH] feat(wordledaily): send the wordle BotFather game Cards from /wordledaily and the 07:00 push now use the BotFather game wordle, and Play answers it. The module, commands and page route keep the wordledaily name. --- docs/wordledaily.md | 4 +++- internal/modules/wordledaily/callback_test.go | 14 +++++++------- internal/modules/wordledaily/command.go | 2 +- internal/modules/wordledaily/recap.go | 2 +- internal/modules/wordledaily/recap_test.go | 2 +- internal/modules/wordledaily/wordledaily.go | 8 +++++--- 6 files changed, 18 insertions(+), 14 deletions(-) diff --git a/docs/wordledaily.md b/docs/wordledaily.md index fe996a4..d443dc9 100644 --- a/docs/wordledaily.md +++ b/docs/wordledaily.md @@ -29,7 +29,9 @@ data and scoring through `internal/modules/wordle/wordlist`. ## Setup 1. **BotFather:** create a game for the bot with `/newgame` and the short name - `wordledaily`. The share link is then `t.me/?game=wordledaily`. + `wordle`. The share link is then `t.me/?game=wordle`. The + module, its commands and its routes keep the name `wordledaily`; only the + BotFather game is `wordle`. 2. **Public URL:** this uses the same `GAME_BASE_URL` as the [noitu game](noitu-game.md#setup). The page is served at `/games/wordledaily/`. diff --git a/internal/modules/wordledaily/callback_test.go b/internal/modules/wordledaily/callback_test.go index 8aa0166..56ec1b6 100644 --- a/internal/modules/wordledaily/callback_test.go +++ b/internal/modules/wordledaily/callback_test.go @@ -50,7 +50,7 @@ func TestModule_Registration(t *testing.T) { if strings.Join(names, " ") != "wordledaily wordledaily_subscribe wordledaily_unsubscribe" { t.Fatalf("commands = %v", names) } - if len(mod.Games) != 1 || mod.Games[0].ShortName != "wordledaily" { + if len(mod.Games) != 1 || mod.Games[0].ShortName != "wordle" { t.Fatalf("games = %+v", mod.Games) } if len(mod.HTTP) != 0 || len(mod.Crons) != 0 { @@ -84,7 +84,7 @@ func TestNew_FromEnv(t *testing.T) { func TestPlay_DisabledAnswersAlert(t *testing.T) { rb := install(t, newService(config{}).module()) - rb.Bot.ProcessUpdate(context.Background(), testutil.NewGameCallback(1, 1, 5, ShortName)) + rb.Bot.ProcessUpdate(context.Background(), testutil.NewGameCallback(1, 1, 5, GameShortName)) f := answerForm(t, rb) if f["text"] != msgDisabled || f["show_alert"] != "true" || f["url"] != "" { t.Fatalf("answer = %v", f) @@ -108,7 +108,7 @@ func TestPlay_AnswersSignedURLForEveryCardForm(t *testing.T) { h := newHarness(t) rb := install(t, h.svc.module()) - topic := testutil.NewGameCallback(42, groupChat, 9, ShortName) + topic := testutil.NewGameCallback(42, groupChat, 9, GameShortName) topic.CallbackQuery.From.LastName = "Nguyen" topic.CallbackQuery.Message.Message.IsTopicMessage = true topic.CallbackQuery.Message.Message.MessageThreadID = 77 @@ -122,7 +122,7 @@ func TestPlay_AnswersSignedURLForEveryCardForm(t *testing.T) { } inaccessible := &models.Update{CallbackQuery: &models.CallbackQuery{ - ID: "q", From: models.User{ID: 42, FirstName: "A"}, GameShortName: ShortName, + ID: "q", From: models.User{ID: 42, FirstName: "A"}, GameShortName: GameShortName, Message: models.MaybeInaccessibleMessage{ Type: models.MaybeInaccessibleMessageTypeInaccessibleMessage, InaccessibleMessage: &models.InaccessibleMessage{Chat: models.Chat{ID: -5}, MessageID: 3}, @@ -133,12 +133,12 @@ func TestPlay_AnswersSignedURLForEveryCardForm(t *testing.T) { t.Fatalf("inaccessible claims = %+v", c) } - rb.Bot.ProcessUpdate(context.Background(), testutil.NewInlineGameCallback(42, "BAAAInline", ShortName)) + rb.Bot.ProcessUpdate(context.Background(), testutil.NewInlineGameCallback(42, "BAAAInline", GameShortName)) if c := decodeURLToken(t, h, answerForm(t, rb)["url"]); c.InlineID != "BAAAInline" || c.ChatID != 0 { t.Fatalf("inline claims = %+v", c) } - none := testutil.NewInlineGameCallback(42, "", ShortName) + none := testutil.NewInlineGameCallback(42, "", GameShortName) rb.Bot.ProcessUpdate(context.Background(), none) if f := answerForm(t, rb); f["text"] != msgNoGameTarget || f["show_alert"] != "true" { t.Fatalf("no target = %v", f) @@ -172,7 +172,7 @@ func TestCommand_SendsGameKeepingTopic(t *testing.T) { u.Message.MessageThreadID, u.Message.IsTopicMessage = 77, true rb.Bot.ProcessUpdate(context.Background(), u) games := sentMethod(rb, "sendGame") - if len(games) != 1 || games[0].Form["game_short_name"] != ShortName || games[0].Form["message_thread_id"] != "77" || games[0].ChatID() != "-100" { + if len(games) != 1 || games[0].Form["game_short_name"] != GameShortName || games[0].Form["message_thread_id"] != "77" || games[0].ChatID() != "-100" { t.Fatalf("sent %+v", rb.Sent()) } // A reply chain in an ordinary supergroup carries a thread id too, but diff --git a/internal/modules/wordledaily/command.go b/internal/modules/wordledaily/command.go index 38a775d..22ab44c 100644 --- a/internal/modules/wordledaily/command.go +++ b/internal/modules/wordledaily/command.go @@ -33,7 +33,7 @@ func (s *service) handleCommand(ctx context.Context, b *bot.Bot, update *models. if _, err := b.SendGame(ctx, &bot.SendGameParams{ ChatID: msg.Chat.ID, MessageThreadID: topicOf(msg), - GameShorName: ShortName, // the library's field name is misspelled + GameShorName: GameShortName, // the library's field name is misspelled }); err != nil { _ = chathelper.Reply(ctx, b, msg, msgSendGameFail) return err diff --git a/internal/modules/wordledaily/recap.go b/internal/modules/wordledaily/recap.go index 337ee3c..5a35758 100644 --- a/internal/modules/wordledaily/recap.go +++ b/internal/modules/wordledaily/recap.go @@ -83,7 +83,7 @@ func (s *service) pushTo(ctx context.Context, api telegramAPI, num int, sub subs } } } - _, err := api.SendGame(ctx, &bot.SendGameParams{ChatID: sub.ChatID, MessageThreadID: sub.ThreadID, GameShorName: ShortName}) + _, err := api.SendGame(ctx, &bot.SendGameParams{ChatID: sub.ChatID, MessageThreadID: sub.ThreadID, GameShorName: GameShortName}) return err } diff --git a/internal/modules/wordledaily/recap_test.go b/internal/modules/wordledaily/recap_test.go index 80ef24f..f22aa75 100644 --- a/internal/modules/wordledaily/recap_test.go +++ b/internal/modules/wordledaily/recap_test.go @@ -70,7 +70,7 @@ func TestPush_RecapThenCardWithCrownTiesAndLoss(t *testing.T) { t.Fatalf("not sent to the topic: %+v", c) } } - if sent[1].Form["game_short_name"] != ShortName { + if sent[1].Form["game_short_name"] != GameShortName { t.Fatalf("card = %v", sent[1].Form) } // The same puzzle is never pushed twice. diff --git a/internal/modules/wordledaily/wordledaily.go b/internal/modules/wordledaily/wordledaily.go index 36225b5..2a949c2 100644 --- a/internal/modules/wordledaily/wordledaily.go +++ b/internal/modules/wordledaily/wordledaily.go @@ -30,9 +30,11 @@ import ( ) const ( - // ShortName is the game's BotFather short name and the module's catalog - // key, so its routes live under /games/wordledaily/. + // ShortName is the module's catalog key and command name, so its routes + // live under /games/wordledaily/. ShortName = "wordledaily" + // GameShortName is the BotFather game the cards send and Play answers. + GameShortName = "wordle" subscribeCommand = ShortName + "_subscribe" unsubscribeCommand = ShortName + "_unsubscribe" @@ -203,7 +205,7 @@ func (s *service) module() modules.Module { Handler: s.handleUnsubscribe, }}, Games: []modules.Game{{ - ShortName: ShortName, + ShortName: GameShortName, Visibility: modules.VisibilityPublic, Handler: s.handlePlay, }},