diff --git a/automod/engine/account_meta.go b/automod/engine/account_meta.go index 94dfe67c..76d16755 100644 --- a/automod/engine/account_meta.go +++ b/automod/engine/account_meta.go @@ -25,7 +25,8 @@ type AccountMeta struct { type ProfileSummary struct { HasAvatar bool - Avatar *string + AvatarCid *string + BannerCid *string Description *string DisplayName *string } diff --git a/automod/engine/cid_from_cdn_test.go b/automod/engine/cid_from_cdn_test.go new file mode 100644 index 00000000..cc7553cb --- /dev/null +++ b/automod/engine/cid_from_cdn_test.go @@ -0,0 +1,42 @@ +package engine + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestCidFromCdnUrl(t *testing.T) { + assert := assert.New(t) + + fixCid := "abcdefghijk" + + fixtures := []struct { + url string + cid *string + }{ + { + url: "https://cdn.bsky.app/img/avatar/plain/did:plc:abc123/abcdefghijk@jpeg", + cid: &fixCid, + }, + { + url: "https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:abc123/abcdefghijk@jpeg", + cid: &fixCid, + }, + { + url: "https://cdn.bsky.app/img/feed_fullsize", + cid: nil, + }, + { + url: "https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:abc123/abcdefghijk", + cid: &fixCid, + }, + { + url: "https://cdn.asky.app/img/feed_fullsize/plain/did:plc:abc123/abcdefghijk@jpeg", + cid: nil, + }, + } + + for _, fix := range fixtures { + assert.Equal(fix.cid, CidFromCdnUrl(&fix.url)) + } +} diff --git a/automod/engine/fetch_account_meta.go b/automod/engine/fetch_account_meta.go index f501b92f..b634c856 100644 --- a/automod/engine/fetch_account_meta.go +++ b/automod/engine/fetch_account_meta.go @@ -5,6 +5,8 @@ import ( "encoding/json" "errors" "fmt" + "net/url" + "strings" "time" comatproto "github.com/bluesky-social/indigo/api/atproto" @@ -17,6 +19,25 @@ import ( var newAccountRetryDuration = 3 * 1000 * time.Millisecond +// get the cid from a bluesky cdn url +func CidFromCdnUrl(str *string) *string { + if str == nil { + return nil + } + + u, err := url.Parse(*str) + if err != nil || u.Host != "cdn.bsky.app" { + return nil + } + + parts := strings.Split(u.Path, "/") + if len(parts) != 6 { + return nil + } + + return &strings.Split(parts[5], "@")[0] +} + // Helper to hydrate metadata about an account from several sources: PDS (if access), mod service (if access), public identity resolution func (e *Engine) GetAccountMeta(ctx context.Context, ident *identity.Identity) (*AccountMeta, error) { @@ -75,7 +96,8 @@ func (e *Engine) GetAccountMeta(ctx context.Context, ident *identity.Identity) ( am.Profile = ProfileSummary{ HasAvatar: pv.Avatar != nil, - Avatar: pv.Avatar, + AvatarCid: cidFromCdnUrl(pv.Avatar), + BannerCid: cidFromCdnUrl(pv.Banner), Description: pv.Description, DisplayName: pv.DisplayName, } diff --git a/automod/engine/util.go b/automod/engine/util.go index 195454c1..e96c411d 100644 --- a/automod/engine/util.go +++ b/automod/engine/util.go @@ -1,5 +1,10 @@ package engine +import ( + "net/url" + "strings" +) + func dedupeStrings(in []string) []string { var out []string seen := make(map[string]bool) @@ -11,3 +16,22 @@ func dedupeStrings(in []string) []string { } return out } + +// get the cid from a bluesky cdn url +func cidFromCdnUrl(str *string) *string { + if str == nil { + return nil + } + + u, err := url.Parse(*str) + if err != nil || u.Host != "cdn.bsky.app" { + return nil + } + + parts := strings.Split(u.Path, "/") + if len(parts) != 6 { + return nil + } + + return &strings.Split(parts[5], "@")[0] +}