mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-11-18 16:07:30 -06:00
outbound federation of likes working
This commit is contained in:
parent
5219a7b9e7
commit
79daebe99c
11 changed files with 196 additions and 57 deletions
|
|
@ -270,7 +270,7 @@ type DB interface {
|
||||||
|
|
||||||
// FaveStatus faves the given status, using accountID as the faver.
|
// FaveStatus faves the given status, using accountID as the faver.
|
||||||
// The returned fave will be nil if the status was already faved.
|
// The returned fave will be nil if the status was already faved.
|
||||||
FaveStatus(status *gtsmodel.Status, accountID string) (*gtsmodel.StatusFave, error)
|
// FaveStatus(status *gtsmodel.Status, accountID string) (*gtsmodel.StatusFave, error)
|
||||||
|
|
||||||
// UnfaveStatus unfaves the given status, using accountID as the unfaver (sure, that's a word).
|
// UnfaveStatus unfaves the given status, using accountID as the unfaver (sure, that's a word).
|
||||||
// The returned fave will be nil if the status was already not faved.
|
// The returned fave will be nil if the status was already not faved.
|
||||||
|
|
|
||||||
|
|
@ -1037,32 +1037,32 @@ func (ps *postgresService) StatusBookmarkedBy(status *gtsmodel.Status, accountID
|
||||||
return ps.conn.Model(>smodel.StatusBookmark{}).Where("status_id = ?", status.ID).Where("account_id = ?", accountID).Exists()
|
return ps.conn.Model(>smodel.StatusBookmark{}).Where("status_id = ?", status.ID).Where("account_id = ?", accountID).Exists()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ps *postgresService) FaveStatus(status *gtsmodel.Status, accountID string) (*gtsmodel.StatusFave, error) {
|
// func (ps *postgresService) FaveStatus(status *gtsmodel.Status, accountID string) (*gtsmodel.StatusFave, error) {
|
||||||
// first check if a fave already exists, we can just return if so
|
// // first check if a fave already exists, we can just return if so
|
||||||
existingFave := >smodel.StatusFave{}
|
// existingFave := >smodel.StatusFave{}
|
||||||
err := ps.conn.Model(existingFave).Where("status_id = ?", status.ID).Where("account_id = ?", accountID).Select()
|
// err := ps.conn.Model(existingFave).Where("status_id = ?", status.ID).Where("account_id = ?", accountID).Select()
|
||||||
if err == nil {
|
// if err == nil {
|
||||||
// fave already exists so just return nothing at all
|
// // fave already exists so just return nothing at all
|
||||||
return nil, nil
|
// return nil, nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
// an error occurred so it might exist or not, we don't know
|
// // an error occurred so it might exist or not, we don't know
|
||||||
if err != pg.ErrNoRows {
|
// if err != pg.ErrNoRows {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
|
|
||||||
// it doesn't exist so create it
|
// // it doesn't exist so create it
|
||||||
newFave := >smodel.StatusFave{
|
// newFave := >smodel.StatusFave{
|
||||||
AccountID: accountID,
|
// AccountID: accountID,
|
||||||
TargetAccountID: status.AccountID,
|
// TargetAccountID: status.AccountID,
|
||||||
StatusID: status.ID,
|
// StatusID: status.ID,
|
||||||
}
|
// }
|
||||||
if _, err = ps.conn.Model(newFave).Insert(); err != nil {
|
// if _, err = ps.conn.Model(newFave).Insert(); err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
|
|
||||||
return newFave, nil
|
// return newFave, nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (ps *postgresService) UnfaveStatus(status *gtsmodel.Status, accountID string) (*gtsmodel.StatusFave, error) {
|
func (ps *postgresService) UnfaveStatus(status *gtsmodel.Status, accountID string) (*gtsmodel.StatusFave, error) {
|
||||||
// if a fave doesn't exist, we don't need to do anything
|
// if a fave doesn't exist, we don't need to do anything
|
||||||
|
|
|
||||||
|
|
@ -777,7 +777,7 @@ func (f *federatingDB) NewID(c context.Context, t vocab.Type) (id *url.URL, err
|
||||||
if iter.IsIRI() {
|
if iter.IsIRI() {
|
||||||
actorAccount := >smodel.Account{}
|
actorAccount := >smodel.Account{}
|
||||||
if err := f.db.GetWhere([]db.Where{{Key: "uri", Value: iter.GetIRI().String()}}, actorAccount); err == nil { // if there's an error here, just use the fallback behavior -- we don't need to return an error here
|
if err := f.db.GetWhere([]db.Where{{Key: "uri", Value: iter.GetIRI().String()}}, actorAccount); err == nil { // if there's an error here, just use the fallback behavior -- we don't need to return an error here
|
||||||
return url.Parse(util.GenerateURIForFollow(actorAccount.Username, f.config.Protocol, f.config.Host))
|
return url.Parse(util.GenerateURIForFollow(actorAccount.Username, f.config.Protocol, f.config.Host, uuid.NewString()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -787,7 +787,7 @@ func (f *federatingDB) NewID(c context.Context, t vocab.Type) (id *url.URL, err
|
||||||
// ID might already be set on a note we've created, so check it here and return it if it is
|
// 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)
|
note, ok := t.(vocab.ActivityStreamsNote)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("newid: follow couldn't be parsed into vocab.ActivityStreamsNote")
|
return nil, errors.New("newid: note couldn't be parsed into vocab.ActivityStreamsNote")
|
||||||
}
|
}
|
||||||
idProp := note.GetJSONLDId()
|
idProp := note.GetJSONLDId()
|
||||||
if idProp != nil {
|
if idProp != nil {
|
||||||
|
|
@ -795,6 +795,19 @@ func (f *federatingDB) NewID(c context.Context, t vocab.Type) (id *url.URL, err
|
||||||
return idProp.GetIRI(), nil
|
return idProp.GetIRI(), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case gtsmodel.ActivityStreamsLike:
|
||||||
|
// 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)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("newid: fave couldn't be parsed into vocab.ActivityStreamsLike")
|
||||||
|
}
|
||||||
|
idProp := fave.GetJSONLDId()
|
||||||
|
if idProp != nil {
|
||||||
|
if idProp.IsIRI() {
|
||||||
|
return idProp.GetIRI(), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fallback default behavior: just return a random UUID after our protocol and host
|
// fallback default behavior: just return a random UUID after our protocol and host
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,10 @@ type StatusFave struct {
|
||||||
// ActivityPub URI of this fave
|
// ActivityPub URI of this fave
|
||||||
URI string `pg:",notnull"`
|
URI string `pg:",notnull"`
|
||||||
|
|
||||||
// FavedStatus is the status being interacted with. It won't be put or retrieved from the db, it's just for conveniently passing a pointer around.
|
// GTSStatus is the status being interacted with. It won't be put or retrieved from the db, it's just for conveniently passing a pointer around.
|
||||||
FavedStatus *Status `pg:"-"`
|
GTSStatus *Status `pg:"-"`
|
||||||
|
// GTSTargetAccount is the account being interacted with. It won't be put or retrieved from the db, it's just for conveniently passing a pointer around.
|
||||||
|
GTSTargetAccount *Account `pg:"-"`
|
||||||
|
// GTSFavingAccount is the account doing the faving. It won't be put or retrieved from the db, it's just for conveniently passing a pointer around.
|
||||||
|
GTSFavingAccount *Account `pg:"-"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
|
|
@ -417,11 +418,15 @@ func (p *processor) AccountFollowCreate(authed *oauth.Auth, form *apimodel.Accou
|
||||||
}
|
}
|
||||||
|
|
||||||
// make the follow request
|
// make the follow request
|
||||||
|
|
||||||
|
newFollowID := uuid.NewString()
|
||||||
|
|
||||||
fr := >smodel.FollowRequest{
|
fr := >smodel.FollowRequest{
|
||||||
|
ID: newFollowID,
|
||||||
AccountID: authed.Account.ID,
|
AccountID: authed.Account.ID,
|
||||||
TargetAccountID: form.TargetAccountID,
|
TargetAccountID: form.TargetAccountID,
|
||||||
ShowReblogs: true,
|
ShowReblogs: true,
|
||||||
URI: util.GenerateURIForFollow(authed.Account.Username, p.config.Protocol, p.config.Host),
|
URI: util.GenerateURIForFollow(authed.Account.Username, p.config.Protocol, p.config.Host, newFollowID),
|
||||||
Notify: false,
|
Notify: false,
|
||||||
}
|
}
|
||||||
if form.Reblogs != nil {
|
if form.Reblogs != nil {
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ func (p *processor) processFromClientAPI(clientMsg gtsmodel.FromClientAPI) error
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.VisibilityAdvanced.Federated {
|
if status.VisibilityAdvanced != nil && status.VisibilityAdvanced.Federated {
|
||||||
return p.federateStatus(status)
|
return p.federateStatus(status)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -63,6 +63,15 @@ func (p *processor) processFromClientAPI(clientMsg gtsmodel.FromClientAPI) error
|
||||||
case gtsmodel.ActivityStreamsLike:
|
case gtsmodel.ActivityStreamsLike:
|
||||||
// CREATE LIKE/FAVE
|
// CREATE LIKE/FAVE
|
||||||
fave, ok := clientMsg.GTSModel.(*gtsmodel.StatusFave)
|
fave, ok := clientMsg.GTSModel.(*gtsmodel.StatusFave)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("fave was not parseable as *gtsmodel.StatusFave")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := p.notifyFave(fave); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.federateFave(fave, clientMsg.OriginAccount, clientMsg.TargetAccount)
|
||||||
}
|
}
|
||||||
case gtsmodel.ActivityStreamsUpdate:
|
case gtsmodel.ActivityStreamsUpdate:
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
@ -225,7 +234,7 @@ func (p *processor) federateFave(fave *gtsmodel.StatusFave, originAccount *gtsmo
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the AS fave
|
// create the AS fave
|
||||||
asFave, err := p.tc.FaveToAS(fave, originAccount, targetAccount)
|
asFave, err := p.tc.FaveToAS(fave)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("federateFave: error converting fave to as format: %s", err)
|
return fmt.Errorf("federateFave: error converting fave to as format: %s", err)
|
||||||
}
|
}
|
||||||
|
|
@ -234,7 +243,6 @@ func (p *processor) federateFave(fave *gtsmodel.StatusFave, originAccount *gtsmo
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("federateFave: error parsing outboxURI %s: %s", originAccount.OutboxURI, err)
|
return fmt.Errorf("federateFave: error parsing outboxURI %s: %s", originAccount.OutboxURI, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = p.federator.FederatingActor().Send(context.Background(), outboxIRI, asFave)
|
_, err = p.federator.FederatingActor().Send(context.Background(), outboxIRI, asFave)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,3 +27,7 @@ func (p *processor) notifyStatus(status *gtsmodel.Status) error {
|
||||||
func (p *processor) notifyFollow(follow *gtsmodel.Follow) error {
|
func (p *processor) notifyFollow(follow *gtsmodel.Follow) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *processor) notifyFave(fave *gtsmodel.StatusFave) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import (
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||||
|
|
@ -168,6 +169,14 @@ func (p *processor) StatusFave(authed *oauth.Auth, targetStatusID string) (*apim
|
||||||
return nil, fmt.Errorf("error fetching related accounts for status %s: %s", targetStatusID, err)
|
return nil, fmt.Errorf("error fetching related accounts for status %s: %s", targetStatusID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var boostOfStatus *gtsmodel.Status
|
||||||
|
if targetStatus.BoostOfID != "" {
|
||||||
|
boostOfStatus = >smodel.Status{}
|
||||||
|
if err := p.db.GetByID(targetStatus.BoostOfID, boostOfStatus); err != nil {
|
||||||
|
return nil, fmt.Errorf("error fetching boosted status %s: %s", targetStatus.BoostOfID, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
l.Trace("going to see if status is visible")
|
l.Trace("going to see if status is visible")
|
||||||
visible, err := p.db.StatusVisible(targetStatus, targetAccount, authed.Account, relevantAccounts) // requestingAccount might well be nil here, but StatusVisible knows how to take care of that
|
visible, err := p.db.StatusVisible(targetStatus, targetAccount, authed.Account, relevantAccounts) // requestingAccount might well be nil here, but StatusVisible knows how to take care of that
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -185,30 +194,44 @@ func (p *processor) StatusFave(authed *oauth.Auth, targetStatusID string) (*apim
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// it's visible! it's faveable! so let's fave the FUCK out of it
|
// first check if the status is already faved, if so we don't need to do anything
|
||||||
gtsFave, err := p.db.FaveStatus(targetStatus, authed.Account.ID)
|
newFave := true
|
||||||
if err != nil {
|
gtsFave := >smodel.Status{}
|
||||||
return nil, fmt.Errorf("error faveing status: %s", err)
|
if err := p.db.GetWhere([]db.Where{{Key: "status_id", Value: targetStatus.ID}, {Key: "account_id", Value: authed.Account.ID}}, gtsFave); err == nil {
|
||||||
}
|
// we already have a fave for this status
|
||||||
gtsFave.FavedStatus = targetStatus // pin a pointer to the target status to the fave for convenience later on
|
newFave = false
|
||||||
|
|
||||||
// send the new fave through the processor channel for federation etc
|
|
||||||
p.fromClientAPI <- gtsmodel.FromClientAPI{
|
|
||||||
APObjectType: gtsmodel.ActivityStreamsLike,
|
|
||||||
APActivityType: gtsmodel.ActivityStreamsCreate,
|
|
||||||
GTSModel: gtsFave,
|
|
||||||
OriginAccount: authed.Account,
|
|
||||||
TargetAccount: targetAccount,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var boostOfStatus *gtsmodel.Status
|
if newFave {
|
||||||
if targetStatus.BoostOfID != "" {
|
thisFaveID := uuid.NewString()
|
||||||
boostOfStatus = >smodel.Status{}
|
|
||||||
if err := p.db.GetByID(targetStatus.BoostOfID, boostOfStatus); err != nil {
|
// we need to create a new fave in the database
|
||||||
return nil, fmt.Errorf("error fetching boosted status %s: %s", targetStatus.BoostOfID, err)
|
gtsFave := >smodel.StatusFave{
|
||||||
|
ID: thisFaveID,
|
||||||
|
AccountID: authed.Account.ID,
|
||||||
|
TargetAccountID: targetAccount.ID,
|
||||||
|
StatusID: targetStatus.ID,
|
||||||
|
URI: util.GenerateURIForLike(authed.Account.Username, p.config.Protocol, p.config.Host, thisFaveID),
|
||||||
|
GTSStatus: targetStatus,
|
||||||
|
GTSTargetAccount: targetAccount,
|
||||||
|
GTSFavingAccount: authed.Account,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := p.db.Put(gtsFave); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// send the new fave through the processor channel for federation etc
|
||||||
|
p.fromClientAPI <- gtsmodel.FromClientAPI{
|
||||||
|
APObjectType: gtsmodel.ActivityStreamsLike,
|
||||||
|
APActivityType: gtsmodel.ActivityStreamsCreate,
|
||||||
|
GTSModel: gtsFave,
|
||||||
|
OriginAccount: authed.Account,
|
||||||
|
TargetAccount: targetAccount,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return the mastodon representation of the target status
|
||||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, targetAccount, authed.Account, relevantAccounts.BoostedAccount, relevantAccounts.ReplyToAccount, boostOfStatus)
|
mastoStatus, err := p.tc.StatusToMasto(targetStatus, targetAccount, authed.Account, relevantAccounts.BoostedAccount, relevantAccounts.ReplyToAccount, boostOfStatus)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err)
|
return nil, fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err)
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,9 @@ type TypeConverter interface {
|
||||||
|
|
||||||
// AttachmentToAS converts a gts model media attachment into an activity streams Attachment, suitable for federation
|
// AttachmentToAS converts a gts model media attachment into an activity streams Attachment, suitable for federation
|
||||||
AttachmentToAS(a *gtsmodel.MediaAttachment) (vocab.ActivityStreamsDocument, error)
|
AttachmentToAS(a *gtsmodel.MediaAttachment) (vocab.ActivityStreamsDocument, error)
|
||||||
|
|
||||||
|
// FaveToAS converts a gts model status fave into an activityStreams LIKE, suitable for federation.
|
||||||
|
FaveToAS(f *gtsmodel.StatusFave) (vocab.ActivityStreamsLike, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type converter struct {
|
type converter struct {
|
||||||
|
|
|
||||||
|
|
@ -559,3 +559,84 @@ func (c *converter) AttachmentToAS(a *gtsmodel.MediaAttachment) (vocab.ActivityS
|
||||||
|
|
||||||
return doc, nil
|
return doc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
We want to end up with something like this:
|
||||||
|
|
||||||
|
{
|
||||||
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
"actor": "https://ondergrond.org/users/dumpsterqueer",
|
||||||
|
"id": "https://ondergrond.org/users/dumpsterqueer#likes/44584",
|
||||||
|
"object": "https://testingtesting123.xyz/users/gotosocial_test_account/statuses/771aea80-a33d-4d6d-8dfd-57d4d2bfcbd4",
|
||||||
|
"type": "Like"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
func (c *converter) FaveToAS(f *gtsmodel.StatusFave) (vocab.ActivityStreamsLike, error) {
|
||||||
|
// check if targetStatus is already pinned to this fave, and fetch it if not
|
||||||
|
if f.GTSStatus == nil {
|
||||||
|
s := >smodel.Status{}
|
||||||
|
if err := c.db.GetByID(f.StatusID, s); err != nil {
|
||||||
|
return nil, fmt.Errorf("FaveToAS: error fetching target status from database: %s", err)
|
||||||
|
}
|
||||||
|
f.GTSStatus = s
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the targetAccount is already pinned to this fave, and fetch it if not
|
||||||
|
if f.GTSTargetAccount == nil {
|
||||||
|
a := >smodel.Account{}
|
||||||
|
if err := c.db.GetByID(f.TargetAccountID, a); err != nil {
|
||||||
|
return nil, fmt.Errorf("FaveToAS: error fetching target account from database: %s", err)
|
||||||
|
}
|
||||||
|
f.GTSTargetAccount = a
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the faving account is already pinned to this fave, and fetch it if not
|
||||||
|
if f.GTSFavingAccount == nil {
|
||||||
|
a := >smodel.Account{}
|
||||||
|
if err := c.db.GetByID(f.AccountID, a); err != nil {
|
||||||
|
return nil, fmt.Errorf("FaveToAS: error fetching faving account from database: %s", err)
|
||||||
|
}
|
||||||
|
f.GTSFavingAccount = a
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the like
|
||||||
|
like := streams.NewActivityStreamsLike()
|
||||||
|
|
||||||
|
// set the actor property to the fave-ing account's URI
|
||||||
|
actorProp := streams.NewActivityStreamsActorProperty()
|
||||||
|
actorIRI, err := url.Parse(f.GTSFavingAccount.URI)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("FaveToAS: error parsing uri %s: %s", f.GTSFavingAccount.URI, err)
|
||||||
|
}
|
||||||
|
actorProp.AppendIRI(actorIRI)
|
||||||
|
like.SetActivityStreamsActor(actorProp)
|
||||||
|
|
||||||
|
// set the ID property to the fave's URI
|
||||||
|
idProp := streams.NewJSONLDIdProperty()
|
||||||
|
idIRI, err := url.Parse(f.URI)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("FaveToAS: error parsing uri %s: %s", f.URI, err)
|
||||||
|
}
|
||||||
|
idProp.Set(idIRI)
|
||||||
|
like.SetJSONLDId(idProp)
|
||||||
|
|
||||||
|
// set the object property to the target status's URI
|
||||||
|
objectProp := streams.NewActivityStreamsObjectProperty()
|
||||||
|
statusIRI, err := url.Parse(f.GTSStatus.URI)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("FaveToAS: error parsing uri %s: %s", f.GTSStatus.URI, err)
|
||||||
|
}
|
||||||
|
objectProp.AppendIRI(statusIRI)
|
||||||
|
like.SetActivityStreamsObject(objectProp)
|
||||||
|
|
||||||
|
// set the TO property to the target account's IRI
|
||||||
|
toProp := streams.NewActivityStreamsToProperty()
|
||||||
|
toIRI, err := url.Parse(f.GTSTargetAccount.URI)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("FaveToAS: error parsing uri %s: %s", f.GTSTargetAccount.URI, err)
|
||||||
|
}
|
||||||
|
toProp.AppendIRI(toIRI)
|
||||||
|
like.SetActivityStreamsTo(toProp)
|
||||||
|
|
||||||
|
return like, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -109,14 +107,14 @@ type UserURIs struct {
|
||||||
|
|
||||||
// GenerateURIForFollow returns the AP URI for a new follow -- something like:
|
// GenerateURIForFollow returns the AP URI for a new follow -- something like:
|
||||||
// https://example.org/users/whatever_user/follow/41c7f33f-1060-48d9-84df-38dcb13cf0d8
|
// https://example.org/users/whatever_user/follow/41c7f33f-1060-48d9-84df-38dcb13cf0d8
|
||||||
func GenerateURIForFollow(username string, protocol string, host string) string {
|
func GenerateURIForFollow(username string, protocol string, host string, thisFollowID string) string {
|
||||||
return fmt.Sprintf("%s://%s/%s/%s/%s", protocol, host, UsersPath, FollowPath, uuid.NewString())
|
return fmt.Sprintf("%s://%s/%s/%s/%s", protocol, host, UsersPath, FollowPath, thisFollowID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateURIForFollow returns the AP URI for a new like/fave -- something like:
|
// GenerateURIForFollow returns the AP URI for a new like/fave -- something like:
|
||||||
// https://example.org/users/whatever_user/liked/41c7f33f-1060-48d9-84df-38dcb13cf0d8
|
// https://example.org/users/whatever_user/liked/41c7f33f-1060-48d9-84df-38dcb13cf0d8
|
||||||
func GenerateURIForLike(username string, protocol string, host string) string {
|
func GenerateURIForLike(username string, protocol string, host string, thisFavedID string) string {
|
||||||
return fmt.Sprintf("%s://%s/%s/%s/%s", protocol, host, UsersPath, LikedPath, uuid.NewString())
|
return fmt.Sprintf("%s://%s/%s/%s/%s", protocol, host, UsersPath, LikedPath, thisFavedID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateURIsForAccount throws together a bunch of URIs for the given username, with the given protocol and host.
|
// GenerateURIsForAccount throws together a bunch of URIs for the given username, with the given protocol and host.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue