Distort your Bluesky avatar based on how much you're tired, according to your WHOOP band
1package main
2
3import (
4 "context"
5 "fmt"
6 "io"
7 "os"
8
9 comatproto "github.com/bluesky-social/indigo/api/atproto"
10 "github.com/bluesky-social/indigo/api/bsky"
11 "github.com/bluesky-social/indigo/atproto/atclient"
12 "github.com/bluesky-social/indigo/atproto/identity"
13 "github.com/bluesky-social/indigo/atproto/syntax"
14 lexutil "github.com/bluesky-social/indigo/lex/util"
15)
16
17// bskyCredentials reads BSKY_USER and BSKY_PASSWORD from the environment.
18func bskyCredentials() (username, password string, err error) {
19 username = os.Getenv("BSKY_USER")
20 if username == "" {
21 return "", "", fmt.Errorf("BSKY_USER environment variable is not set")
22 }
23 password = os.Getenv("BSKY_PASSWORD")
24 if password == "" {
25 return "", "", fmt.Errorf("BSKY_PASSWORD environment variable is not set")
26 }
27 return username, password, nil
28}
29
30// updateAvatar logs in to Bluesky with the given credentials, uploads the
31// image from r, and sets it as the account's avatar.
32func updateAvatar(ctx context.Context, username, password string, r io.Reader) error {
33 dir := identity.DefaultDirectory()
34 atID, err := syntax.ParseAtIdentifier(username)
35 if err != nil {
36 return fmt.Errorf("parsing identifier %q: %w", username, err)
37 }
38
39 client, err := atclient.LoginWithPassword(ctx, dir, atID, password, "", nil)
40 if err != nil {
41 return fmt.Errorf("bluesky login: %w", err)
42 }
43
44 profileNsid := "app.bsky.actor.profile"
45 selfKey := "self"
46
47 currentRecord, err := comatproto.RepoGetRecord(ctx, client, "", profileNsid, client.AccountDID.String(), selfKey)
48 if err != nil {
49 return fmt.Errorf("fetching current profile record: %w", err)
50 }
51
52 profile, ok := currentRecord.Value.Val.(*bsky.ActorProfile)
53 if !ok {
54 return fmt.Errorf("unexpected profile record type: %T", currentRecord.Value.Val)
55 }
56
57 uploaded, err := comatproto.RepoUploadBlob(ctx, client, r)
58 if err != nil {
59 return fmt.Errorf("uploading avatar blob: %w", err)
60 }
61
62 profile.Avatar = uploaded.Blob
63
64 _, err = comatproto.RepoPutRecord(ctx, client, &comatproto.RepoPutRecord_Input{
65 Collection: profileNsid,
66 Repo: client.AccountDID.String(),
67 Rkey: selfKey,
68 SwapRecord: currentRecord.Cid,
69 Record: &lexutil.LexiconTypeDecoder{Val: profile},
70 })
71 if err != nil {
72 return fmt.Errorf("updating profile: %w", err)
73 }
74
75 return nil
76}