diff --git a/betfair/betfair.py b/betfair/betfair.py index 0d9987c..205781a 100644 --- a/betfair/betfair.py +++ b/betfair/betfair.py @@ -14,7 +14,7 @@ from betfair import utils from betfair import models from betfair import exceptions - +from betfair.models import ScoreEvent, Score, Incidents IDENTITY_URLS = collections.defaultdict( lambda: 'https://identitysso.betfair.com/api/', @@ -26,6 +26,16 @@ australia='https://api-au.betfair.com/exchange/betting/json-rpc/v1', ) +SCORE_URLS = collections.defaultdict( + lambda: 'https://api.betfair.com/exchange/scores/json-rpc/v1' +) + +urls = { + 'Betting': 'https://api.betfair.com/exchange/betting/json-rpc/v1', + 'Accounts': 'https://api.betfair.com/exchange/account/json-rpc/v1', + 'Score': 'https://api.betfair.com/exchange/scores/json-rpc/v1' +} + class Betfair(object): """Betfair API client. @@ -38,6 +48,7 @@ class Betfair(object): :param Session session: Optional Requests session :param int timeout: Optional timeout duration (seconds) """ + def __init__(self, app_key, cert_file, content_type='application/json', locale=None, session=None, timeout=None): self.app_key = app_key @@ -56,6 +67,10 @@ def identity_url(self): def api_url(self): return API_URLS[self.locale] + @property + def score_url(self): + return SCORE_URLS[self.locale] + @property def headers(self): return { @@ -76,10 +91,13 @@ def make_auth_request(self, method): if data.get('status') != 'SUCCESS': raise exceptions.AuthError(response, data) - def make_api_request(self, base, method, params, codes=None, model=None): + def make_api_request(self, base, method, params, codes=None, model=None, api='Betting'): payload = utils.make_payload(base, method, params) + url = urls.get(api) + if not url: + raise exceptions.ApiError("no such API", method) response = self.session.post( - self.api_url, + url, data=json.dumps(payload, cls=utils.BetfairEncoder), headers=self.headers, timeout=self.timeout, @@ -235,7 +253,7 @@ def list_venues(self, filter=None, locale=None): filter = filter or models.MarketFilter() return self.make_api_request( 'Sports', - 'listVenues', + 'listCountries', utils.get_kwargs(locals()), model=models.VenueResult, ) @@ -409,7 +427,7 @@ def cancel_orders(self, market_id, instructions, customer_ref=None): 'Sports', 'cancelOrders', utils.get_kwargs(locals()), - model=models.CancelExecutionReport, + model=models.CancelInstructionReport, ) @utils.requires_login @@ -449,12 +467,14 @@ def get_account_funds(self, wallet=None): :param Wallet wallet: Name of the wallet in question """ - return self.make_api_request( + result = self.make_api_request( 'Account', 'getAccountFunds', utils.get_kwargs(locals()), model=models.AccountFundsResponse, + api='Accounts' ) + return result @utils.requires_login def get_account_statement( @@ -469,7 +489,7 @@ def get_account_statement( :param IncludeItem include_item: Which items to include :param Wallet wallte: Which wallet to return statementItems for """ - return self.make_api_request( + result = self.make_api_request( 'Account', 'getAccountStatement', utils.get_kwargs(locals()), @@ -481,12 +501,14 @@ def get_account_details(self): """Returns the details relating your account, including your discount rate and Betfair point balance. """ - return self.make_api_request( + result = self.make_api_request( 'Account', 'getAccountDetails', utils.get_kwargs(locals()), model=models.AccountDetailsResponse, + api='Accounts' ) + return result @utils.requires_login def list_currency_rates(self, from_currency=None): @@ -494,7 +516,7 @@ def list_currency_rates(self, from_currency=None): :param str from_currency: The currency from which the rates are computed """ - return self.make_api_request( + result = self.make_api_request( 'Account', 'listCurrencyRates', utils.get_kwargs(locals()), @@ -509,9 +531,59 @@ def transfer_funds(self, from_, to, amount): :param Wallet to: Destination wallet :param float amount: Amount to transfer """ - return self.make_api_request( + result = self.make_api_request( 'Account', 'transferFunds', utils.get_kwargs(locals()), model=models.TransferResponse, ) + + @utils.requires_login + def list_scores(self, update_keys): + """List scores of keys in update keys from scores API + + :param List update_keys: Keys to update + """ + update_keys = [{'eventId': k} for k in update_keys] + k = None + del k # Stop k from propagiting as part of locals() + return self.make_api_request( + 'Scores', + 'listScores', + utils.get_kwargs(locals()), + api='Score', + model=Score + ) + + @utils.requires_login + def list_available_events(self, event_ids=None, event_type_ids=None, event_status=None): + """List events that one can query with the scores API + + :param event_ids: + :param event_type_ids: + :param event_status: + """ + return self.make_api_request( + 'Scores', + 'listAvailableEvents', + utils.get_kwargs(locals()), + api='Score', + model=ScoreEvent + ) + + @utils.requires_login + def list_incidents(self, update_keys): + """List incidents for the keys in update_keys + + :param List update_keys: list of keys to get incidents for + """ + update_keys = [{'eventId': k} for k in update_keys] + k = None + del k # Stop k from propagiting as part of locals() + return self.make_api_request( + 'Scores', + 'listIncidents', + utils.get_kwargs(locals()), + api='Score', + model=Incidents + ) diff --git a/betfair/constants.py b/betfair/constants.py index 3f3b76b..b9d6bab 100644 --- a/betfair/constants.py +++ b/betfair/constants.py @@ -6,7 +6,6 @@ from enum import Enum - MarketProjection = Enum( 'MarketProjection', [ 'COMPETITION', @@ -174,6 +173,12 @@ ] ) +TimeInForce = Enum( + 'TimeInForce', [ + 'FILL_OR_KILL' + ] +) + InstructionReportStatus = Enum( 'InstructionReportStatus', [ 'SUCCESS', @@ -270,3 +275,16 @@ 'UNKNOWN', ] ) + +EventStatus = Enum( + 'EventStatus', [ + 'IN_PROGRESS', + 'PENDING', + 'NO_NEW_UPDATES', + 'NO_LIVE_DATA_AVAILABLE', + 'SERVICE_UNAVAILABLE', + 'UNEXPECTED_ERROR', + 'LIVE_DATA_TEMPORARILY_UNAVAILABLE', + 'FINISHED' + ] +) diff --git a/betfair/meta/models.py b/betfair/meta/models.py index 08856bf..8ab19da 100644 --- a/betfair/meta/models.py +++ b/betfair/meta/models.py @@ -21,7 +21,7 @@ def __new__(meta, name, bases, attrs): class BetfairModel(six.with_metaclass(BetfairModelMeta, models.Model)): - def __init__(self, **data): + def __init__(self, *args, **data): super(BetfairModel, self).__init__() self.import_data(data) diff --git a/betfair/models.py b/betfair/models.py index bb95e92..f72984e 100644 --- a/betfair/models.py +++ b/betfair/models.py @@ -210,6 +210,8 @@ class LimitOrder(BetfairModel): size = FloatType(required=True) price = FloatType(required=True) persistence_type = EnumType(constants.PersistenceType, required=True) + time_in_force = EnumType(constants.TimeInForce) + min_fill_size = FloatType() class LimitOnCloseOrder(BetfairModel): @@ -224,7 +226,6 @@ class MarketOnCloseOrder(BetfairModel): # Results class CompetitionResult(BetfairModel): - competition = ModelType(Competition) market_count = IntType() competition_region = StringType() @@ -236,13 +237,11 @@ class CountryCodeResult(BetfairModel): class EventResult(BetfairModel): - event = ModelType(Event) market_count = IntType() class EventTypeResult(BetfairModel): - event_type = ModelType(EventType) market_count = IntType() @@ -253,7 +252,6 @@ class MarketTypeResult(BetfairModel): class TimeRangeResult(BetfairModel): - time_range = ModelType(TimeRange) market_count = IntType() @@ -350,7 +348,6 @@ class ClearedOrderSummary(BetfairModel): size_settled = FloatType() profit = FloatType() size_cancelled = FloatType() - bet_outcome = StringType() class ClearedOrderSummaryReport(BetfairModel): @@ -480,3 +477,45 @@ class CurrencyRate(BetfairModel): class TransferResponse(BetfairModel): transaction_id = StringType() + + +# Score + +class ScoreEvent(BetfairModel): + event_id = IntType() + event_status = StringType() + event_type_id = IntType() + + +class ScoreContext(BetfairModel): + event_time = StringType() + last_updated = DateTimeType() + update_sequence = IntType() + update_type = StringType() + + +class Score(BetfairModel): + event_id = IntType() + event_type_id = IntType() + update_context = ModelType(ScoreContext) + values = DictType(StringType) + event_status = EnumType(constants.EventStatus, required=True) + + +class UpdateContext(BetfairModel): + event_type = StringType() + last_updated = DateTimeType() + update_sequence = IntType() + update_type = StringType() + + +class Incident(BetfairModel): + update_context = ModelType(UpdateContext) + values = DictType(StringType) + + +class Incidents(BetfairModel): + event_id = IntType() + event_type_id = IntType() + event_status = EnumType(constants.EventStatus, required=True) + incidents = ListType(ModelType(Incident))