Merge remote-tracking branch 'parent/main' into upstream-20240319

This commit is contained in:
KMY 2024-03-19 09:15:20 +09:00
commit 76598bd542
496 changed files with 5795 additions and 3709 deletions

View file

@ -118,6 +118,7 @@ class Account < ApplicationRecord
normalizes :username, with: ->(username) { username.squish }
scope :without_internal, -> { where(id: 1...) }
scope :remote, -> { where.not(domain: nil) }
scope :local, -> { where(domain: nil) }
scope :partitioned, -> { order(Arel.sql('row_number() over (partition by domain)')) }
@ -498,7 +499,7 @@ class Account < ApplicationRecord
end
def inboxes
urls = reorder(nil).where(protocol: :activitypub).group(:preferred_inbox_url).pluck(Arel.sql("coalesce(nullif(accounts.shared_inbox_url, ''), accounts.inbox_url) AS preferred_inbox_url"))
urls = reorder(nil).activitypub.group(:preferred_inbox_url).pluck(Arel.sql("coalesce(nullif(accounts.shared_inbox_url, ''), accounts.inbox_url) AS preferred_inbox_url"))
DeliveryFailureTracker.without_unavailable(urls)
end

View file

@ -1,13 +1,13 @@
# frozen_string_literal: true
# Reverted this commit.temporarily because load issues.
# Whenever a manual merge occurs, be sure to check the following commits.
# Hash: ee8d0b94473df357677cd1f82581251ce0423c01
# Message: Fix follow suggestions potentially including silenced or blocked accounts (#29306)
class AccountSuggestions::FriendsOfFriendsSource < AccountSuggestions::Source
def get(account, limit: DEFAULT_LIMIT)
Account.find_by_sql([<<~SQL.squish, { id: account.id, limit: limit }]).map { |row| [row.id, key] }
source_query(account, limit: limit)
.map { |id, _frequency, _followers_count| [id, key] }
end
def source_query(account, limit: DEFAULT_LIMIT)
Account.find_by_sql([<<~SQL.squish, { id: account.id, limit: limit }]).map { |row| [row.id, row.frequency, row.followers_count] }
WITH first_degree AS (
SELECT target_account_id
FROM follows
@ -15,12 +15,16 @@ class AccountSuggestions::FriendsOfFriendsSource < AccountSuggestions::Source
WHERE account_id = :id
AND NOT target_accounts.hide_collections
)
SELECT accounts.id, COUNT(*) AS frequency
SELECT accounts.id, COUNT(*) AS frequency, account_stats.followers_count as followers_count
FROM accounts
JOIN follows ON follows.target_account_id = accounts.id
JOIN account_stats ON account_stats.account_id = accounts.id
LEFT OUTER JOIN follow_recommendation_mutes ON follow_recommendation_mutes.target_account_id = accounts.id AND follow_recommendation_mutes.account_id = :id
WHERE follows.account_id IN (SELECT * FROM first_degree)
AND NOT EXISTS (SELECT 1 FROM blocks b WHERE b.target_account_id = follows.target_account_id AND b.account_id = :id)
AND NOT EXISTS (SELECT 1 FROM blocks b WHERE b.target_account_id = :id AND b.account_id = follows.target_account_id)
AND NOT EXISTS (SELECT 1 FROM mutes m WHERE m.target_account_id = follows.target_account_id AND m.account_id = :id)
AND (accounts.domain IS NULL OR NOT EXISTS (SELECT 1 FROM account_domain_blocks b WHERE b.account_id = :id AND b.domain = accounts.domain))
AND NOT EXISTS (SELECT 1 FROM follows f WHERE f.target_account_id = follows.target_account_id AND f.account_id = :id)
AND follows.target_account_id <> :id
AND accounts.discoverable

View file

@ -267,10 +267,6 @@ module Account::Interactions
status_pins.exists?(status: status)
end
def endorsed?(account)
account_pins.exists?(target_account: account)
end
def status_matches_filters(status)
active_filters = CustomFilter.cached_filters_for(id)
CustomFilter.apply_cached_filters(active_filters, status, following: following?(status.account))

View file

@ -31,7 +31,7 @@ module Account::StatusesSearch
def add_to_public_statuses_index!
return unless Chewy.enabled?
statuses.without_reblogs.where(visibility: :public).reorder(nil).find_in_batches do |batch|
statuses.without_reblogs.public_visibility.reorder(nil).find_in_batches do |batch|
PublicStatusesIndex.import(batch)
end
end

View file

@ -5,6 +5,18 @@ module DomainNormalizable
included do
before_validation :normalize_domain
scope :by_domain_length, -> { order(domain_char_length.desc) }
end
class_methods do
def domain_char_length
Arel.sql(
<<~SQL.squish
CHAR_LENGTH(domain)
SQL
)
end
end
private

View file

@ -45,7 +45,7 @@ class CustomFilter < ApplicationRecord
validates :title, :context, presence: true
validate :context_must_be_valid
before_validation :clean_up_contexts
normalizes :context, with: ->(context) { context.map(&:strip).filter_map(&:presence) }
before_save :prepare_cache_invalidation!
before_destroy :prepare_cache_invalidation!
@ -141,10 +141,6 @@ class CustomFilter < ApplicationRecord
private
def clean_up_contexts
self.context = Array(context).map(&:strip).filter_map(&:presence)
end
def context_must_be_valid
errors.add(:context, I18n.t('filters.errors.invalid_context')) if invalid_context_value?
end

