beds24 0.1.0 → 0.1.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 +4 -4
- data/.rspec_status +33 -0
- data/CHANGELOG.md +22 -0
- data/README.md +1 -1
- data/lib/beds24.rb +19 -2
- data/lib/beds24/constants.rb +30 -0
- data/lib/beds24/json_client.rb +73 -0
- data/lib/beds24/version.rb +1 -1
- data/lib/beds24/xml_client.rb +68 -0
- data/lib/beds24/xml_request.rb +29 -0
- data/lib/ext/hash.rb +56 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 516840b24ce1a38cef9407d190397c3a44c6c089b3d39e951a452325f9a46b93
|
4
|
+
data.tar.gz: e72470ca5cf482c9acede7e5b4f641c060004f7c567606460a85937e6f56d08c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ea509efe8a7496f581fcecce0cb1bd295715389ff593bc0a1c40459b56180837c18fe10d547bc4833266753299553106ee0b14d6db7a9d04d5e94a14229e23e
|
7
|
+
data.tar.gz: 42f9b60e574ad2541c020fe94c2dc605198678ae5105c7c06e13774e6b3a133a2c08559ef1d41de1aaf57ec7036c3de8c7754aa0589f2e56331916879519c195
|
data/.rspec_status
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
example_id | status | run_time |
|
2
|
+
-------------------------------------- | ------ | --------------- |
|
3
|
+
./spec/beds24_spec.rb[1:1] | passed | 0.00159 seconds |
|
4
|
+
./spec/hash_spec.rb[1:1:1] | passed | 0.00247 seconds |
|
5
|
+
./spec/hash_spec.rb[1:1:2] | passed | 0.00467 seconds |
|
6
|
+
./spec/hash_spec.rb[1:1:3] | passed | 0.01313 seconds |
|
7
|
+
./spec/hash_spec.rb[1:1:4] | passed | 0.00266 seconds |
|
8
|
+
./spec/hash_spec.rb[1:1:5] | passed | 0.00146 seconds |
|
9
|
+
./spec/hash_spec.rb[1:1:6] | passed | 0.00117 seconds |
|
10
|
+
./spec/json_client_spec.rb[1:1:1] | passed | 0.00014 seconds |
|
11
|
+
./spec/json_client_spec.rb[1:2:1] | passed | 0.00052 seconds |
|
12
|
+
./spec/json_client_spec.rb[1:2:2] | passed | 0.00011 seconds |
|
13
|
+
./spec/json_client_spec.rb[1:3:1:1] | passed | 0.01676 seconds |
|
14
|
+
./spec/json_client_spec.rb[1:3:2:1] | passed | 0.00161 seconds |
|
15
|
+
./spec/json_client_spec.rb[1:4:1:1] | passed | 0.00227 seconds |
|
16
|
+
./spec/json_client_spec.rb[1:4:2:1] | passed | 0.00131 seconds |
|
17
|
+
./spec/json_client_spec.rb[1:5:1:1] | passed | 0.00297 seconds |
|
18
|
+
./spec/json_client_spec.rb[1:5:2:1] | passed | 0.00236 seconds |
|
19
|
+
./spec/xml_client_spec.rb[1:1:1] | passed | 0.00032 seconds |
|
20
|
+
./spec/xml_client_spec.rb[1:2:1:1] | passed | 0.00054 seconds |
|
21
|
+
./spec/xml_client_spec.rb[1:2:1:2] | passed | 0.00044 seconds |
|
22
|
+
./spec/xml_client_spec.rb[1:2:2:1] | passed | 0.00033 seconds |
|
23
|
+
./spec/xml_client_spec.rb[1:2:2:2] | passed | 0.00028 seconds |
|
24
|
+
./spec/xml_client_spec.rb[1:3:1:1:1:1] | passed | 0.00589 seconds |
|
25
|
+
./spec/xml_client_spec.rb[1:3:1:2:1] | passed | 0.00557 seconds |
|
26
|
+
./spec/xml_client_spec.rb[1:3:2:1:1:1] | passed | 0.00727 seconds |
|
27
|
+
./spec/xml_client_spec.rb[1:3:2:2:1] | passed | 0.00511 seconds |
|
28
|
+
./spec/xml_client_spec.rb[1:3:3:1:1:1] | passed | 0.00455 seconds |
|
29
|
+
./spec/xml_client_spec.rb[1:3:3:2:1] | passed | 0.00421 seconds |
|
30
|
+
./spec/xml_request_spec.rb[1:1:1] | passed | 0.00083 seconds |
|
31
|
+
./spec/xml_request_spec.rb[1:1:2] | passed | 0.00083 seconds |
|
32
|
+
./spec/xml_request_spec.rb[1:2:1] | passed | 0.00067 seconds |
|
33
|
+
./spec/xml_request_spec.rb[1:2:2] | passed | 0.00064 seconds |
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [Unreleased]
|
9
|
+
|
10
|
+
## [0.1.0] - 2019-10-11
|
11
|
+
|
12
|
+
### Added
|
13
|
+
|
14
|
+
- Added ability to list properties in JSON format
|
15
|
+
- Added XML client to interact with XML API
|
16
|
+
- Added ability to fetch properties through XML API
|
17
|
+
- Added ability to fetch bookings through XML API
|
18
|
+
- Added ability to show bookings for a property
|
19
|
+
|
20
|
+
### Changed
|
21
|
+
|
22
|
+
### Removed
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Beds24 [](https://travis-ci.org/mihilbabin/beds24) [](https://badge.fury.io/rb/beds24)
|
2
2
|
|
3
3
|
This is a simple wrapper of [Beds24 API](https://beds24.com/api/index.html). It allows to fetch data related to properties and bookings created and filter that data as per API docs.
|
4
4
|
|
data/lib/beds24.rb
CHANGED
@@ -1,6 +1,23 @@
|
|
1
|
-
require
|
1
|
+
require 'httparty'
|
2
|
+
require 'oj'
|
3
|
+
|
4
|
+
require 'beds24/constants'
|
5
|
+
require 'beds24/json_client'
|
6
|
+
require 'beds24/version'
|
7
|
+
require 'beds24/xml_client'
|
8
|
+
require 'beds24/xml_request'
|
9
|
+
|
10
|
+
require 'ext/hash'
|
2
11
|
|
3
12
|
module Beds24
|
4
13
|
class Error < StandardError; end
|
5
|
-
|
14
|
+
|
15
|
+
class APIError < StandardError
|
16
|
+
attr_accessor :response
|
17
|
+
|
18
|
+
def initialize(msg, response)
|
19
|
+
super(msg)
|
20
|
+
@response = response
|
21
|
+
end
|
22
|
+
end
|
6
23
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Beds24
|
2
|
+
module Constants
|
3
|
+
API_ROOT = 'https://beds24.com/api'.freeze
|
4
|
+
JSON_API_ENDPOINT = "#{API_ROOT}/json".freeze
|
5
|
+
XML_API_ENDPOINT = "#{API_ROOT}/xml".freeze
|
6
|
+
|
7
|
+
PARSE_ERROR_MSG = 'Got encoding different from JSON. Please check passed options'.freeze
|
8
|
+
|
9
|
+
DEFAULT_PROPERTY_OPTIONS = {
|
10
|
+
includeRooms: false,
|
11
|
+
includeRoomUnits: false,
|
12
|
+
includeAccountAccess: false
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
DEFAULT_BOOKING_OPTIONS = {
|
16
|
+
includeInvoice: false,
|
17
|
+
includeInfoItems: false
|
18
|
+
}.freeze
|
19
|
+
|
20
|
+
VALID_XML_BOOKING_OPTS = %i[
|
21
|
+
modified
|
22
|
+
datefrom
|
23
|
+
dateto
|
24
|
+
propid
|
25
|
+
roomid
|
26
|
+
masterid
|
27
|
+
bookid
|
28
|
+
].freeze
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Beds24
|
2
|
+
class JSONClient
|
3
|
+
include HTTParty
|
4
|
+
base_uri Constants::JSON_API_ENDPOINT
|
5
|
+
|
6
|
+
attr_accessor :auth_token
|
7
|
+
|
8
|
+
def initialize(auth_token)
|
9
|
+
@auth_token = auth_token
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_properties
|
13
|
+
response = self.class.post('/getProperties', body: authentication.to_json)
|
14
|
+
json = parse! response
|
15
|
+
json['getProperties']
|
16
|
+
rescue Oj::ParseError
|
17
|
+
raise Error, Constants::PARSE_ERROR_MSG
|
18
|
+
rescue APIError => e
|
19
|
+
e.response
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_property(prop_key, options={})
|
23
|
+
response = self.class.post(
|
24
|
+
'/getProperty',
|
25
|
+
body: payload(prop_key, Constants::DEFAULT_PROPERTY_OPTIONS.merge(options))
|
26
|
+
)
|
27
|
+
json = parse! response
|
28
|
+
json['getProperty'].first
|
29
|
+
rescue Oj::ParseError
|
30
|
+
raise Error, Constants::PARSE_ERROR_MSG
|
31
|
+
rescue APIError => e
|
32
|
+
e.response
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_bookings(prop_key, options={})
|
36
|
+
response = self.class.post(
|
37
|
+
'/getBookings',
|
38
|
+
body: payload(prop_key, Constants::DEFAULT_BOOKING_OPTIONS.merge(options))
|
39
|
+
)
|
40
|
+
parse! response
|
41
|
+
rescue Oj::ParseError
|
42
|
+
raise Error, Constants::PARSE_ERROR_MSG
|
43
|
+
rescue APIError => e
|
44
|
+
e.response
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def authentication(prop_key=nil)
|
50
|
+
{
|
51
|
+
authentication: {
|
52
|
+
apiKey: auth_token,
|
53
|
+
propKey: prop_key
|
54
|
+
}
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def payload(prop_key=nil, options={})
|
59
|
+
authentication(prop_key)
|
60
|
+
.merge(options)
|
61
|
+
.to_json
|
62
|
+
end
|
63
|
+
|
64
|
+
def parse!(response)
|
65
|
+
json = Oj.load response.body
|
66
|
+
raise APIError.new(
|
67
|
+
"API Error: #{json['errorCode']} #{json['error']}",
|
68
|
+
json
|
69
|
+
) if json.is_a?(Hash) && !json['error'].nil?
|
70
|
+
json
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/beds24/version.rb
CHANGED
@@ -0,0 +1,68 @@
|
|
1
|
+
module Beds24
|
2
|
+
class XMLClient
|
3
|
+
include HTTParty
|
4
|
+
base_uri Constants::XML_API_ENDPOINT
|
5
|
+
headers 'Content-Type' => 'text/xml'
|
6
|
+
|
7
|
+
attr_accessor :username, :password
|
8
|
+
|
9
|
+
def initialize(username, password)
|
10
|
+
@username = username
|
11
|
+
@password = password
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_properties(opts = {})
|
15
|
+
response = self.class.post('/getProperties', body: xmlize(opts.slice(:propid)))
|
16
|
+
parse! response
|
17
|
+
rescue APIError => e
|
18
|
+
e.response
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_bookings(opts = {})
|
22
|
+
valid_opts = opts.slice(*Constants::VALID_XML_BOOKING_OPTS)
|
23
|
+
response = self.class.post('/getBookings', body: xmlize(valid_opts))
|
24
|
+
parse! response
|
25
|
+
rescue APIError => e
|
26
|
+
e.response
|
27
|
+
end
|
28
|
+
|
29
|
+
def modify_booking(id, attrs = {})
|
30
|
+
response = self.class.post('/putBookings', body: modify_payload(id, attrs))
|
31
|
+
parse! response
|
32
|
+
rescue APIError => e
|
33
|
+
e.response
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def parse!(response)
|
39
|
+
hash = Hash.from_xml(response.body)
|
40
|
+
raise APIError.new(
|
41
|
+
"API Error: #{hash['code']} #{hash['error']}",
|
42
|
+
hash
|
43
|
+
) if hash.key?('error')
|
44
|
+
hash
|
45
|
+
end
|
46
|
+
|
47
|
+
def auth
|
48
|
+
{ username: @username, password: @password }
|
49
|
+
end
|
50
|
+
|
51
|
+
def xmlize(opts = {})
|
52
|
+
XMLRequest.new(auth, opts).to_xml
|
53
|
+
end
|
54
|
+
|
55
|
+
def modify_payload(id, attrs = {})
|
56
|
+
payload = Nokogiri::XML(xmlize())
|
57
|
+
Nokogiri::XML::Builder.with(payload.at('request')) do |xml|
|
58
|
+
xml.bookings do
|
59
|
+
xml.booking(id: id, action: 'modify') do
|
60
|
+
attrs.each do |prop, value|
|
61
|
+
xml.public_send prop, value
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end.doc.root.to_xml
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Beds24
|
2
|
+
class XMLRequest
|
3
|
+
def initialize(auth, opts = {})
|
4
|
+
@auth = auth
|
5
|
+
@opts = opts
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_xml
|
9
|
+
data = builder.new do |xml|
|
10
|
+
xml.request do
|
11
|
+
xml.auth do
|
12
|
+
xml.username @auth[:username]
|
13
|
+
xml.password @auth[:password]
|
14
|
+
end
|
15
|
+
@opts.each do |prop, value|
|
16
|
+
xml.public_send prop, value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
data.doc.root.to_xml
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def builder
|
26
|
+
Nokogiri::XML::Builder
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/ext/hash.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
class << self
|
5
|
+
def from_xml(xml_io)
|
6
|
+
result = Nokogiri::XML(xml_io)
|
7
|
+
{ result.root.name => xml_node_to_hash(result.root)}
|
8
|
+
end
|
9
|
+
|
10
|
+
def xml_node_to_hash(node)
|
11
|
+
if node.element?
|
12
|
+
result_hash = {}
|
13
|
+
if node.attributes != {}
|
14
|
+
attributes = {}
|
15
|
+
node.attributes.keys.each do |key|
|
16
|
+
if [:id, 'id', :name, 'name'].include?(key)
|
17
|
+
node.name = node.attributes[key].value
|
18
|
+
node.delete(key.to_s)
|
19
|
+
else
|
20
|
+
attributes[node.attributes[key].name] = node.attributes[key].value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
if node.children.size > 0
|
26
|
+
node.children.each do |child|
|
27
|
+
result = xml_node_to_hash(child)
|
28
|
+
|
29
|
+
if child.name == 'text'
|
30
|
+
unless child.next_sibling || child.previous_sibling
|
31
|
+
return result unless attributes
|
32
|
+
result_hash[child.name] = result
|
33
|
+
end
|
34
|
+
elsif result_hash[child.name]
|
35
|
+
if result_hash[child.name].is_a?(Array)
|
36
|
+
result_hash[child.name] << result
|
37
|
+
else
|
38
|
+
result_hash[child.name] = [result_hash[child.name]] << result
|
39
|
+
end
|
40
|
+
else
|
41
|
+
result_hash[child.name] = result
|
42
|
+
end
|
43
|
+
end
|
44
|
+
if attributes
|
45
|
+
result_hash = attributes.merge(result_hash)
|
46
|
+
end
|
47
|
+
return result_hash
|
48
|
+
else
|
49
|
+
return attributes
|
50
|
+
end
|
51
|
+
else
|
52
|
+
node.content.to_s
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beds24
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Babin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-10-
|
11
|
+
date: 2019-10-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -131,7 +131,9 @@ extra_rdoc_files: []
|
|
131
131
|
files:
|
132
132
|
- ".gitignore"
|
133
133
|
- ".rspec"
|
134
|
+
- ".rspec_status"
|
134
135
|
- ".travis.yml"
|
136
|
+
- CHANGELOG.md
|
135
137
|
- Gemfile
|
136
138
|
- LICENSE.txt
|
137
139
|
- README.md
|
@@ -140,7 +142,12 @@ files:
|
|
140
142
|
- bin/console
|
141
143
|
- bin/setup
|
142
144
|
- lib/beds24.rb
|
145
|
+
- lib/beds24/constants.rb
|
146
|
+
- lib/beds24/json_client.rb
|
143
147
|
- lib/beds24/version.rb
|
148
|
+
- lib/beds24/xml_client.rb
|
149
|
+
- lib/beds24/xml_request.rb
|
150
|
+
- lib/ext/hash.rb
|
144
151
|
homepage: https://github.com/mihilbabin/beds24
|
145
152
|
licenses:
|
146
153
|
- MIT
|