Compare commits

..

5 commits

7 changed files with 169 additions and 45 deletions

View file

@ -1,11 +1,13 @@
package goap package goap
// JsonLD fields
const ( const (
KEY_ID = "@id" // Value of type string KEY_ID = "@id" // Value of type string
KEY_TYPE = "@type" // Value of type string slice / activitystreams object url slice KEY_TYPE = "@type" // Value of type string slice / activitystreams object url slice
KEY_VALUE = "@value" // Could be any type really KEY_VALUE = "@value" // Could be any type really
) )
// Mastodon fields
const ( const (
KEY_MASTO_DEVICES = "http://joinmastodon.org/ns#devices" // No idea what this is, but Masto includes it 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 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 KEY_MASTO_EMOJI = "http://joinmastodon.org/ns#Emoji" // Object is an emoji
) )
// Generic W3 fields
const ( const (
KEY_W3_INBOX = "http://www.w3.org/ns/ldp#inbox" // Where to send activities to 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 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_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 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 KEY_W3_SECURITY_KEY = "https://w3id.org/security#Key" // Object is a PublicKey
) )
// W3 Activitystreams fields
const ( const (
KEY_ACTIVITYSTREAMS_ACTOR = "https://www.w3.org/ns/activitystreams#actor" KEY_ACTIVITYSTREAMS_ACTOR = "https://www.w3.org/ns/activitystreams#actor"
KEY_ACTIVITYSTREAMS_ALSOKNOWNAS = "https://www.w3.org/ns/activitystreams#alsoKnownAs" // Lists of usernames? 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_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_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 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) // Object types (I think)
// Those are values the object type can have // 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_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_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 KEY_ACTIVITYSTREAMS_PARTOF = "https://www.w3.org/ns/activitystreams#partOf" // Collection the current page is a part of
)
// W3 Activitystreams unknown
const (
// Misc // Misc
KEY_ACTIVITYSTREAMS_OAUTHAUTHORIZATION = "https://www.w3.org/ns/activitystreams#oauthAuthorizationEndpoint" // Endpoint url for oauth login? 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? 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 KEY_ACTIVITYSTREAMS_PUBLIC = "https://www.w3.org/ns/activitystreams#Public" // Note target
) )
// schema fields
const ( const (
KEY_SCHEMA_VALUE = "http://schema.org#value" // The value for some field 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 KEY_SCHEMA_PROPERTYVALUE = "http://schema.org#PropertyValue" // Object is of type property value
) )
// Misskey and fork fields
const ( const (
KEY_MISSKEY_MKSUMMARY = "https://misskey-hub.net/ns#_misskey_summary" // Misskey specific formatted summary 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? 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 // No idea what either of those two do or are used for
// Litepub fields
const ( const (
KEY_LITEPUB_CAPABILITIES = "http://litepub.social/ns#capabilities" KEY_LITEPUB_CAPABILITIES = "http://litepub.social/ns#capabilities"
KEY_LITEPUB_OAUTHREGISTRATION = "http://litepub.social/ns#oauthRegistrationEndpoint" KEY_LITEPUB_OAUTHREGISTRATION = "http://litepub.social/ns#oauthRegistrationEndpoint"
) )
// W3 XML fields
const ( const (
KEY_XMLSCHEMA_DATETIME = "http://www.w3.org/2001/XMLSchema#dateTime" // Type value for published value field 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 // NOTE: ostatus.org seems to be redirecting to some weird scam(?) page
const ( const (
KEY_OSTATUS_ATOMURI = "http://ostatus.org#atomUri" // Same as @id I think 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 KEY_OSTATUS_INREPLYTOATOMURI = "http://ostatus.org#inReplyToAtomUri" // Same as InReplyTo, but with an atom uri as target
) )
// Unknown origin fields
const ( const (
KEY_MYSTERIOUS_NOINDEX = "_:noindex" KEY_MYSTERIOUS_NOINDEX = "_:noindex"
KEY_MYSTERIOUS_BACKGROUNDURL = "_:backgroundUrl" KEY_MYSTERIOUS_BACKGROUNDURL = "_:backgroundUrl"
KEY_MYSTERIOUS_FEATURED = "_:featured" KEY_MYSTERIOUS_FEATURED = "_:featured"
) )
// Fedibird fields
const ( const (
KEY_FEDIBIRD_QUOTEURI = "http://fedibird.com/ns#quoteUri" KEY_FEDIBIRD_QUOTEURI = "http://fedibird.com/ns#quoteUri"
) )

View file

@ -3,7 +3,7 @@ package general
import ( import (
"time" "time"
"gitlab.com/mstarongitlab/goap" "git.mstar.dev/mstar/goap"
) )
type CreateEvent struct { type CreateEvent struct {

2
go.mod
View file

@ -1,4 +1,4 @@
module gitlab.com/mstarongitlab/goap module git.mstar.dev/mstar/goap
go 1.22.5 go 1.22.5

View file

@ -3,7 +3,7 @@ package mastodon
import ( import (
"time" "time"
"gitlab.com/mstarongitlab/goap" "git.mstar.dev/mstar/goap"
) )
type Person struct { type Person struct {
@ -32,3 +32,134 @@ type Person struct {
Tags []goap.Tag Tags []goap.Tag
Url string 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
}

View file

@ -3,7 +3,7 @@ package goap
import ( import (
"time" "time"
"github.com/datainq/xml-date-time" xmldatetime "github.com/datainq/xml-date-time"
"gitlab.com/mstarongitlab/goutils/sliceutils" "gitlab.com/mstarongitlab/goutils/sliceutils"
) )
@ -28,54 +28,23 @@ func ParseASActorData(raw map[string]any, next BaseApChain) (BaseApChain, error)
} }
type ASAlsoKnownAsData struct { type ASAlsoKnownAsData struct {
Next BaseApChain FullIdType
Urls []string
} }
func (cc *ASAlsoKnownAsData) GetSelfOrBase() (BaseApChain, bool) { func (cc *ASAlsoKnownAsData) GetSelfOrBase() (BaseApChain, bool) {
return cc.Next, true return cc.FullIdType.GetSelfOrBase()
} }
func (cc *ASAlsoKnownAsData) MarshalToMap() map[string]any { func (cc *ASAlsoKnownAsData) MarshalToMap() map[string]any {
return appendWithKey( return cc.FullIdType.MarshalToMapWithName(KEY_ACTIVITYSTREAMS_ALSOKNOWNAS)
cc.Next.MarshalToMap(),
KEY_ACTIVITYSTREAMS_ALSOKNOWNAS,
sliceutils.Map(cc.Urls, func(t string) map[string]any {
return map[string]any{KEY_ID: t}
}),
)
} }
func ParseASAlsoKnownAsData(raw map[string]any, next BaseApChain) (BaseApChain, error) { func ParseASAlsoKnownAsData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
rawData1, ok := raw[KEY_ACTIVITYSTREAMS_ALSOKNOWNAS] id, err := ParseIdTypeWithName(raw, next, KEY_ACTIVITYSTREAMS_ALSOKNOWNAS)
if !ok { if err != nil {
return nil, NoRequiredFieldError{KEY_ACTIVITYSTREAMS_ALSOKNOWNAS} return nil, err
} }
data1, ok := rawData1.([]map[string]any) return &ASAlsoKnownAsData{FullIdType: *id}, nil
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
} }
type ASAttachmentsData struct { type ASAttachmentsData struct {

View file

@ -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) // TODO: Handle case with multiple public keys (if allowed, idk if it is)
type W3SecurityPublicKeyData struct { type W3SecurityPublicKeyData struct {
Next BaseApChain Next BaseApChain
Id string Id string

View file

@ -139,7 +139,7 @@ func UnmarshalPreprocessed(
// Find an attribute in an ActivityPub object of the given type // Find an attribute in an ActivityPub object of the given type
// Returns a pointer to the found attribute and whether it found it // Returns a pointer to the found attribute and whether it found it
// 2nd parameter is true if the attribute was found, false otherwise // 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 obj T
var ok bool var ok bool
// Try and cast object into wanted type // Try and cast object into wanted type
@ -150,8 +150,8 @@ func FindAttribute[T BaseApChain](object BaseApChain) (*T, bool) {
object, ok = object.GetSelfOrBase() object, ok = object.GetSelfOrBase()
// If this is the final object in the chain, cancel and return false // If this is the final object in the chain, cancel and return false
if !ok { if !ok {
return nil, false return obj, false
} }
} }
return &obj, true return obj, true
} }