betfair 0.0.13 → 0.0.14

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.
Files changed (3) hide show
  1. data/lib/betfair/api.rb +206 -83
  2. data/lib/betfair/version.rb +1 -1
  3. metadata +12 -12
data/lib/betfair/api.rb CHANGED
@@ -2,131 +2,254 @@ module Betfair
2
2
 
3
3
  class API
4
4
 
5
+
6
+ ## Some handy constants...
7
+
8
+ EXCHANGE_IDS = {
9
+ :aus => 2,
10
+ :uk => 1
11
+ }
12
+
13
+ PRODUCT_ID_FREE = 82
14
+
15
+ BET_TYPE_LAY = 'L'
16
+ BET_TYPE_BACK = 'B'
17
+
18
+
19
+ ## API METHODS
20
+ #
21
+
5
22
  def place_bet(session_token, exchange_id, market_id, runner_id, bet_type, price, size)
6
- bf_bet = { :marketId => market_id, :selectionId => runner_id, :betType => bet_type, :price => price, :size => size, :asianLineId => 0, :betCategoryType => 'E', :betPersistenceType => 'NONE', :bspLiability => 0 }
7
- response = exchange(exchange_id).request :bf, :placeBets do
8
- soap.body = { 'bf:request' => { :header => api_request_header(session_token), :bets => { 'PlaceBets' => [bf_bet] } } }
9
- end
10
- error_code = response.to_hash[:place_bets_response][:result][:error_code]
11
- error_code2 = response.to_hash[:place_bets_response][:result][:header][:error_code]
12
- return error_code == 'OK' ? response.to_hash[:place_bets_response][:result][:bet_results][:place_bets_result] : "#{error_code} - #{error_code2}"
23
+ bf_bet = {
24
+ :marketId => market_id,
25
+ :selectionId => runner_id,
26
+ :betType => bet_type,
27
+ :price => price,
28
+ :size => size,
29
+ :asianLineId => 0,
30
+ :betCategoryType => 'E',
31
+ :betPersistenceType => 'NONE',
32
+ :bspLiability => 0
33
+ }
34
+
35
+ response = exchange(exchange_id).
36
+ session_request( session_token,
37
+ :placeBets,
38
+ :place_bets_response,
39
+ :bets => { 'PlaceBets' => [bf_bet] } )
40
+
41
+ return response.maybe_result( :bet_results, :place_bets_result )
13
42
  end
14
43
 
44
+
15
45
  def cancel_bet(session_token, exchange_id, bet_id)
16
- response = exchange(exchange_id).request :bf, :cancelBets do
17
- soap.body = { 'bf:request' => { :header => api_request_header(session_token), :bets => { 'CancelBets' => [ { :betId => bet_id } ] } } } # "CancelBets" has to be a string, not a symbol!
18
- end
19
- error_code = response.to_hash[:cancel_bets_response][:result][:error_code]
20
- error_code2 = response.to_hash[:cancel_bets_response][:result][:header][:error_code]
21
- return error_code == 'OK' ? response.to_hash[:cancel_bets_response][:result][:bet_results][:cancel_bets_result] : "#{error_code} - #{error_code2}"
46
+ bf_bet = { :betId => bet_id }
47
+
48
+ response = exchange(exchange_id).
49
+ session_request( session_token,
50
+ :cancelBets,
51
+ :cancel_bets_response,
52
+ :bets => { 'CancelBets' => [bf_bet] } ) # "CancelBets" has to be a string, not a symbol!
53
+
54
+ return response.maybe_result( :bet_results, :cancel_bets_result )
22
55
  end
23
56
 
57
+
24
58
  def get_market(session_token, exchange_id, market_id, locale = nil)
25
- response = exchange(exchange_id).request :bf, :getMarket do
26
- soap.body = { 'bf:request' => { :header => api_request_header(session_token), :marketId => market_id, :locale => locale } }
27
- end
28
- error_code = response.to_hash[:get_market_response][:result][:error_code]
29
- error_code2 = response.to_hash[:get_market_response][:result][:header][:error_code]
30
- return error_code == 'OK' ? response.to_hash[:get_market_response][:result][:market] : "#{error_code} - #{error_code2}"
59
+ response = exchange(exchange_id).
60
+ session_request( session_token,
61
+ :getMarket,
62
+ :get_market_response,
63
+ :marketId => market_id,
64
+ :locale => locale )
65
+
66
+ return response.maybe_result( :market )
31
67
  end
