Sessions 29-30: Content templates + PropLine 3-key adapter + MLB Stats API + ESPN summary (1694 tests)
This commit is contained in:
+42
-4
@@ -28,6 +28,22 @@
|
||||
|
||||
const PROVIDERS = {
|
||||
// === ODDS / LINES ===
|
||||
// Session 30 — PropLine is now PRIMARY for player props. 3 free keys
|
||||
// rotate for 3,000 req/day combined (vs odds-api's 500/MONTH), and its
|
||||
// response shape is The-Odds-API-compatible. The proplineAdapter handles
|
||||
// which physical key to use; the gateway counts total propline calls
|
||||
// against the 3,000/day cap here. odds-api drops to priority 2 (backup
|
||||
// we conserve). Configured when at least key 1 is present.
|
||||
'propline': {
|
||||
name: 'PropLine',
|
||||
envKey: 'PROPLINE_API_KEY_1',
|
||||
quotaType: 'daily',
|
||||
quotaLimit: 3000,
|
||||
resetDay: null,
|
||||
sports: ['nba', 'wnba', 'mlb', 'nfl', 'nhl'],
|
||||
capabilities: ['odds', 'props', 'lines', 'spreads'],
|
||||
priority: 1,
|
||||
},
|
||||
'odds-api': {
|
||||
name: 'The Odds API',
|
||||
envKey: 'ODDS_API_KEY',
|
||||
@@ -36,7 +52,7 @@ const PROVIDERS = {
|
||||
resetDay: 1,
|
||||
sports: ['nba', 'wnba', 'mlb', 'soccer_wc', 'nfl', 'nhl'],
|
||||
capabilities: ['odds', 'props', 'lines', 'spreads'],
|
||||
priority: 1,
|
||||
priority: 2,
|
||||
},
|
||||
// Session 21 — correction. ODDSPAPI is NOT a live-props fallback
|
||||
// for the-odds-api. It serves Pinnacle CLOSING lines, captured at
|
||||
@@ -90,6 +106,21 @@ const PROVIDERS = {
|
||||
capabilities: ['box_scores', 'schedules', 'player_stats', 'bvp'],
|
||||
priority: 1,
|
||||
},
|
||||
// Session 30 — official MLB data. FREE, no auth, unlimited. The
|
||||
// mlbStatsAdapter does NOT route through the gateway (no quota to
|
||||
// track); this entry is informational + surfaces it on the admin
|
||||
// dashboard. `noAuth` marks it always-configured (no env key gate).
|
||||
'mlb-stats': {
|
||||
name: 'MLB Stats API',
|
||||
envKey: null,
|
||||
noAuth: true,
|
||||
quotaType: 'unlimited',
|
||||
quotaLimit: null,
|
||||
resetDay: null,
|
||||
sports: ['mlb'],
|
||||
capabilities: ['game_logs', 'season_averages', 'splits', 'probable_pitchers', 'bvp'],
|
||||
priority: 1,
|
||||
},
|
||||
|
||||
// === SOCCER ===
|
||||
'api-football': {
|
||||
@@ -136,9 +167,16 @@ function listProviderIds() {
|
||||
* by the admin dashboard to render only providers the operator has
|
||||
* actually wired up.
|
||||
*/
|
||||
// A provider counts as configured when its key is present OR it needs no
|
||||
// auth at all (e.g. MLB Stats API). Dead providers are always excluded.
|
||||
function isProviderConfigured(cfg) {
|
||||
if (!cfg || cfg.status === 'dead') return false;
|
||||
return cfg.noAuth === true || !!(cfg.envKey && process.env[cfg.envKey]);
|
||||
}
|
||||
|
||||
function getConfiguredProviders() {
|
||||
return Object.entries(PROVIDERS)
|
||||
.filter(([, cfg]) => !!process.env[cfg.envKey] && cfg.status !== 'dead')
|
||||
.filter(([, cfg]) => isProviderConfigured(cfg))
|
||||
.map(([id, cfg]) => ({ id, ...cfg }));
|
||||
}
|
||||
|
||||
@@ -156,10 +194,9 @@ function getFallbackChain(capability, sport, excludeId) {
|
||||
return Object.entries(PROVIDERS)
|
||||
.filter(([id, cfg]) =>
|
||||
id !== excludeId &&
|
||||
cfg.status !== 'dead' && // Session 23 — skip retired providers
|
||||
cfg.capabilities.includes(capability) &&
|
||||
(!sport || cfg.sports.includes(sport)) &&
|
||||
!!process.env[cfg.envKey],
|
||||
isProviderConfigured(cfg), // excludes dead + unconfigured, includes noAuth
|
||||
)
|
||||
.sort((a, b) => a[1].priority - b[1].priority)
|
||||
.map(([id]) => id);
|
||||
@@ -173,4 +210,5 @@ module.exports = {
|
||||
getConfiguredProviders,
|
||||
getFallbackChain,
|
||||
isDeadProvider,
|
||||
isProviderConfigured,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user