porting all github actions from bluesky-social/indigo to tangled CI

basic refresh auth login

Changed files
+100 -8
atproto
client
cmd
atclient
+61 -8
atproto/client/cmd/atclient/main.go
··· 8 8 "os" 9 9 10 10 "github.com/bluesky-social/indigo/atproto/client" 11 + "github.com/bluesky-social/indigo/atproto/identity" 12 + "github.com/bluesky-social/indigo/atproto/syntax" 11 13 12 14 "github.com/urfave/cli/v2" 13 15 ) ··· 22 24 Usage: "do a basic GET request", 23 25 Action: runGet, 24 26 }, 27 + &cli.Command{ 28 + Name: "login-refresh", 29 + Usage: "do a basic login and GET request", 30 + Action: runLoginRefresh, 31 + Flags: []cli.Flag{ 32 + &cli.StringFlag{ 33 + Name: "username", 34 + Required: true, 35 + Aliases: []string{"u"}, 36 + Usage: "handle or DID (not email)", 37 + }, 38 + &cli.StringFlag{ 39 + Name: "password", 40 + Required: true, 41 + Aliases: []string{"p"}, 42 + Usage: "password (or app password)", 43 + }, 44 + }, 45 + }, 25 46 }, 26 47 } 27 48 h := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug}) ··· 29 50 app.RunAndExitOnError() 30 51 } 31 52 53 + func simpleGet(ctx context.Context, c *client.APIClient) error { 54 + params := map[string]string{ 55 + "actor": "atproto.com", 56 + "limit": "5", 57 + "includePins": "false", 58 + } 59 + 60 + var d json.RawMessage 61 + err := c.Get(ctx, "app.bsky.feed.getAuthorFeed", params, &d) 62 + if err != nil { 63 + return err 64 + } 65 + 66 + out, err := json.MarshalIndent(d, "", " ") 67 + if err != nil { 68 + return err 69 + } 70 + fmt.Println(string(out)) 71 + return nil 72 + } 73 + 32 74 func runGet(cctx *cli.Context) error { 33 75 ctx := context.Background() 34 76 ··· 36 78 Host: "https://public.api.bsky.app", 37 79 } 38 80 39 - params := map[string]string{ 40 - "actor": "atproto.com", 41 - "limit": "5", 42 - "includePins": "false", 81 + return simpleGet(ctx, &c) 82 + } 83 + 84 + func runLoginRefresh(cctx *cli.Context) error { 85 + ctx := context.Background() 86 + 87 + atid, err := syntax.ParseAtIdentifier(cctx.String("username")) 88 + if err != nil { 89 + return err 43 90 } 44 - b, err := c.Get(ctx, "app.bsky.feed.getAuthorFeed", params) 91 + 92 + dir := identity.DefaultDirectory() 93 + ident, err := dir.Lookup(ctx, *atid) 45 94 if err != nil { 46 95 return err 47 96 } 48 97 49 - out, err := json.MarshalIndent(b, "", " ") 98 + c := client.APIClient{ 99 + Host: ident.PDSEndpoint(), 100 + } 101 + 102 + _, err = client.NewSession(ctx, &c, atid.String(), cctx.String("password"), "") 50 103 if err != nil { 51 104 return err 52 105 } 53 - fmt.Println(string(out)) 54 - return nil 106 + 107 + return simpleGet(ctx, &c) 55 108 }
+39
atproto/client/refresh_auth.go
··· 1 1 package client 2 2 3 3 import ( 4 + "context" 5 + "fmt" 4 6 "net/http" 7 + "sync" 8 + 9 + comatproto "github.com/bluesky-social/indigo/api/atproto" 5 10 6 11 "github.com/bluesky-social/indigo/atproto/syntax" 7 12 ) ··· 12 17 DID syntax.DID 13 18 // The AuthHost might different from any APIClient host, if there is an entryway involved 14 19 AuthHost string 20 + 21 + lk sync.Mutex 15 22 } 16 23 17 24 // TODO: ··· 28 35 func (a *RefreshAuth) AccountDID() syntax.DID { 29 36 return a.DID 30 37 } 38 + 39 + // updates the client with the new auth method 40 + func NewSession(ctx context.Context, client *APIClient, username, password, token string) (*RefreshAuth, error) { 41 + 42 + reqBody := comatproto.ServerCreateSession_Input{ 43 + Identifier: username, 44 + Password: password, 45 + } 46 + if token != "" { 47 + reqBody.AuthFactorToken = &token 48 + } 49 + 50 + var out comatproto.ServerCreateSession_Output 51 + err := client.Post(ctx, syntax.NSID("com.atproto.server.createSession"), &reqBody, &out) 52 + if err != nil { 53 + return nil, err 54 + } 55 + 56 + if out.Active != nil && *out.Active == false { 57 + return nil, fmt.Errorf("account is disabled: %s", out.Status) 58 + } 59 + 60 + ra := RefreshAuth{ 61 + AccessToken: out.AccessJwt, 62 + RefreshToken: out.RefreshJwt, 63 + DID: syntax.DID(out.Did), 64 + // TODO: authHost / PDS host distinction 65 + AuthHost: client.Host, 66 + } 67 + client.Auth = &ra 68 + return &ra, nil 69 + }