about summary refs log tree commit diff
path: root/app/services
diff options
context:
space:
mode:
authorClaire <claire.github-309c@sitedethib.com>2022-04-07 15:03:31 +0200
committerGitHub <noreply@github.com>2022-04-07 15:03:31 +0200
commit3f9959a4b66c8d33a1de6dd13972327ff62f2cd3 (patch)
tree56bef462d8ec527b893e5f02d687d419b5440cc9 /app/services
parent00c9363f07081e0149533023992fba47dd905384 (diff)
parente2f4bafc136cb0853321ed4be1b02106bec8bc93 (diff)
Merge pull request #1734 from ClearlyClaire/glitch-soc/merge-upstream
Merge upstream changes
Diffstat (limited to 'app/services')
-rw-r--r--app/services/activitypub/fetch_featured_collection_service.rb16
-rw-r--r--app/services/activitypub/process_status_update_service.rb50
-rw-r--r--app/services/remove_status_service.rb4
3 files changed, 55 insertions, 15 deletions
diff --git a/app/services/activitypub/fetch_featured_collection_service.rb b/app/services/activitypub/fetch_featured_collection_service.rb
index 780741feb..66234b711 100644
--- a/app/services/activitypub/fetch_featured_collection_service.rb
+++ b/app/services/activitypub/fetch_featured_collection_service.rb
@@ -22,9 +22,19 @@ class ActivityPub::FetchFeaturedCollectionService < BaseService
   private
 
   def process_items(items)
-    status_ids = items.map { |item| value_or_id(item) }
-                      .filter_map { |uri| ActivityPub::FetchRemoteStatusService.new.call(uri, on_behalf_of: local_follower) unless ActivityPub::TagManager.instance.local_uri?(uri) }
-                      .filter_map { |status| status.id if status.account_id == @account.id }
+    status_ids = items.filter_map do |item|
+      uri = value_or_id(item)
+      next if ActivityPub::TagManager.instance.local_uri?(uri)
+
+      status = ActivityPub::FetchRemoteStatusService.new.call(uri, on_behalf_of: local_follower)
+      next unless status.account_id == @account.id
+
+      status.id
+    rescue ActiveRecord::RecordInvalid => e
+      Rails.logger.debug "Invalid pinned status #{uri}: #{e.message}"
+      nil
+    end
+
     to_remove = []
     to_add    = status_ids
 
diff --git a/app/services/activitypub/process_status_update_service.rb b/app/services/activitypub/process_status_update_service.rb
index 6dc14d8c2..3d9d9cb84 100644
--- a/app/services/activitypub/process_status_update_service.rb
+++ b/app/services/activitypub/process_status_update_service.rb
@@ -17,10 +17,19 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
     # Only native types can be updated at the moment
     return @status if !expected_type? || already_updated_more_recently?
 
-    last_edit_date = status.edited_at.presence || status.created_at
+    if @status_parser.edited_at.present? && (@status.edited_at.nil? || @status_parser.edited_at > @status.edited_at)
+      handle_explicit_update!
+    else
+      handle_implicit_update!
+    end
+
+    @status
+  end
+
+  private
 
-    # Since we rely on tracking of previous changes, ensure clean slate
-    status.clear_changes_information
+  def handle_explicit_update!
+    last_edit_date = @status.edited_at.presence || @status.created_at
 
     # Only allow processing one create/update per status at a time
     RedisLock.acquire(lock_options) do |lock|
@@ -45,12 +54,20 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
       end
     end
 
-    forward_activity! if significant_changes? && @status_parser.edited_at.present? && @status_parser.edited_at > last_edit_date
-
-    @status
+    forward_activity! if significant_changes? && @status_parser.edited_at > last_edit_date
   end
 
-  private
+  def handle_implicit_update!
+    RedisLock.acquire(lock_options) do |lock|
+      if lock.acquired?
+        update_poll!(allow_significant_changes: false)
+      else
+        raise Mastodon::RaceConditionError
+      end
+    end
+
+    queue_poll_notifications!
+  end
 
   def update_media_attachments!
     previous_media_attachments     = @status.media_attachments.to_a
@@ -98,7 +115,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
     @media_attachments_changed = true if @status.ordered_media_attachment_ids != previous_media_attachments_ids
   end
 
-  def update_poll!
+  def update_poll!(allow_significant_changes: true)
     previous_poll        = @status.preloadable_poll
     @previous_expires_at = previous_poll&.expires_at
     poll_parser          = ActivityPub::Parser::PollParser.new(@json)
@@ -109,6 +126,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
       # If for some reasons the options were changed, it invalidates all previous
       # votes, so we need to remove them
       @poll_changed = true if poll_parser.significantly_changes?(poll)
+      return if @poll_changed && !allow_significant_changes
 
       poll.last_fetched_at = Time.now.utc
       poll.options         = poll_parser.options
@@ -121,6 +139,8 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
 
       @status.poll_id = poll.id
     elsif previous_poll.present?
+      return unless allow_significant_changes
+
       previous_poll.destroy!
       @poll_changed = true
       @status.poll_id = nil
@@ -132,7 +152,10 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
     @status.spoiler_text = @status_parser.spoiler_text || ''
     @status.sensitive    = @account.sensitized? || @status_parser.sensitive || false
     @status.language     = @status_parser.language
-    @status.edited_at    = @status_parser.edited_at || Time.now.utc if significant_changes?
+
+    @significant_changes = text_significantly_changed? || @status.spoiler_text_changed? || @media_attachments_changed || @poll_changed
+
+    @status.edited_at = @status_parser.edited_at if significant_changes?
 
     @status.save!
   end
@@ -243,7 +266,14 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
   end
 
   def significant_changes?
-    @status.text_changed? || @status.text_previously_changed? || @status.spoiler_text_changed? || @status.spoiler_text_previously_changed? || @media_attachments_changed || @poll_changed
+    @significant_changes
+  end
+
+  def text_significantly_changed?
+    return false unless @status.text_changed?
+
+    old, new = @status.text_change
+    HtmlAwareFormatter.new(old, false).to_s != HtmlAwareFormatter.new(new, false).to_s
   end
 
   def already_updated_more_recently?
diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb
index c28e16572..dfe9f9ac5 100644
--- a/app/services/remove_status_service.rb
+++ b/app/services/remove_status_service.rb
@@ -17,10 +17,10 @@ class RemoveStatusService < BaseService
     @account  = status.account
     @options  = options
 
-    @status.discard
-
     RedisLock.acquire(lock_options) do |lock|
       if lock.acquired?
+        @status.discard
+
         remove_from_self if @account.local?
         remove_from_followers
         remove_from_lists