Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
83b604a5ab
|
@ -1,6 +1,4 @@
|
||||||
image: archlinux
|
image: archlinux
|
||||||
secrets:
|
|
||||||
- 72c9ab0b-ed5f-4291-bab7-30b361be94a6
|
|
||||||
packages:
|
packages:
|
||||||
- go
|
- go
|
||||||
sources:
|
sources:
|
||||||
|
@ -15,10 +13,3 @@ tasks:
|
||||||
- coverage: |
|
- coverage: |
|
||||||
set -a +x
|
set -a +x
|
||||||
cd activitypub && make coverage
|
cd activitypub && make coverage
|
||||||
GIT_SHA=$(git rev-parse --verify HEAD)
|
|
||||||
GIT_BRANCH=$(git name-rev --name-only HEAD)
|
|
||||||
source ~/.code-cov.sh
|
|
||||||
curl -X POST \
|
|
||||||
--data-binary @activitypub.coverprofile \
|
|
||||||
-H 'Accept: application/json' \
|
|
||||||
"https://codecov.io/upload/v2?commit=${GIT_SHA}&token=${PUB_TOKEN}&branch=${GIT_BRANCH}&service=custom" || true
|
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -4,7 +4,7 @@ go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078
|
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078
|
||||||
github.com/go-ap/errors v0.0.0-20220917143055-4283ea5dae18
|
github.com/go-ap/errors v0.0.0-20221115052505-8aaa26f930b4
|
||||||
github.com/go-ap/jsonld v0.0.0-20220917142617-76bf51585778
|
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
|
||||||
github.com/valyala/fastjson v1.6.3
|
github.com/valyala/fastjson v1.6.3
|
||||||
)
|
)
|
||||||
|
|
60
iri.go
60
iri.go
|
@ -6,7 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/valyala/fastjson"
|
"github.com/valyala/fastjson"
|
||||||
|
@ -134,7 +134,8 @@ func (i *IRIs) GobDecode(data []byte) error {
|
||||||
|
|
||||||
// AddPath concatenates el elements as a path to i
|
// AddPath concatenates el elements as a path to i
|
||||||
func (i IRI) AddPath(el ...string) IRI {
|
func (i IRI) AddPath(el ...string) IRI {
|
||||||
return IRI(fmt.Sprintf("%s/%s", i, path.Join(el...)))
|
iri := strings.TrimRight(i.String(), "/")
|
||||||
|
return IRI(iri + filepath.Clean(filepath.Join("/", filepath.Join(el...))))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetID
|
// GetID
|
||||||
|
@ -215,6 +216,55 @@ func (i *IRIs) UnmarshalJSON(data []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetID returns the ID corresponding to ItemCollection
|
||||||
|
func (i IRIs) GetID() ID {
|
||||||
|
return EmptyID
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLink returns the empty IRI
|
||||||
|
func (i IRIs) GetLink() IRI {
|
||||||
|
return EmptyIRI
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetType returns the ItemCollection's type
|
||||||
|
func (i IRIs) GetType() ActivityVocabularyType {
|
||||||
|
return CollectionOfItems
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsLink returns false for an ItemCollection object
|
||||||
|
func (i IRIs) IsLink() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsObject returns true for a ItemCollection object
|
||||||
|
func (i IRIs) IsObject() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCollection returns true for IRI slices
|
||||||
|
func (i IRIs) IsCollection() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append facilitates adding elements to IRI slices
|
||||||
|
// and ensures IRIs implements the Collection interface
|
||||||
|
func (i *IRIs) Append(r IRI) error {
|
||||||
|
*i = append(*i, r)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IRIs) Collection() ItemCollection {
|
||||||
|
res := make(ItemCollection, len(*i))
|
||||||
|
for k, iri := range *i {
|
||||||
|
res[k] = iri
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IRIs) Count() uint {
|
||||||
|
return uint(len(*i))
|
||||||
|
}
|
||||||
|
|
||||||
// Contains verifies if IRIs array contains the received one
|
// Contains verifies if IRIs array contains the received one
|
||||||
func (i IRIs) Contains(r IRI) bool {
|
func (i IRIs) Contains(r IRI) bool {
|
||||||
if len(i) == 0 {
|
if len(i) == 0 {
|
||||||
|
@ -250,7 +300,7 @@ func (i IRI) Equals(with IRI, checkScheme bool) bool {
|
||||||
if strings.ToLower(u.Host) != strings.ToLower(uw.Host) {
|
if strings.ToLower(u.Host) != strings.ToLower(uw.Host) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if path.Clean(u.Path) != path.Clean(uw.Path) {
|
if filepath.Clean(u.Path) != filepath.Clean(uw.Path) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
uq := u.Query()
|
uq := u.Query()
|
||||||
|
@ -311,11 +361,11 @@ func (i IRI) Contains(what IRI, checkScheme bool) bool {
|
||||||
}
|
}
|
||||||
p := u.Path
|
p := u.Path
|
||||||
if p != "" {
|
if p != "" {
|
||||||
p = path.Clean(p)
|
p = filepath.Clean(p)
|
||||||
}
|
}
|
||||||
pw := uw.Path
|
pw := uw.Path
|
||||||
if pw != "" {
|
if pw != "" {
|
||||||
pw = path.Clean(pw)
|
pw = filepath.Clean(pw)
|
||||||
}
|
}
|
||||||
return strings.Contains(p, pw)
|
return strings.Contains(p, pw)
|
||||||
}
|
}
|
||||||
|
|
2
item.go
2
item.go
|
@ -146,7 +146,7 @@ func IsNil(it Item) bool {
|
||||||
// NOTE(marius): we're not dealing with a type that we know about, so we use slow reflection
|
// NOTE(marius): we're not dealing with a type that we know about, so we use slow reflection
|
||||||
// as we still care about the result
|
// as we still care about the result
|
||||||
v := reflect.ValueOf(it)
|
v := reflect.ValueOf(it)
|
||||||
isNil = v.Kind() != reflect.Pointer || v.IsNil()
|
isNil = v.Kind() == reflect.Pointer && v.IsNil()
|
||||||
}
|
}
|
||||||
return isNil
|
return isNil
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,9 @@ import (
|
||||||
// It is used for LangRefValue objects without an explicit language key.
|
// It is used for LangRefValue objects without an explicit language key.
|
||||||
const NilLangRef LangRef = "-"
|
const NilLangRef LangRef = "-"
|
||||||
|
|
||||||
|
// DefaultLang represents the default language reference used when using the convenience content generation.
|
||||||
|
var DefaultLang = NilLangRef
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// LangRef is the type for a language reference code, should be an ISO639-1 language specifier.
|
// LangRef is the type for a language reference code, should be an ISO639-1 language specifier.
|
||||||
LangRef string
|
LangRef string
|
||||||
|
@ -29,8 +32,16 @@ type (
|
||||||
NaturalLanguageValues []LangRefValue
|
NaturalLanguageValues []LangRefValue
|
||||||
)
|
)
|
||||||
|
|
||||||
func NaturalLanguageValuesNew() NaturalLanguageValues {
|
func NaturalLanguageValuesNew(values ...LangRefValue) NaturalLanguageValues {
|
||||||
return make(NaturalLanguageValues, 0)
|
n := make(NaturalLanguageValues, len(values))
|
||||||
|
for i, val := range values {
|
||||||
|
n[i] = val
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultNaturalLanguageValue(content string) NaturalLanguageValues {
|
||||||
|
return NaturalLanguageValuesNew(DefaultLangRef(content))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n NaturalLanguageValues) String() string {
|
func (n NaturalLanguageValues) String() string {
|
||||||
|
@ -74,6 +85,10 @@ func (n *NaturalLanguageValues) Set(ref LangRef, v Content) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *NaturalLanguageValues) Add(ref LangRefValue) {
|
||||||
|
*n = append(*n, ref)
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalJSON encodes the receiver object to a JSON document.
|
// MarshalJSON encodes the receiver object to a JSON document.
|
||||||
func (n NaturalLanguageValues) MarshalJSON() ([]byte, error) {
|
func (n NaturalLanguageValues) MarshalJSON() ([]byte, error) {
|
||||||
l := len(n)
|
l := len(n)
|
||||||
|
@ -183,6 +198,14 @@ func (l LangRefValue) String() string {
|
||||||
return fmt.Sprintf("%s[%s]", l.Value, l.Ref)
|
return fmt.Sprintf("%s[%s]", l.Value, l.Ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DefaultLangRef(value string) LangRefValue {
|
||||||
|
return LangRefValue{Ref: DefaultLang, Value: Content(value)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func LangRefValueNew(lang LangRef, value string) LangRefValue {
|
||||||
|
return LangRefValue{Ref: lang, Value: Content(value)}
|
||||||
|
}
|
||||||
|
|
||||||
func (l LangRefValue) Format(s fmt.State, verb rune) {
|
func (l LangRefValue) Format(s fmt.State, verb rune) {
|
||||||
switch verb {
|
switch verb {
|
||||||
case 's', 'q':
|
case 's', 'q':
|
||||||
|
|
98
typer.go
98
typer.go
|
@ -2,7 +2,7 @@ package activitypub
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-ap/errors"
|
"github.com/go-ap/errors"
|
||||||
|
@ -71,7 +71,7 @@ func (t CollectionPaths) Contains(typ CollectionPath) bool {
|
||||||
// Split splits the IRI in an actor IRI and its CollectionPath
|
// Split splits the IRI in an actor IRI and its CollectionPath
|
||||||
// if the CollectionPath is found in the elements in the t CollectionPaths slice
|
// if the CollectionPath is found in the elements in the t CollectionPaths slice
|
||||||
func (t CollectionPaths) Split(i IRI) (IRI, CollectionPath) {
|
func (t CollectionPaths) Split(i IRI) (IRI, CollectionPath) {
|
||||||
maybeActor, maybeCol := path.Split(i.String())
|
maybeActor, maybeCol := filepath.Split(i.String())
|
||||||
tt := CollectionPath(maybeCol)
|
tt := CollectionPath(maybeCol)
|
||||||
if !t.Contains(tt) {
|
if !t.Contains(tt) {
|
||||||
tt = ""
|
tt = ""
|
||||||
|
@ -104,38 +104,84 @@ func (t CollectionPath) IRI(i Item) IRI {
|
||||||
return IRIf(i.GetLink(), t)
|
return IRIf(i.GetLink(), t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Of gives us the property of the i Item that corresponds to the t CollectionPath type.
|
func (t CollectionPath) ofItemCollection(col ItemCollection) Item {
|
||||||
func (t CollectionPath) Of(i Item) Item {
|
iriCol := make(ItemCollection, len(col))
|
||||||
if IsNil(i) || !i.IsObject() {
|
for i, it := range col {
|
||||||
|
iriCol[i] = t.Of(it)
|
||||||
|
}
|
||||||
|
return iriCol
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t CollectionPath) ofObject(ob *Object) Item {
|
||||||
|
var it Item
|
||||||
|
switch t {
|
||||||
|
case Likes:
|
||||||
|
it = ob.Likes
|
||||||
|
case Shares:
|
||||||
|
it = ob.Shares
|
||||||
|
case Replies:
|
||||||
|
it = ob.Replies
|
||||||
|
}
|
||||||
|
if it == nil {
|
||||||
|
it = t.ofIRI(ob.ID)
|
||||||
|
}
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
func (t CollectionPath) ofActor(a *Actor) Item {
|
||||||
|
var it Item
|
||||||
|
switch t {
|
||||||
|
case Inbox:
|
||||||
|
it = a.Inbox
|
||||||
|
case Outbox:
|
||||||
|
it = a.Outbox
|
||||||
|
case Liked:
|
||||||
|
it = a.Liked
|
||||||
|
case Following:
|
||||||
|
it = a.Following
|
||||||
|
case Followers:
|
||||||
|
it = a.Followers
|
||||||
|
}
|
||||||
|
if it == nil {
|
||||||
|
it = t.ofIRI(a.ID)
|
||||||
|
}
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t CollectionPath) ofIRI(iri IRI) Item {
|
||||||
|
if len(iri) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
return iri.AddPath(string(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t CollectionPath) ofItem(i Item) Item {
|
||||||
var it Item
|
var it Item
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
|
||||||
|
// Of gives us the property of the i Item that corresponds to the t CollectionPath type.
|
||||||
|
func (t CollectionPath) Of(i Item) Item {
|
||||||
|
if IsNil(i) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if IsIRI(i) {
|
||||||
|
return t.ofIRI(i.GetLink())
|
||||||
|
}
|
||||||
|
var it Item
|
||||||
|
if IsItemCollection(i) {
|
||||||
|
OnItemCollection(i, func(col *ItemCollection) error {
|
||||||
|
it = t.ofItemCollection(*col)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
if OfActor.Contains(t) && ActorTypes.Contains(i.GetType()) {
|
if OfActor.Contains(t) && ActorTypes.Contains(i.GetType()) {
|
||||||
OnActor(i, func(a *Actor) error {
|
OnActor(i, func(a *Actor) error {
|
||||||
switch t {
|
it = t.ofActor(a)
|
||||||
case Inbox:
|
|
||||||
it = a.Inbox
|
|
||||||
case Outbox:
|
|
||||||
it = a.Outbox
|
|
||||||
case Liked:
|
|
||||||
it = a.Liked
|
|
||||||
case Following:
|
|
||||||
it = a.Following
|
|
||||||
case Followers:
|
|
||||||
it = a.Followers
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
OnObject(i, func(o *Object) error {
|
OnObject(i, func(o *Object) error {
|
||||||
switch t {
|
it = t.ofObject(o)
|
||||||
case Likes:
|
|
||||||
it = o.Likes
|
|
||||||
case Shares:
|
|
||||||
it = o.Shares
|
|
||||||
case Replies:
|
|
||||||
it = o.Replies
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -144,7 +190,7 @@ func (t CollectionPath) Of(i Item) Item {
|
||||||
|
|
||||||
// OfActor returns the base IRI of received i, if i represents an IRI matching CollectionPath type t
|
// OfActor returns the base IRI of received i, if i represents an IRI matching CollectionPath type t
|
||||||
func (t CollectionPath) OfActor(i IRI) (IRI, error) {
|
func (t CollectionPath) OfActor(i IRI) (IRI, error) {
|
||||||
maybeActor, maybeCol := path.Split(i.String())
|
maybeActor, maybeCol := filepath.Split(i.String())
|
||||||
if strings.ToLower(maybeCol) == strings.ToLower(string(t)) {
|
if strings.ToLower(maybeCol) == strings.ToLower(string(t)) {
|
||||||
maybeActor = strings.TrimRight(maybeActor, "/")
|
maybeActor = strings.TrimRight(maybeActor, "/")
|
||||||
return IRI(maybeActor), nil
|
return IRI(maybeActor), nil
|
||||||
|
|
Reference in a new issue