summaryrefslogtreecommitdiff
path: root/internal/typeutils/astointernal.go
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2023-01-25 11:12:27 +0100
committerLibravatar GitHub <noreply@github.com>2023-01-25 11:12:27 +0100
commit993aae5e48a5a3b47a7c7bb3cb66e2d8abda17b2 (patch)
treea64ad3edaf2a29f457bd050b24609fe4f1abdf02 /internal/typeutils/astointernal.go
parent[feature] Implement reports admin API so admins can view + close reports (#1378) (diff)
downloadgotosocial-993aae5e48a5a3b47a7c7bb3cb66e2d8abda17b2.tar.xz
[feature] Accept incoming federated Flag activity (#1382)
* start working on handling incoming Flag activity * interim commit * federate Flag in successfully
Diffstat (limited to 'internal/typeutils/astointernal.go')
-rw-r--r--internal/typeutils/astointernal.go125
1 files changed, 125 insertions, 0 deletions
diff --git a/internal/typeutils/astointernal.go b/internal/typeutils/astointernal.go
index cd1b0c77a..bebf62989 100644
--- a/internal/typeutils/astointernal.go
+++ b/internal/typeutils/astointernal.go
@@ -22,12 +22,15 @@ import (
"context"
"errors"
"fmt"
+ "net/url"
"github.com/miekg/dns"
"github.com/superseriousbusiness/gotosocial/internal/ap"
+ "github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/log"
+ "github.com/superseriousbusiness/gotosocial/internal/uris"
)
func (c *converter) ASRepresentationToAccount(ctx context.Context, accountable ap.Accountable, accountDomain string, update bool) (*gtsmodel.Account, error) {
@@ -574,3 +577,125 @@ func (c *converter) ASAnnounceToStatus(ctx context.Context, announceable ap.Anno
// the rest of the fields will be taken from the target status, but it's not our job to do the dereferencing here
return status, isNew, nil
}
+
+func (c *converter) ASFlagToReport(ctx context.Context, flaggable ap.Flaggable) (*gtsmodel.Report, error) {
+ // Extract flag uri.
+ idProp := flaggable.GetJSONLDId()
+ if idProp == nil || !idProp.IsIRI() {
+ return nil, errors.New("ASFlagToReport: no id property set on flaggable, or was not an iri")
+ }
+ uri := idProp.GetIRI().String()
+
+ // Extract account that created the flag / report.
+ // This will usually be an instance actor.
+ actor, err := ap.ExtractActor(flaggable)
+ if err != nil {
+ return nil, fmt.Errorf("ASFlagToReport: error extracting actor: %w", err)
+ }
+ account, err := c.db.GetAccountByURI(ctx, actor.String())
+ if err != nil {
+ return nil, fmt.Errorf("ASFlagToReport: error in db fetching account with uri %s: %w", actor.String(), err)
+ }
+
+ // Get the content of the report.
+ // For Mastodon, this will just be a string, or nothing.
+ // In Misskey's case, it may also contain the URLs of
+ // one or more reported statuses, so extract these too.
+ content := ap.ExtractContent(flaggable)
+ statusURIs := []*url.URL{}
+ inlineURLs := misskeyReportInlineURLs(content)
+ statusURIs = append(statusURIs, inlineURLs...)
+
+ // Extract account and statuses targeted by the flag / report.
+ //
+ // Incoming flags from mastodon usually have a target account uri as
+ // first entry in objects, followed by URIs of one or more statuses.
+ // Misskey on the other hand will just contain the target account uri.
+ // We shouldn't assume the order of the objects will correspond to this,
+ // but we can check that he objects slice contains just one account, and
+ // maybe some statuses.
+ //
+ // Throw away anything that's not relevant to us.
+ objects, err := ap.ExtractObjects(flaggable)
+ if err != nil {
+ return nil, fmt.Errorf("ASFlagToReport: error extracting objects: %w", err)
+ }
+ if len(objects) == 0 {
+ return nil, errors.New("ASFlagToReport: flaggable objects empty, can't create report")
+ }
+
+ var targetAccountURI *url.URL
+ for _, object := range objects {
+ switch {
+ case object.Host != config.GetHost():
+ // object doesn't belong to us, just ignore it
+ continue
+ case uris.IsUserPath(object):
+ if targetAccountURI != nil {
+ return nil, errors.New("ASFlagToReport: flaggable objects contained more than one target account uri")
+ }
+ targetAccountURI = object
+ case uris.IsStatusesPath(object):
+ statusURIs = append(statusURIs, object)
+ }
+ }
+
+ // Make sure we actually have a target account now.
+ if targetAccountURI == nil {
+ return nil, errors.New("ASFlagToReport: flaggable objects contained no recognizable target account uri")
+ }
+ targetAccount, err := c.db.GetAccountByURI(ctx, targetAccountURI.String())
+ if err != nil {
+ if errors.Is(err, db.ErrNoEntries) {
+ return nil, fmt.Errorf("ASFlagToReport: account with uri %s could not be found in the db", targetAccountURI.String())
+ }
+ return nil, fmt.Errorf("ASFlagToReport: db error getting account with uri %s: %w", targetAccountURI.String(), err)
+ }
+
+ // If we got some status URIs, try to get them from the db now
+ var (
+ statusIDs = make([]string, 0, len(statusURIs))
+ statuses = make([]*gtsmodel.Status, 0, len(statusURIs))
+ )
+ for _, statusURI := range statusURIs {
+ statusURIString := statusURI.String()
+
+ // try getting this status by URI first, then URL
+ status, err := c.db.GetStatusByURI(ctx, statusURIString)
+ if err != nil {
+ if !errors.Is(err, db.ErrNoEntries) {
+ return nil, fmt.Errorf("ASFlagToReport: db error getting status with uri %s: %w", statusURIString, err)
+ }
+
+ status, err = c.db.GetStatusByURL(ctx, statusURIString)
+ if err != nil {
+ if !errors.Is(err, db.ErrNoEntries) {
+ return nil, fmt.Errorf("ASFlagToReport: db error getting status with url %s: %w", statusURIString, err)
+ }
+
+ log.Warnf("ASFlagToReport: reported status %s could not be found in the db, skipping it", statusURIString)
+ continue
+ }
+ }
+
+ if status.AccountID != targetAccount.ID {
+ // status doesn't belong to this account, ignore it
+ continue
+ }
+
+ statusIDs = append(statusIDs, status.ID)
+ statuses = append(statuses, status)
+ }
+
+ // id etc should be handled the caller, so just return what we got
+ return &gtsmodel.Report{
+ URI: uri,
+ AccountID: account.ID,
+ Account: account,
+ TargetAccountID: targetAccount.ID,
+ TargetAccount: targetAccount,
+ Comment: content,
+ StatusIDs: statusIDs,
+ Statuses: statuses,
+ }, nil
+}