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) } }