https://github.com/bluesky-social/goat but with tangled's CI
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

update to urfav/cli/v3

+352 -410
+41 -50
account.go
··· 13 13 "github.com/bluesky-social/indigo/atproto/syntax" 14 14 "github.com/bluesky-social/indigo/xrpc" 15 15 16 - "github.com/urfave/cli/v2" 16 + "github.com/urfave/cli/v3" 17 17 ) 18 18 19 19 var cmdAccount = &cli.Command{ 20 20 Name: "account", 21 21 Usage: "sub-commands for auth and account management", 22 22 Flags: []cli.Flag{}, 23 - Subcommands: []*cli.Command{ 23 + Commands: []*cli.Command{ 24 24 &cli.Command{ 25 25 Name: "login", 26 26 Usage: "create session with PDS instance", ··· 30 30 Aliases: []string{"u"}, 31 31 Required: true, 32 32 Usage: "account identifier (handle or DID)", 33 - EnvVars: []string{"ATP_AUTH_USERNAME"}, 33 + Sources: cli.EnvVars("ATP_AUTH_USERNAME"), 34 34 }, 35 35 &cli.StringFlag{ 36 36 Name: "app-password", 37 37 Aliases: []string{"p"}, 38 38 Required: true, 39 39 Usage: "password (app password recommended)", 40 - EnvVars: []string{"ATP_AUTH_PASSWORD"}, 40 + Sources: cli.EnvVars("ATP_AUTH_PASSWORD"), 41 41 }, 42 42 &cli.StringFlag{ 43 43 Name: "auth-factor-token", 44 44 Usage: "token required if password is used and 2fa is required", 45 - EnvVars: []string{"ATP_AUTH_FACTOR_TOKEN"}, 45 + Sources: cli.EnvVars("ATP_AUTH_FACTOR_TOKEN"), 46 46 }, 47 47 &cli.StringFlag{ 48 48 Name: "pds-host", 49 49 Usage: "URL of the PDS to create account on (overrides DID doc)", 50 - EnvVars: []string{"ATP_PDS_HOST"}, 50 + Sources: cli.EnvVars("ATP_PDS_HOST"), 51 51 }, 52 52 }, 53 53 Action: runAccountLogin, ··· 120 120 Name: "atproto-signing-key", 121 121 Required: true, 122 122 Usage: "private key used to sign the token (multibase syntax)", 123 - EnvVars: []string{"ATPROTO_SIGNING_KEY"}, 123 + Sources: cli.EnvVars("ATPROTO_SIGNING_KEY"), 124 124 }, 125 125 &cli.StringFlag{ 126 126 Name: "iss", ··· 154 154 Name: "pds-host", 155 155 Usage: "URL of the PDS to create account on", 156 156 Required: true, 157 - EnvVars: []string{"ATP_PDS_HOST"}, 157 + Sources: cli.EnvVars("ATP_PDS_HOST"), 158 158 }, 159 159 &cli.StringFlag{ 160 160 Name: "handle", 161 161 Usage: "handle for new account", 162 162 Required: true, 163 - EnvVars: []string{"ATP_AUTH_HANDLE"}, 163 + Sources: cli.EnvVars("ATP_AUTH_HANDLE"), 164 164 }, 165 165 &cli.StringFlag{ 166 166 Name: "password", 167 167 Usage: "initial account password", 168 168 Required: true, 169 - EnvVars: []string{"ATP_AUTH_PASSWORD"}, 169 + Sources: cli.EnvVars("ATP_AUTH_PASSWORD"), 170 170 }, 171 171 &cli.StringFlag{ 172 172 Name: "invite-code", ··· 196 196 }, 197 197 } 198 198 199 - func runAccountLogin(cctx *cli.Context) error { 200 - ctx := context.Background() 199 + func runAccountLogin(ctx context.Context, cmd *cli.Command) error { 201 200 202 - username, err := syntax.ParseAtIdentifier(cctx.String("username")) 201 + username, err := syntax.ParseAtIdentifier(cmd.String("username")) 203 202 if err != nil { 204 203 return err 205 204 } 206 205 207 - _, err = refreshAuthSession(ctx, *username, cctx.String("app-password"), cctx.String("pds-host"), cctx.String("auth-factor-token")) 206 + _, err = refreshAuthSession(ctx, *username, cmd.String("app-password"), cmd.String("pds-host"), cmd.String("auth-factor-token")) 208 207 return err 209 208 } 210 209 211 - func runAccountLogout(cctx *cli.Context) error { 210 + func runAccountLogout(ctx context.Context, cmd *cli.Command) error { 212 211 return wipeAuthSession() 213 212 } 214 213 215 - func runAccountLookup(cctx *cli.Context) error { 216 - ctx := context.Background() 217 - username := cctx.Args().First() 214 + func runAccountLookup(ctx context.Context, cmd *cli.Command) error { 215 + username := cmd.Args().First() 218 216 if username == "" { 219 217 return fmt.Errorf("need to provide username as an argument") 220 218 } ··· 248 246 return nil 249 247 } 250 248 251 - func runAccountStatus(cctx *cli.Context) error { 252 - ctx := context.Background() 249 + func runAccountStatus(ctx context.Context, cmd *cli.Command) error { 253 250 254 251 client, err := loadAuthClient(ctx) 255 252 if err == ErrNoAuthSession { ··· 274 271 return nil 275 272 } 276 273 277 - func runAccountMissingBlobs(cctx *cli.Context) error { 278 - ctx := context.Background() 274 + func runAccountMissingBlobs(ctx context.Context, cmd *cli.Command) error { 279 275 280 276 client, err := loadAuthClient(ctx) 281 277 if err == ErrNoAuthSession { ··· 302 298 return nil 303 299 } 304 300 305 - func runAccountActivate(cctx *cli.Context) error { 306 - ctx := context.Background() 301 + func runAccountActivate(ctx context.Context, cmd *cli.Command) error { 307 302 308 303 client, err := loadAuthClient(ctx) 309 304 if err == ErrNoAuthSession { ··· 320 315 return nil 321 316 } 322 317 323 - func runAccountDeactivate(cctx *cli.Context) error { 324 - ctx := context.Background() 318 + func runAccountDeactivate(ctx context.Context, cmd *cli.Command) error { 325 319 326 320 client, err := loadAuthClient(ctx) 327 321 if err == ErrNoAuthSession { ··· 338 332 return nil 339 333 } 340 334 341 - func runAccountUpdateHandle(cctx *cli.Context) error { 342 - ctx := context.Background() 335 + func runAccountUpdateHandle(ctx context.Context, cmd *cli.Command) error { 343 336 344 - raw := cctx.Args().First() 337 + raw := cmd.Args().First() 345 338 if raw == "" { 346 339 return fmt.Errorf("need to provide new handle as argument") 347 340 } ··· 367 360 return nil 368 361 } 369 362 370 - func runAccountServiceAuth(cctx *cli.Context) error { 371 - ctx := context.Background() 363 + func runAccountServiceAuth(ctx context.Context, cmd *cli.Command) error { 372 364 373 365 client, err := loadAuthClient(ctx) 374 366 if err == ErrNoAuthSession { ··· 377 369 return err 378 370 } 379 371 380 - lxm := cctx.String("endpoint") 372 + lxm := cmd.String("endpoint") 381 373 if lxm != "" { 382 374 _, err := syntax.ParseNSID(lxm) 383 375 if err != nil { ··· 385 377 } 386 378 } 387 379 388 - aud := cctx.String("audience") 380 + aud := cmd.String("audience") 389 381 // TODO: can aud DID have a fragment? 390 382 _, err = syntax.ParseDID(aud) 391 383 if err != nil { 392 384 return fmt.Errorf("aud argument must be a valid DID: %w", err) 393 385 } 394 386 395 - durSec := cctx.Int("duration-sec") 387 + durSec := cmd.Int("duration-sec") 396 388 expTimestamp := time.Now().Unix() + int64(durSec) 397 389 398 390 resp, err := comatproto.ServerGetServiceAuth(ctx, client, aud, expTimestamp, lxm) ··· 405 397 return nil 406 398 } 407 399 408 - func runAccountServiceAuthOffline(cctx *cli.Context) error { 409 - privStr := cctx.String("atproto-signing-key") 400 + func runAccountServiceAuthOffline(ctx context.Context, cmd *cli.Command) error { 401 + privStr := cmd.String("atproto-signing-key") 410 402 if privStr == "" { 411 403 return fmt.Errorf("private key must be provided") 412 404 } ··· 415 407 return fmt.Errorf("failed parsing private key: %w", err) 416 408 } 417 409 418 - issString := cctx.String("iss") 410 + issString := cmd.String("iss") 419 411 // TODO: support fragment identifiers 420 412 iss, err := syntax.ParseDID(issString) 421 413 if err != nil { 422 414 return fmt.Errorf("iss argument must be a valid DID: %w", err) 423 415 } 424 416 425 - lxmString := cctx.String("endpoint") 417 + lxmString := cmd.String("endpoint") 426 418 var lxm *syntax.NSID = nil 427 419 if lxmString != "" { 428 420 lxmTmp, err := syntax.ParseNSID(lxmString) ··· 432 424 lxm = &lxmTmp 433 425 } 434 426 435 - aud := cctx.String("audience") 427 + aud := cmd.String("audience") 436 428 // TODO: can aud DID have a fragment? 437 429 _, err = syntax.ParseDID(aud) 438 430 if err != nil { 439 431 return fmt.Errorf("aud argument must be a valid DID: %w", err) 440 432 } 441 433 442 - durSec := cctx.Int("duration-sec") 434 + durSec := cmd.Int("duration-sec") 443 435 duration := time.Duration(durSec * int(time.Second)) 444 436 445 437 token, err := auth.SignServiceAuth(iss, aud, duration, lxm, privkey) ··· 452 444 return nil 453 445 } 454 446 455 - func runAccountCreate(cctx *cli.Context) error { 456 - ctx := context.Background() 447 + func runAccountCreate(ctx context.Context, cmd *cli.Command) error { 457 448 458 449 // validate args 459 - pdsHost := cctx.String("pds-host") 450 + pdsHost := cmd.String("pds-host") 460 451 if !strings.Contains(pdsHost, "://") { 461 452 return fmt.Errorf("PDS host is not a url: %s", pdsHost) 462 453 } 463 - handle := cctx.String("handle") 454 + handle := cmd.String("handle") 464 455 _, err := syntax.ParseHandle(handle) 465 456 if err != nil { 466 457 return err 467 458 } 468 - password := cctx.String("password") 459 + password := cmd.String("password") 469 460 params := &comatproto.ServerCreateAccount_Input{ 470 461 Handle: handle, 471 462 Password: &password, 472 463 } 473 - raw := cctx.String("existing-did") 464 + raw := cmd.String("existing-did") 474 465 if raw != "" { 475 466 _, err := syntax.ParseDID(raw) 476 467 if err != nil { ··· 479 470 s := raw 480 471 params.Did = &s 481 472 } 482 - raw = cctx.String("email") 473 + raw = cmd.String("email") 483 474 if raw != "" { 484 475 s := raw 485 476 params.Email = &s 486 477 } 487 - raw = cctx.String("invite-code") 478 + raw = cmd.String("invite-code") 488 479 if raw != "" { 489 480 s := raw 490 481 params.InviteCode = &s 491 482 } 492 - raw = cctx.String("recovery-key") 483 + raw = cmd.String("recovery-key") 493 484 if raw != "" { 494 485 s := raw 495 486 params.RecoveryKey = &s ··· 501 492 UserAgent: userAgent(), 502 493 } 503 494 504 - raw = cctx.String("service-auth") 495 + raw = cmd.String("service-auth") 505 496 if raw != "" && params.Did != nil { 506 497 xrpcc.Auth = &xrpc.AuthInfo{ 507 498 Did: *params.Did,
+12 -14
account_migrate.go
··· 14 14 "github.com/bluesky-social/indigo/atproto/syntax" 15 15 "github.com/bluesky-social/indigo/xrpc" 16 16 17 - "github.com/urfave/cli/v2" 17 + "github.com/urfave/cli/v3" 18 18 ) 19 19 20 20 var cmdAccountMigrate = &cli.Command{ ··· 25 25 Name: "pds-host", 26 26 Usage: "URL of the new PDS to create account on", 27 27 Required: true, 28 - EnvVars: []string{"ATP_PDS_HOST"}, 28 + Sources: cli.EnvVars("ATP_PDS_HOST"), 29 29 }, 30 30 &cli.StringFlag{ 31 31 Name: "new-handle", 32 32 Required: true, 33 33 Usage: "handle on new PDS", 34 - EnvVars: []string{"NEW_ACCOUNT_HANDLE"}, 34 + Sources: cli.EnvVars("NEW_ACCOUNT_HANDLE"), 35 35 }, 36 36 &cli.StringFlag{ 37 37 Name: "new-password", 38 38 Required: true, 39 39 Usage: "password on new PDS", 40 - EnvVars: []string{"NEW_ACCOUNT_PASSWORD"}, 40 + Sources: cli.EnvVars("NEW_ACCOUNT_PASSWORD"), 41 41 }, 42 42 &cli.StringFlag{ 43 43 Name: "plc-token", 44 44 Required: true, 45 45 Usage: "token from old PDS authorizing token signature", 46 - EnvVars: []string{"PLC_SIGN_TOKEN"}, 46 + Sources: cli.EnvVars("PLC_SIGN_TOKEN"), 47 47 }, 48 48 &cli.StringFlag{ 49 49 Name: "invite-code", ··· 57 57 Action: runAccountMigrate, 58 58 } 59 59 60 - func runAccountMigrate(cctx *cli.Context) error { 60 + func runAccountMigrate(ctx context.Context, cmd *cli.Command) error { 61 61 // NOTE: this could check rev / commit before and after and ensure last-minute content additions get lost 62 - ctx := context.Background() 63 - 64 62 oldClient, err := loadAuthClient(ctx) 65 63 if err == ErrNoAuthSession { 66 64 return fmt.Errorf("auth required, but not logged in") ··· 69 67 } 70 68 did := oldClient.Auth.Did 71 69 72 - newHostURL := cctx.String("pds-host") 70 + newHostURL := cmd.String("pds-host") 73 71 if !strings.Contains(newHostURL, "://") { 74 72 return fmt.Errorf("PDS host is not a url: %s", newHostURL) 75 73 } 76 - newHandle := cctx.String("new-handle") 74 + newHandle := cmd.String("new-handle") 77 75 _, err = syntax.ParseHandle(newHandle) 78 76 if err != nil { 79 77 return err 80 78 } 81 - newPassword := cctx.String("new-password") 82 - plcToken := cctx.String("plc-token") 83 - inviteCode := cctx.String("invite-code") 84 - newEmail := cctx.String("new-email") 79 + newPassword := cmd.String("new-password") 80 + plcToken := cmd.String("plc-token") 81 + inviteCode := cmd.String("invite-code") 82 + newEmail := cmd.String("new-email") 85 83 86 84 newClient := xrpc.Client{ 87 85 Host: newHostURL,
+17 -23
account_plc.go
··· 13 13 "github.com/bluesky-social/indigo/atproto/syntax" 14 14 "github.com/did-method-plc/go-didplc" 15 15 16 - "github.com/urfave/cli/v2" 16 + "github.com/urfave/cli/v3" 17 17 ) 18 18 19 19 var cmdAccountPlc = &cli.Command{ ··· 24 24 Name: "plc-host", 25 25 Usage: "method, hostname, and port of PLC registry", 26 26 Value: "https://plc.directory", 27 - EnvVars: []string{"ATP_PLC_HOST"}, 27 + Sources: cli.EnvVars("ATP_PLC_HOST"), 28 28 }, 29 29 }, 30 - Subcommands: []*cli.Command{ 30 + Commands: []*cli.Command{ 31 31 &cli.Command{ 32 32 Name: "recommended", 33 33 Usage: "list recommended DID fields for current account", ··· 80 80 }, 81 81 } 82 82 83 - func runAccountPlcRecommended(cctx *cli.Context) error { 84 - ctx := context.Background() 83 + func runAccountPlcRecommended(ctx context.Context, cmd *cli.Command) error { 85 84 86 85 xrpcc, err := loadAuthClient(ctx) 87 86 if err == ErrNoAuthSession { ··· 104 103 return nil 105 104 } 106 105 107 - func runAccountPlcRequestToken(cctx *cli.Context) error { 108 - ctx := context.Background() 106 + func runAccountPlcRequestToken(ctx context.Context, cmd *cli.Command) error { 109 107 110 108 xrpcc, err := loadAuthClient(ctx) 111 109 if err == ErrNoAuthSession { ··· 123 121 return nil 124 122 } 125 123 126 - func runAccountPlcSign(cctx *cli.Context) error { 127 - ctx := context.Background() 124 + func runAccountPlcSign(ctx context.Context, cmd *cli.Command) error { 128 125 129 - opPath := cctx.Args().First() 126 + opPath := cmd.Args().First() 130 127 if opPath == "" { 131 128 return fmt.Errorf("need to provide JSON file path as an argument") 132 129 } ··· 148 145 return fmt.Errorf("failed decoding PLC op JSON: %w", err) 149 146 } 150 147 151 - token := cctx.String("token") 148 + token := cmd.String("token") 152 149 if token != "" { 153 150 body.Token = &token 154 151 } ··· 167 164 return nil 168 165 } 169 166 170 - func runAccountPlcSubmit(cctx *cli.Context) error { 171 - ctx := context.Background() 167 + func runAccountPlcSubmit(ctx context.Context, cmd *cli.Command) error { 172 168 173 - opPath := cctx.Args().First() 169 + opPath := cmd.Args().First() 174 170 if opPath == "" { 175 171 return fmt.Errorf("need to provide JSON file path as an argument") 176 172 } ··· 218 214 return nil 219 215 } 220 216 221 - func runAccountPlcCurrent(cctx *cli.Context) error { 222 - ctx := context.Background() 217 + func runAccountPlcCurrent(ctx context.Context, cmd *cli.Command) error { 223 218 224 219 xrpcc, err := loadAuthClient(ctx) 225 220 if err == ErrNoAuthSession || xrpcc.Auth == nil { ··· 233 228 return err 234 229 } 235 230 236 - plcData, err := fetchPLCData(ctx, cctx.String("plc-host"), did) 231 + plcData, err := fetchPLCData(ctx, cmd.String("plc-host"), did) 237 232 if err != nil { 238 233 return err 239 234 } ··· 246 241 return nil 247 242 } 248 243 249 - func runAccountPlcAddRotationKey(cctx *cli.Context) error { 250 - ctx := context.Background() 244 + func runAccountPlcAddRotationKey(ctx context.Context, cmd *cli.Command) error { 251 245 252 - newKeyStr := cctx.Args().First() 246 + newKeyStr := cmd.Args().First() 253 247 if newKeyStr == "" { 254 248 return fmt.Errorf("need to provide public key argument (as did:key)") 255 249 } ··· 273 267 } 274 268 275 269 // 1. fetch current PLC op: plc.directory/{did}/data 276 - plcData, err := fetchPLCData(ctx, cctx.String("plc-host"), did) 270 + plcData, err := fetchPLCData(ctx, cmd.String("plc-host"), did) 277 271 if err != nil { 278 272 return err 279 273 } ··· 289 283 } 290 284 291 285 // 2. update data 292 - if cctx.Bool("first") { 286 + if cmd.Bool("first") { 293 287 plcData.RotationKeys = slices.Insert(plcData.RotationKeys, 0, newKeyStr) 294 288 } else { 295 289 plcData.RotationKeys = append(plcData.RotationKeys, newKeyStr) ··· 305 299 return fmt.Errorf("failed decoding PLC op JSON: %w", err) 306 300 } 307 301 308 - token := cctx.String("token") 302 + token := cmd.String("token") 309 303 if token != "" { 310 304 body.Token = &token 311 305 }
+1 -1
auth.go
··· 48 48 49 49 func loadAuthClient(ctx context.Context) (*xrpc.Client, error) { 50 50 51 - // TODO: could also load from env var / cctx 51 + // TODO: could also load from env var / cmd 52 52 53 53 fPath, err := xdg.SearchStateFile("goat/auth-session.json") 54 54 if err != nil {
+15 -19
blob.go
··· 10 10 comatproto "github.com/bluesky-social/indigo/api/atproto" 11 11 "github.com/bluesky-social/indigo/xrpc" 12 12 13 - "github.com/urfave/cli/v2" 13 + "github.com/urfave/cli/v3" 14 14 ) 15 15 16 16 var cmdBlob = &cli.Command{ 17 17 Name: "blob", 18 18 Usage: "sub-commands for blobs", 19 19 Flags: []cli.Flag{}, 20 - Subcommands: []*cli.Command{ 20 + Commands: []*cli.Command{ 21 21 &cli.Command{ 22 22 Name: "export", 23 23 Usage: "download all blobs for given account", ··· 66 66 }, 67 67 } 68 68 69 - func runBlobExport(cctx *cli.Context) error { 70 - ctx := context.Background() 71 - username := cctx.Args().First() 69 + func runBlobExport(ctx context.Context, cmd *cli.Command) error { 70 + username := cmd.Args().First() 72 71 if username == "" { 73 72 return fmt.Errorf("need to provide username as an argument") 74 73 } ··· 77 76 return err 78 77 } 79 78 80 - pdsHost := cctx.String("pds-host") 79 + pdsHost := cmd.String("pds-host") 81 80 if pdsHost == "" { 82 81 pdsHost = ident.PDSEndpoint() 83 82 } ··· 91 90 return fmt.Errorf("no PDS endpoint for identity") 92 91 } 93 92 94 - topDir := cctx.String("output") 93 + topDir := cmd.String("output") 95 94 if topDir == "" { 96 95 topDir = fmt.Sprintf("%s_blobs", username) 97 96 } ··· 130 129 return nil 131 130 } 132 131 133 - func runBlobList(cctx *cli.Context) error { 134 - ctx := context.Background() 135 - username := cctx.Args().First() 132 + func runBlobList(ctx context.Context, cmd *cli.Command) error { 133 + username := cmd.Args().First() 136 134 if username == "" { 137 135 return fmt.Errorf("need to provide username as an argument") 138 136 } ··· 168 166 return nil 169 167 } 170 168 171 - func runBlobDownload(cctx *cli.Context) error { 172 - ctx := context.Background() 173 - username := cctx.Args().First() 169 + func runBlobDownload(ctx context.Context, cmd *cli.Command) error { 170 + username := cmd.Args().First() 174 171 if username == "" { 175 172 return fmt.Errorf("need to provide username as an argument") 176 173 } 177 - if cctx.Args().Len() < 2 { 174 + if cmd.Args().Len() < 2 { 178 175 return fmt.Errorf("need to provide blob CID as second argument") 179 176 } 180 - blobCID := cctx.Args().Get(1) 177 + blobCID := cmd.Args().Get(1) 181 178 ident, err := resolveIdent(ctx, username) 182 179 if err != nil { 183 180 return err ··· 192 189 return fmt.Errorf("no PDS endpoint for identity") 193 190 } 194 191 195 - blobPath := cctx.String("output") 192 + blobPath := cmd.String("output") 196 193 if blobPath == "" { 197 194 blobPath = blobCID 198 195 } ··· 209 206 return os.WriteFile(blobPath, blobBytes, 0666) 210 207 } 211 208 212 - func runBlobUpload(cctx *cli.Context) error { 213 - ctx := context.Background() 214 - blobPath := cctx.Args().First() 209 + func runBlobUpload(ctx context.Context, cmd *cli.Command) error { 210 + blobPath := cmd.Args().First() 215 211 if blobPath == "" { 216 212 return fmt.Errorf("need to provide file path as an argument") 217 213 }
+4 -5
bsky.go
··· 9 9 "github.com/bluesky-social/indigo/atproto/syntax" 10 10 lexutil "github.com/bluesky-social/indigo/lex/util" 11 11 12 - "github.com/urfave/cli/v2" 12 + "github.com/urfave/cli/v3" 13 13 ) 14 14 15 15 var cmdBsky = &cli.Command{ 16 16 Name: "bsky", 17 17 Usage: "sub-commands for bsky app", 18 18 Flags: []cli.Flag{}, 19 - Subcommands: []*cli.Command{ 19 + Commands: []*cli.Command{ 20 20 &cli.Command{ 21 21 Name: "post", 22 22 Usage: "create a post", ··· 27 27 }, 28 28 } 29 29 30 - func runBskyPost(cctx *cli.Context) error { 31 - ctx := context.Background() 32 - text := cctx.Args().First() 30 + func runBskyPost(ctx context.Context, cmd *cli.Command) error { 31 + text := cmd.Args().First() 33 32 if text == "" { 34 33 return fmt.Errorf("need to provide post text as argument") 35 34 }
+5 -7
bsky_prefs.go
··· 8 8 9 9 "github.com/bluesky-social/indigo/api/agnostic" 10 10 11 - "github.com/urfave/cli/v2" 11 + "github.com/urfave/cli/v3" 12 12 ) 13 13 14 14 var cmdBskyPrefs = &cli.Command{ 15 15 Name: "prefs", 16 16 Usage: "sub-commands for preferences", 17 17 Flags: []cli.Flag{}, 18 - Subcommands: []*cli.Command{ 18 + Commands: []*cli.Command{ 19 19 &cli.Command{ 20 20 Name: "export", 21 21 Usage: "dump preferences out as JSON", ··· 30 30 }, 31 31 } 32 32 33 - func runBskyPrefsExport(cctx *cli.Context) error { 34 - ctx := context.Background() 33 + func runBskyPrefsExport(ctx context.Context, cmd *cli.Command) error { 35 34 36 35 xrpcc, err := loadAuthClient(ctx) 37 36 if err == ErrNoAuthSession { ··· 55 54 return nil 56 55 } 57 56 58 - func runBskyPrefsImport(cctx *cli.Context) error { 59 - ctx := context.Background() 60 - prefsPath := cctx.Args().First() 57 + func runBskyPrefsImport(ctx context.Context, cmd *cli.Command) error { 58 + prefsPath := cmd.Args().First() 61 59 if prefsPath == "" { 62 60 return fmt.Errorf("need to provide file path as an argument") 63 61 }
+21 -22
firehose.go
··· 23 23 lexutil "github.com/bluesky-social/indigo/lex/util" 24 24 25 25 "github.com/gorilla/websocket" 26 - "github.com/urfave/cli/v2" 26 + "github.com/urfave/cli/v3" 27 27 ) 28 28 29 29 var cmdFirehose = &cli.Command{ ··· 34 34 Name: "relay-host", 35 35 Usage: "method, hostname, and port of Relay instance (websocket)", 36 36 Value: "wss://bsky.network", 37 - EnvVars: []string{"ATP_RELAY_HOST", "RELAY_HOST"}, 37 + Sources: cli.EnvVars("ATP_RELAY_HOST", "RELAY_HOST"), 38 38 }, 39 39 &cli.IntFlag{ 40 40 Name: "cursor", ··· 93 93 Dir identity.Directory 94 94 } 95 95 96 - func runFirehose(cctx *cli.Context) error { 97 - ctx := context.Background() 96 + func runFirehose(ctx context.Context, cmd *cli.Command) error { 98 97 99 - slog.SetDefault(configLogger(cctx, os.Stderr)) 98 + slog.SetDefault(configLogger(cmd, os.Stderr)) 100 99 101 100 // main thing is skipping handle verification 102 101 bdir := identity.BaseDirectory{ ··· 108 107 cdir := identity.NewCacheDirectory(&bdir, 1_000_000, time.Hour*24, time.Minute*2, time.Minute*5) 109 108 110 109 gfc := GoatFirehoseConsumer{ 111 - OpsMode: cctx.Bool("ops"), 112 - AccountsOnly: cctx.Bool("account-events"), 113 - CollectionFilter: cctx.StringSlice("collection"), 114 - Quiet: cctx.Bool("quiet"), 115 - Blocks: cctx.Bool("blocks"), 116 - VerifyBasic: cctx.Bool("verify-basic"), 117 - VerifySig: cctx.Bool("verify-sig"), 118 - VerifyMST: cctx.Bool("verify-mst"), 110 + OpsMode: cmd.Bool("ops"), 111 + AccountsOnly: cmd.Bool("account-events"), 112 + CollectionFilter: cmd.StringSlice("collection"), 113 + Quiet: cmd.Bool("quiet"), 114 + Blocks: cmd.Bool("blocks"), 115 + VerifyBasic: cmd.Bool("verify-basic"), 116 + VerifySig: cmd.Bool("verify-sig"), 117 + VerifyMST: cmd.Bool("verify-mst"), 119 118 Dir: &cdir, 120 119 } 121 120 122 121 var relayHost string 123 - if cctx.IsSet("relay-host") { 124 - if cctx.Args().Len() != 0 { 122 + if cmd.IsSet("relay-host") { 123 + if cmd.Args().Len() != 0 { 125 124 return errors.New("error: unused positional args") 126 125 } 127 - relayHost = cctx.String("relay-host") 126 + relayHost = cmd.String("relay-host") 128 127 } else { 129 - if cctx.Args().Len() == 1 { 130 - relayHost = cctx.Args().First() 131 - } else if cctx.Args().Len() > 1 { 128 + if cmd.Args().Len() == 1 { 129 + relayHost = cmd.Args().First() 130 + } else if cmd.Args().Len() > 1 { 132 131 return errors.New("can only have at most one relay-host") 133 132 } else { 134 - relayHost = cctx.String("relay-host") 133 + relayHost = cmd.String("relay-host") 135 134 } 136 135 } 137 136 ··· 147 146 u.Scheme = "wss" 148 147 } 149 148 u.Path = "xrpc/com.atproto.sync.subscribeRepos" 150 - if cctx.IsSet("cursor") { 151 - u.RawQuery = fmt.Sprintf("cursor=%d", cctx.Int("cursor")) 149 + if cmd.IsSet("cursor") { 150 + u.RawQuery = fmt.Sprintf("cursor=%d", cmd.Int("cursor")) 152 151 } 153 152 urlString := u.String() 154 153 con, _, err := dialer.Dial(urlString, http.Header{
+1 -4
go.mod
··· 14 14 github.com/ipfs/go-ipld-cbor v0.2.1 15 15 github.com/ipfs/go-ipld-format v0.6.2 16 16 github.com/joho/godotenv v1.5.1 17 - github.com/urfave/cli/v2 v2.27.7 17 + github.com/urfave/cli/v3 v3.4.1 18 18 github.com/xlab/treeprint v1.2.0 19 19 ) 20 20 ··· 23 23 github.com/beorn7/perks v1.0.1 // indirect 24 24 github.com/carlmjohnson/versioninfo v0.22.5 // indirect 25 25 github.com/cespare/xxhash/v2 v2.3.0 // indirect 26 - github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect 27 26 github.com/felixge/httpsnoop v1.0.4 // indirect 28 27 github.com/go-logr/logr v1.4.2 // indirect 29 28 github.com/go-logr/stdr v1.2.2 // indirect ··· 71 70 github.com/prometheus/common v0.63.0 // indirect 72 71 github.com/prometheus/procfs v0.16.1 // indirect 73 72 github.com/rivo/uniseg v0.1.0 // indirect 74 - github.com/russross/blackfriday/v2 v2.1.0 // indirect 75 73 github.com/spaolacci/murmur3 v1.1.0 // indirect 76 74 github.com/whyrusleeping/cbor-gen v0.3.1 // indirect 77 - github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect 78 75 gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect 79 76 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect 80 77 go.opentelemetry.io/auto/sdk v1.1.0 // indirect
+2 -8
go.sum
··· 14 14 github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 15 15 github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 16 16 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 17 - github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= 18 - github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= 19 17 github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0= 20 18 github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis= 21 19 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= ··· 278 276 github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= 279 277 github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= 280 278 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 281 - github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= 282 - github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 283 279 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 284 280 github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= 285 281 github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= ··· 295 291 github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 296 292 github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 297 293 github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 298 - github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU= 299 - github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4= 294 + github.com/urfave/cli/v3 v3.4.1 h1:1M9UOCy5bLmGnuu1yn3t3CB4rG79Rtoxuv1sPhnm6qM= 295 + github.com/urfave/cli/v3 v3.4.1/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= 300 296 github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s= 301 297 github.com/warpfork/go-testmark v0.12.1/go.mod h1:kHwy7wfvGSPh1rQJYKayD4AbtNaeyZdcGi9tNJTaa5Y= 302 298 github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= ··· 309 305 github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= 310 306 github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= 311 307 github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= 312 - github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= 313 - github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= 314 308 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 315 309 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 316 310 gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b h1:CzigHMRySiX3drau9C6Q5CAbNIApmLdat5jPMqChvDA=
+5 -6
identity.go
··· 8 8 "github.com/bluesky-social/indigo/atproto/identity" 9 9 "github.com/bluesky-social/indigo/atproto/syntax" 10 10 11 - "github.com/urfave/cli/v2" 11 + "github.com/urfave/cli/v3" 12 12 ) 13 13 14 14 var cmdResolve = &cli.Command{ ··· 24 24 Action: runResolve, 25 25 } 26 26 27 - func runResolve(cctx *cli.Context) error { 28 - ctx := context.Background() 29 - s := cctx.Args().First() 27 + func runResolve(ctx context.Context, cmd *cli.Command) error { 28 + s := cmd.Args().First() 30 29 if s == "" { 31 30 return fmt.Errorf("need to provide account identifier as an argument") 32 31 } ··· 43 42 if err != nil { 44 43 return err 45 44 } 46 - if cctx.Bool("did") { 45 + if cmd.Bool("did") { 47 46 fmt.Println(did) 48 47 return nil 49 48 } ··· 60 59 if err != nil { 61 60 return err 62 61 } 63 - if cctx.Bool("did") { 62 + if cmd.Bool("did") { 64 63 fmt.Println(did) 65 64 return nil 66 65 }
+9 -8
key.go
··· 1 1 package main 2 2 3 3 import ( 4 + "context" 4 5 "fmt" 5 6 6 7 "github.com/bluesky-social/indigo/atproto/crypto" 7 8 8 - "github.com/urfave/cli/v2" 9 + "github.com/urfave/cli/v3" 9 10 ) 10 11 11 12 var cmdKey = &cli.Command{ 12 13 Name: "key", 13 14 Usage: "sub-commands for cryptographic keys", 14 - Subcommands: []*cli.Command{ 15 + Commands: []*cli.Command{ 15 16 &cli.Command{ 16 17 Name: "generate", 17 18 Usage: "outputs a new secret key", ··· 37 38 }, 38 39 } 39 40 40 - func runKeyGenerate(cctx *cli.Context) error { 41 + func runKeyGenerate(ctx context.Context, cmd *cli.Command) error { 41 42 var priv crypto.PrivateKey 42 43 var privMultibase string 43 - switch cctx.String("type") { 44 + switch cmd.String("type") { 44 45 case "", "P-256", "p256", "ES256", "secp256r1": 45 46 sec, err := crypto.GeneratePrivateKeyP256() 46 47 if err != nil { ··· 56 57 privMultibase = sec.Multibase() 57 58 priv = sec 58 59 default: 59 - return fmt.Errorf("unknown key type: %s", cctx.String("type")) 60 + return fmt.Errorf("unknown key type: %s", cmd.String("type")) 60 61 } 61 - if cctx.Bool("terse") { 62 + if cmd.Bool("terse") { 62 63 fmt.Println(privMultibase) 63 64 return nil 64 65 } ··· 87 88 } 88 89 } 89 90 90 - func runKeyInspect(cctx *cli.Context) error { 91 - s := cctx.Args().First() 91 + func runKeyInspect(ctx context.Context, cmd *cli.Command) error { 92 + s := cmd.Args().First() 92 93 if s == "" { 93 94 return fmt.Errorf("need to provide key as an argument") 94 95 }
+20 -23
lexicon.go
··· 1 1 package main 2 2 3 3 import ( 4 + "context" 4 5 "encoding/json" 5 6 "fmt" 6 7 "io" ··· 14 15 "github.com/bluesky-social/indigo/atproto/syntax" 15 16 "github.com/bluesky-social/indigo/xrpc" 16 17 17 - "github.com/urfave/cli/v2" 18 + "github.com/urfave/cli/v3" 18 19 ) 19 20 20 21 var cmdLex = &cli.Command{ 21 22 Name: "lex", 22 23 Usage: "sub-commands for Lexicons", 23 24 Flags: []cli.Flag{}, 24 - Subcommands: []*cli.Command{ 25 + Commands: []*cli.Command{ 25 26 &cli.Command{ 26 27 Name: "resolve", 27 28 Usage: "lookup a schema for an NSID", ··· 102 103 return d, nil 103 104 } 104 105 105 - func runLexParse(cctx *cli.Context) error { 106 - if cctx.Args().Len() <= 0 { 106 + func runLexParse(ctx context.Context, cmd *cli.Command) error { 107 + if cmd.Args().Len() <= 0 { 107 108 return fmt.Errorf("require at least one path to parse") 108 109 } 109 - for _, path := range cctx.Args().Slice() { 110 + for _, path := range cmd.Args().Slice() { 110 111 _, err := loadSchemaFile(path) 111 112 if err != nil { 112 113 return fmt.Errorf("failed to parse %s: %w", path, err) ··· 116 117 return nil 117 118 } 118 119 119 - func runLexPublish(cctx *cli.Context) error { 120 - if cctx.Args().Len() <= 0 { 120 + func runLexPublish(ctx context.Context, cmd *cli.Command) error { 121 + if cmd.Args().Len() <= 0 { 121 122 return fmt.Errorf("require at least one path to publish") 122 123 } 123 124 124 - ctx := cctx.Context 125 125 xrpcc, err := loadAuthClient(ctx) 126 126 if err == ErrNoAuthSession { 127 127 return fmt.Errorf("auth required, but not logged in") ··· 131 131 132 132 validateFlag := false 133 133 134 - for _, path := range cctx.Args().Slice() { 134 + for _, path := range cmd.Args().Slice() { 135 135 recordVal, err := loadSchemaFile(path) 136 136 if err != nil { 137 137 return fmt.Errorf("failed to parse %s: %w", path, err) ··· 168 168 return nil 169 169 } 170 170 171 - func runLexResolve(cctx *cli.Context) error { 172 - ctx := cctx.Context 173 - raw := cctx.Args().First() 171 + func runLexResolve(ctx context.Context, cmd *cli.Command) error { 172 + raw := cmd.Args().First() 174 173 if raw == "" { 175 174 return fmt.Errorf("NSID argument is required") 176 175 } ··· 182 181 } 183 182 184 183 dir := identity.BaseDirectory{} 185 - if cctx.Bool("did") { 184 + if cmd.Bool("did") { 186 185 did, err := dir.ResolveNSID(ctx, nsid) 187 186 if err != nil { 188 187 return err ··· 205 204 return nil 206 205 } 207 206 208 - func runLexList(cctx *cli.Context) error { 209 - ctx := cctx.Context 210 - raw := cctx.Args().First() 207 + func runLexList(ctx context.Context, cmd *cli.Command) error { 208 + raw := cmd.Args().First() 211 209 if raw == "" { 212 210 return fmt.Errorf("NSID argument is required") 213 211 } ··· 271 269 return nil 272 270 } 273 271 274 - func runLexValidate(cctx *cli.Context) error { 275 - ctx := cctx.Context 276 - ref := cctx.Args().First() 272 + func runLexValidate(ctx context.Context, cmd *cli.Command) error { 273 + ref := cmd.Args().First() 277 274 if ref == "" { 278 275 return fmt.Errorf("URI or file path argument is required") 279 276 } ··· 284 281 cat := lexicon.NewResolvingCatalog() 285 282 286 283 var flags lexicon.ValidateFlags = 0 287 - if cctx.Bool("allow-legacy-blob") { 284 + if cmd.Bool("allow-legacy-blob") { 288 285 flags |= lexicon.AllowLegacyBlob 289 286 } 290 287 291 - if cctx.String("catalog") != "" { 292 - fmt.Printf("loading catalog directory: %s\n", cctx.String("catalog")) 293 - if err := cat.Base.LoadDirectory(cctx.String("catalog")); err != nil { 288 + if cmd.String("catalog") != "" { 289 + fmt.Printf("loading catalog directory: %s\n", cmd.String("catalog")) 290 + if err := cat.Base.LoadDirectory(cmd.String("catalog")); err != nil { 294 291 return err 295 292 } 296 293 }
+5 -4
main.go
··· 1 1 package main 2 2 3 3 import ( 4 + "context" 4 5 "fmt" 5 6 "os" 6 7 7 8 _ "github.com/joho/godotenv/autoload" 8 9 9 10 "github.com/earthboundkid/versioninfo/v2" 10 - "github.com/urfave/cli/v2" 11 + "github.com/urfave/cli/v3" 11 12 ) 12 13 13 14 func main() { ··· 19 20 20 21 func run(args []string) error { 21 22 22 - app := cli.App{ 23 + app := cli.Command{ 23 24 Name: "goat", 24 25 Usage: "Go AT protocol CLI tool", 25 26 Version: versioninfo.Short(), ··· 27 28 &cli.StringFlag{ 28 29 Name: "log-level", 29 30 Usage: "log verbosity level (eg: warn, info, debug)", 30 - EnvVars: []string{"GOAT_LOG_LEVEL", "GO_LOG_LEVEL", "LOG_LEVEL"}, 31 + Sources: cli.EnvVars("GOAT_LOG_LEVEL", "GO_LOG_LEVEL", "LOG_LEVEL"), 31 32 }, 32 33 }, 33 34 } ··· 48 49 cmdPds, 49 50 cmdRelay, 50 51 } 51 - return app.Run(args) 52 + return app.Run(context.Background(), args) 52 53 }
+4 -5
pds.go
··· 9 9 comatproto "github.com/bluesky-social/indigo/api/atproto" 10 10 "github.com/bluesky-social/indigo/xrpc" 11 11 12 - "github.com/urfave/cli/v2" 12 + "github.com/urfave/cli/v3" 13 13 ) 14 14 15 15 var cmdPds = &cli.Command{ 16 16 Name: "pds", 17 17 Usage: "sub-commands for pds hosts", 18 18 Flags: []cli.Flag{}, 19 - Subcommands: []*cli.Command{ 19 + Commands: []*cli.Command{ 20 20 &cli.Command{ 21 21 Name: "describe", 22 22 Usage: "shows info about a PDS info", ··· 26 26 }, 27 27 } 28 28 29 - func runPdsDescribe(cctx *cli.Context) error { 30 - ctx := context.Background() 29 + func runPdsDescribe(ctx context.Context, cmd *cli.Command) error { 31 30 32 - pdsHost := cctx.Args().First() 31 + pdsHost := cmd.Args().First() 33 32 if pdsHost == "" { 34 33 return fmt.Errorf("need to provide new handle as argument") 35 34 }
+40 -45
plc.go
··· 17 17 18 18 "github.com/did-method-plc/go-didplc" 19 19 20 - "github.com/urfave/cli/v2" 20 + "github.com/urfave/cli/v3" 21 21 ) 22 22 23 23 var cmdPLC = &cli.Command{ ··· 28 28 Name: "plc-host", 29 29 Usage: "method, hostname, and port of PLC registry", 30 30 Value: "https://plc.directory", 31 - EnvVars: []string{"ATP_PLC_HOST"}, 31 + Sources: cli.EnvVars("ATP_PLC_HOST"), 32 32 }, 33 33 }, 34 - Subcommands: []*cli.Command{ 34 + Commands: []*cli.Command{ 35 35 &cli.Command{ 36 36 Name: "history", 37 37 Usage: "fetch operation log for individual DID", ··· 113 113 &cli.StringFlag{ 114 114 Name: "plc-signing-key", 115 115 Usage: "private key used to sign operation (multibase syntax)", 116 - EnvVars: []string{"PLC_SIGNING_KEY"}, 116 + Sources: cli.EnvVars("PLC_SIGNING_KEY"), 117 117 }, 118 118 }, 119 119 Action: runPLCSign, ··· 169 169 }, 170 170 } 171 171 172 - func runPLCHistory(cctx *cli.Context) error { 173 - ctx := context.Background() 174 - plcHost := cctx.String("plc-host") 175 - s := cctx.Args().First() 172 + func runPLCHistory(ctx context.Context, cmd *cli.Command) error { 173 + plcHost := cmd.String("plc-host") 174 + s := cmd.Args().First() 176 175 if s == "" { 177 176 return fmt.Errorf("need to provide account identifier as an argument") 178 177 } ··· 238 237 return nil 239 238 } 240 239 241 - func runPLCData(cctx *cli.Context) error { 242 - ctx := context.Background() 243 - plcHost := cctx.String("plc-host") 244 - s := cctx.Args().First() 240 + func runPLCData(ctx context.Context, cmd *cli.Command) error { 241 + plcHost := cmd.String("plc-host") 242 + s := cmd.Args().First() 245 243 if s == "" { 246 244 return fmt.Errorf("need to provide account identifier as an argument") 247 245 } ··· 288 286 return nil 289 287 } 290 288 291 - func runPLCDump(cctx *cli.Context) error { 292 - ctx := context.Background() 293 - plcHost := cctx.String("plc-host") 289 + func runPLCDump(ctx context.Context, cmd *cli.Command) error { 290 + plcHost := cmd.String("plc-host") 294 291 client := util.RobustHTTPClient() 295 - size := cctx.Int("batch-size") 296 - tailMode := cctx.Bool("tail") 297 - interval := cctx.Duration("interval") 292 + size := cmd.Int("batch-size") 293 + tailMode := cmd.Bool("tail") 294 + interval := cmd.Duration("interval") 298 295 299 - cursor := cctx.String("cursor") 296 + cursor := cmd.String("cursor") 300 297 if cursor == "now" { 301 298 cursor = syntax.DatetimeNow().String() 302 299 } ··· 416 413 return &d, nil 417 414 } 418 415 419 - func runPLCGenesis(cctx *cli.Context) error { 416 + func runPLCGenesis(ctx context.Context, cmd *cli.Command) error { 420 417 // TODO: helper function in didplc to make an empty op like this? 421 418 services := make(map[string]didplc.OpService) 422 419 verifMethods := make(map[string]string) ··· 428 425 Services: services, 429 426 } 430 427 431 - for _, rotationKey := range cctx.StringSlice("rotation-key") { 428 + for _, rotationKey := range cmd.StringSlice("rotation-key") { 432 429 if _, err := crypto.ParsePublicDIDKey(rotationKey); err != nil { 433 430 return err 434 431 } 435 432 op.RotationKeys = append(op.RotationKeys, rotationKey) 436 433 } 437 434 438 - handle := cctx.String("handle") 435 + handle := cmd.String("handle") 439 436 if handle != "" { 440 437 parsedHandle, err := syntax.ParseHandle(strings.TrimPrefix(handle, "at://")) 441 438 if err != nil { ··· 445 442 op.AlsoKnownAs = append(op.AlsoKnownAs, "at://"+string(parsedHandle)) 446 443 } 447 444 448 - atprotoKey := cctx.String("atproto-key") 445 + atprotoKey := cmd.String("atproto-key") 449 446 if atprotoKey != "" { 450 447 if _, err := crypto.ParsePublicDIDKey(atprotoKey); err != nil { 451 448 return err ··· 453 450 op.VerificationMethods["atproto"] = atprotoKey 454 451 } 455 452 456 - pds := cctx.String("pds") 453 + pds := cmd.String("pds") 457 454 if pds != "" { 458 455 parsedUrl, err := url.Parse(pds) 459 456 if err != nil { ··· 477 474 return nil 478 475 } 479 476 480 - func runPLCCalcDID(cctx *cli.Context) error { 481 - s := cctx.Args().First() 477 + func runPLCCalcDID(ctx context.Context, cmd *cli.Command) error { 478 + s := cmd.Args().First() 482 479 if s == "" { 483 480 return fmt.Errorf("need to provide genesis json path as input") 484 481 } ··· 509 506 return nil 510 507 } 511 508 512 - func runPLCSign(cctx *cli.Context) error { 513 - s := cctx.Args().First() 509 + func runPLCSign(ctx context.Context, cmd *cli.Command) error { 510 + s := cmd.Args().First() 514 511 if s == "" { 515 512 return fmt.Errorf("need to provide PLC operation json path as input") 516 513 } 517 514 518 - privStr := cctx.String("plc-signing-key") 515 + privStr := cmd.String("plc-signing-key") 519 516 if privStr == "" { 520 517 return fmt.Errorf("private key must be provided (HINT: use `goat account plc` if your PDS holds the keys)") 521 518 } ··· 557 554 return nil 558 555 } 559 556 560 - func runPLCSubmit(cctx *cli.Context) error { 561 - ctx := context.Background() 562 - expectGenesis := cctx.Bool("genesis") 563 - didString := cctx.String("did") 557 + func runPLCSubmit(ctx context.Context, cmd *cli.Command) error { 558 + expectGenesis := cmd.Bool("genesis") 559 + didString := cmd.String("did") 564 560 565 561 if !expectGenesis && didString == "" { 566 562 return fmt.Errorf("exactly one of either --genesis or --did must be specified") ··· 570 566 return fmt.Errorf("exactly one of either --genesis or --did must be specified") 571 567 } 572 568 573 - s := cctx.Args().First() 569 + s := cmd.Args().First() 574 570 if s == "" { 575 571 return fmt.Errorf("need to provide PLC operation json path as input") 576 572 } ··· 611 607 } 612 608 613 609 c := didplc.Client{ 614 - DirectoryURL: cctx.String("plc-host"), 610 + DirectoryURL: cmd.String("plc-host"), 615 611 UserAgent: *userAgent(), 616 612 } 617 613 ··· 669 665 return &op, nil 670 666 } 671 667 672 - func runPLCUpdate(cctx *cli.Context) error { 673 - ctx := context.Background() 674 - prevCID := cctx.String("prev") 668 + func runPLCUpdate(ctx context.Context, cmd *cli.Command) error { 669 + prevCID := cmd.String("prev") 675 670 676 - didString := cctx.Args().First() 671 + didString := cmd.Args().First() 677 672 if didString == "" { 678 673 return fmt.Errorf("please specify a DID to update") 679 674 } 680 675 681 676 c := didplc.Client{ 682 - DirectoryURL: cctx.String("plc-host"), 677 + DirectoryURL: cmd.String("plc-host"), 683 678 UserAgent: *userAgent(), 684 679 } 685 680 op, err := fetchOpForUpdate(ctx, c, didString, prevCID) ··· 687 682 return err 688 683 } 689 684 690 - for _, rotationKey := range cctx.StringSlice("remove-rotation-key") { 685 + for _, rotationKey := range cmd.StringSlice("remove-rotation-key") { 691 686 if _, err := crypto.ParsePublicDIDKey(rotationKey); err != nil { 692 687 return err 693 688 } ··· 703 698 } 704 699 } 705 700 706 - for _, rotationKey := range cctx.StringSlice("add-rotation-key") { 701 + for _, rotationKey := range cmd.StringSlice("add-rotation-key") { 707 702 if _, err := crypto.ParsePublicDIDKey(rotationKey); err != nil { 708 703 return err 709 704 } ··· 711 706 op.RotationKeys = append([]string{rotationKey}, op.RotationKeys...) 712 707 } 713 708 714 - handle := cctx.String("handle") 709 + handle := cmd.String("handle") 715 710 if handle != "" { 716 711 parsedHandle, err := syntax.ParseHandle(strings.TrimPrefix(handle, "at://")) 717 712 if err != nil { ··· 730 725 op.AlsoKnownAs = append(akas, "at://"+string(parsedHandle)) 731 726 } 732 727 733 - atprotoKey := cctx.String("atproto-key") 728 + atprotoKey := cmd.String("atproto-key") 734 729 if atprotoKey != "" { 735 730 if _, err := crypto.ParsePublicDIDKey(atprotoKey); err != nil { 736 731 return err ··· 738 733 op.VerificationMethods["atproto"] = atprotoKey 739 734 } 740 735 741 - pds := cctx.String("pds") 736 + pds := cmd.String("pds") 742 737 if pds != "" { 743 738 parsedUrl, err := url.Parse(pds) 744 739 if err != nil {
+20 -25
record.go
··· 13 13 "github.com/bluesky-social/indigo/atproto/syntax" 14 14 "github.com/bluesky-social/indigo/xrpc" 15 15 16 - "github.com/urfave/cli/v2" 16 + "github.com/urfave/cli/v3" 17 17 ) 18 18 19 19 var cmdRecord = &cli.Command{ 20 20 Name: "record", 21 21 Usage: "sub-commands for repo records", 22 22 Flags: []cli.Flag{}, 23 - Subcommands: []*cli.Command{ 23 + Commands: []*cli.Command{ 24 24 cmdRecordGet, 25 25 cmdRecordList, 26 26 &cli.Command{ ··· 109 109 Action: runRecordList, 110 110 } 111 111 112 - func runRecordGet(cctx *cli.Context) error { 113 - ctx := context.Background() 112 + func runRecordGet(ctx context.Context, cmd *cli.Command) error { 114 113 dir := identity.DefaultDirectory() 115 114 116 - uriArg := cctx.Args().First() 115 + uriArg := cmd.Args().First() 117 116 if uriArg == "" { 118 117 return fmt.Errorf("expected a single AT-URI argument") 119 118 } ··· 141 140 return nil 142 141 } 143 142 144 - func runRecordList(cctx *cli.Context) error { 145 - ctx := context.Background() 146 - username := cctx.Args().First() 143 + func runRecordList(ctx context.Context, cmd *cli.Command) error { 144 + username := cmd.Args().First() 147 145 if username == "" { 148 146 return fmt.Errorf("need to provide username as an argument") 149 147 } ··· 165 163 if err != nil { 166 164 return err 167 165 } 168 - if cctx.Bool("collections") { 166 + if cmd.Bool("collections") { 169 167 for _, nsid := range desc.Collections { 170 168 fmt.Printf("%s\n", nsid) 171 169 } 172 170 return nil 173 171 } 174 172 collections := desc.Collections 175 - filter := cctx.String("collection") 173 + filter := cmd.String("collection") 176 174 if filter != "" { 177 175 collections = []string{filter} 178 176 } ··· 203 201 return nil 204 202 } 205 203 206 - func runRecordCreate(cctx *cli.Context) error { 207 - ctx := context.Background() 208 - recordPath := cctx.Args().First() 204 + func runRecordCreate(ctx context.Context, cmd *cli.Command) error { 205 + recordPath := cmd.Args().First() 209 206 if recordPath == "" { 210 207 return fmt.Errorf("need to provide file path as an argument") 211 208 } ··· 233 230 } 234 231 235 232 var rkey *string 236 - if cctx.String("rkey") != "" { 237 - rk, err := syntax.ParseRecordKey(cctx.String("rkey")) 233 + if cmd.String("rkey") != "" { 234 + rk, err := syntax.ParseRecordKey(cmd.String("rkey")) 238 235 if err != nil { 239 236 return err 240 237 } 241 238 s := rk.String() 242 239 rkey = &s 243 240 } 244 - validate := !cctx.Bool("no-validate") 241 + validate := !cmd.Bool("no-validate") 245 242 246 243 resp, err := agnostic.RepoCreateRecord(ctx, xrpcc, &agnostic.RepoCreateRecord_Input{ 247 244 Collection: nsid, ··· 258 255 return nil 259 256 } 260 257 261 - func runRecordUpdate(cctx *cli.Context) error { 262 - ctx := context.Background() 263 - recordPath := cctx.Args().First() 258 + func runRecordUpdate(ctx context.Context, cmd *cli.Command) error { 259 + recordPath := cmd.Args().First() 264 260 if recordPath == "" { 265 261 return fmt.Errorf("need to provide file path as an argument") 266 262 } ··· 287 283 return err 288 284 } 289 285 290 - rkey := cctx.String("rkey") 286 + rkey := cmd.String("rkey") 291 287 292 288 // NOTE: need to fetch existing record CID to perform swap. this is optional in theory, but golang can't deal with "optional" and "nullable", so we always need to set this (?) 293 289 existing, err := agnostic.RepoGetRecord(ctx, xrpcc, "", nsid, xrpcc.Auth.Did, rkey) ··· 295 291 return err 296 292 } 297 293 298 - validate := !cctx.Bool("no-validate") 294 + validate := !cmd.Bool("no-validate") 299 295 300 296 resp, err := agnostic.RepoPutRecord(ctx, xrpcc, &agnostic.RepoPutRecord_Input{ 301 297 Collection: nsid, ··· 313 309 return nil 314 310 } 315 311 316 - func runRecordDelete(cctx *cli.Context) error { 317 - ctx := context.Background() 312 + func runRecordDelete(ctx context.Context, cmd *cli.Command) error { 318 313 319 314 xrpcc, err := loadAuthClient(ctx) 320 315 if err == ErrNoAuthSession { ··· 323 318 return err 324 319 } 325 320 326 - rkey, err := syntax.ParseRecordKey(cctx.String("rkey")) 321 + rkey, err := syntax.ParseRecordKey(cmd.String("rkey")) 327 322 if err != nil { 328 323 return err 329 324 } 330 - collection, err := syntax.ParseNSID(cctx.String("collection")) 325 + collection, err := syntax.ParseNSID(cmd.String("collection")) 331 326 if err != nil { 332 327 return err 333 328 }
+34 -40
relay.go
··· 10 10 "github.com/bluesky-social/indigo/atproto/syntax" 11 11 "github.com/bluesky-social/indigo/xrpc" 12 12 13 - "github.com/urfave/cli/v2" 13 + "github.com/urfave/cli/v3" 14 14 ) 15 15 16 16 var cmdRelay = &cli.Command{ ··· 21 21 Name: "relay-host", 22 22 Usage: "method, hostname, and port of Relay instance", 23 23 Value: "https://bsky.network", 24 - EnvVars: []string{"ATP_RELAY_HOST", "RELAY_HOST"}, 24 + Sources: cli.EnvVars("ATP_RELAY_HOST", "RELAY_HOST"), 25 25 }, 26 26 }, 27 - Subcommands: []*cli.Command{ 27 + Commands: []*cli.Command{ 28 28 &cli.Command{ 29 29 Name: "account", 30 30 Usage: "sub-commands for accounts/repos on relay", 31 - Subcommands: []*cli.Command{ 31 + Commands: []*cli.Command{ 32 32 &cli.Command{ 33 33 Name: "list", 34 34 Aliases: []string{"ls"}, ··· 63 63 &cli.Command{ 64 64 Name: "host", 65 65 Usage: "sub-commands for upstream hosts (eg, PDS)", 66 - Subcommands: []*cli.Command{ 66 + Commands: []*cli.Command{ 67 67 &cli.Command{ 68 68 Name: "request-crawl", 69 69 Aliases: []string{"add"}, ··· 118 118 }, 119 119 } 120 120 121 - func runRelayAccountList(cctx *cli.Context) error { 122 - ctx := cctx.Context 121 + func runRelayAccountList(ctx context.Context, cmd *cli.Command) error { 123 122 124 - if cctx.Args().Len() > 0 { 123 + if cmd.Args().Len() > 0 { 125 124 return fmt.Errorf("unexpected arguments") 126 125 } 127 126 128 127 client := xrpc.Client{ 129 - Host: cctx.String("relay-host"), 128 + Host: cmd.String("relay-host"), 130 129 UserAgent: userAgent(), 131 130 } 132 131 133 - collection := cctx.String("collection") 132 + collection := cmd.String("collection") 134 133 cursor := "" 135 134 var size int64 = 500 136 135 for { ··· 154 153 } 155 154 156 155 for _, r := range resp.Repos { 157 - if cctx.Bool("json") { 156 + if cmd.Bool("json") { 158 157 b, err := json.Marshal(r) 159 158 if err != nil { 160 159 return err ··· 180 179 return nil 181 180 } 182 181 183 - func runRelayAccountStatus(cctx *cli.Context) error { 184 - ctx := cctx.Context 182 + func runRelayAccountStatus(ctx context.Context, cmd *cli.Command) error { 185 183 186 - didStr := cctx.Args().First() 184 + didStr := cmd.Args().First() 187 185 if didStr == "" { 188 186 return fmt.Errorf("need to provide account DID as argument") 189 187 } 190 - if cctx.Args().Len() != 1 { 188 + if cmd.Args().Len() != 1 { 191 189 return fmt.Errorf("unexpected arguments") 192 190 } 193 191 ··· 197 195 } 198 196 199 197 client := xrpc.Client{ 200 - Host: cctx.String("relay-host"), 198 + Host: cmd.String("relay-host"), 201 199 UserAgent: userAgent(), 202 200 } 203 201 ··· 206 204 return err 207 205 } 208 206 209 - if cctx.Bool("json") { 207 + if cmd.Bool("json") { 210 208 b, err := json.Marshal(r) 211 209 if err != nil { 212 210 return err ··· 229 227 return nil 230 228 } 231 229 232 - func runRelayHostRequestCrawl(cctx *cli.Context) error { 233 - ctx := cctx.Context 230 + func runRelayHostRequestCrawl(ctx context.Context, cmd *cli.Command) error { 234 231 235 - hostname := cctx.Args().First() 232 + hostname := cmd.Args().First() 236 233 if hostname == "" { 237 234 return fmt.Errorf("need to provide hostname as argument") 238 235 } 239 - if cctx.Args().Len() != 1 { 236 + if cmd.Args().Len() != 1 { 240 237 return fmt.Errorf("unexpected arguments") 241 238 } 242 239 243 240 client := xrpc.Client{ 244 - Host: cctx.String("relay-host"), 241 + Host: cmd.String("relay-host"), 245 242 UserAgent: userAgent(), 246 243 } 247 244 ··· 253 250 return nil 254 251 } 255 252 256 - func runRelayHostList(cctx *cli.Context) error { 257 - ctx := cctx.Context 253 + func runRelayHostList(ctx context.Context, cmd *cli.Command) error { 258 254 259 - if cctx.Args().Len() > 0 { 255 + if cmd.Args().Len() > 0 { 260 256 return fmt.Errorf("unexpected arguments") 261 257 } 262 258 263 259 client := xrpc.Client{ 264 - Host: cctx.String("relay-host"), 260 + Host: cmd.String("relay-host"), 265 261 UserAgent: userAgent(), 266 262 } 267 263 ··· 274 270 } 275 271 276 272 for _, h := range resp.Hosts { 277 - if cctx.Bool("json") { 273 + if cmd.Bool("json") { 278 274 b, err := json.Marshal(h) 279 275 if err != nil { 280 276 return err ··· 305 301 return nil 306 302 } 307 303 308 - func runRelayHostStatus(cctx *cli.Context) error { 309 - ctx := cctx.Context 304 + func runRelayHostStatus(ctx context.Context, cmd *cli.Command) error { 310 305 311 - hostname := cctx.Args().First() 306 + hostname := cmd.Args().First() 312 307 if hostname == "" { 313 308 return fmt.Errorf("need to provide hostname as argument") 314 309 } 315 - if cctx.Args().Len() != 1 { 310 + if cmd.Args().Len() != 1 { 316 311 return fmt.Errorf("unexpected arguments") 317 312 } 318 313 319 314 client := xrpc.Client{ 320 - Host: cctx.String("relay-host"), 315 + Host: cmd.String("relay-host"), 321 316 UserAgent: userAgent(), 322 317 } 323 318 ··· 326 321 return err 327 322 } 328 323 329 - if cctx.Bool("json") { 324 + if cmd.Bool("json") { 330 325 b, err := json.Marshal(h) 331 326 if err != nil { 332 327 return err ··· 395 390 return hosts, nil 396 391 } 397 392 398 - func runRelayHostDiff(cctx *cli.Context) error { 399 - ctx := cctx.Context 400 - verbose := cctx.Bool("verbose") 401 - seqSlop := cctx.Int64("seq-slop") 393 + func runRelayHostDiff(ctx context.Context, cmd *cli.Command) error { 394 + verbose := cmd.Bool("verbose") 395 + seqSlop := cmd.Int64("seq-slop") 402 396 403 - if cctx.Args().Len() != 2 { 397 + if cmd.Args().Len() != 2 { 404 398 return fmt.Errorf("expected two relay URLs are args") 405 399 } 406 400 407 - urlOne := cctx.Args().Get(0) 408 - urlTwo := cctx.Args().Get(1) 401 + urlOne := cmd.Args().Get(0) 402 + urlTwo := cmd.Args().Get(1) 409 403 410 404 listOne, err := fetchHosts(ctx, urlOne) 411 405 if err != nil {
+41 -41
relay_admin.go
··· 2 2 3 3 import ( 4 4 "bytes" 5 + "context" 5 6 "encoding/base64" 6 7 "encoding/json" 7 8 "fmt" ··· 10 11 "net/http" 11 12 "net/url" 12 13 13 - "github.com/urfave/cli/v2" 14 + "github.com/urfave/cli/v3" 14 15 ) 15 16 16 17 var cmdRelayAdmin = &cli.Command{ ··· 20 21 &cli.StringFlag{ 21 22 Name: "admin-password", 22 23 Usage: "relay admin password (for Basic admin auth)", 23 - EnvVars: []string{"RELAY_ADMIN_PASSWORD", "ATP_AUTH_ADMIN_PASSWORD"}, 24 + Sources: cli.EnvVars("RELAY_ADMIN_PASSWORD", "ATP_AUTH_ADMIN_PASSWORD"), 24 25 }, 25 26 &cli.StringFlag{ 26 27 Name: "admin-bearer-token", 27 28 Usage: "relay admin auth token (for Bearer auth)", 28 - EnvVars: []string{"RELAY_ADMIN_BEARER_TOKEN"}, 29 + Sources: cli.EnvVars("RELAY_ADMIN_BEARER_TOKEN"), 29 30 }, 30 31 }, 31 - Subcommands: []*cli.Command{ 32 + Commands: []*cli.Command{ 32 33 &cli.Command{ 33 34 Name: "account", 34 35 Usage: "sub-commands for managing accounts", 35 - Subcommands: []*cli.Command{ 36 + Commands: []*cli.Command{ 36 37 &cli.Command{ 37 38 Name: "takedown", 38 39 Usage: "takedown a single account on relay", ··· 60 61 &cli.Command{ 61 62 Name: "host", 62 63 Usage: "sub-commands for upstream hosts (eg, PDS)", 63 - Subcommands: []*cli.Command{ 64 + Commands: []*cli.Command{ 64 65 &cli.Command{ 65 66 Name: "add", 66 67 Usage: "request crawl of upstream host (eg, PDS)", ··· 101 102 &cli.Command{ 102 103 Name: "domain", 103 104 Usage: "sub-commands for domain-level config", 104 - Subcommands: []*cli.Command{ 105 + Commands: []*cli.Command{ 105 106 &cli.Command{ 106 107 Name: "ban", 107 108 Usage: "ban an entire domain name from being crawled", ··· 125 126 &cli.Command{ 126 127 Name: "consumer", 127 128 Usage: "sub-commands for consumers", 128 - Subcommands: []*cli.Command{ 129 + Commands: []*cli.Command{ 129 130 &cli.Command{ 130 131 Name: "list", 131 132 Aliases: []string{"ls"}, ··· 200 201 return respBytes, nil 201 202 } 202 203 203 - func NewRelayAdminClient(cctx *cli.Context) (*RelayAdminClient, error) { 204 + func NewRelayAdminClient(cmd *cli.Command) (*RelayAdminClient, error) { 204 205 client := RelayAdminClient{ 205 - Host: cctx.String("relay-host"), 206 - Password: cctx.String("admin-password"), 207 - BearerToken: cctx.String("admin-bearer-token"), 206 + Host: cmd.String("relay-host"), 207 + Password: cmd.String("admin-password"), 208 + BearerToken: cmd.String("admin-bearer-token"), 208 209 } 209 210 if client.Password == "" && client.BearerToken == "" { 210 211 return nil, fmt.Errorf("either admin password or admin bearer token must be provided") ··· 212 213 return &client, nil 213 214 } 214 215 215 - func runRelayAdminAccountTakedown(cctx *cli.Context) error { 216 - ctx := cctx.Context 216 + func runRelayAdminAccountTakedown(ctx context.Context, cmd *cli.Command) error { 217 217 218 - username := cctx.Args().First() 218 + username := cmd.Args().First() 219 219 if username == "" { 220 220 return fmt.Errorf("need to provide username as an argument") 221 221 } ··· 224 224 return err 225 225 } 226 226 227 - client, err := NewRelayAdminClient(cctx) 227 + client, err := NewRelayAdminClient(cmd) 228 228 if err != nil { 229 229 return err 230 230 } 231 231 232 232 path := "/admin/repo/takeDown" 233 - if cctx.Bool("reverse") { 233 + if cmd.Bool("reverse") { 234 234 path = "/admin/repo/reverseTakedown" 235 235 } 236 236 ··· 244 244 return nil 245 245 } 246 246 247 - func runRelayAdminAccountList(cctx *cli.Context) error { 248 - client, err := NewRelayAdminClient(cctx) 247 + func runRelayAdminAccountList(ctx context.Context, cmd *cli.Command) error { 248 + client, err := NewRelayAdminClient(cmd) 249 249 if err != nil { 250 250 return err 251 251 } ··· 275 275 return nil 276 276 } 277 277 278 - func runRelayAdminHostAdd(cctx *cli.Context) error { 278 + func runRelayAdminHostAdd(ctx context.Context, cmd *cli.Command) error { 279 279 280 - hostname := cctx.Args().First() 280 + hostname := cmd.Args().First() 281 281 if hostname == "" { 282 282 return fmt.Errorf("need to provide hostname as an argument") 283 283 } 284 284 285 - client, err := NewRelayAdminClient(cctx) 285 + client, err := NewRelayAdminClient(cmd) 286 286 if err != nil { 287 287 return err 288 288 } ··· 297 297 return nil 298 298 } 299 299 300 - func runRelayAdminHostBlock(cctx *cli.Context) error { 300 + func runRelayAdminHostBlock(ctx context.Context, cmd *cli.Command) error { 301 301 302 - hostname := cctx.Args().First() 302 + hostname := cmd.Args().First() 303 303 if hostname == "" { 304 304 return fmt.Errorf("need to provide hostname as an argument") 305 305 } 306 306 307 - client, err := NewRelayAdminClient(cctx) 307 + client, err := NewRelayAdminClient(cmd) 308 308 if err != nil { 309 309 return err 310 310 } 311 311 312 312 path := "/admin/pds/block" 313 - if cctx.Bool("reverse") { 313 + if cmd.Bool("reverse") { 314 314 path = "/admin/pds/unblock" 315 315 } 316 316 ··· 324 324 return nil 325 325 } 326 326 327 - func runRelayAdminHostList(cctx *cli.Context) error { 328 - client, err := NewRelayAdminClient(cctx) 327 + func runRelayAdminHostList(ctx context.Context, cmd *cli.Command) error { 328 + client, err := NewRelayAdminClient(cmd) 329 329 if err != nil { 330 330 return err 331 331 } ··· 349 349 return nil 350 350 } 351 351 352 - func runRelayAdminHostConfig(cctx *cli.Context) error { 352 + func runRelayAdminHostConfig(ctx context.Context, cmd *cli.Command) error { 353 353 354 - hostname := cctx.Args().First() 354 + hostname := cmd.Args().First() 355 355 if hostname == "" { 356 356 return fmt.Errorf("need to provide hostname as an argument") 357 357 } 358 358 359 - client, err := NewRelayAdminClient(cctx) 359 + client, err := NewRelayAdminClient(cmd) 360 360 if err != nil { 361 361 return err 362 362 } ··· 366 366 body := map[string]any{ 367 367 "host": hostname, 368 368 } 369 - if cctx.IsSet("account-limit") { 370 - body["repo_limit"] = cctx.Int("account-limit") 369 + if cmd.IsSet("account-limit") { 370 + body["repo_limit"] = cmd.Int("account-limit") 371 371 } 372 372 373 373 _, err = client.Do("POST", path, nil, body) ··· 377 377 return nil 378 378 } 379 379 380 - func runRelayAdminDomainBan(cctx *cli.Context) error { 380 + func runRelayAdminDomainBan(ctx context.Context, cmd *cli.Command) error { 381 381 382 - domain := cctx.Args().First() 382 + domain := cmd.Args().First() 383 383 if domain == "" { 384 384 return fmt.Errorf("need to provide domain as an argument") 385 385 } 386 386 387 - client, err := NewRelayAdminClient(cctx) 387 + client, err := NewRelayAdminClient(cmd) 388 388 if err != nil { 389 389 return err 390 390 } 391 391 392 392 path := "/admin/subs/banDomain" 393 - if cctx.Bool("reverse") { 393 + if cmd.Bool("reverse") { 394 394 path = "/admin/subs/unbanDomain" 395 395 } 396 396 ··· 404 404 return nil 405 405 } 406 406 407 - func runRelayAdminDomainList(cctx *cli.Context) error { 408 - client, err := NewRelayAdminClient(cctx) 407 + func runRelayAdminDomainList(ctx context.Context, cmd *cli.Command) error { 408 + client, err := NewRelayAdminClient(cmd) 409 409 if err != nil { 410 410 return err 411 411 } ··· 425 425 return nil 426 426 } 427 427 428 - func runRelayAdminConsumerList(cctx *cli.Context) error { 429 - client, err := NewRelayAdminClient(cctx) 428 + func runRelayAdminConsumerList(ctx context.Context, cmd *cli.Command) error { 429 + client, err := NewRelayAdminClient(cmd) 430 430 if err != nil { 431 431 return err 432 432 }
+18 -24
repo.go
··· 18 18 "github.com/bluesky-social/indigo/xrpc" 19 19 20 20 "github.com/ipfs/go-cid" 21 - "github.com/urfave/cli/v2" 21 + "github.com/urfave/cli/v3" 22 22 ) 23 23 24 24 var cmdRepo = &cli.Command{ 25 25 Name: "repo", 26 26 Usage: "sub-commands for repositories", 27 27 Flags: []cli.Flag{}, 28 - Subcommands: []*cli.Command{ 28 + Commands: []*cli.Command{ 29 29 &cli.Command{ 30 30 Name: "export", 31 31 Usage: "download CAR file for given account", ··· 94 94 }, 95 95 } 96 96 97 - func runRepoExport(cctx *cli.Context) error { 98 - ctx := context.Background() 99 - username := cctx.Args().First() 97 + func runRepoExport(ctx context.Context, cmd *cli.Command) error { 98 + username := cmd.Args().First() 100 99 if username == "" { 101 100 return fmt.Errorf("need to provide username as an argument") 102 101 } ··· 118 117 xrpcc.Client = util.RobustHTTPClient() 119 118 xrpcc.Client.Timeout = 600 * time.Second 120 119 121 - carPath := cctx.String("output") 120 + carPath := cmd.String("output") 122 121 if carPath == "" { 123 122 // NOTE: having the rev in the the path might be nice 124 123 now := time.Now().Format("20060102150405") ··· 145 144 return nil 146 145 } 147 146 148 - func runRepoImport(cctx *cli.Context) error { 149 - ctx := context.Background() 147 + func runRepoImport(ctx context.Context, cmd *cli.Command) error { 150 148 151 - carPath := cctx.Args().First() 149 + carPath := cmd.Args().First() 152 150 if carPath == "" { 153 151 return fmt.Errorf("need to provide CAR file path as an argument") 154 152 } ··· 173 171 return nil 174 172 } 175 173 176 - func runRepoList(cctx *cli.Context) error { 177 - ctx := context.Background() 178 - carPath := cctx.Args().First() 174 + func runRepoList(ctx context.Context, cmd *cli.Command) error { 175 + carPath := cmd.Args().First() 179 176 if carPath == "" { 180 177 return fmt.Errorf("need to provide path to CAR file as argument") 181 178 } ··· 200 197 return nil 201 198 } 202 199 203 - func runRepoInspect(cctx *cli.Context) error { 204 - ctx := context.Background() 205 - carPath := cctx.Args().First() 200 + func runRepoInspect(ctx context.Context, cmd *cli.Command) error { 201 + carPath := cmd.Args().First() 206 202 if carPath == "" { 207 203 return fmt.Errorf("need to provide path to CAR file as argument") 208 204 } ··· 227 223 return nil 228 224 } 229 225 230 - func runRepoMST(cctx *cli.Context) error { 231 - ctx := context.Background() 226 + func runRepoMST(ctx context.Context, cmd *cli.Command) error { 232 227 opts := repoMSTOptions{ 233 - carPath: cctx.Args().First(), 234 - fullCID: cctx.Bool("full-cid"), 235 - root: cctx.String("root"), 228 + carPath: cmd.Args().First(), 229 + fullCID: cmd.Bool("full-cid"), 230 + root: cmd.String("root"), 236 231 } 237 232 // read from file or stdin 238 233 if opts.carPath == "" { ··· 245 240 return prettyMST(ctx, inputCAR, opts) 246 241 } 247 242 248 - func runRepoUnpack(cctx *cli.Context) error { 249 - ctx := context.Background() 250 - carPath := cctx.Args().First() 243 + func runRepoUnpack(ctx context.Context, cmd *cli.Command) error { 244 + carPath := cmd.Args().First() 251 245 if carPath == "" { 252 246 return fmt.Errorf("need to provide path to CAR file as argument") 253 247 } ··· 267 261 return err 268 262 } 269 263 270 - topDir := cctx.String("output") 264 + topDir := cmd.String("output") 271 265 if topDir == "" { 272 266 topDir = did.String() 273 267 }
+34 -33
syntax.go
··· 1 1 package main 2 2 3 3 import ( 4 + "context" 4 5 "fmt" 5 6 "time" 6 7 7 8 "github.com/bluesky-social/indigo/atproto/syntax" 8 9 9 - "github.com/urfave/cli/v2" 10 + "github.com/urfave/cli/v3" 10 11 ) 11 12 12 13 var cmdSyntax = &cli.Command{ 13 14 Name: "syntax", 14 15 Usage: "sub-commands for string syntax helpers", 15 - Subcommands: []*cli.Command{ 16 + Commands: []*cli.Command{ 16 17 &cli.Command{ 17 18 Name: "tid", 18 19 Usage: "sub-commands for TIDs", 19 - Subcommands: []*cli.Command{ 20 + Commands: []*cli.Command{ 20 21 &cli.Command{ 21 22 Name: "check", 22 23 Usage: "validates TID syntax", ··· 40 41 &cli.Command{ 41 42 Name: "handle", 42 43 Usage: "sub-commands for handle syntax", 43 - Subcommands: []*cli.Command{ 44 + Commands: []*cli.Command{ 44 45 &cli.Command{ 45 46 Name: "check", 46 47 Usage: "validates handle syntax", ··· 52 53 &cli.Command{ 53 54 Name: "did", 54 55 Usage: "sub-commands for DID syntax", 55 - Subcommands: []*cli.Command{ 56 + Commands: []*cli.Command{ 56 57 &cli.Command{ 57 58 Name: "check", 58 59 Usage: "validates DID syntax", ··· 64 65 &cli.Command{ 65 66 Name: "cid", 66 67 Usage: "sub-commands for CID syntax", 67 - Subcommands: []*cli.Command{ 68 + Commands: []*cli.Command{ 68 69 &cli.Command{ 69 70 Name: "check", 70 71 Usage: "validates CID syntax", ··· 76 77 &cli.Command{ 77 78 Name: "rkey", 78 79 Usage: "sub-commands for record key syntax", 79 - Subcommands: []*cli.Command{ 80 + Commands: []*cli.Command{ 80 81 &cli.Command{ 81 82 Name: "check", 82 83 Usage: "validates record key syntax", ··· 88 89 &cli.Command{ 89 90 Name: "nsid", 90 91 Usage: "sub-commands for NSID syntax", 91 - Subcommands: []*cli.Command{ 92 + Commands: []*cli.Command{ 92 93 &cli.Command{ 93 94 Name: "check", 94 95 Usage: "validates NSID syntax", ··· 100 101 &cli.Command{ 101 102 Name: "at-uri", 102 103 Usage: "sub-commands for AT-URI syntax", 103 - Subcommands: []*cli.Command{ 104 + Commands: []*cli.Command{ 104 105 &cli.Command{ 105 106 Name: "check", 106 107 Usage: "validates AT-URI syntax", ··· 112 113 &cli.Command{ 113 114 Name: "datetime", 114 115 Usage: "sub-commands for datetimes", 115 - Subcommands: []*cli.Command{ 116 + Commands: []*cli.Command{ 116 117 &cli.Command{ 117 118 Name: "check", 118 119 Usage: "validates datetime syntax", ··· 129 130 &cli.Command{ 130 131 Name: "language", 131 132 Usage: "sub-commands for language code syntax", 132 - Subcommands: []*cli.Command{ 133 + Commands: []*cli.Command{ 133 134 &cli.Command{ 134 135 Name: "check", 135 136 Usage: "validates language code syntax", ··· 141 142 }, 142 143 } 143 144 144 - func runSyntaxTIDCheck(cctx *cli.Context) error { 145 - s := cctx.Args().First() 145 + func runSyntaxTIDCheck(ctx context.Context, cmd *cli.Command) error { 146 + s := cmd.Args().First() 146 147 if s == "" { 147 148 return fmt.Errorf("need to provide identifier as argument") 148 149 } ··· 154 155 return nil 155 156 } 156 157 157 - func runSyntaxTIDGenerate(cctx *cli.Context) error { 158 + func runSyntaxTIDGenerate(ctx context.Context, cmd *cli.Command) error { 158 159 fmt.Printf("%s\n", syntax.NewTIDNow(0).String()) 159 160 return nil 160 161 } 161 162 162 - func runSyntaxTIDInspect(cctx *cli.Context) error { 163 - s := cctx.Args().First() 163 + func runSyntaxTIDInspect(ctx context.Context, cmd *cli.Command) error { 164 + s := cmd.Args().First() 164 165 if s == "" { 165 166 return fmt.Errorf("need to provide identifier as argument") 166 167 } ··· 175 176 return nil 176 177 } 177 178 178 - func runSyntaxRecordKeyCheck(cctx *cli.Context) error { 179 - s := cctx.Args().First() 179 + func runSyntaxRecordKeyCheck(ctx context.Context, cmd *cli.Command) error { 180 + s := cmd.Args().First() 180 181 if s == "" { 181 182 return fmt.Errorf("need to provide identifier as argument") 182 183 } ··· 188 189 return nil 189 190 } 190 191 191 - func runSyntaxDIDCheck(cctx *cli.Context) error { 192 - s := cctx.Args().First() 192 + func runSyntaxDIDCheck(ctx context.Context, cmd *cli.Command) error { 193 + s := cmd.Args().First() 193 194 if s == "" { 194 195 return fmt.Errorf("need to provide identifier as argument") 195 196 } ··· 201 202 return nil 202 203 } 203 204 204 - func runSyntaxCIDCheck(cctx *cli.Context) error { 205 - s := cctx.Args().First() 205 + func runSyntaxCIDCheck(ctx context.Context, cmd *cli.Command) error { 206 + s := cmd.Args().First() 206 207 if s == "" { 207 208 return fmt.Errorf("need to provide identifier as argument") 208 209 } ··· 214 215 return nil 215 216 } 216 217 217 - func runSyntaxHandleCheck(cctx *cli.Context) error { 218 - s := cctx.Args().First() 218 + func runSyntaxHandleCheck(ctx context.Context, cmd *cli.Command) error { 219 + s := cmd.Args().First() 219 220 if s == "" { 220 221 return fmt.Errorf("need to provide identifier as argument") 221 222 } ··· 227 228 return nil 228 229 } 229 230 230 - func runSyntaxNSIDCheck(cctx *cli.Context) error { 231 - s := cctx.Args().First() 231 + func runSyntaxNSIDCheck(ctx context.Context, cmd *cli.Command) error { 232 + s := cmd.Args().First() 232 233 if s == "" { 233 234 return fmt.Errorf("need to provide identifier as argument") 234 235 } ··· 240 241 return nil 241 242 } 242 243 243 - func runSyntaxATURICheck(cctx *cli.Context) error { 244 - s := cctx.Args().First() 244 + func runSyntaxATURICheck(ctx context.Context, cmd *cli.Command) error { 245 + s := cmd.Args().First() 245 246 if s == "" { 246 247 return fmt.Errorf("need to provide identifier as argument") 247 248 } ··· 253 254 return nil 254 255 } 255 256 256 - func runSyntaxDatetimeCheck(cctx *cli.Context) error { 257 - s := cctx.Args().First() 257 + func runSyntaxDatetimeCheck(ctx context.Context, cmd *cli.Command) error { 258 + s := cmd.Args().First() 258 259 if s == "" { 259 260 return fmt.Errorf("need to provide identifier as argument") 260 261 } ··· 266 267 return nil 267 268 } 268 269 269 - func runSyntaxDatetimeNow(cctx *cli.Context) error { 270 + func runSyntaxDatetimeNow(ctx context.Context, cmd *cli.Command) error { 270 271 fmt.Printf("%s\n", syntax.DatetimeNow().String()) 271 272 return nil 272 273 } 273 274 274 - func runSyntaxLanguageCheck(cctx *cli.Context) error { 275 - s := cctx.Args().First() 275 + func runSyntaxLanguageCheck(ctx context.Context, cmd *cli.Command) error { 276 + s := cmd.Args().First() 276 277 if s == "" { 277 278 return fmt.Errorf("need to provide identifier as argument") 278 279 }
+3 -3
util.go
··· 12 12 "github.com/bluesky-social/indigo/atproto/syntax" 13 13 14 14 "github.com/earthboundkid/versioninfo/v2" 15 - "github.com/urfave/cli/v2" 15 + "github.com/urfave/cli/v3" 16 16 ) 17 17 18 18 func resolveIdent(ctx context.Context, arg string) (*identity.Identity, error) { ··· 49 49 return file, nil 50 50 } 51 51 52 - func configLogger(cctx *cli.Context, writer io.Writer) *slog.Logger { 52 + func configLogger(cmd *cli.Command, writer io.Writer) *slog.Logger { 53 53 var level slog.Level 54 - switch strings.ToLower(cctx.String("log-level")) { 54 + switch strings.ToLower(cmd.String("log-level")) { 55 55 case "error": 56 56 level = slog.LevelError 57 57 case "warn":