diff --git a/atproto/atclient/cmd/atp-client-demo/main.go b/atproto/atclient/cmd/atp-client-demo/main.go index e2223e3c..0f6479b7 100644 --- a/atproto/atclient/cmd/atp-client-demo/main.go +++ b/atproto/atclient/cmd/atp-client-demo/main.go @@ -12,11 +12,11 @@ import ( "github.com/bluesky-social/indigo/atproto/identity" "github.com/bluesky-social/indigo/atproto/syntax" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) func main() { - app := cli.App{ + app := cli.Command{ Name: "atp-client-demo", Usage: "dev helper for atproto/client SDK", Commands: []*cli.Command{ @@ -117,7 +117,10 @@ func main() { } h := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug}) slog.SetDefault(slog.New(h)) - app.RunAndExitOnError() + if err := app.Run(context.Background(), os.Args); err != nil { + slog.Error("command failed", "error", err) + os.Exit(-1) + } } func getFeed(ctx context.Context, c *atclient.APIClient) error { @@ -156,37 +159,34 @@ func listRecords(ctx context.Context, c *atclient.APIClient) error { return nil } -func runGetFeedPublic(cctx *cli.Context) error { - ctx := cctx.Context +func runGetFeedPublic(ctx context.Context, cmd *cli.Command) error { c := atclient.APIClient{ - Host: cctx.String("host"), + Host: cmd.String("host"), } return getFeed(ctx, &c) } -func runListRecordsPublic(cctx *cli.Context) error { - ctx := cctx.Context +func runListRecordsPublic(ctx context.Context, cmd *cli.Command) error { c := atclient.APIClient{ - Host: cctx.String("host"), + Host: cmd.String("host"), } return listRecords(ctx, &c) } -func runLoginAuth(cctx *cli.Context) error { - ctx := cctx.Context +func runLoginAuth(ctx context.Context, cmd *cli.Command) error { - atid, err := syntax.ParseAtIdentifier(cctx.String("username")) + atid, err := syntax.ParseAtIdentifier(cmd.String("username")) if err != nil { return err } dir := identity.DefaultDirectory() - c, err := atclient.LoginWithPassword(ctx, dir, *atid, cctx.String("password"), "", nil) + c, err := atclient.LoginWithPassword(ctx, dir, *atid, cmd.String("password"), "", nil) if err != nil { return err } @@ -205,33 +205,31 @@ func runLoginAuth(cctx *cli.Context) error { return nil } -func runGetFeedAuth(cctx *cli.Context) error { - ctx := cctx.Context +func runGetFeedAuth(ctx context.Context, cmd *cli.Command) error { - atid, err := syntax.ParseAtIdentifier(cctx.String("username")) + atid, err := syntax.ParseAtIdentifier(cmd.String("username")) if err != nil { return err } dir := identity.DefaultDirectory() - c, err := atclient.LoginWithPassword(ctx, dir, *atid, cctx.String("password"), "", nil) + c, err := atclient.LoginWithPassword(ctx, dir, *atid, cmd.String("password"), "", nil) if err != nil { return err } - c = c.WithService(cctx.String("appview")) + c = c.WithService(cmd.String("appview")) return getFeed(ctx, c) } -func runLookupAdmin(cctx *cli.Context) error { - ctx := cctx.Context +func runLookupAdmin(ctx context.Context, cmd *cli.Command) error { - c := atclient.NewAdminClient(cctx.String("host"), cctx.String("admin-password")) + c := atclient.NewAdminClient(cmd.String("host"), cmd.String("admin-password")) var d json.RawMessage params := map[string]any{ - "did": cctx.String("did"), + "did": cmd.String("did"), } if err := c.Get(ctx, "com.atproto.admin.getAccountInfo", params, &d); err != nil { return err diff --git a/atproto/atcrypto/cmd/atp-crypto/main.go b/atproto/atcrypto/cmd/atp-crypto/main.go index 59f6a32c..036064ad 100644 --- a/atproto/atcrypto/cmd/atp-crypto/main.go +++ b/atproto/atcrypto/cmd/atp-crypto/main.go @@ -1,17 +1,18 @@ package main import ( + "context" "fmt" "log/slog" "os" "github.com/bluesky-social/indigo/atproto/atcrypto" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) func main() { - app := cli.App{ + app := cli.Command{ Name: "atp-crypto", Usage: "informal debugging CLI tool for atproto key and cryptography", } @@ -35,11 +36,14 @@ func main() { } h := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug}) slog.SetDefault(slog.New(h)) - app.RunAndExitOnError() + if err := app.Run(context.Background(), os.Args); err != nil { + slog.Error("command failed", "error", err) + os.Exit(-1) + } } -func runGenerate(cctx *cli.Context) error { - if cctx.Bool("k256") { +func runGenerate(ctx context.Context, cmd *cli.Command) error { + if cmd.Bool("k256") { priv, err := atcrypto.GeneratePrivateKeyK256() if err != nil { return err diff --git a/atproto/auth/oauth/cmd/oauth-web-demo/main.go b/atproto/auth/oauth/cmd/oauth-web-demo/main.go index bcbc7d6b..c8623c30 100644 --- a/atproto/auth/oauth/cmd/oauth-web-demo/main.go +++ b/atproto/auth/oauth/cmd/oauth-web-demo/main.go @@ -1,7 +1,7 @@ package main import ( - _ "embed" + "context" "encoding/json" "fmt" "html/template" @@ -10,6 +10,7 @@ import ( "os" "slices" + _ "embed" _ "github.com/joho/godotenv/autoload" "github.com/bluesky-social/indigo/atproto/atcrypto" @@ -18,11 +19,11 @@ import ( "github.com/bluesky-social/indigo/atproto/syntax" "github.com/gorilla/sessions" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) func main() { - app := cli.App{ + app := cli.Command{ Name: "oauth-web-demo", Usage: "atproto OAuth web server demo", Action: runServer, @@ -31,29 +32,32 @@ func main() { Name: "session-secret", Usage: "random string/token used for session cookie security", Required: true, - EnvVars: []string{"SESSION_SECRET"}, + Sources: cli.EnvVars("SESSION_SECRET"), }, &cli.StringFlag{ Name: "hostname", Usage: "public host name for this client (if not localhost dev mode)", - EnvVars: []string{"CLIENT_HOSTNAME"}, + Sources: cli.EnvVars("CLIENT_HOSTNAME"), }, &cli.StringFlag{ Name: "client-secret-key", Usage: "confidential client secret key. should be P-256 private key in multibase encoding", - EnvVars: []string{"CLIENT_SECRET_KEY"}, + Sources: cli.EnvVars("CLIENT_SECRET_KEY"), }, &cli.StringFlag{ Name: "client-secret-key-id", Usage: "key id for client-secret-key", Value: "primary", - EnvVars: []string{"CLIENT_SECRET_KEY_ID"}, + Sources: cli.EnvVars("CLIENT_SECRET_KEY_ID"), }, }, } h := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug}) slog.SetDefault(slog.New(h)) - app.RunAndExitOnError() + if err := app.Run(context.Background(), os.Args); err != nil { + slog.Error("command failed", "error", err) + os.Exit(-1) + } } type Server struct { @@ -77,14 +81,14 @@ var tmplLogin = template.Must(template.Must(template.New("login.html").Parse(tmp var tmplPostText string var tmplPost = template.Must(template.Must(template.New("post.html").Parse(tmplBaseText)).Parse(tmplPostText)) -func runServer(cctx *cli.Context) error { +func runServer(ctx context.Context, cmd *cli.Command) error { // the 'account:email' scope is requested only as a demo of users not granting a permission during auth flow scopes := []string{"atproto", "repo:app.bsky.feed.post?action=create", "account:email"} bind := ":8080" var config oauth.ClientConfig - hostname := cctx.String("hostname") + hostname := cmd.String("hostname") if hostname == "" { config = oauth.NewLocalhostConfig( fmt.Sprintf("http://127.0.0.1%s/oauth/callback", bind), @@ -100,12 +104,12 @@ func runServer(cctx *cli.Context) error { } // If a client secret key is provided (as a multibase string), turn this in to a confidential client - if cctx.String("client-secret-key") != "" && hostname != "" { - priv, err := atcrypto.ParsePrivateMultibase(cctx.String("client-secret-key")) + if cmd.String("client-secret-key") != "" && hostname != "" { + priv, err := atcrypto.ParsePrivateMultibase(cmd.String("client-secret-key")) if err != nil { return err } - if err := config.SetClientSecret(priv, cctx.String("client-secret-key-id")); err != nil { + if err := config.SetClientSecret(priv, cmd.String("client-secret-key-id")); err != nil { return err } slog.Info("configuring confidential OAuth client") @@ -114,7 +118,7 @@ func runServer(cctx *cli.Context) error { oauthClient := oauth.NewClientApp(&config, oauth.NewMemStore()) srv := Server{ - CookieStore: sessions.NewCookieStore([]byte(cctx.String("session-secret"))), + CookieStore: sessions.NewCookieStore([]byte(cmd.String("session-secret"))), Dir: identity.DefaultDirectory(), OAuth: oauthClient, } diff --git a/atproto/identity/cmd/atp-id/main.go b/atproto/identity/cmd/atp-id/main.go index 9d721656..c920c0e2 100644 --- a/atproto/identity/cmd/atp-id/main.go +++ b/atproto/identity/cmd/atp-id/main.go @@ -10,11 +10,11 @@ import ( "github.com/bluesky-social/indigo/atproto/identity" "github.com/bluesky-social/indigo/atproto/syntax" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) func main() { - app := cli.App{ + app := cli.Command{ Name: "atp-id", Usage: "informal debugging CLI tool for atproto identities", } @@ -40,12 +40,14 @@ func main() { } h := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug}) slog.SetDefault(slog.New(h)) - app.RunAndExitOnError() + if err := app.Run(context.Background(), os.Args); err != nil { + slog.Error("command failed", "error", err) + os.Exit(-1) + } } -func runLookup(cctx *cli.Context) error { - ctx := context.Background() - s := cctx.Args().First() +func runLookup(ctx context.Context, cmd *cli.Command) error { + s := cmd.Args().First() if s == "" { return fmt.Errorf("need to provide identifier as an argument") } @@ -65,9 +67,8 @@ func runLookup(cctx *cli.Context) error { return nil } -func runResolveHandle(cctx *cli.Context) error { - ctx := context.Background() - s := cctx.Args().First() +func runResolveHandle(ctx context.Context, cmd *cli.Command) error { + s := cmd.Args().First() if s == "" { return fmt.Errorf("need to provide handle as an argument") } @@ -87,9 +88,8 @@ func runResolveHandle(cctx *cli.Context) error { return nil } -func runResolveDID(cctx *cli.Context) error { - ctx := context.Background() - s := cctx.Args().First() +func runResolveDID(ctx context.Context, cmd *cli.Command) error { + s := cmd.Args().First() if s == "" { fmt.Println("need to provide DID as an argument") os.Exit(-1) diff --git a/atproto/lexicon/cmd/lextool/main.go b/atproto/lexicon/cmd/lextool/main.go index 9ea8d592..d63186c1 100644 --- a/atproto/lexicon/cmd/lextool/main.go +++ b/atproto/lexicon/cmd/lextool/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "encoding/json" "fmt" "io" @@ -9,11 +10,11 @@ import ( "github.com/bluesky-social/indigo/atproto/lexicon" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) func main() { - app := cli.App{ + app := cli.Command{ Name: "lex-tool", Usage: "informal debugging CLI tool for atproto lexicons", } @@ -41,11 +42,14 @@ func main() { } h := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug}) slog.SetDefault(slog.New(h)) - app.RunAndExitOnError() + if err := app.Run(context.Background(), os.Args); err != nil { + slog.Error("command failed", "error", err) + os.Exit(-1) + } } -func runParseSchema(cctx *cli.Context) error { - p := cctx.Args().First() +func runParseSchema(ctx context.Context, cmd *cli.Command) error { + p := cmd.Args().First() if p == "" { return fmt.Errorf("need to provide path to a schema file as an argument") } @@ -73,8 +77,8 @@ func runParseSchema(cctx *cli.Context) error { return nil } -func runLoadDirectory(cctx *cli.Context) error { - p := cctx.Args().First() +func runLoadDirectory(ctx context.Context, cmd *cli.Command) error { + p := cmd.Args().First() if p == "" { return fmt.Errorf("need to provide directory path as an argument") } @@ -89,8 +93,8 @@ func runLoadDirectory(cctx *cli.Context) error { return nil } -func runResolve(cctx *cli.Context) error { - ref := cctx.Args().First() +func runResolve(ctx context.Context, cmd *cli.Command) error { + ref := cmd.Args().First() if ref == "" { return fmt.Errorf("need to provide NSID as an argument") } diff --git a/atproto/lexicon/cmd/lextool/net.go b/atproto/lexicon/cmd/lextool/net.go index 1cd9ad14..6b6ea8ac 100644 --- a/atproto/lexicon/cmd/lextool/net.go +++ b/atproto/lexicon/cmd/lextool/net.go @@ -12,12 +12,11 @@ import ( "github.com/bluesky-social/indigo/atproto/lexicon" "github.com/bluesky-social/indigo/atproto/syntax" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) -func runValidateRecord(cctx *cli.Context) error { - ctx := context.Background() - args := cctx.Args().Slice() +func runValidateRecord(ctx context.Context, cmd *cli.Command) error { + args := cmd.Args().Slice() if len(args) != 2 { return fmt.Errorf("expected two args (catalog path and AT-URI)") } diff --git a/atproto/repo/cmd/repo-tool/firehose.go b/atproto/repo/cmd/repo-tool/firehose.go index 7de2a0c2..5120f5be 100644 --- a/atproto/repo/cmd/repo-tool/firehose.go +++ b/atproto/repo/cmd/repo-tool/firehose.go @@ -16,18 +16,17 @@ import ( "github.com/earthboundkid/versioninfo/v2" "github.com/gorilla/websocket" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) // write out error cases as JSON files to disk, for use in regression tests var CAPTURE_TEST_CASES = false -func runVerifyFirehose(cctx *cli.Context) error { - ctx := context.Background() +func runVerifyFirehose(ctx context.Context, cmd *cli.Command) error { - slog.SetDefault(configLogger(cctx, os.Stdout)) + slog.SetDefault(configLogger(ctx, cmd, os.Stdout)) - relayHost := cctx.String("relay-host") + relayHost := cmd.String("relay-host") dialer := websocket.DefaultDialer u, err := url.Parse(relayHost) diff --git a/atproto/repo/cmd/repo-tool/main.go b/atproto/repo/cmd/repo-tool/main.go index a1137133..44611e47 100644 --- a/atproto/repo/cmd/repo-tool/main.go +++ b/atproto/repo/cmd/repo-tool/main.go @@ -12,18 +12,18 @@ import ( "github.com/bluesky-social/indigo/atproto/repo" "github.com/bluesky-social/indigo/atproto/syntax" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) func main() { - app := cli.App{ + app := cli.Command{ Name: "repo-tool", Usage: "development tool for atproto MST trees, CAR files, etc", Flags: []cli.Flag{ &cli.StringFlag{ Name: "log-level", Usage: "log verbosity level (eg: warn, info, debug)", - EnvVars: []string{"BEEMO_LOG_LEVEL", "GO_LOG_LEVEL", "LOG_LEVEL"}, + Sources: cli.EnvVars("BEEMO_LOG_LEVEL", "GO_LOG_LEVEL", "LOG_LEVEL"), }, }, } @@ -49,19 +49,22 @@ func main() { Name: "relay-host", Usage: "method, hostname, and port of Relay instance (websocket)", Value: "wss://bsky.network", - EnvVars: []string{"ATP_RELAY_HOST"}, + Sources: cli.EnvVars("ATP_RELAY_HOST"), }, }, }, } h := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug}) slog.SetDefault(slog.New(h)) - app.RunAndExitOnError() + if err := app.Run(context.Background(), os.Args); err != nil { + slog.Error("command failed", "error", err) + os.Exit(-1) + } } -func configLogger(cctx *cli.Context, writer io.Writer) *slog.Logger { +func configLogger(ctx context.Context, cmd *cli.Command, writer io.Writer) *slog.Logger { var level slog.Level - switch strings.ToLower(cctx.String("log-level")) { + switch strings.ToLower(cmd.String("log-level")) { case "error": level = slog.LevelError case "warn": @@ -80,9 +83,8 @@ func configLogger(cctx *cli.Context, writer io.Writer) *slog.Logger { return logger } -func runVerifyCarMst(cctx *cli.Context) error { - ctx := context.Background() - p := cctx.Args().First() +func runVerifyCarMst(ctx context.Context, cmd *cli.Command) error { + p := cmd.Args().First() if p == "" { return fmt.Errorf("need to provide path to CAR file") } @@ -110,11 +112,10 @@ func runVerifyCarMst(cctx *cli.Context) error { return nil } -func runVerifyCarSignature(cctx *cli.Context) error { - ctx := context.Background() +func runVerifyCarSignature(ctx context.Context, cmd *cli.Command) error { dir := identity.DefaultDirectory() - p := cctx.Args().First() + p := cmd.Args().First() if p == "" { return fmt.Errorf("need to provide path to CAR file") } diff --git a/atproto/syntax/cmd/atp-syntax/main.go b/atproto/syntax/cmd/atp-syntax/main.go index e1410e91..7289d13f 100644 --- a/atproto/syntax/cmd/atp-syntax/main.go +++ b/atproto/syntax/cmd/atp-syntax/main.go @@ -1,17 +1,18 @@ package main import ( + "context" "fmt" "log/slog" "os" "github.com/bluesky-social/indigo/atproto/syntax" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) func main() { - app := cli.App{ + app := cli.Command{ Name: "atp-syntax", Usage: "informal debugging CLI tool for atproto syntax (identifiers)", } @@ -31,11 +32,14 @@ func main() { } h := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug}) slog.SetDefault(slog.New(h)) - app.RunAndExitOnError() + if err := app.Run(context.Background(), os.Args); err != nil { + slog.Error("command failed", "error", err) + os.Exit(-1) + } } -func runParseTID(cctx *cli.Context) error { - s := cctx.Args().First() +func runParseTID(ctx context.Context, cmd *cli.Command) error { + s := cmd.Args().First() if s == "" { return fmt.Errorf("need to provide identifier as an argument") } @@ -50,8 +54,8 @@ func runParseTID(cctx *cli.Context) error { return nil } -func runParseDID(cctx *cli.Context) error { - s := cctx.Args().First() +func runParseDID(ctx context.Context, cmd *cli.Command) error { + s := cmd.Args().First() if s == "" { return fmt.Errorf("need to provide identifier as an argument") }