You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

79 lines
1.8 KiB

  1. # frozen_string_literal: true
  2. class RemoteFollow
  3. include ActiveModel::Validations
  4. include RoutingHelper
  5. include WebfingerHelper
  6. attr_accessor :acct, :addressable_template
  7. validates :acct, presence: true, domain: { acct: true }
  8. def initialize(attrs = {})
  9. @acct = normalize_acct(attrs[:acct])
  10. end
  11. def valid?
  12. return false unless super
  13. fetch_template!
  14. errors.empty?
  15. end
  16. def subscribe_address_for(account)
  17. addressable_template.expand(uri: ActivityPub::TagManager.instance.uri_for(account)).to_s
  18. end
  19. def interact_address_for(status)
  20. addressable_template.expand(uri: ActivityPub::TagManager.instance.uri_for(status)).to_s
  21. end
  22. private
  23. def normalize_acct(value)
  24. return if value.blank?
  25. username, domain = value.strip.gsub(/\A@/, '').split('@')
  26. domain = begin
  27. if TagManager.instance.local_domain?(domain)
  28. nil
  29. else
  30. TagManager.instance.normalize_domain(domain)
  31. end
  32. end
  33. [username, domain].compact.join('@')
  34. rescue Addressable::URI::InvalidURIError
  35. value
  36. end
  37. def fetch_template!
  38. return missing_resource_error if acct.blank?
  39. _, domain = acct.split('@')
  40. if domain.nil?
  41. @addressable_template = Addressable::Template.new("#{authorize_interaction_url}?uri={uri}")
  42. elsif redirect_uri_template.nil?
  43. missing_resource_error
  44. else
  45. @addressable_template = Addressable::Template.new(redirect_uri_template)
  46. end
  47. end
  48. def redirect_uri_template
  49. acct_resource&.link('http://ostatus.org/schema/1.0/subscribe', 'template')
  50. end
  51. def acct_resource
  52. @acct_resource ||= webfinger!("acct:#{acct}")
  53. rescue Webfinger::Error, HTTP::ConnectionError
  54. nil
  55. end
  56. def missing_resource_error
  57. errors.add(:acct, I18n.t('remote_follow.missing_resource'))
  58. end
  59. end