From 2bee4c5fb549d91537dc10c359107ca9b2722ae3 Mon Sep 17 00:00:00 2001 From: mstar Date: Mon, 7 Apr 2025 15:00:43 +0200 Subject: [PATCH 1/5] Update module name following host switch, impl masto person from ap object --- general/createEvent.go | 2 +- go.mod | 2 +- mastodon/account.go | 133 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 134 insertions(+), 3 deletions(-) diff --git a/general/createEvent.go b/general/createEvent.go index bc79c5d..4283118 100644 --- a/general/createEvent.go +++ b/general/createEvent.go @@ -3,7 +3,7 @@ package general import ( "time" - "gitlab.com/mstarongitlab/goap" + "git.mstar.dev/mstar/goap" ) type CreateEvent struct { diff --git a/go.mod b/go.mod index 3af66f6..c1bc9e4 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module gitlab.com/mstarongitlab/goap +module git.mstar.dev/mstar/goap go 1.22.5 diff --git a/mastodon/account.go b/mastodon/account.go index 9bfc683..8397e22 100644 --- a/mastodon/account.go +++ b/mastodon/account.go @@ -3,7 +3,7 @@ package mastodon import ( "time" - "gitlab.com/mstarongitlab/goap" + "git.mstar.dev/mstar/goap" ) type Person struct { @@ -32,3 +32,134 @@ type Person struct { Tags []goap.Tag Url string } + +func PersonFromChain(base goap.BaseApChain) (*Person, error) { + id, ok := goap.FindAttribute[*goap.UDIdData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ID} + } + devices, ok := goap.FindAttribute[*goap.MastoDevicesData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_MASTO_DEVICES} + } + discoverable, ok := goap.FindAttribute[*goap.MastoDiscoverableData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_MASTO_DISCOVERABLE} + } + + featured, ok := goap.FindAttribute[*goap.MastoFeaturedData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_MASTO_FEATURED} + } + featuredTags, ok := goap.FindAttribute[*goap.MastoFeaturedTagsData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_MASTO_FEATURED_TAGS} + } + Indexable, ok := goap.FindAttribute[*goap.MastoIndexableData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_MASTO_INDEXABLE} + } + memorial, ok := goap.FindAttribute[*goap.MastoMemorialData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_MASTO_MEMORIAL} + } + inbox, ok := goap.FindAttribute[*goap.W3InboxData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_W3_INBOX} + } + publicKey, ok := goap.FindAttribute[*goap.W3SecurityPublicKeyData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_W3_SECURITY_PUBLICKEY} + } + alsoKnownAs, ok := goap.FindAttribute[*goap.ASAlsoKnownAsData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ACTIVITYSTREAMS_ALSOKNOWNAS} + } + attachments, ok := goap.FindAttribute[*goap.ASAttachmentsData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ACTIVITYSTREAMS_ATTACHMENTS} + } + endpoints, ok := goap.FindAttribute[*goap.ASEndpointsData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ACTIVITYSTREAMS_ENDPOINTS} + } + followers, ok := goap.FindAttribute[*goap.ASFollowersData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ACTIVITYSTREAMS_FOLLOWERS} + } + following, ok := goap.FindAttribute[*goap.ASFollowingData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ACTIVITYSTREAMS_FOLLOWING} + } + icon, ok := goap.FindAttribute[*goap.ASIconData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ACTIVITYSTREAMS_ICON} + } + image, ok := goap.FindAttribute[*goap.ASImageData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ACTIVITYSTREAMS_IMAGE_ATTRIBUTE} + } + approvesFollowers, ok := goap.FindAttribute[*goap.ASRestrictedFollowData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ACTIVITYSTREAMS_RESTRICTED_FOLLOW} + } + name, ok := goap.FindAttribute[*goap.ASNameData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ACTIVITYSTREAMS_NAME} + } + outbox, ok := goap.FindAttribute[*goap.ASOutboxData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ACTIVITYSTREAMS_OUTBOX} + } + preferredUsername, ok := goap.FindAttribute[*goap.ASPreferredNameData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ACTIVITYSTREAMS_PREFFEREDUSERNAME} + } + published, ok := goap.FindAttribute[*goap.ASPublishedData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ACTIVITYSTREAMS_PUBLISHED} + } + summary, ok := goap.FindAttribute[*goap.ASSummaryData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ACTIVITYSTREAMS_SUMMARY} + } + tags, ok := goap.FindAttribute[*goap.ASTagData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ACTIVITYSTREAMS_TAG} + } + url, ok := goap.FindAttribute[*goap.ASUrlData](base) + if !ok { + return nil, goap.NoRequiredFieldError{FieldName: goap.KEY_ACTIVITYSTREAMS_URL} + } + + return &Person{ + Id: id.Id, + Devices: devices.Id, + Discoverable: discoverable.Value.Value, + Featured: featured.Id, + FeaturedTags: featuredTags.Id, + Indexable: Indexable.Value.Value, + Memorial: memorial.Value.Value, + Inbox: inbox.Id, + PublicKey: goap.PublicKey{ + Id: publicKey.Id, + Owner: publicKey.Owner, + Pem: publicKey.Key, + }, + AlsoKnownAs: alsoKnownAs.Id, + Attachments: attachments.Attachments, + Endpoints: endpoints.Endpoints, + Followers: followers.Id, + Following: following.Id, + Icon: icon.Media, + Image: image.Media, + ApprovesFollowers: approvesFollowers.Value.Value, + Name: name.Value.Value, + Outbox: outbox.Id, + PreferredUsername: preferredUsername.Value.Value, + Published: published.Timestamp, + Summary: summary.Value.Value, + Tags: tags.Tags, + Url: url.Id, + }, nil +} From 6fa37a91b8f4c3c595c2777be3ab6b49250135d9 Mon Sep 17 00:00:00 2001 From: mstar Date: Mon, 7 Apr 2025 15:01:26 +0200 Subject: [PATCH 2/5] Comment out different sections of constants --- constants.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/constants.go b/constants.go index 575a3f6..7d5c243 100644 --- a/constants.go +++ b/constants.go @@ -1,11 +1,13 @@ package goap +// JsonLD fields const ( KEY_ID = "@id" // Value of type string KEY_TYPE = "@type" // Value of type string slice / activitystreams object url slice KEY_VALUE = "@value" // Could be any type really ) +// Mastodon fields const ( KEY_MASTO_DEVICES = "http://joinmastodon.org/ns#devices" // No idea what this is, but Masto includes it KEY_MASTO_DISCOVERABLE = "http://joinmastodon.org/ns#discoverable" // iirc this is whether the object can be found by crawlers @@ -17,6 +19,7 @@ const ( KEY_MASTO_EMOJI = "http://joinmastodon.org/ns#Emoji" // Object is an emoji ) +// Generic W3 fields const ( KEY_W3_INBOX = "http://www.w3.org/ns/ldp#inbox" // Where to send activities to KEY_W3_SECURITY_OWNER = "https://w3id.org/security#owner" // Owner of the public key @@ -25,9 +28,14 @@ const ( KEY_W3_VCARD_ADDRESS = "http://www.w3.org/2006/vcard/ns#Address" // Vcard address of an account KEY_W3_VCARD_BIRTHDAY = "http://www.w3.org/2006/vcard/ns#bday" // Vcard birthday of an account +) + +// Generic W3 object type +const ( KEY_W3_SECURITY_KEY = "https://w3id.org/security#Key" // Object is a PublicKey ) +// W3 Activitystreams fields const ( KEY_ACTIVITYSTREAMS_ACTOR = "https://www.w3.org/ns/activitystreams#actor" KEY_ACTIVITYSTREAMS_ALSOKNOWNAS = "https://www.w3.org/ns/activitystreams#alsoKnownAs" // Lists of usernames? @@ -58,7 +66,10 @@ const ( KEY_ACTIVITYSTREAMS_UPDATED = "https://www.w3.org/ns/activitystreams#updated" // When the content was last updated KEY_ACTIVITYSTREAMS_INREPLYTO = "https://www.w3.org/ns/activitystreams#inReplyTo" // What the object is replying to KEY_ACTIVITYSTREAMS_QUOTEURL = "https://www.w3.org/ns/activitystreams#quoteUrl" // Url to the object being quoted +) +// W3 Activitystreams object types +const ( // Object types (I think) // Those are values the object type can have @@ -78,7 +89,10 @@ const ( KEY_ACTIVITYSTREAMS_ITEMS = "https://www.w3.org/ns/activitystreams#items" // Items in this collection page KEY_ACTIVITYSTREAMS_NEXT = "https://www.w3.org/ns/activitystreams#next" // Next page in a collection KEY_ACTIVITYSTREAMS_PARTOF = "https://www.w3.org/ns/activitystreams#partOf" // Collection the current page is a part of +) +// W3 Activitystreams unknown +const ( // Misc KEY_ACTIVITYSTREAMS_OAUTHAUTHORIZATION = "https://www.w3.org/ns/activitystreams#oauthAuthorizationEndpoint" // Endpoint url for oauth login? KEY_ACTIVITYSTREAMS_OAUTHTOKEN = "https://www.w3.org/ns/activitystreams#oauthTokenEndpoint" // Endpoint url for oauth token verification? @@ -86,12 +100,14 @@ const ( KEY_ACTIVITYSTREAMS_PUBLIC = "https://www.w3.org/ns/activitystreams#Public" // Note target ) +// schema fields const ( KEY_SCHEMA_VALUE = "http://schema.org#value" // The value for some field KEY_SCHEMA_PROPERTYVALUE = "http://schema.org#PropertyValue" // Object is of type property value ) +// Misskey and fork fields const ( KEY_MISSKEY_MKSUMMARY = "https://misskey-hub.net/ns#_misskey_summary" // Misskey specific formatted summary KEY_MISSKEY_ISCAT = "https://misskey-hub.net/ns#isCat" // Does the account identify as cat? @@ -100,15 +116,20 @@ const ( ) // No idea what either of those two do or are used for + +// Litepub fields const ( KEY_LITEPUB_CAPABILITIES = "http://litepub.social/ns#capabilities" KEY_LITEPUB_OAUTHREGISTRATION = "http://litepub.social/ns#oauthRegistrationEndpoint" ) +// W3 XML fields const ( KEY_XMLSCHEMA_DATETIME = "http://www.w3.org/2001/XMLSchema#dateTime" // Type value for published value field ) +// Ostatus fields +// // NOTE: ostatus.org seems to be redirecting to some weird scam(?) page const ( KEY_OSTATUS_ATOMURI = "http://ostatus.org#atomUri" // Same as @id I think @@ -116,12 +137,14 @@ const ( KEY_OSTATUS_INREPLYTOATOMURI = "http://ostatus.org#inReplyToAtomUri" // Same as InReplyTo, but with an atom uri as target ) +// Unknown origin fields const ( KEY_MYSTERIOUS_NOINDEX = "_:noindex" KEY_MYSTERIOUS_BACKGROUNDURL = "_:backgroundUrl" KEY_MYSTERIOUS_FEATURED = "_:featured" ) +// Fedibird fields const ( KEY_FEDIBIRD_QUOTEURI = "http://fedibird.com/ns#quoteUri" ) From 43b1310f3ec920fda9061c360ea590bf5fd5b4c7 Mon Sep 17 00:00:00 2001 From: mstar Date: Mon, 7 Apr 2025 15:01:40 +0200 Subject: [PATCH 3/5] Fix bad type for AlsoKnownAs --- nsActivitystreams.go | 47 ++++++++------------------------------------ 1 file changed, 8 insertions(+), 39 deletions(-) diff --git a/nsActivitystreams.go b/nsActivitystreams.go index 3c6e0af..8d06596 100644 --- a/nsActivitystreams.go +++ b/nsActivitystreams.go @@ -3,7 +3,7 @@ package goap import ( "time" - "github.com/datainq/xml-date-time" + xmldatetime "github.com/datainq/xml-date-time" "gitlab.com/mstarongitlab/goutils/sliceutils" ) @@ -28,54 +28,23 @@ func ParseASActorData(raw map[string]any, next BaseApChain) (BaseApChain, error) } type ASAlsoKnownAsData struct { - Next BaseApChain - Urls []string + FullIdType } func (cc *ASAlsoKnownAsData) GetSelfOrBase() (BaseApChain, bool) { - return cc.Next, true + return cc.FullIdType.GetSelfOrBase() } func (cc *ASAlsoKnownAsData) MarshalToMap() map[string]any { - return appendWithKey( - cc.Next.MarshalToMap(), - KEY_ACTIVITYSTREAMS_ALSOKNOWNAS, - sliceutils.Map(cc.Urls, func(t string) map[string]any { - return map[string]any{KEY_ID: t} - }), - ) + return cc.FullIdType.MarshalToMapWithName(KEY_ACTIVITYSTREAMS_ALSOKNOWNAS) } func ParseASAlsoKnownAsData(raw map[string]any, next BaseApChain) (BaseApChain, error) { - rawData1, ok := raw[KEY_ACTIVITYSTREAMS_ALSOKNOWNAS] - if !ok { - return nil, NoRequiredFieldError{KEY_ACTIVITYSTREAMS_ALSOKNOWNAS} + id, err := ParseIdTypeWithName(raw, next, KEY_ACTIVITYSTREAMS_ALSOKNOWNAS) + if err != nil { + return nil, err } - data1, ok := rawData1.([]map[string]any) - if !ok { - return nil, BadFieldValueError[[]map[string]any]{ - KEY_ACTIVITYSTREAMS_ALSOKNOWNAS, - rawData1, - []map[string]any{}, - } - } - urls := []string{} - for _, v := range data1 { - rawData2, ok := v[KEY_ID] - if !ok { - return nil, NoRequiredSubFieldError{KEY_ACTIVITYSTREAMS_ALSOKNOWNAS, KEY_ID} - } - data2, ok := rawData2.(string) - if !ok { - return nil, BadFieldValueError[string]{KEY_ACTIVITYSTREAMS_ALSOKNOWNAS, rawData2, ""} - } - urls = append(urls, data2) - } - delete(raw, KEY_ACTIVITYSTREAMS_ALSOKNOWNAS) - return &ASAlsoKnownAsData{ - Next: next, - Urls: urls, - }, nil + return &ASAlsoKnownAsData{FullIdType: *id}, nil } type ASAttachmentsData struct { From e534fc8ec4946b7aa60e7bc59d3dce1d567de0d8 Mon Sep 17 00:00:00 2001 From: mstar Date: Mon, 7 Apr 2025 15:02:10 +0200 Subject: [PATCH 4/5] TODO is not a doc comment --- nsW3Security.go | 1 + 1 file changed, 1 insertion(+) diff --git a/nsW3Security.go b/nsW3Security.go index e22704b..09bb03a 100644 --- a/nsW3Security.go +++ b/nsW3Security.go @@ -21,6 +21,7 @@ func ParseW3SecurityOwnerData(raw map[string]any, next BaseApChain) (BaseApChain } // TODO: Handle case with multiple public keys (if allowed, idk if it is) + type W3SecurityPublicKeyData struct { Next BaseApChain Id string From 6f9ac80c39ed5976665d38b67344b38d2297c581 Mon Sep 17 00:00:00 2001 From: mstar Date: Mon, 7 Apr 2025 15:02:23 +0200 Subject: [PATCH 5/5] Remove one pointer too many --- parser.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/parser.go b/parser.go index 4f5ed05..8af6b5c 100644 --- a/parser.go +++ b/parser.go @@ -139,7 +139,7 @@ func UnmarshalPreprocessed( // Find an attribute in an ActivityPub object of the given type // Returns a pointer to the found attribute and whether it found it // 2nd parameter is true if the attribute was found, false otherwise -func FindAttribute[T BaseApChain](object BaseApChain) (*T, bool) { +func FindAttribute[T BaseApChain](object BaseApChain) (T, bool) { var obj T var ok bool // Try and cast object into wanted type @@ -150,8 +150,8 @@ func FindAttribute[T BaseApChain](object BaseApChain) (*T, bool) { object, ok = object.GetSelfOrBase() // If this is the final object in the chain, cancel and return false if !ok { - return nil, false + return obj, false } } - return &obj, true + return obj, true }