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.
@@ -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