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.

55 lines
1.5 KiB

  1. # frozen_string_literal: true
  2. class SubscribeService < BaseService
  3. def call(account)
  4. @account = account
  5. @account.secret = SecureRandom.hex
  6. @response = build_request.perform
  7. if response_failed_permanently?
  8. # We're not allowed to subscribe. Fail and move on.
  9. @account.secret = ''
  10. @account.save!
  11. elsif response_successful?
  12. # The subscription will be confirmed asynchronously.
  13. @account.save!
  14. else
  15. # The response was either a 429 rate limit, or a 5xx error.
  16. # We need to retry at a later time. Fail loudly!
  17. raise "Subscription attempt failed for #{@account.acct} (#{@account.hub_url}): HTTP #{@response.code}"
  18. end
  19. end
  20. private
  21. def build_request
  22. request = Request.new(:post, @account.hub_url, form: subscription_params)
  23. request.on_behalf_of(some_local_account) if some_local_account
  24. request
  25. end
  26. def subscription_params
  27. {
  28. 'hub.topic': @account.remote_url,
  29. 'hub.mode': 'subscribe',
  30. 'hub.callback': api_subscription_url(@account.id),
  31. 'hub.verify': 'async',
  32. 'hub.secret': @account.secret,
  33. 'hub.lease_seconds': 7.days.seconds,
  34. }
  35. end
  36. def some_local_account
  37. @some_local_account ||= Account.local.first
  38. end
  39. # Any response in the 3xx or 4xx range, except for 429 (rate limit)
  40. def response_failed_permanently?
  41. (@response.status.redirect? || @response.status.client_error?) && !@response.status.too_many_requests?
  42. end
  43. # Any response in the 2xx range
  44. def response_successful?
  45. @response.status.success?
  46. end
  47. end