Codex commited on
Commit ·
af8ceca
1
Parent(s): bf291c4
Expand home run odds book coverage
Browse files- src/commands.js +1 -5
- src/embeds.js +1 -1
- src/market-scanner.js +1 -1
- test/market-scanner.test.js +89 -0
src/commands.js
CHANGED
|
@@ -508,11 +508,7 @@ export const commands = [
|
|
| 508 |
.setName('book')
|
| 509 |
.setDescription('Optionally limit the result to one book. Defaults to all books including Circa.')
|
| 510 |
.setRequired(false)
|
| 511 |
-
.addChoices(
|
| 512 |
-
{ name: 'Circa', value: 'Circa' },
|
| 513 |
-
{ name: 'BetMGM', value: 'BetMGM' },
|
| 514 |
-
{ name: 'Caesars', value: 'Caesars' }
|
| 515 |
-
)
|
| 516 |
),
|
| 517 |
new SlashCommandBuilder()
|
| 518 |
.setName('hitodds')
|
|
|
|
| 508 |
.setName('book')
|
| 509 |
.setDescription('Optionally limit the result to one book. Defaults to all books including Circa.')
|
| 510 |
.setRequired(false)
|
| 511 |
+
.addChoices(...SPORTSBOOK_BOOK_CHOICES)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 512 |
),
|
| 513 |
new SlashCommandBuilder()
|
| 514 |
.setName('hitodds')
|
src/embeds.js
CHANGED
|
@@ -312,7 +312,7 @@ export function buildCommandsEmbed() {
|
|
| 312 |
{ name: '/scanrun', value: 'Run the market scanner manually. Admin only.' },
|
| 313 |
{ name: '/scanreport', value: 'Post the morning scan reports immediately. Admin only.' },
|
| 314 |
{ name: 'Sharp Market Commands', value: '`/edgeboard`, `/playeredge`, `/marketedge`, `/widthboard`, `/consensusvs`, `/steam`, `/sharpboard`, `/bookscoreboard`, `/markethealth` cover sportsbook comparisons. `/dfsedgeboard`, `/dfsplayeredge`, `/dfsmarketedge`, `/dfswidthboard`, `/dfsconsensusvs` and `/exchangeedgeboard`, `/exchangeplayeredge`, `/exchangemarketedge`, `/exchangewidthboard`, `/exchangeconsensusvs` mirror those views for DFS and exchange lanes.' },
|
| 315 |
-
{ name: '/hrodds', value: 'Show live Home Run odds for one player across Caesars,
|
| 316 |
{ name: 'Other Odds Commands', value: '`/hitodds`, `/tbodds`, `/rbiodds`, `/runodds`, `/sbodds`, `/kodds` stay sportsbook-only. `/dfsodds` and `/exchangeodds` show direct prices inside the DFS or exchange lane.' },
|
| 317 |
{ name: '/circatest', value: 'Run a Circa OCR diagnostic preview. Admin only.' },
|
| 318 |
{ name: 'Circa Market Commands', value: '`/circamarket`, `/circahr`, `/circahits`, `/circatb`, `/circarbis`, `/circaruns`, `/circasb`, `/circahrri`, `/circak` post the latest parsed Circa markets in the channel where you run them.' },
|
|
|
|
| 312 |
{ name: '/scanrun', value: 'Run the market scanner manually. Admin only.' },
|
| 313 |
{ name: '/scanreport', value: 'Post the morning scan reports immediately. Admin only.' },
|
| 314 |
{ name: 'Sharp Market Commands', value: '`/edgeboard`, `/playeredge`, `/marketedge`, `/widthboard`, `/consensusvs`, `/steam`, `/sharpboard`, `/bookscoreboard`, `/markethealth` cover sportsbook comparisons. `/dfsedgeboard`, `/dfsplayeredge`, `/dfsmarketedge`, `/dfswidthboard`, `/dfsconsensusvs` and `/exchangeedgeboard`, `/exchangeplayeredge`, `/exchangemarketedge`, `/exchangewidthboard`, `/exchangeconsensusvs` mirror those views for DFS and exchange lanes.' },
|
| 315 |
+
{ name: '/hrodds', value: 'Show live Home Run odds for one player across the supported sportsbook books, including Circa, FanDuel, DraftKings, Caesars, Fanatics, Bally Bet, Hard Rock Bet, and BetMGM when available.' },
|
| 316 |
{ name: 'Other Odds Commands', value: '`/hitodds`, `/tbodds`, `/rbiodds`, `/runodds`, `/sbodds`, `/kodds` stay sportsbook-only. `/dfsodds` and `/exchangeodds` show direct prices inside the DFS or exchange lane.' },
|
| 317 |
{ name: '/circatest', value: 'Run a Circa OCR diagnostic preview. Admin only.' },
|
| 318 |
{ name: 'Circa Market Commands', value: '`/circamarket`, `/circahr`, `/circahits`, `/circatb`, `/circarbis`, `/circaruns`, `/circasb`, `/circahrri`, `/circak` post the latest parsed Circa markets in the channel where you run them.' },
|
src/market-scanner.js
CHANGED
|
@@ -3424,7 +3424,7 @@ const DIRECT_ODDS_MARKET_CONFIG = {
|
|
| 3424 |
circaMarketType: 'home_runs',
|
| 3425 |
preferredSide: 'yes',
|
| 3426 |
preferredLine: 0.5,
|
| 3427 |
-
allowedBooks: ['
|
| 3428 |
},
|
| 3429 |
batter_hits: {
|
| 3430 |
marketLabel: 'Hits',
|
|
|
|
| 3424 |
circaMarketType: 'home_runs',
|
| 3425 |
preferredSide: 'yes',
|
| 3426 |
preferredLine: 0.5,
|
| 3427 |
+
allowedBooks: ['Circa', 'FanDuel', 'DraftKings', 'BetMGM', 'Caesars', 'Fanatics', 'Bally Bet', 'Hard Rock Bet'],
|
| 3428 |
},
|
| 3429 |
batter_hits: {
|
| 3430 |
marketLabel: 'Hits',
|
test/market-scanner.test.js
CHANGED
|
@@ -1345,6 +1345,95 @@ test('dfs player odds lookup stays inside the dfs lane', async () => {
|
|
| 1345 |
}
|
| 1346 |
});
|
| 1347 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1348 |
test('direct player odds lookups reuse cached Odds API entries within the ttl window', async () => {
|
| 1349 |
const scanner = new MarketScanner({
|
| 1350 |
client: {},
|
|
|
|
| 1345 |
}
|
| 1346 |
});
|
| 1347 |
|
| 1348 |
+
test('home run odds lookup accepts expanded sportsbook books', async () => {
|
| 1349 |
+
const scanner = new MarketScanner({
|
| 1350 |
+
client: {},
|
| 1351 |
+
store: {
|
| 1352 |
+
getLatestCircaSnapshot: async () => null,
|
| 1353 |
+
},
|
| 1354 |
+
embeds: {},
|
| 1355 |
+
config: {
|
| 1356 |
+
enabled: true,
|
| 1357 |
+
oddsWorkflowEnabled: true,
|
| 1358 |
+
circaWorkflowEnabled: false,
|
| 1359 |
+
oddsApiBaseUrl: 'https://api.the-odds-api.com/v4',
|
| 1360 |
+
oddsApiSportKey: 'baseball_mlb',
|
| 1361 |
+
oddsApiKey: 'test-key',
|
| 1362 |
+
oddsApiRegions: 'us,us2',
|
| 1363 |
+
oddsApiBookmakers: ['fanduel', 'hardrockbet'],
|
| 1364 |
+
oddsApiMarkets: ['batter_home_runs'],
|
| 1365 |
+
scanHttpTimeoutMs: 15000,
|
| 1366 |
+
},
|
| 1367 |
+
});
|
| 1368 |
+
|
| 1369 |
+
const originalFetch = global.fetch;
|
| 1370 |
+
global.fetch = async (input) => {
|
| 1371 |
+
const asString = String(input);
|
| 1372 |
+
|
| 1373 |
+
if (asString.includes('/events?')) {
|
| 1374 |
+
return {
|
| 1375 |
+
ok: true,
|
| 1376 |
+
status: 200,
|
| 1377 |
+
headers: new Headers(),
|
| 1378 |
+
json: async () => [{ id: 'event-1', away_team: 'Dodgers', home_team: 'Cubs' }],
|
| 1379 |
+
};
|
| 1380 |
+
}
|
| 1381 |
+
|
| 1382 |
+
if (asString.includes('/events/event-1/odds')) {
|
| 1383 |
+
return {
|
| 1384 |
+
ok: true,
|
| 1385 |
+
status: 200,
|
| 1386 |
+
headers: new Headers(),
|
| 1387 |
+
json: async () => ({
|
| 1388 |
+
id: 'event-1',
|
| 1389 |
+
away_team: 'Dodgers',
|
| 1390 |
+
home_team: 'Cubs',
|
| 1391 |
+
bookmakers: [
|
| 1392 |
+
{
|
| 1393 |
+
key: 'fanduel',
|
| 1394 |
+
title: 'FanDuel',
|
| 1395 |
+
markets: [
|
| 1396 |
+
{
|
| 1397 |
+
key: 'batter_home_runs',
|
| 1398 |
+
outcomes: [
|
| 1399 |
+
{ name: 'Yes', description: 'Shohei Ohtani', price: 350 },
|
| 1400 |
+
],
|
| 1401 |
+
},
|
| 1402 |
+
],
|
| 1403 |
+
},
|
| 1404 |
+
{
|
| 1405 |
+
key: 'hardrockbet',
|
| 1406 |
+
title: 'Hard Rock Bet',
|
| 1407 |
+
markets: [
|
| 1408 |
+
{
|
| 1409 |
+
key: 'batter_home_runs',
|
| 1410 |
+
outcomes: [
|
| 1411 |
+
{ name: 'Yes', description: 'Shohei Ohtani', price: 365 },
|
| 1412 |
+
],
|
| 1413 |
+
},
|
| 1414 |
+
],
|
| 1415 |
+
},
|
| 1416 |
+
],
|
| 1417 |
+
}),
|
| 1418 |
+
};
|
| 1419 |
+
}
|
| 1420 |
+
|
| 1421 |
+
throw new Error(`Unexpected fetch URL: ${asString}`);
|
| 1422 |
+
};
|
| 1423 |
+
|
| 1424 |
+
try {
|
| 1425 |
+
const result = await scanner.getPlayerMarketOdds('batter_home_runs', 'Shohei Ohtani', {
|
| 1426 |
+
book: 'FanDuel',
|
| 1427 |
+
});
|
| 1428 |
+
|
| 1429 |
+
assert.equal(result.entries.length, 1);
|
| 1430 |
+
assert.equal(result.entries[0].book, 'FanDuel');
|
| 1431 |
+
assert.equal(result.entries[0].oddsInput, '350');
|
| 1432 |
+
} finally {
|
| 1433 |
+
global.fetch = originalFetch;
|
| 1434 |
+
}
|
| 1435 |
+
});
|
| 1436 |
+
|
| 1437 |
test('direct player odds lookups reuse cached Odds API entries within the ttl window', async () => {
|
| 1438 |
const scanner = new MarketScanner({
|
| 1439 |
client: {},
|