nwmls_client 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +8 -0
- data/README +4 -0
- data/lib/nwmls_client/amenity.rb +42 -0
- data/lib/nwmls_client/amenity.yml +1954 -0
- data/lib/nwmls_client/business.rb +23 -0
- data/lib/nwmls_client/codes.rb +470 -0
- data/lib/nwmls_client/commercial.rb +23 -0
- data/lib/nwmls_client/community.rb +38 -0
- data/lib/nwmls_client/condominium.rb +23 -0
- data/lib/nwmls_client/farmranch.rb +23 -0
- data/lib/nwmls_client/history.rb +48 -0
- data/lib/nwmls_client/image.rb +125 -0
- data/lib/nwmls_client/image_data.rb +37 -0
- data/lib/nwmls_client/listing.rb +195 -0
- data/lib/nwmls_client/manufactured.rb +22 -0
- data/lib/nwmls_client/member.rb +38 -0
- data/lib/nwmls_client/multifamily.rb +22 -0
- data/lib/nwmls_client/office.rb +38 -0
- data/lib/nwmls_client/rental.rb +23 -0
- data/lib/nwmls_client/residential.rb +23 -0
- data/lib/nwmls_client/school.rb +38 -0
- data/lib/nwmls_client/timeshare.rb +22 -0
- data/lib/nwmls_client/vacantland.rb +23 -0
- metadata +84 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative "listing"
|
2
|
+
|
3
|
+
module NwmlsClient
|
4
|
+
|
5
|
+
class Commercial < Listing
|
6
|
+
|
7
|
+
def initialize(criteria = {})
|
8
|
+
criteria[:property_code] = "COMI"
|
9
|
+
criteria[:property_type] = :commercial_industrial
|
10
|
+
@criteria = criteria
|
11
|
+
super(@criteria)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
if __FILE__ == $0
|
20
|
+
commercial = NwmlsClient::Commercial.new()
|
21
|
+
listings = commercial.retrieve_data
|
22
|
+
commercial.display(listings)
|
23
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative "listing"
|
2
|
+
|
3
|
+
module NwmlsClient
|
4
|
+
|
5
|
+
class Community < Listing
|
6
|
+
|
7
|
+
def initialize(criteria = {})
|
8
|
+
criteria[:operation] = :retrieve_area_community_data
|
9
|
+
criteria[:data_response] = :retrieve_area_community_data_response
|
10
|
+
criteria[:data_result] = :retrieve_area_community_data_result
|
11
|
+
criteria[:data_types] = :areas_communities
|
12
|
+
criteria[:data_type] = :areacommunity
|
13
|
+
@criteria = criteria
|
14
|
+
super(@criteria)
|
15
|
+
end
|
16
|
+
|
17
|
+
def display(community_data)
|
18
|
+
|
19
|
+
if community_data.is_a?(Array)
|
20
|
+
community_data.each do |item|
|
21
|
+
item.each do |key, value|
|
22
|
+
puts "#{key}: #{value}"
|
23
|
+
end
|
24
|
+
puts "\n"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
if __FILE__ == $0
|
35
|
+
community = NwmlsClient::Community.new()
|
36
|
+
data = community.retrieve_data
|
37
|
+
community.display(data)
|
38
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative "listing"
|
2
|
+
|
3
|
+
module NwmlsClient
|
4
|
+
|
5
|
+
class Condominium < Listing
|
6
|
+
|
7
|
+
def initialize(criteria = {})
|
8
|
+
criteria[:property_code] = "COND"
|
9
|
+
criteria[:property_type] = :condominium
|
10
|
+
@criteria = criteria
|
11
|
+
super(@criteria)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
if __FILE__ == $0
|
20
|
+
condo = NwmlsClient::Condominium.new()
|
21
|
+
listings = condo.retrieve_data
|
22
|
+
condo.display(listings)
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative "listing"
|
2
|
+
|
3
|
+
module NwmlsClient
|
4
|
+
|
5
|
+
class FarmRanch < Listing
|
6
|
+
|
7
|
+
def initialize(criteria = {})
|
8
|
+
criteria[:property_code] = "FARM"
|
9
|
+
criteria[:property_type] = :farm_ranch
|
10
|
+
@criteria = criteria
|
11
|
+
super(@criteria)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
if __FILE__ == $0
|
20
|
+
farm_ranch = NwmlsClient::FarmRanch.new()
|
21
|
+
listings = farm_ranch.retrieve_data
|
22
|
+
farm_ranch.display(listings)
|
23
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative "listing"
|
2
|
+
|
3
|
+
module NwmlsClient
|
4
|
+
|
5
|
+
class History < Listing
|
6
|
+
|
7
|
+
def initialize(criteria = {})
|
8
|
+
criteria[:operation] = :retrieve_listing_history_data
|
9
|
+
criteria[:data_response] = :retrieve_listing_history_data_response
|
10
|
+
criteria[:data_result] = :retrieve_listing_history_data_result
|
11
|
+
criteria[:data_types] = :listing_history
|
12
|
+
criteria[:data_type] = :history
|
13
|
+
@criteria = criteria
|
14
|
+
super(@criteria)
|
15
|
+
end
|
16
|
+
|
17
|
+
def display(history_data)
|
18
|
+
|
19
|
+
if history_data.is_a?(Array)
|
20
|
+
history_data.each do |item|
|
21
|
+
item.each do |key, value|
|
22
|
+
if key.to_s == "ml_number"
|
23
|
+
puts "#{key}: #{value}"
|
24
|
+
else
|
25
|
+
if value.is_a?(Array)
|
26
|
+
value.each do |item2|
|
27
|
+
puts "list price: #{item2[:list_price]} change date: #{item2[:change_date]}"
|
28
|
+
end
|
29
|
+
else
|
30
|
+
puts "list price: #{value[:list_price]} change date: #{value[:change_date]}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
if __FILE__ == $0
|
44
|
+
history = NwmlsClient::History.new()
|
45
|
+
data = history.retrieve_data
|
46
|
+
#puts "#{data}"
|
47
|
+
history.display(data)
|
48
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'savon'
|
2
|
+
|
3
|
+
module NwmlsClient
|
4
|
+
|
5
|
+
class Image
|
6
|
+
|
7
|
+
DEFAULT_SCHEMA_NAME = 'StandardXML1_3'
|
8
|
+
MLS = 'NWMLS'
|
9
|
+
DEFAULT_PTYP = 'RESI'
|
10
|
+
IMAGE_SCHEMA = 'NWMLS:EverNet:ImageData:1.0'
|
11
|
+
|
12
|
+
attr_accessor :schema_name
|
13
|
+
attr_accessor :user_id
|
14
|
+
attr_accessor :password
|
15
|
+
attr_accessor :listing_number
|
16
|
+
|
17
|
+
def initialize(listing_number = nil)
|
18
|
+
@user_id = nil
|
19
|
+
@password = nil
|
20
|
+
@listing_number = listing_number
|
21
|
+
end
|
22
|
+
|
23
|
+
def retrieve_images()
|
24
|
+
|
25
|
+
if !@user_id && !@password
|
26
|
+
puts "\nBoth user_id and password must be provided.\nExample: #{Image.name}.user_id\n\n"
|
27
|
+
end
|
28
|
+
|
29
|
+
request = { 'query' => build_request()}
|
30
|
+
|
31
|
+
begin
|
32
|
+
@client = create_client()
|
33
|
+
response = @client.call(:retrieve_images, message: request)
|
34
|
+
rescue Savon::SOAPFault => error
|
35
|
+
#puts "The call to retrieve_listing_data failed: #{$!}"
|
36
|
+
puts "Error making call to retrieve_images: #{error.http.code}"
|
37
|
+
end
|
38
|
+
|
39
|
+
cdata = response.body[:retrieve_images_response][:retrieve_images_result]
|
40
|
+
nori_options = { :convert_tags_to => lambda { |tag| tag.snakecase.to_sym } }
|
41
|
+
result = Nori.new(nori_options).parse(cdata)
|
42
|
+
|
43
|
+
images_data = result[:results][:images]
|
44
|
+
|
45
|
+
if images_data == nil
|
46
|
+
puts "No images found for MLS# #{@listing_number}, ensure MLS# is correct."
|
47
|
+
return images_data
|
48
|
+
else
|
49
|
+
image_folder = File.join(Dir.pwd, "images")
|
50
|
+
if not Dir.exist?(image_folder)
|
51
|
+
Dir.mkdir(image_folder)
|
52
|
+
end
|
53
|
+
|
54
|
+
dirpath = File.join(Dir.pwd, "images/#{@listing_number}")
|
55
|
+
if not Dir.exist?(dirpath)
|
56
|
+
Dir.mkdir(dirpath)
|
57
|
+
end
|
58
|
+
|
59
|
+
image_data = images_data[:image]
|
60
|
+
if image_data.is_a?(Array)
|
61
|
+
image_data.each do |image|
|
62
|
+
|
63
|
+
filename = File.join(dirpath, "#{@listing_number}_#{image[:image_order]}.jpg")
|
64
|
+
File.open(filename, 'wb') do |f|
|
65
|
+
f.write(Base64.decode64(image[:blob]))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
else
|
69
|
+
image = image_data
|
70
|
+
|
71
|
+
filename = File.join(dirpath, "#{@listing_number}_#{image[:image_order]}.jpg")
|
72
|
+
File.open(filename, 'wb') do |f|
|
73
|
+
f.write(Base64.decode64(image[:blob]))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def create_client()
|
84
|
+
|
85
|
+
@client = Savon.client(
|
86
|
+
wsdl: "http://images.idx.nwmls.com/imageservice/imagequery.asmx?wsdl"
|
87
|
+
#log_level: :debug, # can be: :debug, warn, :error, :fatal, :info
|
88
|
+
#log: true,
|
89
|
+
#open_timeout: 10,
|
90
|
+
#read_timeout: 60
|
91
|
+
)
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
def build_request()
|
96
|
+
|
97
|
+
xm = Builder::XmlMarkup.new
|
98
|
+
|
99
|
+
# Generate query to obtain actual images of specified property
|
100
|
+
xm.instruct! :xml, :version=>"1.0"
|
101
|
+
xm.ImageQuery(:xmlns => "NWMLS:EverNet:ImageQuery:1.0") {
|
102
|
+
xm.Auth {
|
103
|
+
xm.UserId user_id
|
104
|
+
xm.Password password
|
105
|
+
}
|
106
|
+
xm.Query {
|
107
|
+
xm.ByListingNumber @listing_number
|
108
|
+
}
|
109
|
+
xm.Results {
|
110
|
+
xm.Schema IMAGE_SCHEMA
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
if __FILE__ == $0
|
121
|
+
image = NwmlsClient::Image.new(877620)
|
122
|
+
image.user_id = "nwmls_user_id"
|
123
|
+
image.password = "secret_password"
|
124
|
+
images = image.retrieve_images
|
125
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative "listing"
|
2
|
+
|
3
|
+
module NwmlsClient
|
4
|
+
|
5
|
+
class ImageData < Listing
|
6
|
+
|
7
|
+
def initialize(criteria = {})
|
8
|
+
criteria[:operation] = :retrieve_image_data
|
9
|
+
criteria[:data_response] = :retrieve_image_data_response
|
10
|
+
criteria[:data_result] = :retrieve_image_data_result
|
11
|
+
criteria[:data_types] = :images
|
12
|
+
criteria[:data_type] = :image
|
13
|
+
@criteria = criteria
|
14
|
+
super(@criteria)
|
15
|
+
end
|
16
|
+
|
17
|
+
def display(image_data)
|
18
|
+
|
19
|
+
if image_data.is_a?(Array)
|
20
|
+
image_data.each do |item|
|
21
|
+
item.each do |key, value|
|
22
|
+
puts "#{key}: #{value}"
|
23
|
+
end
|
24
|
+
puts "\n"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
if __FILE__ == $0
|
34
|
+
image_data = NwmlsClient::ImageData.new()
|
35
|
+
data = image_data.retrieve_data
|
36
|
+
image_data.display(data)
|
37
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'savon'
|
3
|
+
require 'date'
|
4
|
+
require 'yaml'
|
5
|
+
require_relative 'codes'
|
6
|
+
|
7
|
+
module NwmlsClient
|
8
|
+
|
9
|
+
class Listing
|
10
|
+
|
11
|
+
DEFAULT_SCHEMA_NAME = 'StandardXML1_3'
|
12
|
+
MLS = 'NWMLS'
|
13
|
+
DEFAULT_PTYP = 'RESI'
|
14
|
+
IMAGE_SCHEMA = 'NWMLS:EverNet:ImageData:1.0'
|
15
|
+
AMENITY_FILE = "amenity.yml"
|
16
|
+
|
17
|
+
attr_accessor :criteria
|
18
|
+
attr_accessor :schema_name
|
19
|
+
attr_accessor :user_id
|
20
|
+
attr_accessor :password
|
21
|
+
|
22
|
+
def initialize(criteria = {})
|
23
|
+
@user_id = nil
|
24
|
+
@password = nil
|
25
|
+
@criteria = criteria
|
26
|
+
@criteria[:property_type] ||= :residential
|
27
|
+
@criteria[:begin_date] ||= DateTime.now-1
|
28
|
+
@criteria[:end_date] ||= DateTime.now
|
29
|
+
end
|
30
|
+
|
31
|
+
def retrieve_data()
|
32
|
+
|
33
|
+
operation = ( @criteria[:operation] || :retrieve_listing_data )
|
34
|
+
data_response = ( @criteria[:data_response] || :retrieve_listing_data_response )
|
35
|
+
data_result = ( @criteria[:data_result] || :retrieve_listing_data_result )
|
36
|
+
data_types = ( @criteria[:data_types] || :listings )
|
37
|
+
data_type = ( @criteria[:data_type] || @criteria[:property_type] )
|
38
|
+
|
39
|
+
if !@user_id && !@password
|
40
|
+
puts "\nBoth user_id and password must be provided.\nExample: #{Listing.name}.user_id\n\n"
|
41
|
+
end
|
42
|
+
|
43
|
+
request = { 'v_strXmlQuery' => build_request()}
|
44
|
+
|
45
|
+
begin
|
46
|
+
@client = create_client()
|
47
|
+
response = @client.call(operation, message: request)
|
48
|
+
rescue Savon::SOAPFault => error
|
49
|
+
#puts "The call to retrieve_listing_data failed: #{$!}"
|
50
|
+
puts "Error making call to retrieve_listing_data: #{error.http.code}"
|
51
|
+
end
|
52
|
+
|
53
|
+
cdata = response.body[data_response][data_result]
|
54
|
+
nori_options = { :convert_tags_to => lambda { |tag| tag.snakecase.to_sym } }
|
55
|
+
result = Nori.new(nori_options).parse(cdata)
|
56
|
+
|
57
|
+
if result[data_types][data_type] == nil
|
58
|
+
puts "Unable to retrieve data, please review returned data:\n#{result}"
|
59
|
+
end
|
60
|
+
|
61
|
+
listing_data = result[data_types][data_type]
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
def display(listing_data)
|
66
|
+
|
67
|
+
if !listing_data
|
68
|
+
puts "Unable to display data. Invalid listing_data: #{listing_data}"
|
69
|
+
return
|
70
|
+
end
|
71
|
+
|
72
|
+
puts "listing_data input: #{listing_data}"
|
73
|
+
|
74
|
+
begin
|
75
|
+
amenity = YAML.load(File.open(File.join(Dir.pwd, AMENITY_FILE)))
|
76
|
+
rescue ArgumentError => e
|
77
|
+
puts "Could not parse YAML: #{e.message}"
|
78
|
+
end
|
79
|
+
|
80
|
+
# TODO: Is there a way to load the listing data and replace both
|
81
|
+
# Codes and Amenities with the friendly names using regular expressions?
|
82
|
+
|
83
|
+
# Check if there is a list of items to display
|
84
|
+
# or only one
|
85
|
+
if listing_data.is_a?(Array)
|
86
|
+
listing_data.each do |item|
|
87
|
+
item.each do |key, value|
|
88
|
+
items = []
|
89
|
+
code = key.to_s.upcase
|
90
|
+
friendly_name = Codes.expand_code(code)
|
91
|
+
|
92
|
+
if amenity[code] && value
|
93
|
+
amenities = value.split('|')
|
94
|
+
amenities.each do |am|
|
95
|
+
items << "#{amenity[code][am]}"
|
96
|
+
end
|
97
|
+
puts "#{friendly_name}: #{items.join(", ")}"
|
98
|
+
else
|
99
|
+
puts "#{friendly_name}: #{value}"
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
puts "\n"
|
104
|
+
end
|
105
|
+
else
|
106
|
+
listing_data.each do |key, value|
|
107
|
+
|
108
|
+
if value != nil
|
109
|
+
items = []
|
110
|
+
code = key.to_s.upcase
|
111
|
+
friendly_name = Codes.expand_code(code)
|
112
|
+
|
113
|
+
if amenity[code]
|
114
|
+
amenities = value.split('|')
|
115
|
+
amenities.each do |am|
|
116
|
+
items << "#{amenity[code][am]}"
|
117
|
+
end
|
118
|
+
puts "#{friendly_name}: #{items.join(', ')}"
|
119
|
+
else
|
120
|
+
puts "#{friendly_name}: #{value}"
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def create_client()
|
133
|
+
|
134
|
+
@client = Savon.client(
|
135
|
+
wsdl: "http://evernet.nwmls.com/evernetqueryservice/evernetquery.asmx?wsdl"
|
136
|
+
#log_level: :debug, # can be: :debug, warn, :error, :fatal, :info
|
137
|
+
#log: true,
|
138
|
+
#open_timeout: 10,
|
139
|
+
#read_timeout: 60
|
140
|
+
)
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
def build_request()
|
145
|
+
|
146
|
+
xm = Builder::XmlMarkup.new
|
147
|
+
|
148
|
+
#Generate query to obtain data from Evernet web service
|
149
|
+
xm.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8", :standalone=>"no"
|
150
|
+
xm.EverNetQuerySpecification(:xmlns => "urn:www.nwmls.com/Schemas/General/EverNetQueryXML.xsd") {
|
151
|
+
xm.Message {
|
152
|
+
xm.Head {
|
153
|
+
xm.UserId user_id
|
154
|
+
xm.Password password
|
155
|
+
xm.SchemaName (schema_name || DEFAULT_SCHEMA_NAME)
|
156
|
+
}
|
157
|
+
xm.Body {
|
158
|
+
xm.Query {
|
159
|
+
xm.MLS MLS
|
160
|
+
if @criteria[:listing_number]
|
161
|
+
xm.ListingNumber @criteria[:listing_number] if @criteria[:listing_number]
|
162
|
+
xm.PropertyType (@criteria[:property_code] || DEFAULT_PTYP)
|
163
|
+
else
|
164
|
+
xm.PropertyType (@criteria[:property_code] || DEFAULT_PTYP)
|
165
|
+
xm.Status @criteria[:status] if @criteria[:status]
|
166
|
+
xm.County @criteria[:county] if @criteria[:county]
|
167
|
+
xm.Area @criteria[:area] if @criteria[:area]
|
168
|
+
xm.City @criteria[:city] if @criteria[:city]
|
169
|
+
xm.BeginDate @criteria[:begin_date]
|
170
|
+
xm.EndDate @criteria[:end_date]
|
171
|
+
xm.OfficeId @criteria[:office_id] if @criteria[:office_id]
|
172
|
+
xm.AgentId @criteria[:agent_id] if @criteria[:agent_id]
|
173
|
+
xm.Bedrooms @criteria[:bedrooms] if @criteria[:bedrooms]
|
174
|
+
xm.Bathrooms @criteria[:bathrooms] if @criteria[:bathrooms]
|
175
|
+
end
|
176
|
+
}
|
177
|
+
xm.Filter @criteria[:filters].join(',') if @criteria[:filters]
|
178
|
+
}
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
if __FILE__ == $0
|
190
|
+
listing = NwmlsClient::Listing.new()
|
191
|
+
listing.user_id = "nwmls_user_id"
|
192
|
+
listing.password = "secret_password"
|
193
|
+
data = listing.retrieve_data
|
194
|
+
listing.display(data)
|
195
|
+
end
|