Farmbot-Web-App/app/lib/resources/preprocessor.rb

69 lines
2.0 KiB
Ruby

module Resources
# Takes a bunch of unsafe, string-y data that came in over AMQP and parses it
# into fully formed
class PreProcessor < Mutations::Command
def self.from_amqp(delivery_info, body)
# Parse the AMQP rotuing key into an Array of strings.
# A properly formatted routing_key will look like this after processing:
#
# ["bot", "device_3", "resources_v0", "destroy", "Sequence", "2", "xyz"]
segments = delivery_info.routing_key.split(".")
_, device_name, _, action, resource, uuid, resource_id = segments
run!(device_name: device_name,
action: action,
resource: resource,
resource_id: resource_id,
uuid: uuid,
body: body.empty? ? "{}" : body)
end
required do
string :action, in: ACTIONS # "destroy"
string :device_name, matches: DEVICE_REGEX # "device_3"
string :resource, in: RESOURCES.keys # "Sequence"
end
optional do
integer :resource_id, default: 0 # 2
string :body # "{\"json\":true}"
string :uuid, default: "NONE" # "0dce-1d-41-1d-e95c3b"
end
def validate
maybe_set_device
maybe_set_body
end
def execute
{
action: action,
device: @device,
body: @body,
resource_id: resource_id,
resource: RESOURCES.fetch(resource),
uuid: uuid,
}
end
private
def fail_body
add_error :body, :body, "body must be a JSON object"
end
def maybe_set_body
hash = JSON.parse(body)
fail_body unless hash.is_a?(Hash)
@body = hash
rescue JSON::ParserError
fail_body
end
def maybe_set_device
id = device_name.gsub("device_", "").to_i
@device = Device.find_by(id: id)
add_error :device, :device, "Can't find device ##{id}" unless @device
end
end # PreProcessor
end # Resources