60 lines
1.9 KiB
Go
60 lines
1.9 KiB
Go
|
package ap
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"net/url"
|
||
|
|
||
|
"github.com/piprate/json-gold/ld"
|
||
|
)
|
||
|
|
||
|
type ApThing map[string]any
|
||
|
|
||
|
type RemoteDocumentLoader struct{}
|
||
|
|
||
|
// 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) {
|
||
|
opts := ld.NewJsonLdOptions("")
|
||
|
processor := ld.NewJsonLdProcessor()
|
||
|
// 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 := processor.Expand(u.String(), opts)
|
||
|
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) {
|
||
|
opts := ld.NewJsonLdOptions("")
|
||
|
processor := ld.NewJsonLdProcessor()
|
||
|
res, err := processor.Compact(content, allContext, opts)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("failed to compact data: %w", err)
|
||
|
}
|
||
|
return json.Marshal(res)
|
||
|
}
|