mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-11-18 10:27:30 -06:00
[feature] Interaction requests client api + settings panel (#3215)
* [feature] Interaction requests client api + settings panel * test accept / reject * fmt * don't pin rejected interaction * use single db model for interaction accept, reject, and request * swaggor * env sharting * append errors * remove ErrNoEntries checks * change intReqID to reqID * rename "pend" to "request" * markIntsPending -> mark interactionsPending * use log instead of returning error when rejecting interaction * empty migration * jolly renaming * make interactionURI unique again * swag grr * remove unnecessary locks * invalidate as last step
This commit is contained in:
parent
8e5a72ac5c
commit
f23f04e0b1
72 changed files with 4446 additions and 663 deletions
|
|
@ -20,6 +20,7 @@ package typeutils
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/id"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/uris"
|
||||
|
|
@ -97,3 +98,80 @@ func (c *Converter) StatusToBoost(
|
|||
|
||||
return boost, nil
|
||||
}
|
||||
|
||||
func StatusToInteractionRequest(
|
||||
ctx context.Context,
|
||||
status *gtsmodel.Status,
|
||||
) (*gtsmodel.InteractionRequest, error) {
|
||||
reqID, err := id.NewULIDFromTime(status.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, gtserror.Newf("error generating ID: %w", err)
|
||||
}
|
||||
|
||||
var (
|
||||
targetID string
|
||||
target *gtsmodel.Status
|
||||
targetAccountID string
|
||||
targetAccount *gtsmodel.Account
|
||||
interactionType gtsmodel.InteractionType
|
||||
reply *gtsmodel.Status
|
||||
announce *gtsmodel.Status
|
||||
)
|
||||
|
||||
if status.InReplyToID != "" {
|
||||
// It's a reply.
|
||||
targetID = status.InReplyToID
|
||||
target = status.InReplyTo
|
||||
targetAccountID = status.InReplyToAccountID
|
||||
targetAccount = status.InReplyToAccount
|
||||
interactionType = gtsmodel.InteractionReply
|
||||
reply = status
|
||||
} else {
|
||||
// It's a boost.
|
||||
targetID = status.BoostOfID
|
||||
target = status.BoostOf
|
||||
targetAccountID = status.BoostOfAccountID
|
||||
targetAccount = status.BoostOfAccount
|
||||
interactionType = gtsmodel.InteractionAnnounce
|
||||
announce = status
|
||||
}
|
||||
|
||||
return >smodel.InteractionRequest{
|
||||
ID: reqID,
|
||||
CreatedAt: status.CreatedAt,
|
||||
StatusID: targetID,
|
||||
Status: target,
|
||||
TargetAccountID: targetAccountID,
|
||||
TargetAccount: targetAccount,
|
||||
InteractingAccountID: status.AccountID,
|
||||
InteractingAccount: status.Account,
|
||||
InteractionURI: status.URI,
|
||||
InteractionType: interactionType,
|
||||
Reply: reply,
|
||||
Announce: announce,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func StatusFaveToInteractionRequest(
|
||||
ctx context.Context,
|
||||
fave *gtsmodel.StatusFave,
|
||||
) (*gtsmodel.InteractionRequest, error) {
|
||||
reqID, err := id.NewULIDFromTime(fave.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, gtserror.Newf("error generating ID: %w", err)
|
||||
}
|
||||
|
||||
return >smodel.InteractionRequest{
|
||||
ID: reqID,
|
||||
CreatedAt: fave.CreatedAt,
|
||||
StatusID: fave.StatusID,
|
||||
Status: fave.Status,
|
||||
TargetAccountID: fave.TargetAccountID,
|
||||
TargetAccount: fave.TargetAccount,
|
||||
InteractingAccountID: fave.AccountID,
|
||||
InteractingAccount: fave.Account,
|
||||
InteractionURI: fave.URI,
|
||||
InteractionType: gtsmodel.InteractionLike,
|
||||
Like: fave,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1960,36 +1960,36 @@ func (c *Converter) InteractionPolicyToASInteractionPolicy(
|
|||
return policy, nil
|
||||
}
|
||||
|
||||
// InteractionApprovalToASAccept converts a *gtsmodel.InteractionApproval
|
||||
// InteractionReqToASAccept converts a *gtsmodel.InteractionRequest
|
||||
// to an ActivityStreams Accept, addressed to the interacting account.
|
||||
func (c *Converter) InteractionApprovalToASAccept(
|
||||
func (c *Converter) InteractionReqToASAccept(
|
||||
ctx context.Context,
|
||||
approval *gtsmodel.InteractionApproval,
|
||||
req *gtsmodel.InteractionRequest,
|
||||
) (vocab.ActivityStreamsAccept, error) {
|
||||
accept := streams.NewActivityStreamsAccept()
|
||||
|
||||
acceptID, err := url.Parse(approval.URI)
|
||||
acceptID, err := url.Parse(req.URI)
|
||||
if err != nil {
|
||||
return nil, gtserror.Newf("invalid accept uri: %w", err)
|
||||
}
|
||||
|
||||
actorIRI, err := url.Parse(approval.Account.URI)
|
||||
actorIRI, err := url.Parse(req.TargetAccount.URI)
|
||||
if err != nil {
|
||||
return nil, gtserror.Newf("invalid account uri: %w", err)
|
||||
}
|
||||
|
||||
objectIRI, err := url.Parse(approval.InteractionURI)
|
||||
objectIRI, err := url.Parse(req.InteractionURI)
|
||||
if err != nil {
|
||||
return nil, gtserror.Newf("invalid target uri: %w", err)
|
||||
}
|
||||
|
||||
toIRI, err := url.Parse(approval.InteractingAccount.URI)
|
||||
toIRI, err := url.Parse(req.InteractingAccount.URI)
|
||||
if err != nil {
|
||||
return nil, gtserror.Newf("invalid interacting account uri: %w", err)
|
||||
}
|
||||
|
||||
// Set id to the URI of
|
||||
// interactionApproval.
|
||||
// interaction request.
|
||||
ap.SetJSONLDId(accept, acceptID)
|
||||
|
||||
// Actor is the account that
|
||||
|
|
|
|||
|
|
@ -1057,26 +1057,26 @@ func (suite *InternalToASTestSuite) TestPollVoteToASCreate() {
|
|||
}`, string(bytes))
|
||||
}
|
||||
|
||||
func (suite *InternalToASTestSuite) TestInteractionApprovalToASAccept() {
|
||||
func (suite *InternalToASTestSuite) TestInteractionReqToASAccept() {
|
||||
acceptingAccount := suite.testAccounts["local_account_1"]
|
||||
interactingAccount := suite.testAccounts["remote_account_1"]
|
||||
|
||||
interactionApproval := >smodel.InteractionApproval{
|
||||
req := >smodel.InteractionRequest{
|
||||
ID: "01J1AKMZ8JE5NW0ZSFTRC1JJNE",
|
||||
CreatedAt: testrig.TimeMustParse("2022-06-09T13:12:00Z"),
|
||||
UpdatedAt: testrig.TimeMustParse("2022-06-09T13:12:00Z"),
|
||||
AccountID: acceptingAccount.ID,
|
||||
Account: acceptingAccount,
|
||||
TargetAccountID: acceptingAccount.ID,
|
||||
TargetAccount: acceptingAccount,
|
||||
InteractingAccountID: interactingAccount.ID,
|
||||
InteractingAccount: interactingAccount,
|
||||
InteractionURI: "https://fossbros-anonymous.io/users/foss_satan/statuses/01J1AKRRHQ6MDDQHV0TP716T2K",
|
||||
InteractionType: gtsmodel.InteractionAnnounce,
|
||||
URI: "http://localhost:8080/users/the_mighty_zork/accepts/01J1AKMZ8JE5NW0ZSFTRC1JJNE",
|
||||
AcceptedAt: testrig.TimeMustParse("2022-06-09T13:12:00Z"),
|
||||
}
|
||||
|
||||
accept, err := suite.typeconverter.InteractionApprovalToASAccept(
|
||||
accept, err := suite.typeconverter.InteractionReqToASAccept(
|
||||
context.Background(),
|
||||
interactionApproval,
|
||||
req,
|
||||
)
|
||||
if err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
|
|
|
|||
|
|
@ -2592,3 +2592,74 @@ func policyValsToAPIPolicyVals(vals gtsmodel.PolicyValues) []apimodel.PolicyValu
|
|||
|
||||
return apiVals
|
||||
}
|
||||
|
||||
// InteractionReqToAPIInteractionReq converts the given *gtsmodel.InteractionRequest
|
||||
// to an *apimodel.InteractionRequest, from the perspective of requestingAcct.
|
||||
func (c *Converter) InteractionReqToAPIInteractionReq(
|
||||
ctx context.Context,
|
||||
req *gtsmodel.InteractionRequest,
|
||||
requestingAcct *gtsmodel.Account,
|
||||
) (*apimodel.InteractionRequest, error) {
|
||||
// Ensure interaction request is populated.
|
||||
if err := c.state.DB.PopulateInteractionRequest(ctx, req); err != nil {
|
||||
err := gtserror.Newf("error populating: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
interactingAcct, err := c.AccountToAPIAccountPublic(ctx, req.InteractingAccount)
|
||||
if err != nil {
|
||||
err := gtserror.Newf("error converting interacting acct: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
interactedStatus, err := c.StatusToAPIStatus(
|
||||
ctx,
|
||||
req.Status,
|
||||
requestingAcct,
|
||||
statusfilter.FilterContextNone,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
err := gtserror.Newf("error converting interacted status: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var reply *apimodel.Status
|
||||
if req.InteractionType == gtsmodel.InteractionReply {
|
||||
reply, err = c.StatusToAPIStatus(
|
||||
ctx,
|
||||
req.Reply,
|
||||
requestingAcct,
|
||||
statusfilter.FilterContextNone,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
err := gtserror.Newf("error converting reply: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var acceptedAt string
|
||||
if req.IsAccepted() {
|
||||
acceptedAt = util.FormatISO8601(req.AcceptedAt)
|
||||
}
|
||||
|
||||
var rejectedAt string
|
||||
if req.IsRejected() {
|
||||
rejectedAt = util.FormatISO8601(req.RejectedAt)
|
||||
}
|
||||
|
||||
return &apimodel.InteractionRequest{
|
||||
ID: req.ID,
|
||||
Type: req.InteractionType.String(),
|
||||
CreatedAt: util.FormatISO8601(req.CreatedAt),
|
||||
Account: interactingAcct,
|
||||
Status: interactedStatus,
|
||||
Reply: reply,
|
||||
AcceptedAt: acceptedAt,
|
||||
RejectedAt: rejectedAt,
|
||||
URI: req.URI,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue