about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/api/v1/follow_requests_controller.rb4
-rw-r--r--app/controllers/concerns/obfuscate_filename.rb1
-rw-r--r--app/helpers/atom_builder_helper.rb8
-rw-r--r--app/lib/tag_manager.rb22
-rw-r--r--app/models/favourite.rb4
-rw-r--r--app/models/follow_request.rb36
-rw-r--r--app/models/stream_entry.rb2
-rw-r--r--app/services/authorize_follow_service.rb11
-rw-r--r--app/services/block_service.rb4
-rw-r--r--app/services/concerns/stream_entry_renderer.rb8
-rw-r--r--app/services/favourite_service.rb4
-rw-r--r--app/services/follow_service.rb13
-rw-r--r--app/services/process_interaction_service.rb14
-rw-r--r--app/services/process_mentions_service.rb4
-rw-r--r--app/services/reblog_service.rb10
-rw-r--r--app/services/reject_follow_service.rb11
-rw-r--r--app/services/remove_status_service.rb4
-rw-r--r--app/services/send_interaction_service.rb19
-rw-r--r--app/services/unblock_service.rb4
-rw-r--r--app/services/unfavourite_service.rb4
-rw-r--r--app/services/unfollow_service.rb4
-rw-r--r--app/services/update_remote_profile_service.rb1
-rw-r--r--app/workers/notification_worker.rb4
-rw-r--r--app/workers/push_notification_worker.rb11
-rw-r--r--spec/helpers/atom_builder_helper_spec.rb2
25 files changed, 148 insertions, 61 deletions
diff --git a/app/controllers/api/v1/follow_requests_controller.rb b/app/controllers/api/v1/follow_requests_controller.rb
index a30e97e71..740083735 100644
--- a/app/controllers/api/v1/follow_requests_controller.rb
+++ b/app/controllers/api/v1/follow_requests_controller.rb
@@ -18,12 +18,12 @@ class Api::V1::FollowRequestsController < ApiController
   end
 
   def authorize
-    FollowRequest.find_by!(account_id: params[:id], target_account: current_account).authorize!
+    AuthorizeFollowService.new.call(Account.find(params[:id]), current_account)
     render_empty
   end
 
   def reject
-    FollowRequest.find_by!(account_id: params[:id], target_account: current_account).reject!
+    RejectFollowService.new.call(Account.find(params[:id]), current_account)
     render_empty
   end
 end
diff --git a/app/controllers/concerns/obfuscate_filename.rb b/app/controllers/concerns/obfuscate_filename.rb
index 9f12cb7e9..dde7ce8c6 100644
--- a/app/controllers/concerns/obfuscate_filename.rb
+++ b/app/controllers/concerns/obfuscate_filename.rb
@@ -1,4 +1,5 @@
 # frozen_string_literal: true
+
 module ObfuscateFilename
   extend ActiveSupport::Concern
 
diff --git a/app/helpers/atom_builder_helper.rb b/app/helpers/atom_builder_helper.rb
index fb8f0976c..5d20f8c2d 100644
--- a/app/helpers/atom_builder_helper.rb
+++ b/app/helpers/atom_builder_helper.rb
@@ -143,6 +143,10 @@ module AtomBuilderHelper
     xml.link(:rel => 'mentioned', :href => TagManager::COLLECTIONS[:public], 'ostatus:object-type' => TagManager::TYPES[:collection])
   end
 
+  def privacy_scope(xml, level)
+    xml['mastodon'].scope(level)
+  end
+
   def include_author(xml, account)
     object_type      xml, :person
     uri              xml, TagManager.instance.uri_for(account)
@@ -152,6 +156,7 @@ module AtomBuilderHelper
     link_alternate   xml, TagManager.instance.url_for(account)
     link_avatar      xml, account
     portable_contact xml, account
+    privacy_scope    xml, account.locked? ? :private : :public
   end
 
   def rich_content(xml, activity)
@@ -216,6 +221,7 @@ module AtomBuilderHelper
           end
 
           category(xml, 'nsfw') if stream_entry.target.sensitive?
+          privacy_scope(xml, stream_entry.target.visibility)
         end
       end
     end
@@ -237,6 +243,7 @@ module AtomBuilderHelper
     end
 
     category(xml, 'nsfw') if stream_entry.activity.sensitive?
