mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-11-20 09:27:28 -06:00
start on federating faves
This commit is contained in:
parent
2dbd132e50
commit
5219a7b9e7
5 changed files with 69 additions and 5 deletions
|
|
@ -32,6 +32,8 @@ type StatusFave struct {
|
||||||
TargetAccountID string `pg:",notnull"`
|
TargetAccountID string `pg:",notnull"`
|
||||||
// database id of the status that has been 'faved'
|
// database id of the status that has been 'faved'
|
||||||
StatusID string `pg:",notnull"`
|
StatusID string `pg:",notnull"`
|
||||||
|
// ActivityPub URI of this fave
|
||||||
|
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.
|
// 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.
|
||||||
FavedStatus *Status `pg:"-"`
|
FavedStatus *Status `pg:"-"`
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,9 @@ func (p *processor) processFromClientAPI(clientMsg gtsmodel.FromClientAPI) error
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.federateFollow(follow, clientMsg.OriginAccount, clientMsg.TargetAccount)
|
return p.federateFollow(follow, clientMsg.OriginAccount, clientMsg.TargetAccount)
|
||||||
|
case gtsmodel.ActivityStreamsLike:
|
||||||
|
// CREATE LIKE/FAVE
|
||||||
|
fave, ok := clientMsg.GTSModel.(*gtsmodel.StatusFave)
|
||||||
}
|
}
|
||||||
case gtsmodel.ActivityStreamsUpdate:
|
case gtsmodel.ActivityStreamsUpdate:
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
@ -214,3 +217,24 @@ func (p *processor) federateAcceptFollowRequest(follow *gtsmodel.Follow, originA
|
||||||
_, err = p.federator.FederatingActor().Send(context.Background(), outboxIRI, accept)
|
_, err = p.federator.FederatingActor().Send(context.Background(), outboxIRI, accept)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *processor) federateFave(fave *gtsmodel.StatusFave, originAccount *gtsmodel.Account, targetAccount *gtsmodel.Account) error {
|
||||||
|
// if both accounts are local there's nothing to do here
|
||||||
|
if originAccount.Domain == "" && targetAccount.Domain == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the AS fave
|
||||||
|
asFave, err := p.tc.FaveToAS(fave, originAccount, targetAccount)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("federateFave: error converting fave to as format: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
outboxIRI, err := url.Parse(originAccount.OutboxURI)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("federateFave: error parsing outboxURI %s: %s", originAccount.OutboxURI, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = p.federator.FederatingActor().Send(context.Background(), outboxIRI, asFave)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -186,10 +186,20 @@ 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
|
// it's visible! it's faveable! so let's fave the FUCK out of it
|
||||||
_, err = p.db.FaveStatus(targetStatus, authed.Account.ID)
|
gtsFave, err := p.db.FaveStatus(targetStatus, authed.Account.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error faveing status: %s", err)
|
return nil, fmt.Errorf("error faveing status: %s", err)
|
||||||
}
|
}
|
||||||
|
gtsFave.FavedStatus = targetStatus // pin a pointer to the target status to the fave for convenience later on
|
||||||
|
|
||||||
|
// 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
|
var boostOfStatus *gtsmodel.Status
|
||||||
if targetStatus.BoostOfID != "" {
|
if targetStatus.BoostOfID != "" {
|
||||||
|
|
|
||||||
|
|
@ -85,13 +85,18 @@ var (
|
||||||
// followingPathRegex parses a path that validates and captures the username part from eg /users/example_username/following
|
// followingPathRegex parses a path that validates and captures the username part from eg /users/example_username/following
|
||||||
followingPathRegex = regexp.MustCompile(followingPathRegexString)
|
followingPathRegex = regexp.MustCompile(followingPathRegexString)
|
||||||
|
|
||||||
likedPathRegexString = fmt.Sprintf(`^/?%s/%s/%s$`, UsersPath, usernameRegexString, LikedPath)
|
|
||||||
// followingPathRegex parses a path that validates and captures the username part from eg /users/example_username/liked
|
|
||||||
likedPathRegex = regexp.MustCompile(likedPathRegexString)
|
|
||||||
|
|
||||||
// see https://ihateregex.io/expr/uuid/
|
// see https://ihateregex.io/expr/uuid/
|
||||||
uuidRegexString = `[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}`
|
uuidRegexString = `[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}`
|
||||||
|
|
||||||
|
likedPathRegexString = fmt.Sprintf(`^/?%s/(%s)/%s$`, UsersPath, usernameRegexString, LikedPath)
|
||||||
|
// likedPathRegex parses a path that validates and captures the username part from eg /users/example_username/liked
|
||||||
|
likedPathRegex = regexp.MustCompile(likedPathRegexString)
|
||||||
|
|
||||||
|
likePathRegexString = fmt.Sprintf(`^/?%s/(%s)/%s/(%s)$`, UsersPath, usernameRegexString, LikedPath, uuidRegexString)
|
||||||
|
// likePathRegex parses a path that validates and captures the username part and the uuid part
|
||||||
|
// from eg /users/example_username/liked/123e4567-e89b-12d3-a456-426655440000.
|
||||||
|
likePathRegex = regexp.MustCompile(likePathRegexString)
|
||||||
|
|
||||||
statusesPathRegexString = fmt.Sprintf(`^/?%s/(%s)/%s/(%s)$`, UsersPath, usernameRegexString, StatusesPath, uuidRegexString)
|
statusesPathRegexString = fmt.Sprintf(`^/?%s/(%s)/%s/(%s)$`, UsersPath, usernameRegexString, StatusesPath, uuidRegexString)
|
||||||
// statusesPathRegex parses a path that validates and captures the username part and the uuid part
|
// statusesPathRegex parses a path that validates and captures the username part and the uuid part
|
||||||
// from eg /users/example_username/statuses/123e4567-e89b-12d3-a456-426655440000.
|
// from eg /users/example_username/statuses/123e4567-e89b-12d3-a456-426655440000.
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,12 @@ func GenerateURIForFollow(username string, protocol string, host 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, uuid.NewString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateURIForFollow returns the AP URI for a new like/fave -- something like:
|
||||||
|
// https://example.org/users/whatever_user/liked/41c7f33f-1060-48d9-84df-38dcb13cf0d8
|
||||||
|
func GenerateURIForLike(username string, protocol string, host string) string {
|
||||||
|
return fmt.Sprintf("%s://%s/%s/%s/%s", protocol, host, UsersPath, LikedPath, uuid.NewString())
|
||||||
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
func GenerateURIsForAccount(username string, protocol string, host string) *UserURIs {
|
func GenerateURIsForAccount(username string, protocol string, host string) *UserURIs {
|
||||||
// The below URLs are used for serving web requests
|
// The below URLs are used for serving web requests
|
||||||
|
|
@ -183,6 +189,11 @@ func IsLikedPath(id *url.URL) bool {
|
||||||
return likedPathRegex.MatchString(strings.ToLower(id.Path))
|
return likedPathRegex.MatchString(strings.ToLower(id.Path))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsLikedPath returns true if the given URL path corresponds to eg /users/example_username/liked/SOME_UUID_OF_A_STATUS
|
||||||
|
func IsLikePath(id *url.URL) bool {
|
||||||
|
return likePathRegex.MatchString(strings.ToLower(id.Path))
|
||||||
|
}
|
||||||
|
|
||||||
// IsStatusesPath returns true if the given URL path corresponds to eg /users/example_username/statuses/SOME_UUID_OF_A_STATUS
|
// IsStatusesPath returns true if the given URL path corresponds to eg /users/example_username/statuses/SOME_UUID_OF_A_STATUS
|
||||||
func IsStatusesPath(id *url.URL) bool {
|
func IsStatusesPath(id *url.URL) bool {
|
||||||
return statusesPathRegex.MatchString(strings.ToLower(id.Path))
|
return statusesPathRegex.MatchString(strings.ToLower(id.Path))
|
||||||
|
|
@ -254,3 +265,15 @@ func ParseFollowingPath(id *url.URL) (username string, err error) {
|
||||||
username = matches[1]
|
username = matches[1]
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseLikedPath returns the username and uuid from a path such as /users/example_username/liked/SOME_UUID_OF_A_STATUS
|
||||||
|
func ParseLikedPath(id *url.URL) (username string, uuid string, err error) {
|
||||||
|
matches := likePathRegex.FindStringSubmatch(id.Path)
|
||||||
|
if len(matches) != 3 {
|
||||||
|
err = fmt.Errorf("expected 3 matches but matches length was %d", len(matches))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
username = matches[1]
|
||||||
|
uuid = matches[2]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue