This repository has been archived by the owner on Nov 20, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
client.rb
110 lines (86 loc) · 3.48 KB
/
client.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
module Realestate
class Client
include HTTParty
base_uri "http://api.realestate.co.nz/#{Realestate::API_VERSION}/"
attr_accessor :public_key, :private_key
def initialize(options = {})
self.public_key, self.private_key = options.delete(:public_key), options.delete(:private_key)
unless self.public_key.present? && self.private_key.present?
raise CredentialsRequired.new("You must specify your Public and Private keys")
end
end
%w(suburbs districts regions listing_types pricing_methods).each do |cat_name|
define_method(cat_name) do
request(:get, cat_name.dasherize)
end
end
# List / Search listings
def listings(options = {})
# max results is more like "results per page"
options[:max_results] ||= 100
options[:format] ||= "basic"
sort_column = options.delete(:sort)
sort_direction = options.delete(:sort_direction)
# -price_min for price_min, descending etc..
options[:sort_order] = "#{"-" if sort_direction == :desc}#{sort_column}" if sort_column.present?
listings = []
more = true
offset = 0
while more do
result = request(:get, "listings", options)
listings = listings + result["listings"]
offset = offset + options[:max_results]
options[:offset] = offset
more = result["more"]
end
listings
end
def listing(id, options = {})
options[:format] ||= "basic"
request(:get, "listings/#{id}", options)
end
private
def request(method, path, params = {})
query = prepare_params(path, params).map { |x| x.join("=") }.join("&")
process_response(self.class.send(method, "/#{path}/", :query => query))
end
# Adds necessary authentication parameters to the passed request parameters,
# and returns the signed set of parameters
#
# These parameters are api_key and api_sig as per the "Authentication" section
# in the API documentation
#
# @param params Hash - the parameters to sign
# @returns Hash - a hash of signed parameters, plus the original params
def prepare_params(request_path, params)
# use multiple instances of the same param name for Array values
params = params.inject([]) do |array, pair|
Array.wrap(pair.last).each do |val|
array << [ pair.first.to_s, CGI.escape(val.to_s) ]
end
array
end
params << ["api_sig", calculate_api_sig(request_path, params)]
params << ["api_key", public_key ]
end
def calculate_api_sig(request_path, params_array)
# Sort your URL argument list into alphabetical (ASCII) order based on the parameter name and value. e.g. a=B, foo=1, bar=2, baz=P, baz=3 sorts to a=B, bar=2, baz=3, baz=P, foo=1
sorted_params = params_array.sort_by { |k, v| "#{k}-#{v}" }
# Concatenate api secret, request path, sorted params
concatenated_string = [ self.private_key, "#{Realestate::API_VERSION}", request_path, sorted_params.join ].join("/")
Digest::MD5.hexdigest(concatenated_string)
end
def process_response(response)
case response.code
when 200..299
response.parsed_response
when 401
raise AuthenticationError.new(response.body)
when 400
raise ApiError.new(response)
else
raise "Unhandled Response Code: #{response.code}: #{response.body}"
end
end
end
end