rets-hack 0.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +142 -0
- data/Manifest.txt +58 -0
- data/README.md +129 -0
- data/Rakefile +28 -0
- data/bin/rets +202 -0
- data/example/connect.rb +19 -0
- data/example/get-photos.rb +20 -0
- data/example/get-property.rb +16 -0
- data/lib/rets/client.rb +373 -0
- data/lib/rets/client_progress_reporter.rb +48 -0
- data/lib/rets/http_client.rb +133 -0
- data/lib/rets/locking_http_client.rb +34 -0
- data/lib/rets/measuring_http_client.rb +27 -0
- data/lib/rets/metadata/caching.rb +59 -0
- data/lib/rets/metadata/containers.rb +89 -0
- data/lib/rets/metadata/file_cache.rb +29 -0
- data/lib/rets/metadata/json_serializer.rb +27 -0
- data/lib/rets/metadata/lookup_table.rb +65 -0
- data/lib/rets/metadata/lookup_type.rb +19 -0
- data/lib/rets/metadata/marshal_serializer.rb +27 -0
- data/lib/rets/metadata/multi_lookup_table.rb +70 -0
- data/lib/rets/metadata/null_cache.rb +24 -0
- data/lib/rets/metadata/resource.rb +103 -0
- data/lib/rets/metadata/rets_class.rb +57 -0
- data/lib/rets/metadata/rets_object.rb +41 -0
- data/lib/rets/metadata/root.rb +155 -0
- data/lib/rets/metadata/table.rb +33 -0
- data/lib/rets/metadata/table_factory.rb +19 -0
- data/lib/rets/metadata/yaml_serializer.rb +27 -0
- data/lib/rets/metadata.rb +18 -0
- data/lib/rets/parser/compact.rb +117 -0
- data/lib/rets/parser/error_checker.rb +56 -0
- data/lib/rets/parser/multipart.rb +39 -0
- data/lib/rets.rb +269 -0
- data/test/fixtures.rb +324 -0
- data/test/helper.rb +14 -0
- data/test/test_caching.rb +89 -0
- data/test/test_client.rb +307 -0
- data/test/test_error_checker.rb +87 -0
- data/test/test_file_cache.rb +42 -0
- data/test/test_http_client.rb +132 -0
- data/test/test_json_serializer.rb +26 -0
- data/test/test_locking_http_client.rb +29 -0
- data/test/test_marshal_serializer.rb +26 -0
- data/test/test_metadata.rb +71 -0
- data/test/test_metadata_class.rb +50 -0
- data/test/test_metadata_lookup_table.rb +21 -0
- data/test/test_metadata_lookup_type.rb +21 -0
- data/test/test_metadata_multi_lookup_table.rb +60 -0
- data/test/test_metadata_object.rb +33 -0
- data/test/test_metadata_resource.rb +148 -0
- data/test/test_metadata_root.rb +151 -0
- data/test/test_metadata_table.rb +21 -0
- data/test/test_metadata_table_factory.rb +24 -0
- data/test/test_parser_compact.rb +115 -0
- data/test/test_parser_multipart.rb +39 -0
- data/test/test_yaml_serializer.rb +26 -0
- data/test/vcr_cassettes/unauthorized_response.yml +262 -0
- metadata +227 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: aa7eec964ae1e040ba2d291f5283432661b1a08c
|
4
|
+
data.tar.gz: 597bbab53e0a16701d8b070cf193f7d4bc015053
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4946f647c2cc1a67f644018c50918cfb6fd992ce13eda38de79db7ea5f842f7e7aa10dadb8244b7f4ef908cac4c4ebe564cad1a2191bc1819972a70e66d7278f
|
7
|
+
data.tar.gz: 994a48a22bef9a8f03a1195a685339e9d6d2a29a985172962e312d072b1487b8f37a51819afe22765f1d5fbd2627afa65f6c0a0dbe1917ce6a61302b77b17466
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
### 0.11.0 / NOT RELEASED YET
|
2
|
+
|
3
|
+
* fix: fix retry logging
|
4
|
+
* feature: allow retries to be configured for all query types in client settings
|
5
|
+
* feature: allow configrable wait time between retries
|
6
|
+
* feature: detect errors as error messages in a response body delivered with HTTP 200
|
7
|
+
|
8
|
+
### 0.10.1 / 2016-05-04
|
9
|
+
|
10
|
+
* fix: handle invalid codepoints in character references
|
11
|
+
|
12
|
+
### 0.10.0 / 2016-02-29
|
13
|
+
|
14
|
+
* fix: ensure cookie store exists #133
|
15
|
+
* feature: make cached capabilities case insensitive #136
|
16
|
+
* feature: add specific classes for each rets error #137
|
17
|
+
* feature: whitelist RETS search options #142
|
18
|
+
* feature: simplify metadata caching #134
|
19
|
+
* feature: use a SAX parser #98
|
20
|
+
* fix: save capabilities to avoid double logins #148
|
21
|
+
* feature: login on authorization error #155
|
22
|
+
* add basic support for DataDictionary feeds #156
|
23
|
+
* fix: count always returns a number #161
|
24
|
+
* feature: make lookup tables case insensitive #163
|
25
|
+
* feature: update to httpclient 2.7 #165
|
26
|
+
* fix: getObject now works with non-multipart responses #166
|
27
|
+
* fix: getObject works with multiple ids #167
|
28
|
+
* feature: store rets object metadata #168
|
29
|
+
* feature: add a code of conduct #171
|
30
|
+
|
31
|
+
### 0.9.0 / 2015-06-11
|
32
|
+
|
33
|
+
* feature: update to httpclient 2.6
|
34
|
+
|
35
|
+
### 0.8.1 / 2015-06-09
|
36
|
+
|
37
|
+
* fix: actually make the httpclient version more specific this time
|
38
|
+
|
39
|
+
### 0.8.0 / 2015-06-09
|
40
|
+
|
41
|
+
* feature: reduce memory usage on parsing metadata
|
42
|
+
* fix: correctly raise authorization error when given XHTML instead of XML
|
43
|
+
* fix: unescape HTML encoded responses
|
44
|
+
* fix: make httpclient version requirement more specific
|
45
|
+
* feature: add ability to print metadata to a file
|
46
|
+
* fix: remove Gemfile.lock from repository
|
47
|
+
|
48
|
+
### 0.7.0 / 2015-01-16
|
49
|
+
|
50
|
+
* feature: optionally treat No Records Found as not an error
|
51
|
+
* fix: update httpclient version, patches SSL vulnerabilities
|
52
|
+
* feature: work around bogus http status codes that don't agree with XML body
|
53
|
+
|
54
|
+
### 0.6.0 / 2014-11-26
|
55
|
+
|
56
|
+
* fix: fix spelling error that created misleading exceptions
|
57
|
+
* feature: track stats for http requests sent
|
58
|
+
* feature: raise an exception if the login action doesn't return an http 200 status
|
59
|
+
* feature: add better class description and more fields to print tree
|
60
|
+
* feature: support http proxies
|
61
|
+
* feature: customizable http timeouts
|
62
|
+
* feature: add logging http headers when in debug mode
|
63
|
+
* feature: strip invalid utf8 from responses before parsing
|
64
|
+
* fix: don't raise an exception on a 401 after logout
|
65
|
+
* fix: treat no matching records status without a count node as a zero count
|
66
|
+
* feature: add an option for loading custom ca_certs
|
67
|
+
* feature: remove invalid resource types from metadata
|
68
|
+
* feature: special case http 412
|
69
|
+
* feature: add max_retries option
|
70
|
+
|
71
|
+
### 0.5.1 / 2013-10-30
|
72
|
+
|
73
|
+
* fix: 0.5.0 was broken, fix gem Manifest to fix gem
|
74
|
+
|
75
|
+
### 0.5.0 / 2013-09-05
|
76
|
+
|
77
|
+
* feature: Allow client.count to get integer count
|
78
|
+
* feature: Allow for downcased capability names
|
79
|
+
* fix: Handle the rets element being empty
|
80
|
+
* feature: Instrument rets client with stats reporting
|
81
|
+
* feature: Add a locking client
|
82
|
+
* feature: Support Basic Authentication
|
83
|
+
|
84
|
+
### 0.4.0 / 2012-08-29
|
85
|
+
|
86
|
+
* fix: update authentication header to uri matches path
|
87
|
+
|
88
|
+
### 0.3.0 / 2012-07-31
|
89
|
+
|
90
|
+
* correctly handle digest authentication
|
91
|
+
|
92
|
+
### 0.3.0.rc.0 / 2012-07-26
|
93
|
+
|
94
|
+
* feature: significantly better handling of authorization failures
|
95
|
+
|
96
|
+
### 0.2.1 / 2012-04-20
|
97
|
+
|
98
|
+
* fix: better handling of malformed RETS responses
|
99
|
+
|
100
|
+
### 0.2.0 / 2012-04-20
|
101
|
+
|
102
|
+
* feature: Ruby 1.9 compatibility!
|
103
|
+
|
104
|
+
### 0.1.7 / 2012-04-05
|
105
|
+
|
106
|
+
* feature: key_field lookup for resources
|
107
|
+
|
108
|
+
### 0.1.6 / 2012-04-03
|
109
|
+
|
110
|
+
* fix: user_agent authentication
|
111
|
+
|
112
|
+
### 0.1.5 / 2012-03-17
|
113
|
+
|
114
|
+
* fix: retries raise error after too many failures
|
115
|
+
* fix: raise error for failed multipart object request
|
116
|
+
* fix: retries start with a clean slate, fixing authorization errors during retry
|
117
|
+
|
118
|
+
### 0.1.4 / 2012-03-12
|
119
|
+
|
120
|
+
* fix: an MLS uses lower case in RETS tag
|
121
|
+
|
122
|
+
### 0.1.3 / 2012-03-05
|
123
|
+
|
124
|
+
* fixes to support location=1 in getobject query
|
125
|
+
|
126
|
+
### 0.1.2 / 2012-02-17
|
127
|
+
|
128
|
+
* bugfix - check ReplyCode in login, retry on errors
|
129
|
+
|
130
|
+
### 0.1.1 / 2012-01-11
|
131
|
+
|
132
|
+
* bugfix - prevent infinite loop in login
|
133
|
+
|
134
|
+
# rets Changelog
|
135
|
+
|
136
|
+
### 0.1.0 / 2011-06-23
|
137
|
+
|
138
|
+
* First public release!
|
139
|
+
|
140
|
+
### 0.0.1 / 2011-03-24
|
141
|
+
|
142
|
+
* Project Created
|
data/Manifest.txt
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
CHANGELOG.md
|
2
|
+
Manifest.txt
|
3
|
+
README.md
|
4
|
+
Rakefile
|
5
|
+
bin/rets
|
6
|
+
example/connect.rb
|
7
|
+
example/get-photos.rb
|
8
|
+
example/get-property.rb
|
9
|
+
lib/rets.rb
|
10
|
+
lib/rets/client.rb
|
11
|
+
lib/rets/client_progress_reporter.rb
|
12
|
+
lib/rets/http_client.rb
|
13
|
+
lib/rets/locking_http_client.rb
|
14
|
+
lib/rets/measuring_http_client.rb
|
15
|
+
lib/rets/metadata.rb
|
16
|
+
lib/rets/metadata/caching.rb
|
17
|
+
lib/rets/metadata/containers.rb
|
18
|
+
lib/rets/metadata/file_cache.rb
|
19
|
+
lib/rets/metadata/json_serializer.rb
|
20
|
+
lib/rets/metadata/lookup_table.rb
|
21
|
+
lib/rets/metadata/lookup_type.rb
|
22
|
+
lib/rets/metadata/marshal_serializer.rb
|
23
|
+
lib/rets/metadata/multi_lookup_table.rb
|
24
|
+
lib/rets/metadata/null_cache.rb
|
25
|
+
lib/rets/metadata/resource.rb
|
26
|
+
lib/rets/metadata/rets_class.rb
|
27
|
+
lib/rets/metadata/rets_object.rb
|
28
|
+
lib/rets/metadata/root.rb
|
29
|
+
lib/rets/metadata/table.rb
|
30
|
+
lib/rets/metadata/table_factory.rb
|
31
|
+
lib/rets/metadata/yaml_serializer.rb
|
32
|
+
lib/rets/parser/compact.rb
|
33
|
+
lib/rets/parser/error_checker.rb
|
34
|
+
lib/rets/parser/multipart.rb
|
35
|
+
test/fixtures.rb
|
36
|
+
test/helper.rb
|
37
|
+
test/test_caching.rb
|
38
|
+
test/test_client.rb
|
39
|
+
test/test_error_checker.rb
|
40
|
+
test/test_file_cache.rb
|
41
|
+
test/test_http_client.rb
|
42
|
+
test/test_json_serializer.rb
|
43
|
+
test/test_locking_http_client.rb
|
44
|
+
test/test_marshal_serializer.rb
|
45
|
+
test/test_metadata.rb
|
46
|
+
test/test_metadata_class.rb
|
47
|
+
test/test_metadata_lookup_table.rb
|
48
|
+
test/test_metadata_lookup_type.rb
|
49
|
+
test/test_metadata_multi_lookup_table.rb
|
50
|
+
test/test_metadata_object.rb
|
51
|
+
test/test_metadata_resource.rb
|
52
|
+
test/test_metadata_root.rb
|
53
|
+
test/test_metadata_table.rb
|
54
|
+
test/test_metadata_table_factory.rb
|
55
|
+
test/test_parser_compact.rb
|
56
|
+
test/test_parser_multipart.rb
|
57
|
+
test/test_yaml_serializer.rb
|
58
|
+
test/vcr_cassettes/unauthorized_response.yml
|
data/README.md
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
# rets
|
2
|
+
|
3
|
+
* http://github.com/estately/rets
|
4
|
+
|
5
|
+
## DESCRIPTION:
|
6
|
+
|
7
|
+
[![Build Status](https://secure.travis-ci.org/estately/rets.png?branch=master)](http://travis-ci.org/estately/rets)
|
8
|
+
A pure-ruby library for fetching data from [RETS] servers.
|
9
|
+
|
10
|
+
If you're looking for a slick CLI interface check out [retscli](https://github.com/summera/retscli), which is an awesome tool for exploring metadata or learning about RETS.
|
11
|
+
|
12
|
+
[RETS]: http://www.rets.org
|
13
|
+
|
14
|
+
## REQUIREMENTS:
|
15
|
+
|
16
|
+
* [httpclient]
|
17
|
+
* [nokogiri]
|
18
|
+
|
19
|
+
[httpclient]: https://github.com/nahi/httpclient
|
20
|
+
[nokogiri]: http://nokogiri.org
|
21
|
+
|
22
|
+
## INSTALLATION:
|
23
|
+
```
|
24
|
+
gem install rets
|
25
|
+
|
26
|
+
# or add it to your Gemfile if using Bundler then run bundle install
|
27
|
+
gem 'rets'
|
28
|
+
```
|
29
|
+
|
30
|
+
## EXAMPLE USAGE:
|
31
|
+
|
32
|
+
We need work in this area! There are currently a few guideline examples in the `example` folder on connecting, fetching a property's data, and fetching a property's photos.
|
33
|
+
|
34
|
+
## Metadata caching
|
35
|
+
|
36
|
+
Metadata, which is loaded when a client is first started, can be slow
|
37
|
+
to fetch. To avoid the cost of fetching metadata every time the
|
38
|
+
client is started, metadata can be cached.
|
39
|
+
|
40
|
+
To cache metadata, pass the :metadata_cache option to the client when
|
41
|
+
you start it. The library comes with a predefined metadata cache that
|
42
|
+
persists the metadata to a file. It is created with the path to which
|
43
|
+
the cached metadata should be written:
|
44
|
+
|
45
|
+
metadata_cache = Rets::Metadata::FileCache.new("/tmp/metadata")
|
46
|
+
|
47
|
+
When you create the RETS client, pass it the metadata cache:
|
48
|
+
|
49
|
+
client = Rets::Client.new(
|
50
|
+
...
|
51
|
+
metadata_cache: metadata_cache
|
52
|
+
)
|
53
|
+
|
54
|
+
If you want to persist to something other than a file, create your own
|
55
|
+
metadata cache object and pass it in. It should have the same interface
|
56
|
+
as the built-in Metadata::FileCache class:
|
57
|
+
|
58
|
+
class MyMetadataCache
|
59
|
+
|
60
|
+
# Save the metadata. Should yield an IO-like object to a block;
|
61
|
+
# that block will serialize the metadata to that object.
|
62
|
+
def save(&block)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Load the metadata. Should yield an IO-like object to a block;
|
66
|
+
# that block will deserialize the metadata from that object and
|
67
|
+
# return the metadata. Returns the metadata, or nil if it could
|
68
|
+
# not be loaded.
|
69
|
+
def load(&block)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
By default, the metadata is serialized using Marshal. You may select
|
75
|
+
JSON or YAML instead, or define your own serialization mechanism, using the
|
76
|
+
:metadata_serializer option when you create the Rets::Client:
|
77
|
+
|
78
|
+
client = Rets::Client.new(
|
79
|
+
...
|
80
|
+
metadata_serializer: Rets::Metadata::JsonSerializer.new
|
81
|
+
)
|
82
|
+
|
83
|
+
The built-in serializers are:
|
84
|
+
|
85
|
+
* Rets::Metadata::JsonSerializer
|
86
|
+
* Rets::Metadata::MarshalSerializer
|
87
|
+
* Rets::Metadata::YamlSerializer
|
88
|
+
|
89
|
+
To define your own serializer, create an object with this interface:
|
90
|
+
|
91
|
+
class MySerializer
|
92
|
+
|
93
|
+
# Serialize to a file. The library reserves the right to change
|
94
|
+
# the type or contents of o, so don't depend on it being
|
95
|
+
# anything in particular.
|
96
|
+
def save(file, o)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Deserialize from a file. If the metadata cannot be
|
100
|
+
# deserialized, return nil.
|
101
|
+
def load(file)
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
## LICENSE:
|
107
|
+
|
108
|
+
(The MIT License)
|
109
|
+
|
110
|
+
Copyright (c) 2011 Estately, Inc. <opensource@estately.com>
|
111
|
+
|
112
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
113
|
+
a copy of this software and associated documentation files (the
|
114
|
+
'Software'), to deal in the Software without restriction, including
|
115
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
116
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
117
|
+
permit persons to whom the Software is furnished to do so, subject to
|
118
|
+
the following conditions:
|
119
|
+
|
120
|
+
The above copyright notice and this permission notice shall be included
|
121
|
+
in all copies or substantial portions of the Software.
|
122
|
+
|
123
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
124
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
125
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
126
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
127
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
128
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
129
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'hoe'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
Hoe.plugin :git, :doofus
|
6
|
+
Hoe.plugin :travis
|
7
|
+
Hoe.plugin :gemspec
|
8
|
+
|
9
|
+
Hoe.spec 'rets' do
|
10
|
+
developer 'Estately, Inc. Open Source', 'opensource@estately.com'
|
11
|
+
|
12
|
+
extra_deps << [ "httpclient", "~> 2.7.0" ]
|
13
|
+
extra_deps << [ "http-cookie", "~> 1.0.0" ]
|
14
|
+
extra_deps << [ "nokogiri", "~> 1.5" ]
|
15
|
+
|
16
|
+
extra_dev_deps << [ "mocha", "~> 1.1.0" ]
|
17
|
+
extra_dev_deps << [ "vcr", "~> 2.2" ]
|
18
|
+
extra_dev_deps << [ "webmock", "~> 1.8" ]
|
19
|
+
|
20
|
+
### Use markdown for changelog and readme
|
21
|
+
self.history_file = 'CHANGELOG.md'
|
22
|
+
self.readme_file = 'README.md'
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
Rake::TestTask.new do |t|
|
27
|
+
t.pattern = "test/test_*.rb"
|
28
|
+
end
|
data/bin/rets
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "optparse"
|
4
|
+
require "pp"
|
5
|
+
|
6
|
+
require "rubygems"
|
7
|
+
|
8
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
9
|
+
require "rets"
|
10
|
+
|
11
|
+
class RetsCli
|
12
|
+
def self.parse(args)
|
13
|
+
|
14
|
+
actions = %w(metadata search count object)
|
15
|
+
options = {:count => 5}
|
16
|
+
|
17
|
+
opts = OptionParser.new do |opts|
|
18
|
+
opts.banner = "Usage: #{File.basename($0)} URL [options] [query]"
|
19
|
+
|
20
|
+
opts.separator ""
|
21
|
+
opts.separator "Authentication options:"
|
22
|
+
|
23
|
+
opts.on("-U", "--username USERNAME", "The username to authenticate with.") do |username|
|
24
|
+
options[:username] = username
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("-P", "--password [PASSWORD]", "The password to authenticate with.","Prompts if no argument is provided.") do |password|
|
28
|
+
options[:password] = password #or prompt # TODO
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("-A", "--agent AGENT", "User-Agent header to provide.") do |agent|
|
32
|
+
options[:agent] = agent
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on("-B", "--agent-password [PASSWORD]", "User-Agent password to provide.") do |ua_password|
|
36
|
+
options[:ua_password] = ua_password
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.separator ""
|
40
|
+
opts.separator "Actions:"
|
41
|
+
|
42
|
+
opts.on("-p", "--capabilities", "Print capabilities of the RETS server.") do |capabilities|
|
43
|
+
options[:capabilities] = capabilities
|
44
|
+
end
|
45
|
+
|
46
|
+
opts.on("-a", "--action ACTION", actions, "Action to perform (#{actions.join(",")}).") do |action|
|
47
|
+
options[:action] = action
|
48
|
+
end
|
49
|
+
|
50
|
+
opts.on("-m", "--metadata [FORMAT]", %w(tree long short), "Print metadata.", "Format is short, long or tree.", "Defaults to short.") do |format|
|
51
|
+
options[:action] = "metadata"
|
52
|
+
options[:metadata_format] = format || "short"
|
53
|
+
end
|
54
|
+
|
55
|
+
opts.separator ""
|
56
|
+
opts.separator "Search action options:"
|
57
|
+
|
58
|
+
opts.on("-r", "--resource NAME", "Name of resource to search for.") do |name|
|
59
|
+
options[:resource] = name
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on("-c", "--class NAME", "Name of class to search for.") do |name|
|
63
|
+
options[:class] = name
|
64
|
+
end
|
65
|
+
|
66
|
+
opts.on("-n", "--number LIMIT", Integer, "Return LIMIT results. Defaults to 5.") do |limit|
|
67
|
+
options[:limit] = limit
|
68
|
+
end
|
69
|
+
|
70
|
+
opts.separator ""
|
71
|
+
opts.separator "Misc options:"
|
72
|
+
|
73
|
+
opts.on_tail("-v", "--verbose", "Be verbose.") do |verbose|
|
74
|
+
logger = Class.new do
|
75
|
+
def method_missing(method, *a, &b)
|
76
|
+
puts a
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
options[:logger] = logger.new
|
81
|
+
end
|
82
|
+
|
83
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
84
|
+
puts opts
|
85
|
+
exit
|
86
|
+
end
|
87
|
+
|
88
|
+
opts.on_tail("--version", "Show version") do
|
89
|
+
puts Rets::VERSION
|
90
|
+
exit
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
begin
|
96
|
+
opts.parse!(args.empty? ? ["-h"] : args)
|
97
|
+
rescue OptionParser::InvalidArgument => e
|
98
|
+
abort e.message
|
99
|
+
end
|
100
|
+
|
101
|
+
options
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
options = RetsCli.parse(ARGV)
|
107
|
+
url = ARGV[0] or abort "Need login URL"
|
108
|
+
query = ARGV[1]
|
109
|
+
|
110
|
+
client = Rets::Client.new(options.merge(:login_url => url))
|
111
|
+
|
112
|
+
if options[:capabilities]
|
113
|
+
pp client.capabilities
|
114
|
+
end
|
115
|
+
|
116
|
+
case options[:action]
|
117
|
+
when "metadata" then
|
118
|
+
metadata = client.metadata
|
119
|
+
|
120
|
+
if options[:metadata_format] != "tree"
|
121
|
+
preferred_fields = %w(ClassName SystemName ResourceID StandardName VisibleName MetadataEntryID KeyField)
|
122
|
+
|
123
|
+
|
124
|
+
# All types except system
|
125
|
+
types = Rets::METADATA_TYPES.map { |t| t.downcase.to_sym } - [:system]
|
126
|
+
|
127
|
+
types.each do |type|
|
128
|
+
# if RowContainer ...
|
129
|
+
rows = metadata[type]
|
130
|
+
|
131
|
+
puts type.to_s.capitalize
|
132
|
+
puts "="*40
|
133
|
+
|
134
|
+
print_key_value = lambda do |k,v|
|
135
|
+
key = "#{k}:".ljust(35)
|
136
|
+
value = "#{v}".ljust(35)
|
137
|
+
|
138
|
+
puts [key, value].join
|
139
|
+
end
|
140
|
+
|
141
|
+
rows.each do |row|
|
142
|
+
top, rest = row.partition { |k,v| preferred_fields.include?(k) }
|
143
|
+
|
144
|
+
top.each(&print_key_value)
|
145
|
+
|
146
|
+
rest.sort_by{|k,v|k}.each(&print_key_value) if options[:metadata_format] == "long"
|
147
|
+
|
148
|
+
puts
|
149
|
+
end
|
150
|
+
|
151
|
+
puts
|
152
|
+
end
|
153
|
+
|
154
|
+
# Tree format
|
155
|
+
else
|
156
|
+
metadata.print_tree
|
157
|
+
end
|
158
|
+
|
159
|
+
when "search" then
|
160
|
+
pp client.find(:all,
|
161
|
+
:search_type => options[:resource],
|
162
|
+
:class => options[:class],
|
163
|
+
:query => query,
|
164
|
+
:count => Rets::Client::COUNT.exclude,
|
165
|
+
:limit => options[:limit])
|
166
|
+
|
167
|
+
when "count" then
|
168
|
+
pp client.find(:all,
|
169
|
+
:search_type => options[:resource],
|
170
|
+
:class => options[:class],
|
171
|
+
:query => query,
|
172
|
+
:count => Rets::Client::COUNT.only,
|
173
|
+
:limit => options[:limit])
|
174
|
+
|
175
|
+
when "object" then
|
176
|
+
|
177
|
+
def write_objects(parts)
|
178
|
+
parts.each do |part|
|
179
|
+
cid = part.headers["content-id"].to_i
|
180
|
+
oid = part.headers["object-id"].to_i
|
181
|
+
|
182
|
+
File.open("tmp/#{cid}-#{oid}", "wb") do |f|
|
183
|
+
puts f.path
|
184
|
+
|
185
|
+
f.write part.body
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
parts = client.all_objects(
|
191
|
+
:resource => "Property",
|
192
|
+
:resource_id => 90020062739, # id from KeyField for a given property
|
193
|
+
:object_type => "Photo"
|
194
|
+
)
|
195
|
+
|
196
|
+
parts.each { |pt| p pt.headers }
|
197
|
+
|
198
|
+
write_objects(parts)
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
client.logout
|
data/example/connect.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rets'
|
2
|
+
|
3
|
+
# Pass the :login_url, :username, :password and :version of RETS
|
4
|
+
client = Rets::Client.new({
|
5
|
+
login_url: 'login_url',
|
6
|
+
username: 'xxx',
|
7
|
+
password: 'xxx',
|
8
|
+
version: 'RETS/1.5'
|
9
|
+
})
|
10
|
+
|
11
|
+
begin
|
12
|
+
client.login
|
13
|
+
rescue => e
|
14
|
+
puts 'Error: ' + e.message
|
15
|
+
exit!
|
16
|
+
end
|
17
|
+
|
18
|
+
puts 'We connected! Lets log out...'
|
19
|
+
client.logout
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rets'
|
2
|
+
|
3
|
+
|
4
|
+
# Get all photos (*) for MLS ID 'mls_id'
|
5
|
+
# Pass :object_id (ie '0', '1,2', wildcard '*')
|
6
|
+
# The pass :resource (Property, Agent, MetaData, ...), :object_type (Photo, PhotoLarge), :rescource_id (ID of agent, MLS, ...)
|
7
|
+
photos = client.objects '*', {
|
8
|
+
resource: 'Property',
|
9
|
+
object_type: 'Photo',
|
10
|
+
resource_id: 'mls_id'
|
11
|
+
}
|
12
|
+
|
13
|
+
photos.each_with_index do |data, index|
|
14
|
+
File.open("property-#{index.to_s}.jpg", 'w') do |file|
|
15
|
+
file.write data.body
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
puts photos.length.to_s + ' photos saved.'
|
20
|
+
client.logout
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rets'
|
2
|
+
|
3
|
+
|
4
|
+
# Get one property
|
5
|
+
# Pass :first or :all
|
6
|
+
# Then :search_type (Property, Agent, ...), :class (Condo, Commerical, ...), :query and :limit
|
7
|
+
property = client.find :first, {
|
8
|
+
search_type: 'Property',
|
9
|
+
class: 'CLASS_NAME',
|
10
|
+
query: 'RETS_QUERY',
|
11
|
+
limit: 1
|
12
|
+
}
|
13
|
+
|
14
|
+
puts 'received property: '
|
15
|
+
puts property.inspect
|
16
|
+
client.logout
|