Merge remote-tracking branch 'origin/kb_development' into kb_migration
This commit is contained in:
commit
94cd200097
50 changed files with 801 additions and 66 deletions
|
@ -29,6 +29,7 @@ class ActivityPub::ProcessAccountService < BaseService
|
|||
@account ||= Account.find_remote(@username, @domain)
|
||||
@old_public_key = @account&.public_key
|
||||
@old_protocol = @account&.protocol
|
||||
@old_searchability = @account&.searchability
|
||||
@suspension_changed = false
|
||||
|
||||
if @account.nil?
|
||||
|
@ -112,6 +113,7 @@ class ActivityPub::ProcessAccountService < BaseService
|
|||
@account.fields = property_values || {}
|
||||
@account.also_known_as = as_array(@json['alsoKnownAs'] || []).map { |item| value_or_id(item) }
|
||||
@account.discoverable = @json['discoverable'] || false
|
||||
@account.searchability = searchability_from_audience
|
||||
end
|
||||
|
||||
def set_fetchable_key!
|
||||
|
@ -150,6 +152,10 @@ class ActivityPub::ProcessAccountService < BaseService
|
|||
end
|
||||
end
|
||||
|
||||
def after_searchability_change!
|
||||
SearchabilityUpdateWorker.perform_async(@account.id) if @account.statuses.unset_searchability.exists?
|
||||
end
|
||||
|
||||
def after_protocol_change!
|
||||
ActivityPub::PostUpgradeWorker.perform_async(@account.domain)
|
||||
end
|
||||
|
@ -224,6 +230,24 @@ class ActivityPub::ProcessAccountService < BaseService
|
|||
end
|
||||
end
|
||||
|
||||
def audience_searchable_by
|
||||
return nil if @json['searchableBy'].nil?
|
||||
|
||||
@audience_searchable_by_processaccountservice = as_array(@json['searchableBy']).map { |x| value_or_id(x) }
|
||||
end
|
||||
|
||||
def searchability_from_audience
|
||||
if audience_searchable_by.nil?
|
||||
:private
|
||||
elsif audience_searchable_by.any? { |uri| ActivityPub::TagManager.instance.public_collection?(uri) }
|
||||
:public
|
||||
elsif audience_searchable_by.include?(@account.followers_url)
|
||||
:unlisted # Followers only in kmyblue (generics: private)
|
||||
else
|
||||
:private # Reaction only in kmyblue (generics: direct)
|
||||
end
|
||||
end
|
||||
|
||||
def property_values
|
||||
return unless @json['attachment'].is_a?(Array)
|
||||
|
||||
|
@ -310,6 +334,10 @@ class ActivityPub::ProcessAccountService < BaseService
|
|||
!@old_protocol.nil? && @old_protocol != @account.protocol
|
||||
end
|
||||
|
||||
def searchability_changed?
|
||||
!@old_searchability.nil? && @old_searchability != @account.searchability
|
||||
end
|
||||
|
||||
def process_tags
|
||||
return if @json['tag'].blank?
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ class PostStatusService < BaseService
|
|||
# @option [Status] :thread Optional status to reply to
|
||||
# @option [Boolean] :sensitive
|
||||
# @option [String] :visibility
|
||||
# @option [String] :searchability
|
||||
# @option [String] :spoiler_text
|
||||
# @option [String] :language
|
||||
# @option [String] :scheduled_at
|
||||
|
@ -66,12 +67,28 @@ class PostStatusService < BaseService
|
|||
@text = @options.delete(:spoiler_text) if @text.blank? && @options[:spoiler_text].present?
|
||||
@visibility = @options[:visibility] || @account.user&.setting_default_privacy
|
||||
@visibility = :unlisted if (@visibility&.to_sym == :public || @visibility&.to_sym == :public_unlisted) && @account.silenced?
|
||||
@searchability= searchability
|
||||
@scheduled_at = @options[:scheduled_at]&.to_datetime
|
||||
@scheduled_at = nil if scheduled_in_the_past?
|
||||
rescue ArgumentError
|
||||
raise ActiveRecord::RecordInvalid
|
||||
end
|
||||
|
||||
def searchability
|
||||
case @options[:searchability]&.to_sym
|
||||
when :public
|
||||
case @visibility&.to_sym when :public, :public_unlisted then :public when :unlisted then :unlisted when :private then :private else :direct end
|
||||
when :unlisted
|
||||
case @visibility&.to_sym when :public, :public_unlisted, :unlisted then :unlisted when :private then :private else :direct end
|
||||
when :private
|
||||
case @visibility&.to_sym when :public, :public_unlisted, :unlisted, :private then :private else :direct end
|
||||
when nil
|
||||
@account.searchability
|
||||
else
|
||||
:direct
|
||||
end
|
||||
end
|
||||
|
||||
def process_status!
|
||||
@status = @account.statuses.new(status_attributes)
|
||||
process_mentions_service.call(@status, save_records: false)
|
||||
|
@ -196,6 +213,7 @@ class PostStatusService < BaseService
|
|||
sensitive: @sensitive,
|
||||
spoiler_text: @options[:spoiler_text] || '',
|
||||
visibility: @visibility,
|
||||
searchability: @searchability,
|
||||
language: valid_locale_cascade(@options[:language], @account.user&.preferred_posting_language, I18n.default_locale),
|
||||
application: @options[:application],
|
||||
rate_limit: @options[:with_rate_limit],
|
||||
|
|
|
@ -8,6 +8,7 @@ class SearchService < BaseService
|
|||
@limit = limit.to_i
|
||||
@offset = options[:type].blank? ? 0 : options[:offset].to_i
|
||||
@resolve = options[:resolve] || false
|
||||
@searchability = options[:searchability] || 'public'
|
||||
|
||||
default_results.tap do |results|
|
||||
next if @query.blank? || @limit.zero?
|
||||
|
@ -35,11 +36,26 @@ class SearchService < BaseService
|
|||
end
|
||||
|
||||
def perform_statuses_search!
|
||||
# definition = parsed_query.apply(StatusesIndex.filter(term: { searchable_by: @account.id })).order(id: :desc)
|
||||
definition = parsed_query.apply(StatusesIndex).order(id: :desc)
|
||||
privacy_definition = parsed_query.apply(StatusesIndex.filter(term: { searchable_by: @account.id }))
|
||||
|
||||
# 'private' searchability posts are NOT in here because it's already added at previous line.
|
||||
case @searchability
|
||||
when 'public'
|
||||
privacy_definition = privacy_definition.or(StatusesIndex.filter(term: { searchability: 'public' }))
|
||||
privacy_definition = privacy_definition.or(StatusesIndex.filter(term: { searchability: 'unlisted' }).filter(terms: { account_id: following_account_ids })) unless following_account_ids.empty?
|
||||
privacy_definition = privacy_definition.or(StatusesIndex.filter(term: { searchability: 'direct' }).filter(term: { account_id: @account.id }))
|
||||
when 'unlisted', 'private'
|
||||
privacy_definition = privacy_definition.or(StatusesIndex.filter(terms: { searchability: %w(public unlisted) }).filter(terms: { account_id: following_account_ids })) unless following_account_ids.empty?
|
||||
privacy_definition = privacy_definition.or(StatusesIndex.filter(term: { searchability: 'direct' }).filter(term: { account_id: @account.id }))
|
||||
when 'direct'
|
||||
privacy_definition = privacy_definition.or(StatusesIndex.filter(term: { searchability: 'direct' }).filter(term: { account_id: @account.id }))
|
||||
end
|
||||
|
||||
definition = parsed_query.apply(StatusesIndex).order(id: :desc)
|
||||
definition = definition.filter(term: { account_id: @options[:account_id] }) if @options[:account_id].present?
|
||||
|
||||
definition = definition.and(privacy_definition)
|
||||
|
||||
if @options[:min_id].present? || @options[:max_id].present?
|
||||
range = {}
|
||||
range[:gt] = @options[:min_id].to_i if @options[:min_id].present?
|
||||
|
@ -50,9 +66,9 @@ class SearchService < BaseService
|
|||
results = definition.limit(@limit).offset(@offset).objects.compact
|
||||
account_ids = results.map(&:account_id)
|
||||
account_domains = results.map(&:account_domain)
|
||||
preloaded_relations = @account.relations_map(account_ids, account_domains)
|
||||
account_relations = @account.relations_map(account_ids, account_domains) # variable old name: preloaded_relations
|
||||
|
||||
results.reject { |status| StatusFilter.new(status, @account, preloaded_relations).search_filtered? }
|
||||
results.reject { |status| StatusFilter.new(status, @account, account_relations).filtered? }
|
||||
rescue Faraday::ConnectionFailed, Parslet::ParseFailed
|
||||
[]
|
||||
end
|
||||
|
@ -115,4 +131,13 @@ class SearchService < BaseService
|
|||
def parsed_query
|
||||
SearchQueryTransformer.new.apply(SearchQueryParser.new.parse(@query))
|
||||
end
|
||||
|
||||
def following_account_ids
|
||||
return @following_account_ids if defined?(@following_account_ids)
|
||||
|
||||
account_exists_sql = Account.where('accounts.id = follows.target_account_id').where(searchability: %w(public unlisted private)).reorder(nil).select(1).to_sql
|
||||
status_exists_sql = Status.where('statuses.account_id = follows.target_account_id').where(reblog_of_id: nil).where(searchability: %w(public unlisted private)).reorder(nil).select(1).to_sql
|
||||
following_accounts = Follow.where(account_id: @account.id).merge(Account.where("EXISTS (#{account_exists_sql})").or(Account.where("EXISTS (#{status_exists_sql})")))
|
||||
@following_account_ids = following_accounts.pluck(:target_account_id)
|
||||
end
|
||||
end
|
||||
|
|
27
app/services/searchability_update_service.rb
Normal file
27
app/services/searchability_update_service.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class SearchabilityUpdateService < BaseService
|
||||
def call(account)
|
||||
statuses = account.statuses.unset_searchability
|
||||
|
||||
return unless statuses.exists?
|
||||
|
||||
ids = statuses.pluck(:id)
|
||||
|
||||
if account.public_searchability?
|
||||
statuses.update_all('searchability = CASE visibility WHEN 0 THEN 0 WHEN 10 THEN 0 WHEN 1 THEN 2 WHEN 2 THEN 2 ELSE 3 END, updated_at = CURRENT_TIMESTAMP')
|
||||
elsif account.unlisted_searchability?
|
||||
statuses.update_all('searchability = CASE visibility WHEN 0 THEN 1 WHEN 10 THEN 1 WHEN 1 THEN 2 WHEN 2 THEN 2 ELSE 3 END, updated_at = CURRENT_TIMESTAMP')
|
||||
elsif account.private_searchability?
|
||||
statuses.update_all('searchability = CASE WHEN visibility IN (0, 1, 2, 10) THEN 2 ELSE 3 END, updated_at = CURRENT_TIMESTAMP')
|
||||
else
|
||||
statuses.update_all('searchability = 3, updated_at = CURRENT_TIMESTAMP')
|
||||
end
|
||||
|
||||
return unless Chewy.enabled?
|
||||
|
||||
ids.each_slice(100) do |chunk_ids|
|
||||
StatusesIndex.import chunk_ids, update_fields: [:searchability]
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue