Distort your Bluesky avatar based on how much you're tired, according to your WHOOP band
1
fork

Configure Feed

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

*: don't touch the avatar if new strain isnt' the same

geesawra 30b2ca86 ca82e704

+39 -23
+39 -23
main.go
··· 34 34 return 35 35 } 36 36 37 - if err := runOnce(ctx, *imagePath, *noPublish, *strainOverride); err != nil { 37 + if _, err := runOnce(ctx, *imagePath, *noPublish, *strainOverride, -1); err != nil { 38 38 log.Fatal(err) 39 39 } 40 40 } ··· 49 49 log.Fatalf("invalid UPDATE_INTERVAL %q: %v", intervalStr, err) 50 50 } 51 51 52 + var lastValue float64 53 + 52 54 log.Printf("running in daemon mode, updating every %s", interval) 53 55 for { 54 - if err := runOnce(ctx, imagePath, noPublish, strainOverride); err != nil { 56 + strainValue, err := runOnce(ctx, imagePath, noPublish, strainOverride, lastValue) 57 + if err != nil { 55 58 log.Printf("error: %v", err) 56 59 } 60 + 61 + lastValue = strainValue 62 + 57 63 select { 58 64 case <-ctx.Done(): 59 65 return ··· 62 68 } 63 69 } 64 70 65 - func runOnce(ctx context.Context, imagePath string, noPublish bool, strainOverride float64) error { 71 + func runOnce(ctx context.Context, imagePath string, noPublish bool, strainOverride float64, lastValue float64) (float64, error) { 66 72 file, err := os.Open(imagePath) 67 73 if err != nil { 68 - return fmt.Errorf("could not open image file: %w", err) 74 + return 0, fmt.Errorf("could not open image file: %w", err) 69 75 } 70 76 defer func() { _ = file.Close() }() 71 77 ··· 73 79 if strainOverride >= 0 { 74 80 strainScore = strainOverride 75 81 if strainScore > maxStrain { 76 - return fmt.Errorf("strain score cannot be greater than %.0f", maxStrain) 82 + return 0, fmt.Errorf("strain score cannot be greater than %.0f", maxStrain) 77 83 } 78 84 } else { 79 85 api := API{TokenDir: os.Getenv("TOKEN_DIR")} 80 86 if err := api.Login(ctx); err != nil { 81 - return fmt.Errorf("whoop auth failed: %w", err) 87 + return 0, fmt.Errorf("whoop auth failed: %w", err) 82 88 } 83 89 84 90 cycle, err := api.LatestCycle() 85 91 if err != nil { 86 - return fmt.Errorf("could not fetch latest cycle: %w", err) 92 + return 0, fmt.Errorf("could not fetch latest cycle: %w", err) 87 93 } 88 94 89 - if cycle.Score == nil { 95 + if cycle.Score != nil { 96 + strainScore = cycle.Score.Strain 97 + } else { 90 98 log.Println("cycle has no info yet, setting default image") 91 - if !noPublish { 92 - bskyUser, bskyPass, err := bskyCredentials() 93 - if err != nil { 94 - return err 95 - } 96 - if err := updateAvatar(ctx, bskyUser, bskyPass, file); err != nil { 97 - return fmt.Errorf("could not update avatar: %w", err) 98 - } 99 + if noPublish { 100 + return 0, nil 99 101 } 100 - return nil 102 + 103 + bskyUser, bskyPass, err := bskyCredentials() 104 + if err != nil { 105 + return 0, fmt.Errorf("log in to bluesky: %w", err) 106 + } 107 + if err := updateAvatar(ctx, bskyUser, bskyPass, file); err != nil { 108 + return 0, fmt.Errorf("could not update avatar: %w", err) 109 + } 110 + 111 + return 0, nil 101 112 } 102 - strainScore = cycle.Score.Strain 113 + } 114 + 115 + if strainScore == lastValue { 116 + return strainScore, nil 103 117 } 104 118 119 + fmt.Printf("strain score changed from %.2f to %.2f, processing avatar\n", lastValue, strainScore) 120 + 105 121 strained, err := os.CreateTemp("", "strained-*.jpg") 106 122 if err != nil { 107 - return fmt.Errorf("could not create temp file for strained avatar: %w", err) 123 + return 0, fmt.Errorf("could not create temp file for strained avatar: %w", err) 108 124 } 109 125 defer func() { 110 126 _ = strained.Close() ··· 117 133 118 134 if noPublish { 119 135 log.Printf("filtered image at %s", strained.Name()) 120 - return nil 136 + return 0, nil 121 137 } 122 138 123 139 _, _ = strained.Seek(0, io.SeekStart) 124 140 125 141 bskyUser, bskyPass, err := bskyCredentials() 126 142 if err != nil { 127 - return err 143 + return 0, err 128 144 } 129 145 if err := updateAvatar(ctx, bskyUser, bskyPass, strained); err != nil { 130 - return fmt.Errorf("could not update avatar: %w", err) 146 + return 0, fmt.Errorf("could not update avatar: %w", err) 131 147 } 132 - return nil 148 + return strainScore, nil 133 149 }