@ -232,25 +232,40 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
items = @object [ 'oneOf' ]
items = @object [ 'oneOf' ]
end
end
voters_count = @object [ 'votersCount' ]
@account . polls . new (
@account . polls . new (
multiple : multiple ,
multiple : multiple ,
expires_at : expires_at ,
expires_at : expires_at ,
options : items . map { | item | item [ 'name' ] . presence || item [ 'content' ] } . compact ,
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
end
def poll_vote?
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' ] )
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?
poll_vote! 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
true
true
end
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 )
def resolve_thread ( status )
return unless status . reply? && status . thread . nil? && Request . valid_url? ( in_reply_to_uri )
return unless status . reply? && status . thread . nil? && Request . valid_url? ( in_reply_to_uri )
ThreadResolveWorker . perform_async ( status . id , 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 ] )
ActivityPub :: RawDistributionWorker . perform_async ( Oj . dump ( @json ) , replied_to_status . account_id , [ @account . preferred_inbox_url ] )
end
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
def lock_options
{ redis : Redis . current , key : " create: #{ @object [ 'id' ] } " }
{ redis : Redis . current , key : " create: #{ @object [ 'id' ] } " }
end
end
def poll_lock_options
{ redis : Redis . current , key : " vote: #{ replied_to_status . poll_id } : #{ @account . id } " }
end
end
end