32
68
 
69
+
33
70
  def get_market_prices_compressed(session_token, exchange_id, market_id, currency_code = nil)
34
- response = exchange(exchange_id).request :bf, :getMarketPricesCompressed do
35
- soap.body = { 'bf:request' => { :header => api_request_header(session_token), :marketId => market_id, :currencyCode => currency_code } }
36
- end
37
- error_code = response.to_hash[:get_market_prices_compressed_response][:result][:error_code]
38
- error_code2 = response.to_hash[:get_market_prices_compressed_response][:result][:header][:error_code]
39
- return error_code == 'OK' ? response.to_hash[:get_market_prices_compressed_response][:result][:market_prices] : "#{error_code} - #{error_code2}"
71
+ response = exchange(exchange_id).
72
+ session_request( session_token,
73
+ :getMarketPricesCompressed,
74
+ :get_market_prices_compressed_response,
75
+ :marketId => market_id,
76
+ :currencyCode => currency_code )
77
+
78
+ return response.maybe_result( :market_prices )
40
79
  end
41
80
 
81
+
42
82
  def get_active_event_types(session_token, locale = nil)
43
- response = @global_service.request :bf, :getActiveEventTypes do
44
- soap.body = { 'bf:request' => { :header => api_request_header(session_token),
45
- :locale => locale
46
- }
47
- }
48
- end
49
- error_code = response.to_hash[:get_active_event_types_response][:result][:error_code]
50
- error_code2 = response.to_hash[:get_active_event_types_response][:result][:header][:error_code]
51
- return error_code == 'OK' ? response.to_hash[:get_active_event_types_response][:result][:event_type_items][:event_type] : "#{error_code} - #{error_code2}"
83
+ response = @global_service.
84
+ session_request( session_token,
85
+ :getActiveEventTypes,
86
+ :get_active_event_types_response,
87
+ :locale => locale )
88
+
89
+ return response.maybe_result( :event_type_items, :event_type )
52
90
  end
53
91
 
92
+
54
93
  def get_all_markets(session_token, exchange_id, event_type_ids = nil, locale = nil, countries = nil, from_date = nil, to_date = nil)
55
- response = exchange(exchange_id).request :bf, :getAllMarkets do
56
- soap.body = { 'bf:request' => { :header => api_request_header(session_token),
57
- :eventTypeIds => { 'int' => event_type_ids },
58
- :locale => locale, :countries => { 'country' => countries },
59
- :fromDate => from_date,
60
- :toDate => to_date
61
- }
62
- }
63
- end
64
- error_code = response.to_hash[:get_all_markets_response][:result][:error_code]
65
- error_code2 = response.to_hash[:get_all_markets_response][:result][:header][:error_code]
66
- return error_code == 'OK' ? response.to_hash[:get_all_markets_response][:result][:market_data] : "#{error_code} - #{error_code2}"
94
+ response = exchange(exchange_id).
95
+ session_request( session_token,
96
+ :getAllMarkets,
97
+ :get_all_markets_response,
98
+ :eventTypeIds => { 'int' => event_type_ids },
99
+ :locale => locale,
100
+ :countries => { 'country' => countries },
101
+ :fromDate => from_date,
102
+ :toDate => to_date )
103
+
104
+ return response.maybe_result( :market_data )
67
105
  end
68
106
 
69
107
 
70
108
  def get_account_funds( session_token, exchange_id )
71
- response = exchange( exchange_id ).request :bf, :getAccountFunds do
72
- soap.body = { 'bf:request' => { :header => api_request_header(session_token) } }
73
- end
74
- error_code = response.to_hash[:get_account_funds_response][:result][:error_code]
75
- error_code2 = response.to_hash[:get_account_funds_response][:result][:header][:error_code]
76
- return error_code == 'OK' ? response.to_hash[:get_account_funds_response][:result] : "#{error_code} - #{error_code2}"
109
+ response = exchange( exchange_id ).
110
+ session_request( session_token,
111
+ :getAccountFunds,
112
+ :get_account_funds_response )
113
+
114
+ return response.maybe_result
77
115
  end
