mirror of
https://github.com/tiennm99/tiennm99bot.git
synced 2026-10-14 22:17:43 +00:00
feat(misc): add wheelofnames command
This commit is contained in:
1 parent
beebddf1d8
commit
d375029214
5 files changed
+83
-2
No files matched your search
@@ -8,7 +8,7 @@ Atlas via long polling and an in-process cron scheduler.
|
||||
| Module | What it does |
|
||||
|---|---|
|
||||
| `util` | `/help`, `/info`, `/stickerid` |
|
||||
| `misc` | `/ping`, `/ping_stats`, `/the_answer`, `/trongtruonghop` + `/tth` disclaimer |
|
||||
| `misc` | `/ping`, `/ping_stats`, `/wheelofnames`, `/the_answer`, `/trongtruonghop` + `/tth` disclaimer |
|
||||
| `wordle` | Daily Wordle game |
|
||||
| `loldle` | League-of-Legends "guess the champion" |
|
||||
| `lol` | Pro-match schedule + daily push |
|
||||
|
||||
@@ -89,6 +89,48 @@ func TestPingStats_DeniedToNonAdmin(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWheelOfNames_UsageWhenMissingOptions(t *testing.T) {
|
||||
for _, text := range []string{"/wheelofnames", "/wheelofnames , ,"} {
|
||||
t.Run(text, func(t *testing.T) {
|
||||
rb, _ := installMisc(t, 999)
|
||||
rb.Bot.ProcessUpdate(context.Background(), testutil.NewPrivateMessage(7, text))
|
||||
|
||||
if got := rb.LastSent().Text(); got != wheelOfNamesUsage {
|
||||
t.Errorf("wheelofnames reply = %q, want usage %q", got, wheelOfNamesUsage)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWheelOfNames_SingleOption(t *testing.T) {
|
||||
rb, _ := installMisc(t, 999)
|
||||
rb.Bot.ProcessUpdate(context.Background(), testutil.NewPrivateMessage(7, "/wheelofnames Alice"))
|
||||
|
||||
if got := rb.LastSent().Text(); got != "Alice" {
|
||||
t.Errorf("wheelofnames reply = %q, want Alice", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWheelOfNames_PicksFromTrimmedOptions(t *testing.T) {
|
||||
rb, _ := installMisc(t, 999)
|
||||
rb.Bot.ProcessUpdate(context.Background(), testutil.NewPrivateMessage(7, "/wheelofnames Alice, Bob, Carol"))
|
||||
|
||||
got := rb.LastSent().Text()
|
||||
if got != "Alice" && got != "Bob" && got != "Carol" {
|
||||
t.Errorf("wheelofnames reply = %q, want one of Alice/Bob/Carol", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWheelOfNames_IgnoresEmptySegments(t *testing.T) {
|
||||
rb, _ := installMisc(t, 999)
|
||||
rb.Bot.ProcessUpdate(context.Background(), testutil.NewPrivateMessage(7, "/wheelofnames , Alice , , Bob ,"))
|
||||
|
||||
got := rb.LastSent().Text()
|
||||
if got != "Alice" && got != "Bob" {
|
||||
t.Errorf("wheelofnames reply = %q, want Alice or Bob", got)
|
||||
}
|
||||
}
|
||||
|
||||
// trongTruongHopUpdate is the inline counterpart of testutil.NewPrivateMessage
|
||||
// for cases that need control over From (username, names). The dispatcher
|
||||
// requires a bot_command entity, so we lift that from the helper API by reusing
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Package misc is a small stub module that proves the framework end-to-end:
|
||||
// /ping (public, exercises KV write), /ping_stats (protected, exercises KV
|
||||
// read), /the_answer (private easter egg).
|
||||
// read), /wheelofnames (public random picker), /the_answer (private easter
|
||||
// egg).
|
||||
package misc
|
||||
|
||||
import (
|
||||
@@ -8,6 +9,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"html"
|
||||
"math/rand/v2"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -31,6 +33,8 @@ const defaultTarget = "VNG"
|
||||
// %s slots: target (escaped), sender mention, sender mention.
|
||||
const trongTruongHopTemplate = "Trong trường hợp nhóm này bị điều tra bởi %s, %s khẳng định không liên quan tới nhóm hoặc những cá nhân khác trong nhóm này. %s không rõ tại sao lại có mặt ở đây vào thời điểm này, có lẽ tài khoản đã được thêm bởi một bên thứ ba."
|
||||
|
||||
const wheelOfNamesUsage = "Usage: /wheelofnames <option1>, <option2>, ..."
|
||||
|
||||
// lastPing is the value stored at the `last_ping` key: { at: <ms-since-epoch> }.
|
||||
// int64 ms-epoch (not time.Time → RFC3339) keeps the on-disk shape compact
|
||||
// and consistent with every other timestamp field in the bot's KV.
|
||||
@@ -46,6 +50,7 @@ func New(deps modules.Deps) modules.Module {
|
||||
Commands: []modules.Command{
|
||||
pingCommand(store),
|
||||
pingStatsCommand(store),
|
||||
wheelOfNamesCommand(),
|
||||
theAnswerCommand(),
|
||||
trongTruongHopCommand("trongtruonghop"),
|
||||
trongTruongHopCommand("tth"),
|
||||
@@ -99,6 +104,35 @@ func pingStatsCommand(store storage.DocStore[lastPing]) modules.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func splitWheelOptions(arg string) []string {
|
||||
parts := strings.Split(arg, ",")
|
||||
out := make([]string, 0, len(parts))
|
||||
for _, part := range parts {
|
||||
if option := strings.TrimSpace(part); option != "" {
|
||||
out = append(out, option)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func wheelOfNamesCommand() modules.Command {
|
||||
return modules.Command{
|
||||
Name: "wheelofnames",
|
||||
Visibility: modules.VisibilityPublic,
|
||||
Description: "Pick one random comma-separated option",
|
||||
Handler: func(ctx context.Context, b *bot.Bot, update *models.Update) error {
|
||||
if update.Message == nil {
|
||||
return nil
|
||||
}
|
||||
options := splitWheelOptions(chathelper.ArgAfterCommand(update.Message.Text))
|
||||
if len(options) == 0 {
|
||||
return chathelper.Reply(ctx, b, update.Message, wheelOfNamesUsage)
|
||||
}
|
||||
return chathelper.Reply(ctx, b, update.Message, options[rand.N(len(options))])
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// senderMention renders the mention used inside the trongtruonghop template.
|
||||
// Prefer @username (Telegram resolves it server-side and enforces a safe
|
||||
// charset). Fall back to a tg://user?id link with the user's display name when
|
||||
|
||||
@@ -24,6 +24,7 @@ func TestNew_RegistersExpectedCommands(t *testing.T) {
|
||||
want := map[string]modules.Visibility{
|
||||
"ping": modules.VisibilityPublic,
|
||||
"ping_stats": modules.VisibilityProtected,
|
||||
"wheelofnames": modules.VisibilityPublic,
|
||||
"the_answer": modules.VisibilityPrivate,
|
||||
"trongtruonghop": modules.VisibilityPublic,
|
||||
"tth": modules.VisibilityPublic,
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
"command": "ping",
|
||||
"description": "Health check; replies pong"
|
||||
},
|
||||
{
|
||||
"command": "wheelofnames",
|
||||
"description": "Pick one random comma-separated option"
|
||||
},
|
||||
{
|
||||
"command": "trongtruonghop",
|
||||
"description": "Phát biểu disclaimer cho thành viên hiện tại"
|
||||
|
||||
Reference in new issue
Block a user