BettingArbitrageBot/Arbitrage/UnibetService.cs

264 lines
9.3 KiB
C#
Raw Normal View History

2022-12-07 12:48:00 +11:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace Arbitrage
{
public class UnibetService : BookkeeperService
{
private UnibetServiceConfiguration mConfiguration { get; set; }
private dynamic? OddsData { get; set; }
private Dictionary<string, List<string>> mEventParticipants { get; set; }
public UnibetService()
{
IConfiguration config = new ConfigurationBuilder()
.AddJsonFile("configuration.json")
.Build();
mConfiguration = config.GetRequiredSection("unibetService").Get<UnibetServiceConfiguration>();
mEventParticipants = new Dictionary<string, List<string>>();
}
public async Task InitialiseAsync()
{
UriBuilder uriBuilder = new UriBuilder(mConfiguration.BaseSiteUrl);
var httpResult = await mHttpClient.GetAsync(uriBuilder.ToString());
if (!httpResult.IsSuccessStatusCode)
{
mLogger.LogWarning($"Could not get visit Ladbrokes");
}
}
public override async Task<IEnumerable<BookkeeperEvent>> GetSportEventsAsync(Sport sport)
{
if (!mConfiguration.GetSportEventsUrls.Select(x => x.Key).Contains(sport))
{
mLogger.LogWarning($"Unibet not configured to retrieve {sport} events.");
return new List<BookkeeperEvent>();
}
UriBuilder uriBuilder = new UriBuilder(mConfiguration.GetSportEventsUrls[sport]);
var httpResult = await mHttpClient.GetAsync(uriBuilder.ToString());
if (!httpResult.IsSuccessStatusCode)
{
mLogger.LogWarning($"Could not get {sport} events from Unibet");
return new List<BookkeeperEvent>();
}
dynamic? data = JsonConvert.DeserializeObject<dynamic>(await httpResult.Content.ReadAsStringAsync());
if (data == null)
{
mLogger.LogWarning($"Could not deserialise Unibet events for {sport}");
return new List<BookkeeperEvent>();
}
List<BookkeeperEvent> events = new List<BookkeeperEvent>();
foreach (dynamic section in data["layout"]["sections"])
{
foreach (dynamic widget in section["widgets"])
{
foreach (dynamic group in widget["matches"]["groups"])
{
List<dynamic> eventDatas = GetEventsFromGroup(group);
foreach (dynamic eventData in eventDatas)
{
string eventId = eventData.id.ToString();
List<string> participantIds = new List<string>();
if (eventData.ContainsKey("participants"))
{
foreach (dynamic participant in eventData["participants"])
{
participantIds.Add(participant["name"].ToString());
}
}
DateTimeOffset commencementTime = DateTimeOffset.Parse((string)eventData["start"].ToString()).ToUniversalTime();
string url = new Uri(new Uri(mConfiguration.BaseEventUrl), eventId).ToString();
events.Add(new BookkeeperEvent()
{
Bookkeeper = Bookkeeper.Unibet,
BookkeeperEventId = eventId,
Name = eventData.name.ToString(),
Competition = string.Join(" ", ((IEnumerable<dynamic>)eventData.path).Select(x => x.name.ToString())),
Commencement = commencementTime,
Url = url
});
mEventParticipants.Add(eventId, participantIds);
}
}
}
}
return events;
}
private static List<dynamic> GetEventsFromGroup(dynamic group)
{
List<dynamic> events = new List<dynamic>();
dynamic subGroups = group["subGroups"];
if (subGroups == null)
{
foreach (dynamic @event in group["events"])
{
events.Add(@event["event"]);
}
return events;
}
foreach (dynamic subgroup in subGroups)
{
events.AddRange(GetEventsFromGroup(subgroup));
}
return events;
}
public override async Task<IEnumerable<BookkeeperMarket>> GetEventMarketsAsync(BookkeeperEvent bookkeeperEvent)
{
UriBuilder uriBuilder = new UriBuilder(new Uri(new Uri(mConfiguration.GetOddsUrl), bookkeeperEvent.BookkeeperEventId));
var httpResult = await mHttpClient.GetAsync(uriBuilder.ToString());
if (!httpResult.IsSuccessStatusCode)
{
mLogger.LogWarning($"Could not get Unibet markets for event {bookkeeperEvent.BookkeeperEventId}");
return new List<BookkeeperMarket>();
}
dynamic? data = JsonConvert.DeserializeObject<dynamic>(await httpResult.Content.ReadAsStringAsync());
if (data == null)
{
mLogger.LogWarning($"Could not deserialise Unibet markets for event {bookkeeperEvent.BookkeeperEventId}");
return new List<BookkeeperMarket>();
}
OddsData = data;
List<BookkeeperMarket> markets = new List<BookkeeperMarket>();
foreach (dynamic market in OddsData["betOffers"])
{
string marketName = market["betOfferType"]["name"];
if (market["criterion"] != null)
{
marketName += " " + market["criterion"]["label"];
}
dynamic firstOutcome = market["outcomes"][0];
if (firstOutcome.ContainsKey("line"))
{
float line;
bool didParse = float.TryParse(firstOutcome["line"].ToString(), out line);
if (didParse)
{
marketName += " " + (line / 1000.0).ToString("0.0");
}
}
markets.Add(new BookkeeperMarket()
{
Bookkeeper = Bookkeeper.Unibet,
BookkeeperMarketId = market.id,
Name = marketName,
Url = bookkeeperEvent.Url
});
}
return markets;
}
public async override Task<IEnumerable<BookkeeperOdds>> GetMarketOddsAsync(Event @event, BookkeeperMarket bookkeeperMarket)
{
if (OddsData == null)
{
throw new Exception("OddsData property is not populated.");
}
dynamic betOffer = ((IEnumerable<dynamic>)OddsData["betOffers"]).First(x => x.id == bookkeeperMarket.BookkeeperMarketId);
List<BookkeeperOdds> bookkeeperOdds = new List<BookkeeperOdds>();
foreach (dynamic outcome in betOffer["outcomes"])
{
if (!outcome.ContainsKey("odds"))
{
continue;
}
double value = double.Parse(outcome["odds"].ToString()) / 1000;
string outcomeString = outcome["label"].ToString();
List<int> validParticipantIndices = new List<int>();
if (mEventParticipants.Keys.Contains(@event.TMPUnibetEventId))
{
for (int i = 0; i < mEventParticipants[@event.TMPUnibetEventId].Count; i++)
{
validParticipantIndices.Add(i);
}
}
string newOutcomeString = outcomeString;
foreach (string c in outcomeString.ToList().Select(x => x.ToString()))
{
int representation = -1;
if (int.TryParse(c, out representation))
{
if (validParticipantIndices.Contains(representation - 1))
{
newOutcomeString = newOutcomeString.Replace(c, mEventParticipants[@event.TMPUnibetEventId][representation - 1]);
}
}
else if (c == "X")
{
newOutcomeString = newOutcomeString.Replace(c, "Draw");
}
}
bookkeeperOdds.Add(new BookkeeperOdds()
{
Bookkeeper = Bookkeeper.Unibet,
BookkeeperOddsId = outcome["id"],
Outcome = newOutcomeString,
Value = value,
Url = bookkeeperMarket.Url
});
}
return bookkeeperOdds;
}
}
}