diff options
Diffstat (limited to 'internal/typeutils/internaltofrontend.go')
-rw-r--r-- | internal/typeutils/internaltofrontend.go | 105 |
1 files changed, 78 insertions, 27 deletions
diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go index d5a1dee32..a7bcddac6 100644 --- a/internal/typeutils/internaltofrontend.go +++ b/internal/typeutils/internaltofrontend.go @@ -434,11 +434,14 @@ func (c *Converter) AppToAPIAppPublic(ctx context.Context, a *gtsmodel.Applicati // AttachmentToAPIAttachment converts a gts model media attacahment into its api representation for serialization on the API. func (c *Converter) AttachmentToAPIAttachment(ctx context.Context, a *gtsmodel.MediaAttachment) (apimodel.Attachment, error) { apiAttachment := apimodel.Attachment{ - ID: a.ID, - Type: strings.ToLower(string(a.Type)), - TextURL: a.URL, - PreviewURL: a.Thumbnail.URL, - Meta: apimodel.MediaMeta{ + ID: a.ID, + Type: strings.ToLower(string(a.Type)), + } + + // Don't try to serialize meta for + // unknown attachments, there's no point. + if a.Type != gtsmodel.FileTypeUnknown { + apiAttachment.Meta = &apimodel.MediaMeta{ Original: apimodel.MediaDimensions{ Width: a.FileMeta.Original.Width, Height: a.FileMeta.Original.Height, @@ -449,13 +452,20 @@ func (c *Converter) AttachmentToAPIAttachment(ctx context.Context, a *gtsmodel.M Size: strconv.Itoa(a.FileMeta.Small.Width) + "x" + strconv.Itoa(a.FileMeta.Small.Height), Aspect: float32(a.FileMeta.Small.Aspect), }, - }, - Blurhash: a.Blurhash, + } + } + + if i := a.Blurhash; i != "" { + apiAttachment.Blurhash = &i } - // nullable fields if i := a.URL; i != "" { apiAttachment.URL = &i + apiAttachment.TextURL = &i + } + + if i := a.Thumbnail.URL; i != "" { + apiAttachment.PreviewURL = &i } if i := a.RemoteURL; i != "" { @@ -470,8 +480,9 @@ func (c *Converter) AttachmentToAPIAttachment(ctx context.Context, a *gtsmodel.M apiAttachment.Description = &i } - // type specific fields + // Type-specific fields. switch a.Type { + case gtsmodel.FileTypeImage: apiAttachment.Meta.Original.Size = strconv.Itoa(a.FileMeta.Original.Width) + "x" + strconv.Itoa(a.FileMeta.Original.Height) apiAttachment.Meta.Original.Aspect = float32(a.FileMeta.Original.Aspect) @@ -479,16 +490,17 @@ func (c *Converter) AttachmentToAPIAttachment(ctx context.Context, a *gtsmodel.M X: a.FileMeta.Focus.X, Y: a.FileMeta.Focus.Y, } + case gtsmodel.FileTypeVideo: if i := a.FileMeta.Original.Duration; i != nil { apiAttachment.Meta.Original.Duration = *i } if i := a.FileMeta.Original.Framerate; i != nil { - // the masto api expects this as a string in - // the format `integer/1`, so 30fps is `30/1` + // The masto api expects this as a string in + // the format `integer/1`, so 30fps is `30/1`. round := math.Round(float64(*i)) - fr := strconv.FormatInt(int64(round), 10) + fr := strconv.Itoa(int(round)) apiAttachment.Meta.Original.FrameRate = fr + "/1" } @@ -599,7 +611,7 @@ func (c *Converter) EmojiCategoryToAPIEmojiCategory(ctx context.Context, categor func (c *Converter) TagToAPITag(ctx context.Context, t *gtsmodel.Tag, stubHistory bool) (apimodel.Tag, error) { return apimodel.Tag{ Name: strings.ToLower(t.Name), - URL: uris.GenerateURIForTag(t.Name), + URL: uris.URIForTag(t.Name), History: func() *[]any { if !stubHistory { return nil @@ -611,15 +623,56 @@ func (c *Converter) TagToAPITag(ctx context.Context, t *gtsmodel.Tag, stubHistor }, nil } -// StatusToAPIStatus converts a gts model status into its api (frontend) representation for serialization on the API. +// StatusToAPIStatus converts a gts model status into its api +// (frontend) representation for serialization on the API. +// +// Requesting account can be nil. +func (c *Converter) StatusToAPIStatus( + ctx context.Context, + s *gtsmodel.Status, + requestingAccount *gtsmodel.Account, +) (*apimodel.Status, error) { + apiStatus, err := c.statusToFrontend(ctx, s, requestingAccount) + if err != nil { + return nil, err + } + + // Normalize status for the API by pruning + // out unknown attachment types and replacing + // them with a helpful message. + var aside string + aside, apiStatus.MediaAttachments = placeholdUnknownAttachments(apiStatus.MediaAttachments) + apiStatus.Content += aside + + return apiStatus, nil +} + +// StatusToWebStatus converts a gts model status into an +// api representation suitable for serving into a web template. // // Requesting account can be nil. -func (c *Converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, requestingAccount *gtsmodel.Account) (*apimodel.Status, error) { +func (c *Converter) StatusToWebStatus( + ctx context.Context, + s *gtsmodel.Status, + requestingAccount *gtsmodel.Account, +) (*apimodel.Status, error) { + return c.statusToFrontend(ctx, s, requestingAccount) +} + +// statusToFrontend is a package internal function for +// parsing a status into its initial frontend representation. +// +// Requesting account can be nil. +func (c *Converter) statusToFrontend( + ctx context.Context, + s *gtsmodel.Status, + requestingAccount *gtsmodel.Account, +) (*apimodel.Status, error) { if err := c.state.DB.PopulateStatus(ctx, s); err != nil { // Ensure author account present + correct; // can't really go further without this! if s.Account == nil { - return nil, fmt.Errorf("error(s) populating status, cannot continue: %w", err) + return nil, gtserror.Newf("error(s) populating status, cannot continue: %w", err) } log.Errorf(ctx, "error(s) populating status, will continue: %v", err) @@ -627,22 +680,22 @@ func (c *Converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, r apiAuthorAccount, err := c.AccountToAPIAccountPublic(ctx, s.Account) if err != nil { - return nil, fmt.Errorf("error converting status author: %w", err) + return nil, gtserror.Newf("error converting status author: %w", err) } repliesCount, err := c.state.DB.CountStatusReplies(ctx, s.ID) if err != nil { - return nil, fmt.Errorf("error counting replies: %w", err) + return nil, gtserror.Newf("error counting replies: %w", err) } reblogsCount, err := c.state.DB.CountStatusBoosts(ctx, s.ID) if err != nil { - return nil, fmt.Errorf("error counting reblogs: %w", err) + return nil, gtserror.Newf("error counting reblogs: %w", err) } favesCount, err := c.state.DB.CountStatusFaves(ctx, s.ID) if err != nil { - return nil, fmt.Errorf("error counting faves: %w", err) + return nil, gtserror.Newf("error counting faves: %w", err) } interacts, err := c.interactionsWithStatusForAccount(ctx, s, requestingAccount) @@ -722,7 +775,7 @@ func (c *Converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, r if s.BoostOf != nil { apiBoostOf, err := c.StatusToAPIStatus(ctx, s.BoostOf, requestingAccount) if err != nil { - return nil, fmt.Errorf("error converting boosted status: %w", err) + return nil, gtserror.Newf("error converting boosted status: %w", err) } apiStatus.Reblog = &apimodel.StatusReblogged{Status: apiBoostOf} @@ -733,13 +786,13 @@ func (c *Converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, r if app == nil { app, err = c.state.DB.GetApplicationByID(ctx, appID) if err != nil { - return nil, fmt.Errorf("error getting application %s: %w", appID, err) + return nil, gtserror.Newf("error getting application %s: %w", appID, err) } } apiApp, err := c.AppToAPIAppPublic(ctx, app) if err != nil { - return nil, fmt.Errorf("error converting application %s: %w", appID, err) + return nil, gtserror.Newf("error converting application %s: %w", appID, err) } apiStatus.Application = apiApp @@ -757,11 +810,9 @@ func (c *Converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, r } } - // Normalization. - + // If web URL is empty for whatever + // reason, provide AP URI as fallback. if s.URL == "" { - // URL was empty for some reason; - // provide AP URI as fallback. s.URL = s.URI } |