about summary refs log tree commit diff
path: root/app/lib
diff options
context:
space:
mode:
authorReverite <github@reverite.sh>2019-03-10 19:19:52 -0700
committerReverite <github@reverite.sh>2019-03-10 19:19:52 -0700
commit229e2726cad36066afb210d7087a40cd9f955483 (patch)
treea14d55e9469f1f339fc40b777827aa4886bb7889 /app/lib
parent715c552fe4c1b2d59bf1f281d77b6e2546bdb531 (diff)
parent3cef04610cd809c7bd01adc00d34fb3d25261a16 (diff)
Merge branch 'glitch'
Diffstat (limited to 'app/lib')
-rw-r--r--app/lib/activitypub/activity.rb2
-rw-r--r--app/lib/activitypub/activity/create.rb50
-rw-r--r--app/lib/activitypub/tag_manager.rb6
-rw-r--r--app/lib/formatter.rb4
-rw-r--r--app/lib/ostatus/atom_serializer.rb2
5 files changed, 60 insertions, 4 deletions
diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb
index 11fa3363a..54b175613 100644
--- a/app/lib/activitypub/activity.rb
+++ b/app/lib/activitypub/activity.rb
@@ -4,7 +4,7 @@ class ActivityPub::Activity
   include JsonLdHelper
   include Redisable
 
-  SUPPORTED_TYPES = %w(Note).freeze
+  SUPPORTED_TYPES = %w(Note Question).freeze
   CONVERTED_TYPES = %w(Image Video Article Page).freeze
 
   def initialize(json, account, **options)
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index d7bd65c80..7e4e57ead 100644
--- a/app/lib/activitypub/activity/create.rb
+++ b/app/lib/activitypub/activity/create.rb
@@ -6,7 +6,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
 
     RedisLock.acquire(lock_options) do |lock|
       if lock.acquired?
-        return if delete_arrived_first?(object_uri)
+        return if delete_arrived_first?(object_uri) || poll_vote?
 
         @status = find_existing_status
 
@@ -40,6 +40,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
     end
 
     resolve_thread(@status)
+    fetch_replies(@status)
     distribute(@status)
     forward_for_reply if @status.public_visibility? || @status.unlisted_visibility?
   end
@@ -67,6 +68,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
         thread: replied_to_status,
         conversation: conversation_from_uri(@object['conversation']),
         media_attachment_ids: process_attachments.take(4).map(&:id),
+        owned_poll: process_poll,
       }
     end
   end
@@ -159,7 +161,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
     return if tag['href'].blank?
 
     account = account_from_uri(tag['href'])
-    account = ::FetchRemoteAccountService.new.call(tag['href'], id: false) if account.nil?
+    account = ::FetchRemoteAccountService.new.call(tag['href']) if account.nil?
 
     return if account.nil?
 
@@ -208,11 +210,55 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
     media_attachments
   end
 
+  def process_poll
+    return unless @object['type'] == 'Question' && (@object['anyOf'].is_a?(Array) || @object['oneOf'].is_a?(Array))
+
+    expires_at = begin
+      if @object['closed'].is_a?(String)
+        @object['closed']
+      elsif !@object['closed'].nil? && !@object['closed'].is_a?(FalseClass)
+        Time.now.utc
+      else
+        @object['endTime']
+      end
+    end
+
+    if @object['anyOf'].is_a?(Array)
+      multiple = true
+      items    = @object['anyOf']
+    else
+      multiple = false
+      items    = @object['oneOf']
+    end
+
+    @account.polls.new(
+      multiple: multiple,
+      expires_at: expires_at,
+      options: items.map { |item| item['name'].presence || item['content'] },
+      cached_tallies: items.map { |item| item.dig('replies', 'totalItems') || 0 }
+    )
+  end
+
+  def poll_vote?
+    return false if replied_to_status.nil? || replied_to_status.poll.nil? || !replied_to_status.local? || !replied_to_status.poll.options.include?(@object['name'])
+    return true if replied_to_status.poll.expired?
+    replied_to_status.poll.votes.create!(account: @account, choice: replied_to_status.poll.options.index(@object['name']), uri: @object['id'])
+  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)
   end
 
+  def fetch_replies(status)
+    collection = @object['replies']
+    return if collection.nil?
+    replies = ActivityPub::FetchRepliesService.new.call(status, collection, false)
+    return unless replies.nil?
+    uri = value_or_id(collection)
+    ActivityPub::FetchRepliesWorker.perform_async(status.id, uri) unless uri.nil?
+  end
+
   def conversation_from_uri(uri)
     return nil if uri.nil?
     return Conversation.find_by(id: OStatus::TagManager.instance.unique_tag_to_local_id(uri, 'Conversation')) if OStatus::TagManager.instance.local_id?(uri)
diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb
index be3a562d0..892bb9974 100644
--- a/app/lib/activitypub/tag_manager.rb
+++ b/app/lib/activitypub/tag_manager.rb
@@ -48,6 +48,12 @@ class ActivityPub::TagManager
     activity_account_status_url(target.account, target)
   end
 
+  def replies_uri_for(target, page_params = nil)
+    raise ArgumentError, 'target must be a local activity' unless %i(note comment activity).include?(target.object_type) && target.local?
+
+    replies_account_status_url(target.account, target, page_params)
+  end
+
   # Primary audience of a status
   # Public statuses go out to primarily the public collection
   # Unlisted and private statuses go out primarily to the followers collection
diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb
index 0653214f5..464e1ee7e 100644
--- a/app/lib/formatter.rb
+++ b/app/lib/formatter.rb
@@ -19,6 +19,10 @@ class Formatter
 
     raw_content = status.text
 
+    if options[:inline_poll_options] && status.poll
+      raw_content = raw_content + "\n\n" + status.poll.options.map { |title| "[ ] #{title}" }.join("\n")
+    end
+
     return '' if raw_content.blank?
 
     unless status.local?
diff --git a/app/lib/ostatus/atom_serializer.rb b/app/lib/ostatus/atom_serializer.rb
index 7a181fb40..9a05d96cf 100644
--- a/app/lib/ostatus/atom_serializer.rb
+++ b/app/lib/ostatus/atom_serializer.rb
@@ -352,7 +352,7 @@ class OStatus::AtomSerializer
     append_element(entry, 'link', nil, rel: :alternate, type: 'application/activity+json', href: ActivityPub::TagManager.instance.uri_for(status)) if status.account.local?
 
     append_element(entry, 'summary', status.spoiler_text, 'xml:lang': status.language) if status.spoiler_text?
-    append_element(entry, 'content', Formatter.instance.format(status).to_str || '.', type: 'html', 'xml:lang': status.language)
+    append_element(entry, 'content', Formatter.instance.format(status, inline_poll_options: true).to_str || '.', type: 'html', 'xml:lang': status.language)
 
     status.active_mentions.sort_by(&:id).each do |mentioned|
       append_element(entry, 'link', nil, rel: :mentioned, 'ostatus:object-type': OStatus::TagManager::TYPES[:person], href: OStatus::TagManager.instance.uri_for(mentioned.account))