|
@@ -232,25 +232,40 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
|
|
items = @object['oneOf']
|
|
|
end
|
|
|
|
|
|
+ voters_count = @object['votersCount']
|
|
|
+
|
|
|
@account.polls.new(
|
|
|
multiple: multiple,
|
|
|
expires_at: expires_at,
|
|
|
options: items.map { |item| item['name'].presence || item['content'] }.compact,
|
|
|
- cached_tallies: items.map { |item| item.dig('replies', 'totalItems') || 0 }
|
|
|
+ cached_tallies: items.map { |item| item.dig('replies', 'totalItems') || 0 },
|
|
|
+ voters_count: voters_count
|
|
|
)
|
|
|
end
|
|
|
|
|
|
def poll_vote?
|
|
|
return false if replied_to_status.nil? || replied_to_status.preloadable_poll.nil? || !replied_to_status.local? || !replied_to_status.preloadable_poll.options.include?(@object['name'])
|
|
|
|
|
|
- unless replied_to_status.preloadable_poll.expired?
|
|
|
- replied_to_status.preloadable_poll.votes.create!(account: @account, choice: replied_to_status.preloadable_poll.options.index(@object['name']), uri: @object['id'])
|
|
|
- ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, replied_to_status.id) unless replied_to_status.preloadable_poll.hide_totals?
|
|
|
- end
|
|
|
+ poll_vote! unless replied_to_status.preloadable_poll.expired?
|
|
|
|
|
|
true
|
|
|
end
|
|
|
|
|
|
+ def poll_vote!
|
|
|
+ poll = replied_to_status.preloadable_poll
|
|
|
+ already_voted = true
|
|
|
+ RedisLock.acquire(poll_lock_options) do |lock|
|
|
|
+ if lock.acquired?
|
|
|
+ already_voted = poll.votes.where(account: @account).exists?
|
|
|
+ poll.votes.create!(account: @account, choice: poll.options.index(@object['name']), uri: @object['id'])
|
|
|
+ else
|
|
|
+ raise Mastodon::RaceConditionError
|
|
|
+ end
|
|
|
+ end
|
|
|
+ increment_voters_count! unless already_voted
|
|
|
+ ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, replied_to_status.id) unless replied_to_status.preloadable_poll.hide_totals?
|
|
|
+ end
|
|
|
+
|
|
|
def resolve_thread(status)
|
|
|
return unless status.reply? && status.thread.nil? && Request.valid_url?(in_reply_to_uri)
|
|
|
ThreadResolveWorker.perform_async(status.id, in_reply_to_uri)
|
|
@@ -416,7 +431,22 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
|
|
ActivityPub::RawDistributionWorker.perform_async(Oj.dump(@json), replied_to_status.account_id, [@account.preferred_inbox_url])
|
|
|
end
|
|
|
|
|
|
+ def increment_voters_count!
|
|
|
+ poll = replied_to_status.preloadable_poll
|
|
|
+ unless poll.voters_count.nil?
|
|
|
+ poll.voters_count = poll.voters_count + 1
|
|
|
+ poll.save
|
|
|
+ end
|
|
|
+ rescue ActiveRecord::StaleObjectError
|
|
|
+ poll.reload
|
|
|
+ retry
|
|
|
+ end
|
|
|
+
|
|
|
def lock_options
|
|
|
{ redis: Redis.current, key: "create:#{@object['id']}" }
|
|
|
end
|
|
|
+
|
|
|
+ def poll_lock_options
|
|
|
+ { redis: Redis.current, key: "vote:#{replied_to_status.poll_id}:#{@account.id}" }
|
|
|
+ end
|
|
|
end
|