package main import ( "encoding/json" "io" "net/http" "net/http/httptest" "os" "path/filepath" "strings" "testing" ) const goodToken = "123456789:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsawQ" func tokenFile(t *testing.T, content string) string { t.Helper() p := filepath.Join(t.TempDir(), "telegram-token") if content != "" { if err := os.WriteFile(p, []byte(content), 0o600); err != nil { t.Fatal(err) } } return p } func TestTelegramSaysWhatItLacks(t *testing.T) { for _, c := range []struct{ token, chat, says string }{ {"", "42", "not on this machine yet"}, {"r4nd0mlyMadeByTheMeshBecauseNobodyAcceptedOne", "42", "not a bot token"}, {goodToken, "", "telegram-chat-id is not given"}, {goodToken, "not a chat", "is not a chat id"}, } { tg := NewTelegram(TelegramConfig{TokenFile: tokenFile(t, c.token), ChatID: func() string { return c.chat }}) err := tg.Ready() if err == nil || !strings.Contains(err.Error(), c.says) { t.Errorf("%+v: %v", c, err) } if err != nil && strings.Contains(err.Error(), goodToken) { t.Errorf("the token is in the words") } } } func TestTelegramSendsEditsAndNeverSaysItsToken(t *testing.T) { var asked []string var bodies []map[string]any srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { asked = append(asked, r.URL.Path) raw, _ := io.ReadAll(r.Body) var b map[string]any _ = json.Unmarshal(raw, &b) bodies = append(bodies, b) switch { case strings.HasSuffix(r.URL.Path, "/sendMessage"): _, _ = w.Write([]byte(`{"ok":true,"result":{"message_id":77}}`)) case strings.HasSuffix(r.URL.Path, "/editMessageText"): _, _ = w.Write([]byte(`{"ok":false,"error_code":400,"description":"Bad Request: message to edit not found"}`)) default: _, _ = w.Write([]byte(`{"ok":true,"result":{"username":"mesh_bot"}}`)) } })) defer srv.Close() old := TelegramAPI TelegramAPI = srv.URL defer func() { TelegramAPI = old }() tg := NewTelegram(TelegramConfig{TokenFile: tokenFile(t, goodToken+"\n"), ChatID: func() string { return "-1001" }}) id, err := tg.Send(Message{Title: "URGENT: x", Body: "key: a.b.c"}) if err != nil || id != "77" { t.Fatalf("%q %v", id, err) } if asked[0] != "/bot"+goodToken+"/sendMessage" || bodies[0]["chat_id"] != "-1001" || bodies[0]["text"] != "URGENT: x\nkey: a.b.c" { t.Fatalf("%v %v", asked, bodies[0]) } err = tg.Edit("77", Message{Title: "CLEARED"}) if err == nil || !strings.Contains(err.Error(), "message to edit not found") || strings.Contains(err.Error(), goodToken) { t.Fatalf("edit: %v", err) } if bodies[1]["message_id"] != float64(77) { t.Fatalf("message id: %v", bodies[1]["message_id"]) } if who, err := tg.Who(); err != nil || who != "mesh_bot" { t.Fatalf("%q %v", who, err) } // Nothing answers: the error is in words, without the URL that carries the token. srv.Close() _, err = tg.Send(Message{Title: "x"}) if err == nil || strings.Contains(err.Error(), goodToken) || strings.Contains(err.Error(), "/bot") { t.Fatalf("unreachable: %v", err) } }