# frozen_string_literal: true class DeliveryAntennaService include FormattingHelper def call(status, update, stl_home) @status = status @account = @status.account @update = update if stl_home delivery_stl! else delivery! end end private def delivery! tag_ids = @status.tags.pluck(:id) domain = @account.domain || Rails.configuration.x.local_domain antennas = Antenna.availables antennas = antennas.left_joins(:antenna_domains).where(any_domains: true).or(Antenna.left_joins(:antenna_domains).where(antenna_domains: { name: domain })) antennas = Antenna.where(id: antennas.select(:id)) antennas = antennas.left_joins(:antenna_accounts).where(any_accounts: true).or(Antenna.left_joins(:antenna_accounts).where(antenna_accounts: { account: @account })) tag_ids = @status.tags.pluck(:id) antennas = Antenna.where(id: antennas.select(:id)) antennas = antennas.left_joins(:antenna_tags).where(any_tags: true).or(Antenna.left_joins(:antenna_tags).where(antenna_tags: { tag_id: tag_ids })) antennas = antennas.where(account_id: Account.without_suspended.joins(:user).select('accounts.id').where('users.current_sign_in_at > ?', User::ACTIVE_DURATION.ago)) antennas = antennas.where(account: @status.account.followers) if [:public, :public_unlisted, :login, :limited].exclude?(@status.visibility.to_sym) antennas = antennas.where(account: @status.mentioned_accounts) if @status.visibility.to_sym == :limited antennas = antennas.where(with_media_only: false) unless @status.with_media? antennas = antennas.where(ignore_reblog: false) if @status.reblog? antennas = antennas.where(stl: false) collection = AntennaCollection.new(@status, @update, false) content = extract_status_plain_text_with_spoiler_text(@status) antennas.in_batches do |ans| ans.each do |antenna| next unless antenna.enabled? next if antenna.keywords&.any? && antenna.keywords&.none? { |keyword| content.include?(keyword) } next if antenna.exclude_keywords&.any? { |keyword| content.include?(keyword) } next if antenna.exclude_accounts&.include?(@status.account_id) next if antenna.exclude_domains&.include?(domain) next if antenna.exclude_tags&.any? { |tag_id| tag_ids.include?(tag_id) } collection.push(antenna) end end collection.deliver! end def delivery_stl! antennas = Antenna.available_stls antennas = antennas.where(account_id: Account.without_suspended.joins(:user).select('accounts.id').where('users.current_sign_in_at > ?', User::ACTIVE_DURATION.ago)) home_post = !@account.domain.nil? || @status.reblog? || [:public, :public_unlisted, :login].exclude?(@status.visibility.to_sym) antennas = antennas.where(account: @account.followers).or(antennas.where(account: @account)).where.not(list_id: 0) if home_post collection = AntennaCollection.new(@status, @update, home_post) antennas.in_batches do |ans| ans.each do |antenna| next if antenna.expired? collection.push(antenna) end end collection.deliver! end class AntennaCollection def initialize(status, update, stl_home = false) # rubocop:disable Style/OptionalBooleanParameter @status = status @update = update @stl_home = stl_home @home_account_ids = [] @list_ids = [] end def push(antenna) if antenna.list_id.zero? @home_account_ids << { id: antenna.account_id, antenna_id: antenna.id } if @home_account_ids.none? { |id| id[:id] == antenna.account_id } elsif @list_ids.none? { |id| id[:id] == antenna.list_id } @list_ids << { id: antenna.list_id, antenna_id: antenna.id } end end def deliver! lists = @list_ids homes = @home_account_ids if lists.any? FeedInsertWorker.push_bulk(lists) do |list| [@status.id, list[:id], 'list', { 'update' => @update, 'stl_home' => @stl_home || false, 'antenna_id' => list[:antenna_id] }] end end return unless homes.any? FeedInsertWorker.push_bulk(homes) do |home| [@status.id, home[:id], 'home', { 'update' => @update, 'antenna_id' => home[:antenna_id] }] end end end end