diff --git a/README.md b/README.md index 7c0152b..af6d500 100644 --- a/README.md +++ b/README.md @@ -240,9 +240,8 @@ fopost knowledge list · add · sync · delete · search fopost analytics overview · top-posts · time-series fopost automations list · get · toggle · trigger · runs fopost webhooks list · create · test · delete -fopost ads tree · pause · resume · insights · leads fopost activity list · audit -fopost ads tree · pause · resume · insights · leads · catalogs · library +fopost ads networks · tree · pause · resume · insights · leads · catalogs · library fopost completion bash · zsh · fish · powershell fopost version ``` diff --git a/go.mod b/go.mod index fde1896..cd17466 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/fopost/fopost-cli go 1.22 require ( - github.com/fopost/fopost-go v0.2.1-0.20261003215548-65ec0bbbe207 + github.com/fopost/fopost-go v0.2.1-0.20261003222702-faf657bdaf90 github.com/spf13/cobra v1.10.2 golang.org/x/term v0.27.0 ) diff --git a/go.sum b/go.sum index 1e9e0cf..716488b 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,8 @@ github.com/fopost/fopost-go v0.2.1-0.20260920195809-0f2a3f293638 h1:HyHOHnuVqcv8 github.com/fopost/fopost-go v0.2.1-0.20260920195809-0f2a3f293638/go.mod h1:Qz+7UCYTBnDEeZqB3VMrePxmYLVR9rFvx3+QWcKND8Q= github.com/fopost/fopost-go v0.2.1-0.20261003215548-65ec0bbbe207 h1:mHYksMJZWjyhMiJPmJOxa4fxvjUyaBkYjog9GWM+MnU= github.com/fopost/fopost-go v0.2.1-0.20261003215548-65ec0bbbe207/go.mod h1:Qz+7UCYTBnDEeZqB3VMrePxmYLVR9rFvx3+QWcKND8Q= +github.com/fopost/fopost-go v0.2.1-0.20261003222702-faf657bdaf90 h1:vzeOG95v+uy3sTuLYiv0PdDAIGMBGNofSD/NTB0hQ1o= +github.com/fopost/fopost-go v0.2.1-0.20261003222702-faf657bdaf90/go.mod h1:Qz+7UCYTBnDEeZqB3VMrePxmYLVR9rFvx3+QWcKND8Q= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= diff --git a/internal/cmd/ads.go b/internal/cmd/ads.go index 137a17b..60aadf2 100644 --- a/internal/cmd/ads.go +++ b/internal/cmd/ads.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "sort" "strings" fopost "github.com/fopost/fopost-go" @@ -18,6 +19,7 @@ func newAdsCmd(state *State) *cobra.Command { Short: "Inspect campaigns and catalogs, change status, and read insights, leads, the ad archive and ad comments", } cmd.AddCommand( + newAdsNetworksCmd(state), newAdsTreeCmd(state), newAdsStatusCmd(state, "pause", fopost.AdStatusPaused), newAdsStatusCmd(state, "resume", fopost.AdStatusActive), @@ -37,6 +39,52 @@ func newAdsCmd(state *State) *cobra.Command { return cmd } +func newAdsNetworksCmd(state *State) *cobra.Command { + return &cobra.Command{ + Use: "networks", + Short: "List the ad networks this deployment knows and what each one supports", + Long: "Lists every ad network in the API's registry. A network reported as not " + + "configured is listed but cannot be connected yet.", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { + client, err := state.Client() + if err != nil { + return err + } + providers, err := client.Ads.Providers(cmd.Context()) + if err != nil { + return err + } + printer := state.Printer() + return printer.Value(providers, func() { + rows := make([][]string, 0, len(providers)) + for _, provider := range providers { + rows = append(rows, []string{ + provider.ID, + output.Truncate(provider.Name, 24), + boolLabel(provider.Configured, "yes", "no"), + output.Truncate(strings.Join(provider.ConnectMethods, ", "), 20), + output.Truncate(strings.Join(capabilityNames(provider.Capabilities), ", "), 48), + }) + } + printer.Table([]string{"id", "name", "configured", "logins", "supports"}, rows) + }) + }, + } +} + +// The capabilities a network answers true for, sorted so the table is stable. +func capabilityNames(capabilities map[string]bool) []string { + names := make([]string, 0, len(capabilities)) + for name, supported := range capabilities { + if supported { + names = append(names, name) + } + } + sort.Strings(names) + return names +} + // The client and the resolved workspace, the two every ads command needs. func (s *State) clientAndWorkspace() (*fopost.Client, string, error) { client, err := s.Client()