2023-03-12 18:00:57 +03: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-04-19 20:42:19 +03:00
package gtsmodel
2021-08-10 14:32:39 +03:00
import (
2023-10-25 17:04:53 +03:00
"slices"
2023-10-31 14:12:22 +03:00
"time"
2024-12-05 16:35:07 +03:00
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
2021-08-10 14:32:39 +03:00
)
2021-04-19 20:42:19 +03:00
// Status represents a user-created 'post' or 'status' in the database, either remote or local
type Status struct {
2023-08-06 13:22:40 +03:00
ID string ` bun:"type:CHAR(26),pk,nullzero,notnull,unique" ` // id of this item in the database
CreatedAt time . Time ` bun:"type:timestamptz,nullzero,notnull,default:current_timestamp" ` // when was item created
UpdatedAt time . Time ` bun:"type:timestamptz,nullzero,notnull,default:current_timestamp" ` // when was item last updated
FetchedAt time . Time ` bun:"type:timestamptz,nullzero" ` // when was item (remote) last fetched.
PinnedAt time . Time ` bun:"type:timestamptz,nullzero" ` // Status was pinned by owning account at this time.
URI string ` bun:",unique,nullzero,notnull" ` // activitypub URI of this status
URL string ` bun:",nullzero" ` // web url for viewing this status
Content string ` bun:"" ` // content of this status; likely html-formatted but not guaranteed
AttachmentIDs [ ] string ` bun:"attachments,array" ` // Database IDs of any media attachments associated with this status
Attachments [ ] * MediaAttachment ` bun:"attached_media,rel:has-many" ` // Attachments corresponding to attachmentIDs
TagIDs [ ] string ` bun:"tags,array" ` // Database IDs of any tags used in this status
Tags [ ] * Tag ` bun:"attached_tags,m2m:status_to_tags" ` // Tags corresponding to tagIDs. https://bun.uptrace.dev/guide/relations.html#many-to-many-relation
MentionIDs [ ] string ` bun:"mentions,array" ` // Database IDs of any mentions in this status
Mentions [ ] * Mention ` bun:"attached_mentions,rel:has-many" ` // Mentions corresponding to mentionIDs
EmojiIDs [ ] string ` bun:"emojis,array" ` // Database IDs of any emojis used in this status
Emojis [ ] * Emoji ` bun:"attached_emojis,m2m:status_to_emojis" ` // Emojis corresponding to emojiIDs. https://bun.uptrace.dev/guide/relations.html#many-to-many-relation
Local * bool ` bun:",nullzero,notnull,default:false" ` // is this status from a local account?
AccountID string ` bun:"type:CHAR(26),nullzero,notnull" ` // which account posted this status?
Account * Account ` bun:"rel:belongs-to" ` // account corresponding to accountID
AccountURI string ` bun:",nullzero,notnull" ` // activitypub uri of the owner of this status
InReplyToID string ` bun:"type:CHAR(26),nullzero" ` // id of the status this status replies to
InReplyToURI string ` bun:",nullzero" ` // activitypub uri of the status this status is a reply to
InReplyToAccountID string ` bun:"type:CHAR(26),nullzero" ` // id of the account that this status replies to
InReplyTo * Status ` bun:"-" ` // status corresponding to inReplyToID
InReplyToAccount * Account ` bun:"rel:belongs-to" ` // account corresponding to inReplyToAccountID
BoostOfID string ` bun:"type:CHAR(26),nullzero" ` // id of the status this status is a boost of
2023-12-01 17:27:15 +03:00
BoostOfURI string ` bun:"-" ` // URI of the status this status is a boost of; field not inserted in the db, just for dereferencing purposes.
2023-08-06 13:22:40 +03:00
BoostOfAccountID string ` bun:"type:CHAR(26),nullzero" ` // id of the account that owns the boosted status
BoostOf * Status ` bun:"-" ` // status that corresponds to boostOfID
BoostOfAccount * Account ` bun:"rel:belongs-to" ` // account that corresponds to boostOfAccountID
2023-10-25 17:04:53 +03:00
ThreadID string ` bun:"type:CHAR(26),nullzero" ` // id of the thread to which this status belongs; only set for remote statuses if a local account is involved at some point in the thread, otherwise null
2024-12-05 16:35:07 +03:00
EditIDs [ ] string ` bun:"edits,array" ` //
Edits [ ] * StatusEdit ` bun:"-" ` //
2023-11-08 17:32:17 +03:00
PollID string ` bun:"type:CHAR(26),nullzero" ` //
Poll * Poll ` bun:"-" ` //
2023-08-06 13:22:40 +03:00
ContentWarning string ` bun:",nullzero" ` // cw string for this status
Visibility Visibility ` bun:",nullzero,notnull" ` // visibility entry for this status
Sensitive * bool ` bun:",nullzero,notnull,default:false" ` // mark the status as sensitive?
Language string ` bun:",nullzero" ` // what language is this status written in?
CreatedWithApplicationID string ` bun:"type:CHAR(26),nullzero" ` // Which application was used to create this status?
CreatedWithApplication * Application ` bun:"rel:belongs-to" ` // application corresponding to createdWithApplicationID
ActivityStreamsType string ` bun:",nullzero,notnull" ` // What is the activitystreams type of this status? See: https://www.w3.org/TR/activitystreams-vocabulary/#object-types. Will probably almost always be Note but who knows!.
Text string ` bun:"" ` // Original text of the status without formatting
Federated * bool ` bun:",notnull" ` // This status will be federated beyond the local timeline(s)
2024-07-11 17:44:29 +03:00
InteractionPolicy * InteractionPolicy ` bun:"" ` // InteractionPolicy for this status. If null then the default InteractionPolicy should be assumed for this status's Visibility. Always null for boost wrappers.
PendingApproval * bool ` bun:",nullzero,notnull,default:false" ` // If true then status is a reply or boost wrapper that must be Approved by the reply-ee or boost-ee before being fully distributed.
2024-07-26 13:04:28 +03:00
PreApproved bool ` bun:"-" ` // If true, then status is a reply to or boost wrapper of a status on our instance, has permission to do the interaction, and an Accept should be sent out for it immediately. Field not stored in the DB.
2024-07-11 17:44:29 +03:00
ApprovedByURI string ` bun:",nullzero" ` // URI of an Accept Activity that approves the Announce or Create Activity that this status was/will be attached to.
2021-08-20 13:26:56 +03:00
}
2021-04-19 20:42:19 +03: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 16:03:14 +03:00
// GetID implements timeline.Timelineable{}.
2022-02-05 14:47:38 +03:00
func ( s * Status ) GetID ( ) string {
return s . ID
}
[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 16:03:14 +03:00
// GetAccountID implements timeline.Timelineable{}.
2022-02-05 14:47:38 +03:00
func ( s * Status ) GetAccountID ( ) string {
return s . AccountID
}
[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 16:03:14 +03:00
// GetBoostID implements timeline.Timelineable{}.
2022-02-05 14:47:38 +03:00
func ( s * Status ) GetBoostOfID ( ) string {
return s . BoostOfID
}
[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 16:03:14 +03:00
// GetBoostOfAccountID implements timeline.Timelineable{}.
2022-02-05 14:47:38 +03:00
func ( s * Status ) GetBoostOfAccountID ( ) string {
return s . BoostOfAccountID
}
2024-12-05 16:35:07 +03:00
// AttachmentsPopulated returns whether media attachments
// are populated according to current AttachmentIDs.
[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 16:03:14 +03:00
func ( s * Status ) AttachmentsPopulated ( ) bool {
if len ( s . AttachmentIDs ) != len ( s . Attachments ) {
// this is the quickest indicator.
return false
}
2023-10-31 14:12:22 +03:00
for i , id := range s . AttachmentIDs {
if s . Attachments [ i ] . ID != id {
[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 16:03:14 +03:00
return false
}
}
return true
}
2024-12-05 16:35:07 +03:00
// TagsPopulated returns whether tags are
// populated according to current TagIDs.
[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 16:03:14 +03:00
func ( s * Status ) TagsPopulated ( ) bool {
if len ( s . TagIDs ) != len ( s . Tags ) {
// this is the quickest indicator.
return false
}
for i , id := range s . TagIDs {
if s . Tags [ i ] . ID != id {
return false
}
}
return true
}
2024-12-05 16:35:07 +03:00
// MentionsPopulated returns whether mentions are
// populated according to current MentionIDs.
[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 16:03:14 +03:00
func ( s * Status ) MentionsPopulated ( ) bool {
if len ( s . MentionIDs ) != len ( s . Mentions ) {
// this is the quickest indicator.
return false
}
2023-10-31 14:12:22 +03:00
for i , id := range s . MentionIDs {
if s . Mentions [ i ] . ID != id {
[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 16:03:14 +03:00
return false
}
}
return true
}
2024-12-05 16:35:07 +03:00
// EmojisPopulated returns whether emojis are
// populated according to current EmojiIDs.
[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 16:03:14 +03:00
func ( s * Status ) EmojisPopulated ( ) bool {
if len ( s . EmojiIDs ) != len ( s . Emojis ) {
// this is the quickest indicator.
return false
}
for i , id := range s . EmojiIDs {
if s . Emojis [ i ] . ID != id {
return false
}
}
return true
}
2024-12-05 16:35:07 +03:00
// EditsPopulated returns whether edits are
// populated according to current EditIDs.
func ( s * Status ) EditsPopulated ( ) bool {
if len ( s . EditIDs ) != len ( s . Edits ) {
// this is quickest indicator.
return false
}
for i , id := range s . EditIDs {
if s . Edits [ i ] . ID != id {
return false
}
}
return true
}
2023-05-12 12:15:54 +03:00
// EmojissUpToDate returns whether status emoji attachments of receiving status are up-to-date
// according to emoji attachments of the passed status, by comparing their emoji URIs. We don't
// use IDs as this is used to determine whether there are new emojis to fetch.
func ( s * Status ) EmojisUpToDate ( other * Status ) bool {
if len ( s . Emojis ) != len ( other . Emojis ) {
// this is the quickest indicator.
return false
}
for i := range s . Emojis {
2023-10-31 14:12:22 +03:00
if s . Emojis [ i ] . URI != other . Emojis [ i ] . URI {
2023-05-12 12:15:54 +03:00
return false
}
2023-10-31 14:12:22 +03:00
}
return true
}
2023-05-12 12:15:54 +03:00
2023-10-31 14:12:22 +03:00
// GetAttachmentByRemoteURL searches status for MediaAttachment{} with remote URL.
func ( s * Status ) GetAttachmentByRemoteURL ( url string ) ( * MediaAttachment , bool ) {
for _ , media := range s . Attachments {
if media . RemoteURL == url {
return media , true
2023-05-12 12:15:54 +03:00
}
2023-10-31 14:12:22 +03:00
}
return nil , false
}
2023-05-12 12:15:54 +03:00
2023-10-31 14:12:22 +03:00
// GetMentionByTargetURI searches status for Mention{} with target URI.
func ( s * Status ) GetMentionByTargetURI ( uri string ) ( * Mention , bool ) {
for _ , mention := range s . Mentions {
if mention . TargetAccountURI == uri {
return mention , true
2023-05-12 12:15:54 +03:00
}
}
2023-10-31 14:12:22 +03:00
return nil , false
}
2023-05-12 12:15:54 +03:00
2024-09-10 15:33:32 +03:00
// GetMentionByUsernameDomain fetches the Mention associated with given
// username and domains, typically extracted from a mention Namestring.
func ( s * Status ) GetMentionByUsernameDomain ( username , domain string ) ( * Mention , bool ) {
for _ , mention := range s . Mentions {
// We can only check if target
// account is set on the mention.
account := mention . TargetAccount
if account == nil {
continue
}
// Usernames must always match.
if account . Username != username {
continue
}
// Finally, either domains must
// match or an empty domain may
// be permitted if account local.
if account . Domain == domain ||
( domain == "" && account . IsLocal ( ) ) {
return mention , true
}
}
return nil , false
}
2023-10-31 14:12:22 +03:00
// GetTagByName searches status for Tag{} with name.
func ( s * Status ) GetTagByName ( name string ) ( * Tag , bool ) {
for _ , tag := range s . Tags {
if tag . Name == name {
return tag , true
}
}
return nil , false
2023-05-12 12:15:54 +03: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 16:03:14 +03:00
// MentionsAccount returns whether status mentions the given account ID.
2023-10-25 17:04:53 +03:00
func ( s * Status ) MentionsAccount ( accountID string ) bool {
return slices . ContainsFunc ( s . Mentions , func ( m * Mention ) bool {
return m . TargetAccountID == accountID
} )
}
// BelongsToAccount returns whether status belongs to the given account ID.
func ( s * Status ) BelongsToAccount ( accountID string ) bool {
return s . AccountID == accountID
[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 16:03:14 +03:00
}
2024-02-09 17:24:49 +03:00
// IsLocal returns true if this is a local
// status (ie., originating from this instance).
func ( s * Status ) IsLocal ( ) bool {
return s . Local != nil && * s . Local
}
2024-08-22 20:47:10 +03:00
// IsLocalOnly returns true if this status
// is "local-only" ie., unfederated.
func ( s * Status ) IsLocalOnly ( ) bool {
return s . Federated == nil || ! * s . Federated
}
2024-12-05 16:35:07 +03:00
// AllAttachmentIDs gathers ALL media attachment IDs from both the
// receiving Status{}, and any historical Status{}.Edits. Note that
// this function will panic if Status{}.Edits is not populated.
func ( s * Status ) AllAttachmentIDs ( ) [ ] string {
var total int
if len ( s . EditIDs ) != len ( s . Edits ) {
panic ( "status edits not populated" )
}
// Get count of attachment IDs.
total += len ( s . Attachments )
for _ , edit := range s . Edits {
total += len ( edit . AttachmentIDs )
}
// Start gathering of all IDs with *current* attachment IDs.
attachmentIDs := make ( [ ] string , len ( s . AttachmentIDs ) , total )
copy ( attachmentIDs , s . AttachmentIDs )
// Append IDs of historical edits.
for _ , edit := range s . Edits {
attachmentIDs = append ( attachmentIDs , edit . AttachmentIDs ... )
}
// Deduplicate these IDs in case of shared media.
return xslices . Deduplicate ( attachmentIDs )
}
2021-08-20 13:26:56 +03:00
// StatusToTag is an intermediate struct to facilitate the many2many relationship between a status and one or more tags.
type StatusToTag struct {
2023-08-06 13:22:40 +03:00
StatusID string ` bun:"type:CHAR(26),unique:statustag,nullzero,notnull" `
Status * Status ` bun:"rel:belongs-to" `
TagID string ` bun:"type:CHAR(26),unique:statustag,nullzero,notnull" `
Tag * Tag ` bun:"rel:belongs-to" `
2021-08-20 13:26:56 +03:00
}
2021-04-19 20:42:19 +03:00
2021-08-20 13:26:56 +03:00
// StatusToEmoji is an intermediate struct to facilitate the many2many relationship between a status and one or more emojis.
type StatusToEmoji struct {
2023-08-06 13:22:40 +03:00
StatusID string ` bun:"type:CHAR(26),unique:statusemoji,nullzero,notnull" `
Status * Status ` bun:"rel:belongs-to" `
EmojiID string ` bun:"type:CHAR(26),unique:statusemoji,nullzero,notnull" `
Emoji * Emoji ` bun:"rel:belongs-to" `
2021-04-19 20:42:19 +03:00
}
2024-11-25 16:48:59 +03:00
// Visibility represents the
// visibility granularity of a status.
type Visibility enumType
2021-04-19 20:42:19 +03:00
const (
2024-09-09 19:07:25 +03:00
// VisibilityNone means nobody can see this.
// It's only used for web status visibility.
2024-11-25 16:48:59 +03:00
VisibilityNone Visibility = 1
// VisibilityPublic means this status will
// be visible to everyone on all timelines.
VisibilityPublic Visibility = 2
// VisibilityUnlocked means this status will be visible to everyone,
// but will only show on home timeline to followers, and in lists.
VisibilityUnlocked Visibility = 3
2021-04-20 19:14:23 +03:00
// VisibilityFollowersOnly means this status is viewable to followers only.
2024-11-25 16:48:59 +03:00
VisibilityFollowersOnly Visibility = 4
// VisibilityMutualsOnly means this status
// is visible to mutual followers only.
VisibilityMutualsOnly Visibility = 5
// VisibilityDirect means this status is
// visible only to mentioned recipients.
VisibilityDirect Visibility = 6
2021-08-02 20:06:44 +03:00
// VisibilityDefault is used when no other setting can be found.
VisibilityDefault Visibility = VisibilityUnlocked
2021-04-19 20:42:19 +03:00
)
2023-11-21 17:13:30 +03:00
2024-11-25 16:48:59 +03:00
// String returns a stringified, frontend API compatible form of Visibility.
func ( v Visibility ) String ( ) string {
switch v {
case VisibilityNone :
return "none"
case VisibilityPublic :
return "public"
case VisibilityUnlocked :
return "unlocked"
case VisibilityFollowersOnly :
return "followers_only"
case VisibilityMutualsOnly :
return "mutuals_only"
case VisibilityDirect :
return "direct"
default :
panic ( "invalid visibility" )
}
}
2023-11-21 17:13:30 +03:00
// Content models the simple string content
// of a status along with its ContentMap,
// which contains content entries keyed by
// BCP47 language tag.
//
// Content and/or ContentMap may be zero/nil.
type Content struct {
Content string
ContentMap map [ string ] string
}