betfair 0.0.13 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
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