Extract Neopets::CustomPets service from the Pet class
Just getting this stuff out of Pet, in part because I want to start being able to unit test modeling, and that will require stubbing out what this service returns!
This commit is contained in:
parent
83e5ad6bcc
commit
e36e273d50
3 changed files with 67 additions and 68 deletions
|
@ -1,12 +1,4 @@
|
||||||
require 'rocketamf_extensions/remote_gateway'
|
|
||||||
|
|
||||||
class Pet < ApplicationRecord
|
class Pet < ApplicationRecord
|
||||||
NEOPETS_URL_ORIGIN = ENV['NEOPETS_URL_ORIGIN'] || 'https://www.neopets.com'
|
|
||||||
GATEWAY_URL = NEOPETS_URL_ORIGIN + '/amfphp/gateway.php'
|
|
||||||
GATEWAY = RocketAMFExtensions::RemoteGateway.new(GATEWAY_URL)
|
|
||||||
CUSTOM_PET_SERVICE = GATEWAY.service('CustomPetService')
|
|
||||||
PET_SERVICE = GATEWAY.service('PetService')
|
|
||||||
|
|
||||||
belongs_to :pet_type
|
belongs_to :pet_type
|
||||||
|
|
||||||
attr_reader :items, :pet_state, :alt_style
|
attr_reader :items, :pet_state, :alt_style
|
||||||
|
@ -16,7 +8,7 @@ class Pet < ApplicationRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
def load!(timeout: nil)
|
def load!(timeout: nil)
|
||||||
viewer_data = self.class.fetch_viewer_data(name, timeout:)
|
viewer_data = Neopets::CustomPets.fetch_viewer_data(name, timeout:)
|
||||||
use_viewer_data(viewer_data)
|
use_viewer_data(viewer_data)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -35,7 +27,7 @@ class Pet < ApplicationRecord
|
||||||
)
|
)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
new_image_hash = Pet.fetch_image_hash(self.name)
|
new_image_hash = Neopets::CustomPets.fetch_image_hash(self.name)
|
||||||
rescue => error
|
rescue => error
|
||||||
Rails.logger.warn "Failed to load image hash: #{error.full_message}"
|
Rails.logger.warn "Failed to load image hash: #{error.full_message}"
|
||||||
end
|
end
|
||||||
|
@ -122,61 +114,5 @@ class Pet < ApplicationRecord
|
||||||
pet.load!(**options)
|
pet.load!(**options)
|
||||||
pet
|
pet
|
||||||
end
|
end
|
||||||
|
|
||||||
# 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 self.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 self.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 self.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
|
|
||||||
|
|
||||||
class PetNotFound < RuntimeError;end
|
|
||||||
class DownloadError < RuntimeError;end
|
|
||||||
class UnexpectedDataFormat < RuntimeError;end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
# Send an AMFPHP request, re-raising errors as `Pet::DownloadError`.
|
|
||||||
# Return the response body as a `HashWithIndifferentAccess`.
|
|
||||||
def self.send_amfphp_request(request, timeout: 10)
|
|
||||||
begin
|
|
||||||
response_data = request.post(timeout: timeout, headers: {
|
|
||||||
"User-Agent" => Rails.configuration.user_agent_for_neopets,
|
|
||||||
})
|
|
||||||
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
|
end
|
||||||
|
|
||||||
|
|
63
app/services/neopets/custom_pets.rb
Normal file
63
app/services/neopets/custom_pets.rb
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
require 'rocketamf_extensions/remote_gateway'
|
||||||
|
|
||||||
|
module Neopets::CustomPets
|
||||||
|
NEOPETS_URL_ORIGIN = ENV['NEOPETS_URL_ORIGIN'] || 'https://www.neopets.com'
|
||||||
|
GATEWAY_URL = NEOPETS_URL_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 `Pet::DownloadError`.
|
||||||
|
# Return the response body as a `HashWithIndifferentAccess`.
|
||||||
|
def send_amfphp_request(request, timeout: 10)
|
||||||
|
begin
|
||||||
|
response_data = request.post(timeout: timeout, headers: {
|
||||||
|
"User-Agent" => Rails.configuration.user_agent_for_neopets,
|
||||||
|
})
|
||||||
|
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
|
||||||
|
end
|
|
@ -1,7 +1,7 @@
|
||||||
namespace :pets do
|
namespace :pets do
|
||||||
desc "Load a pet's viewer data"
|
desc "Load a pet's viewer data"
|
||||||
task :load, [:name] => [:environment] do |task, args|
|
task :load, [:name] => [:environment] do |task, args|
|
||||||
pp Pet.fetch_viewer_data(args[:name])
|
pp Neopets::CustomPets.fetch_viewer_data(args[:name])
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Find pets that were, last we saw, of the given color and species"
|
desc "Find pets that were, last we saw, of the given color and species"
|
||||||
|
@ -10,7 +10,7 @@ namespace :pets do
|
||||||
pt = PetType.matching_name(args.color_name, args.species_name).first!
|
pt = PetType.matching_name(args.color_name, args.species_name).first!
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
abort "Could not find pet type for " +
|
abort "Could not find pet type for " +
|
||||||
"#{args.color_name} #{args.species_name}"
|
"#{args.color_name} #{args.species_name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
limit = ENV.fetch("LIMIT", 10)
|
limit = ENV.fetch("LIMIT", 10)
|
||||||
|
|
Loading…
Reference in a new issue