Skip to content

Commit

Permalink
correctly parse orbit data
Browse files Browse the repository at this point in the history
  • Loading branch information
nigelnindodev committed Oct 18, 2023
1 parent cb3c40a commit d606703
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/core/parsers/betika/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export class BetikaParser extends BaseParser {
throw new Error(`Unknown bet type provided for provider: ${this.betProvider.name}`);
}

if (results2.result == "success") {
if (results2.result === "success") {
logger.info("Successfully fetched games: ", results2.value);
} else {
logger.error("Failed to parse html into games: ", {
Expand Down
4 changes: 2 additions & 2 deletions src/core/parsers/betika/parser_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function processBetikaTwoWayGamesHtml(html: string): Result<any[], Error>
});
return {result: "success", value: gameEvents};
} catch (e: any) {
logger.error('An error occurred while parsing Betika two way html data: ', e.message);
logger.error("An error occurred while parsing Betika two way html data: ", e.message);
return {result: "error", value: new Error(e.message)};
}
}
Expand All @@ -55,7 +55,7 @@ export function processBetikaThreeWayGamesHtml(html: string): Result<any[], Erro
});
return {result: "success", value: gameEvents};
} catch (e: any) {
logger.error('An error occurred while parsing Betika two way html data: ', e.message);
logger.error("An error occurred while parsing Betika two way html data: ", e.message);
return {result: "error", value: new Error(e.message)};
}
}
82 changes: 82 additions & 0 deletions src/core/parsers/orbit/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { BaseParser } from "..";
import { getConfig } from "../../..";
import { BetProvider } from "../../../bet_providers";
import { OrbitProvider } from "../../../bet_providers/orbit";
import { RedisSingleton } from "../../../datastores/redis";
import { getRedisHtmlParserChannelName } from "../../../utils/redis";
import { BetTypes, RawHtmlForProcessingMessage } from "../../../utils/types/common";
import { Result } from "../../../utils/types/result_type";
import { processOrbitThreeWayGamesHtml } from "./parser_types";

const {logger} = getConfig();

export class OrbitParser extends BaseParser {
public override betProvider: BetProvider;

constructor() {
super();
this.betProvider = new OrbitProvider();
}

// TODO: This function should be moved to the base class
public async subscribeToChannels(): Promise<Result<boolean, Error>> {
const getBetProviderConfigResult = await this.betProvider.getConfig();
if (getBetProviderConfigResult.result === "error") {
logger.error("HTML parse failed to load config for provider: ", this.betProvider.name);
return getBetProviderConfigResult;
}

const getRedisSubscriberResult = await RedisSingleton.getSubscriber();
if (getRedisSubscriberResult.result === "success") {
const betProviderConfig = getBetProviderConfigResult.value;
const results = betProviderConfig.games.map(async game => {
await getRedisSubscriberResult.value.subscribe(getRedisHtmlParserChannelName(this.betProvider, game), message => {
const parsedMessage = JSON.parse(message) as RawHtmlForProcessingMessage;
logger.trace("Redis subscriber message received.", {
betProviderName: parsedMessage.betProviderName,
betType: parsedMessage.betType,
fromUrl: parsedMessage.fromUrl,
gameName: parsedMessage.gameName
});
this.processRawHtmlMessage(parsedMessage);
});
return true;
});
await Promise.all(results);
return {result: "success", value: true};
} else {
logger.error("HTML parser failed to connect to redis subscriber for bet provider: ", this.betProvider.name);
return getRedisSubscriberResult;
}
}

private processRawHtmlMessage(parsedMessage: RawHtmlForProcessingMessage): void {
let results2;
switch (parsedMessage.betType) {
case BetTypes.THREE_WAY:
results2 = processOrbitThreeWayGamesHtml(parsedMessage.rawHtml);
break;
default:
const message = "Unknown bet type provided";
logger.error(message, {
betProviderName: parsedMessage.betProviderName,
betType: parsedMessage.betType,
fromUrl: parsedMessage.fromUrl,
gameName: parsedMessage.gameName
});
throw new Error(`Unknown bet type provided for provider: ${this.betProvider.name}`);
}

if (results2.result === "success") {
logger.info("Successfully fetched games", results2.value);
} else {
logger.error("Failed to parse html into games: ", {
betProviderName: parsedMessage.betProviderName,
betType: parsedMessage.betType,
fromUrl: parsedMessage.fromUrl,
gameName: parsedMessage.gameName,
errorMessage: results2.value.message
});
}
}
}
74 changes: 74 additions & 0 deletions src/core/parsers/orbit/parser_types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import * as cheerio from "cheerio";
import _ from "lodash";

