mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-11-28 02:23:33 -06:00
change muchos things
This commit is contained in:
parent
fffff93b75
commit
2786b5f887
70 changed files with 999 additions and 570 deletions
|
|
@ -27,8 +27,10 @@ import (
|
|||
"github.com/go-fed/activity/streams"
|
||||
"github.com/go-fed/activity/streams/vocab"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/messages"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
|
||||
|
|
@ -67,7 +69,7 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA
|
|||
l.Error("ACCEPT: from federator channel wasn't set on context")
|
||||
return nil
|
||||
}
|
||||
fromFederatorChan, ok := fromFederatorChanI.(chan gtsmodel.FromFederator)
|
||||
fromFederatorChan, ok := fromFederatorChanI.(chan messages.FromFederator)
|
||||
if !ok {
|
||||
l.Error("ACCEPT: from federator channel was set on context but couldn't be parsed")
|
||||
return nil
|
||||
|
|
@ -99,9 +101,9 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA
|
|||
return err
|
||||
}
|
||||
|
||||
fromFederatorChan <- gtsmodel.FromFederator{
|
||||
APObjectType: gtsmodel.ActivityStreamsFollow,
|
||||
APActivityType: gtsmodel.ActivityStreamsAccept,
|
||||
fromFederatorChan <- messages.FromFederator{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityAccept,
|
||||
GTSModel: follow,
|
||||
ReceivingAccount: targetAcct,
|
||||
}
|
||||
|
|
@ -116,7 +118,7 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA
|
|||
}
|
||||
switch iter.GetType().GetTypeName() {
|
||||
// we have the whole object so we can figure out what we're accepting
|
||||
case string(gtsmodel.ActivityStreamsFollow):
|
||||
case string(ap.ActivityFollow):
|
||||
// ACCEPT FOLLOW
|
||||
asFollow, ok := iter.GetType().(vocab.ActivityStreamsFollow)
|
||||
if !ok {
|
||||
|
|
@ -136,9 +138,9 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA
|
|||
return err
|
||||
}
|
||||
|
||||
fromFederatorChan <- gtsmodel.FromFederator{
|
||||
APObjectType: gtsmodel.ActivityStreamsFollow,
|
||||
APActivityType: gtsmodel.ActivityStreamsAccept,
|
||||
fromFederatorChan <- messages.FromFederator{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityAccept,
|
||||
GTSModel: follow,
|
||||
ReceivingAccount: targetAcct,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ import (
|
|||
"github.com/go-fed/activity/streams"
|
||||
"github.com/go-fed/activity/streams/vocab"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/messages"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
|
||||
|
|
@ -65,7 +67,7 @@ func (f *federatingDB) Announce(ctx context.Context, announce vocab.ActivityStre
|
|||
l.Error("ANNOUNCE: from federator channel wasn't set on context")
|
||||
return nil
|
||||
}
|
||||
fromFederatorChan, ok := fromFederatorChanI.(chan gtsmodel.FromFederator)
|
||||
fromFederatorChan, ok := fromFederatorChanI.(chan messages.FromFederator)
|
||||
if !ok {
|
||||
l.Error("ANNOUNCE: from federator channel was set on context but couldn't be parsed")
|
||||
return nil
|
||||
|
|
@ -82,9 +84,9 @@ func (f *federatingDB) Announce(ctx context.Context, announce vocab.ActivityStre
|
|||
}
|
||||
|
||||
// it's a new announce so pass it back to the processor async for dereferencing etc
|
||||
fromFederatorChan <- gtsmodel.FromFederator{
|
||||
APObjectType: gtsmodel.ActivityStreamsAnnounce,
|
||||
APActivityType: gtsmodel.ActivityStreamsCreate,
|
||||
fromFederatorChan <- messages.FromFederator{
|
||||
APObjectType: ap.ActivityAnnounce,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: boost,
|
||||
ReceivingAccount: targetAcct,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,11 @@ import (
|
|||
"github.com/go-fed/activity/streams"
|
||||
"github.com/go-fed/activity/streams/vocab"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/id"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/messages"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
|
||||
|
|
@ -81,14 +83,14 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error {
|
|||
l.Error("CREATE: from federator channel wasn't set on context")
|
||||
return nil
|
||||
}
|
||||
fromFederatorChan, ok := fromFederatorChanI.(chan gtsmodel.FromFederator)
|
||||
fromFederatorChan, ok := fromFederatorChanI.(chan messages.FromFederator)
|
||||
if !ok {
|
||||
l.Error("CREATE: from federator channel was set on context but couldn't be parsed")
|
||||
return nil
|
||||
}
|
||||
|
||||
switch asType.GetTypeName() {
|
||||
case gtsmodel.ActivityStreamsCreate:
|
||||
case ap.ActivityCreate:
|
||||
// CREATE SOMETHING
|
||||
create, ok := asType.(vocab.ActivityStreamsCreate)
|
||||
if !ok {
|
||||
|
|
@ -97,7 +99,7 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error {
|
|||
object := create.GetActivityStreamsObject()
|
||||
for objectIter := object.Begin(); objectIter != object.End(); objectIter = objectIter.Next() {
|
||||
switch objectIter.GetType().GetTypeName() {
|
||||
case gtsmodel.ActivityStreamsNote:
|
||||
case ap.ObjectNote:
|
||||
// CREATE A NOTE
|
||||
note := objectIter.GetActivityStreamsNote()
|
||||
status, err := f.typeConverter.ASStatusToStatus(ctx, note)
|
||||
|
|
@ -122,15 +124,15 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error {
|
|||
return fmt.Errorf("CREATE: database error inserting status: %s", err)
|
||||
}
|
||||
|
||||
fromFederatorChan <- gtsmodel.FromFederator{
|
||||
APObjectType: gtsmodel.ActivityStreamsNote,
|
||||
APActivityType: gtsmodel.ActivityStreamsCreate,
|
||||
fromFederatorChan <- messages.FromFederator{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: status,
|
||||
ReceivingAccount: targetAcct,
|
||||
}
|
||||
}
|
||||
}
|
||||
case gtsmodel.ActivityStreamsFollow:
|
||||
case ap.ActivityFollow:
|
||||
// FOLLOW SOMETHING
|
||||
follow, ok := asType.(vocab.ActivityStreamsFollow)
|
||||
if !ok {
|
||||
|
|
@ -152,13 +154,13 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error {
|
|||
return fmt.Errorf("CREATE: database error inserting follow request: %s", err)
|
||||
}
|
||||
|
||||
fromFederatorChan <- gtsmodel.FromFederator{
|
||||
APObjectType: gtsmodel.ActivityStreamsFollow,
|
||||
APActivityType: gtsmodel.ActivityStreamsCreate,
|
||||
fromFederatorChan <- messages.FromFederator{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: followRequest,
|
||||
ReceivingAccount: targetAcct,
|
||||
}
|
||||
case gtsmodel.ActivityStreamsLike:
|
||||
case ap.ActivityLike:
|
||||
// LIKE SOMETHING
|
||||
like, ok := asType.(vocab.ActivityStreamsLike)
|
||||
if !ok {
|
||||
|
|
@ -180,13 +182,13 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error {
|
|||
return fmt.Errorf("CREATE: database error inserting fave: %s", err)
|
||||
}
|
||||
|
||||
fromFederatorChan <- gtsmodel.FromFederator{
|
||||
APObjectType: gtsmodel.ActivityStreamsLike,
|
||||
APActivityType: gtsmodel.ActivityStreamsCreate,
|
||||
fromFederatorChan <- messages.FromFederator{
|
||||
APObjectType: ap.ActivityLike,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: fave,
|
||||
ReceivingAccount: targetAcct,
|
||||
}
|
||||
case gtsmodel.ActivityStreamsBlock:
|
||||
case ap.ActivityBlock:
|
||||
// BLOCK SOMETHING
|
||||
blockable, ok := asType.(vocab.ActivityStreamsBlock)
|
||||
if !ok {
|
||||
|
|
@ -208,9 +210,9 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error {
|
|||
return fmt.Errorf("CREATE: database error inserting block: %s", err)
|
||||
}
|
||||
|
||||
fromFederatorChan <- gtsmodel.FromFederator{
|
||||
APObjectType: gtsmodel.ActivityStreamsBlock,
|
||||
APActivityType: gtsmodel.ActivityStreamsCreate,
|
||||
fromFederatorChan <- messages.FromFederator{
|
||||
APObjectType: ap.ActivityBlock,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: block,
|
||||
ReceivingAccount: targetAcct,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@ import (
|
|||
"net/url"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/messages"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
|
||||
|
|
@ -61,7 +63,7 @@ func (f *federatingDB) Delete(ctx context.Context, id *url.URL) error {
|
|||
l.Error("DELETE: from federator channel wasn't set on context")
|
||||
return nil
|
||||
}
|
||||
fromFederatorChan, ok := fromFederatorChanI.(chan gtsmodel.FromFederator)
|
||||
fromFederatorChan, ok := fromFederatorChanI.(chan messages.FromFederator)
|
||||
if !ok {
|
||||
l.Error("DELETE: from federator channel was set on context but couldn't be parsed")
|
||||
return nil
|
||||
|
|
@ -76,9 +78,9 @@ func (f *federatingDB) Delete(ctx context.Context, id *url.URL) error {
|
|||
if err := f.db.DeleteByID(ctx, s.ID, >smodel.Status{}); err != nil {
|
||||
return fmt.Errorf("DELETE: err deleting status: %s", err)
|
||||
}
|
||||
fromFederatorChan <- gtsmodel.FromFederator{
|
||||
APObjectType: gtsmodel.ActivityStreamsNote,
|
||||
APActivityType: gtsmodel.ActivityStreamsDelete,
|
||||
fromFederatorChan <- messages.FromFederator{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityDelete,
|
||||
GTSModel: s,
|
||||
ReceivingAccount: targetAcct,
|
||||
}
|
||||
|
|
@ -91,9 +93,9 @@ func (f *federatingDB) Delete(ctx context.Context, id *url.URL) error {
|
|||
if err := f.db.DeleteByID(ctx, a.ID, >smodel.Account{}); err != nil {
|
||||
return fmt.Errorf("DELETE: err deleting account: %s", err)
|
||||
}
|
||||
fromFederatorChan <- gtsmodel.FromFederator{
|
||||
APObjectType: gtsmodel.ActivityStreamsProfile,
|
||||
APActivityType: gtsmodel.ActivityStreamsDelete,
|
||||
fromFederatorChan <- messages.FromFederator{
|
||||
APObjectType: ap.ObjectProfile,
|
||||
APActivityType: ap.ActivityDelete,
|
||||
GTSModel: a,
|
||||
ReceivingAccount: targetAcct,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/go-fed/activity/streams"
|
||||
"github.com/go-fed/activity/streams/vocab"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
|
|
@ -72,7 +73,7 @@ func (f *federatingDB) Undo(ctx context.Context, undo vocab.ActivityStreamsUndo)
|
|||
continue
|
||||
}
|
||||
switch iter.GetType().GetTypeName() {
|
||||
case string(gtsmodel.ActivityStreamsFollow):
|
||||
case string(ap.ActivityFollow):
|
||||
// UNDO FOLLOW
|
||||
ASFollow, ok := iter.GetType().(vocab.ActivityStreamsFollow)
|
||||
if !ok {
|
||||
|
|
@ -101,11 +102,11 @@ func (f *federatingDB) Undo(ctx context.Context, undo vocab.ActivityStreamsUndo)
|
|||
}
|
||||
l.Debug("follow undone")
|
||||
return nil
|
||||
case string(gtsmodel.ActivityStreamsLike):
|
||||
case string(ap.ActivityLike):
|
||||
// UNDO LIKE
|
||||
case string(gtsmodel.ActivityStreamsAnnounce):
|
||||
case string(ap.ActivityAnnounce):
|
||||
// UNDO BOOST/REBLOG/ANNOUNCE
|
||||
case string(gtsmodel.ActivityStreamsBlock):
|
||||
case string(ap.ActivityBlock):
|
||||
// UNDO BLOCK
|
||||
ASBlock, ok := iter.GetType().(vocab.ActivityStreamsBlock)
|
||||
if !ok {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import (
|
|||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/messages"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
|
||||
|
|
@ -84,50 +85,50 @@ func (f *federatingDB) Update(ctx context.Context, asType vocab.Type) error {
|
|||
if fromFederatorChanI == nil {
|
||||
l.Error("UPDATE: from federator channel wasn't set on context")
|
||||
}
|
||||
fromFederatorChan, ok := fromFederatorChanI.(chan gtsmodel.FromFederator)
|
||||
fromFederatorChan, ok := fromFederatorChanI.(chan messages.FromFederator)
|
||||
if !ok {
|
||||
l.Error("UPDATE: from federator channel was set on context but couldn't be parsed")
|
||||
}
|
||||
|
||||
typeName := asType.GetTypeName()
|
||||
if typeName == gtsmodel.ActivityStreamsApplication ||
|
||||
typeName == gtsmodel.ActivityStreamsGroup ||
|
||||
typeName == gtsmodel.ActivityStreamsOrganization ||
|
||||
typeName == gtsmodel.ActivityStreamsPerson ||
|
||||
typeName == gtsmodel.ActivityStreamsService {
|
||||
if typeName == ap.ActorApplication ||
|
||||
typeName == ap.ActorGroup ||
|
||||
typeName == ap.ActorOrganization ||
|
||||
typeName == ap.ActorPerson ||
|
||||
typeName == ap.ActorService {
|
||||
// it's an UPDATE to some kind of account
|
||||
var accountable ap.Accountable
|
||||
|
||||
switch asType.GetTypeName() {
|
||||
case gtsmodel.ActivityStreamsApplication:
|
||||
case ap.ActorApplication:
|
||||
l.Debug("got update for APPLICATION")
|
||||
i, ok := asType.(vocab.ActivityStreamsApplication)
|
||||
if !ok {
|
||||
return errors.New("UPDATE: could not convert type to application")
|
||||
}
|
||||
accountable = i
|
||||
case gtsmodel.ActivityStreamsGroup:
|
||||
case ap.ActorGroup:
|
||||
l.Debug("got update for GROUP")
|
||||
i, ok := asType.(vocab.ActivityStreamsGroup)
|
||||
if !ok {
|
||||
return errors.New("UPDATE: could not convert type to group")
|
||||
}
|
||||
accountable = i
|
||||
case gtsmodel.ActivityStreamsOrganization:
|
||||
case ap.ActorOrganization:
|
||||
l.Debug("got update for ORGANIZATION")
|
||||
i, ok := asType.(vocab.ActivityStreamsOrganization)
|
||||
if !ok {
|
||||
return errors.New("UPDATE: could not convert type to organization")
|
||||
}
|
||||
accountable = i
|
||||
case gtsmodel.ActivityStreamsPerson:
|
||||
case ap.ActorPerson:
|
||||
l.Debug("got update for PERSON")
|
||||
i, ok := asType.(vocab.ActivityStreamsPerson)
|
||||
if !ok {
|
||||
return errors.New("UPDATE: could not convert type to person")
|
||||
}
|
||||
accountable = i
|
||||
case gtsmodel.ActivityStreamsService:
|
||||
case ap.ActorService:
|
||||
l.Debug("got update for SERVICE")
|
||||
i, ok := asType.(vocab.ActivityStreamsService)
|
||||
if !ok {
|
||||
|
|
@ -157,9 +158,9 @@ func (f *federatingDB) Update(ctx context.Context, asType vocab.Type) error {
|
|||
return fmt.Errorf("UPDATE: database error inserting updated account: %s", err)
|
||||
}
|
||||
|
||||
fromFederatorChan <- gtsmodel.FromFederator{
|
||||
APObjectType: gtsmodel.ActivityStreamsProfile,
|
||||
APActivityType: gtsmodel.ActivityStreamsUpdate,
|
||||
fromFederatorChan <- messages.FromFederator{
|
||||
APObjectType: ap.ObjectProfile,
|
||||
APActivityType: ap.ActivityUpdate,
|
||||
GTSModel: updatedAcct,
|
||||
ReceivingAccount: targetAcct,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import (
|
|||
"github.com/go-fed/activity/streams"
|
||||
"github.com/go-fed/activity/streams/vocab"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/id"
|
||||
|
|
@ -78,7 +79,7 @@ func (f *federatingDB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL,
|
|||
l.Debugf("received NEWID request for asType %s", string(b))
|
||||
|
||||
switch t.GetTypeName() {
|
||||
case gtsmodel.ActivityStreamsFollow:
|
||||
case ap.ActivityFollow:
|
||||
// FOLLOW
|
||||
// ID might already be set on a follow we've created, so check it here and return it if it is
|
||||
follow, ok := t.(vocab.ActivityStreamsFollow)
|
||||
|
|
@ -108,7 +109,7 @@ func (f *federatingDB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL,
|
|||
}
|
||||
}
|
||||
}
|
||||
case gtsmodel.ActivityStreamsNote:
|
||||
case ap.ObjectNote:
|
||||
// NOTE aka STATUS
|
||||
// ID might already be set on a note we've created, so check it here and return it if it is
|
||||
note, ok := t.(vocab.ActivityStreamsNote)
|
||||
|
|
@ -121,7 +122,7 @@ func (f *federatingDB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL,
|
|||
return idProp.GetIRI(), nil
|
||||
}
|
||||
}
|
||||
case gtsmodel.ActivityStreamsLike:
|
||||
case ap.ActivityLike:
|
||||
// LIKE aka FAVE
|
||||
// ID might already be set on a fave we've created, so check it here and return it if it is
|
||||
fave, ok := t.(vocab.ActivityStreamsLike)
|
||||
|
|
@ -134,7 +135,7 @@ func (f *federatingDB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL,
|
|||
return idProp.GetIRI(), nil
|
||||
}
|
||||
}
|
||||
case gtsmodel.ActivityStreamsAnnounce:
|
||||
case ap.ActivityAnnounce:
|
||||
// ANNOUNCE aka BOOST
|
||||
// ID might already be set on an announce we've created, so check it here and return it if it is
|
||||
announce, ok := t.(vocab.ActivityStreamsAnnounce)
|
||||
|
|
@ -147,7 +148,7 @@ func (f *federatingDB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL,
|
|||
return idProp.GetIRI(), nil
|
||||
}
|
||||
}
|
||||
case gtsmodel.ActivityStreamsUpdate:
|
||||
case ap.ActivityUpdate:
|
||||
// UPDATE
|
||||
// ID might already be set on an update we've created, so check it here and return it if it is
|
||||
update, ok := t.(vocab.ActivityStreamsUpdate)
|
||||
|
|
@ -160,7 +161,7 @@ func (f *federatingDB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL,
|
|||
return idProp.GetIRI(), nil
|
||||
}
|
||||
}
|
||||
case gtsmodel.ActivityStreamsBlock:
|
||||
case ap.ActivityBlock:
|
||||
// BLOCK
|
||||
// ID might already be set on a block we've created, so check it here and return it if it is
|
||||
block, ok := t.(vocab.ActivityStreamsBlock)
|
||||
|
|
@ -173,7 +174,7 @@ func (f *federatingDB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL,
|
|||
return idProp.GetIRI(), nil
|
||||
}
|
||||
}
|
||||
case gtsmodel.ActivityStreamsUndo:
|
||||
case ap.ActivityUndo:
|
||||
// UNDO
|
||||
// ID might already be set on an undo we've created, so check it here and return it if it is
|
||||
undo, ok := t.(vocab.ActivityStreamsUndo)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue