76 lines
2 KiB
Ruby
76 lines
2 KiB
Ruby
|
require "async/http/internet/instance"
|
||
|
|
||
|
module NCMall
|
||
|
# Share a pool of persistent connections, rather than reconnecting on
|
||
|
# each request. (This library does that automatically!)
|
||
|
INTERNET = Async::HTTP::Internet.instance
|
||
|
|
||
|
# Load the NC home page, and return its useful data.
|
||
|
HOME_PAGE_URL = "https://ncmall.neopets.com/mall/ajax/home_page.phtml"
|
||
|
def self.load_home_page
|
||
|
response = Sync do
|
||
|
INTERNET.get(HOME_PAGE_URL, [
|
||
|
["User-Agent", Rails.configuration.user_agent_for_neopets],
|
||
|
])
|
||
|
end
|
||
|
|
||
|
if response.status != 200
|
||
|
raise ResponseNotOK.new(response.status),
|
||
|
"expected status 200 but got #{response.status} (#{HOME_PAGE_URL})"
|
||
|
end
|
||
|
|
||
|
parse_nc_page response.body.read
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
# Given a string of NC page data, parse the useful data out of it!
|
||
|
def self.parse_nc_page(nc_page_str)
|
||
|
begin
|
||
|
nc_page = JSON.parse(nc_page_str)
|
||
|
rescue JSON::ParserError
|
||
|
Rails.logger.debug "Unexpected NC page response:\n#{nc_page_str}"
|
||
|
raise UnexpectedResponseFormat,
|
||
|
"failed to parse NC page response as JSON"
|
||
|
end
|
||
|
|
||
|
unless nc_page.has_key? "object_data"
|
||
|
raise UnexpectedResponseFormat, "missing field object_data in NC page"
|
||
|
end
|
||
|
|
||
|
items = nc_page["object_data"].values.map do |item_info|
|
||
|
{
|
||
|
id: item_info["id"],
|
||
|
name: item_info["name"],
|
||
|
description: item_info["description"],
|
||
|
price: item_info["price"],
|
||
|
discount: parse_item_discount(item_info),
|
||
|
is_available: item_info["isAvailable"] == 1,
|
||
|
}
|
||
|
end
|
||
|
|
||
|
{items:}
|
||
|
end
|
||
|
|
||
|
# Given item info, return a hash of discount-specific info, if any.
|
||
|
def self.parse_item_discount(item_info)
|
||
|
discount_price = item_info["discountPrice"]
|
||
|
return nil unless discount_price.present? && discount_price > 0
|
||
|
|
||
|
{
|
||
|
price: discount_price,
|
||
|
start: item_info["discountBegin"],
|
||
|
end: item_info["discountEnd"],
|
||
|
}
|
||
|
end
|
||
|
|
||
|
class ResponseNotOK < StandardError
|
||
|
attr_reader :status
|
||
|
def initialize(status)
|
||
|
super
|
||
|
@status = status
|
||
|
end
|
||
|
end
|
||
|
class UnexpectedResponseFormat < StandardError;end
|
||
|
end
|