summaryrefslogtreecommitdiff
path: root/internal/processing
diff options
context:
space:
mode:
Diffstat (limited to 'internal/processing')
-rw-r--r--internal/processing/account/account.go6
-rw-r--r--internal/processing/account/account_test.go8
-rw-r--r--internal/processing/account/get.go8
-rw-r--r--internal/processing/account/update.go63
-rw-r--r--internal/processing/admin.go2
-rw-r--r--internal/processing/admin/admin.go8
-rw-r--r--internal/processing/admin/emoji.go48
-rw-r--r--internal/processing/federation/getfollowers.go2
-rw-r--r--internal/processing/federation/getfollowing.go2
-rw-r--r--internal/processing/federation/getoutbox.go2
-rw-r--r--internal/processing/federation/getstatus.go2
-rw-r--r--internal/processing/federation/getstatusreplies.go2
-rw-r--r--internal/processing/federation/getuser.go2
-rw-r--r--internal/processing/fromfederator.go109
-rw-r--r--internal/processing/media/create.go54
-rw-r--r--internal/processing/media/media.go6
-rw-r--r--internal/processing/processor.go14
-rw-r--r--internal/processing/processor_test.go8
-rw-r--r--internal/processing/search.go4
19 files changed, 209 insertions, 141 deletions
diff --git a/internal/processing/account/account.go b/internal/processing/account/account.go
index ae005f4f6..b2321f414 100644
--- a/internal/processing/account/account.go
+++ b/internal/processing/account/account.go
@@ -77,7 +77,7 @@ type Processor interface {
type processor struct {
tc typeutils.TypeConverter
- mediaHandler media.Handler
+ mediaManager media.Manager
fromClientAPI chan messages.FromClientAPI
oauthServer oauth.Server
filter visibility.Filter
@@ -87,10 +87,10 @@ type processor struct {
}
// New returns a new account processor.
-func New(db db.DB, tc typeutils.TypeConverter, mediaHandler media.Handler, oauthServer oauth.Server, fromClientAPI chan messages.FromClientAPI, federator federation.Federator) Processor {
+func New(db db.DB, tc typeutils.TypeConverter, mediaManager media.Manager, oauthServer oauth.Server, fromClientAPI chan messages.FromClientAPI, federator federation.Federator) Processor {
return &processor{
tc: tc,
- mediaHandler: mediaHandler,
+ mediaManager: mediaManager,
fromClientAPI: fromClientAPI,
oauthServer: oauthServer,
filter: visibility.NewFilter(db),
diff --git a/internal/processing/account/account_test.go b/internal/processing/account/account_test.go
index e4611ba23..5a9382ed6 100644
--- a/internal/processing/account/account_test.go
+++ b/internal/processing/account/account_test.go
@@ -41,7 +41,7 @@ type AccountStandardTestSuite struct {
db db.DB
tc typeutils.TypeConverter
storage *kv.KVStore
- mediaHandler media.Handler
+ mediaManager media.Manager
oauthServer oauth.Server
fromClientAPIChan chan messages.FromClientAPI
httpClient pub.HttpClient
@@ -80,15 +80,15 @@ func (suite *AccountStandardTestSuite) SetupTest() {
suite.db = testrig.NewTestDB()
suite.tc = testrig.NewTestTypeConverter(suite.db)
suite.storage = testrig.NewTestStorage()
- suite.mediaHandler = testrig.NewTestMediaHandler(suite.db, suite.storage)
+ suite.mediaManager = testrig.NewTestMediaManager(suite.db, suite.storage)
suite.oauthServer = testrig.NewTestOauthServer(suite.db)
suite.fromClientAPIChan = make(chan messages.FromClientAPI, 100)
suite.httpClient = testrig.NewMockHTTPClient(nil)
suite.transportController = testrig.NewTestTransportController(suite.httpClient, suite.db)
- suite.federator = testrig.NewTestFederator(suite.db, suite.transportController, suite.storage)
+ suite.federator = testrig.NewTestFederator(suite.db, suite.transportController, suite.storage, suite.mediaManager)
suite.sentEmails = make(map[string]string)
suite.emailSender = testrig.NewEmailSender("../../../web/template/", suite.sentEmails)
- suite.accountProcessor = account.New(suite.db, suite.tc, suite.mediaHandler, suite.oauthServer, suite.fromClientAPIChan, suite.federator)
+ suite.accountProcessor = account.New(suite.db, suite.tc, suite.mediaManager, suite.oauthServer, suite.fromClientAPIChan, suite.federator)
testrig.StandardDBSetup(suite.db, nil)
testrig.StandardStorageSetup(suite.storage, "../../../testrig/media")
}
diff --git a/internal/processing/account/get.go b/internal/processing/account/get.go
index e96040db7..2571d7af1 100644
--- a/internal/processing/account/get.go
+++ b/internal/processing/account/get.go
@@ -22,6 +22,7 @@ import (
"context"
"errors"
"fmt"
+ "net/url"
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/db"
@@ -56,7 +57,12 @@ func (p *processor) Get(ctx context.Context, requestingAccount *gtsmodel.Account
// last-minute check to make sure we have remote account header/avi cached
if targetAccount.Domain != "" {
- a, err := p.federator.EnrichRemoteAccount(ctx, requestingAccount.Username, targetAccount)
+ targetAccountURI, err := url.Parse(targetAccount.URI)
+ if err != nil {
+ return nil, fmt.Errorf("error parsing url %s: %s", targetAccount.URI, err)
+ }
+
+ a, err := p.federator.GetRemoteAccount(ctx, requestingAccount.Username, targetAccountURI, true, false)
if err == nil {
targetAccount = a
}
diff --git a/internal/processing/account/update.go b/internal/processing/account/update.go
index a32dd9ac0..4d10f1d0c 100644
--- a/internal/processing/account/update.go
+++ b/internal/processing/account/update.go
@@ -19,9 +19,7 @@
package account
import (
- "bytes"
"context"
- "errors"
"fmt"
"io"
"mime/multipart"
@@ -137,68 +135,57 @@ func (p *processor) Update(ctx context.Context, account *gtsmodel.Account, form
// parsing and checking the image, and doing the necessary updates in the database for this to become
// the account's new avatar image.
func (p *processor) UpdateAvatar(ctx context.Context, avatar *multipart.FileHeader, accountID string) (*gtsmodel.MediaAttachment, error) {
- var err error
maxImageSize := viper.GetInt(config.Keys.MediaImageMaxSize)
if int(avatar.Size) > maxImageSize {
- err = fmt.Errorf("avatar with size %d exceeded max image size of %d bytes", avatar.Size, maxImageSize)
- return nil, err
- }
- f, err := avatar.Open()
- if err != nil {
- return nil, fmt.Errorf("could not read provided avatar: %s", err)
+ return nil, fmt.Errorf("UpdateAvatar: avatar with size %d exceeded max image size of %d bytes", avatar.Size, maxImageSize)
}
- // extract the bytes
- buf := new(bytes.Buffer)
- size, err := io.Copy(buf, f)
- if err != nil {
- return nil, fmt.Errorf("could not read provided avatar: %s", err)
+ dataFunc := func(innerCtx context.Context) (io.Reader, int, error) {
+ f, err := avatar.Open()
+ return f, int(avatar.Size), err
}
- if size == 0 {
- return nil, errors.New("could not read provided avatar: size 0 bytes")
+
+ isAvatar := true
+ ai := &media.AdditionalMediaInfo{
+ Avatar: &isAvatar,
}
- // do the setting
- avatarInfo, err := p.mediaHandler.ProcessHeaderOrAvatar(ctx, buf.Bytes(), accountID, media.TypeAvatar, "")
+ processingMedia, err := p.mediaManager.ProcessMedia(ctx, dataFunc, accountID, ai)
if err != nil {
- return nil, fmt.Errorf("error processing avatar: %s", err)
+ return nil, fmt.Errorf("UpdateAvatar: error processing avatar: %s", err)
}
- return avatarInfo, f.Close()
+ return processingMedia.LoadAttachment(ctx)
}
// UpdateHeader does the dirty work of checking the header part of an account update form,
// parsing and checking the image, and doing the necessary updates in the database for this to become
// the account's new header image.
func (p *processor) UpdateHeader(ctx context.Context, header *multipart.FileHeader, accountID string) (*gtsmodel.MediaAttachment, error) {
- var err error
maxImageSize := viper.GetInt(config.Keys.MediaImageMaxSize)
if int(header.Size) > maxImageSize {
- err = fmt.Errorf("header with size %d exceeded max image size of %d bytes", header.Size, maxImageSize)
- return nil, err
- }
- f, err := header.Open()
- if err != nil {
- return nil, fmt.Errorf("could not read provided header: %s", err)
+ return nil, fmt.Errorf("UpdateHeader: header with size %d exceeded max image size of %d bytes", header.Size, maxImageSize)
}
- // extract the bytes
- buf := new(bytes.Buffer)
- size, err := io.Copy(buf, f)
- if err != nil {
- return nil, fmt.Errorf("could not read provided header: %s", err)
+ dataFunc := func(innerCtx context.Context) (io.Reader, int, error) {
+ f, err := header.Open()
+ return f, int(header.Size), err
}
- if size == 0 {
- return nil, errors.New("could not read provided header: size 0 bytes")
+
+ isHeader := true
+ ai := &media.AdditionalMediaInfo{
+ Header: &isHeader,
}
- // do the setting
- headerInfo, err := p.mediaHandler.ProcessHeaderOrAvatar(ctx, buf.Bytes(), accountID, media.TypeHeader, "")
+ processingMedia, err := p.mediaManager.ProcessMedia(ctx, dataFunc, accountID, ai)
+ if err != nil {
+ return nil, fmt.Errorf("UpdateHeader: error processing header: %s", err)
+ }
if err != nil {
- return nil, fmt.Errorf("error processing header: %s", err)
+ return nil, fmt.Errorf("UpdateHeader: error processing header: %s", err)
}
- return headerInfo, f.Close()
+ return processingMedia.LoadAttachment(ctx)
}
func (p *processor) processNote(ctx context.Context, note string, accountID string) (string, error) {
diff --git a/internal/processing/admin.go b/internal/processing/admin.go
index c70bd79d0..764e6d302 100644
--- a/internal/processing/admin.go
+++ b/internal/processing/admin.go
@@ -26,7 +26,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/oauth"
)
-func (p *processor) AdminEmojiCreate(ctx context.Context, authed *oauth.Auth, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, error) {
+func (p *processor) AdminEmojiCreate(ctx context.Context, authed *oauth.Auth, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, gtserror.WithCode) {
return p.adminProcessor.EmojiCreate(ctx, authed.Account, authed.User, form)
}
diff --git a/internal/processing/admin/admin.go b/internal/processing/admin/admin.go
index 217d10dfe..bdb586588 100644
--- a/internal/processing/admin/admin.go
+++ b/internal/processing/admin/admin.go
@@ -38,21 +38,21 @@ type Processor interface {
DomainBlocksGet(ctx context.Context, account *gtsmodel.Account, export bool) ([]*apimodel.DomainBlock, gtserror.WithCode)
DomainBlockGet(ctx context.Context, account *gtsmodel.Account, id string, export bool) (*apimodel.DomainBlock, gtserror.WithCode)
DomainBlockDelete(ctx context.Context, account *gtsmodel.Account, id string) (*apimodel.DomainBlock, gtserror.WithCode)
- EmojiCreate(ctx context.Context, account *gtsmodel.Account, user *gtsmodel.User, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, error)
+ EmojiCreate(ctx context.Context, account *gtsmodel.Account, user *gtsmodel.User, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, gtserror.WithCode)
}
type processor struct {
tc typeutils.TypeConverter
- mediaHandler media.Handler
+ mediaManager media.Manager
fromClientAPI chan messages.FromClientAPI
db db.DB
}
// New returns a new admin processor.
-func New(db db.DB, tc typeutils.TypeConverter, mediaHandler media.Handler, fromClientAPI chan messages.FromClientAPI) Processor {
+func New(db db.DB, tc typeutils.TypeConverter, mediaManager media.Manager, fromClientAPI chan messages.FromClientAPI) Processor {
return &processor{
tc: tc,
- mediaHandler: mediaHandler,
+ mediaManager: mediaManager,
fromClientAPI: fromClientAPI,
db: db,
}
diff --git a/internal/processing/admin/emoji.go b/internal/processing/admin/emoji.go
index 4989d8e8d..bb9f4ecb5 100644
--- a/internal/processing/admin/emoji.go
+++ b/internal/processing/admin/emoji.go
@@ -19,55 +19,51 @@
package admin
import (
- "bytes"
"context"
- "errors"
"fmt"
"io"
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
+ "github.com/superseriousbusiness/gotosocial/internal/db"
+ "github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/id"
+ "github.com/superseriousbusiness/gotosocial/internal/uris"
)
-func (p *processor) EmojiCreate(ctx context.Context, account *gtsmodel.Account, user *gtsmodel.User, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, error) {
- if user.Admin {
- return nil, fmt.Errorf("user %s not an admin", user.ID)
+func (p *processor) EmojiCreate(ctx context.Context, account *gtsmodel.Account, user *gtsmodel.User, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, gtserror.WithCode) {
+ if !user.Admin {
+ return nil, gtserror.NewErrorNotAuthorized(fmt.Errorf("user %s not an admin", user.ID), "user is not an admin")
}
- // open the emoji and extract the bytes from it
- f, err := form.Image.Open()
- if err != nil {
- return nil, fmt.Errorf("error opening emoji: %s", err)
+ data := func(innerCtx context.Context) (io.Reader, int, error) {
+ f, err := form.Image.Open()
+ return f, int(form.Image.Size), err
}
- buf := new(bytes.Buffer)
- size, err := io.Copy(buf, f)
+
+ emojiID, err := id.NewRandomULID()
if err != nil {
- return nil, fmt.Errorf("error reading emoji: %s", err)
- }
- if size == 0 {
- return nil, errors.New("could not read provided emoji: size 0 bytes")
+ return nil, gtserror.NewErrorInternalError(fmt.Errorf("error creating id for new emoji: %s", err), "error creating emoji ID")
}
- // allow the mediaHandler to work its magic of processing the emoji bytes, and putting them in whatever storage backend we're using
- emoji, err := p.mediaHandler.ProcessLocalEmoji(ctx, buf.Bytes(), form.Shortcode)
+ emojiURI := uris.GenerateURIForEmoji(emojiID)
+
+ processingEmoji, err := p.mediaManager.ProcessEmoji(ctx, data, form.Shortcode, emojiID, emojiURI, nil)
if err != nil {
- return nil, fmt.Errorf("error reading emoji: %s", err)
+ return nil, gtserror.NewErrorInternalError(fmt.Errorf("error processing emoji: %s", err), "error processing emoji")
}
- emojiID, err := id.NewULID()
+ emoji, err := processingEmoji.LoadEmoji(ctx)
if err != nil {
- return nil, err
+ if err == db.ErrAlreadyExists {
+ return nil, gtserror.NewErrorConflict(fmt.Errorf("emoji with shortcode %s already exists", form.Shortcode), fmt.Sprintf("emoji with shortcode %s already exists", form.Shortcode))
+ }
+ return nil, gtserror.NewErrorInternalError(fmt.Errorf("error loading emoji: %s", err), "error loading emoji")
}
- emoji.ID = emojiID
apiEmoji, err := p.tc.EmojiToAPIEmoji(ctx, emoji)
if err != nil {
- return nil, fmt.Errorf("error converting emoji to apitype: %s", err)
- }
-
- if err := p.db.Put(ctx, emoji); err != nil {
- return nil, fmt.Errorf("database error while processing emoji: %s", err)
+ return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting emoji: %s", err), "error converting emoji to api representation")
}
return &apiEmoji, nil
diff --git a/internal/processing/federation/getfollowers.go b/internal/processing/federation/getfollowers.go
index 9153cde1e..c15b2b6c4 100644
--- a/internal/processing/federation/getfollowers.go
+++ b/internal/processing/federation/getfollowers.go
@@ -41,7 +41,7 @@ func (p *processor) GetFollowers(ctx context.Context, requestedUsername string,
return nil, gtserror.NewErrorNotAuthorized(errors.New("not authorized"), "not authorized")
}
- requestingAccount, _, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false)
+ requestingAccount, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false, false)
if err != nil {
return nil, gtserror.NewErrorNotAuthorized(err)
}
diff --git a/internal/processing/federation/getfollowing.go b/internal/processing/federation/getfollowing.go
index 8a3025154..d2beaada0 100644
--- a/internal/processing/federation/getfollowing.go
+++ b/internal/processing/federation/getfollowing.go
@@ -41,7 +41,7 @@ func (p *processor) GetFollowing(ctx context.Context, requestedUsername string,
return nil, gtserror.NewErrorNotAuthorized(errors.New("not authorized"), "not authorized")
}
- requestingAccount, _, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false)
+ requestingAccount, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false, false)
if err != nil {
return nil, gtserror.NewErrorNotAuthorized(err)
}
diff --git a/internal/processing/federation/getoutbox.go b/internal/processing/federation/getoutbox.go
index 0f2043447..944c0b571 100644
--- a/internal/processing/federation/getoutbox.go
+++ b/internal/processing/federation/getoutbox.go
@@ -42,7 +42,7 @@ func (p *processor) GetOutbox(ctx context.Context, requestedUsername string, pag
return nil, gtserror.NewErrorNotAuthorized(errors.New("not authorized"), "not authorized")
}
- requestingAccount, _, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false)
+ requestingAccount, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false, false)
if err != nil {
return nil, gtserror.NewErrorNotAuthorized(err)
}
diff --git a/internal/processing/federation/getstatus.go b/internal/processing/federation/getstatus.go
index f065eaa71..1651516b5 100644
--- a/internal/processing/federation/getstatus.go
+++ b/internal/processing/federation/getstatus.go
@@ -43,7 +43,7 @@ func (p *processor) GetStatus(ctx context.Context, requestedUsername string, req
return nil, gtserror.NewErrorNotAuthorized(errors.New("not authorized"), "not authorized")
}
- requestingAccount, _, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false)
+ requestingAccount, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false, false)
if err != nil {
return nil, gtserror.NewErrorNotAuthorized(err)
}
diff --git a/internal/processing/federation/getstatusreplies.go b/internal/processing/federation/getstatusreplies.go
index 4fc21e3ad..c6db4dd3e 100644
--- a/internal/processing/federation/getstatusreplies.go
+++ b/internal/processing/federation/getstatusreplies.go
@@ -43,7 +43,7 @@ func (p *processor) GetStatusReplies(ctx context.Context, requestedUsername stri
return nil, gtserror.NewErrorNotAuthorized(errors.New("not authorized"), "not authorized")
}
- requestingAccount, _, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false)
+ requestingAccount, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false, false)
if err != nil {
return nil, gtserror.NewErrorNotAuthorized(err)
}
diff --git a/internal/processing/federation/getuser.go b/internal/processing/federation/getuser.go
index a8d6bcf38..6d5b8463f 100644
--- a/internal/processing/federation/getuser.go
+++ b/internal/processing/federation/getuser.go
@@ -54,7 +54,7 @@ func (p *processor) GetUser(ctx context.Context, requestedUsername string, reque
// if we're not already handshaking/dereferencing a remote account, dereference it now
if !p.federator.Handshaking(ctx, requestedUsername, requestingAccountURI) {
- requestingAccount, _, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false)
+ requestingAccount, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false, false)
if err != nil {
return nil, gtserror.NewErrorNotAuthorized(err)
}
diff --git a/internal/processing/fromfederator.go b/internal/processing/fromfederator.go
index 3083bcc40..bb2cb5323 100644
--- a/internal/processing/fromfederator.go
+++ b/internal/processing/fromfederator.go
@@ -22,6 +22,7 @@ import (
"context"
"errors"
"fmt"
+ "net/url"
"github.com/sirupsen/logrus"
"github.com/superseriousbusiness/gotosocial/internal/ap"
@@ -114,6 +115,30 @@ func (p *processor) processCreateStatusFromFederator(ctx context.Context, federa
}
}
+ // make sure the account is pinned
+ if status.Account == nil {
+ a, err := p.db.GetAccountByID(ctx, status.AccountID)
+ if err != nil {
+ return err
+ }
+ status.Account = a
+ }
+
+ // do a BLOCKING get of the remote account to make sure the avi and header are cached
+ if status.Account.Domain != "" {
+ remoteAccountID, err := url.Parse(status.Account.URI)
+ if err != nil {
+ return err
+ }
+
+ a, err := p.federator.GetRemoteAccount(ctx, federatorMsg.ReceivingAccount.Username, remoteAccountID, true, false)
+ if err != nil {
+ return err
+ }
+
+ status.Account = a
+ }
+
if err := p.timelineStatus(ctx, status); err != nil {
return err
}
@@ -132,6 +157,30 @@ func (p *processor) processCreateFaveFromFederator(ctx context.Context, federato
return errors.New("like was not parseable as *gtsmodel.StatusFave")
}
+ // make sure the account is pinned
+ if incomingFave.Account == nil {
+ a, err := p.db.GetAccountByID(ctx, incomingFave.AccountID)
+ if err != nil {
+ return err
+ }
+ incomingFave.Account = a
+ }
+
+ // do a BLOCKING get of the remote account to make sure the avi and header are cached
+ if incomingFave.Account.Domain != "" {
+ remoteAccountID, err := url.Parse(incomingFave.Account.URI)
+ if err != nil {
+ return err
+ }
+
+ a, err := p.federator.GetRemoteAccount(ctx, federatorMsg.ReceivingAccount.Username, remoteAccountID, true, false)
+ if err != nil {
+ return err
+ }
+
+ incomingFave.Account = a
+ }
+
if err := p.notifyFave(ctx, incomingFave); err != nil {
return err
}
@@ -146,6 +195,30 @@ func (p *processor) processCreateFollowRequestFromFederator(ctx context.Context,
return errors.New("incomingFollowRequest was not parseable as *gtsmodel.FollowRequest")
}
+ // make sure the account is pinned
+ if followRequest.Account == nil {
+ a, err := p.db.GetAccountByID(ctx, followRequest.AccountID)
+ if err != nil {
+ return err
+ }
+ followRequest.Account = a
+ }
+
+ // do a BLOCKING get of the remote account to make sure the avi and header are cached
+ if followRequest.Account.Domain != "" {
+ remoteAccountID, err := url.Parse(followRequest.Account.URI)
+ if err != nil {
+ return err
+ }
+
+ a, err := p.federator.GetRemoteAccount(ctx, federatorMsg.ReceivingAccount.Username, remoteAccountID, true, false)
+ if err != nil {
+ return err
+ }
+
+ followRequest.Account = a
+ }
+
if followRequest.TargetAccount == nil {
a, err := p.db.GetAccountByID(ctx, followRequest.TargetAccountID)
if err != nil {
@@ -153,9 +226,8 @@ func (p *processor) processCreateFollowRequestFromFederator(ctx context.Context,
}
followRequest.TargetAccount = a
}
- targetAccount := followRequest.TargetAccount
- if targetAccount.Locked {
+ if followRequest.TargetAccount.Locked {
// if the account is locked just notify the follow request and nothing else
return p.notifyFollowRequest(ctx, followRequest)
}
@@ -170,7 +242,7 @@ func (p *processor) processCreateFollowRequestFromFederator(ctx context.Context,
return err
}
- return p.notifyFollow(ctx, follow, targetAccount)
+ return p.notifyFollow(ctx, follow, followRequest.TargetAccount)
}
// processCreateAnnounceFromFederator handles Activity Create and Object Announce
@@ -180,6 +252,30 @@ func (p *processor) processCreateAnnounceFromFederator(ctx context.Context, fede
return errors.New("announce was not parseable as *gtsmodel.Status")
}
+ // make sure the account is pinned
+ if incomingAnnounce.Account == nil {
+ a, err := p.db.GetAccountByID(ctx, incomingAnnounce.AccountID)
+ if err != nil {
+ return err
+ }
+ incomingAnnounce.Account = a
+ }
+
+ // do a BLOCKING get of the remote account to make sure the avi and header are cached
+ if incomingAnnounce.Account.Domain != "" {
+ remoteAccountID, err := url.Parse(incomingAnnounce.Account.URI)
+ if err != nil {
+ return err
+ }
+
+ a, err := p.federator.GetRemoteAccount(ctx, federatorMsg.ReceivingAccount.Username, remoteAccountID, true, false)
+ if err != nil {
+ return err
+ }
+
+ incomingAnnounce.Account = a
+ }
+
if err := p.federator.DereferenceAnnounce(ctx, incomingAnnounce, federatorMsg.ReceivingAccount.Username); err != nil {
return fmt.Errorf("error dereferencing announce from federator: %s", err)
}
@@ -232,7 +328,12 @@ func (p *processor) processUpdateAccountFromFederator(ctx context.Context, feder
return errors.New("profile was not parseable as *gtsmodel.Account")
}
- if _, err := p.federator.EnrichRemoteAccount(ctx, federatorMsg.ReceivingAccount.Username, incomingAccount); err != nil {
+ incomingAccountURL, err := url.Parse(incomingAccount.URI)
+ if err != nil {
+ return err
+ }
+
+ if _, err := p.federator.GetRemoteAccount(ctx, federatorMsg.ReceivingAccount.Username, incomingAccountURL, false, true); err != nil {
return fmt.Errorf("error enriching updated account from federator: %s", err)
}
diff --git a/internal/processing/media/create.go b/internal/processing/media/create.go
index de15d3162..4047278eb 100644
--- a/internal/processing/media/create.go
+++ b/internal/processing/media/create.go
@@ -19,56 +19,39 @@
package media
import (
- "bytes"
"context"
- "errors"
"fmt"
"io"
- "time"
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
- "github.com/superseriousbusiness/gotosocial/internal/text"
+ "github.com/superseriousbusiness/gotosocial/internal/media"
)
func (p *processor) Create(ctx context.Context, account *gtsmodel.Account, form *apimodel.AttachmentRequest) (*apimodel.Attachment, error) {
- // open the attachment and extract the bytes from it
- f, err := form.File.Open()
- if err != nil {
- return nil, fmt.Errorf("error opening attachment: %s", err)
- }
- buf := new(bytes.Buffer)
- size, err := io.Copy(buf, f)
- if err != nil {
- return nil, fmt.Errorf("error reading attachment: %s", err)
- }
- if size == 0 {
- return nil, errors.New("could not read provided attachment: size 0 bytes")
+ data := func(innerCtx context.Context) (io.Reader, int, error) {
+ f, err := form.File.Open()
+ return f, int(form.File.Size), err
}
- // now parse the focus parameter
- focusx, focusy, err := parseFocus(form.Focus)
+ focusX, focusY, err := parseFocus(form.Focus)
if err != nil {
- return nil, fmt.Errorf("couldn't parse attachment focus: %s", err)
+ return nil, fmt.Errorf("could not parse focus value %s: %s", form.Focus, err)
}
- minAttachment := &gtsmodel.MediaAttachment{
- CreatedAt: time.Now(),
- UpdatedAt: time.Now(),
- AccountID: account.ID,
- Description: text.SanitizeCaption(form.Description),
- FileMeta: gtsmodel.FileMeta{
- Focus: gtsmodel.Focus{
- X: focusx,
- Y: focusy,
- },
- },
+ // process the media attachment and load it immediately
+ media, err := p.mediaManager.ProcessMedia(ctx, data, account.ID, &media.AdditionalMediaInfo{
+ Description: &form.Description,
+ FocusX: &focusX,
+ FocusY: &focusY,
+ })
+ if err != nil {
+ return nil, err
}
- // allow the mediaHandler to work its magic of processing the attachment bytes, and putting them in whatever storage backend we're using
- attachment, err := p.mediaHandler.ProcessAttachment(ctx, buf.Bytes(), minAttachment)
+ attachment, err := media.LoadAttachment(ctx)
if err != nil {
- return nil, fmt.Errorf("error reading attachment: %s", err)
+ return nil, err
}
// prepare the frontend representation now -- if there are any errors here at least we can bail without
@@ -78,10 +61,5 @@ func (p *processor) Create(ctx context.Context, account *gtsmodel.Account, form
return nil, fmt.Errorf("error parsing media attachment to frontend type: %s", err)
}
- // now we can confidently put the attachment in the database
- if err := p.db.Put(ctx, attachment); err != nil {
- return nil, fmt.Errorf("error storing media attachment in db: %s", err)
- }
-
return &apiAttachment, nil
}
diff --git a/internal/processing/media/media.go b/internal/processing/media/media.go
index 9e050fe84..3d4ae5009 100644
--- a/internal/processing/media/media.go
+++ b/internal/processing/media/media.go
@@ -43,16 +43,16 @@ type Processor interface {
type processor struct {
tc typeutils.TypeConverter
- mediaHandler media.Handler
+ mediaManager media.Manager
storage *kv.KVStore
db db.DB
}
// New returns a new media processor.
-func New(db db.DB, tc typeutils.TypeConverter, mediaHandler media.Handler, storage *kv.KVStore) Processor {
+func New(db db.DB, tc typeutils.TypeConverter, mediaManager media.Manager, storage *kv.KVStore) Processor {
return &processor{
tc: tc,
- mediaHandler: mediaHandler,
+ mediaManager: mediaManager,
storage: storage,
db: db,
}
diff --git a/internal/processing/processor.go b/internal/processing/processor.go
index 13fc08c26..46d17a160 100644
--- a/internal/processing/processor.go
+++ b/internal/processing/processor.go
@@ -96,7 +96,7 @@ type Processor interface {
AccountBlockRemove(ctx context.Context, authed *oauth.Auth, targetAccountID string) (*apimodel.Relationship, gtserror.WithCode)
// AdminEmojiCreate handles the creation of a new instance emoji by an admin, using the given form.
- AdminEmojiCreate(ctx context.Context, authed *oauth.Auth, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, error)
+ AdminEmojiCreate(ctx context.Context, authed *oauth.Auth, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, gtserror.WithCode)
// AdminDomainBlockCreate handles the creation of a new domain block by an admin, using the given form.
AdminDomainBlockCreate(ctx context.Context, authed *oauth.Auth, form *apimodel.DomainBlockCreateRequest) (*apimodel.DomainBlock, gtserror.WithCode)
// AdminDomainBlocksImport handles the import of multiple domain blocks by an admin, using the given form.
@@ -235,7 +235,7 @@ type processor struct {
stop chan interface{}
tc typeutils.TypeConverter
oauthServer oauth.Server
- mediaHandler media.Handler
+ mediaManager media.Manager
storage *kv.KVStore
statusTimelines timeline.Manager
db db.DB
@@ -259,7 +259,7 @@ func NewProcessor(
tc typeutils.TypeConverter,
federator federation.Federator,
oauthServer oauth.Server,
- mediaHandler media.Handler,
+ mediaManager media.Manager,
storage *kv.KVStore,
db db.DB,
emailSender email.Sender) Processor {
@@ -268,9 +268,9 @@ func NewProcessor(
statusProcessor := status.New(db, tc, fromClientAPI)
streamingProcessor := streaming.New(db, oauthServer)
- accountProcessor := account.New(db, tc, mediaHandler, oauthServer, fromClientAPI, federator)
- adminProcessor := admin.New(db, tc, mediaHandler, fromClientAPI)
- mediaProcessor := mediaProcessor.New(db, tc, mediaHandler, storage)
+ accountProcessor := account.New(db, tc, mediaManager, oauthServer, fromClientAPI, federator)
+ adminProcessor := admin.New(db, tc, mediaManager, fromClientAPI)
+ mediaProcessor := mediaProcessor.New(db, tc, mediaManager, storage)
userProcessor := user.New(db, emailSender)
federationProcessor := federationProcessor.New(db, tc, federator, fromFederator)
filter := visibility.NewFilter(db)
@@ -282,7 +282,7 @@ func NewProcessor(
stop: make(chan interface{}),
tc: tc,
oauthServer: oauthServer,
- mediaHandler: mediaHandler,
+ mediaManager: mediaManager,
storage: storage,
statusTimelines: timeline.NewManager(StatusGrabFunction(db), StatusFilterFunction(db, filter), StatusPrepareFunction(db, tc), StatusSkipInsertFunction()),
db: db,
diff --git a/internal/processing/processor_test.go b/internal/processing/processor_test.go
index 34b8f40bb..794bcc197 100644
--- a/internal/processing/processor_test.go
+++ b/internal/processing/processor_test.go
@@ -47,11 +47,11 @@ type ProcessingStandardTestSuite struct {
suite.Suite
db db.DB
storage *kv.KVStore
+ mediaManager media.Manager
typeconverter typeutils.TypeConverter
transportController transport.Controller
federator federation.Federator
oauthServer oauth.Server
- mediaHandler media.Handler
timelineManager timeline.Manager
emailSender email.Sender
@@ -216,12 +216,12 @@ func (suite *ProcessingStandardTestSuite) SetupTest() {
})
suite.transportController = testrig.NewTestTransportController(httpClient, suite.db)
- suite.federator = testrig.NewTestFederator(suite.db, suite.transportController, suite.storage)
+ suite.mediaManager = testrig.NewTestMediaManager(suite.db, suite.storage)
+ suite.federator = testrig.NewTestFederator(suite.db, suite.transportController, suite.storage, suite.mediaManager)
suite.oauthServer = testrig.NewTestOauthServer(suite.db)
- suite.mediaHandler = testrig.NewTestMediaHandler(suite.db, suite.storage)
suite.emailSender = testrig.NewEmailSender("../../web/template/", nil)
- suite.processor = processing.NewProcessor(suite.typeconverter, suite.federator, suite.oauthServer, suite.mediaHandler, suite.storage, suite.db, suite.emailSender)
+ suite.processor = processing.NewProcessor(suite.typeconverter, suite.federator, suite.oauthServer, suite.mediaManager, suite.storage, suite.db, suite.emailSender)
testrig.StandardDBSetup(suite.db, suite.testAccounts)
testrig.StandardStorageSetup(suite.storage, "../../testrig/media")
diff --git a/internal/processing/search.go b/internal/processing/search.go
index b03ced831..c8c302857 100644
--- a/internal/processing/search.go
+++ b/internal/processing/search.go
@@ -148,7 +148,7 @@ func (p *processor) searchAccountByURI(ctx context.Context, authed *oauth.Auth,
if resolve {
// we don't have it locally so try and dereference it
- account, _, err := p.federator.GetRemoteAccount(ctx, authed.Account.Username, uri, true)
+ account, err := p.federator.GetRemoteAccount(ctx, authed.Account.Username, uri, true, true)
if err != nil {
return nil, fmt.Errorf("searchAccountByURI: error dereferencing account with uri %s: %s", uri.String(), err)
}
@@ -203,7 +203,7 @@ func (p *processor) searchAccountByMention(ctx context.Context, authed *oauth.Au
}
// we don't have it locally so try and dereference it
- account, _, err := p.federator.GetRemoteAccount(ctx, authed.Account.Username, acctURI, true)
+ account, err := p.federator.GetRemoteAccount(ctx, authed.Account.Username, acctURI, true, true)
if err != nil {
return nil, fmt.Errorf("searchAccountByMention: error dereferencing account with uri %s: %s", acctURI.String(), err)
}