78
116
 
117
+
79
118
  def login(username, password, product_id, vendor_software_id, location_id, ip_address)
80
- response = @global_service.request :bf, :login do
81
- soap.body = { 'bf:request' => { :username => username,
82
- :password => password,
83
- :productId => product_id,
84
- :vendorSoftwareId => vendor_software_id,
85
- :locationId => location_id,
86
- :ipAddress => ip_address
87
- }
88
- }
89
- end
90
- session_token(response.to_hash[:login_response][:result][:header])
119
+ response = @global_service.request( :login,
120
+ :login_response,
121
+ :username => username,
122
+ :password => password,
123
+ :productId => product_id,
124
+ :vendorSoftwareId => vendor_software_id,
125
+ :locationId => location_id,
126
+ :ipAddress => ip_address )
127
+
128
+ session_token(response[:header])
91
129
  end
92
130
 
93
- def exchange(exchange_id)
94
- exchange_id == 2 ? @aus_service : @uk_service
95
- end
131
+ #
132
+ ## END OF API METHODS
96
133
 
97
- def api_request_header(session_token)
98
- { :client_stamp => 0, :session_token => session_token }
134
+
135
+ def exchange(exchange_id)
136
+ exchange_id == EXCHANGE_IDS[:aus] ? @aus_service : @uk_service
99
137
  end
100
138
 
101
139
  def session_token(response_header)
102
140
  response_header[:error_code] == 'OK' ? response_header[:session_token] : response_header[:error_code]
103
141
  end
104
142
 
143
+
105
144
  def initialize(proxy = nil, logging = nil)
106
145
 
107
- logging == true ? Savon.log = true : Savon.log = false
146
+ SOAPClient.log = logging
147
+
148
+ @global_service = SOAPClient.global( proxy )
149
+ @uk_service = SOAPClient.uk( proxy )
150
+ @aus_service = SOAPClient.aus( proxy )
151
+
152
+ end
153
+
154
+
155
+
156
+
157
+ # A wrapper around the raw Savon::Client to hide the details of
158
+ # the Savon API and those parts of the Betfair API which are
159
+ # constant across the different API method calls
160
+ class SOAPClient
161
+
162
+ # Handy constants
163
+ NAMESPACES = {
164
+ :aus => 'http://www.betfair.com/exchange/v3/BFExchangeService/AUS',
165
+ :global => 'https://www.betfair.com/global/v3/BFGlobalService',
166
+ :uk => 'http://www.betfair.com/exchange/v3/BFExchangeService/UK' }
167
+ ENDPOINTS = {
168
+ :aus => 'https://api-au.betfair.com/exchange/v5/BFExchangeService',
169
+ :global => 'https://api.betfair.com/global/v3/BFGlobalService',
170
+ :uk => 'https://api.betfair.com/exchange/v5/BFExchangeService' }
171
+
172
+
173
+ # Factory methods for building clients to the different endpoints
174
+ def self.global( proxy ); new( :global, proxy ); end
175
+ def self.uk( proxy ); new( :uk, proxy ); end
176
+ def self.aus( proxy ); new( :aus, proxy ); end
177
+
178
+
179
+ # Wrapper to avoid leaking Savon's logging API
180
+ def self.log=(logging); Savon.log = !!logging; end
108
181
 
109
- @global_service = Savon::Client.new do |wsdl, http|
110
- wsdl.endpoint = 'https://api.betfair.com/global/v3/BFGlobalService'
111
- wsdl.namespace = 'https://www.betfair.com/global/v3/BFGlobalService'
112
- http.proxy = proxy if !proxy.nil?
182
+
183
+ # Pass the `region` (see ENDPOINTS for valid values) to pick the
184
+ # WSDL endpoint and namespace. `proxy` should be a string URL
185
+ # for HTTPI to use as a proxy setting.
186
+ def initialize( region, proxy )
187
+ @client = Savon::Client.new do |wsdl, http|
188
+ wsdl.endpoint = ENDPOINTS[region]
189
+ wsdl.namespace = NAMESPACES[region]
190
+ http.proxy = proxy if proxy
191
+ end
113
192
  end
