# frozen_string_literal: true # = ActivityPub = # # El registro de actividades recibidas y su estado. Cuando recibimos # una actividad, puede estar destinada a varies actores dentro de Sutty, # con lo que generamos una cola para cada une. # # # @todo Ya que une actore puede hacer varias actividades sobre el mismo # objeto, lo correcto sería que la actividad a moderar sea una sola en # lugar de una lista acumulativa. Es decir cada ActivityPub representa # el estado del conjunto (Actor, Object, Activity) # # @see {https://www.w3.org/TR/activitypub/#client-to-server-interactions} class ActivityPub < ApplicationRecord IGNORED_EVENTS = %i[pause remove].freeze IGNORED_STATES = %i[removed].freeze include AASM belongs_to :instance belongs_to :site belongs_to :object, polymorphic: true belongs_to :actor belongs_to :remote_flag, optional: true, class_name: 'ActivityPub::RemoteFlag' has_many :activities validates :site_id, presence: true validates :object_id, presence: true validates :aasm_state, presence: true, inclusion: { in: %w[paused approved rejected reported removed] } accepts_nested_attributes_for :remote_flag # Encuentra la URI de un objeto # # @return [String, nil] def self.uri_from_object(object) case object when Array then uri_from_object(object.first) when String then object when Hash then (object['id'] || object[:id]) end end aasm do # Todavía no hay una decisión sobre el objeto state :paused, initial: true # Le usuarie aprobó el objeto state :approved # Le usuarie rechazó el objeto state :rejected # Le usuarie reportó el objeto state :reported # Le actore eliminó el objeto state :removed # Gestionar todos los errores error_on_all_events do |e| ExceptionNotifier.notify_exception(e, data: { site: site.name, activity_pub: self.id, activity: activities.first.uri }) end # Se puede volver a pausa en caso de actualización remota, para # revisar los cambios. event :pause do transitions to: :paused end # Recibir una acción de eliminación, eliminar el contenido de la # base de datos. Esto elimina el contenido para todos los sitios # porque estamos respetando lo que pidió le actore. event :remove do transitions to: :removed after do next if object.blank? object.update(content: {}) unless object.content.empty? end end # La actividad se aprueba, informándole a la Social Inbox que está # aprobada. También recibimos la aprobación via # webhook a modo de confirmación. event :approve do transitions from: %i[paused], to: :approved after do ActivityPub::InboxJob.perform_later(site: site, activity: activities.first.uri, action: :accept) end end # La actividad fue rechazada event :reject do transitions from: %i[paused], to: :rejected after do ActivityPub::InboxJob.perform_later(site: site, activity: activities.first.uri, action: :reject) end end # Solo podemos reportarla luego de rechazarla event :report do transitions from: :rejected, to: :reported after do ActivityPub::RemoteFlagJob.perform_later(remote_flag: remote_flag) if remote_flag.waiting? end end end # Definir eventos en masa include AasmEventsConcern end