app/models/paper_trail/version.decorator
# frozen_string_literal: true
module PaperTrail
decorate Version do
decorated do
after_create :broadcast
delegate :actor, to: :user
delegate :activity_id, :as_activity, to: :item
scope :unpublished, -> { where(broadcasted_at: nil) }
end
# Users that are following this change.
#
# @return [ActiveRecord::Relation<User>]
def followers
return [] if user.blank?
user.followers(User)
end
# Users from remote Soundstorm instances that are following this
# change.
def remote_followers
followers.reject do |follower|
follower.host == Soundstorm::HOST
end
end
# User who performed this change.
#
# @return [User] or `nil` if the whodunnit field is blank.
def user
return if whodunnit.blank?
GlobalID::Locator.locate(whodunnit)
end
# Test if this change is a track upload.
#
# @return [Boolean] Whether the item being changed is a Track
# and event is "create".
def upload?
item.is_a?(Track) && event == 'create'
end
# Denote what kind of change this is on the frontend.
#
# @return [String] "uploaded" or "created"
def verb
case event
when 'create'
upload? ? 'uploaded' : 'created'
when 'update'
'updated'
when 'destroy'
'deleted'
end
end
# Type of the event being broadcast.
#
# @return [String] Class name of the event type.
def type
event.classify
end
# The message object used to broadcast over ActivityPub.
#
# @return [ActivityPub::Message]
def message
ActivityPub::Message.new(
id: activity_id,
type: type,
published: created_at,
actor: actor,
payload: as_activity
)
end
# Whether this activity has been broadcast.
#
# @return [Boolean] whether `broadcasted_at` is present.
def broadcasted?
broadcasted_at.present?
end
# Whether this activity should be broadcasted in ActivityPub.
#
# @return [Boolean] `true` if not broadcasted and remote
def broadcastable?
!broadcasted? && remote?
end
# Whether any remote users should receive a broadcast of this
# activity.
def remote?
remote_followers.any?
end
private
# Publish this event to all ActivityPub subscribers.
#
# @return [BroadcastMessageJob] or `nil` if not broadcasting
def broadcast
BroadcastMessageJob.perform_later(self) if broadcastable?
end
end
end