114
193
 
115
- @uk_service = Savon::Client.new do |wsdl, http|
116
- wsdl.endpoint = 'https://api.betfair.com/exchange/v5/BFExchangeService'
117
- wsdl.namespace = 'http://www.betfair.com/exchange/v3/BFExchangeService/UK'
118
- http.proxy = proxy if !proxy.nil?
194
+
195
+ # Delegate the SOAP call to bf:`method` with `body` as the
196
+ # `bf:request` field. Getting a Hash back, this method returns
197
+ # response[result_field][:result] as its result.
198
+ def request( method, result_field, body )
199
+ response = @client.request( :bf, method ) {
200
+ soap.body = { 'bf:request' => body }
201
+ }.to_hash[result_field][:result]
202
+
203
+ response.extend( ErrorPresenter )
204
+
205
+ response
119
206
  end
120
207
 
121
- @aus_service = Savon::Client.new do |wsdl, http|
122
- wsdl.endpoint = 'https://api-au.betfair.com/exchange/v5/BFExchangeService'
123
- wsdl.namespace = 'http://www.betfair.com/exchange/v3/BFExchangeService/AUS'
124
- http.proxy = proxy if !proxy.nil?
208
+
209
+ # For those requests which take place in the context of a session,
210
+ # this method constructs the correct header and delegates to #request.
211
+ def session_request( session_token, method, result_field, body = {})
212
+ header_body = { :header => api_request_header(session_token) }
213
+ full_body = header_body.merge( body )
214
+
215
+ request method, result_field, full_body
125
216
  end
126
217
 
127
- end
128
218
 
129
- end
219
+ def api_request_header(session_token)
220
+ { :client_stamp => 0, :session_token => session_token }
221
+ end
222
+ protected :api_request_header
223
+
224
+
225
+ end # class SoapClient
226
+
227
+
228
+ # Mix this into a Hash to give it basic error reporting and a nice
229
+ # path-based data extractor.
230
+ module ErrorPresenter
231
+
232
+ def success?
233
+ self[:error_code] == "OK"
234
+ end
235
+
236
+
237
+ def format_error
238
+ "#{self[:error_code]} - #{self[:header][:error_code]}"
239
+ end
240
+
241
+
242
+ def maybe_result( *path )
243
+ success? ? path.inject(self){|m,r| m[r]} : format_error()
244
+ end
245
+
246
+
247
+ end # module ErrorPresenter
248
+
249
+
250
+ end # class API
251
+
252
+
130
253
 
131
254
  class Helpers
132
255
 
@@ -1,3 +1,3 @@
1
1
  module Betfair
2
- VERSION = "0.0.13"
2
+ VERSION = "0.0.14"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: betfair
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
4
+ version: 0.0.14
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-27 00:00:00.000000000Z
12
+ date: 2012-02-29 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: savon
16
- requirement: &70291854542960 !ruby/object:Gem::Requirement
16
+ requirement: &70236502261180 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70291854542960
24
+ version_requirements: *70236502261180
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &70291854541880 !ruby/object:Gem::Requirement
27
+ requirement: &70236502258180 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70291854541880
35
+ version_requirements: *70236502258180
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70291854540880 !ruby/object:Gem::Requirement
38
+ requirement: &70236502252040 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70291854540880
46
+ version_requirements: *70236502252040
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: savon_spec
49
- requirement: &70291854539840 !ruby/object:Gem::Requirement
49
+ requirement: &70236502249320 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70291854539840
57
+ version_requirements: *70236502249320
58
58
  description: Gem for accessing the Betfair API.
59
59
  email:
60
60
  - lukeb@lukebyrne.com
@@ -102,7 +102,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
102
102
  version: '0'
103
103
  segments:
104
104
  - 0
105
- hash: -2983570207811971585
105
+ hash: -2051552141254141461
106
106
  required_rubygems_version: !ruby/object:Gem::Requirement
107
107
  none: false
108
108
  requirements:
@@ -111,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
111
  version: '0'
112
112
  segments:
113
113
  - 0
114
- hash: -2983570207811971585
114
+ hash: -2051552141254141461
115
115
  requirements: []
116
116
  rubyforge_project: betfair
117
117
  rubygems_version: 1.8.10