2019-03-03 13:18:23 -08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
class VoteService < BaseService
|
|
|
|
include Authorization
|
2019-06-04 14:11:18 -07:00
|
|
|
include Payloadable
|
2022-04-28 08:47:34 -07:00
|
|
|
include Redisable
|
2022-05-12 15:02:35 -07:00
|
|
|
include Lockable
|
2019-03-03 13:18:23 -08:00
|
|
|
|
|
|
|
def call(account, poll, choices)
|
2022-05-26 13:06:10 -07:00
|
|
|
return if choices.empty?
|
|
|
|
|
2019-03-03 13:18:23 -08:00
|
|
|
authorize_with account, poll, :vote?
|
|
|
|
|
|
|
|
@account = account
|
|
|
|
@poll = poll
|
|
|
|
@choices = choices
|
|
|
|
@votes = []
|
|
|
|
|
2019-09-29 13:58:01 -07:00
|
|
|
already_voted = true
|
|
|
|
|
2023-05-02 09:16:07 -07:00
|
|
|
with_redis_lock("vote:#{@poll.id}:#{@account.id}") do
|
2024-01-23 03:41:34 -08:00
|
|
|
already_voted = @poll.votes.exists?(account: @account)
|
2019-09-29 13:58:01 -07:00
|
|
|
|
2022-05-12 15:02:35 -07:00
|
|
|
ApplicationRecord.transaction do
|
|
|
|
@choices.each do |choice|
|
|
|
|
@votes << @poll.votes.create!(account: @account, choice: Integer(choice))
|
2019-09-29 13:58:01 -07:00
|
|
|
end
|
2019-03-03 13:18:23 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-09-29 13:58:01 -07:00
|
|
|
increment_voters_count! unless already_voted
|
|
|
|
|
2019-03-23 06:07:17 -07:00
|
|
|
ActivityTracker.increment('activity:interactions')
|
|
|
|
|
2019-03-10 16:49:31 -07:00
|
|
|
if @poll.account.local?
|
2019-03-12 14:58:59 -07:00
|
|
|
distribute_poll!
|
2019-03-10 16:49:31 -07:00
|
|
|
else
|
2019-03-12 14:58:59 -07:00
|
|
|
deliver_votes!
|
|
|
|
queue_final_poll_check!
|
2019-03-03 13:18:23 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2019-03-12 14:58:59 -07:00
|
|
|
def distribute_poll!
|
|
|
|
return if @poll.hide_totals?
|
2023-02-19 21:58:28 -08:00
|
|
|
|
2019-03-12 14:58:59 -07:00
|
|
|
ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, @poll.status.id)
|
|
|
|
end
|
|
|
|
|
|
|
|
def queue_final_poll_check!
|
|
|
|
return unless @poll.expires?
|
2023-02-19 21:58:28 -08:00
|
|
|
|
2019-03-12 14:58:59 -07:00
|
|
|
PollExpirationNotifyWorker.perform_at(@poll.expires_at + 5.minutes, @poll.id)
|
|
|
|
end
|
|
|
|
|
|
|
|
def deliver_votes!
|
|
|
|
@votes.each do |vote|
|
|
|
|
ActivityPub::DeliveryWorker.perform_async(
|
|
|
|
build_json(vote),
|
|
|
|
@account.id,
|
|
|
|
@poll.account.inbox_url
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-03-03 13:18:23 -08:00
|
|
|
def build_json(vote)
|
2019-06-04 14:11:18 -07:00
|
|
|
Oj.dump(serialize_payload(vote, ActivityPub::VoteSerializer))
|
2019-03-03 13:18:23 -08:00
|
|
|
end
|
2019-09-29 13:58:01 -07:00
|
|
|
|
|
|
|
def increment_voters_count!
|
|
|
|
unless @poll.voters_count.nil?
|
|
|
|
@poll.voters_count = @poll.voters_count + 1
|
|
|
|
@poll.save
|
|
|
|
end
|
|
|
|
rescue ActiveRecord::StaleObjectError
|
|
|
|
@poll.reload
|
|
|
|
retry
|
|
|
|
end
|
2019-03-03 13:18:23 -08:00
|
|
|
end
|