follow_service.rb 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. # frozen_string_literal: true
  2. class FollowService < BaseService
  3. include StreamEntryRenderer
  4. # Follow a remote user, notify remote user about the follow
  5. # @param [Account] source_account From which to follow
  6. # @param [String] uri User URI to follow in the form of username@domain
  7. def call(source_account, uri)
  8. target_account = ResolveRemoteAccountService.new.call(uri)
  9. raise ActiveRecord::RecordNotFound if target_account.nil? || target_account.id == source_account.id || target_account.suspended?
  10. raise Mastodon::NotPermittedError if target_account.blocking?(source_account) || source_account.blocking?(target_account)
  11. return if source_account.following?(target_account)
  12. if target_account.locked? || target_account.activitypub?
  13. request_follow(source_account, target_account)
  14. else
  15. direct_follow(source_account, target_account)
  16. end
  17. end
  18. private
  19. def request_follow(source_account, target_account)
  20. follow_request = FollowRequest.create!(account: source_account, target_account: target_account)
  21. if target_account.local?
  22. NotifyService.new.call(target_account, follow_request)
  23. elsif target_account.ostatus?
  24. NotificationWorker.perform_async(build_follow_request_xml(follow_request), source_account.id, target_account.id)
  25. AfterRemoteFollowRequestWorker.perform_async(follow_request.id)
  26. elsif target_account.activitypub?
  27. ActivityPub::DeliveryWorker.perform_async(build_json(follow_request), source_account.id, target_account.inbox_url)
  28. end
  29. follow_request
  30. end
  31. def direct_follow(source_account, target_account)
  32. follow = source_account.follow!(target_account)
  33. if target_account.local?
  34. NotifyService.new.call(target_account, follow)
  35. else
  36. Pubsubhubbub::SubscribeWorker.perform_async(target_account.id) unless target_account.subscribed?
  37. NotificationWorker.perform_async(build_follow_xml(follow), source_account.id, target_account.id)
  38. AfterRemoteFollowWorker.perform_async(follow.id)
  39. end
  40. MergeWorker.perform_async(target_account.id, source_account.id)
  41. follow
  42. end
  43. def redis
  44. Redis.current
  45. end
  46. def build_follow_request_xml(follow_request)
  47. OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.follow_request_salmon(follow_request))
  48. end
  49. def build_follow_xml(follow)
  50. OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.follow_salmon(follow))
  51. end
  52. def build_json(follow_request)
  53. Oj.dump(ActivityPub::LinkedDataSignature.new(ActiveModelSerializers::SerializableResource.new(
  54. follow_request,
  55. serializer: ActivityPub::FollowSerializer,
  56. adapter: ActivityPub::Adapter
  57. ).as_json).sign!(follow_request.account))
  58. end
  59. end