# frozen_string_literal: true class ActivityPub # Sincroniza las listas de bloqueo y permitidas con el estado actual # de la base de datos. class SyncListsJob < ApplicationJob # Siempre correr al final self.priority = 100 attr_reader :logs # Ejecuta todas las requests y consolida los posibles errores. # # @param site [Site] def run(site:) @logs = {} instance_scope = site.instance_moderations.joins(:instance) actor_scope = site.actor_moderations.joins(:actor) blocklist = wildcardize(instance_scope.blocked.pluck(:hostname)) + actor_scope.blocked.distinct.pluck(:mention).compact allowlist = wildcardize(instance_scope.allowed.pluck(:hostname)) + actor_scope.allowed.distinct.pluck(:mention).compact pauselist = wildcardize(instance_scope.paused.pluck(:hostname)) + actor_scope.paused.distinct.pluck(:mention).compact if blocklist.present? Rails.logger.info "Bloqueando: #{blocklist.join(', ')}" process(:blocked) { site.social_inbox.allowlist.delete(list: blocklist) } process(:blocked) { site.social_inbox.blocklist.post(list: blocklist) } end if allowlist.present? Rails.logger.info "Permitiendo: #{allowlist.join(', ')}" process(:allowed) { site.social_inbox.blocklist.delete(list: allowlist) } process(:allowed) { site.social_inbox.allowlist.post(list: allowlist) } end if pauselist.present? Rails.logger.info "Pausando: #{pauselist.join(', ')}" process(:paused) { site.social_inbox.blocklist.delete(list: pauselist) } process(:paused) { site.social_inbox.allowlist.delete(list: pauselist) } end # Si alguna falló, reintentar raise if logs.present? rescue Exception => e ExceptionNotifier.notify_exception(e, data: { site: site.name, logs: logs, blocklist: blocklist, allowlist: allowlist, pauselist: pauselist }) raise end private def process(stage) response = yield return if response.success? logs[stage] ||= [] logs[stage] << { body: response.body, code: response.code } end # @params hostnames [Array] # @return [Array] def wildcardize(hostnames) hostnames.map do |hostname| "@*@#{hostname}" end end end end