View file

@ -132,7 +132,7 @@ class DomainBlock < ApplicationRecord
segments = uri.normalized_host.split('.')
variants = segments.map.with_index { |_, i| segments[i..].join('.') }
where(domain: variants).order(Arel.sql('char_length(domain) desc')).first
where(domain: variants).by_domain_length.first
rescue Addressable::URI::InvalidURIError, IDN::Idna::IdnaError
nil
end

View file

@ -56,7 +56,7 @@ class EmailDomainBlock < ApplicationRecord
end
def blocking?(allow_with_approval: false)
blocks = EmailDomainBlock.where(domain: domains_with_variants, allow_with_approval: allow_with_approval).order(Arel.sql('char_length(domain) desc'))
blocks = EmailDomainBlock.where(domain: domains_with_variants, allow_with_approval: allow_with_approval).by_domain_length
blocks.each { |block| block.history.add(@attempt_ip) } if @attempt_ip.present?
blocks.any?
end

View file

@ -23,7 +23,7 @@ class IpBlock < ApplicationRecord
sign_up_requires_approval: 5000,
sign_up_block: 5500,
no_access: 9999,
}
}, prefix: true
validates :ip, :severity, presence: true
validates :ip, uniqueness: true

View file

@ -33,23 +33,55 @@ class Notification < ApplicationRecord
'AccountWarning' => :warning,
}.freeze
TYPES = %i(
mention
status
list_status
reblog
status_reference
follow
follow_request
favourite
emoji_reaction
reaction
poll
update
warning
admin.sign_up
admin.report
).freeze
PROPERTIES = {
mention: {
filterable: true,
}.freeze,
status: {
filterable: false,
}.freeze,
list_status: {
filterable: false,
}.freeze,
reblog: {
filterable: true,
}.freeze,
status_reference: {
filterable: true,
}.freeze,
follow: {
filterable: true,
}.freeze,
follow_request: {
filterable: true,
}.freeze,
favourite: {
filterable: true,
}.freeze,
emoji_reaction: {
filterable: true,
}.freeze,
reaction: {
filterable: true,
}.freeze,
poll: {
filterable: false,
}.freeze,
update: {
filterable: false,
}.freeze,
warning: {
filterable: false,
}.freeze,
'admin.sign_up': {
filterable: false,
}.freeze,
'admin.report': {
filterable: false,
}.freeze,
}.freeze
TYPES = PROPERTIES.keys.freeze
TARGET_STATUS_INCLUDES_BY_TYPE = {
status: :status,

View file

@ -54,6 +54,6 @@ class PreviewCardProvider < ApplicationRecord
def self.matching_domain(domain)
segments = domain.split('.')
where(domain: segments.map.with_index { |_, i| segments[i..].join('.') }).order(Arel.sql('char_length(domain) desc')).first
where(domain: segments.map.with_index { |_, i| segments[i..].join('.') }).by_domain_length.first
end
end

View file

@ -69,7 +69,7 @@ class PublicFeed
end
def public_scope
Status.with_public_visibility.joins(:account).merge(Account.without_suspended.without_silenced)
Status.public_visibility.joins(:account).merge(Account.without_suspended.without_silenced)
end
def public_search_scope

View file

@ -138,7 +138,6 @@ class Status < ApplicationRecord
scope :with_accounts, ->(ids) { where(id: ids).includes(:account) }
scope :without_replies, -> { where('statuses.reply = FALSE OR statuses.in_reply_to_account_id = statuses.account_id') }
scope :without_reblogs, -> { where(statuses: { reblog_of_id: nil }) }
scope :with_public_visibility, -> { where(visibility: [:public, :public_unlisted, :login]) }
scope :with_public_search_visibility, -> { merge(where(visibility: [:public, :public_unlisted, :login]).or(Status.where(searchability: [:public, :public_unlisted]))) }
scope :tagged_with, ->(tag_ids) { joins(:statuses_tags).where(statuses_tags: { tag_id: tag_ids }) }
scope :not_excluded_by_account, ->(account) { where.not(account_id: account.excluded_from_timeline_account_ids) }
@ -659,7 +658,6 @@ class Status < ApplicationRecord
def set_visibility
self.visibility = reblog.visibility if reblog? && visibility.nil?
self.visibility = (account.locked? ? :private : :public) if visibility.nil?
self.sensitive = false if sensitive.nil?
end
def set_searchability

View file

@ -449,7 +449,7 @@ class User < ApplicationRecord
end
def sign_up_from_ip_requires_approval?
sign_up_ip.present? && IpBlock.sign_up_requires_approval.exists?(['ip >>= ?', sign_up_ip.to_s])
sign_up_ip.present? && IpBlock.severity_sign_up_requires_approval.exists?(['ip >>= ?', sign_up_ip.to_s])
end
def sign_up_email_requires_approval?