Compare commits

..

2 commits

Author SHA1 Message Date
06a89689d8 Oops, fix crash when modeling Patchwork Staff (AMFPHP string encoding!)
See comment for details! I wonder if other items have been affected by
this in the past. I think probably what happened before was that we
successfully created this item, but failed to create the *translation*,
so when migrating over the Patchwork Staff all its translated fields
were empty? (That's what I found looking in the database today.)

But yeah, thankfully our crash logging at health.openneo.net gave me
the name of a pet someone was trying to model, and so I was able to
find the bug and fix it!
2024-09-27 15:18:43 -07:00
a08fb89d59 Oops, don't crash when an item has no previews
A weird state to get into, one would expect impossible! But something
funny is going on with the Kiko Lake Team Popcorn item (85598)!
2024-09-27 15:18:43 -07:00
3 changed files with 33 additions and 4 deletions

View file

@ -215,7 +215,8 @@ class ItemsController < ApplicationController
@item.compatible_pet_types. @item.compatible_pet_types.
preferring_species(cookies["preferred-preview-species-id"] || "<ignore>"). preferring_species(cookies["preferred-preview-species-id"] || "<ignore>").
preferring_color(cookies["preferred-preview-color-id"] || "<ignore>"). preferring_color(cookies["preferred-preview-color-id"] || "<ignore>").
preferring_simple.first preferring_simple.first ||
PetType.matching_name("Blue", "Acara").first!
end end
def validate_preview def validate_preview

View file

@ -168,7 +168,7 @@ class Pet < ApplicationRecord
# Return the response body as a `HashWithIndifferentAccess`. # Return the response body as a `HashWithIndifferentAccess`.
def self.send_amfphp_request(request, timeout: 10) def self.send_amfphp_request(request, timeout: 10)
begin begin
response = request.post(timeout: timeout, headers: { response_data = request.post(timeout: timeout, headers: {
"User-Agent" => Rails.configuration.user_agent_for_neopets, "User-Agent" => Rails.configuration.user_agent_for_neopets,
}) })
rescue RocketAMFExtensions::RemoteGateway::AMFError => e rescue RocketAMFExtensions::RemoteGateway::AMFError => e
@ -177,7 +177,7 @@ class Pet < ApplicationRecord
raise DownloadError, e.message, e.backtrace raise DownloadError, e.message, e.backtrace
end end
HashWithIndifferentAccess.new(response.messages[0].data.body) HashWithIndifferentAccess.new(response_data)
end end
end end

View file

@ -54,7 +54,25 @@ module RocketAMFExtensions
raise RocketAMF::AMFError.new(first_message_data) raise RocketAMF::AMFError.new(first_message_data)
end end
result # HACK: It seems to me that these messages come back with Windows-1250
# (or similar) encoding on the strings? I'm basing this on the
# Patchwork Staff item, whose description arrives as:
#
# "That staff is cute, but dont use it as a walking stick \x96 I " +
# "dont think it will hold you up!"
#
# And the `\x96` is meant to represent an endash, which it doesn't in
# UTF-8 or in most extended ASCII encodings, but *does* in Windows's
# specific extended ASCII.
#
# Idk if this is something to do with the AMFPHP spec or how the AMFPHP
# server code they use serializes strings (I couldn't find any
# reference to it?), or just their internal database encoding being
# passed along as-is, or what? But this seems to be the most correct
# interpretation I know how to do, so, let's do it!
result.messages[0].data.body.tap do |body|
reencode_strings! body, "Windows-1250", "UTF-8"
end
end end
private private
@ -86,6 +104,16 @@ module RocketAMFExtensions
raise ConnectionError, e.message raise ConnectionError, e.message
end end
end end
def reencode_strings!(target, from, to)
if target.is_a? String
target.force_encoding(from).encode!(to)
elsif target.is_a? Array
target.each { |x| reencode_strings!(x, from, to) }
elsif target.is_a? Hash
target.values.each { |x| reencode_strings!(x, from, to) }
end
end
end end
class ConnectionError < RuntimeError class ConnectionError < RuntimeError