Compare commits
No commits in common. "5aec50990e46ee54d80397594c136d435c73677f" and "926e32898620feb60ea2576d87ab0018ddc69e1b" have entirely different histories.
5aec50990e
...
926e328986
26 changed files with 617 additions and 887 deletions
14
CHANGELOG
14
CHANGELOG
|
@ -1,14 +0,0 @@
|
||||||
- v1.1.0:
|
|
||||||
- More attributes added:
|
|
||||||
- Activitystreams#first
|
|
||||||
- Activitystreams#next
|
|
||||||
- Activitystreams#items
|
|
||||||
- Activitystreams#partOf
|
|
||||||
- Activitystreams#inReplyTo
|
|
||||||
- Activitystreams#quoteUrl
|
|
||||||
- Ostatus#inReplyToAtomUri
|
|
||||||
- Misskey#mk_quote
|
|
||||||
- Fedibird#quoteUri
|
|
||||||
- Bug fixes:
|
|
||||||
- A few Attributes were returning the wrong struct due to copy paste mistakes
|
|
||||||
- v1.0.0: Release
|
|
21
LICENSE
21
LICENSE
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2024 mStar
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
|
@ -16,6 +16,48 @@ type BaseApChain interface {
|
||||||
// It is expected that, on success, the function removes its key from the raw map
|
// It is expected that, on success, the function removes its key from the raw map
|
||||||
type UnmarshalFunc func(map[string]any, BaseApChain) (BaseApChain, error)
|
type UnmarshalFunc func(map[string]any, BaseApChain) (BaseApChain, error)
|
||||||
|
|
||||||
|
// The minimum data every AP object has
|
||||||
|
type BaseObject struct {
|
||||||
|
Id string
|
||||||
|
Type string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseObject) GetSelfOrBase() (BaseApChain, bool) {
|
||||||
|
return b, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseObject) MarshalToMap() map[string]any {
|
||||||
|
return map[string]any{
|
||||||
|
KEY_ID: b.Id,
|
||||||
|
KEY_TYPE: b.Type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnmarshalBaseObject(raw map[string]any, _ BaseApChain) (BaseApChain, error) {
|
||||||
|
rawId, ok := raw[KEY_ID]
|
||||||
|
if !ok {
|
||||||
|
return nil, NoRequiredFieldError{KEY_ID}
|
||||||
|
}
|
||||||
|
id, ok := rawId.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, BadFieldValueError[string]{KEY_ID, rawId, ""}
|
||||||
|
}
|
||||||
|
|
||||||
|
rawObjType, ok := raw[KEY_TYPE]
|
||||||
|
if !ok {
|
||||||
|
return nil, NoRequiredFieldError{KEY_TYPE}
|
||||||
|
}
|
||||||
|
objType, ok := rawObjType.([]string)
|
||||||
|
if !ok {
|
||||||
|
return nil, BadFieldValueError[[]string]{KEY_TYPE, rawObjType, []string{}}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &BaseObject{
|
||||||
|
Id: id,
|
||||||
|
Type: objType[0],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type EmptyBaseObject struct{}
|
type EmptyBaseObject struct{}
|
||||||
|
|
||||||
func (e *EmptyBaseObject) GetSelfOrBase() (BaseApChain, bool) {
|
func (e *EmptyBaseObject) GetSelfOrBase() (BaseApChain, bool) {
|
||||||
|
|
13
constants.go
13
constants.go
|
@ -56,8 +56,6 @@ const (
|
||||||
KEY_ACTIVITYSTREAMS_TO = "https://www.w3.org/ns/activitystreams#to" // Urls to send an activity to
|
KEY_ACTIVITYSTREAMS_TO = "https://www.w3.org/ns/activitystreams#to" // Urls to send an activity to
|
||||||
KEY_ACTIVITYSTREAMS_URL = "https://www.w3.org/ns/activitystreams#url" // Some url
|
KEY_ACTIVITYSTREAMS_URL = "https://www.w3.org/ns/activitystreams#url" // Some url
|
||||||
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_QUOTEURL = "https://www.w3.org/ns/activitystreams#quoteUrl" // Url to the object being quoted
|
|
||||||
|
|
||||||
// Object types (I think)
|
// Object types (I think)
|
||||||
// Those are values the object type can have
|
// Those are values the object type can have
|
||||||
|
@ -95,11 +93,9 @@ const (
|
||||||
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?
|
||||||
KEY_MISSKEY_MKQUOTE = "https://misskey-hub.net/ns#_misskey_quote" // Misskey specific quote field
|
|
||||||
KEY_FIREFISH_SPEAKASCAT = "https://joinfirefish.org/ns#speakAsCat" // Does the account speak like a cat?
|
KEY_FIREFISH_SPEAKASCAT = "https://joinfirefish.org/ns#speakAsCat" // Does the account speak like a cat?
|
||||||
)
|
)
|
||||||
|
|
||||||
// No idea what either of those two do or are used for
|
|
||||||
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"
|
||||||
|
@ -111,9 +107,8 @@ const (
|
||||||
|
|
||||||
// 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"
|
||||||
KEY_OSTATUS_CONVERSATION = "http://ostatus.org#conversation" // Similar to inReplyTo
|
KEY_OSTATUS_CONVERSATION = "http://ostatus.org#conversation"
|
||||||
KEY_OSTATUS_INREPLYTOATOMURI = "http://ostatus.org#inReplyToAtomUri" // Same as InReplyTo, but with an atom uri as target
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -121,7 +116,3 @@ const (
|
||||||
KEY_MYSTERIOUS_BACKGROUNDURL = "_:backgroundUrl"
|
KEY_MYSTERIOUS_BACKGROUNDURL = "_:backgroundUrl"
|
||||||
KEY_MYSTERIOUS_FEATURED = "_:featured"
|
KEY_MYSTERIOUS_FEATURED = "_:featured"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
KEY_FEDIBIRD_QUOTEURI = "http://fedibird.com/ns#quoteUri"
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,122 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/statuses/113046100718699502/replies",
|
|
||||||
"@type": [
|
|
||||||
"https://www.w3.org/ns/activitystreams#Collection"
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#first": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/statuses/113046100718699502/replies?page=true",
|
|
||||||
"@type": [
|
|
||||||
"https://www.w3.org/ns/activitystreams#CollectionPage"
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#items": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/statuses/113046106230737452",
|
|
||||||
"@type": [
|
|
||||||
"https://www.w3.org/ns/activitystreams#Note"
|
|
||||||
],
|
|
||||||
"http://ostatus.org#atomUri": [
|
|
||||||
{
|
|
||||||
"@value": "https://activitypub.academy/users/fagusia_aseod/statuses/113046106230737452"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"http://ostatus.org#conversation": [
|
|
||||||
{
|
|
||||||
"@value": "tag:activitypub.academy,2024-08-29:objectId=186920:objectType=Conversation"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"http://ostatus.org#inReplyToAtomUri": [
|
|
||||||
{
|
|
||||||
"@value": "https://activitypub.academy/users/fagusia_aseod/statuses/113046100718699502"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#attachment": [],
|
|
||||||
"https://www.w3.org/ns/activitystreams#attributedTo": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#cc": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/followers"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#content": [
|
|
||||||
{
|
|
||||||
"@value": "\u003cp\u003ereply\u003c/p\u003e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"@language": "en",
|
|
||||||
"@value": "\u003cp\u003ereply\u003c/p\u003e"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#inReplyTo": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/statuses/113046100718699502"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#published": [
|
|
||||||
{
|
|
||||||
"@type": "http://www.w3.org/2001/XMLSchema#dateTime",
|
|
||||||
"@value": "2024-08-29T15:51:29Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#replies": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/statuses/113046106230737452/replies",
|
|
||||||
"@type": [
|
|
||||||
"https://www.w3.org/ns/activitystreams#Collection"
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#first": [
|
|
||||||
{
|
|
||||||
"@type": [
|
|
||||||
"https://www.w3.org/ns/activitystreams#CollectionPage"
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#items": [],
|
|
||||||
"https://www.w3.org/ns/activitystreams#next": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/statuses/113046106230737452/replies?only_other_accounts=true\u0026page=true"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#partOf": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/statuses/113046106230737452/replies"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#sensitive": [
|
|
||||||
{
|
|
||||||
"@value": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#tag": [],
|
|
||||||
"https://www.w3.org/ns/activitystreams#to": [
|
|
||||||
{
|
|
||||||
"@id": "https://www.w3.org/ns/activitystreams#Public"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#url": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/@fagusia_aseod/113046106230737452"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#next": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/statuses/113046100718699502/replies?only_other_accounts=true\u0026page=true"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#partOf": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/statuses/113046100718699502/replies"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,96 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/statuses/113049754774052158",
|
|
||||||
"@type": [
|
|
||||||
"https://www.w3.org/ns/activitystreams#Note"
|
|
||||||
],
|
|
||||||
"http://ostatus.org#atomUri": [
|
|
||||||
{
|
|
||||||
"@value": "https://activitypub.academy/users/fagusia_aseod/statuses/113049754774052158"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"http://ostatus.org#conversation": [
|
|
||||||
{
|
|
||||||
"@value": "tag:activitypub.academy,2024-08-30:objectId=186955:objectType=Conversation"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"http://ostatus.org#inReplyToAtomUri": [
|
|
||||||
{
|
|
||||||
"@value": "https://activitypub.academy/users/fagusia_aseod/statuses/113049753895761634"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#attachment": [],
|
|
||||||
"https://www.w3.org/ns/activitystreams#attributedTo": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#cc": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/followers"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#content": [
|
|
||||||
{
|
|
||||||
"@value": "\u003cp\u003ereply\u003c/p\u003e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"@language": "en",
|
|
||||||
"@value": "\u003cp\u003ereply\u003c/p\u003e"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#inReplyTo": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/statuses/113049753895761634"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#published": [
|
|
||||||
{
|
|
||||||
"@type": "http://www.w3.org/2001/XMLSchema#dateTime",
|
|
||||||
"@value": "2024-08-30T07:19:21Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#replies": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/statuses/113049754774052158/replies",
|
|
||||||
"@type": [
|
|
||||||
"https://www.w3.org/ns/activitystreams#Collection"
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#first": [
|
|
||||||
{
|
|
||||||
"@type": [
|
|
||||||
"https://www.w3.org/ns/activitystreams#CollectionPage"
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#items": [],
|
|
||||||
"https://www.w3.org/ns/activitystreams#next": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/statuses/113049754774052158/replies?only_other_accounts=true\u0026page=true"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#partOf": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/users/fagusia_aseod/statuses/113049754774052158/replies"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#sensitive": [
|
|
||||||
{
|
|
||||||
"@value": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#tag": [],
|
|
||||||
"https://www.w3.org/ns/activitystreams#to": [
|
|
||||||
{
|
|
||||||
"@id": "https://www.w3.org/ns/activitystreams#Public"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#url": [
|
|
||||||
{
|
|
||||||
"@id": "https://activitypub.academy/@fagusia_aseod/113049754774052158"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,75 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"@id": "https://fedi.catboy.agency/notes/9xk3lj95g43b02t8",
|
|
||||||
"@type": [
|
|
||||||
"https://www.w3.org/ns/activitystreams#Note"
|
|
||||||
],
|
|
||||||
"http://fedibird.com/ns#quoteUri": [
|
|
||||||
{
|
|
||||||
"@value": "https://activitypub.academy/users/fagusia_aseod/statuses/113050350412353987"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://misskey-hub.net/ns#_misskey_content": [
|
|
||||||
{
|
|
||||||
"@value": "quote test"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://misskey-hub.net/ns#_misskey_quote": [
|
|
||||||
{
|
|
||||||
"@value": "https://activitypub.academy/users/fagusia_aseod/statuses/113050350412353987"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#attachment": [],
|
|
||||||
"https://www.w3.org/ns/activitystreams#attributedTo": [
|
|
||||||
{
|
|
||||||
"@id": "https://fedi.catboy.agency/users/9ltetvu2n34t01lj"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#cc": [
|
|
||||||
{
|
|
||||||
"@id": "https://fedi.catboy.agency/users/9ltetvu2n34t01lj/followers"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#content": [
|
|
||||||
{
|
|
||||||
"@value": "\u003cp\u003e\u003cspan\u003equote test\u003cbr\u003e\u003cbr\u003eRE: \u003c/span\u003e\u003ca href=\"https://activitypub.academy/users/fagusia_aseod/statuses/113050350412353987\"\u003ehttps://activitypub.academy/users/fagusia_aseod/statuses/113050350412353987\u003c/a\u003e\u003c/p\u003e"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#published": [
|
|
||||||
{
|
|
||||||
"@type": "http://www.w3.org/2001/XMLSchema#dateTime",
|
|
||||||
"@value": "2024-08-30T09:51:01.049Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#quoteUrl": [
|
|
||||||
{
|
|
||||||
"@value": "https://activitypub.academy/users/fagusia_aseod/statuses/113050350412353987"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#sensitive": [
|
|
||||||
{
|
|
||||||
"@value": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#source": [
|
|
||||||
{
|
|
||||||
"https://www.w3.org/ns/activitystreams#content": [
|
|
||||||
{
|
|
||||||
"@value": "quote test"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#mediaType": [
|
|
||||||
{
|
|
||||||
"@value": "text/x.misskeymarkdown"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://www.w3.org/ns/activitystreams#tag": [],
|
|
||||||
"https://www.w3.org/ns/activitystreams#to": [
|
|
||||||
{
|
|
||||||
"@id": "https://www.w3.org/ns/activitystreams#Public"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,43 +0,0 @@
|
||||||
{
|
|
||||||
"@context": [
|
|
||||||
"https://www.w3.org/ns/activitystreams",
|
|
||||||
{
|
|
||||||
"ostatus": "http://ostatus.org#",
|
|
||||||
"atomUri": "ostatus:atomUri",
|
|
||||||
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
|
|
||||||
"conversation": "ostatus:conversation",
|
|
||||||
"sensitive": "as:sensitive",
|
|
||||||
"toot": "http://joinmastodon.org/ns#",
|
|
||||||
"votersCount": "toot:votersCount"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"id": "https://activitypub.academy/users/fagusia_aseod/statuses/113049754774052158",
|
|
||||||
"type": "Note",
|
|
||||||
"summary": null,
|
|
||||||
"inReplyTo": "https://activitypub.academy/users/fagusia_aseod/statuses/113049753895761634",
|
|
||||||
"published": "2024-08-30T07:19:21Z",
|
|
||||||
"url": "https://activitypub.academy/@fagusia_aseod/113049754774052158",
|
|
||||||
"attributedTo": "https://activitypub.academy/users/fagusia_aseod",
|
|
||||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
|
||||||
"cc": ["https://activitypub.academy/users/fagusia_aseod/followers"],
|
|
||||||
"sensitive": false,
|
|
||||||
"atomUri": "https://activitypub.academy/users/fagusia_aseod/statuses/113049754774052158",
|
|
||||||
"inReplyToAtomUri": "https://activitypub.academy/users/fagusia_aseod/statuses/113049753895761634",
|
|
||||||
"conversation": "tag:activitypub.academy,2024-08-30:objectId=186955:objectType=Conversation",
|
|
||||||
"content": "<p>reply</p>",
|
|
||||||
"contentMap": {
|
|
||||||
"en": "<p>reply</p>"
|
|
||||||
},
|
|
||||||
"attachment": [],
|
|
||||||
"tag": [],
|
|
||||||
"replies": {
|
|
||||||
"id": "https://activitypub.academy/users/fagusia_aseod/statuses/113049754774052158/replies",
|
|
||||||
"type": "Collection",
|
|
||||||
"first": {
|
|
||||||
"type": "CollectionPage",
|
|
||||||
"next": "https://activitypub.academy/users/fagusia_aseod/statuses/113049754774052158/replies?only_other_accounts=true&page=true",
|
|
||||||
"partOf": "https://activitypub.academy/users/fagusia_aseod/statuses/113049754774052158/replies",
|
|
||||||
"items": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
{
|
|
||||||
"@context": [
|
|
||||||
"https://www.w3.org/ns/activitystreams",
|
|
||||||
"https://w3id.org/security/v1",
|
|
||||||
{
|
|
||||||
"Key": "sec:Key",
|
|
||||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
|
||||||
"sensitive": "as:sensitive",
|
|
||||||
"Hashtag": "as:Hashtag",
|
|
||||||
"quoteUrl": "as:quoteUrl",
|
|
||||||
"fedibird": "http://fedibird.com/ns#",
|
|
||||||
"quoteUri": "fedibird:quoteUri",
|
|
||||||
"toot": "http://joinmastodon.org/ns#",
|
|
||||||
"Emoji": "toot:Emoji",
|
|
||||||
"featured": "toot:featured",
|
|
||||||
"discoverable": "toot:discoverable",
|
|
||||||
"schema": "http://schema.org#",
|
|
||||||
"PropertyValue": "schema:PropertyValue",
|
|
||||||
"value": "schema:value",
|
|
||||||
"misskey": "https://misskey-hub.net/ns#",
|
|
||||||
"_misskey_content": "misskey:_misskey_content",
|
|
||||||
"_misskey_quote": "misskey:_misskey_quote",
|
|
||||||
"_misskey_reaction": "misskey:_misskey_reaction",
|
|
||||||
"_misskey_votes": "misskey:_misskey_votes",
|
|
||||||
"_misskey_summary": "misskey:_misskey_summary",
|
|
||||||
"isCat": "misskey:isCat",
|
|
||||||
"firefish": "https://joinfirefish.org/ns#",
|
|
||||||
"speakAsCat": "firefish:speakAsCat",
|
|
||||||
"sharkey": "https://joinsharkey.org/ns#",
|
|
||||||
"backgroundUrl": "sharkey:backgroundUrl",
|
|
||||||
"listenbrainz": "sharkey:listenbrainz",
|
|
||||||
"vcard": "http://www.w3.org/2006/vcard/ns#"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"id": "https://fedi.catboy.agency/notes/9xk3lj95g43b02t8",
|
|
||||||
"type": "Note",
|
|
||||||
"attributedTo": "https://fedi.catboy.agency/users/9ltetvu2n34t01lj",
|
|
||||||
"content": "<p><span>quote test<br><br>RE: </span><a href=\"https://activitypub.academy/users/fagusia_aseod/statuses/113050350412353987\">https://activitypub.academy/users/fagusia_aseod/statuses/113050350412353987</a></p>",
|
|
||||||
"_misskey_content": "quote test",
|
|
||||||
"source": {
|
|
||||||
"content": "quote test",
|
|
||||||
"mediaType": "text/x.misskeymarkdown"
|
|
||||||
},
|
|
||||||
"_misskey_quote": "https://activitypub.academy/users/fagusia_aseod/statuses/113050350412353987",
|
|
||||||
"quoteUrl": "https://activitypub.academy/users/fagusia_aseod/statuses/113050350412353987",
|
|
||||||
"quoteUri": "https://activitypub.academy/users/fagusia_aseod/statuses/113050350412353987",
|
|
||||||
"published": "2024-08-30T09:51:01.049Z",
|
|
||||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
|
||||||
"cc": ["https://fedi.catboy.agency/users/9ltetvu2n34t01lj/followers"],
|
|
||||||
"inReplyTo": null,
|
|
||||||
"attachment": [],
|
|
||||||
"sensitive": false,
|
|
||||||
"tag": []
|
|
||||||
}
|
|
6
go.mod
6
go.mod
|
@ -2,9 +2,11 @@ module gitlab.com/mstarongitlab/goap
|
||||||
|
|
||||||
go 1.22.5
|
go 1.22.5
|
||||||
|
|
||||||
|
require github.com/piprate/json-gold v0.5.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/datainq/xml-date-time v0.0.0-20170820214645-2292f08baa38
|
github.com/datainq/xml-date-time v0.0.0-20170820214645-2292f08baa38 // indirect
|
||||||
github.com/piprate/json-gold v0.5.0
|
github.com/samber/go-type-to-string v1.7.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -8,6 +8,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
|
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
|
||||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||||
|
github.com/samber/go-type-to-string v1.7.0 h1:FiSstaAikHMUSLt5bhVlsvCnD7bbQzC8L0UkkGS3Bj8=
|
||||||
|
github.com/samber/go-type-to-string v1.7.0/go.mod h1:jpU77vIDoIxkahknKDoEx9C8bQ1ADnh2sotZ8I4QqBU=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
gitlab.com/mstarongitlab/goutils v1.3.0 h1:uuxPHjIU36lyJ8/z4T2xI32zOyh53Xj0Au8K12qkaJ4=
|
gitlab.com/mstarongitlab/goutils v1.3.0 h1:uuxPHjIU36lyJ8/z4T2xI32zOyh53Xj0Au8K12qkaJ4=
|
||||||
|
|
|
@ -327,7 +327,7 @@ func ParseASFollowersData(raw map[string]any, next BaseApChain) (BaseApChain, er
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &ASFollowersData{FullIdType: *id}, nil
|
return &ASAttributedToData{FullIdType: *id}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ASFollowingData struct {
|
type ASFollowingData struct {
|
||||||
|
@ -347,7 +347,7 @@ func ParseASFollowingData(raw map[string]any, next BaseApChain) (BaseApChain, er
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &ASFollowingData{FullIdType: *id}, nil
|
return &ASAttributedToData{FullIdType: *id}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ASHrefData struct {
|
type ASHrefData struct {
|
||||||
|
@ -367,7 +367,7 @@ func ParseASHrefData(raw map[string]any, next BaseApChain) (BaseApChain, error)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &ASHrefData{FullIdType: *id}, nil
|
return &ASAttributedToData{FullIdType: *id}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ASIconData struct {
|
type ASIconData struct {
|
||||||
|
@ -503,7 +503,7 @@ func (attributedtodata *ASOutboxData) GetSelfOrBase() (BaseApChain, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (attributedtodata *ASOutboxData) MarshalToMap() map[string]any {
|
func (attributedtodata *ASOutboxData) MarshalToMap() map[string]any {
|
||||||
return attributedtodata.FullIdType.MarshalToMapWithName(KEY_ACTIVITYSTREAMS_OUTBOX)
|
return attributedtodata.FullIdType.MarshalToMapWithName(KEY_ACTIVITYSTREAMS_HREF)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseASOutboxData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
func ParseASOutboxData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
||||||
|
@ -515,29 +515,23 @@ func ParseASOutboxData(raw map[string]any, next BaseApChain) (BaseApChain, error
|
||||||
}
|
}
|
||||||
|
|
||||||
type ASObjectData struct {
|
type ASObjectData struct {
|
||||||
Next BaseApChain
|
FullIdType
|
||||||
// Unparsed objects. Please parse yourself. Go doesn't like the recursion if the parser for this attribute was calling Unmarshal
|
|
||||||
Objects []map[string]any
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (object *ASObjectData) GetSelfOrBase() (BaseApChain, bool) {
|
func (object *ASObjectData) GetSelfOrBase() (BaseApChain, bool) {
|
||||||
return object.Next, true
|
return object.FullIdType.Next, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (object *ASObjectData) MarshalToMap() map[string]any {
|
func (object *ASObjectData) MarshalToMap() map[string]any {
|
||||||
return appendWithKey(object.Next.MarshalToMap(), KEY_ACTIVITYSTREAMS_OBJECT, object.Objects)
|
return object.FullIdType.MarshalToMapWithName(KEY_ACTIVITYSTREAMS_OBJECT)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseASObjectData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
func ParseASObjectData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
||||||
rawData1, ok := raw[KEY_ACTIVITYSTREAMS_OBJECT]
|
id, err := ParseIdTypeWithName(raw, next, KEY_ACTIVITYSTREAMS_OBJECT)
|
||||||
if !ok {
|
if err != nil {
|
||||||
return nil, NoRequiredFieldError{KEY_ACTIVITYSTREAMS_OBJECT}
|
return nil, err
|
||||||
}
|
}
|
||||||
data, ok := rawData1.([]map[string]any)
|
return &ASObjectData{FullIdType: *id}, nil
|
||||||
if !ok {
|
|
||||||
return nil, BadFieldValueError[[]map[string]any]{KEY_ACTIVITYSTREAMS_OBJECT, rawData1, data}
|
|
||||||
}
|
|
||||||
return &ASObjectData{Next: next, Objects: data}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ASPreferredNameData struct {
|
type ASPreferredNameData struct {
|
||||||
|
@ -807,7 +801,7 @@ func (object *ASUrlData) GetSelfOrBase() (BaseApChain, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (object *ASUrlData) MarshalToMap() map[string]any {
|
func (object *ASUrlData) MarshalToMap() map[string]any {
|
||||||
return object.FullIdType.MarshalToMapWithName(KEY_ACTIVITYSTREAMS_URL)
|
return object.FullIdType.MarshalToMapWithName(KEY_ACTIVITYSTREAMS_SHAREDINBOX)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseASUrlData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
func ParseASUrlData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
||||||
|
@ -864,148 +858,3 @@ func ParseASUpdatedData(raw map[string]any, next BaseApChain) (BaseApChain, erro
|
||||||
Timestamp: t,
|
Timestamp: t,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ASFirstData struct {
|
|
||||||
Next BaseApChain
|
|
||||||
// Technically the object is decodable into BaseApChain as well
|
|
||||||
// but Go doesn't like the potential recursive call
|
|
||||||
// So uhh, you have to do it yourself
|
|
||||||
Objects map[string]any
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *ASFirstData) GetSelfOrBase() (BaseApChain, bool) {
|
|
||||||
return a.Next, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *ASFirstData) MarshalToMap() map[string]any {
|
|
||||||
return appendWithKey(
|
|
||||||
a.Next.MarshalToMap(),
|
|
||||||
KEY_ACTIVITYSTREAMS_FIRST,
|
|
||||||
[]map[string]any{a.Objects},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseASFirstData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
|
||||||
rawData, ok := raw[KEY_ACTIVITYSTREAMS_FIRST]
|
|
||||||
if !ok {
|
|
||||||
return nil, NoRequiredFieldError{KEY_ACTIVITYSTREAMS_FIRST}
|
|
||||||
}
|
|
||||||
data, ok := rawData.([]map[string]any)
|
|
||||||
if !ok {
|
|
||||||
return nil, BadFieldValueError[[]map[string]any]{KEY_ACTIVITYSTREAMS_FIRST, rawData, data}
|
|
||||||
}
|
|
||||||
if len(data) != 1 {
|
|
||||||
return nil, BadFieldArrayLengthError{KEY_ACTIVITYSTREAMS_FIRST, 1, len(data)}
|
|
||||||
}
|
|
||||||
delete(raw, KEY_ACTIVITYSTREAMS_FIRST)
|
|
||||||
return &ASFirstData{
|
|
||||||
Next: next,
|
|
||||||
Objects: data[0],
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type ASItemsData struct {
|
|
||||||
Next BaseApChain
|
|
||||||
// Items are all AP objects, but can't preparse since Go doesn't like the potential recursion
|
|
||||||
Items []map[string]any
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *ASItemsData) GetSelfOrBase() (BaseApChain, bool) {
|
|
||||||
return a.Next, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *ASItemsData) MarshalToMap() map[string]any {
|
|
||||||
return appendWithKey(a.Next.MarshalToMap(), KEY_ACTIVITYSTREAMS_ITEMS, a.Items)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseASItemsData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
|
||||||
rawData, ok := raw[KEY_ACTIVITYSTREAMS_ITEMS]
|
|
||||||
if !ok {
|
|
||||||
return nil, NoRequiredFieldError{KEY_ACTIVITYSTREAMS_ITEMS}
|
|
||||||
}
|
|
||||||
data, ok := rawData.([]map[string]any)
|
|
||||||
if !ok {
|
|
||||||
return nil, BadFieldValueError[[]map[string]any]{KEY_ACTIVITYSTREAMS_ITEMS, rawData, data}
|
|
||||||
}
|
|
||||||
return &ASItemsData{Next: next, Items: data}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type ASNextData struct {
|
|
||||||
FullIdType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (object *ASNextData) GetSelfOrBase() (BaseApChain, bool) {
|
|
||||||
return object.FullIdType.Next, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (object *ASNextData) MarshalToMap() map[string]any {
|
|
||||||
return object.FullIdType.MarshalToMapWithName(KEY_ACTIVITYSTREAMS_NEXT)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseASNextData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
|
||||||
id, err := ParseIdTypeWithName(raw, next, KEY_ACTIVITYSTREAMS_NEXT)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &ASNextData{FullIdType: *id}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type ASPartOfData struct {
|
|
||||||
FullIdType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (object *ASPartOfData) GetSelfOrBase() (BaseApChain, bool) {
|
|
||||||
return object.FullIdType.Next, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (object *ASPartOfData) MarshalToMap() map[string]any {
|
|
||||||
return object.FullIdType.MarshalToMapWithName(KEY_ACTIVITYSTREAMS_PARTOF)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseASPartOfData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
|
||||||
id, err := ParseIdTypeWithName(raw, next, KEY_ACTIVITYSTREAMS_PARTOF)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &ASPartOfData{FullIdType: *id}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type ASInReplyTo struct {
|
|
||||||
FullIdType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *ASInReplyTo) GetSelfOrBase() (BaseApChain, bool) {
|
|
||||||
return a.Next, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *ASInReplyTo) MarshalToMap() map[string]any {
|
|
||||||
return a.MarshalToMapWithName(KEY_ACTIVITYSTREAMS_INREPLYTO)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseASInReplyToData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
|
||||||
id, err := ParseIdTypeWithName(raw, next, KEY_ACTIVITYSTREAMS_INREPLYTO)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &ASInReplyTo{*id}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type ASQuoteUrlData struct {
|
|
||||||
FullValueType[string]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (namedata *ASQuoteUrlData) GetSelfOrBase() (BaseApChain, bool) {
|
|
||||||
return namedata.Next, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (namedata *ASQuoteUrlData) MarshalToMap() map[string]any {
|
|
||||||
return namedata.MarshalToMapWithName(KEY_ACTIVITYSTREAMS_QUOTEURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseASQuoteUrlData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
|
||||||
tmp, err := ParseValueTypeWithName[string](raw, next, KEY_ACTIVITYSTREAMS_QUOTEURL)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &ASQuoteUrlData{*tmp}, nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
package goap
|
|
||||||
|
|
||||||
type FedibirdQuoteUriData struct {
|
|
||||||
FullValueType[string]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FedibirdQuoteUriData) GetSelfOrBase() (BaseApChain, bool) {
|
|
||||||
return f.Next, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FedibirdQuoteUriData) MarshalToMap() map[string]any {
|
|
||||||
return f.MarshalToMapWithName(KEY_FEDIBIRD_QUOTEURI)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseFedibirdQuoteUriData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
|
||||||
v, err := ParseValueTypeWithName[string](raw, next, KEY_FEDIBIRD_QUOTEURI)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &FedibirdQuoteUriData{*v}, nil
|
|
||||||
}
|
|
20
nsMisskey.go
20
nsMisskey.go
|
@ -61,23 +61,3 @@ func ParseFFSpeakAsCatData(raw map[string]any, next BaseApChain) (BaseApChain, e
|
||||||
}
|
}
|
||||||
return &FFSpeakAsCatData{*tmp}, nil
|
return &FFSpeakAsCatData{*tmp}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type MKQuoteData struct {
|
|
||||||
FullValueType[string]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (misskeysummarydata *MKQuoteData) GetSelfOrBase() (BaseApChain, bool) {
|
|
||||||
return misskeysummarydata.Next, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (misskeysummarydata *MKQuoteData) MarshalToMap() map[string]any {
|
|
||||||
return misskeysummarydata.MarshalToMapWithName(KEY_MISSKEY_MKQUOTE)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseMKQuoteData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
|
||||||
tmp, err := ParseValueTypeWithName[string](raw, next, KEY_MISSKEY_MKQUOTE)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &MKQuoteData{*tmp}, nil
|
|
||||||
}
|
|
||||||
|
|
84
nsOstatus.go
84
nsOstatus.go
|
@ -1,7 +1,8 @@
|
||||||
package goap
|
package goap
|
||||||
|
|
||||||
type OstatusAtomUriData struct {
|
type OstatusAtomUriData struct {
|
||||||
FullValueType[string]
|
Next BaseApChain
|
||||||
|
Uri ValueValue[string]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (atomurivalue *OstatusAtomUriData) GetSelfOrBase() (BaseApChain, bool) {
|
func (atomurivalue *OstatusAtomUriData) GetSelfOrBase() (BaseApChain, bool) {
|
||||||
|
@ -9,19 +10,43 @@ func (atomurivalue *OstatusAtomUriData) GetSelfOrBase() (BaseApChain, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (atomurivalue *OstatusAtomUriData) MarshalToMap() map[string]any {
|
func (atomurivalue *OstatusAtomUriData) MarshalToMap() map[string]any {
|
||||||
return atomurivalue.MarshalToMapWithName(KEY_OSTATUS_ATOMURI)
|
return appendWithKey(
|
||||||
|
atomurivalue.Next.MarshalToMap(),
|
||||||
|
KEY_OSTATUS_ATOMURI,
|
||||||
|
[]map[string]any{atomurivalue.Uri.Marshal()},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseOstatusAtomUriData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
func ParseOstatusAtomUriData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
||||||
v, err := ParseValueTypeWithName[string](raw, next, KEY_OSTATUS_ATOMURI)
|
rawData1, ok := raw[KEY_OSTATUS_ATOMURI]
|
||||||
|
if !ok {
|
||||||
|
return nil, NoRequiredFieldError{KEY_OSTATUS_ATOMURI}
|
||||||
|
}
|
||||||
|
data1, ok := rawData1.([]map[string]any)
|
||||||
|
if !ok {
|
||||||
|
return nil, BadFieldValueError[[]map[string]any]{
|
||||||
|
KEY_OSTATUS_ATOMURI,
|
||||||
|
rawData1,
|
||||||
|
data1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(data1) != 1 {
|
||||||
|
return nil, BadFieldArrayLengthError{KEY_OSTATUS_ATOMURI, 1, len(data1)}
|
||||||
|
}
|
||||||
|
tmp, err := ParseValueValue[string](data1[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &OstatusAtomUriData{*v}, nil
|
delete(raw, KEY_OSTATUS_ATOMURI)
|
||||||
|
return &OstatusAtomUriData{
|
||||||
|
Next: next,
|
||||||
|
Uri: *tmp,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type OstatusConversationData struct {
|
type OstatusConversationData struct {
|
||||||
FullValueType[string]
|
Next BaseApChain
|
||||||
|
Uri ValueValue[string]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (atomurivalue *OstatusConversationData) GetSelfOrBase() (BaseApChain, bool) {
|
func (atomurivalue *OstatusConversationData) GetSelfOrBase() (BaseApChain, bool) {
|
||||||
|
@ -29,33 +54,36 @@ func (atomurivalue *OstatusConversationData) GetSelfOrBase() (BaseApChain, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (atomurivalue *OstatusConversationData) MarshalToMap() map[string]any {
|
func (atomurivalue *OstatusConversationData) MarshalToMap() map[string]any {
|
||||||
return atomurivalue.MarshalToMapWithName(KEY_OSTATUS_CONVERSATION)
|
return appendWithKey(
|
||||||
|
atomurivalue.Next.MarshalToMap(),
|
||||||
|
KEY_OSTATUS_CONVERSATION,
|
||||||
|
[]map[string]any{atomurivalue.Uri.Marshal()},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseOstatusConversationData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
func ParseOstatusConversationData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
||||||
v, err := ParseValueTypeWithName[string](raw, next, KEY_OSTATUS_CONVERSATION)
|
rawData1, ok := raw[KEY_OSTATUS_CONVERSATION]
|
||||||
|
if !ok {
|
||||||
|
return nil, NoRequiredFieldError{KEY_OSTATUS_CONVERSATION}
|
||||||
|
}
|
||||||
|
data1, ok := rawData1.([]map[string]any)
|
||||||
|
if !ok {
|
||||||
|
return nil, BadFieldValueError[[]map[string]any]{
|
||||||
|
KEY_OSTATUS_CONVERSATION,
|
||||||
|
rawData1,
|
||||||
|
data1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(data1) != 1 {
|
||||||
|
return nil, BadFieldArrayLengthError{KEY_OSTATUS_CONVERSATION, 1, len(data1)}
|
||||||
|
}
|
||||||
|
tmp, err := ParseValueValue[string](data1[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &OstatusConversationData{*v}, nil
|
delete(raw, KEY_OSTATUS_CONVERSATION)
|
||||||
}
|
return &OstatusConversationData{
|
||||||
|
Next: next,
|
||||||
type OstatusReplyToAtomUriData struct {
|
Uri: *tmp,
|
||||||
FullValueType[string]
|
}, nil
|
||||||
}
|
|
||||||
|
|
||||||
func (a *OstatusReplyToAtomUriData) GetSelfOrBase() (BaseApChain, bool) {
|
|
||||||
return a.Next, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *OstatusReplyToAtomUriData) MarshalToMap() map[string]any {
|
|
||||||
return a.MarshalToMapWithName(KEY_OSTATUS_INREPLYTOATOMURI)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseOstatusInReplyToAtomUriData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
|
||||||
v, err := ParseValueTypeWithName[string](raw, next, KEY_OSTATUS_INREPLYTOATOMURI)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &OstatusReplyToAtomUriData{*v}, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
package goap
|
|
||||||
|
|
||||||
type UDIdData struct {
|
|
||||||
Next BaseApChain
|
|
||||||
Id string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UDIdData) GetSelfOrBase() (BaseApChain, bool) {
|
|
||||||
return u.Next, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *UDIdData) MarshalToMap() map[string]any {
|
|
||||||
return appendWithKey(b.Next.MarshalToMap(), "KEY_ID", b.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseUDIdData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
|
||||||
rawId, ok := raw[KEY_ID]
|
|
||||||
if !ok {
|
|
||||||
return nil, NoRequiredFieldError{KEY_ID}
|
|
||||||
}
|
|
||||||
id, ok := rawId.(string)
|
|
||||||
if !ok {
|
|
||||||
return nil, BadFieldValueError[string]{KEY_ID, rawId, ""}
|
|
||||||
}
|
|
||||||
delete(raw, KEY_ID)
|
|
||||||
return &UDIdData{
|
|
||||||
Next: next,
|
|
||||||
Id: id,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type UDTypeData struct {
|
|
||||||
Next BaseApChain
|
|
||||||
Type string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UDTypeData) GetSelfOrBase() (BaseApChain, bool) {
|
|
||||||
return u.Next, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UDTypeData) MarshalToMap() map[string]any {
|
|
||||||
return appendWithKey(u.Next.MarshalToMap(), KEY_TYPE, []any{u.Type})
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseUDTypeData(raw map[string]any, next BaseApChain) (BaseApChain, error) {
|
|
||||||
rawObjType, ok := raw[KEY_TYPE]
|
|
||||||
if !ok {
|
|
||||||
return nil, NoRequiredFieldError{KEY_TYPE}
|
|
||||||
}
|
|
||||||
objType, ok := rawObjType.([]string)
|
|
||||||
if !ok {
|
|
||||||
return nil, BadFieldValueError[[]string]{KEY_TYPE, rawObjType, []string{}}
|
|
||||||
}
|
|
||||||
if len(objType) != 1 {
|
|
||||||
return nil, BadFieldArrayLengthError{KEY_TYPE, 1, len(objType)}
|
|
||||||
}
|
|
||||||
return &UDTypeData{Next: next, Type: objType[0]}, nil
|
|
||||||
}
|
|
34
old/actor.go
Normal file
34
old/actor.go
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package ap
|
||||||
|
|
||||||
|
type MinimalActor struct {
|
||||||
|
Id string
|
||||||
|
Username string
|
||||||
|
Inbox string
|
||||||
|
}
|
||||||
|
|
||||||
|
type MastoActor struct {
|
||||||
|
Id string
|
||||||
|
Devices MastoDevices
|
||||||
|
Discoverable MastoDiscoverable
|
||||||
|
Featured MastoFeatured
|
||||||
|
FeaturedTags MastoFeaturedTags
|
||||||
|
Indexable MastoIndexable
|
||||||
|
Memorial MastoMemorial
|
||||||
|
Inbox W3Inbox
|
||||||
|
PublicKey W3SecurityPublicKey
|
||||||
|
AlsoKnownAs ActivityStreamsAlsoKnownAs
|
||||||
|
Attachments []ActivityStreamsAttachment
|
||||||
|
Endpoints []map[string]IdType
|
||||||
|
Followers ActivityStreamsFollowers
|
||||||
|
Following ActivityStreamsFollowing
|
||||||
|
Icon ActivityStreamsIcon
|
||||||
|
Image ActivityStreamsImage
|
||||||
|
RestrictedFollow ActivityStreamsRestrictedFollow
|
||||||
|
Name ActivityStreamsName
|
||||||
|
Outbox ActivityStreamsOutbox
|
||||||
|
PrefferedUsername ActivityStreamsPrefferedUsername
|
||||||
|
Published ActivityStreamsPublished
|
||||||
|
Summary ActivityStreamsSummary
|
||||||
|
Tags []ActivityStreamsTag
|
||||||
|
Url ActivityStreamsUrl
|
||||||
|
}
|
24
old/checkHeader.go
Normal file
24
old/checkHeader.go
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
package ap
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// Header used for making requests for AP resources
|
||||||
|
// Not used yet
|
||||||
|
const OUTBOUND_REQUEST_HEADER = "application/ld+json, application/json;q=0.9, application/javascript;q=0.5, text/javascript;q=0.5, text/plain;q=0.2, */*;q=0.1"
|
||||||
|
|
||||||
|
var contentHeadersToCheck = []string{
|
||||||
|
"application/json",
|
||||||
|
"application/ld+json",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check a given string if it contains any of the content types specified in
|
||||||
|
// the contentHeadersToCheck slice
|
||||||
|
// Used for differentiating requests for the ActivityPub version of some data vs frontend version
|
||||||
|
func ContainsApContentHeader(toCheck string) bool {
|
||||||
|
for _, h := range contentHeadersToCheck {
|
||||||
|
if strings.Contains(toCheck, h) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
18
old/common_types.go
Normal file
18
old/common_types.go
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package ap
|
||||||
|
|
||||||
|
import "net/url"
|
||||||
|
|
||||||
|
type IdType struct {
|
||||||
|
Id *url.URL
|
||||||
|
}
|
||||||
|
|
||||||
|
type ValueType[T any] struct {
|
||||||
|
Value T
|
||||||
|
}
|
||||||
|
|
||||||
|
type Media struct {
|
||||||
|
Type url.URL
|
||||||
|
MediaType *ValueType[string]
|
||||||
|
Url IdType
|
||||||
|
Sensitive *ValueType[bool]
|
||||||
|
}
|
81
old/constants.go
Normal file
81
old/constants.go
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
package ap
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
KEY_MASTO_FEATURED = "http://joinmastodon.org/ns#featured" // Users tagged? I think
|
||||||
|
KEY_MASTO_FEATURED_TAGS = "http://joinmastodon.org/ns#featuredTags" // Hashtags included, I think
|
||||||
|
KEY_MASTO_INDEXABLE = "http://joinmastodon.org/ns#indexable" // Is the object crawlable round 2
|
||||||
|
KEY_MASTO_MEMORIAL = "http://joinmastodon.org/ns#memorial" // Account dead and disabled?
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
KEY_W3_INBOX = "http://www.w3.org/ns/ldp#inbox" // Where to send activities to
|
||||||
|
KEY_W3_SECURITY_PUBLICKEY = "https://w3id.org/security#publicKey" // Public key of the account
|
||||||
|
KEY_W3_SECURITY_OWNER = "https://w3id.org/security#owner" // Owner of the public key
|
||||||
|
KEY_W3_SECURITY_PUBLICKEYPEM = "https://w3id.org/security#publicKeyPem" // Pem content of the key
|
||||||
|
KEY_W3_VCARD_ADRESS = "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
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
KEY_ACTIVITYSTREAMS_ALSOKNOWNAS = "https://www.w3.org/ns/activitystreams#alsoKnownAs" // Lists of usernames?
|
||||||
|
KEY_ACTIVITYSTREAMS_ATTACHMENTS = "https://www.w3.org/ns/activitystreams#attachment" // Attached elements like emotes and hashtags
|
||||||
|
KEY_ACTIVITYSTREAMS_NAME = "https://www.w3.org/ns/activitystreams#name" // AP name
|
||||||
|
KEY_ACTIVITYSTREAMS_ENDPOINTS = "https://www.w3.org/ns/activitystreams#endpoints" // list of assocciated endpoints
|
||||||
|
KEY_ACTIVITYSTREAMS_SHAREDINBOX = "https://www.w3.org/ns/activitystreams#sharedInbox" // Link to the shared inbox of the server
|
||||||
|
KEY_ACTIVITYSTREAMS_FOLLOWERS = "https://www.w3.org/ns/activitystreams#followers" // Who is following the account
|
||||||
|
KEY_ACTIVITYSTREAMS_FOLLOWING = "https://www.w3.org/ns/activitystreams#following" // Who is this account following
|
||||||
|
KEY_ACTIVITYSTREAMS_ICON = "https://www.w3.org/ns/activitystreams#icon" // User icon
|
||||||
|
KEY_ACTIVITYSTREAMS_MEDIATYPE = "https://www.w3.org/ns/activitystreams#mediaType" // What type of media is this? Example image/jpeg
|
||||||
|
KEY_ACTIVITYSTREAMS_URL = "https://www.w3.org/ns/activitystreams#url" // Some url
|
||||||
|
KEY_ACTIVITYSTREAMS_IMAGE = "https://www.w3.org/ns/activitystreams#image" // Account banner
|
||||||
|
KEY_ACTIVITYSTREAMS_RESTRICTED_FOLLOW = "https://www.w3.org/ns/activitystreams#manuallyApprovesFollowers" // Does the account manually approve follow requests
|
||||||
|
KEY_ACTIVITYSTREAMS_OUTBOX = "https://www.w3.org/ns/activitystreams#outbox" // Link to the account's outbox
|
||||||
|
KEY_ACTIVITYSTREAMS_PREFFEREDUSERNAME = "https://www.w3.org/ns/activitystreams#preferredUsername" // What the shown username is
|
||||||
|
KEY_ACTIVITYSTREAMS_PUBLISHED = "https://www.w3.org/ns/activitystreams#published" // When an object was created
|
||||||
|
KEY_ACTIVITYSTREAMS_SUMMARY = "https://www.w3.org/ns/activitystreams#summary" // Summary of an account
|
||||||
|
KEY_ACTIVITYSTREAMS_TAG = "https://www.w3.org/ns/activitystreams#tag" // A tag, no idea what those are
|
||||||
|
KEY_ACTIVITYSTREAMS_CC = "https://www.w3.org/ns/activitystreams#cc" // Urls also included in the object
|
||||||
|
KEY_ACTIVITYSTREAMS_TO = "https://www.w3.org/ns/activitystreams#to" // Urls to send an activity to
|
||||||
|
KEY_ACTIVITYSTREAMS_OBJECT = "https://www.w3.org/ns/activitystreams#object" // Object url and sometimes value
|
||||||
|
|
||||||
|
// Object types (I think)
|
||||||
|
// Those are values the object type can have
|
||||||
|
|
||||||
|
KEY_ACTIVITYSTREAMS_ACTOR = "https://www.w3.org/ns/activitystreams#actor"
|
||||||
|
KEY_ACTIVITYSTREAMS_FOLLOW = "https://www.w3.org/ns/activitystreams#Follow" // Object is an activity of type follow
|
||||||
|
KEY_ACTIVITYSTREAMS_PERSON = "https://www.w3.org/ns/activitystreams#Person" // Object is of type Person
|
||||||
|
KEY_ACTIVITYSTREAMS_CREATE = "https://www.w3.org/ns/activitystreams#Create" // Object is an activity of type Create
|
||||||
|
|
||||||
|
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_UPLOADMEDIA = "https://www.w3.org/ns/activitystreams#uploadMedia" // Endpoint url to upload media to?
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
KEY_SCHEMA_VALUE = "http://schema.org#value" // The value for some field
|
||||||
|
)
|
||||||
|
|
||||||
|
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?
|
||||||
|
KEY_FIREFISH_SPEAKASCAT = "https://joinfirefish.org/ns#speakAsCat" // Does the account speak like a cat?
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
KEY_LITEPUB_CAPABILITIES = "http://litepub.social/ns#capabilities"
|
||||||
|
KEY_LITEPUB_OAUTHREGISTRATION = "http://litepub.social/ns#oauthRegistrationEndpoint"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
KEY_MYSTERIOUS_NOINDEX = "_:noindex"
|
||||||
|
KEY_MYSTERIOUS_BACKGROUNDURL = "_:backgroundUrl"
|
||||||
|
KEY_MYSTERIOUS_FEATURED = "_:featured"
|
||||||
|
)
|
49
old/context.go
Normal file
49
old/context.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package ap
|
||||||
|
|
||||||
|
// Just steal this one from sharkey
|
||||||
|
// Also use this one for all AP objects for now
|
||||||
|
// Can make a function to extract context from an expanded object later
|
||||||
|
// TODO: Consider if such a function is worth it or if it would hinder learning
|
||||||
|
var allContext = map[string]any{
|
||||||
|
"@context": []any{
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
map[string]any{
|
||||||
|
"fedibird": "http://fedibird.com/ns#",
|
||||||
|
"toot": "http://joinmastodon.org/ns#",
|
||||||
|
"schema": "http://schema.org#",
|
||||||
|
"misskey": "https://misskey-hub.net/ns#",
|
||||||
|
"firefish": "https://joinfirefish.org/ns#",
|
||||||
|
"sharkey": "https://joinsharkey.org/ns#",
|
||||||
|
"vcard": "http://www.w3.org/2006/vcard/ns#",
|
||||||
|
|
||||||
|
"Key": "sec:Key",
|
||||||
|
|
||||||
|
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||||
|
"sensitive": "as:sensitive",
|
||||||
|
"Hashtag": "as:Hashtag",
|
||||||
|
"quoteUrl": "as:quoteUrl",
|
||||||
|
|
||||||
|
"quoteUri": "fedibird:quoteUri",
|
||||||
|
|
||||||
|
"Emoji": "toot:Emoji",
|
||||||
|
"featured": "toot:featured",
|
||||||
|
"discoverable": "toot:discoverable",
|
||||||
|
|
||||||
|
"PropertyValue": "schema:PropertyValue",
|
||||||
|
"value": "schema:value",
|
||||||
|
|
||||||
|
"_misskey_content": "misskey:_misskey_content",
|
||||||
|
"_misskey_quote": "misskey:_misskey_quote",
|
||||||
|
"_misskey_reaction": "misskey:_misskey_reaction",
|
||||||
|
"_misskey_votes": "misskey:_misskey_votes",
|
||||||
|
"_misskey_summary": "misskey:_misskey_summary",
|
||||||
|
"isCat": "misskey:isCat",
|
||||||
|
|
||||||
|
"speakAsCat": "firefish:speakAsCat",
|
||||||
|
|
||||||
|
"backgroundUrl": "sharkey:backgroundUrl",
|
||||||
|
"listenbrainz": "sharkey:listenbrainz",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
61
old/explicit_types.go
Normal file
61
old/explicit_types.go
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
package ap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
ActivityStreamsAlsoKnownAs IdType
|
||||||
|
ActivityStreamsAttachment struct {
|
||||||
|
Type *url.URL
|
||||||
|
Value ValueType[string]
|
||||||
|
Name ValueType[string]
|
||||||
|
}
|
||||||
|
ActivityStreamsSharedInbox IdType
|
||||||
|
ActivityStreamsFollowers IdType
|
||||||
|
ActivityStreamsFollowing IdType
|
||||||
|
ActivityStreamsImage Media
|
||||||
|
ActivityStreamsIcon Media
|
||||||
|
ActivityStreamsRestrictedFollow ValueType[bool]
|
||||||
|
ActivityStreamsName ValueType[string]
|
||||||
|
ActivityStreamsOutbox IdType
|
||||||
|
ActivityStreamsPrefferedUsername ValueType[string]
|
||||||
|
ActivityStreamsPublished struct {
|
||||||
|
Type string
|
||||||
|
Value time.Time
|
||||||
|
}
|
||||||
|
ActivityStreamsSummary ValueType[string]
|
||||||
|
ActivityStreamsUrl IdType
|
||||||
|
// NOTE: Technically can contain a lot more values, but tags are not consistent in what those are. Only consistent one is the type
|
||||||
|
|
||||||
|
ActivityStreamsTag struct {
|
||||||
|
Type string
|
||||||
|
}
|
||||||
|
ActivityStreamsTo IdType
|
||||||
|
ActivityStreamsCC IdType
|
||||||
|
|
||||||
|
ActivityStreamsActor IdType
|
||||||
|
// NOTE: Technically, objects can have a LOT of data. I don't care. Treat them as ID type
|
||||||
|
// Just fetch whatever the ID is later on separately and throw away anything else but the ID
|
||||||
|
ActivityStreamsObject IdType
|
||||||
|
ActivityStreamsFollow IdType
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
MastoDevices IdType
|
||||||
|
MastoDiscoverable ValueType[bool]
|
||||||
|
MastoFeatured IdType
|
||||||
|
MastoFeaturedTags IdType
|
||||||
|
MastoIndexable ValueType[bool]
|
||||||
|
MastoMemorial ValueType[bool]
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
W3Inbox IdType
|
||||||
|
W3SecurityPublicKey struct {
|
||||||
|
Id *url.URL
|
||||||
|
Owner *url.URL
|
||||||
|
KeyPem string
|
||||||
|
}
|
||||||
|
)
|
58
old/parser.go
Normal file
58
old/parser.go
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
package ap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/piprate/json-gold/ld"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ApThing map[string]any
|
||||||
|
|
||||||
|
type RemoteDocumentLoader struct{}
|
||||||
|
|
||||||
|
var ldOpts = ld.NewJsonLdOptions("")
|
||||||
|
var ldProcessor = ld.NewJsonLdProcessor()
|
||||||
|
|
||||||
|
// Try and parse a remote ActivityPub object into a more usable form
|
||||||
|
// Result is a map[string]any where the keys defined in /ap/constants.go should be usable,
|
||||||
|
// depending on the type of object
|
||||||
|
// The general approach for fetching an object will be to fetch the main object
|
||||||
|
// and only store the ID for sub-objects to fetch them later
|
||||||
|
func ParseFromUrl(u *url.URL) (ApThing, error) {
|
||||||
|
// TODO: Add custom document parser (copy default implementation) that includes verification
|
||||||
|
|
||||||
|
// Explanation:
|
||||||
|
// Expansion removes the context from a document (json-ld activitypub data)
|
||||||
|
// and turns every field into something along the lines of
|
||||||
|
// "https://example.com/ns#ObjectType": <Insert data for that object here>
|
||||||
|
// This makes it easier to deal with things as they now have a very consistent naming scheme
|
||||||
|
// See /ap/constants.go for those
|
||||||
|
|
||||||
|
parsed, err := ldProcessor.Expand(u.String(), ldOpts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to process remote document: %w", err)
|
||||||
|
}
|
||||||
|
if len(parsed) == 0 {
|
||||||
|
return nil, fmt.Errorf("document has a length of 0")
|
||||||
|
}
|
||||||
|
typed, ok := parsed[0].(ApThing)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("couldn't cast data to ApThing")
|
||||||
|
}
|
||||||
|
return typed, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compact an AP object down into a compressed json-ld form
|
||||||
|
// That compacted form should be accepted by all AP servers
|
||||||
|
// It also handles context for any fields
|
||||||
|
// Content should only use keys defined in /ap/constants.go though
|
||||||
|
// Other things might get lost in translation
|
||||||
|
func Compact(content map[string]any) ([]byte, error) {
|
||||||
|
res, err := ldProcessor.Compact(content, allContext, ldOpts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to compact data: %w", err)
|
||||||
|
}
|
||||||
|
return json.Marshal(res)
|
||||||
|
}
|
172
old/type_parsers.go
Normal file
172
old/type_parsers.go
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
package ap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Try and parse a value into an IdType
|
||||||
|
// Returns nil if failed
|
||||||
|
func TryParseIdType(rawIn any) *IdType {
|
||||||
|
switch in := rawIn.(type) {
|
||||||
|
case []any:
|
||||||
|
if len(in) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
m, ok := in[0].(map[string]any)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return TryParseIdType(m)
|
||||||
|
case map[string]any:
|
||||||
|
vRaw, ok := in[KEY_ID]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v, ok := vRaw.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
u, err := url.Parse(v)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &IdType{
|
||||||
|
Id: u,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TryParseValueType[T any](rawIn any) *ValueType[T] {
|
||||||
|
switch in := rawIn.(type) {
|
||||||
|
case map[string]any:
|
||||||
|
vRaw, ok := in[KEY_ID]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v, ok := vRaw.(T)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &ValueType[T]{
|
||||||
|
Value: v,
|
||||||
|
}
|
||||||
|
case []any:
|
||||||
|
if len(in) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v, ok := in[0].(map[string]any)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return TryParseValueType[T](v)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TryParseActivityStreamsPublicKey(rawIn any) *W3SecurityPublicKey {
|
||||||
|
switch in := rawIn.(type) {
|
||||||
|
case map[string]any:
|
||||||
|
asIdType := TryParseIdType(in)
|
||||||
|
if asIdType == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ownerType := TryParseIdType(in[KEY_W3_SECURITY_OWNER])
|
||||||
|
if ownerType == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
keyValue := TryParseValueType[string](in[KEY_W3_SECURITY_PUBLICKEYPEM])
|
||||||
|
if keyValue == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &W3SecurityPublicKey{
|
||||||
|
Id: asIdType.Id,
|
||||||
|
Owner: ownerType.Id,
|
||||||
|
KeyPem: keyValue.Value,
|
||||||
|
}
|
||||||
|
case []any:
|
||||||
|
if len(in) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return TryParseActivityStreamsPublicKey(in[0])
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TryParseActivityStreamsAttachment(rawIn any) *ActivityStreamsAttachment {
|
||||||
|
switch in := rawIn.(type) {
|
||||||
|
case []any:
|
||||||
|
if len(in) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return TryParseActivityStreamsAttachment(in[0])
|
||||||
|
case map[string]any:
|
||||||
|
rawType, ok := in[KEY_TYPE]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
strType, ok := rawType.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
urlType, err := url.Parse(strType)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := TryParseValueType[string](in[KEY_SCHEMA_VALUE])
|
||||||
|
if value == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
name := TryParseValueType[string](in[KEY_ACTIVITYSTREAMS_NAME])
|
||||||
|
if name == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &ActivityStreamsAttachment{
|
||||||
|
Type: urlType,
|
||||||
|
Name: *name,
|
||||||
|
Value: *value,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TryParseActivityStreamsPublished(rawIn any) *ActivityStreamsPublished {
|
||||||
|
switch in := rawIn.(type) {
|
||||||
|
case []any:
|
||||||
|
if len(in) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return TryParseActivityStreamsPublished(in[0])
|
||||||
|
case map[string]any:
|
||||||
|
rawType, ok := in[KEY_TYPE]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
strType, ok := rawType.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := TryParseValueType[string](in)
|
||||||
|
tv, err := time.Parse("2006-01-02T04:05:06Z", value.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &ActivityStreamsPublished{
|
||||||
|
Type: strType,
|
||||||
|
Value: tv,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Since I do not know if tags are consistent with the struct yet,
|
||||||
|
// This funtion does not do anything yet and should not be used
|
||||||
|
func TryParseActivityStreamsTag(rawIn any) *ActivityStreamsTag {
|
||||||
|
return nil
|
||||||
|
}
|
157
parser.go
157
parser.go
|
@ -1,157 +0,0 @@
|
||||||
package goap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"slices"
|
|
||||||
|
|
||||||
"github.com/piprate/json-gold/ld"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Internal so that others don't mess with this and potentially accidentally overwrite it, breaking everything
|
|
||||||
var allInternalParsersExceptBase []UnmarshalFunc = []UnmarshalFunc{
|
|
||||||
ParseUDIdData,
|
|
||||||
ParseUDTypeData,
|
|
||||||
ParseASActorData,
|
|
||||||
ParseASAlsoKnownAsData,
|
|
||||||
ParseASAttachmentsData,
|
|
||||||
ParseASAttributedToData,
|
|
||||||
ParseASCCData,
|
|
||||||
ParseASContentData,
|
|
||||||
ParseASEndpointsData,
|
|
||||||
ParseASFollowersData,
|
|
||||||
ParseASFollowingData,
|
|
||||||
ParseASHrefData,
|
|
||||||
ParseASIconData,
|
|
||||||
ParseASImageData,
|
|
||||||
ParseASMediaTypeData,
|
|
||||||
ParseASNameData,
|
|
||||||
ParseASOutboxData,
|
|
||||||
ParseASObjectData,
|
|
||||||
ParseASPreferredNameData,
|
|
||||||
ParseASPublishedData,
|
|
||||||
ParseASRestrictedData,
|
|
||||||
ParseASRepliesData,
|
|
||||||
ParseASSharedInboxData,
|
|
||||||
ParseASSummaryData,
|
|
||||||
ParseASSensitiveData,
|
|
||||||
ParseASTagData,
|
|
||||||
ParseASToData,
|
|
||||||
ParseASUrlData,
|
|
||||||
ParseASUpdatedData,
|
|
||||||
ParseASFirstData,
|
|
||||||
ParseASNextData,
|
|
||||||
ParseASItemsData,
|
|
||||||
ParseASPartOfData,
|
|
||||||
ParseASInReplyToData,
|
|
||||||
ParseASQuoteUrlData,
|
|
||||||
|
|
||||||
ParseOstatusAtomUriData,
|
|
||||||
ParseOstatusConversationData,
|
|
||||||
ParseOstatusInReplyToAtomUriData,
|
|
||||||
|
|
||||||
ParseW3InboxData,
|
|
||||||
|
|
||||||
ParseW3VcardAddressData,
|
|
||||||
ParseW3VcardBirthdayData,
|
|
||||||
|
|
||||||
ParseW3SecurityOwnerData,
|
|
||||||
ParseW3SecurityPublicKeyPemData,
|
|
||||||
ParseW3SecurityPublicKeyData,
|
|
||||||
|
|
||||||
ParseMastoDevicesData,
|
|
||||||
ParseMastoDiscoverableData,
|
|
||||||
ParseMastoFeaturedData,
|
|
||||||
ParseMastoDiscoverableData,
|
|
||||||
ParseMastoIndexableData,
|
|
||||||
ParseMastoMemorialData,
|
|
||||||
|
|
||||||
ParseSchemaValueData,
|
|
||||||
|
|
||||||
ParseMKIsCatData,
|
|
||||||
ParseMKSummaryData,
|
|
||||||
ParseMKQuoteData,
|
|
||||||
|
|
||||||
ParseFFSpeakAsCatData,
|
|
||||||
|
|
||||||
ParseFedibirdQuoteUriData,
|
|
||||||
}
|
|
||||||
|
|
||||||
func chainParse(
|
|
||||||
raw map[string]any,
|
|
||||||
start BaseApChain,
|
|
||||||
parsers ...UnmarshalFunc,
|
|
||||||
) (BaseApChain, []error) {
|
|
||||||
var current BaseApChain = start
|
|
||||||
errors := []error{}
|
|
||||||
|
|
||||||
for _, p := range parsers {
|
|
||||||
next, err := p(raw, current)
|
|
||||||
current = next
|
|
||||||
errors = append(errors, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return current, errors
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal raw data into an Activitypub object in the form of a recursive BaseApChain
|
|
||||||
// Each element corresponds to one attribute the object contained
|
|
||||||
// If ldOptions or processor are nil, the following defaults are used:
|
|
||||||
// - ldOptions: `ld.NewJsonLdOptions("")`
|
|
||||||
// - processor: `ld.NewJsonLdProcessor()`
|
|
||||||
// Returns an ActivityPub object and a list of errors produced by the parser functions
|
|
||||||
// Not each function has to produce an error. Those will have nil as error value
|
|
||||||
// Those errors (or nils) come in the order of the parser functions
|
|
||||||
// which can be inspected in the `allInternalParsersExceptBase` internal variable
|
|
||||||
func Unmarshal(
|
|
||||||
raw []byte,
|
|
||||||
ldOptions *ld.JsonLdOptions,
|
|
||||||
processor *ld.JsonLdProcessor,
|
|
||||||
extraParsers ...UnmarshalFunc,
|
|
||||||
) (BaseApChain, []error) {
|
|
||||||
if ldOptions == nil {
|
|
||||||
ldOptions = ld.NewJsonLdOptions("")
|
|
||||||
}
|
|
||||||
if processor == nil {
|
|
||||||
processor = ld.NewJsonLdProcessor()
|
|
||||||
}
|
|
||||||
rawData, err := processor.Expand(raw, ldOptions)
|
|
||||||
if err != nil {
|
|
||||||
return nil, []error{err}
|
|
||||||
}
|
|
||||||
data, ok := rawData[0].(map[string]any)
|
|
||||||
if !ok {
|
|
||||||
return nil, []error{fmt.Errorf("failed to cast expand result into map[string]any")}
|
|
||||||
}
|
|
||||||
return UnmarshalPreprocessed(data, extraParsers...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal a preproccessed object. Preproccessed meaning being first parsed as json and then expanded by json-gold
|
|
||||||
// Otherwise the same as Unmarshal
|
|
||||||
func UnmarshalPreprocessed(
|
|
||||||
raw map[string]any,
|
|
||||||
extraParsers ...UnmarshalFunc,
|
|
||||||
) (BaseApChain, []error) {
|
|
||||||
base := EmptyBaseObject{}
|
|
||||||
allParsers := slices.Concat(allInternalParsersExceptBase, extraParsers)
|
|
||||||
return chainParse(raw, &base, allParsers...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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) {
|
|
||||||
var obj T
|
|
||||||
var ok bool
|
|
||||||
// Try and cast object into wanted type
|
|
||||||
// If cast failed, do inner codeblock
|
|
||||||
// Try and cast again
|
|
||||||
for obj, ok = object.(T); !ok; obj, ok = object.(T) {
|
|
||||||
// Get the next attribute in the chain
|
|
||||||
object, ok = object.GetSelfOrBase()
|
|
||||||
// If this is the final object in the chain, cancel and return false
|
|
||||||
if !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &obj, true
|
|
||||||
}
|
|
4
tags.go
4
tags.go
|
@ -134,7 +134,7 @@ func parseMentionTag(raw map[string]any) (*TagMention, error) {
|
||||||
name := rawName.(*ASNameData)
|
name := rawName.(*ASNameData)
|
||||||
return &TagMention{
|
return &TagMention{
|
||||||
TargetId: href.Id,
|
TargetId: href.Id,
|
||||||
TargetName: name.Value.Value,
|
TargetName: name.Name.Value,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,6 +151,6 @@ func parseHashtagTag(raw map[string]any) (*TagHashtag, error) {
|
||||||
name := rawName.(*ASNameData)
|
name := rawName.(*ASNameData)
|
||||||
return &TagHashtag{
|
return &TagHashtag{
|
||||||
Url: href.Id,
|
Url: href.Id,
|
||||||
Name: name.Value.Value,
|
Name: name.Name.Value,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue