about summary refs log tree commit diff
path: root/app/services
diff options
context:
space:
mode:
Diffstat (limited to 'app/services')
-rw-r--r--app/services/backup_service.rb21
-rw-r--r--app/services/batched_remove_status_service.rb11
-rw-r--r--app/services/fan_out_on_write_service.rb20
-rw-r--r--app/services/post_status_service.rb13
-rw-r--r--app/services/process_mentions_service.rb4
-rw-r--r--app/services/reblog_service.rb7
-rw-r--r--app/services/remove_status_service.rb8
7 files changed, 74 insertions, 10 deletions
diff --git a/app/services/backup_service.rb b/app/services/backup_service.rb
index 4cfa22ab8..5fcc98057 100644
--- a/app/services/backup_service.rb
+++ b/app/services/backup_service.rb
@@ -45,6 +45,7 @@ class BackupService < BaseService
           dump_media_attachments!(tar)
           dump_outbox!(tar)
           dump_likes!(tar)
+          dump_bookmarks!(tar)
           dump_actor!(tar)
         end
       end
@@ -85,6 +86,7 @@ class BackupService < BaseService
     actor[:image][:url] = 'header' + File.extname(actor[:image][:url]) if actor[:image]
     actor[:outbox]      = 'outbox.json'
     actor[:likes]       = 'likes.json'
+    actor[:bookmarks]   = 'bookmarks.json'
 
     download_to_tar(tar, account.avatar, 'avatar' + File.extname(account.avatar.path)) if account.avatar.exists?
     download_to_tar(tar, account.header, 'header' + File.extname(account.header.path)) if account.header.exists?
@@ -115,6 +117,25 @@ class BackupService < BaseService
     end
   end
 
