The provisioner records the MTProto channel id; the Bot API needs -100<id>. adapter-config now converts it, so the test channel resolves to -1004427430639. scripts/send-post.sh starts a short-lived adapter with the bot token injected from OpenBao (never printed) and sends one reviewed post. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 5457@bnt-lap001 Assistant-Session: 792bf84a-3783-4f5d-a811-cded61dd2012
129 lines
3.9 KiB
Go
129 lines
3.9 KiB
Go
package adaptercfg
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/tegwick/fluid-telegram/internal/secrets"
|
|
"github.com/tegwick/fluid-telegram/internal/spec"
|
|
"github.com/tegwick/fluid-telegram/internal/state"
|
|
)
|
|
|
|
func provisioned() *state.Resolved {
|
|
now := time.Now()
|
|
return &state.Resolved{
|
|
Campaign: "hall-of-helix",
|
|
Bot: state.Bot{Username: "HelixForgeBot", ID: 42},
|
|
Channels: map[string]state.Channel{
|
|
spec.Test: {ChatID: -1001, AdminRights: []string{spec.PostMessages}, TestPublicationAt: &now},
|
|
spec.Live: {ChatID: -2002, Username: "hallofhelix", AdminRights: []string{spec.PostMessages}},
|
|
},
|
|
}
|
|
}
|
|
|
|
func TestFromResolvedPicksOneChannel(t *testing.T) {
|
|
cfg, err := FromResolved(provisioned(), spec.Test, "bao:platform/x/bot-token")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if cfg.ChatID != -1001 || cfg.Channel != spec.Test {
|
|
t.Fatalf("got %+v", cfg)
|
|
}
|
|
cfg, err = FromResolved(provisioned(), spec.Live, "bao:platform/x/bot-token")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if cfg.ChatID != -2002 {
|
|
t.Fatalf("public chat id = %d", cfg.ChatID)
|
|
}
|
|
}
|
|
|
|
func TestFromResolvedRefusesUnprovisioned(t *testing.T) {
|
|
if _, err := FromResolved(&state.Resolved{}, spec.Test, "ref"); err == nil {
|
|
t.Fatal("accepted an empty state")
|
|
}
|
|
rs := provisioned()
|
|
delete(rs.Channels, spec.Live)
|
|
rs.Channels[spec.Test] = state.Channel{ChatID: -1001, AdminRights: []string{spec.PostMessages}}
|
|
if _, err := FromResolved(rs, spec.Live, "ref"); err == nil {
|
|
t.Fatal("accepted a public channel that has not been provisioned")
|
|
}
|
|
}
|
|
|
|
func TestEnvFileHasNoToken(t *testing.T) {
|
|
cfg, _ := FromResolved(provisioned(), spec.Test, "bao:platform/x/bot-token")
|
|
out := cfg.EnvFile()
|
|
for _, line := range strings.Split(out, "\n") {
|
|
if strings.HasPrefix(line, "TELEGRAM_BOT_TOKEN=") {
|
|
t.Fatal("env file emitted a token value")
|
|
}
|
|
}
|
|
if !strings.Contains(out, "TELEGRAM_CHANNEL_ID=-1001") {
|
|
t.Fatalf("missing chat id:\n%s", out)
|
|
}
|
|
if !strings.Contains(out, "TELEGRAM_BOT_TOKEN_REF=bao:platform/x/bot-token") {
|
|
t.Fatalf("missing token ref:\n%s", out)
|
|
}
|
|
if strings.Contains(out, "operator-session") {
|
|
t.Fatal("adapter config mentioned the operator session")
|
|
}
|
|
}
|
|
|
|
func TestLoadTokenReadsOnlyTheBotToken(t *testing.T) {
|
|
var requested []string
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
requested = append(requested, r.URL.Path)
|
|
if strings.Contains(r.URL.Path, secrets.KeyOperatorSession) {
|
|
t.Errorf("adapter requested the operator session: %s", r.URL.Path)
|
|
w.WriteHeader(http.StatusForbidden)
|
|
return
|
|
}
|
|
if !strings.HasSuffix(r.URL.Path, "/"+secrets.KeyBotToken) {
|
|
t.Errorf("unexpected path %s", r.URL.Path)
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
json.NewEncoder(w).Encode(map[string]any{
|
|
"data": map[string]any{"data": map[string]string{"token": "123:abc"}},
|
|
})
|
|
}))
|
|
t.Cleanup(srv.Close)
|
|
t.Setenv("BAO_ADDR", srv.URL)
|
|
t.Setenv("BAO_TOKEN", "test-token")
|
|
store, err := secrets.NewFromEnv("hall-of-helix")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
got, err := LoadToken(context.Background(), store)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got != "123:abc" {
|
|
t.Fatalf("token = %q", got)
|
|
}
|
|
for _, p := range requested {
|
|
if strings.Contains(p, secrets.KeyOperatorSession) || strings.Contains(p, secrets.KeyOperatorApp) {
|
|
t.Fatalf("adapter store was asked for %s", p)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBotAPIChatIDPrefixesChannelIDs(t *testing.T) {
|
|
if got := BotAPIChatID(4427430639); got != -1004427430639 {
|
|
t.Fatalf("BotAPIChatID(4427430639) = %d", got)
|
|
}
|
|
if got := BotAPIChatID(-1001); got != -1001 {
|
|
t.Fatalf("an id already in Bot API form changed: %d", got)
|
|
}
|
|
rs := provisioned()
|
|
rs.Channels[spec.Test] = state.Channel{ChatID: 4427430639, AdminRights: []string{spec.PostMessages}}
|
|
cfg, err := FromResolved(rs, spec.Test, "ref")
|
|
if err != nil || cfg.ChatID != -1004427430639 {
|
|
t.Fatalf("FromResolved chat id = %d, err %v", cfg.ChatID, err)
|
|
}
|
|
}
|