2023-03-12 16:00:57 +01:00
|
|
|
// GoToSocial
|
|
|
|
// Copyright (C) GoToSocial Authors admin@gotosocial.org
|
|
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Affero General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2021-07-05 13:23:03 +02:00
|
|
|
|
|
|
|
package account
|
|
|
|
|
|
|
|
import (
|
2021-08-25 15:34:33 +02:00
|
|
|
"context"
|
2023-03-20 19:10:08 +01:00
|
|
|
"errors"
|
2021-07-05 13:23:03 +02:00
|
|
|
|
2025-04-26 15:34:10 +02:00
|
|
|
"code.superseriousbusiness.org/gotosocial/internal/ap"
|
|
|
|
apimodel "code.superseriousbusiness.org/gotosocial/internal/api/model"
|
|
|
|
"code.superseriousbusiness.org/gotosocial/internal/db"
|
|
|
|
"code.superseriousbusiness.org/gotosocial/internal/gtscontext"
|
|
|
|
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
|
|
|
|
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
|
|
|
|
"code.superseriousbusiness.org/gotosocial/internal/id"
|
|
|
|
"code.superseriousbusiness.org/gotosocial/internal/messages"
|
|
|
|
"code.superseriousbusiness.org/gotosocial/internal/uris"
|
|
|
|
"code.superseriousbusiness.org/gotosocial/internal/util"
|
2021-07-05 13:23:03 +02:00
|
|
|
)
|
|
|
|
|
2023-02-22 16:05:26 +01:00
|
|
|
// FollowCreate handles a follow request to an account, either remote or local.
|
|
|
|
func (p *Processor) FollowCreate(ctx context.Context, requestingAccount *gtsmodel.Account, form *apimodel.AccountFollowRequest) (*apimodel.Relationship, gtserror.WithCode) {
|
2023-09-12 14:00:35 +01:00
|
|
|
targetAccount, errWithCode := p.getFollowTarget(ctx, requestingAccount, form.ID)
|
2023-03-20 19:10:08 +01:00
|
|
|
if errWithCode != nil {
|
|
|
|
return nil, errWithCode
|
2021-07-05 13:23:03 +02:00
|
|
|
}
|
|
|
|
|
2023-03-20 19:10:08 +01:00
|
|
|
// Check if a follow exists already.
|
2023-04-10 21:56:02 +02:00
|
|
|
if follow, err := p.state.DB.GetFollow(
|
|
|
|
gtscontext.SetBarebones(ctx),
|
|
|
|
requestingAccount.ID,
|
|
|
|
targetAccount.ID,
|
|
|
|
); err != nil && !errors.Is(err, db.ErrNoEntries) {
|
2023-09-12 14:00:35 +01:00
|
|
|
err = gtserror.Newf("db error checking existing follow: %w", err)
|
2021-08-20 12:26:56 +02:00
|
|
|
return nil, gtserror.NewErrorInternalError(err)
|
2023-04-10 21:56:02 +02:00
|
|
|
} else if follow != nil {
|
|
|
|
// Already follows, update if necessary + return relationship.
|
|
|
|
return p.updateFollow(
|
|
|
|
ctx,
|
|
|
|
requestingAccount,
|
|
|
|
form,
|
|
|
|
follow.ShowReblogs,
|
|
|
|
follow.Notify,
|
|
|
|
func(columns ...string) error { return p.state.DB.UpdateFollow(ctx, follow, columns...) },
|
|
|
|
)
|
2021-07-05 13:23:03 +02:00
|
|
|
}
|
|
|
|
|
2023-03-20 19:10:08 +01:00
|
|
|
// Check if a follow request exists already.
|
2023-04-10 21:56:02 +02:00
|
|
|
if followRequest, err := p.state.DB.GetFollowRequest(
|
|
|
|
gtscontext.SetBarebones(ctx),
|
|
|
|
requestingAccount.ID,
|
|
|
|
targetAccount.ID,
|
|
|
|
); err != nil && !errors.Is(err, db.ErrNoEntries) {
|
2023-09-12 14:00:35 +01:00
|
|
|
err = gtserror.Newf("db error checking existing follow request: %w", err)
|
2023-03-20 19:10:08 +01:00
|
|
|
return nil, gtserror.NewErrorInternalError(err)
|
2023-04-10 21:56:02 +02:00
|
|
|
} else if followRequest != nil {
|
|
|
|
// Already requested, update if necessary + return relationship.
|
|
|
|
return p.updateFollow(
|
|
|
|
ctx,
|
|
|
|
requestingAccount,
|
|
|
|
form,
|
|
|
|
followRequest.ShowReblogs,
|
|
|
|
followRequest.Notify,
|
|
|
|
func(columns ...string) error { return p.state.DB.UpdateFollowRequest(ctx, followRequest, columns...) },
|
|
|
|
)
|
2021-07-05 13:23:03 +02:00
|
|
|
}
|
|
|
|
|
2023-04-10 21:56:02 +02:00
|
|
|
// Neither follows nor follow requests, so
|
|
|
|
// create and store a new follow request.
|
[feature] Support new model of interaction flow for forward compat with v0.21.0 (#4394)
~~Still WIP!~~
This PR allows v0.20.0 of GtS to be forward-compatible with the interaction request / authorization flow that will fully replace the current flow in v0.21.0.
Basically, this means we need to recognize LikeRequest, ReplyRequest, and AnnounceRequest, and in response to those requests, deliver either a Reject or an Accept, with the latter pointing towards a LikeAuthorization, ReplyAuthorization, or AnnounceAuthorization, respectively. This can then be used by the remote instance to prove to third parties that the interaction has been accepted by the interactee. These Authorization types need to be dereferencable to third parties, so we need to serve them.
As well as recognizing the above "polite" interaction request types, we also need to still serve appropriate responses to "impolite" interaction request types, where an instance that's unaware of interaction policies tries to interact with a post by sending a reply, like, or boost directly, without wrapping it in a WhateverRequest type.
Doesn't fully close https://codeberg.org/superseriousbusiness/gotosocial/issues/4026 but gets damn near (just gotta update the federating with GtS documentation).
Migrations tested on both Postgres and SQLite.
Co-authored-by: kim <grufwub@gmail.com>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4394
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
2025-09-14 15:37:35 +02:00
|
|
|
followID := id.NewRandomULID()
|
2023-03-20 19:10:08 +01:00
|
|
|
followURI := uris.GenerateURIForFollow(requestingAccount.Username, followID)
|
2021-07-05 13:23:03 +02:00
|
|
|
|
|
|
|
fr := >smodel.FollowRequest{
|
2023-03-20 19:10:08 +01:00
|
|
|
ID: followID,
|
|
|
|
URI: followURI,
|
2021-07-05 13:23:03 +02:00
|
|
|
AccountID: requestingAccount.ID,
|
2023-03-20 19:10:08 +01:00
|
|
|
Account: requestingAccount,
|
2021-08-02 19:06:44 +02:00
|
|
|
TargetAccountID: form.ID,
|
2023-03-20 19:10:08 +01:00
|
|
|
TargetAccount: targetAccount,
|
|
|
|
ShowReblogs: form.Reblogs,
|
|
|
|
Notify: form.Notify,
|
2021-07-05 13:23:03 +02:00
|
|
|
}
|
|
|
|
|
2024-06-12 14:23:10 +02:00
|
|
|
// Insert the new follow request.
|
[performance] refactoring + add fave / follow / request / visibility caching (#1607)
* refactor visibility checking, add caching for visibility
* invalidate visibility cache items on account / status deletes
* fix requester ID passed to visibility cache nil ptr
* de-interface caches, fix home / public timeline caching + visibility
* finish adding code comments for visibility filter
* fix angry goconst linter warnings
* actually finish adding filter visibility code comments for timeline functions
* move home timeline status author check to after visibility
* remove now-unused code
* add more code comments
* add TODO code comment, update printed cache start names
* update printed cache names on stop
* start adding separate follow(request) delete db functions, add specific visibility cache tests
* add relationship type caching
* fix getting local account follows / followed-bys, other small codebase improvements
* simplify invalidation using cache hooks, add more GetAccountBy___() functions
* fix boosting to return 404 if not boostable but no error (to not leak status ID)
* remove dead code
* improved placement of cache invalidation
* update license headers
* add example follow, follow-request config entries
* add example visibility cache configuration to config file
* use specific PutFollowRequest() instead of just Put()
* add tests for all GetAccountBy()
* add GetBlockBy() tests
* update block to check primitive fields
* update and finish adding Get{Account,Block,Follow,FollowRequest}By() tests
* fix copy-pasted code
* update envparsing test
* whitespace
* fix bun struct tag
* add license header to gtscontext
* fix old license header
* improved error creation to not use fmt.Errorf() when not needed
* fix various rebase conflicts, fix account test
* remove commented-out code, fix-up mention caching
* fix mention select bun statement
* ensure mention target account populated, pass in context to customrenderer logging
* remove more uncommented code, fix typeutil test
* add statusfave database model caching
* add status fave cache configuration
* add status fave cache example config
* woops, catch missed error. nice catch linter!
* add back testrig panic on nil db
* update example configuration to match defaults, slight tweak to cache configuration defaults
* update envparsing test with new defaults
* fetch followingget to use the follow target account
* use accounnt.IsLocal() instead of empty domain check
* use constants for the cache visibility type check
* use bun.In() for notification type restriction in db query
* include replies when fetching PublicTimeline() (to account for single-author threads in Visibility{}.StatusPublicTimelineable())
* use bun query building for nested select statements to ensure working with postgres
* update public timeline future status checks to match visibility filter
* same as previous, for home timeline
* update public timeline tests to dynamically check for appropriate statuses
* migrate accounts to allow unique constraint on public_key
* provide minimal account with publicKey
---------
Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
2023-03-28 14:03:14 +01:00
|
|
|
if err := p.state.DB.PutFollowRequest(ctx, fr); err != nil {
|
2023-09-12 14:00:35 +01:00
|
|
|
err = gtserror.Newf("error creating follow request in db: %s", err)
|
2023-03-20 19:10:08 +01:00
|
|
|
return nil, gtserror.NewErrorInternalError(err)
|
2021-07-05 13:23:03 +02:00
|
|
|
}
|
|
|
|
|
2024-06-12 14:23:10 +02:00
|
|
|
// And get the new relationship state.
|
|
|
|
rel, errWithCode := p.RelationshipGet(ctx, requestingAccount, form.ID)
|
|
|
|
if errWithCode != nil {
|
|
|
|
return nil, errWithCode
|
|
|
|
}
|
|
|
|
|
|
|
|
// For unlocked accounts on the same instance,
|
|
|
|
// we can already optimistically show the follow
|
|
|
|
// request as accepted in the returned relationship.
|
2023-03-20 19:10:08 +01:00
|
|
|
if targetAccount.IsLocal() && !*targetAccount.Locked {
|
2024-06-12 14:23:10 +02:00
|
|
|
rel.Requested = false
|
|
|
|
rel.Following = true
|
2024-07-17 15:26:33 +00:00
|
|
|
rel.ShowingReblogs = util.PtrOrValue(fr.ShowReblogs, true)
|
|
|
|
rel.Notifying = util.PtrOrValue(fr.Notify, false)
|
2021-07-05 13:23:03 +02:00
|
|
|
}
|
|
|
|
|
2024-06-12 14:23:10 +02:00
|
|
|
// Handle side effects async.
|
|
|
|
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
|
|
|
APObjectType: ap.ActivityFollow,
|
|
|
|
APActivityType: ap.ActivityCreate,
|
|
|
|
GTSModel: fr,
|
|
|
|
Origin: requestingAccount,
|
|
|
|
Target: targetAccount,
|
|
|
|
})
|
|
|
|
|
|
|
|
return rel, nil
|
2021-07-05 13:23:03 +02:00
|
|
|
}
|
2023-02-22 16:05:26 +01:00
|
|
|
|
|
|
|
// FollowRemove handles the removal of a follow/follow request to an account, either remote or local.
|
|
|
|
func (p *Processor) FollowRemove(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Relationship, gtserror.WithCode) {
|
2023-09-12 14:00:35 +01:00
|
|
|
targetAccount, errWithCode := p.getFollowTarget(ctx, requestingAccount, targetAccountID)
|
2023-03-20 19:10:08 +01:00
|
|
|
if errWithCode != nil {
|
|
|
|
return nil, errWithCode
|
2023-02-22 16:05:26 +01:00
|
|
|
}
|
|
|
|
|
2023-03-20 19:10:08 +01:00
|
|
|
// Unfollow and deal with side effects.
|
|
|
|
msgs, err := p.unfollow(ctx, requestingAccount, targetAccount)
|
2023-02-22 16:05:26 +01:00
|
|
|
if err != nil {
|
2023-09-12 14:00:35 +01:00
|
|
|
return nil, gtserror.NewErrorNotFound(gtserror.Newf("account %s not found in the db: %s", targetAccountID, err))
|
2023-02-22 16:05:26 +01:00
|
|
|
}
|
|
|
|
|
2023-03-20 19:10:08 +01:00
|
|
|
// Batch queue accreted client api messages.
|
2024-04-26 13:50:46 +01:00
|
|
|
p.state.Workers.Client.Queue.Push(msgs...)
|
2023-03-20 19:10:08 +01:00
|
|
|
|
|
|
|
return p.RelationshipGet(ctx, requestingAccount, targetAccountID)
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Utility functions.
|
|
|
|
*/
|
|
|
|
|
2023-04-10 21:56:02 +02:00
|
|
|
// updateFollow is a utility function for updating an existing
|
|
|
|
// follow or followRequest with the parameters provided in the
|
|
|
|
// given form. If nothing changes, this function is a no-op and
|
|
|
|
// will just return the existing relationship between follow
|
|
|
|
// origin and follow target account.
|
|
|
|
func (p *Processor) updateFollow(
|
|
|
|
ctx context.Context,
|
|
|
|
requestingAccount *gtsmodel.Account,
|
|
|
|
form *apimodel.AccountFollowRequest,
|
|
|
|
currentShowReblogs *bool,
|
|
|
|
currentNotify *bool,
|
|
|
|
update func(...string) error,
|
|
|
|
) (*apimodel.Relationship, gtserror.WithCode) {
|
|
|
|
if form.Reblogs == nil && form.Notify == nil {
|
|
|
|
// There's nothing to update.
|
|
|
|
return p.RelationshipGet(ctx, requestingAccount, form.ID)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Including "updated_at", max 3 columns may change.
|
|
|
|
columns := make([]string, 0, 3)
|
|
|
|
|
|
|
|
// Check what we need to update (if anything).
|
|
|
|
if newReblogs := form.Reblogs; newReblogs != nil && *newReblogs != *currentShowReblogs {
|
|
|
|
*currentShowReblogs = *newReblogs
|
|
|
|
columns = append(columns, "show_reblogs")
|
|
|
|
}
|
|
|
|
|
|
|
|
if newNotify := form.Notify; newNotify != nil && *newNotify != *currentNotify {
|
|
|
|
*currentNotify = *newNotify
|
|
|
|
columns = append(columns, "notify")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(columns) == 0 {
|
|
|
|
// Nothing actually changed.
|
|
|
|
return p.RelationshipGet(ctx, requestingAccount, form.ID)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := update(columns...); err != nil {
|
2023-09-12 14:00:35 +01:00
|
|
|
err = gtserror.Newf("error updating existing follow (request): %w", err)
|
2023-04-10 21:56:02 +02:00
|
|
|
return nil, gtserror.NewErrorInternalError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return p.RelationshipGet(ctx, requestingAccount, form.ID)
|
|
|
|
}
|
|
|
|
|
2023-03-20 19:10:08 +01:00
|
|
|
// getFollowTarget is a convenience function which:
|
|
|
|
// - Checks if account is trying to follow/unfollow itself.
|
2023-09-12 14:00:35 +01:00
|
|
|
// - Returns not found if target should not be visible to requester.
|
2023-03-20 19:10:08 +01:00
|
|
|
// - Returns target account according to its id.
|
2023-09-12 14:00:35 +01:00
|
|
|
func (p *Processor) getFollowTarget(ctx context.Context, requester *gtsmodel.Account, targetID string) (*gtsmodel.Account, gtserror.WithCode) {
|
|
|
|
// Check for requester.
|
|
|
|
if requester == nil {
|
|
|
|
err := errors.New("no authorized user")
|
|
|
|
return nil, gtserror.NewErrorUnauthorized(err)
|
|
|
|
}
|
|
|
|
|
2023-03-20 19:10:08 +01:00
|
|
|
// Account can't follow or unfollow itself.
|
2023-09-12 14:00:35 +01:00
|
|
|
if requester.ID == targetID {
|
2023-03-20 19:10:08 +01:00
|
|
|
err := errors.New("account can't follow or unfollow itself")
|
|
|
|
return nil, gtserror.NewErrorNotAcceptable(err)
|
2023-02-22 16:05:26 +01:00
|
|
|
}
|
|
|
|
|
2023-09-12 14:00:35 +01:00
|
|
|
// Fetch the target account for requesting user account.
|
|
|
|
return p.c.GetVisibleTargetAccount(ctx, requester, targetID)
|
2023-03-20 19:10:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// unfollow is a convenience function for having requesting account
|
|
|
|
// unfollow (and un follow request) target account, if follows and/or
|
|
|
|
// follow requests exist.
|
|
|
|
//
|
|
|
|
// If a follow and/or follow request was removed this way, one or two
|
|
|
|
// messages will be returned which should then be processed by a client
|
|
|
|
// api worker.
|
2024-04-26 13:50:46 +01:00
|
|
|
func (p *Processor) unfollow(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccount *gtsmodel.Account) ([]*messages.FromClientAPI, error) {
|
|
|
|
var msgs []*messages.FromClientAPI
|
2023-03-20 19:10:08 +01:00
|
|
|
|
[performance] refactoring + add fave / follow / request / visibility caching (#1607)
* refactor visibility checking, add caching for visibility
* invalidate visibility cache items on account / status deletes
* fix requester ID passed to visibility cache nil ptr
* de-interface caches, fix home / public timeline caching + visibility
* finish adding code comments for visibility filter
* fix angry goconst linter warnings
* actually finish adding filter visibility code comments for timeline functions
* move home timeline status author check to after visibility
* remove now-unused code
* add more code comments
* add TODO code comment, update printed cache start names
* update printed cache names on stop
* start adding separate follow(request) delete db functions, add specific visibility cache tests
* add relationship type caching
* fix getting local account follows / followed-bys, other small codebase improvements
* simplify invalidation using cache hooks, add more GetAccountBy___() functions
* fix boosting to return 404 if not boostable but no error (to not leak status ID)
* remove dead code
* improved placement of cache invalidation
* update license headers
* add example follow, follow-request config entries
* add example visibility cache configuration to config file
* use specific PutFollowRequest() instead of just Put()
* add tests for all GetAccountBy()
* add GetBlockBy() tests
* update block to check primitive fields
* update and finish adding Get{Account,Block,Follow,FollowRequest}By() tests
* fix copy-pasted code
* update envparsing test
* whitespace
* fix bun struct tag
* add license header to gtscontext
* fix old license header
* improved error creation to not use fmt.Errorf() when not needed
* fix various rebase conflicts, fix account test
* remove commented-out code, fix-up mention caching
* fix mention select bun statement
* ensure mention target account populated, pass in context to customrenderer logging
* remove more uncommented code, fix typeutil test
* add statusfave database model caching
* add status fave cache configuration
* add status fave cache example config
* woops, catch missed error. nice catch linter!
* add back testrig panic on nil db
* update example configuration to match defaults, slight tweak to cache configuration defaults
* update envparsing test with new defaults
* fetch followingget to use the follow target account
* use accounnt.IsLocal() instead of empty domain check
* use constants for the cache visibility type check
* use bun.In() for notification type restriction in db query
* include replies when fetching PublicTimeline() (to account for single-author threads in Visibility{}.StatusPublicTimelineable())
* use bun query building for nested select statements to ensure working with postgres
* update public timeline future status checks to match visibility filter
* same as previous, for home timeline
* update public timeline tests to dynamically check for appropriate statuses
* migrate accounts to allow unique constraint on public_key
* provide minimal account with publicKey
---------
Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
2023-03-28 14:03:14 +01:00
|
|
|
// Get follow from requesting account to target account.
|
|
|
|
follow, err := p.state.DB.GetFollow(ctx, requestingAccount.ID, targetAccount.ID)
|
|
|
|
if err != nil && !errors.Is(err, db.ErrNoEntries) {
|
2023-09-12 14:00:35 +01:00
|
|
|
err = gtserror.Newf("error getting follow from %s targeting %s: %w", requestingAccount.ID, targetAccount.ID, err)
|
2023-03-20 19:10:08 +01:00
|
|
|
return nil, err
|
[performance] refactoring + add fave / follow / request / visibility caching (#1607)
* refactor visibility checking, add caching for visibility
* invalidate visibility cache items on account / status deletes
* fix requester ID passed to visibility cache nil ptr
* de-interface caches, fix home / public timeline caching + visibility
* finish adding code comments for visibility filter
* fix angry goconst linter warnings
* actually finish adding filter visibility code comments for timeline functions
* move home timeline status author check to after visibility
* remove now-unused code
* add more code comments
* add TODO code comment, update printed cache start names
* update printed cache names on stop
* start adding separate follow(request) delete db functions, add specific visibility cache tests
* add relationship type caching
* fix getting local account follows / followed-bys, other small codebase improvements
* simplify invalidation using cache hooks, add more GetAccountBy___() functions
* fix boosting to return 404 if not boostable but no error (to not leak status ID)
* remove dead code
* improved placement of cache invalidation
* update license headers
* add example follow, follow-request config entries
* add example visibility cache configuration to config file
* use specific PutFollowRequest() instead of just Put()
* add tests for all GetAccountBy()
* add GetBlockBy() tests
* update block to check primitive fields
* update and finish adding Get{Account,Block,Follow,FollowRequest}By() tests
* fix copy-pasted code
* update envparsing test
* whitespace
* fix bun struct tag
* add license header to gtscontext
* fix old license header
* improved error creation to not use fmt.Errorf() when not needed
* fix various rebase conflicts, fix account test
* remove commented-out code, fix-up mention caching
* fix mention select bun statement
* ensure mention target account populated, pass in context to customrenderer logging
* remove more uncommented code, fix typeutil test
* add statusfave database model caching
* add status fave cache configuration
* add status fave cache example config
* woops, catch missed error. nice catch linter!
* add back testrig panic on nil db
* update example configuration to match defaults, slight tweak to cache configuration defaults
* update envparsing test with new defaults
* fetch followingget to use the follow target account
* use accounnt.IsLocal() instead of empty domain check
* use constants for the cache visibility type check
* use bun.In() for notification type restriction in db query
* include replies when fetching PublicTimeline() (to account for single-author threads in Visibility{}.StatusPublicTimelineable())
* use bun query building for nested select statements to ensure working with postgres
* update public timeline future status checks to match visibility filter
* same as previous, for home timeline
* update public timeline tests to dynamically check for appropriate statuses
* migrate accounts to allow unique constraint on public_key
* provide minimal account with publicKey
---------
Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
2023-03-28 14:03:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if follow != nil {
|
|
|
|
// Delete known follow from database with ID.
|
|
|
|
err = p.state.DB.DeleteFollowByID(ctx, follow.ID)
|
|
|
|
if err != nil {
|
|
|
|
if !errors.Is(err, db.ErrNoEntries) {
|
2023-09-12 14:00:35 +01:00
|
|
|
err = gtserror.Newf("error deleting request from %s targeting %s: %w", requestingAccount.ID, targetAccount.ID, err)
|
[performance] refactoring + add fave / follow / request / visibility caching (#1607)
* refactor visibility checking, add caching for visibility
* invalidate visibility cache items on account / status deletes
* fix requester ID passed to visibility cache nil ptr
* de-interface caches, fix home / public timeline caching + visibility
* finish adding code comments for visibility filter
* fix angry goconst linter warnings
* actually finish adding filter visibility code comments for timeline functions
* move home timeline status author check to after visibility
* remove now-unused code
* add more code comments
* add TODO code comment, update printed cache start names
* update printed cache names on stop
* start adding separate follow(request) delete db functions, add specific visibility cache tests
* add relationship type caching
* fix getting local account follows / followed-bys, other small codebase improvements
* simplify invalidation using cache hooks, add more GetAccountBy___() functions
* fix boosting to return 404 if not boostable but no error (to not leak status ID)
* remove dead code
* improved placement of cache invalidation
* update license headers
* add example follow, follow-request config entries
* add example visibility cache configuration to config file
* use specific PutFollowRequest() instead of just Put()
* add tests for all GetAccountBy()
* add GetBlockBy() tests
* update block to check primitive fields
* update and finish adding Get{Account,Block,Follow,FollowRequest}By() tests
* fix copy-pasted code
* update envparsing test
* whitespace
* fix bun struct tag
* add license header to gtscontext
* fix old license header
* improved error creation to not use fmt.Errorf() when not needed
* fix various rebase conflicts, fix account test
* remove commented-out code, fix-up mention caching
* fix mention select bun statement
* ensure mention target account populated, pass in context to customrenderer logging
* remove more uncommented code, fix typeutil test
* add statusfave database model caching
* add status fave cache configuration
* add status fave cache example config
* woops, catch missed error. nice catch linter!
* add back testrig panic on nil db
* update example configuration to match defaults, slight tweak to cache configuration defaults
* update envparsing test with new defaults
* fetch followingget to use the follow target account
* use accounnt.IsLocal() instead of empty domain check
* use constants for the cache visibility type check
* use bun.In() for notification type restriction in db query
* include replies when fetching PublicTimeline() (to account for single-author threads in Visibility{}.StatusPublicTimelineable())
* use bun query building for nested select statements to ensure working with postgres
* update public timeline future status checks to match visibility filter
* same as previous, for home timeline
* update public timeline tests to dynamically check for appropriate statuses
* migrate accounts to allow unique constraint on public_key
* provide minimal account with publicKey
---------
Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
2023-03-28 14:03:14 +01:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// If err == db.ErrNoEntries here then it
|
|
|
|
// indicates a race condition with another
|
|
|
|
// unfollow for the same requester->target.
|
|
|
|
return msgs, nil
|
|
|
|
}
|
|
|
|
|
2023-03-20 19:10:08 +01:00
|
|
|
// Follow status changed, process side effects.
|
2024-04-26 13:50:46 +01:00
|
|
|
msgs = append(msgs, &messages.FromClientAPI{
|
2023-02-22 16:05:26 +01:00
|
|
|
APObjectType: ap.ActivityFollow,
|
|
|
|
APActivityType: ap.ActivityUndo,
|
2025-05-03 10:10:23 +00:00
|
|
|
GTSModel: follow,
|
|
|
|
Origin: requestingAccount,
|
|
|
|
Target: targetAccount,
|
2023-02-22 16:05:26 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
[performance] refactoring + add fave / follow / request / visibility caching (#1607)
* refactor visibility checking, add caching for visibility
* invalidate visibility cache items on account / status deletes
* fix requester ID passed to visibility cache nil ptr
* de-interface caches, fix home / public timeline caching + visibility
* finish adding code comments for visibility filter
* fix angry goconst linter warnings
* actually finish adding filter visibility code comments for timeline functions
* move home timeline status author check to after visibility
* remove now-unused code
* add more code comments
* add TODO code comment, update printed cache start names
* update printed cache names on stop
* start adding separate follow(request) delete db functions, add specific visibility cache tests
* add relationship type caching
* fix getting local account follows / followed-bys, other small codebase improvements
* simplify invalidation using cache hooks, add more GetAccountBy___() functions
* fix boosting to return 404 if not boostable but no error (to not leak status ID)
* remove dead code
* improved placement of cache invalidation
* update license headers
* add example follow, follow-request config entries
* add example visibility cache configuration to config file
* use specific PutFollowRequest() instead of just Put()
* add tests for all GetAccountBy()
* add GetBlockBy() tests
* update block to check primitive fields
* update and finish adding Get{Account,Block,Follow,FollowRequest}By() tests
* fix copy-pasted code
* update envparsing test
* whitespace
* fix bun struct tag
* add license header to gtscontext
* fix old license header
* improved error creation to not use fmt.Errorf() when not needed
* fix various rebase conflicts, fix account test
* remove commented-out code, fix-up mention caching
* fix mention select bun statement
* ensure mention target account populated, pass in context to customrenderer logging
* remove more uncommented code, fix typeutil test
* add statusfave database model caching
* add status fave cache configuration
* add status fave cache example config
* woops, catch missed error. nice catch linter!
* add back testrig panic on nil db
* update example configuration to match defaults, slight tweak to cache configuration defaults
* update envparsing test with new defaults
* fetch followingget to use the follow target account
* use accounnt.IsLocal() instead of empty domain check
* use constants for the cache visibility type check
* use bun.In() for notification type restriction in db query
* include replies when fetching PublicTimeline() (to account for single-author threads in Visibility{}.StatusPublicTimelineable())
* use bun query building for nested select statements to ensure working with postgres
* update public timeline future status checks to match visibility filter
* same as previous, for home timeline
* update public timeline tests to dynamically check for appropriate statuses
* migrate accounts to allow unique constraint on public_key
* provide minimal account with publicKey
---------
Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
2023-03-28 14:03:14 +01:00
|
|
|
// Get follow request from requesting account to target account.
|
|
|
|
followReq, err := p.state.DB.GetFollowRequest(ctx, requestingAccount.ID, targetAccount.ID)
|
|
|
|
if err != nil && !errors.Is(err, db.ErrNoEntries) {
|
2023-09-12 14:00:35 +01:00
|
|
|
err = gtserror.Newf("error getting follow request from %s targeting %s: %w", requestingAccount.ID, targetAccount.ID, err)
|
2023-03-20 19:10:08 +01:00
|
|
|
return nil, err
|
[performance] refactoring + add fave / follow / request / visibility caching (#1607)
* refactor visibility checking, add caching for visibility
* invalidate visibility cache items on account / status deletes
* fix requester ID passed to visibility cache nil ptr
* de-interface caches, fix home / public timeline caching + visibility
* finish adding code comments for visibility filter
* fix angry goconst linter warnings
* actually finish adding filter visibility code comments for timeline functions
* move home timeline status author check to after visibility
* remove now-unused code
* add more code comments
* add TODO code comment, update printed cache start names
* update printed cache names on stop
* start adding separate follow(request) delete db functions, add specific visibility cache tests
* add relationship type caching
* fix getting local account follows / followed-bys, other small codebase improvements
* simplify invalidation using cache hooks, add more GetAccountBy___() functions
* fix boosting to return 404 if not boostable but no error (to not leak status ID)
* remove dead code
* improved placement of cache invalidation
* update license headers
* add example follow, follow-request config entries
* add example visibility cache configuration to config file
* use specific PutFollowRequest() instead of just Put()
* add tests for all GetAccountBy()
* add GetBlockBy() tests
* update block to check primitive fields
* update and finish adding Get{Account,Block,Follow,FollowRequest}By() tests
* fix copy-pasted code
* update envparsing test
* whitespace
* fix bun struct tag
* add license header to gtscontext
* fix old license header
* improved error creation to not use fmt.Errorf() when not needed
* fix various rebase conflicts, fix account test
* remove commented-out code, fix-up mention caching
* fix mention select bun statement
* ensure mention target account populated, pass in context to customrenderer logging
* remove more uncommented code, fix typeutil test
* add statusfave database model caching
* add status fave cache configuration
* add status fave cache example config
* woops, catch missed error. nice catch linter!
* add back testrig panic on nil db
* update example configuration to match defaults, slight tweak to cache configuration defaults
* update envparsing test with new defaults
* fetch followingget to use the follow target account
* use accounnt.IsLocal() instead of empty domain check
* use constants for the cache visibility type check
* use bun.In() for notification type restriction in db query
* include replies when fetching PublicTimeline() (to account for single-author threads in Visibility{}.StatusPublicTimelineable())
* use bun query building for nested select statements to ensure working with postgres
* update public timeline future status checks to match visibility filter
* same as previous, for home timeline
* update public timeline tests to dynamically check for appropriate statuses
* migrate accounts to allow unique constraint on public_key
* provide minimal account with publicKey
---------
Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
2023-03-28 14:03:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if followReq != nil {
|
|
|
|
// Delete known follow request from database with ID.
|
|
|
|
err = p.state.DB.DeleteFollowRequestByID(ctx, followReq.ID)
|
|
|
|
if err != nil {
|
|
|
|
if !errors.Is(err, db.ErrNoEntries) {
|
2023-09-12 14:00:35 +01:00
|
|
|
err = gtserror.Newf("error deleting follow request from %s targeting %s: %w", requestingAccount.ID, targetAccount.ID, err)
|
[performance] refactoring + add fave / follow / request / visibility caching (#1607)
* refactor visibility checking, add caching for visibility
* invalidate visibility cache items on account / status deletes
* fix requester ID passed to visibility cache nil ptr
* de-interface caches, fix home / public timeline caching + visibility
* finish adding code comments for visibility filter
* fix angry goconst linter warnings
* actually finish adding filter visibility code comments for timeline functions
* move home timeline status author check to after visibility
* remove now-unused code
* add more code comments
* add TODO code comment, update printed cache start names
* update printed cache names on stop
* start adding separate follow(request) delete db functions, add specific visibility cache tests
* add relationship type caching
* fix getting local account follows / followed-bys, other small codebase improvements
* simplify invalidation using cache hooks, add more GetAccountBy___() functions
* fix boosting to return 404 if not boostable but no error (to not leak status ID)
* remove dead code
* improved placement of cache invalidation
* update license headers
* add example follow, follow-request config entries
* add example visibility cache configuration to config file
* use specific PutFollowRequest() instead of just Put()
* add tests for all GetAccountBy()
* add GetBlockBy() tests
* update block to check primitive fields
* update and finish adding Get{Account,Block,Follow,FollowRequest}By() tests
* fix copy-pasted code
* update envparsing test
* whitespace
* fix bun struct tag
* add license header to gtscontext
* fix old license header
* improved error creation to not use fmt.Errorf() when not needed
* fix various rebase conflicts, fix account test
* remove commented-out code, fix-up mention caching
* fix mention select bun statement
* ensure mention target account populated, pass in context to customrenderer logging
* remove more uncommented code, fix typeutil test
* add statusfave database model caching
* add status fave cache configuration
* add status fave cache example config
* woops, catch missed error. nice catch linter!
* add back testrig panic on nil db
* update example configuration to match defaults, slight tweak to cache configuration defaults
* update envparsing test with new defaults
* fetch followingget to use the follow target account
* use accounnt.IsLocal() instead of empty domain check
* use constants for the cache visibility type check
* use bun.In() for notification type restriction in db query
* include replies when fetching PublicTimeline() (to account for single-author threads in Visibility{}.StatusPublicTimelineable())
* use bun query building for nested select statements to ensure working with postgres
* update public timeline future status checks to match visibility filter
* same as previous, for home timeline
* update public timeline tests to dynamically check for appropriate statuses
* migrate accounts to allow unique constraint on public_key
* provide minimal account with publicKey
---------
Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
2023-03-28 14:03:14 +01:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// If err == db.ErrNoEntries here then it
|
|
|
|
// indicates a race condition with another
|
|
|
|
// unfollow for the same requester->target.
|
|
|
|
return msgs, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Follow status changed, process side effects.
|
2024-04-26 13:50:46 +01:00
|
|
|
msgs = append(msgs, &messages.FromClientAPI{
|
2023-02-22 16:05:26 +01:00
|
|
|
APObjectType: ap.ActivityFollow,
|
|
|
|
APActivityType: ap.ActivityUndo,
|
2025-05-03 10:10:23 +00:00
|
|
|
// Dummy out a follow to undo,
|
|
|
|
// based on the follow request.
|
2023-02-22 16:05:26 +01:00
|
|
|
GTSModel: >smodel.Follow{
|
|
|
|
AccountID: requestingAccount.ID,
|
2025-05-03 10:10:23 +00:00
|
|
|
Account: requestingAccount,
|
2023-03-20 19:10:08 +01:00
|
|
|
TargetAccountID: targetAccount.ID,
|
2025-05-03 10:10:23 +00:00
|
|
|
TargetAccount: targetAccount,
|
[performance] refactoring + add fave / follow / request / visibility caching (#1607)
* refactor visibility checking, add caching for visibility
* invalidate visibility cache items on account / status deletes
* fix requester ID passed to visibility cache nil ptr
* de-interface caches, fix home / public timeline caching + visibility
* finish adding code comments for visibility filter
* fix angry goconst linter warnings
* actually finish adding filter visibility code comments for timeline functions
* move home timeline status author check to after visibility
* remove now-unused code
* add more code comments
* add TODO code comment, update printed cache start names
* update printed cache names on stop
* start adding separate follow(request) delete db functions, add specific visibility cache tests
* add relationship type caching
* fix getting local account follows / followed-bys, other small codebase improvements
* simplify invalidation using cache hooks, add more GetAccountBy___() functions
* fix boosting to return 404 if not boostable but no error (to not leak status ID)
* remove dead code
* improved placement of cache invalidation
* update license headers
* add example follow, follow-request config entries
* add example visibility cache configuration to config file
* use specific PutFollowRequest() instead of just Put()
* add tests for all GetAccountBy()
* add GetBlockBy() tests
* update block to check primitive fields
* update and finish adding Get{Account,Block,Follow,FollowRequest}By() tests
* fix copy-pasted code
* update envparsing test
* whitespace
* fix bun struct tag
* add license header to gtscontext
* fix old license header
* improved error creation to not use fmt.Errorf() when not needed
* fix various rebase conflicts, fix account test
* remove commented-out code, fix-up mention caching
* fix mention select bun statement
* ensure mention target account populated, pass in context to customrenderer logging
* remove more uncommented code, fix typeutil test
* add statusfave database model caching
* add status fave cache configuration
* add status fave cache example config
* woops, catch missed error. nice catch linter!
* add back testrig panic on nil db
* update example configuration to match defaults, slight tweak to cache configuration defaults
* update envparsing test with new defaults
* fetch followingget to use the follow target account
* use accounnt.IsLocal() instead of empty domain check
* use constants for the cache visibility type check
* use bun.In() for notification type restriction in db query
* include replies when fetching PublicTimeline() (to account for single-author threads in Visibility{}.StatusPublicTimelineable())
* use bun query building for nested select statements to ensure working with postgres
* update public timeline future status checks to match visibility filter
* same as previous, for home timeline
* update public timeline tests to dynamically check for appropriate statuses
* migrate accounts to allow unique constraint on public_key
* provide minimal account with publicKey
---------
Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
2023-03-28 14:03:14 +01:00
|
|
|
URI: followReq.URI,
|
2023-02-22 16:05:26 +01:00
|
|
|
},
|
2024-04-26 13:50:46 +01:00
|
|
|
Origin: requestingAccount,
|
|
|
|
Target: targetAccount,
|
2023-02-22 16:05:26 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-03-20 19:10:08 +01:00
|
|
|
return msgs, nil
|
2023-02-22 16:05:26 +01:00
|
|
|
}
|