diff options
author | 2024-06-06 14:35:50 +0000 | |
---|---|---|
committer | 2024-06-06 15:35:50 +0100 | |
commit | b371c2db47a6c93fbea1b06b56eecb7237bc6130 (patch) | |
tree | cb351547a11e2bd722272ef9f1e4cc84ee88569c /internal/federation/dereferencing/util.go | |
parent | [feature] Self-serve email change for users (#2957) (diff) | |
download | gotosocial-b371c2db47a6c93fbea1b06b56eecb7237bc6130.tar.xz |
[bugfix] update media if more than just url changes (#2970)
* refactor status media handling into separate functions, handle case of changed metadata
* update fetchRemoteAccount{Avatar,Header} to use new refactored {load,update}Attachment() functions
* whoops, nearly marked avatars as headers :')
* reformatting to improve legibility
Diffstat (limited to 'internal/federation/dereferencing/util.go')
-rw-r--r-- | internal/federation/dereferencing/util.go | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/internal/federation/dereferencing/util.go b/internal/federation/dereferencing/util.go index 38622f6c1..5cb7a0106 100644 --- a/internal/federation/dereferencing/util.go +++ b/internal/federation/dereferencing/util.go @@ -18,11 +18,122 @@ package dereferencing import ( + "context" + "io" + "net/url" "slices" + "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + "github.com/superseriousbusiness/gotosocial/internal/media" + "github.com/superseriousbusiness/gotosocial/internal/transport" + "github.com/superseriousbusiness/gotosocial/internal/util" ) +// loadAttachment handles the case of a new media attachment +// that requires loading. it stores and caches from given data. +func (d *Dereferencer) loadAttachment( + ctx context.Context, + tsport transport.Transport, + accountID string, // media account owner + remoteURL string, + info *media.AdditionalMediaInfo, +) ( + *gtsmodel.MediaAttachment, + error, +) { + // Parse str as valid URL object. + url, err := url.Parse(remoteURL) + if err != nil { + return nil, gtserror.Newf("invalid remote media url %q: %v", remoteURL, err) + } + + // Start pre-processing remote media at remote URL. + processing := d.mediaManager.PreProcessMedia( + func(ctx context.Context) (io.ReadCloser, int64, error) { + return tsport.DereferenceMedia(ctx, url) + }, + accountID, + info, + ) + + // Force attachment loading *right now*. + return processing.LoadAttachment(ctx) +} + +// updateAttachment handles the case of an existing media attachment +// that *may* have changes or need recaching. it checks for changed +// fields, updating in the database if so, and recaches uncached media. +func (d *Dereferencer) updateAttachment( + ctx context.Context, + tsport transport.Transport, + existing *gtsmodel.MediaAttachment, // existing attachment + media *gtsmodel.MediaAttachment, // (optional) changed media +) ( + *gtsmodel.MediaAttachment, // always set + error, +) { + if media != nil { + // Possible changed media columns. + changed := make([]string, 0, 3) + + // Check if attachment description has changed. + if existing.Description != media.Description { + changed = append(changed, "description") + existing.Description = media.Description + } + + // Check if attachment blurhash has changed (i.e. content change). + if existing.Blurhash != media.Blurhash && media.Blurhash != "" { + changed = append(changed, "blurhash", "cached") + existing.Blurhash = media.Blurhash + existing.Cached = util.Ptr(false) + } + + if len(changed) > 0 { + // Update the existing attachment model in the database. + err := d.state.DB.UpdateAttachment(ctx, existing, changed...) + if err != nil { + return media, gtserror.Newf("error updating media: %w", err) + } + } + } + + // Check if cached. + if *existing.Cached { + return existing, nil + } + + // Parse str as valid URL object. + url, err := url.Parse(existing.RemoteURL) + if err != nil { + return nil, gtserror.Newf("invalid remote media url %q: %v", media.RemoteURL, err) + } + + // Start pre-processing remote media recaching from remote. + processing, err := d.mediaManager.PreProcessMediaRecache( + ctx, + func(ctx context.Context) (io.ReadCloser, int64, error) { + return tsport.DereferenceMedia(ctx, url) + }, + existing.ID, + ) + if err != nil { + return nil, gtserror.Newf("error processing recache: %w", err) + } + + // Force load attachment recache *right now*. + recached, err := processing.LoadAttachment(ctx) + + // Always return the error we + // receive, but ensure we return + // most up-to-date media file. + if recached != nil { + return recached, err + } + return existing, err +} + // pollChanged returns whether a poll has changed in way that // indicates that this should be an entirely new poll. i.e. if // the available options have changed, or the expiry has increased. |