// Package cli wires up the ssm command-line interface, mirroring cli.py's // argparse-based command tree with cobra. package cli import ( "fmt" "os" "github.com/spf13/cobra" "gitea.epss.net.cn/klesh/ss/internal/core" "gitea.epss.net.cn/klesh/ss/internal/corecfg" "gitea.epss.net.cn/klesh/ss/internal/hook" "gitea.epss.net.cn/klesh/ss/internal/storage" "gitea.epss.net.cn/klesh/ss/internal/subscription" ) // managers bundles the manager instances every command needs, mirroring the // set built unconditionally in cli.py's main(). type managers struct { Storage *storage.Manager Subscription *subscription.Manager CoreConfig *corecfg.Manager Core *core.Manager Hook *hook.Manager } // newManagers builds the full manager stack. configFile/outputFile/ // subscriptionName are only ever non-empty when the "config" command tree // supplies its persistent flags, matching cli.py's main() which populates // CoreConfigManager from args.config_file/output_file/subscription // regardless of which subcommand is running (those attributes simply don't // exist on the namespace for other subcommands). func newManagers(configFile, outputFile, subscriptionName string) (*managers, error) { s, err := storage.New() if err != nil { return nil, fmt.Errorf("failed to initialize storage: %w", err) } subMgr, err := subscription.New(s) if err != nil { return nil, fmt.Errorf("failed to initialize subscription manager: %w", err) } coreCfgMgr, err := corecfg.New(subMgr, configFile, outputFile, subscriptionName) if err != nil { return nil, fmt.Errorf("failed to initialize core config manager: %w", err) } coreMgr := core.New(coreCfgMgr) hookMgr := hook.New(s) return &managers{ Storage: s, Subscription: subMgr, CoreConfig: coreCfgMgr, Core: coreMgr, Hook: hookMgr, }, nil } // Version is the ssm build version, injected at build time via // -ldflags "-X gitea.epss.net.cn/klesh/ss/internal/cli.Version=vX.Y.Z" // (see .drone.yml). Defaults to "dev" for local/unversioned builds. var Version = "dev" // Execute runs the ssm CLI. It is the Go equivalent of cli.py's main(). func Execute() { root := &cobra.Command{ Use: "ssm", Short: "Scientific Surfing - CLI for managing clash RSS subscriptions", Version: Version, SilenceUsage: true, SilenceErrors: true, } root.AddCommand( newSubscriptionCmd(), newCoreCmd(), newConfigCmd(), newServiceCmd(), newHookCmd(), ) if err := root.Execute(); err != nil { if _, silent := err.(*silentError); !silent { fmt.Printf("❌ Error: %v\n", err) } os.Exit(1) } }