+    privacy_scope(xml, stream_entry.activity.visibility)
   end
 
   private
@@ -249,6 +256,7 @@ module AtomBuilderHelper
                'xmlns:poco'     => TagManager::POCO_XMLNS,
                'xmlns:media'    => TagManager::MEDIA_XMLNS,
                'xmlns:ostatus'  => TagManager::OS_XMLNS,
+               'xmlns:mastodon' => TagManager::MTDN_XMLNS,
              }, &block)
   end
 
diff --git a/app/lib/tag_manager.rb b/app/lib/tag_manager.rb
index 2508eea97..9fef70fda 100644
--- a/app/lib/tag_manager.rb
+++ b/app/lib/tag_manager.rb
@@ -7,15 +7,18 @@ class TagManager
   include RoutingHelper
 
   VERBS = {
-    post:       'http://activitystrea.ms/schema/1.0/post',
-    share:      'http://activitystrea.ms/schema/1.0/share',
-    favorite:   'http://activitystrea.ms/schema/1.0/favorite',
-    unfavorite: 'http://activitystrea.ms/schema/1.0/unfavorite',
-    delete:     'http://activitystrea.ms/schema/1.0/delete',
-    follow:     'http://activitystrea.ms/schema/1.0/follow',
-    unfollow:   'http://ostatus.org/schema/1.0/unfollow',
-    block:      'http://mastodon.social/schema/1.0/block',
-    unblock:    'http://mastodon.social/schema/1.0/unblock',
+    post:           'http://activitystrea.ms/schema/1.0/post',
+    share:          'http://activitystrea.ms/schema/1.0/share',
+    favorite:       'http://activitystrea.ms/schema/1.0/favorite',
+    unfavorite:     'http://activitystrea.ms/schema/1.0/unfavorite',
+    delete:         'http://activitystrea.ms/schema/1.0/delete',
+    follow:         'http://activitystrea.ms/schema/1.0/follow',
+    request_friend: 'http://activitystrea.ms/schema/1.0/request-friend',
+    authorize:      'http://activitystrea.ms/schema/1.0/authorize',
+    reject:         'http://activitystrea.ms/schema/1.0/reject',
+    unfollow:       'http://ostatus.org/schema/1.0/unfollow',
+    block:          'http://mastodon.social/schema/1.0/block',
+    unblock:        'http://mastodon.social/schema/1.0/unblock',
   }.freeze
 
   TYPES = {
@@ -38,6 +41,7 @@ class TagManager
   POCO_XMLNS  = 'http://portablecontacts.net/spec/1.0'
   DFRN_XMLNS  = 'http://purl.org/macgirvin/dfrn/1.0'
   OS_XMLNS    = 'http://ostatus.org/schema/1.0'
+  MTDN_XMLNS  = 'http://mastodon.social/schema/1.0'
 
   def unique_tag(date, id, type)
     "tag:#{Rails.configuration.x.local_domain},#{date.strftime('%Y-%m-%d')}:objectId=#{id}:objectType=#{type}"
diff --git a/app/models/favourite.rb b/app/models/favourite.rb
index 3f3616dce..cd8e2098c 100644
--- a/app/models/favourite.rb
+++ b/app/models/favourite.rb
@@ -12,11 +12,11 @@ class Favourite < ApplicationRecord
   validates :status_id, uniqueness: { scope: :account_id }
 
   def verb
-    :favorite
+    destroyed? ? :unfavorite : :favorite
   end
 
   def title
-    "#{account.acct} favourited a status by #{status.account.acct}"
+    destroyed? ? "#{account.acct} no longer favourites a status by #{status.account.acct}" : "#{account.acct} favourited a status by #{status.account.acct}"
   end
 
   delegate :object_type, to: :target
diff --git a/app/models/follow_request.rb b/app/models/follow_request.rb
index 936ad0691..989c2c2a2 100644
--- a/app/models/follow_request.rb
+++ b/app/models/follow_request.rb
@@ -2,6 +2,7 @@
 
 class FollowRequest < ApplicationRecord
   include Paginable
+  include Streamable
 
   belongs_to :account
   belongs_to :target_account, class_name: 'Account'
@@ -12,12 +13,47 @@ class FollowRequest < ApplicationRecord
   validates :account_id, uniqueness: { scope: :target_account_id }
 
   def authorize!
+    @verb = :authorize
+
     account.follow!(target_account)
     MergeWorker.perform_async(target_account.id, account.id)
+
     destroy!
   end
 
   def reject!
+    @verb = :reject
     destroy!
   end
+
+  def verb
+    destroyed? ? (@verb || :delete) : :request_friend
+  end
+
+  def target
+    target_account
+  end
+
+  def object_type
+    :person
+  end
+
+  def hidden?
+    true
+  end
+
+  def title
+    if destroyed?
+      case @verb
+      when :authorize
+        "#{target_account.acct} authorized #{account.acct}'s request to follow"
+      when :reject
+        "#{target_account.acct} rejected #{account.acct}'s request to follow"
+      else
+        "#{account.acct} withdrew the request to follow #{target_account.acct}"
+      end
+    else
+      "#{account.acct} requested to follow #{target_account.acct}"
+    end
+  end
 end
diff --git a/app/models/stream_entry.rb b/app/models/stream_entry.rb
index fcc691bef..e0b85be15 100644
--- a/app/models/stream_entry.rb
+++ b/app/models/stream_entry.rb
@@ -30,7 +30,7 @@ class StreamEntry < ApplicationRecord
   end
 
   def targeted?
-    [:follow, :unfollow, :block, :unblock, :share, :favorite].include? verb
+    [:follow, :request_friend, :authorize, :unfollow, :block, :unblock, :share, :favorite].include? verb
   end
 
   def target
diff --git a/app/services/authorize_follow_service.rb b/app/services/authorize_follow_service.rb
new file mode 100644
index 000000000..1590d8433
--- /dev/null
+++ b/app/services/authorize_follow_service.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AuthorizeFollowService < BaseService
+  include StreamEntryRenderer
+
+  def call(source_account, target_account)
+    follow_request = FollowRequest.find_by!(account: source_account, target_account: target_account)
+    follow_request.authorize!
+    NotificationWorker.perform_async(stream_entry_to_xml(follow_request.stream_entry), target_account.id, source_account.id) unless source_account.local?
+  end
+end
diff --git a/app/services/block_service.rb b/app/services/block_service.rb
index e04b6cc39..095d2a8eb 100644
--- a/app/services/block_service.rb
+++ b/app/services/block_service.rb
@@ -1,6 +1,8 @@
 # frozen_string_literal: true
 
 class BlockService < BaseService
+  include StreamEntryRenderer
+
   def call(account, target_account)
     return if account.id == target_account.id
 
@@ -10,6 +12,6 @@ class BlockService < BaseService
     block = account.block!(target_account)
 
     BlockWorker.perform_async(account.id, target_account.id)
-    NotificationWorker.perform_async(block.stream_entry.id, target_account.id) unless target_account.local?
+    NotificationWorker.perform_async(stream_entry_to_xml(block.stream_entry), account.id, target_account.id) unless target_account.local?
   end
 end
diff --git a/app/services/concerns/stream_entry_renderer.rb b/app/services/concerns/stream_entry_renderer.rb
new file mode 100644
index 000000000..a4255daea
--- /dev/null
+++ b/app/services/concerns/stream_entry_renderer.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+module StreamEntryRenderer
+  def stream_entry_to_xml(stream_entry)
+    renderer = StreamEntriesController.renderer.new(method: 'get', http_host: Rails.configuration.x.local_domain, https: Rails.configuration.x.use_https)
+    renderer.render(:show, assigns: { stream_entry: stream_entry }, formats: [:atom])
+  end
+end
diff --git a/app/services/favourite_service.rb b/app/services/favourite_service.rb
index d5fbd29e9..ce1722b77 100644
--- a/app/services/favourite_service.rb
+++ b/app/services/favourite_service.rb
@@ -1,6 +1,8 @@
 # frozen_string_literal: true
 
 class FavouriteService < BaseService
+  include StreamEntryRenderer
+
   # Favourite a status and notify remote user
   # @param [Account] account
   # @param [Status] status
@@ -15,7 +17,7 @@ class FavouriteService < BaseService
     if status.local?
       NotifyService.new.call(favourite.status.account, favourite)
     else
-      NotificationWorker.perform_async(favourite.stream_entry.id, status.account_id)
+      NotificationWorker.perform_async(stream_entry_to_xml(favourite.stream_entry), account.id, status.account_id)
     end
 
     favourite
diff --git a/app/services/follow_service.rb b/app/services/follow_service.rb
index 9f34cb6ac..45b7895b6 100644
--- a/app/services/follow_service.rb
+++ b/app/services/follow_service.rb
@@ -1,6 +1,8 @@
 # frozen_string_literal: true
 
 class FollowService < BaseService
+  include StreamEntryRenderer
+
   # Follow a remote user, notify remote user about the follow
   # @param [Account] source_account From which to follow
   # @param [String] uri User URI to follow in the form of username@domain
@@ -20,10 +22,13 @@ class FollowService < BaseService
   private
 
   def request_follow(source_account, target_account)
-    return unless target_account.local?
-
     follow_request = FollowRequest.create!(account: source_account, target_account: target_account)
-    NotifyService.new.call(target_account, follow_request)
+
+    if target_account.local?
+      NotifyService.new.call(target_account, follow_request)
+    else
+      NotificationWorker.perform_async(stream_entry_to_xml(follow_request.stream_entry), source_account.id, target_account.id)
+    end
 
     follow_request
   end
@@ -35,7 +40,7 @@ class FollowService < BaseService
       NotifyService.new.call(target_account, follow)
     else
       subscribe_service.call(target_account)
-      NotificationWorker.perform_async(follow.stream_entry.id, target_account.id)
+      NotificationWorker.perform_async(stream_entry_to_xml(follow.stream_entry), source_account.id, target_account.id)
     end
 
     MergeWorker.perform_async(target_account.id, source_account.id)
diff --git a/app/services/process_interaction_service.rb b/app/services/process_interaction_service.rb
index 5f91e3127..27f0758ce 100644
--- a/app/services/process_interaction_service.rb
+++ b/app/services/process_interaction_service.rb
@@ -29,6 +29,10 @@ class ProcessInteractionService < BaseService
       case verb(xml)
       when :follow
         follow!(account, target_account) unless target_account.locked? || target_account.blocking?(account)
+      when :request_friend
+        follow_request!(account, target_account) unless !target_account.locked? || target_account.blocking?(account)
+      when :authorize
+        authorize_follow_request!(account, target_account)
       when :unfollow
         unfollow!(account, target_account)
       when :favorite
@@ -72,6 +76,16 @@ class ProcessInteractionService < BaseService
     NotifyService.new.call(target_account, follow)
   end
 
+  def follow_request(account, target_account)
+    follow_request = FollowRequest.create!(account: account, target_account: target_account)
+    NotifyService.new.call(target_account, follow_request)
+  end
+
+  def authorize_target_account!(account, target_account)
+    follow_request = FollowRequest.find_by(account: target_account, target_account: account)
+    follow_request&.authorize!
+  end
+
   def unfollow!(account, target_account)
     account.unfollow!(target_account)
   end
diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb
index 72568e702..67fd3dcf7 100644
--- a/app/services/process_mentions_service.rb
+++ b/app/services/process_mentions_service.rb
@@ -1,6 +1,8 @@
 # frozen_string_literal: true
 
 class ProcessMentionsService < BaseService
+  include StreamEntryRenderer
+
   # Scan status for mentions and fetch remote mentioned users, create
   # local mention pointers, send Salmon notifications to mentioned
   # remote users
@@ -33,7 +35,7 @@ class ProcessMentionsService < BaseService
       if mentioned_account.local?
         NotifyService.new.call(mentioned_account, mention)
       else
-        NotificationWorker.perform_async(status.stream_entry.id, mentioned_account.id)
+        NotificationWorker.perform_async(stream_entry_to_xml(status.stream_entry), status.account_id, mentioned_account.id)
       end
     end
   end
diff --git a/app/services/reblog_service.rb b/app/services/reblog_service.rb
index 4ea0dbf6c..7a52f041f 100644
--- a/app/services/reblog_service.rb
+++ b/app/services/reblog_service.rb
@@ -1,6 +1,8 @@
 # frozen_string_literal: true
 
 class ReblogService < BaseService
+  include StreamEntryRenderer
+
   # Reblog a status and notify its remote author
   # @param [Account] account Account to reblog from
   # @param [Status] reblogged_status Status to be reblogged
@@ -18,15 +20,9 @@ class ReblogService < BaseService
     if reblogged_status.local?
       NotifyService.new.call(reblog.reblog.account, reblog)
     else
-      NotificationWorker.perform_async(reblog.stream_entry.id, reblog.reblog.account_id)
+      NotificationWorker.perform_async(stream_entry_to_xml(reblog.stream_entry), account.id, reblog.reblog.account_id)
     end
 
     reblog
   end
-
-  private
-
-  def send_interaction_service
-    @send_interaction_service ||= SendInteractionService.new
-  end
 end
diff --git a/app/services/reject_follow_service.rb b/app/services/reject_follow_service.rb
new file mode 100644
index 000000000..0c568b981
--- /dev/null
+++ b/app/services/reject_follow_service.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class RejectFollowService < BaseService
+  include StreamEntryRenderer
+
+  def call(source_account, target_account)
+    follow_request = FollowRequest.find_by!(account: source_account, target_account: target_account)
+    follow_request.reject!
+    NotificationWorker.perform_async(stream_entry_to_xml(follow_request.stream_entry), target_account.id, source_account.id) unless source_account.local?
+  end
+end
diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb
index 48e8dd3b8..b1a646b14 100644
--- a/app/services/remove_status_service.rb
+++ b/app/services/remove_status_service.rb
@@ -1,6 +1,8 @@
 # frozen_string_literal: true
 
 class RemoveStatusService < BaseService
+  include StreamEntryRenderer
+
   def call(status)
     remove_from_self(status) if status.account.local?
     remove_from_followers(status)
@@ -43,7 +45,7 @@ class RemoveStatusService < BaseService
 
   def send_delete_salmon(account, status)
     return unless status.local?
-    NotificationWorker.perform_async(status.stream_entry.id, account.id)
+    NotificationWorker.perform_async(stream_entry_to_xml(status.stream_entry), status.account_id, account.id)
   end
 
   def remove_reblogs(status)
diff --git a/app/services/send_interaction_service.rb b/app/services/send_interaction_service.rb
index 05a1e77e3..99113eeca 100644
--- a/app/services/send_interaction_service.rb
+++ b/app/services/send_interaction_service.rb
@@ -2,27 +2,16 @@
 
 class SendInteractionService < BaseService
   # Send an Atom representation of an interaction to a remote Salmon endpoint
-  # @param [StreamEntry] stream_entry
+  # @param [String] Entry XML
+  # @param [Account] source_account
   # @param [Account] target_account
-  def call(stream_entry, target_account)
-    envelope = salmon.pack(entry_xml(stream_entry), stream_entry.account.keypair)
+  def call(xml, source_account, target_account)
+    envelope = salmon.pack(xml, source_account.keypair)
     salmon.post(target_account.salmon_url, envelope)
   end
 
   private
 
-  def entry_xml(stream_entry)
-    Nokogiri::XML::Builder.new do |xml|
-      entry(xml, true) do
-        author(xml) do
-          include_author xml, stream_entry.account
-        end
-
-        include_entry xml, stream_entry
-      end
-    end.to_xml
-  end
-
   def salmon
     @salmon ||= OStatus2::Salmon.new
   end
diff --git a/app/services/unblock_service.rb b/app/services/unblock_service.rb
index f389364f9..84b1050c1 100644
--- a/app/services/unblock_service.rb
+++ b/app/services/unblock_service.rb
@@ -1,10 +1,12 @@
 # frozen_string_literal: true
 
 class UnblockService < BaseService
+  include StreamEntryRenderer
+
   def call(account, target_account)
     return unless account.blocking?(target_account)
 
     unblock = account.unblock!(target_account)
-    NotificationWorker.perform_async(unblock.stream_entry.id, target_account.id) unless target_account.local?
+    NotificationWorker.perform_async(stream_entry_to_xml(unblock.stream_entry), account.id, target_account.id) unless target_account.local?
   end
 end
diff --git a/app/services/unfavourite_service.rb b/app/services/unfavourite_service.rb
index de6e84e7d..04293ee08 100644
--- a/app/services/unfavourite_service.rb
+++ b/app/services/unfavourite_service.rb
@@ -1,12 +1,14 @@
 # frozen_string_literal: true
 
 class UnfavouriteService < BaseService
+  include StreamEntryRenderer
+
   def call(account, status)
     favourite = Favourite.find_by!(account: account, status: status)
     favourite.destroy!
 
     unless status.local?
-      NotificationWorker.perform_async(favourite.stream_entry.id, status.account_id)
+      NotificationWorker.perform_async(stream_entry_to_xml(favourite.stream_entry), account.id, status.account_id)
     end
 
     favourite
diff --git a/app/services/unfollow_service.rb b/app/services/unfollow_service.rb
index f469793c1..178da4da3 100644
--- a/app/services/unfollow_service.rb
+++ b/app/services/unfollow_service.rb
@@ -1,12 +1,14 @@
 # frozen_string_literal: true
 
 class UnfollowService < BaseService
+  include StreamEntryRenderer
+
   # Unfollow and notify the remote user
   # @param [Account] source_account Where to unfollow from
   # @param [Account] target_account Which to unfollow
   def call(source_account, target_account)
     follow = source_account.unfollow!(target_account)
-    NotificationWorker.perform_async(follow.stream_entry.id, target_account.id) unless target_account.local?
+    NotificationWorker.perform_async(stream_entry_to_xml(follow.stream_entry), source_account.id, target_account.id) unless target_account.local?
     UnmergeWorker.perform_async(target_account.id, source_account.id)
   end
 end
diff --git a/app/services/update_remote_profile_service.rb b/app/services/update_remote_profile_service.rb
index ad9c56540..dc315db19 100644
--- a/app/services/update_remote_profile_service.rb
+++ b/app/services/update_remote_profile_service.rb
@@ -10,6 +10,7 @@ class UpdateRemoteProfileService < BaseService
     unless author_xml.nil?
       account.display_name = author_xml.at_xpath('./poco:displayName', poco: TagManager::POCO_XMLNS).content unless author_xml.at_xpath('./poco:displayName', poco: TagManager::POCO_XMLNS).nil?
       account.note         = author_xml.at_xpath('./poco:note', poco: TagManager::POCO_XMLNS).content unless author_xml.at_xpath('./poco:note', poco: TagManager::POCO_XMLNS).nil?
+      account.locked       = author_xml.at_xpath('./mastodon:scope', mastodon: TagManager::MTDN_XMLNS)&.content == 'private'
 
       unless account.suspended? || DomainBlock.find_by(domain: account.domain)&.reject_media?
         account.avatar_remote_url = author_xml.at_xpath('./xmlns:link[@rel="avatar"]', xmlns: TagManager::XMLNS)['href'] unless author_xml.at_xpath('./xmlns:link[@rel="avatar"]', xmlns: TagManager::XMLNS).nil? || author_xml.at_xpath('./xmlns:link[@rel="avatar"]', xmlns: TagManager::XMLNS)['href'].blank?
diff --git a/app/workers/notification_worker.rb b/app/workers/notification_worker.rb
index e4c38d384..1a2faefd8 100644
--- a/app/workers/notification_worker.rb
+++ b/app/workers/notification_worker.rb
@@ -5,7 +5,7 @@ class NotificationWorker
 
   sidekiq_options retry: 5
 
-  def perform(stream_entry_id, target_account_id)
-    SendInteractionService.new.call(StreamEntry.find(stream_entry_id), Account.find(target_account_id))
+  def perform(xml, source_account_id, target_account_id)
+    SendInteractionService.new.call(xml, Account.find(source_account_id), Account.find(target_account_id))
   end
 end
diff --git a/app/workers/push_notification_worker.rb b/app/workers/push_notification_worker.rb
deleted file mode 100644
index a61d0e349..000000000
--- a/app/workers/push_notification_worker.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class PushNotificationWorker
-  include Sidekiq::Worker
-
-  def perform(notification_id)
-    SendPushNotificationService.new.call(Notification.find(notification_id))
-  rescue ActiveRecord::RecordNotFound
-    true
-  end
-end
diff --git a/spec/helpers/atom_builder_helper_spec.rb b/spec/helpers/atom_builder_helper_spec.rb
index 3d3bd56a1..0aca58ee7 100644
--- a/spec/helpers/atom_builder_helper_spec.rb
+++ b/spec/helpers/atom_builder_helper_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe AtomBuilderHelper, type: :helper do
 
   describe '#feed' do
     it 'creates a feed' do
-      expect(used_in_builder { |xml| helper.feed(xml) }).to match '<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0"/>'
+      expect(used_in_builder { |xml| helper.feed(xml) }).to match '<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0"/>'
     end
   end