Neopets.com recently added some new security rules that, if not satisfied, cause the request to return 403 Forbidden. We figured these out through trial and error, and added them to the `DTIRequests` library, so they would apply to all requests we make. We also updated our AMFPHP library to use `DTIRequests` as well, as an easy way to get the same security rules to apply to those requests. This change was motivated by pet loading being down for the past day or so, because all pet loading requests were returning 403 Forbidden! Now, we've fixed it, hooray!
65 lines
2.2 KiB
Ruby
65 lines
2.2 KiB
Ruby
require 'rocketamf_extensions/remote_gateway'
|
|
|
|
module Neopets::CustomPets
|
|
GATEWAY_URL =
|
|
Addressable::URI.parse(Rails.configuration.neopets_origin) +
|
|
'/amfphp/gateway.php'
|
|
GATEWAY = RocketAMFExtensions::RemoteGateway.new(GATEWAY_URL)
|
|
CUSTOM_PET_SERVICE = GATEWAY.service('CustomPetService')
|
|
PET_SERVICE = GATEWAY.service('PetService')
|
|
|
|
class << self
|
|
# NOTE: Ideally pet requests shouldn't take this long, but Neopets can be
|
|
# slow sometimes! Since we're on the Falcon server, long timeouts shouldn't
|
|
# slow down the rest of the request queue, like it used to be in the past.
|
|
def fetch_viewer_data(name, timeout: 10)
|
|
request = CUSTOM_PET_SERVICE.action('getViewerData').request([name])
|
|
send_amfphp_request(request).tap do |data|
|
|
if data[:custom_pet][:name].blank?
|
|
raise PetNotFound, "Pet #{name.inspect} does not exist"
|
|
end
|
|
end
|
|
end
|
|
|
|
def fetch_metadata(name, timeout: 10)
|
|
# If this is an image hash "pet name", it has no metadata.
|
|
return nil if name.start_with?("@")
|
|
|
|
request = PET_SERVICE.action('getPet').request([name])
|
|
send_amfphp_request(request).tap do |data|
|
|
if data[:name].blank?
|
|
raise PetNotFound, "Pet #{name.inspect} does not exist"
|
|
end
|
|
end
|
|
end
|
|
|
|
# Given a pet's name, load its image hash, for use in `pets.neopets.com`
|
|
# image URLs. (This corresponds to its current biology and items.)
|
|
def fetch_image_hash(name, timeout: 10)
|
|
# If this is an image hash "pet name", just take off the `@`!
|
|
return name[1..] if name.start_with?("@")
|
|
|
|
metadata = fetch_metadata(name, timeout:)
|
|
metadata[:hash]
|
|
end
|
|
|
|
private
|
|
|
|
# Send an AMFPHP request, re-raising errors as `DownloadError`.
|
|
# Return the response body as a `HashWithIndifferentAccess`.
|
|
def send_amfphp_request(request, timeout: 10)
|
|
begin
|
|
response_data = request.post(timeout: timeout)
|
|
rescue RocketAMFExtensions::RemoteGateway::AMFError => e
|
|
raise DownloadError, e.message
|
|
rescue RocketAMFExtensions::RemoteGateway::ConnectionError => e
|
|
raise DownloadError, e.message, e.backtrace
|
|
end
|
|
|
|
HashWithIndifferentAccess.new(response_data)
|
|
end
|
|
end
|
|
|
|
class PetNotFound < RuntimeError;end
|
|
class DownloadError < RuntimeError;end
|
|
end
|