From 65cd1acbdf7c322d5788eb2c316c805a86306727 Mon Sep 17 00:00:00 2001 From: tobi <31960611+tsmethurst@users.noreply.github.com> Date: Tue, 9 May 2023 13:25:48 +0200 Subject: [PATCH] [chore] tidy + update StatusToAPIStatus (#1754) --- internal/db/bundb/status.go | 26 ++-- internal/typeutils/internaltofrontend.go | 159 ++++++++++------------- 2 files changed, 85 insertions(+), 100 deletions(-) diff --git a/internal/db/bundb/status.go b/internal/db/bundb/status.go index c2b5546f8..49d4f938b 100644 --- a/internal/db/bundb/status.go +++ b/internal/db/bundb/status.go @@ -27,6 +27,7 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/gtscontext" + "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/log" "github.com/superseriousbusiness/gotosocial/internal/state" @@ -127,7 +128,10 @@ func (s *statusDB) getStatus(ctx context.Context, lookup string, dbQuery func(*g } func (s *statusDB) PopulateStatus(ctx context.Context, status *gtsmodel.Status) error { - var err error + var ( + err error + errs = make(gtserror.MultiError, 0, 9) + ) if status.Account == nil { // Status author is not set, fetch from database. @@ -136,7 +140,7 @@ func (s *statusDB) PopulateStatus(ctx context.Context, status *gtsmodel.Status) status.AccountID, ) if err != nil { - return fmt.Errorf("error populating status author: %w", err) + errs.Append(fmt.Errorf("error populating status author: %w", err)) } } @@ -147,7 +151,7 @@ func (s *statusDB) PopulateStatus(ctx context.Context, status *gtsmodel.Status) status.InReplyToID, ) if err != nil { - return fmt.Errorf("error populating status parent: %w", err) + errs.Append(fmt.Errorf("error populating status parent: %w", err)) } } @@ -159,7 +163,7 @@ func (s *statusDB) PopulateStatus(ctx context.Context, status *gtsmodel.Status) status.InReplyToID, ) if err != nil { - return fmt.Errorf("error populating status parent: %w", err) + errs.Append(fmt.Errorf("error populating status parent: %w", err)) } } @@ -170,7 +174,7 @@ func (s *statusDB) PopulateStatus(ctx context.Context, status *gtsmodel.Status) status.InReplyToAccountID, ) if err != nil { - return fmt.Errorf("error populating status parent author: %w", err) + errs.Append(fmt.Errorf("error populating status parent author: %w", err)) } } } @@ -183,7 +187,7 @@ func (s *statusDB) PopulateStatus(ctx context.Context, status *gtsmodel.Status) status.BoostOfID, ) if err != nil { - return fmt.Errorf("error populating status boost: %w", err) + errs.Append(fmt.Errorf("error populating status boost: %w", err)) } } @@ -194,7 +198,7 @@ func (s *statusDB) PopulateStatus(ctx context.Context, status *gtsmodel.Status) status.BoostOfAccountID, ) if err != nil { - return fmt.Errorf("error populating status boost author: %w", err) + errs.Append(fmt.Errorf("error populating status boost author: %w", err)) } } } @@ -206,7 +210,7 @@ func (s *statusDB) PopulateStatus(ctx context.Context, status *gtsmodel.Status) status.AttachmentIDs, ) if err != nil { - return fmt.Errorf("error populating status attachments: %w", err) + errs.Append(fmt.Errorf("error populating status attachments: %w", err)) } } @@ -221,7 +225,7 @@ func (s *statusDB) PopulateStatus(ctx context.Context, status *gtsmodel.Status) status.MentionIDs, ) if err != nil { - return fmt.Errorf("error populating status mentions: %w", err) + errs.Append(fmt.Errorf("error populating status mentions: %w", err)) } } @@ -232,11 +236,11 @@ func (s *statusDB) PopulateStatus(ctx context.Context, status *gtsmodel.Status) status.EmojiIDs, ) if err != nil { - return fmt.Errorf("error populating status emojis: %w", err) + errs.Append(fmt.Errorf("error populating status emojis: %w", err)) } } - return nil + return errs.Combine() } func (s *statusDB) PutStatus(ctx context.Context, status *gtsmodel.Status) db.Error { diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go index 1e5fb024f..2b53cce48 100644 --- a/internal/typeutils/internaltofrontend.go +++ b/internal/typeutils/internaltofrontend.go @@ -559,100 +559,36 @@ func (c *converter) TagToAPITag(ctx context.Context, t *gtsmodel.Tag) (apimodel. } func (c *converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, requestingAccount *gtsmodel.Account) (*apimodel.Status, error) { - repliesCount, err := c.db.CountStatusReplies(ctx, s) - if err != nil { - return nil, fmt.Errorf("error counting replies: %s", err) - } - - reblogsCount, err := c.db.CountStatusReblogs(ctx, s) - if err != nil { - return nil, fmt.Errorf("error counting reblogs: %s", err) - } - - favesCount, err := c.db.CountStatusFaves(ctx, s) - if err != nil { - return nil, fmt.Errorf("error counting faves: %s", err) - } - - var apiRebloggedStatus *apimodel.Status - if s.BoostOfID != "" { - // the boosted status might have been set on this struct already so check first before doing db calls - if s.BoostOf == nil { - // it's not set so fetch it from the db - bs, err := c.db.GetStatusByID(ctx, s.BoostOfID) - if err != nil { - return nil, fmt.Errorf("error getting boosted status with id %s: %s", s.BoostOfID, err) - } - s.BoostOf = bs + if err := c.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) } - // the boosted account might have been set on this struct already or passed as a param so check first before doing db calls - if s.BoostOfAccount == nil { - // it's not set so fetch it from the db - ba, err := c.db.GetAccountByID(ctx, s.BoostOf.AccountID) - if err != nil { - return nil, fmt.Errorf("error getting boosted account %s from status with id %s: %s", s.BoostOf.AccountID, s.BoostOfID, err) - } - s.BoostOfAccount = ba - s.BoostOf.Account = ba - } - - apiRebloggedStatus, err = c.StatusToAPIStatus(ctx, s.BoostOf, requestingAccount) - if err != nil { - return nil, fmt.Errorf("error converting boosted status to apitype: %s", err) - } - } - - var apiApplication *apimodel.Application - if s.CreatedWithApplicationID != "" { - gtsApplication := >smodel.Application{} - if err := c.db.GetByID(ctx, s.CreatedWithApplicationID, gtsApplication); err != nil { - return nil, fmt.Errorf("error fetching application used to create status: %s", err) - } - apiApplication, err = c.AppToAPIAppPublic(ctx, gtsApplication) - if err != nil { - return nil, fmt.Errorf("error parsing application used to create status: %s", err) - } - } - - if s.Account == nil { - a, err := c.db.GetAccountByID(ctx, s.AccountID) - if err != nil { - return nil, fmt.Errorf("error getting status author: %s", err) - } - s.Account = a + log.Errorf(ctx, "error(s) populating status, will continue: %v", err) } apiAuthorAccount, err := c.AccountToAPIAccountPublic(ctx, s.Account) if err != nil { - return nil, fmt.Errorf("error parsing account of status author: %s", err) + return nil, fmt.Errorf("error converting status author: %w", err) } - // convert status gts model attachments to frontend api model attachments - apiAttachments, err := c.convertAttachmentsToAPIAttachments(ctx, s.Attachments, s.AttachmentIDs) + repliesCount, err := c.db.CountStatusReplies(ctx, s) if err != nil { - log.Errorf(ctx, "error converting status attachments: %v", err) + return nil, fmt.Errorf("error counting replies: %w", err) } - // convert status gts model mentions to frontend api model mentions - apiMentions, err := c.convertMentionsToAPIMentions(ctx, s.Mentions, s.MentionIDs) + reblogsCount, err := c.db.CountStatusReblogs(ctx, s) if err != nil { - log.Errorf(ctx, "error converting status mentions: %v", err) + return nil, fmt.Errorf("error counting reblogs: %w", err) } - // convert status gts model tags to frontend api model tags - apiTags, err := c.convertTagsToAPITags(ctx, s.Tags, s.TagIDs) + favesCount, err := c.db.CountStatusFaves(ctx, s) if err != nil { - log.Errorf(ctx, "error converting status tags: %v", err) + return nil, fmt.Errorf("error counting faves: %w", err) } - // convert status gts model emojis to frontend api model emojis - apiEmojis, err := c.convertEmojisToAPIEmojis(ctx, s.Emojis, s.EmojiIDs) - if err != nil { - log.Errorf(ctx, "error converting status emojis: %v", err) - } - - // Fetch status interaction flags for acccount interacts, err := c.interactionsWithStatusForAccount(ctx, s, requestingAccount) if err != nil { log.Errorf(ctx, "error getting interactions for status %s for account %s: %v", s.ID, requestingAccount.ID, err) @@ -661,9 +597,24 @@ func (c *converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, r interacts = &statusInteractions{} } - var language *string - if s.Language != "" { - language = &s.Language + apiAttachments, err := c.convertAttachmentsToAPIAttachments(ctx, s.Attachments, s.AttachmentIDs) + if err != nil { + log.Errorf(ctx, "error converting status attachments: %v", err) + } + + apiMentions, err := c.convertMentionsToAPIMentions(ctx, s.Mentions, s.MentionIDs) + if err != nil { + log.Errorf(ctx, "error converting status mentions: %v", err) + } + + apiTags, err := c.convertTagsToAPITags(ctx, s.Tags, s.TagIDs) + if err != nil { + log.Errorf(ctx, "error converting status tags: %v", err) + } + + apiEmojis, err := c.convertEmojisToAPIEmojis(ctx, s.Emojis, s.EmojiIDs) + if err != nil { + log.Errorf(ctx, "error converting status emojis: %v", err) } apiStatus := &apimodel.Status{ @@ -674,7 +625,7 @@ func (c *converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, r Sensitive: *s.Sensitive, SpoilerText: s.ContentWarning, Visibility: c.VisToAPIVis(ctx, s.Visibility), - Language: language, + Language: nil, URI: s.URI, URL: s.URL, RepliesCount: repliesCount, @@ -687,7 +638,7 @@ func (c *converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, r Pinned: interacts.Pinned, Content: s.Content, Reblog: nil, - Application: apiApplication, + Application: nil, Account: apiAuthorAccount, MediaAttachments: apiAttachments, Mentions: apiMentions, @@ -698,19 +649,49 @@ func (c *converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, r Text: s.Text, } - // nullable fields + // Nullable fields. + if s.InReplyToID != "" { - i := s.InReplyToID - apiStatus.InReplyToID = &i + apiStatus.InReplyToID = func() *string { i := s.InReplyToID; return &i }() } if s.InReplyToAccountID != "" { - i := s.InReplyToAccountID - apiStatus.InReplyToAccountID = &i + apiStatus.InReplyToAccountID = func() *string { i := s.InReplyToAccountID; return &i }() } - if apiRebloggedStatus != nil { - apiStatus.Reblog = &apimodel.StatusReblogged{Status: apiRebloggedStatus} + if s.Language != "" { + apiStatus.Language = func() *string { i := s.Language; return &i }() + } + + 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) + } + + apiStatus.Reblog = &apimodel.StatusReblogged{Status: apiBoostOf} + } + + if appID := s.CreatedWithApplicationID; appID != "" { + app := >smodel.Application{} + if err := c.db.GetByID(ctx, appID, app); err != nil { + return nil, fmt.Errorf("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) + } + + apiStatus.Application = apiApp + } + + // Normalization. + + if s.URL == "" { + // URL was empty for some reason; + // provide AP URI as fallback. + s.URL = s.URI } return apiStatus, nil