import { getConfig } from "../../..";
import { Result } from "../../../utils/types/result_type";

const {logger} = getConfig();

export function processOrbitThreeWayGamesHtml(html: string): Result<any[], Error> {
const gameEvents: any[] = [];

const $ = cheerio.load(html);
try {

$("div.rowsContainer").each((_,element) => {
const data = $(element).find("div.biab_group-markets-table-row");

data.each((_, element_1) => {
const teamNames = $(element_1).find("div > div.biab_market-title-team-names");
const clubA = $(teamNames).find("p:nth-child(1)").text().trim();
const clubB = $(teamNames).find("p:nth-child(2)").text().trim();

const numBets = Number($(element_1).find("div > span.cursor-help").text().trim());

const oddsWrapper = $(element_1).find("div.styles_betContent__wrapper__25jEo");
const odds = $(oddsWrapper).find("div.styles_contents__Kf8LQ > button > span > div > span.styles_betOdds__bxapE");
const oddsArray: any[] = [];
odds.each((_, element_2) => {
oddsArray.push($(element_2).text().trim());
});

gameEvents.push({
clubA,
clubB,
numBets,
oddsArray
});
});
});

const validationAdded = gameEvents.map(event => {
let valid = true;
//@ts-ignore
event.oddsArray.forEach(potentialOdd => {
if (potentialOdd === "") {
valid = false;
}
});
return {...event, ...{valid: valid}};
});

// Remove game vents without 6 complete odds
const filteredEvents = _.filter(validationAdded, {valid: true});

let finalMapping = filteredEvents.map(event => {
//@ts-ignore
const oddsToNumber = event.oddsArray.map(item => {
return Number(item);
})
return {...event, ...{oddsArray: oddsToNumber}};
});

finalMapping = finalMapping.filter(event => {
return event.numBets > 9;
});

logger.trace(finalMapping);

return {result: "success", value: finalMapping};
} catch(e: any) {
logger.error("An error occurred while parsing Orbit three way html data: ", e.message);
return {result: "error", value: new Error(e.message)};
}
}
3 changes: 1 addition & 2 deletions src/core/scrapping/orbit/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,12 @@ export class OrbitScrapper extends BaseScrapper {
PuppeteerPageLoadPolicy.LOAD,
".biab_body.contentWrap", // scrollingElementSelector
2000, // delayBeforeNextScrollAttemptMillis
30, // numScrollAttempts
60, // numScrollAttempts
150 // scrollDelta
);

if (getHtmlResult.result === "success") {
logger.info("Successfully fetched html for url. ", metadata);
logger.info(getHtmlResult.value.html);
this.publishRawHtmlToRedis(
getRedisPublisherResult.value,
getRedisHtmlParserChannelName(this.betProvider, game),
Expand Down
6 changes: 3 additions & 3 deletions src/testbed/testbed_2.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BetikaParser } from "../core/parsers/betika";
import { OrbitParser } from "../core/parsers/orbit";

const betikaParser = new BetikaParser()
betikaParser.subscribeToChannels();
const parser = new OrbitParser()
parser.subscribeToChannels();

0 comments on commit d606703

Please sign in to comment.