+  def dump_bookmarks!(tar)
+    collection = serialize(ActivityPub::CollectionPresenter.new(id: 'bookmarks.json', type: :ordered, size: 0, items: []), ActivityPub::CollectionSerializer)
+
+    Status.reorder(nil).joins(:bookmarks).includes(:account).merge(account.bookmarks).find_in_batches do |statuses|
+      statuses.each do |status|
+        collection[:totalItems] += 1
+        collection[:orderedItems] << ActivityPub::TagManager.instance.uri_for(status)
+      end
+
+      GC.start
+    end
+
+    json = Oj.dump(collection)
+
+    tar.add_file_simple('bookmarks.json', 0o444, json.bytesize) do |io|
+      io.write(json)
+    end
+  end
+
   def collection_presenter
     ActivityPub::CollectionPresenter.new(
       id: 'outbox.json',
diff --git a/app/services/batched_remove_status_service.rb b/app/services/batched_remove_status_service.rb
index e328b1739..02f7076f7 100644
--- a/app/services/batched_remove_status_service.rb
+++ b/app/services/batched_remove_status_service.rb
@@ -46,6 +46,7 @@ class BatchedRemoveStatusService < BaseService
     # Cannot be batched
     statuses.each do |status|
       unpush_from_public_timelines(status)
+      unpush_from_direct_timelines(status) if status.direct_visibility?
       batch_salmon_slaps(status) if status.local?
     end
 
@@ -102,6 +103,16 @@ class BatchedRemoveStatusService < BaseService
     end
   end
 
+  def unpush_from_direct_timelines(status)
+    payload = @json_payloads[status.id]
+    redis.pipelined do
+      @mentions[status.id].each do |mention|
+        redis.publish("timeline:direct:#{mention.account.id}", payload) if mention.account.local?
+      end
+      redis.publish("timeline:direct:#{status.account.id}", payload) if status.account.local?
+    end
+  end
+
   def batch_salmon_slaps(status)
     return if @mentions[status.id].empty?
 
diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb
index f3e9c855d..b66dc342e 100644
--- a/app/services/fan_out_on_write_service.rb
+++ b/app/services/fan_out_on_write_service.rb
@@ -6,23 +6,27 @@ class FanOutOnWriteService < BaseService
   def call(status)
     raise Mastodon::RaceConditionError if status.visibility.nil?
 
+    deliver_to_self(status) if status.account.local?
+
     render_anonymous_payload(status)
 
     if status.direct_visibility?
+      deliver_to_mentioned_followers(status)
+      deliver_to_direct_timelines(status)
       deliver_to_own_conversation(status)
     elsif status.limited_visibility?
       deliver_to_mentioned_followers(status)
     else
-      deliver_to_self(status) if status.account.local?
       deliver_to_followers(status)
       deliver_to_lists(status)
     end
 
-    return if status.account.silenced? || !status.public_visibility? || status.reblog?
+    return if status.account.silenced? || !status.public_visibility?
+    return if status.reblog? && !Setting.show_reblogs_in_public_timelines
 
     deliver_to_hashtags(status)
 
-    return if status.reply? && status.in_reply_to_account_id != status.account_id
+    return if status.reply? && status.in_reply_to_account_id != status.account_id && !Setting.show_replies_in_public_timelines
 
     deliver_to_public(status)
     deliver_to_media(status) if status.media_attachments.any?
@@ -91,6 +95,16 @@ class FanOutOnWriteService < BaseService
     Redis.current.publish('timeline:public:local:media', @payload) if status.local?
   end
 
+  def deliver_to_direct_timelines(status)
+    Rails.logger.debug "Delivering status #{status.id} to direct timelines"
+
+    status.mentions.includes(:account).each do |mention|
+      Redis.current.publish("timeline:direct:#{mention.account.id}", @payload) if mention.account.local?
+    end
+
+    Redis.current.publish("timeline:direct:#{status.account.id}", @payload) if status.account.local?
+  end
+
   def deliver_to_own_conversation(status)
     AccountConversation.add_status(status.account, status)
   end
diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb
index e7366c7e8..333bf88d8 100644
--- a/app/services/post_status_service.rb
+++ b/app/services/post_status_service.rb
@@ -47,7 +47,10 @@ class PostStatusService < BaseService
   private
 
   def preprocess_attributes!
-    @text         = @options.delete(:spoiler_text) if @text.blank? && @options[:spoiler_text].present?
+    if @text.blank? && @options[:spoiler_text].present?
+     @text = '.'
+     @text = @media.find(&:video?) ? '📹' : '🖼' if @media.size > 0
+    end
     @visibility   = @options[:visibility] || @account.user&.setting_default_privacy
     @visibility   = :unlisted if @visibility == :public && @account.silenced
     @scheduled_at = @options[:scheduled_at]&.to_datetime
@@ -88,8 +91,12 @@ class PostStatusService < BaseService
   def postprocess_status!
     LinkCrawlWorker.perform_async(@status.id) unless @status.spoiler_text?
     DistributionWorker.perform_async(@status.id)
-    Pubsubhubbub::DistributionWorker.perform_async(@status.stream_entry.id)
-    ActivityPub::DistributionWorker.perform_async(@status.id)
+
+    unless @status.local_only?
+      Pubsubhubbub::DistributionWorker.perform_async(@status.stream_entry.id)
+      ActivityPub::DistributionWorker.perform_async(@status.id)
+    end
+
     PollExpirationNotifyWorker.perform_at(@status.poll.expires_at, @status.poll.id) if @status.poll
   end
 
diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb
index 2595c5fd3..1d9448e21 100644
--- a/app/services/process_mentions_service.rb
+++ b/app/services/process_mentions_service.rb
@@ -48,9 +48,9 @@ class ProcessMentionsService < BaseService
 
     if mentioned_account.local?
       LocalNotificationWorker.perform_async(mentioned_account.id, mention.id, mention.class.name)
-    elsif mentioned_account.ostatus? && !@status.stream_entry.hidden?
+    elsif mentioned_account.ostatus? && !@status.stream_entry.hidden? && !@status.local_only?
       NotificationWorker.perform_async(ostatus_xml, @status.account_id, mentioned_account.id)
-    elsif mentioned_account.activitypub?
+    elsif mentioned_account.activitypub? && !@status.local_only?
       ActivityPub::DeliveryWorker.perform_async(activitypub_json, mention.status.account_id, mentioned_account.inbox_url)
     end
   end
diff --git a/app/services/reblog_service.rb b/app/services/reblog_service.rb
index ff48d9c75..deaa0549e 100644
--- a/app/services/reblog_service.rb
+++ b/app/services/reblog_service.rb
@@ -21,8 +21,11 @@ class ReblogService < BaseService
     reblog = account.statuses.create!(reblog: reblogged_status, text: '', visibility: options[:visibility] || account.user&.setting_default_privacy)
 
     DistributionWorker.perform_async(reblog.id)
-    Pubsubhubbub::DistributionWorker.perform_async(reblog.stream_entry.id)
-    ActivityPub::DistributionWorker.perform_async(reblog.id)
+
+    unless reblogged_status.local_only?
+      Pubsubhubbub::DistributionWorker.perform_async(reblog.stream_entry.id)
+      ActivityPub::DistributionWorker.perform_async(reblog.id)
+    end
 
     create_notification(reblog)
     bump_potential_friendship(account, reblog)
diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb
index 747f209f3..6e4998e07 100644
--- a/app/services/remove_status_service.rb
+++ b/app/services/remove_status_service.rb
@@ -24,6 +24,7 @@ class RemoveStatusService < BaseService
         remove_from_hashtags
         remove_from_public
         remove_from_media if status.media_attachments.any?
+        remove_from_direct if status.direct_visibility?
 
         @status.destroy!
       else
@@ -163,6 +164,13 @@ class RemoveStatusService < BaseService
     redis.publish('timeline:public:local:media', @payload) if @status.local?
   end
 
+  def remove_from_direct
+    @mentions.each do |mention|
+      Redis.current.publish("timeline:direct:#{mention.account.id}", @payload) if mention.account.local?
+    end
+    Redis.current.publish("timeline:direct:#{@account.id}", @payload) if @account.local?
+  end
+
   def lock_options
     { redis: Redis.current, key: "distribute:#{@status.id}" }
   end