[WIP] music platform user data scraper
teal-fm atproto

Grabs the current record for swap on put

Changed files
+40 -6
service
playingnow
+40 -6
service/playingnow/playingnow.go
··· 11 11 "github.com/bluesky-social/indigo/api/atproto" 12 12 lexutil "github.com/bluesky-social/indigo/lex/util" 13 13 "github.com/bluesky-social/indigo/xrpc" 14 + oauth "github.com/haileyok/atproto-oauth-golang" 14 15 "github.com/spf13/viper" 15 16 "github.com/teal-fm/piper/api/teal" 16 17 "github.com/teal-fm/piper/db" ··· 85 86 Item: playView, 86 87 } 87 88 89 + var swapRecord *string 90 + authArgs := db.AtpSessionToAuthArgs(sess) 91 + 92 + swapRecord, err = p.getStatusSwapRecord(ctx, xrpcClient, sess, authArgs) 93 + if err != nil { 94 + return err 95 + } 96 + 88 97 // Create the record input 89 98 input := atproto.RepoPutRecord_Input{ 90 99 Collection: "fm.teal.alpha.actor.status", 91 100 Repo: sess.DID, 92 101 Rkey: "self", // Use "self" as the record key for current status 93 102 Record: &lexutil.LexiconTypeDecoder{Val: status}, 103 + SwapRecord: swapRecord, 94 104 } 95 - 96 - authArgs := db.AtpSessionToAuthArgs(sess) 97 105 98 106 // Submit to PDS 99 107 var out atproto.RepoPutRecord_Output ··· 157 165 Item: emptyPlayView, 158 166 } 159 167 168 + authArgs := db.AtpSessionToAuthArgs(sess) 169 + 170 + var swapRecord *string 171 + swapRecord, err = p.getStatusSwapRecord(ctx, xrpcClient, sess, authArgs) 172 + if err != nil { 173 + return err 174 + } 175 + 160 176 // Update the record 161 - //TODO this is failing with InvalidSwap: Record was at "prevouis cid" 162 - //2025/09/22 08:03:29 spotify: Updated! 163 177 input := atproto.RepoPutRecord_Input{ 164 178 Collection: "fm.teal.alpha.actor.status", 165 179 Repo: sess.DID, 166 180 Rkey: "self", 167 181 Record: &lexutil.LexiconTypeDecoder{Val: status}, 182 + SwapRecord: swapRecord, 168 183 } 169 184 170 - authArgs := db.AtpSessionToAuthArgs(sess) 171 - 172 185 var out atproto.RepoPutRecord_Output 173 186 if err := xrpcClient.Do(ctx, authArgs, xrpc.Procedure, "application/json", "com.atproto.repo.putRecord", nil, input, &out); err != nil { 174 187 p.logger.Printf("Error clearing playing now status for DID %s: %v", did, err) ··· 250 263 251 264 return playView, nil 252 265 } 266 + 267 + // getStatusSwapRecord retrieves the current swap record (CID) for the actor status record. 268 + // Returns (nil, nil) if the record does not exist yet. 269 + func (p *PlayingNowService) getStatusSwapRecord(ctx context.Context, xrpcClient *oauth.XrpcClient, sess *models.ATprotoAuthSession, authArgs *oauth.XrpcAuthedRequestArgs) (*string, error) { 270 + getOutput := atproto.RepoGetRecord_Output{} 271 + if err := xrpcClient.Do(ctx, authArgs, xrpc.Query, "application/json", "com.atproto.repo.getRecord", map[string]any{ 272 + "repo": sess.DID, 273 + "collection": "fm.teal.alpha.actor.status", 274 + "rkey": "self", 275 + }, nil, &getOutput); err != nil { 276 + xErr, ok := err.(*xrpc.Error) 277 + if !ok { 278 + return nil, fmt.Errorf("could not get record: %w", err) 279 + } 280 + if xErr.StatusCode != 400 { // 400 means not found in this API 281 + return nil, fmt.Errorf("could not get record: %w", err) 282 + } 283 + return nil, nil 284 + } 285 + return getOutput.Cid, nil 286 + }