@claudinho/cli 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +59 -7
  2. package/dist/index.js +1385 -399
  3. package/package.json +14 -13
package/dist/index.js CHANGED
@@ -3,173 +3,6 @@
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
5
 
6
- // src/config.ts
7
- var SUPPORTED_LANGS = ["en", "es", "pt", "fr"];
8
- function pickLang(explicit) {
9
- const candidates = [
10
- explicit,
11
- process.env.CLAUDINHO_LANG,
12
- process.env.LANG?.split(".")[0]?.split("_")[0]
13
- ];
14
- for (const c of candidates) {
15
- if (c && SUPPORTED_LANGS.includes(c)) {
16
- return c;
17
- }
18
- }
19
- return "en";
20
- }
21
- function pickColor(explicit) {
22
- if (explicit === false) return false;
23
- if (process.env.NO_COLOR) return false;
24
- if (!process.stdout.isTTY) return false;
25
- return true;
26
- }
27
- function isSupportedLang(s) {
28
- return SUPPORTED_LANGS.includes(s);
29
- }
30
- function resolveConfig(opts) {
31
- const langRequestedUnsupported = opts.lang && !isSupportedLang(opts.lang) ? opts.lang : void 0;
32
- return {
33
- lang: pickLang(opts.lang),
34
- tz: opts.tz ?? process.env.CLAUDINHO_TZ ?? void 0,
35
- json: opts.json ?? false,
36
- color: pickColor(opts.color),
37
- source: opts.source ?? process.env.CLAUDINHO_SOURCE ?? "espn",
38
- langRequestedUnsupported
39
- };
40
- }
41
-
42
- // src/i18n.ts
43
- var EN = {
44
- "today.title": "Today's matches",
45
- "today.on": "Matches",
46
- "today.none": "No matches scheduled for this date.",
47
- "live.title": "Live now",
48
- "live.none": "No matches in play right now.",
49
- "next.none": "No upcoming fixture found for {team}.",
50
- "next.label": "Next up for {team}",
51
- "next.in": "in {countdown}",
52
- "table.title": "Group {group}",
53
- "table.none": "No group found for {group}.",
54
- "match.none": "No match found with id {id}.",
55
- "status.scheduled": "scheduled",
56
- "status.live": "LIVE",
57
- "status.ht": "HT",
58
- "status.ft": "FT",
59
- "status.postponed": "postponed",
60
- "status.cancelled": "cancelled",
61
- "col.team": "Team",
62
- "col.p": "P",
63
- "col.w": "W",
64
- "col.d": "D",
65
- "col.l": "L",
66
- "col.gd": "GD",
67
- "col.pts": "Pts",
68
- "err.date": "Invalid date {date}. Use YYYY-MM-DD.",
69
- "warn.tz": "Unknown timezone {tz}; using system timezone.",
70
- "warn.lang": "Unsupported language {lang}; using English. (supported: en, es, pt, fr)",
71
- disclaimer: "Not affiliated with FIFA or Anthropic."
72
- };
73
- var ES = {
74
- "today.title": "Partidos de hoy",
75
- "today.on": "Partidos",
76
- "today.none": "No hay partidos para esta fecha.",
77
- "live.title": "En vivo",
78
- "live.none": "No hay partidos en juego ahora mismo.",
79
- "next.none": "No se encontr\xF3 pr\xF3ximo partido para {team}.",
80
- "next.label": "Pr\xF3ximo de {team}",
81
- "next.in": "en {countdown}",
82
- "table.title": "Grupo {group}",
83
- "table.none": "No se encontr\xF3 el grupo {group}.",
84
- "match.none": "No se encontr\xF3 partido con id {id}.",
85
- "status.scheduled": "programado",
86
- "status.live": "EN VIVO",
87
- "status.ht": "DESC",
88
- "status.ft": "FIN",
89
- "status.postponed": "aplazado",
90
- "status.cancelled": "cancelado",
91
- "col.team": "Equipo",
92
- "col.p": "PJ",
93
- "col.w": "G",
94
- "col.d": "E",
95
- "col.l": "P",
96
- "col.gd": "DG",
97
- "col.pts": "Pts",
98
- "err.date": "Fecha inv\xE1lida {date}. Usa AAAA-MM-DD.",
99
- "warn.tz": "Zona horaria desconocida {tz}; usando la del sistema.",
100
- "warn.lang": "Idioma no soportado {lang}; usando ingl\xE9s. (disponibles: en, es, pt, fr)",
101
- disclaimer: "No afiliado a FIFA ni Anthropic."
102
- };
103
- var PT = {
104
- "today.title": "Jogos de hoje",
105
- "today.on": "Jogos",
106
- "today.none": "Nenhum jogo para esta data.",
107
- "live.title": "Ao vivo",
108
- "live.none": "Nenhum jogo em andamento agora.",
109
- "next.none": "Nenhum pr\xF3ximo jogo encontrado para {team}.",
110
- "next.label": "Pr\xF3ximo de {team}",
111
- "next.in": "em {countdown}",
112
- "table.title": "Grupo {group}",
113
- "table.none": "Grupo {group} n\xE3o encontrado.",
114
- "match.none": "Nenhum jogo encontrado com id {id}.",
115
- "status.scheduled": "agendado",
116
- "status.live": "AO VIVO",
117
- "status.ht": "INT",
118
- "status.ft": "FIM",
119
- "status.postponed": "adiado",
120
- "status.cancelled": "cancelado",
121
- "col.team": "Sele\xE7\xE3o",
122
- "col.p": "J",
123
- "col.w": "V",
124
- "col.d": "E",
125
- "col.l": "D",
126
- "col.gd": "SG",
127
- "col.pts": "Pts",
128
- "err.date": "Data inv\xE1lida {date}. Use AAAA-MM-DD.",
129
- "warn.tz": "Fuso hor\xE1rio desconhecido {tz}; usando o do sistema.",
130
- "warn.lang": "Idioma n\xE3o suportado {lang}; usando ingl\xEAs. (dispon\xEDveis: en, es, pt, fr)",
131
- disclaimer: "N\xE3o afiliado \xE0 FIFA nem \xE0 Anthropic."
132
- };
133
- var FR = {
134
- "today.title": "Matchs d'aujourd'hui",
135
- "today.on": "Matchs",
136
- "today.none": "Aucun match pr\xE9vu pour cette date.",
137
- "live.title": "En direct",
138
- "live.none": "Aucun match en cours pour l'instant.",
139
- "next.none": "Aucun prochain match trouv\xE9 pour {team}.",
140
- "next.label": "Prochain match de {team}",
141
- "next.in": "dans {countdown}",
142
- "table.title": "Groupe {group}",
143
- "table.none": "Groupe {group} introuvable.",
144
- "match.none": "Aucun match trouv\xE9 avec id {id}.",
145
- "status.scheduled": "pr\xE9vu",
146
- "status.live": "DIRECT",
147
- "status.ht": "MT",
148
- "status.ft": "FIN",
149
- "status.postponed": "report\xE9",
150
- "status.cancelled": "annul\xE9",
151
- "col.team": "\xC9quipe",
152
- "col.p": "J",
153
- "col.w": "G",
154
- "col.d": "N",
155
- "col.l": "P",
156
- "col.gd": "Diff",
157
- "col.pts": "Pts",
158
- "err.date": "Date invalide {date}. Utilisez AAAA-MM-JJ.",
159
- "warn.tz": "Fuseau horaire inconnu {tz} ; utilisation du fuseau syst\xE8me.",
160
- "warn.lang": "Langue non prise en charge {lang} ; utilisation de l\u2019anglais. (disponibles : en, es, pt, fr)",
161
- disclaimer: "Non affili\xE9 \xE0 la FIFA ni \xE0 Anthropic."
162
- };
163
- var CATALOGS = { en: EN, es: ES, pt: PT, fr: FR };
164
- function makeT(lang) {
165
- const dict = CATALOGS[lang] ?? EN;
166
- return (key, vars) => {
167
- let s = dict[key] ?? EN[key] ?? key;
168
- if (vars) for (const [k, v] of Object.entries(vars)) s = s.replace(`{${k}}`, v);
169
- return s;
170
- };
171
- }
172
-
173
6
  // ../core/dist/index.js
174
7
  var REGIONAL_INDICATOR_A = 127462;
175
8
  var TAG_BASE = 917504;
@@ -458,9 +291,18 @@ function resolveTz(explicit) {
458
291
  if (fromEnv && isValidTimeZone(fromEnv)) return fromEnv;
459
292
  return systemTz();
460
293
  }
294
+ function safeLocale(locale) {
295
+ if (!locale) return "en";
296
+ try {
297
+ Intl.getCanonicalLocales(locale);
298
+ return locale;
299
+ } catch {
300
+ return "en";
301
+ }
302
+ }
461
303
  function formatKickoff(iso, opts = {}) {
462
304
  const tz = resolveTz(opts.tz);
463
- const locale = opts.locale || "en";
305
+ const locale = safeLocale(opts.locale);
464
306
  return new Intl.DateTimeFormat(locale, {
465
307
  weekday: "short",
466
308
  hour: "2-digit",
@@ -499,9 +341,80 @@ function scoreline(match) {
499
341
  if (!match.score) return "vs";
500
342
  return `${match.score.home}\u2013${match.score.away}`;
501
343
  }
344
+ function matchLocation(match) {
345
+ return [match.venue, match.city, match.country].filter(Boolean).join(", ");
346
+ }
502
347
  function byKickoff(a, b) {
503
348
  return a.kickoff.localeCompare(b.kickoff);
504
349
  }
350
+ var FLAVOR_LEVELS = ["off", "subtle", "full"];
351
+ var DEFAULT_FLAVOR = "full";
352
+ function isFlavorLevel(s) {
353
+ return FLAVOR_LEVELS.includes(s);
354
+ }
355
+ function asFlavorLevel(s) {
356
+ return s && isFlavorLevel(s) ? s : DEFAULT_FLAVOR;
357
+ }
358
+ var BANKS = {
359
+ en: {
360
+ scheduled: ["the big one is coming!", "mark your calendar!", "football is in the air!"],
361
+ live: ["the tension is electric!", "eyes glued to the pitch!", "anything can happen!"],
362
+ goal: ["GOOOAL!", "what a strike!", "the stadium erupts!", "they buried it!"],
363
+ ft: ["the final whistle blows!", "it's all over!", "into the history books!"]
364
+ },
365
+ es: {
366
+ scheduled: ["\xA1se viene el partidazo!", "\xA1huele a f\xFAtbol!", "\xA1a cancha llena!"],
367
+ live: ["\xA1est\xE1 que arde!", "\xA1vibra el estadio!", "\xA1no despeguen los ojos!"],
368
+ goal: ["\xA1GOOOOL!", "\xA1qu\xE9 golazo!", "\xA1para callar bocas!", "\xA1se cae el estadio!"],
369
+ ft: ["\xA1suena el silbatazo final!", "\xA1se acab\xF3, se\xF1ores!", "\xA1a los libros de historia!"]
370
+ },
371
+ pt: {
372
+ scheduled: ["vem jog\xE3o por a\xED!", "cheira a futebol!", "est\xE1dio lotado!"],
373
+ live: ["est\xE1 pegando fogo!", "o est\xE1dio ferve!", "n\xE3o tire os olhos!"],
374
+ goal: ["GOOOL!", "que gola\xE7o!", "pra calar a boca!", "o est\xE1dio explode!"],
375
+ ft: ["apita o juiz, acabou!", "fim de jogo, senhores!", "pros livros de hist\xF3ria!"]
376
+ },
377
+ fr: {
378
+ scheduled: ["\xE7a promet, le grand match arrive !", "\xE7a sent le football !", "stade plein !"],
379
+ live: ["c'est bouillant !", "le stade vibre !", "ne quittez pas des yeux !"],
380
+ goal: ["BUUUT !", "quelle frappe !", "le stade explose !", "imparable !"],
381
+ ft: ["coup de sifflet final !", "c'est termin\xE9 !", "dans les livres d'histoire !"]
382
+ }
383
+ };
384
+ var LEVEL_MOMENTS = {
385
+ off: /* @__PURE__ */ new Set(),
386
+ subtle: /* @__PURE__ */ new Set(["goal", "ft"]),
387
+ full: /* @__PURE__ */ new Set(["scheduled", "live", "goal", "ft"])
388
+ };
389
+ function pick(id, bank) {
390
+ let h = 0;
391
+ for (let i = 0; i < id.length; i++) h = h * 31 + id.charCodeAt(i) >>> 0;
392
+ return bank.length ? bank[h % bank.length] : "";
393
+ }
394
+ function momentOf(m) {
395
+ switch (m.status) {
396
+ case "LIVE":
397
+ case "HT": {
398
+ const goals = (m.score?.home ?? 0) + (m.score?.away ?? 0);
399
+ return goals > 0 ? "goal" : "live";
400
+ }
401
+ case "FT":
402
+ return "ft";
403
+ case "SCHEDULED":
404
+ return "scheduled";
405
+ default:
406
+ return void 0;
407
+ }
408
+ }
409
+ function matchFlavor(m, opts = {}) {
410
+ const level = opts.level ?? DEFAULT_FLAVOR;
411
+ if (level === "off") return "";
412
+ const moment = momentOf(m);
413
+ if (!moment || !LEVEL_MOMENTS[level].has(moment)) return "";
414
+ const lang = (opts.locale ?? "en").slice(0, 2);
415
+ const langBank = BANKS[lang] ?? BANKS.en;
416
+ return langBank ? pick(m.id, langBank[moment]) : "";
417
+ }
505
418
  var schedule_2026_default = [
506
419
  {
507
420
  id: "760415",
@@ -509,6 +422,8 @@ var schedule_2026_default = [
509
422
  group: "A",
510
423
  kickoff: "2026-06-11T19:00Z",
511
424
  venue: "Estadio Banorte",
425
+ city: "Mexico City",
426
+ country: "Mexico",
512
427
  home: {
513
428
  code: "MEX",
514
429
  name: "Mexico",
@@ -520,7 +435,7 @@ var schedule_2026_default = [
520
435
  flag: "\u{1F1FF}\u{1F1E6}"
521
436
  },
522
437
  status: "SCHEDULED",
523
- updatedAt: "2026-05-31T08:32:53.559Z"
438
+ updatedAt: "2026-06-07T07:52:54.333Z"
524
439
  },
525
440
  {
526
441
  id: "760414",
@@ -528,6 +443,8 @@ var schedule_2026_default = [
528
443
  group: "A",
529
444
  kickoff: "2026-06-12T02:00Z",
530
445
  venue: "Estadio Akron",
446
+ city: "Guadalajara",
447
+ country: "Mexico",
531
448
  home: {
532
449
  code: "KOR",
533
450
  name: "South Korea",
@@ -539,7 +456,7 @@ var schedule_2026_default = [
539
456
  flag: "\u{1F1E8}\u{1F1FF}"
540
457
  },
541
458
  status: "SCHEDULED",
542
- updatedAt: "2026-05-31T08:32:53.560Z"
459
+ updatedAt: "2026-06-07T07:52:54.337Z"
543
460
  },
544
461
  {
545
462
  id: "760416",
@@ -547,6 +464,8 @@ var schedule_2026_default = [
547
464
  group: "B",
548
465
  kickoff: "2026-06-12T19:00Z",
549
466
  venue: "BMO Field",
467
+ city: "Toronto",
468
+ country: "Canada",
550
469
  home: {
551
470
  code: "CAN",
552
471
  name: "Canada",
@@ -558,7 +477,7 @@ var schedule_2026_default = [
558
477
  flag: "\u{1F1E7}\u{1F1E6}"
559
478
  },
560
479
  status: "SCHEDULED",
561
- updatedAt: "2026-05-31T08:32:53.560Z"
480
+ updatedAt: "2026-06-07T07:52:54.337Z"
562
481
  },
563
482
  {
564
483
  id: "760417",
@@ -566,6 +485,8 @@ var schedule_2026_default = [
566
485
  group: "D",
567
486
  kickoff: "2026-06-13T01:00Z",
568
487
  venue: "SoFi Stadium",
488
+ city: "Inglewood, California",
489
+ country: "USA",
569
490
  home: {
570
491
  code: "USA",
571
492
  name: "United States",
@@ -577,7 +498,7 @@ var schedule_2026_default = [
577
498
  flag: "\u{1F1F5}\u{1F1FE}"
578
499
  },
579
500
  status: "SCHEDULED",
580
- updatedAt: "2026-05-31T08:32:53.560Z"
501
+ updatedAt: "2026-06-07T07:52:54.337Z"
581
502
  },
582
503
  {
583
504
  id: "760420",
@@ -585,6 +506,8 @@ var schedule_2026_default = [
585
506
  group: "B",
586
507
  kickoff: "2026-06-13T19:00Z",
587
508
  venue: "Levi's Stadium",
509
+ city: "Santa Clara, California",
510
+ country: "USA",
588
511
  home: {
589
512
  code: "QAT",
590
513
  name: "Qatar",
@@ -596,7 +519,7 @@ var schedule_2026_default = [
596
519
  flag: "\u{1F1E8}\u{1F1ED}"
597
520
  },
598
521
  status: "SCHEDULED",
599
- updatedAt: "2026-05-31T08:32:53.560Z"
522
+ updatedAt: "2026-06-07T07:52:54.337Z"
600
523
  },
601
524
  {
602
525
  id: "760419",
@@ -604,6 +527,8 @@ var schedule_2026_default = [
604
527
  group: "C",
605
528
  kickoff: "2026-06-13T22:00Z",
606
529
  venue: "MetLife Stadium",
530
+ city: "East Rutherford, New Jersey",
531
+ country: "USA",
607
532
  home: {
608
533
  code: "BRA",
609
534
  name: "Brazil",
@@ -615,7 +540,7 @@ var schedule_2026_default = [
615
540
  flag: "\u{1F1F2}\u{1F1E6}"
616
541
  },
617
542
  status: "SCHEDULED",
618
- updatedAt: "2026-05-31T08:32:53.560Z"
543
+ updatedAt: "2026-06-07T07:52:54.337Z"
619
544
  },
620
545
  {
621
546
  id: "760418",
@@ -623,6 +548,8 @@ var schedule_2026_default = [
623
548
  group: "C",
624
549
  kickoff: "2026-06-14T01:00Z",
625
550
  venue: "Gillette Stadium",
551
+ city: "Foxborough, Massachusetts",
552
+ country: "USA",
626
553
  home: {
627
554
  code: "HAI",
628
555
  name: "Haiti",
@@ -634,7 +561,7 @@ var schedule_2026_default = [
634
561
  flag: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}"
635
562
  },
636
563
  status: "SCHEDULED",
637
- updatedAt: "2026-05-31T08:32:53.560Z"
564
+ updatedAt: "2026-06-07T07:52:54.337Z"
638
565
  },
639
566
  {
640
567
  id: "760421",
@@ -642,6 +569,8 @@ var schedule_2026_default = [
642
569
  group: "D",
643
570
  kickoff: "2026-06-14T04:00Z",
644
571
  venue: "BC Place",
572
+ city: "Vancouver",
573
+ country: "Canada",
645
574
  home: {
646
575
  code: "AUS",
647
576
  name: "Australia",
@@ -653,7 +582,7 @@ var schedule_2026_default = [
653
582
  flag: "\u{1F1F9}\u{1F1F7}"
654
583
  },
655
584
  status: "SCHEDULED",
656
- updatedAt: "2026-05-31T08:32:53.560Z"
585
+ updatedAt: "2026-06-07T07:52:54.337Z"
657
586
  },
658
587
  {
659
588
  id: "760422",
@@ -661,6 +590,8 @@ var schedule_2026_default = [
661
590
  group: "E",
662
591
  kickoff: "2026-06-14T17:00Z",
663
592
  venue: "NRG Stadium",
593
+ city: "Houston, Texas",
594
+ country: "USA",
664
595
  home: {
665
596
  code: "GER",
666
597
  name: "Germany",
@@ -668,11 +599,11 @@ var schedule_2026_default = [
668
599
  },
669
600
  away: {
670
601
  code: "CUW",
671
- name: "Curacao",
602
+ name: "Cura\xE7ao",
672
603
  flag: "\u{1F1E8}\u{1F1FC}"
673
604
  },
674
605
  status: "SCHEDULED",
675
- updatedAt: "2026-05-31T08:32:53.560Z"
606
+ updatedAt: "2026-06-07T07:52:54.337Z"
676
607
  },
677
608
  {
678
609
  id: "760425",
@@ -680,6 +611,8 @@ var schedule_2026_default = [
680
611
  group: "F",
681
612
  kickoff: "2026-06-14T20:00Z",
682
613
  venue: "AT&T Stadium",
614
+ city: "Arlington, Texas",
615
+ country: "USA",
683
616
  home: {
684
617
  code: "NED",
685
618
  name: "Netherlands",
@@ -691,7 +624,7 @@ var schedule_2026_default = [
691
624
  flag: "\u{1F1EF}\u{1F1F5}"
692
625
  },
693
626
  status: "SCHEDULED",
694
- updatedAt: "2026-05-31T08:32:53.560Z"
627
+ updatedAt: "2026-06-07T07:52:54.337Z"
695
628
  },
696
629
  {
697
630
  id: "760423",
@@ -699,6 +632,8 @@ var schedule_2026_default = [
699
632
  group: "E",
700
633
  kickoff: "2026-06-14T23:00Z",
701
634
  venue: "Lincoln Financial Field",
635
+ city: "Philadelphia, Pennsylvania",
636
+ country: "USA",
702
637
  home: {
703
638
  code: "CIV",
704
639
  name: "Ivory Coast",
@@ -710,7 +645,7 @@ var schedule_2026_default = [
710
645
  flag: "\u{1F1EA}\u{1F1E8}"
711
646
  },
712
647
  status: "SCHEDULED",
713
- updatedAt: "2026-05-31T08:32:53.560Z"
648
+ updatedAt: "2026-06-07T07:52:54.337Z"
714
649
  },
715
650
  {
716
651
  id: "760424",
@@ -718,6 +653,8 @@ var schedule_2026_default = [
718
653
  group: "F",
719
654
  kickoff: "2026-06-15T02:00Z",
720
655
  venue: "Estadio BBVA",
656
+ city: "Guadalupe",
657
+ country: "Mexico",
721
658
  home: {
722
659
  code: "SWE",
723
660
  name: "Sweden",
@@ -729,7 +666,7 @@ var schedule_2026_default = [
729
666
  flag: "\u{1F1F9}\u{1F1F3}"
730
667
  },
731
668
  status: "SCHEDULED",
732
- updatedAt: "2026-05-31T08:32:53.560Z"
669
+ updatedAt: "2026-06-07T07:52:54.337Z"
733
670
  },
734
671
  {
735
672
  id: "760428",
@@ -737,6 +674,8 @@ var schedule_2026_default = [
737
674
  group: "H",
738
675
  kickoff: "2026-06-15T16:00Z",
739
676
  venue: "Mercedes-Benz Stadium",
677
+ city: "Atlanta, Georgia",
678
+ country: "USA",
740
679
  home: {
741
680
  code: "ESP",
742
681
  name: "Spain",
@@ -748,7 +687,7 @@ var schedule_2026_default = [
748
687
  flag: "\u{1F1E8}\u{1F1FB}"
749
688
  },
750
689
  status: "SCHEDULED",
751
- updatedAt: "2026-05-31T08:32:53.560Z"
690
+ updatedAt: "2026-06-07T07:52:54.337Z"
752
691
  },
753
692
  {
754
693
  id: "760426",
@@ -756,6 +695,8 @@ var schedule_2026_default = [
756
695
  group: "G",
757
696
  kickoff: "2026-06-15T19:00Z",
758
697
  venue: "Lumen Field",
698
+ city: "Seattle, Washington",
699
+ country: "USA",
759
700
  home: {
760
701
  code: "BEL",
761
702
  name: "Belgium",
@@ -767,7 +708,7 @@ var schedule_2026_default = [
767
708
  flag: "\u{1F1EA}\u{1F1EC}"
768
709
  },
769
710
  status: "SCHEDULED",
770
- updatedAt: "2026-05-31T08:32:53.560Z"
711
+ updatedAt: "2026-06-07T07:52:54.337Z"
771
712
  },
772
713
  {
773
714
  id: "760429",
@@ -775,6 +716,8 @@ var schedule_2026_default = [
775
716
  group: "H",
776
717
  kickoff: "2026-06-15T22:00Z",
777
718
  venue: "Hard Rock Stadium",
719
+ city: "Miami Gardens, Florida",
720
+ country: "USA",
778
721
  home: {
779
722
  code: "KSA",
780
723
  name: "Saudi Arabia",
@@ -786,7 +729,7 @@ var schedule_2026_default = [
786
729
  flag: "\u{1F1FA}\u{1F1FE}"
787
730
  },
788
731
  status: "SCHEDULED",
789
- updatedAt: "2026-05-31T08:32:53.560Z"
732
+ updatedAt: "2026-06-07T07:52:54.337Z"
790
733
  },
791
734
  {
792
735
  id: "760427",
@@ -794,6 +737,8 @@ var schedule_2026_default = [
794
737
  group: "G",
795
738
  kickoff: "2026-06-16T01:00Z",
796
739
  venue: "SoFi Stadium",
740
+ city: "Inglewood, California",
741
+ country: "USA",
797
742
  home: {
798
743
  code: "IRN",
799
744
  name: "Iran",
@@ -805,7 +750,7 @@ var schedule_2026_default = [
805
750
  flag: "\u{1F1F3}\u{1F1FF}"
806
751
  },
807
752
  status: "SCHEDULED",
808
- updatedAt: "2026-05-31T08:32:53.560Z"
753
+ updatedAt: "2026-06-07T07:52:54.337Z"
809
754
  },
810
755
  {
811
756
  id: "760432",
@@ -813,6 +758,8 @@ var schedule_2026_default = [
813
758
  group: "I",
814
759
  kickoff: "2026-06-16T19:00Z",
815
760
  venue: "MetLife Stadium",
761
+ city: "East Rutherford, New Jersey",
762
+ country: "USA",
816
763
  home: {
817
764
  code: "FRA",
818
765
  name: "France",
@@ -824,7 +771,7 @@ var schedule_2026_default = [
824
771
  flag: "\u{1F1F8}\u{1F1F3}"
825
772
  },
826
773
  status: "SCHEDULED",
827
- updatedAt: "2026-05-31T08:32:53.560Z"
774
+ updatedAt: "2026-06-07T07:52:54.337Z"
828
775
  },
829
776
  {
830
777
  id: "760430",
@@ -832,6 +779,8 @@ var schedule_2026_default = [
832
779
  group: "I",
833
780
  kickoff: "2026-06-16T22:00Z",
834
781
  venue: "Gillette Stadium",
782
+ city: "Foxborough, Massachusetts",
783
+ country: "USA",
835
784
  home: {
836
785
  code: "IRQ",
837
786
  name: "Iraq",
@@ -843,7 +792,7 @@ var schedule_2026_default = [
843
792
  flag: "\u{1F1F3}\u{1F1F4}"
844
793
  },
845
794
  status: "SCHEDULED",
846
- updatedAt: "2026-05-31T08:32:53.560Z"
795
+ updatedAt: "2026-06-07T07:52:54.337Z"
847
796
  },
848
797
  {
849
798
  id: "760433",
@@ -851,6 +800,8 @@ var schedule_2026_default = [
851
800
  group: "J",
852
801
  kickoff: "2026-06-17T01:00Z",
853
802
  venue: "GEHA Field at Arrowhead Stadium",
803
+ city: "Kansas City, Missouri",
804
+ country: "USA",
854
805
  home: {
855
806
  code: "ARG",
856
807
  name: "Argentina",
@@ -862,7 +813,7 @@ var schedule_2026_default = [
862
813
  flag: "\u{1F1E9}\u{1F1FF}"
863
814
  },
864
815
  status: "SCHEDULED",
865
- updatedAt: "2026-05-31T08:32:53.560Z"
816
+ updatedAt: "2026-06-07T07:52:54.337Z"
866
817
  },
867
818
  {
868
819
  id: "760431",
@@ -870,6 +821,8 @@ var schedule_2026_default = [
870
821
  group: "J",
871
822
  kickoff: "2026-06-17T04:00Z",
872
823
  venue: "Levi's Stadium",
824
+ city: "Santa Clara, California",
825
+ country: "USA",
873
826
  home: {
874
827
  code: "AUT",
875
828
  name: "Austria",
@@ -881,7 +834,7 @@ var schedule_2026_default = [
881
834
  flag: "\u{1F1EF}\u{1F1F4}"
882
835
  },
883
836
  status: "SCHEDULED",
884
- updatedAt: "2026-05-31T08:32:53.560Z"
837
+ updatedAt: "2026-06-07T07:52:54.337Z"
885
838
  },
886
839
  {
887
840
  id: "760435",
@@ -889,6 +842,8 @@ var schedule_2026_default = [
889
842
  group: "K",
890
843
  kickoff: "2026-06-17T17:00Z",
891
844
  venue: "NRG Stadium",
845
+ city: "Houston, Texas",
846
+ country: "USA",
892
847
  home: {
893
848
  code: "POR",
894
849
  name: "Portugal",
@@ -900,7 +855,7 @@ var schedule_2026_default = [
900
855
  flag: "\u{1F1E8}\u{1F1E9}"
901
856
  },
902
857
  status: "SCHEDULED",
903
- updatedAt: "2026-05-31T08:32:53.560Z"
858
+ updatedAt: "2026-06-07T07:52:54.337Z"
904
859
  },
905
860
  {
906
861
  id: "760437",
@@ -908,6 +863,8 @@ var schedule_2026_default = [
908
863
  group: "L",
909
864
  kickoff: "2026-06-17T20:00Z",
910
865
  venue: "AT&T Stadium",
866
+ city: "Arlington, Texas",
867
+ country: "USA",
911
868
  home: {
912
869
  code: "ENG",
913
870
  name: "England",
@@ -919,7 +876,7 @@ var schedule_2026_default = [
919
876
  flag: "\u{1F1ED}\u{1F1F7}"
920
877
  },
921
878
  status: "SCHEDULED",
922
- updatedAt: "2026-05-31T08:32:53.560Z"
879
+ updatedAt: "2026-06-07T07:52:54.337Z"
923
880
  },
924
881
  {
925
882
  id: "760434",
@@ -927,6 +884,8 @@ var schedule_2026_default = [
927
884
  group: "L",
928
885
  kickoff: "2026-06-17T23:00Z",
929
886
  venue: "BMO Field",
887
+ city: "Toronto",
888
+ country: "Canada",
930
889
  home: {
931
890
  code: "GHA",
932
891
  name: "Ghana",
@@ -938,7 +897,7 @@ var schedule_2026_default = [
938
897
  flag: "\u{1F1F5}\u{1F1E6}"
939
898
  },
940
899
  status: "SCHEDULED",
941
- updatedAt: "2026-05-31T08:32:53.560Z"
900
+ updatedAt: "2026-06-07T07:52:54.337Z"
942
901
  },
943
902
  {
944
903
  id: "760436",
@@ -946,6 +905,8 @@ var schedule_2026_default = [
946
905
  group: "K",
947
906
  kickoff: "2026-06-18T02:00Z",
948
907
  venue: "Estadio Banorte",
908
+ city: "Mexico City",
909
+ country: "Mexico",
949
910
  home: {
950
911
  code: "UZB",
951
912
  name: "Uzbekistan",
@@ -957,7 +918,7 @@ var schedule_2026_default = [
957
918
  flag: "\u{1F1E8}\u{1F1F4}"
958
919
  },
959
920
  status: "SCHEDULED",
960
- updatedAt: "2026-05-31T08:32:53.560Z"
921
+ updatedAt: "2026-06-07T07:52:54.337Z"
961
922
  },
962
923
  {
963
924
  id: "760438",
@@ -965,6 +926,8 @@ var schedule_2026_default = [
965
926
  group: "A",
966
927
  kickoff: "2026-06-18T16:00Z",
967
928
  venue: "Mercedes-Benz Stadium",
929
+ city: "Atlanta, Georgia",
930
+ country: "USA",
968
931
  home: {
969
932
  code: "CZE",
970
933
  name: "Czechia",
@@ -976,7 +939,7 @@ var schedule_2026_default = [
976
939
  flag: "\u{1F1FF}\u{1F1E6}"
977
940
  },
978
941
  status: "SCHEDULED",
979
- updatedAt: "2026-05-31T08:32:53.624Z"
942
+ updatedAt: "2026-06-07T07:52:54.418Z"
980
943
  },
981
944
  {
982
945
  id: "760439",
@@ -984,6 +947,8 @@ var schedule_2026_default = [
984
947
  group: "B",
985
948
  kickoff: "2026-06-18T19:00Z",
986
949
  venue: "SoFi Stadium",
950
+ city: "Inglewood, California",
951
+ country: "USA",
987
952
  home: {
988
953
  code: "SUI",
989
954
  name: "Switzerland",
@@ -995,7 +960,7 @@ var schedule_2026_default = [
995
960
  flag: "\u{1F1E7}\u{1F1E6}"
996
961
  },
997
962
  status: "SCHEDULED",
998
- updatedAt: "2026-05-31T08:32:53.624Z"
963
+ updatedAt: "2026-06-07T07:52:54.418Z"
999
964
  },
1000
965
  {
1001
966
  id: "760440",
@@ -1003,6 +968,8 @@ var schedule_2026_default = [
1003
968
  group: "B",
1004
969
  kickoff: "2026-06-18T22:00Z",
1005
970
  venue: "BC Place",
971
+ city: "Vancouver",
972
+ country: "Canada",
1006
973
  home: {
1007
974
  code: "CAN",
1008
975
  name: "Canada",
@@ -1014,7 +981,7 @@ var schedule_2026_default = [
1014
981
  flag: "\u{1F1F6}\u{1F1E6}"
1015
982
  },
1016
983
  status: "SCHEDULED",
1017
- updatedAt: "2026-05-31T08:32:53.624Z"
984
+ updatedAt: "2026-06-07T07:52:54.418Z"
1018
985
  },
1019
986
  {
1020
987
  id: "760441",
@@ -1022,6 +989,8 @@ var schedule_2026_default = [
1022
989
  group: "A",
1023
990
  kickoff: "2026-06-19T01:00Z",
1024
991
  venue: "Estadio Akron",
992
+ city: "Guadalajara",
993
+ country: "Mexico",
1025
994
  home: {
1026
995
  code: "MEX",
1027
996
  name: "Mexico",
@@ -1033,7 +1002,7 @@ var schedule_2026_default = [
1033
1002
  flag: "\u{1F1F0}\u{1F1F7}"
1034
1003
  },
1035
1004
  status: "SCHEDULED",
1036
- updatedAt: "2026-05-31T08:32:53.624Z"
1005
+ updatedAt: "2026-06-07T07:52:54.418Z"
1037
1006
  },
1038
1007
  {
1039
1008
  id: "760442",
@@ -1041,6 +1010,8 @@ var schedule_2026_default = [
1041
1010
  group: "D",
1042
1011
  kickoff: "2026-06-19T19:00Z",
1043
1012
  venue: "Lumen Field",
1013
+ city: "Seattle, Washington",
1014
+ country: "USA",
1044
1015
  home: {
1045
1016
  code: "USA",
1046
1017
  name: "United States",
@@ -1052,7 +1023,7 @@ var schedule_2026_default = [
1052
1023
  flag: "\u{1F1E6}\u{1F1FA}"
1053
1024
  },
1054
1025
  status: "SCHEDULED",
1055
- updatedAt: "2026-05-31T08:32:53.624Z"
1026
+ updatedAt: "2026-06-07T07:52:54.418Z"
1056
1027
  },
1057
1028
  {
1058
1029
  id: "760445",
@@ -1060,6 +1031,8 @@ var schedule_2026_default = [
1060
1031
  group: "C",
1061
1032
  kickoff: "2026-06-19T22:00Z",
1062
1033
  venue: "Gillette Stadium",
1034
+ city: "Foxborough, Massachusetts",
1035
+ country: "USA",
1063
1036
  home: {
1064
1037
  code: "SCO",
1065
1038
  name: "Scotland",
@@ -1071,7 +1044,7 @@ var schedule_2026_default = [
1071
1044
  flag: "\u{1F1F2}\u{1F1E6}"
1072
1045
  },
1073
1046
  status: "SCHEDULED",
1074
- updatedAt: "2026-05-31T08:32:53.624Z"
1047
+ updatedAt: "2026-06-07T07:52:54.418Z"
1075
1048
  },
1076
1049
  {
1077
1050
  id: "760444",
@@ -1079,6 +1052,8 @@ var schedule_2026_default = [
1079
1052
  group: "C",
1080
1053
  kickoff: "2026-06-20T00:30Z",
1081
1054
  venue: "Lincoln Financial Field",
1055
+ city: "Philadelphia, Pennsylvania",
1056
+ country: "USA",
1082
1057
  home: {
1083
1058
  code: "BRA",
1084
1059
  name: "Brazil",
@@ -1090,7 +1065,7 @@ var schedule_2026_default = [
1090
1065
  flag: "\u{1F1ED}\u{1F1F9}"
1091
1066
  },
1092
1067
  status: "SCHEDULED",
1093
- updatedAt: "2026-05-31T08:32:53.624Z"
1068
+ updatedAt: "2026-06-07T07:52:54.418Z"
1094
1069
  },
1095
1070
  {
1096
1071
  id: "760443",
@@ -1098,6 +1073,8 @@ var schedule_2026_default = [
1098
1073
  group: "D",
1099
1074
  kickoff: "2026-06-20T03:00Z",
1100
1075
  venue: "Levi's Stadium",
1076
+ city: "Santa Clara, California",
1077
+ country: "USA",
1101
1078
  home: {
1102
1079
  code: "TUR",
1103
1080
  name: "T\xFCrkiye",
@@ -1109,7 +1086,7 @@ var schedule_2026_default = [
1109
1086
  flag: "\u{1F1F5}\u{1F1FE}"
1110
1087
  },
1111
1088
  status: "SCHEDULED",
1112
- updatedAt: "2026-05-31T08:32:53.624Z"
1089
+ updatedAt: "2026-06-07T07:52:54.418Z"
1113
1090
  },
1114
1091
  {
1115
1092
  id: "760447",
@@ -1117,6 +1094,8 @@ var schedule_2026_default = [
1117
1094
  group: "F",
1118
1095
  kickoff: "2026-06-20T17:00Z",
1119
1096
  venue: "NRG Stadium",
1097
+ city: "Houston, Texas",
1098
+ country: "USA",
1120
1099
  home: {
1121
1100
  code: "NED",
1122
1101
  name: "Netherlands",
@@ -1128,7 +1107,7 @@ var schedule_2026_default = [
1128
1107
  flag: "\u{1F1F8}\u{1F1EA}"
1129
1108
  },
1130
1109
  status: "SCHEDULED",
1131
- updatedAt: "2026-05-31T08:32:53.624Z"
1110
+ updatedAt: "2026-06-07T07:52:54.418Z"
1132
1111
  },
1133
1112
  {
1134
1113
  id: "760448",
@@ -1136,6 +1115,8 @@ var schedule_2026_default = [
1136
1115
  group: "E",
1137
1116
  kickoff: "2026-06-20T20:00Z",
1138
1117
  venue: "BMO Field",
1118
+ city: "Toronto",
1119
+ country: "Canada",
1139
1120
  home: {
1140
1121
  code: "GER",
1141
1122
  name: "Germany",
@@ -1147,7 +1128,7 @@ var schedule_2026_default = [
1147
1128
  flag: "\u{1F1E8}\u{1F1EE}"
1148
1129
  },
1149
1130
  status: "SCHEDULED",
1150
- updatedAt: "2026-05-31T08:32:53.624Z"
1131
+ updatedAt: "2026-06-07T07:52:54.418Z"
1151
1132
  },
1152
1133
  {
1153
1134
  id: "760446",
@@ -1155,6 +1136,8 @@ var schedule_2026_default = [
1155
1136
  group: "E",
1156
1137
  kickoff: "2026-06-21T00:00Z",
1157
1138
  venue: "GEHA Field at Arrowhead Stadium",
1139
+ city: "Kansas City, Missouri",
1140
+ country: "USA",
1158
1141
  home: {
1159
1142
  code: "ECU",
1160
1143
  name: "Ecuador",
@@ -1162,11 +1145,11 @@ var schedule_2026_default = [
1162
1145
  },
1163
1146
  away: {
1164
1147
  code: "CUW",
1165
- name: "Curacao",
1148
+ name: "Cura\xE7ao",
1166
1149
  flag: "\u{1F1E8}\u{1F1FC}"
1167
1150
  },
1168
1151
  status: "SCHEDULED",
1169
- updatedAt: "2026-05-31T08:32:53.624Z"
1152
+ updatedAt: "2026-06-07T07:52:54.418Z"
1170
1153
  },
1171
1154
  {
1172
1155
  id: "760449",
@@ -1174,6 +1157,8 @@ var schedule_2026_default = [
1174
1157
  group: "F",
1175
1158
  kickoff: "2026-06-21T04:00Z",
1176
1159
  venue: "Estadio BBVA",
1160
+ city: "Guadalupe",
1161
+ country: "Mexico",
1177
1162
  home: {
1178
1163
  code: "TUN",
1179
1164
  name: "Tunisia",
@@ -1185,7 +1170,7 @@ var schedule_2026_default = [
1185
1170
  flag: "\u{1F1EF}\u{1F1F5}"
1186
1171
  },
1187
1172
  status: "SCHEDULED",
1188
- updatedAt: "2026-05-31T08:32:53.624Z"
1173
+ updatedAt: "2026-06-07T07:52:54.418Z"
1189
1174
  },
1190
1175
  {
1191
1176
  id: "760453",
@@ -1193,6 +1178,8 @@ var schedule_2026_default = [
1193
1178
  group: "H",
1194
1179
  kickoff: "2026-06-21T16:00Z",
1195
1180
  venue: "Mercedes-Benz Stadium",
1181
+ city: "Atlanta, Georgia",
1182
+ country: "USA",
1196
1183
  home: {
1197
1184
  code: "ESP",
1198
1185
  name: "Spain",
@@ -1204,7 +1191,7 @@ var schedule_2026_default = [
1204
1191
  flag: "\u{1F1F8}\u{1F1E6}"
1205
1192
  },
1206
1193
  status: "SCHEDULED",
1207
- updatedAt: "2026-05-31T08:32:53.624Z"
1194
+ updatedAt: "2026-06-07T07:52:54.418Z"
1208
1195
  },
1209
1196
  {
1210
1197
  id: "760451",
@@ -1212,6 +1199,8 @@ var schedule_2026_default = [
1212
1199
  group: "G",
1213
1200
  kickoff: "2026-06-21T19:00Z",
1214
1201
  venue: "SoFi Stadium",
1202
+ city: "Inglewood, California",
1203
+ country: "USA",
1215
1204
  home: {
1216
1205
  code: "BEL",
1217
1206
  name: "Belgium",
@@ -1223,7 +1212,7 @@ var schedule_2026_default = [
1223
1212
  flag: "\u{1F1EE}\u{1F1F7}"
1224
1213
  },
1225
1214
  status: "SCHEDULED",
1226
- updatedAt: "2026-05-31T08:32:53.624Z"
1215
+ updatedAt: "2026-06-07T07:52:54.418Z"
1227
1216
  },
1228
1217
  {
1229
1218
  id: "760450",
@@ -1231,6 +1220,8 @@ var schedule_2026_default = [
1231
1220
  group: "H",
1232
1221
  kickoff: "2026-06-21T22:00Z",
1233
1222
  venue: "Hard Rock Stadium",
1223
+ city: "Miami Gardens, Florida",
1224
+ country: "USA",
1234
1225
  home: {
1235
1226
  code: "URU",
1236
1227
  name: "Uruguay",
@@ -1242,7 +1233,7 @@ var schedule_2026_default = [
1242
1233
  flag: "\u{1F1E8}\u{1F1FB}"
1243
1234
  },
1244
1235
  status: "SCHEDULED",
1245
- updatedAt: "2026-05-31T08:32:53.624Z"
1236
+ updatedAt: "2026-06-07T07:52:54.418Z"
1246
1237
  },
1247
1238
  {
1248
1239
  id: "760452",
@@ -1250,6 +1241,8 @@ var schedule_2026_default = [
1250
1241
  group: "G",
1251
1242
  kickoff: "2026-06-22T01:00Z",
1252
1243
  venue: "BC Place",
1244
+ city: "Vancouver",
1245
+ country: "Canada",
1253
1246
  home: {
1254
1247
  code: "NZL",
1255
1248
  name: "New Zealand",
@@ -1261,7 +1254,7 @@ var schedule_2026_default = [
1261
1254
  flag: "\u{1F1EA}\u{1F1EC}"
1262
1255
  },
1263
1256
  status: "SCHEDULED",
1264
- updatedAt: "2026-05-31T08:32:53.624Z"
1257
+ updatedAt: "2026-06-07T07:52:54.418Z"
1265
1258
  },
1266
1259
  {
1267
1260
  id: "760456",
@@ -1269,6 +1262,8 @@ var schedule_2026_default = [
1269
1262
  group: "J",
1270
1263
  kickoff: "2026-06-22T17:00Z",
1271
1264
  venue: "AT&T Stadium",
1265
+ city: "Arlington, Texas",
1266
+ country: "USA",
1272
1267
  home: {
1273
1268
  code: "ARG",
1274
1269
  name: "Argentina",
@@ -1280,7 +1275,7 @@ var schedule_2026_default = [
1280
1275
  flag: "\u{1F1E6}\u{1F1F9}"
1281
1276
  },
1282
1277
  status: "SCHEDULED",
1283
- updatedAt: "2026-05-31T08:32:53.624Z"
1278
+ updatedAt: "2026-06-07T07:52:54.418Z"
1284
1279
  },
1285
1280
  {
1286
1281
  id: "760457",
@@ -1288,6 +1283,8 @@ var schedule_2026_default = [
1288
1283
  group: "I",
1289
1284
  kickoff: "2026-06-22T21:00Z",
1290
1285
  venue: "Lincoln Financial Field",
1286
+ city: "Philadelphia, Pennsylvania",
1287
+ country: "USA",
1291
1288
  home: {
1292
1289
  code: "FRA",
1293
1290
  name: "France",
@@ -1299,7 +1296,7 @@ var schedule_2026_default = [
1299
1296
  flag: "\u{1F1EE}\u{1F1F6}"
1300
1297
  },
1301
1298
  status: "SCHEDULED",
1302
- updatedAt: "2026-05-31T08:32:53.624Z"
1299
+ updatedAt: "2026-06-07T07:52:54.418Z"
1303
1300
  },
1304
1301
  {
1305
1302
  id: "760454",
@@ -1307,6 +1304,8 @@ var schedule_2026_default = [
1307
1304
  group: "I",
1308
1305
  kickoff: "2026-06-23T00:00Z",
1309
1306
  venue: "MetLife Stadium",
1307
+ city: "East Rutherford, New Jersey",
1308
+ country: "USA",
1310
1309
  home: {
1311
1310
  code: "NOR",
1312
1311
  name: "Norway",
@@ -1318,7 +1317,7 @@ var schedule_2026_default = [
1318
1317
  flag: "\u{1F1F8}\u{1F1F3}"
1319
1318
  },
1320
1319
  status: "SCHEDULED",
1321
- updatedAt: "2026-05-31T08:32:53.624Z"
1320
+ updatedAt: "2026-06-07T07:52:54.418Z"
1322
1321
  },
1323
1322
  {
1324
1323
  id: "760455",
@@ -1326,6 +1325,8 @@ var schedule_2026_default = [
1326
1325
  group: "J",
1327
1326
  kickoff: "2026-06-23T03:00Z",
1328
1327
  venue: "Levi's Stadium",
1328
+ city: "Santa Clara, California",
1329
+ country: "USA",
1329
1330
  home: {
1330
1331
  code: "JOR",
1331
1332
  name: "Jordan",
@@ -1337,7 +1338,7 @@ var schedule_2026_default = [
1337
1338
  flag: "\u{1F1E9}\u{1F1FF}"
1338
1339
  },
1339
1340
  status: "SCHEDULED",
1340
- updatedAt: "2026-05-31T08:32:53.624Z"
1341
+ updatedAt: "2026-06-07T07:52:54.418Z"
1341
1342
  },
1342
1343
  {
1343
1344
  id: "760461",
@@ -1345,6 +1346,8 @@ var schedule_2026_default = [
1345
1346
  group: "K",
1346
1347
  kickoff: "2026-06-23T17:00Z",
1347
1348
  venue: "NRG Stadium",
1349
+ city: "Houston, Texas",
1350
+ country: "USA",
1348
1351
  home: {
1349
1352
  code: "POR",
1350
1353
  name: "Portugal",
@@ -1356,7 +1359,7 @@ var schedule_2026_default = [
1356
1359
  flag: "\u{1F1FA}\u{1F1FF}"
1357
1360
  },
1358
1361
  status: "SCHEDULED",
1359
- updatedAt: "2026-05-31T08:32:53.624Z"
1362
+ updatedAt: "2026-06-07T07:52:54.418Z"
1360
1363
  },
1361
1364
  {
1362
1365
  id: "760458",
@@ -1364,6 +1367,8 @@ var schedule_2026_default = [
1364
1367
  group: "L",
1365
1368
  kickoff: "2026-06-23T20:00Z",
1366
1369
  venue: "Gillette Stadium",
1370
+ city: "Foxborough, Massachusetts",
1371
+ country: "USA",
1367
1372
  home: {
1368
1373
  code: "ENG",
1369
1374
  name: "England",
@@ -1375,7 +1380,7 @@ var schedule_2026_default = [
1375
1380
  flag: "\u{1F1EC}\u{1F1ED}"
1376
1381
  },
1377
1382
  status: "SCHEDULED",
1378
- updatedAt: "2026-05-31T08:32:53.624Z"
1383
+ updatedAt: "2026-06-07T07:52:54.418Z"
1379
1384
  },
1380
1385
  {
1381
1386
  id: "760460",
@@ -1383,6 +1388,8 @@ var schedule_2026_default = [
1383
1388
  group: "L",
1384
1389
  kickoff: "2026-06-23T23:00Z",
1385
1390
  venue: "BMO Field",
1391
+ city: "Toronto",
1392
+ country: "Canada",
1386
1393
  home: {
1387
1394
  code: "PAN",
1388
1395
  name: "Panama",
@@ -1394,7 +1401,7 @@ var schedule_2026_default = [
1394
1401
  flag: "\u{1F1ED}\u{1F1F7}"
1395
1402
  },
1396
1403
  status: "SCHEDULED",
1397
- updatedAt: "2026-05-31T08:32:53.625Z"
1404
+ updatedAt: "2026-06-07T07:52:54.419Z"
1398
1405
  },
1399
1406
  {
1400
1407
  id: "760459",
@@ -1402,6 +1409,8 @@ var schedule_2026_default = [
1402
1409
  group: "K",
1403
1410
  kickoff: "2026-06-24T02:00Z",
1404
1411
  venue: "Estadio Akron",
1412
+ city: "Guadalajara",
1413
+ country: "Mexico",
1405
1414
  home: {
1406
1415
  code: "COL",
1407
1416
  name: "Colombia",
@@ -1413,7 +1422,7 @@ var schedule_2026_default = [
1413
1422
  flag: "\u{1F1E8}\u{1F1E9}"
1414
1423
  },
1415
1424
  status: "SCHEDULED",
1416
- updatedAt: "2026-05-31T08:32:53.625Z"
1425
+ updatedAt: "2026-06-07T07:52:54.419Z"
1417
1426
  },
1418
1427
  {
1419
1428
  id: "760462",
@@ -1421,6 +1430,8 @@ var schedule_2026_default = [
1421
1430
  group: "B",
1422
1431
  kickoff: "2026-06-24T19:00Z",
1423
1432
  venue: "Lumen Field",
1433
+ city: "Seattle, Washington",
1434
+ country: "USA",
1424
1435
  home: {
1425
1436
  code: "BIH",
1426
1437
  name: "Bosnia-Herzegovina",
@@ -1432,7 +1443,7 @@ var schedule_2026_default = [
1432
1443
  flag: "\u{1F1F6}\u{1F1E6}"
1433
1444
  },
1434
1445
  status: "SCHEDULED",
1435
- updatedAt: "2026-05-31T08:32:53.625Z"
1446
+ updatedAt: "2026-06-07T07:52:54.419Z"
1436
1447
  },
1437
1448
  {
1438
1449
  id: "760463",
@@ -1440,6 +1451,8 @@ var schedule_2026_default = [
1440
1451
  group: "B",
1441
1452
  kickoff: "2026-06-24T19:00Z",
1442
1453
  venue: "BC Place",
1454
+ city: "Vancouver",
1455
+ country: "Canada",
1443
1456
  home: {
1444
1457
  code: "SUI",
1445
1458
  name: "Switzerland",
@@ -1451,7 +1464,7 @@ var schedule_2026_default = [
1451
1464
  flag: "\u{1F1E8}\u{1F1E6}"
1452
1465
  },
1453
1466
  status: "SCHEDULED",
1454
- updatedAt: "2026-05-31T08:32:53.625Z"
1467
+ updatedAt: "2026-06-07T07:52:54.419Z"
1455
1468
  },
1456
1469
  {
1457
1470
  id: "760464",
@@ -1459,6 +1472,8 @@ var schedule_2026_default = [
1459
1472
  group: "C",
1460
1473
  kickoff: "2026-06-24T22:00Z",
1461
1474
  venue: "Mercedes-Benz Stadium",
1475
+ city: "Atlanta, Georgia",
1476
+ country: "USA",
1462
1477
  home: {
1463
1478
  code: "MAR",
1464
1479
  name: "Morocco",
@@ -1470,7 +1485,7 @@ var schedule_2026_default = [
1470
1485
  flag: "\u{1F1ED}\u{1F1F9}"
1471
1486
  },
1472
1487
  status: "SCHEDULED",
1473
- updatedAt: "2026-05-31T08:32:53.625Z"
1488
+ updatedAt: "2026-06-07T07:52:54.419Z"
1474
1489
  },
1475
1490
  {
1476
1491
  id: "760465",
@@ -1478,6 +1493,8 @@ var schedule_2026_default = [
1478
1493
  group: "C",
1479
1494
  kickoff: "2026-06-24T22:00Z",
1480
1495
  venue: "Hard Rock Stadium",
1496
+ city: "Miami Gardens, Florida",
1497
+ country: "USA",
1481
1498
  home: {
1482
1499
  code: "SCO",
1483
1500
  name: "Scotland",
@@ -1489,7 +1506,7 @@ var schedule_2026_default = [
1489
1506
  flag: "\u{1F1E7}\u{1F1F7}"
1490
1507
  },
1491
1508
  status: "SCHEDULED",
1492
- updatedAt: "2026-05-31T08:32:53.625Z"
1509
+ updatedAt: "2026-06-07T07:52:54.419Z"
1493
1510
  },
1494
1511
  {
1495
1512
  id: "760467",
@@ -1497,6 +1514,8 @@ var schedule_2026_default = [
1497
1514
  group: "A",
1498
1515
  kickoff: "2026-06-25T01:00Z",
1499
1516
  venue: "Estadio Banorte",
1517
+ city: "Mexico City",
1518
+ country: "Mexico",
1500
1519
  home: {
1501
1520
  code: "CZE",
1502
1521
  name: "Czechia",
@@ -1508,7 +1527,7 @@ var schedule_2026_default = [
1508
1527
  flag: "\u{1F1F2}\u{1F1FD}"
1509
1528
  },
1510
1529
  status: "SCHEDULED",
1511
- updatedAt: "2026-05-31T08:32:53.625Z"
1530
+ updatedAt: "2026-06-07T07:52:54.419Z"
1512
1531
  },
1513
1532
  {
1514
1533
  id: "760466",
@@ -1516,6 +1535,8 @@ var schedule_2026_default = [
1516
1535
  group: "A",
1517
1536
  kickoff: "2026-06-25T01:00Z",
1518
1537
  venue: "Estadio BBVA",
1538
+ city: "Guadalupe",
1539
+ country: "Mexico",
1519
1540
  home: {
1520
1541
  code: "RSA",
1521
1542
  name: "South Africa",
@@ -1527,7 +1548,7 @@ var schedule_2026_default = [
1527
1548
  flag: "\u{1F1F0}\u{1F1F7}"
1528
1549
  },
1529
1550
  status: "SCHEDULED",
1530
- updatedAt: "2026-05-31T08:32:53.625Z"
1551
+ updatedAt: "2026-06-07T07:52:54.419Z"
1531
1552
  },
1532
1553
  {
1533
1554
  id: "760473",
@@ -1535,9 +1556,11 @@ var schedule_2026_default = [
1535
1556
  group: "E",
1536
1557
  kickoff: "2026-06-25T20:00Z",
1537
1558
  venue: "Lincoln Financial Field",
1559
+ city: "Philadelphia, Pennsylvania",
1560
+ country: "USA",
1538
1561
  home: {
1539
1562
  code: "CUW",
1540
- name: "Curacao",
1563
+ name: "Cura\xE7ao",
1541
1564
  flag: "\u{1F1E8}\u{1F1FC}"
1542
1565
  },
1543
1566
  away: {
@@ -1546,7 +1569,7 @@ var schedule_2026_default = [
1546
1569
  flag: "\u{1F1E8}\u{1F1EE}"
1547
1570
  },
1548
1571
  status: "SCHEDULED",
1549
- updatedAt: "2026-05-31T08:32:53.682Z"
1572
+ updatedAt: "2026-06-07T07:52:54.511Z"
1550
1573
  },
1551
1574
  {
1552
1575
  id: "760468",
@@ -1554,6 +1577,8 @@ var schedule_2026_default = [
1554
1577
  group: "E",
1555
1578
  kickoff: "2026-06-25T20:00Z",
1556
1579
  venue: "MetLife Stadium",
1580
+ city: "East Rutherford, New Jersey",
1581
+ country: "USA",
1557
1582
  home: {
1558
1583
  code: "ECU",
1559
1584
  name: "Ecuador",
@@ -1565,7 +1590,7 @@ var schedule_2026_default = [
1565
1590
  flag: "\u{1F1E9}\u{1F1EA}"
1566
1591
  },
1567
1592
  status: "SCHEDULED",
1568
- updatedAt: "2026-05-31T08:32:53.682Z"
1593
+ updatedAt: "2026-06-07T07:52:54.511Z"
1569
1594
  },
1570
1595
  {
1571
1596
  id: "760471",
@@ -1573,6 +1598,8 @@ var schedule_2026_default = [
1573
1598
  group: "F",
1574
1599
  kickoff: "2026-06-25T23:00Z",
1575
1600
  venue: "AT&T Stadium",
1601
+ city: "Arlington, Texas",
1602
+ country: "USA",
1576
1603
  home: {
1577
1604
  code: "JPN",
1578
1605
  name: "Japan",
@@ -1584,7 +1611,7 @@ var schedule_2026_default = [
1584
1611
  flag: "\u{1F1F8}\u{1F1EA}"
1585
1612
  },
1586
1613
  status: "SCHEDULED",
1587
- updatedAt: "2026-05-31T08:32:53.682Z"
1614
+ updatedAt: "2026-06-07T07:52:54.511Z"
1588
1615
  },
1589
1616
  {
1590
1617
  id: "760472",
@@ -1592,6 +1619,8 @@ var schedule_2026_default = [
1592
1619
  group: "F",
1593
1620
  kickoff: "2026-06-25T23:00Z",
1594
1621
  venue: "GEHA Field at Arrowhead Stadium",
1622
+ city: "Kansas City, Missouri",
1623
+ country: "USA",
1595
1624
  home: {
1596
1625
  code: "TUN",
1597
1626
  name: "Tunisia",
@@ -1603,7 +1632,7 @@ var schedule_2026_default = [
1603
1632
  flag: "\u{1F1F3}\u{1F1F1}"
1604
1633
  },
1605
1634
  status: "SCHEDULED",
1606
- updatedAt: "2026-05-31T08:32:53.682Z"
1635
+ updatedAt: "2026-06-07T07:52:54.511Z"
1607
1636
  },
1608
1637
  {
1609
1638
  id: "760469",
@@ -1611,6 +1640,8 @@ var schedule_2026_default = [
1611
1640
  group: "D",
1612
1641
  kickoff: "2026-06-26T02:00Z",
1613
1642
  venue: "Levi's Stadium",
1643
+ city: "Santa Clara, California",
1644
+ country: "USA",
1614
1645
  home: {
1615
1646
  code: "PAR",
1616
1647
  name: "Paraguay",
@@ -1622,7 +1653,7 @@ var schedule_2026_default = [
1622
1653
  flag: "\u{1F1E6}\u{1F1FA}"
1623
1654
  },
1624
1655
  status: "SCHEDULED",
1625
- updatedAt: "2026-05-31T08:32:53.682Z"
1656
+ updatedAt: "2026-06-07T07:52:54.511Z"
1626
1657
  },
1627
1658
  {
1628
1659
  id: "760470",
@@ -1630,6 +1661,8 @@ var schedule_2026_default = [
1630
1661
  group: "D",
1631
1662
  kickoff: "2026-06-26T02:00Z",
1632
1663
  venue: "SoFi Stadium",
1664
+ city: "Inglewood, California",
1665
+ country: "USA",
1633
1666
  home: {
1634
1667
  code: "TUR",
1635
1668
  name: "T\xFCrkiye",
@@ -1641,7 +1674,7 @@ var schedule_2026_default = [
1641
1674
  flag: "\u{1F1FA}\u{1F1F8}"
1642
1675
  },
1643
1676
  status: "SCHEDULED",
1644
- updatedAt: "2026-05-31T08:32:53.682Z"
1677
+ updatedAt: "2026-06-07T07:52:54.511Z"
1645
1678
  },
1646
1679
  {
1647
1680
  id: "760475",
@@ -1649,6 +1682,8 @@ var schedule_2026_default = [
1649
1682
  group: "I",
1650
1683
  kickoff: "2026-06-26T19:00Z",
1651
1684
  venue: "Gillette Stadium",
1685
+ city: "Foxborough, Massachusetts",
1686
+ country: "USA",
1652
1687
  home: {
1653
1688
  code: "NOR",
1654
1689
  name: "Norway",
@@ -1660,7 +1695,7 @@ var schedule_2026_default = [
1660
1695
  flag: "\u{1F1EB}\u{1F1F7}"
1661
1696
  },
1662
1697
  status: "SCHEDULED",
1663
- updatedAt: "2026-05-31T08:32:53.682Z"
1698
+ updatedAt: "2026-06-07T07:52:54.511Z"
1664
1699
  },
1665
1700
  {
1666
1701
  id: "760474",
@@ -1668,6 +1703,8 @@ var schedule_2026_default = [
1668
1703
  group: "I",
1669
1704
  kickoff: "2026-06-26T19:00Z",
1670
1705
  venue: "BMO Field",
1706
+ city: "Toronto",
1707
+ country: "Canada",
1671
1708
  home: {
1672
1709
  code: "SEN",
1673
1710
  name: "Senegal",
@@ -1679,7 +1716,7 @@ var schedule_2026_default = [
1679
1716
  flag: "\u{1F1EE}\u{1F1F6}"
1680
1717
  },
1681
1718
  status: "SCHEDULED",
1682
- updatedAt: "2026-05-31T08:32:53.682Z"
1719
+ updatedAt: "2026-06-07T07:52:54.511Z"
1683
1720
  },
1684
1721
  {
1685
1722
  id: "760478",
@@ -1687,6 +1724,8 @@ var schedule_2026_default = [
1687
1724
  group: "H",
1688
1725
  kickoff: "2026-06-27T00:00Z",
1689
1726
  venue: "NRG Stadium",
1727
+ city: "Houston, Texas",
1728
+ country: "USA",
1690
1729
  home: {
1691
1730
  code: "CPV",
1692
1731
  name: "Cape Verde",
@@ -1698,7 +1737,7 @@ var schedule_2026_default = [
1698
1737
  flag: "\u{1F1F8}\u{1F1E6}"
1699
1738
  },
1700
1739
  status: "SCHEDULED",
1701
- updatedAt: "2026-05-31T08:32:53.682Z"
1740
+ updatedAt: "2026-06-07T07:52:54.511Z"
1702
1741
  },
1703
1742
  {
1704
1743
  id: "760479",
@@ -1706,6 +1745,8 @@ var schedule_2026_default = [
1706
1745
  group: "H",
1707
1746
  kickoff: "2026-06-27T00:00Z",
1708
1747
  venue: "Estadio Akron",
1748
+ city: "Guadalajara",
1749
+ country: "Mexico",
1709
1750
  home: {
1710
1751
  code: "URU",
1711
1752
  name: "Uruguay",
@@ -1717,7 +1758,7 @@ var schedule_2026_default = [
1717
1758
  flag: "\u{1F1EA}\u{1F1F8}"
1718
1759
  },
1719
1760
  status: "SCHEDULED",
1720
- updatedAt: "2026-05-31T08:32:53.682Z"
1761
+ updatedAt: "2026-06-07T07:52:54.511Z"
1721
1762
  },
1722
1763
  {
1723
1764
  id: "760476",
@@ -1725,6 +1766,8 @@ var schedule_2026_default = [
1725
1766
  group: "G",
1726
1767
  kickoff: "2026-06-27T03:00Z",
1727
1768
  venue: "Lumen Field",
1769
+ city: "Seattle, Washington",
1770
+ country: "USA",
1728
1771
  home: {
1729
1772
  code: "EGY",
1730
1773
  name: "Egypt",
@@ -1736,7 +1779,7 @@ var schedule_2026_default = [
1736
1779
  flag: "\u{1F1EE}\u{1F1F7}"
1737
1780
  },
1738
1781
  status: "SCHEDULED",
1739
- updatedAt: "2026-05-31T08:32:53.682Z"
1782
+ updatedAt: "2026-06-07T07:52:54.511Z"
1740
1783
  },
1741
1784
  {
1742
1785
  id: "760477",
@@ -1744,6 +1787,8 @@ var schedule_2026_default = [
1744
1787
  group: "G",
1745
1788
  kickoff: "2026-06-27T03:00Z",
1746
1789
  venue: "BC Place",
1790
+ city: "Vancouver",
1791
+ country: "Canada",
1747
1792
  home: {
1748
1793
  code: "NZL",
1749
1794
  name: "New Zealand",
@@ -1755,7 +1800,7 @@ var schedule_2026_default = [
1755
1800
  flag: "\u{1F1E7}\u{1F1EA}"
1756
1801
  },
1757
1802
  status: "SCHEDULED",
1758
- updatedAt: "2026-05-31T08:32:53.682Z"
1803
+ updatedAt: "2026-06-07T07:52:54.511Z"
1759
1804
  },
1760
1805
  {
1761
1806
  id: "760480",
@@ -1763,6 +1808,8 @@ var schedule_2026_default = [
1763
1808
  group: "L",
1764
1809
  kickoff: "2026-06-27T21:00Z",
1765
1810
  venue: "Lincoln Financial Field",
1811
+ city: "Philadelphia, Pennsylvania",
1812
+ country: "USA",
1766
1813
  home: {
1767
1814
  code: "CRO",
1768
1815
  name: "Croatia",
@@ -1774,7 +1821,7 @@ var schedule_2026_default = [
1774
1821
  flag: "\u{1F1EC}\u{1F1ED}"
1775
1822
  },
1776
1823
  status: "SCHEDULED",
1777
- updatedAt: "2026-05-31T08:32:53.682Z"
1824
+ updatedAt: "2026-06-07T07:52:54.512Z"
1778
1825
  },
1779
1826
  {
1780
1827
  id: "760485",
@@ -1782,6 +1829,8 @@ var schedule_2026_default = [
1782
1829
  group: "L",
1783
1830
  kickoff: "2026-06-27T21:00Z",
1784
1831
  venue: "MetLife Stadium",
1832
+ city: "East Rutherford, New Jersey",
1833
+ country: "USA",
1785
1834
  home: {
1786
1835
  code: "PAN",
1787
1836
  name: "Panama",
@@ -1793,7 +1842,7 @@ var schedule_2026_default = [
1793
1842
  flag: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}"
1794
1843
  },
1795
1844
  status: "SCHEDULED",
1796
- updatedAt: "2026-05-31T08:32:53.682Z"
1845
+ updatedAt: "2026-06-07T07:52:54.512Z"
1797
1846
  },
1798
1847
  {
1799
1848
  id: "760481",
@@ -1801,6 +1850,8 @@ var schedule_2026_default = [
1801
1850
  group: "K",
1802
1851
  kickoff: "2026-06-27T23:30Z",
1803
1852
  venue: "Hard Rock Stadium",
1853
+ city: "Miami Gardens, Florida",
1854
+ country: "USA",
1804
1855
  home: {
1805
1856
  code: "COL",
1806
1857
  name: "Colombia",
@@ -1812,7 +1863,7 @@ var schedule_2026_default = [
1812
1863
  flag: "\u{1F1F5}\u{1F1F9}"
1813
1864
  },
1814
1865
  status: "SCHEDULED",
1815
- updatedAt: "2026-05-31T08:32:53.682Z"
1866
+ updatedAt: "2026-06-07T07:52:54.512Z"
1816
1867
  },
1817
1868
  {
1818
1869
  id: "760482",
@@ -1820,6 +1871,8 @@ var schedule_2026_default = [
1820
1871
  group: "K",
1821
1872
  kickoff: "2026-06-27T23:30Z",
1822
1873
  venue: "Mercedes-Benz Stadium",
1874
+ city: "Atlanta, Georgia",
1875
+ country: "USA",
1823
1876
  home: {
1824
1877
  code: "COD",
1825
1878
  name: "Congo DR",
@@ -1831,7 +1884,7 @@ var schedule_2026_default = [
1831
1884
  flag: "\u{1F1FA}\u{1F1FF}"
1832
1885
  },
1833
1886
  status: "SCHEDULED",
1834
- updatedAt: "2026-05-31T08:32:53.682Z"
1887
+ updatedAt: "2026-06-07T07:52:54.512Z"
1835
1888
  },
1836
1889
  {
1837
1890
  id: "760484",
@@ -1839,6 +1892,8 @@ var schedule_2026_default = [
1839
1892
  group: "J",
1840
1893
  kickoff: "2026-06-28T02:00Z",
1841
1894
  venue: "GEHA Field at Arrowhead Stadium",
1895
+ city: "Kansas City, Missouri",
1896
+ country: "USA",
1842
1897
  home: {
1843
1898
  code: "ALG",
1844
1899
  name: "Algeria",
@@ -1850,7 +1905,7 @@ var schedule_2026_default = [
1850
1905
  flag: "\u{1F1E6}\u{1F1F9}"
1851
1906
  },
1852
1907
  status: "SCHEDULED",
1853
- updatedAt: "2026-05-31T08:32:53.682Z"
1908
+ updatedAt: "2026-06-07T07:52:54.512Z"
1854
1909
  },
1855
1910
  {
1856
1911
  id: "760483",
@@ -1858,6 +1913,8 @@ var schedule_2026_default = [
1858
1913
  group: "J",
1859
1914
  kickoff: "2026-06-28T02:00Z",
1860
1915
  venue: "AT&T Stadium",
1916
+ city: "Arlington, Texas",
1917
+ country: "USA",
1861
1918
  home: {
1862
1919
  code: "JOR",
1863
1920
  name: "Jordan",
@@ -1869,13 +1926,15 @@ var schedule_2026_default = [
1869
1926
  flag: "\u{1F1E6}\u{1F1F7}"
1870
1927
  },
1871
1928
  status: "SCHEDULED",
1872
- updatedAt: "2026-05-31T08:32:53.682Z"
1929
+ updatedAt: "2026-06-07T07:52:54.512Z"
1873
1930
  },
1874
1931
  {
1875
1932
  id: "760486",
1876
1933
  stage: "R32",
1877
1934
  kickoff: "2026-06-28T19:00Z",
1878
1935
  venue: "SoFi Stadium",
1936
+ city: "Inglewood, California",
1937
+ country: "USA",
1879
1938
  home: {
1880
1939
  code: "2A",
1881
1940
  name: "Group A 2nd Place",
@@ -1887,13 +1946,15 @@ var schedule_2026_default = [
1887
1946
  flag: "\u{1F3F3}\uFE0F"
1888
1947
  },
1889
1948
  status: "SCHEDULED",
1890
- updatedAt: "2026-05-31T08:32:53.682Z"
1949
+ updatedAt: "2026-06-07T07:52:54.540Z"
1891
1950
  },
1892
1951
  {
1893
1952
  id: "760487",
1894
1953
  stage: "R32",
1895
1954
  kickoff: "2026-06-29T17:00Z",
1896
1955
  venue: "NRG Stadium",
1956
+ city: "Houston, Texas",
1957
+ country: "USA",
1897
1958
  home: {
1898
1959
  code: "1C",
1899
1960
  name: "Group C Winner",
@@ -1905,13 +1966,15 @@ var schedule_2026_default = [
1905
1966
  flag: "\u{1F3F3}\uFE0F"
1906
1967
  },
1907
1968
  status: "SCHEDULED",
1908
- updatedAt: "2026-05-31T08:32:53.682Z"
1969
+ updatedAt: "2026-06-07T07:52:54.540Z"
1909
1970
  },
1910
1971
  {
1911
1972
  id: "760489",
1912
1973
  stage: "R32",
1913
1974
  kickoff: "2026-06-29T20:30Z",
1914
1975
  venue: "Gillette Stadium",
1976
+ city: "Foxborough, Massachusetts",
1977
+ country: "USA",
1915
1978
  home: {
1916
1979
  code: "1E",
1917
1980
  name: "Group E Winner",
@@ -1923,13 +1986,15 @@ var schedule_2026_default = [
1923
1986
  flag: "\u{1F3F3}\uFE0F"
1924
1987
  },
1925
1988
  status: "SCHEDULED",
1926
- updatedAt: "2026-05-31T08:32:53.682Z"
1989
+ updatedAt: "2026-06-07T07:52:54.540Z"
1927
1990
  },
1928
1991
  {
1929
1992
  id: "760488",
1930
1993
  stage: "R32",
1931
1994
  kickoff: "2026-06-30T01:00Z",
1932
1995
  venue: "Estadio BBVA",
1996
+ city: "Guadalupe",
1997
+ country: "Mexico",
1933
1998
  home: {
1934
1999
  code: "1F",
1935
2000
  name: "Group F Winner",
@@ -1941,13 +2006,15 @@ var schedule_2026_default = [
1941
2006
  flag: "\u{1F3F3}\uFE0F"
1942
2007
  },
1943
2008
  status: "SCHEDULED",
1944
- updatedAt: "2026-05-31T08:32:53.682Z"
2009
+ updatedAt: "2026-06-07T07:52:54.540Z"
1945
2010
  },
1946
2011
  {
1947
2012
  id: "760490",
1948
2013
  stage: "R32",
1949
2014
  kickoff: "2026-06-30T17:00Z",
1950
2015
  venue: "AT&T Stadium",
2016
+ city: "Arlington, Texas",
2017
+ country: "USA",
1951
2018
  home: {
1952
2019
  code: "2E",
1953
2020
  name: "Group E 2nd Place",
@@ -1959,13 +2026,15 @@ var schedule_2026_default = [
1959
2026
  flag: "\u{1F3F3}\uFE0F"
1960
2027
  },
1961
2028
  status: "SCHEDULED",
1962
- updatedAt: "2026-05-31T08:32:53.682Z"
2029
+ updatedAt: "2026-06-07T07:52:54.540Z"
1963
2030
  },
1964
2031
  {
1965
2032
  id: "760492",
1966
2033
  stage: "R32",
1967
2034
  kickoff: "2026-06-30T21:00Z",
1968
2035
  venue: "MetLife Stadium",
2036
+ city: "East Rutherford, New Jersey",
2037
+ country: "USA",
1969
2038
  home: {
1970
2039
  code: "1I",
1971
2040
  name: "Group I Winner",
@@ -1977,13 +2046,15 @@ var schedule_2026_default = [
1977
2046
  flag: "\u{1F3F3}\uFE0F"
1978
2047
  },
1979
2048
  status: "SCHEDULED",
1980
- updatedAt: "2026-05-31T08:32:53.682Z"
2049
+ updatedAt: "2026-06-07T07:52:54.541Z"
1981
2050
  },
1982
2051
  {
1983
2052
  id: "760491",
1984
2053
  stage: "R32",
1985
2054
  kickoff: "2026-07-01T01:00Z",
1986
2055
  venue: "Estadio Banorte",
2056
+ city: "Mexico City",
2057
+ country: "Mexico",
1987
2058
  home: {
1988
2059
  code: "1A",
1989
2060
  name: "Group A Winner",
@@ -1995,13 +2066,15 @@ var schedule_2026_default = [
1995
2066
  flag: "\u{1F3F3}\uFE0F"
1996
2067
  },
1997
2068
  status: "SCHEDULED",
1998
- updatedAt: "2026-05-31T08:32:53.682Z"
2069
+ updatedAt: "2026-06-07T07:52:54.541Z"
1999
2070
  },
2000
2071
  {
2001
2072
  id: "760495",
2002
2073
  stage: "R32",
2003
2074
  kickoff: "2026-07-01T16:00Z",
2004
2075
  venue: "Mercedes-Benz Stadium",
2076
+ city: "Atlanta, Georgia",
2077
+ country: "USA",
2005
2078
  home: {
2006
2079
  code: "1L",
2007
2080
  name: "Group L Winner",
@@ -2013,13 +2086,15 @@ var schedule_2026_default = [
2013
2086
  flag: "\u{1F3F3}\uFE0F"
2014
2087
  },
2015
2088
  status: "SCHEDULED",
2016
- updatedAt: "2026-05-31T08:32:53.682Z"
2089
+ updatedAt: "2026-06-07T07:52:54.541Z"
2017
2090
  },
2018
2091
  {
2019
2092
  id: "760493",
2020
2093
  stage: "R32",
2021
2094
  kickoff: "2026-07-01T20:00Z",
2022
2095
  venue: "Lumen Field",
2096
+ city: "Seattle, Washington",
2097
+ country: "USA",
2023
2098
  home: {
2024
2099
  code: "1G",
2025
2100
  name: "Group G Winner",
@@ -2031,13 +2106,15 @@ var schedule_2026_default = [
2031
2106
  flag: "\u{1F3F3}\uFE0F"
2032
2107
  },
2033
2108
  status: "SCHEDULED",
2034
- updatedAt: "2026-05-31T08:32:53.682Z"
2109
+ updatedAt: "2026-06-07T07:52:54.541Z"
2035
2110
  },
2036
2111
  {
2037
2112
  id: "760494",
2038
2113
  stage: "R32",
2039
2114
  kickoff: "2026-07-02T00:00Z",
2040
2115
  venue: "Levi's Stadium",
2116
+ city: "Santa Clara, California",
2117
+ country: "USA",
2041
2118
  home: {
2042
2119
  code: "1D",
2043
2120
  name: "Group D Winner",
@@ -2049,13 +2126,15 @@ var schedule_2026_default = [
2049
2126
  flag: "\u{1F3F3}\uFE0F"
2050
2127
  },
2051
2128
  status: "SCHEDULED",
2052
- updatedAt: "2026-05-31T08:32:53.683Z"
2129
+ updatedAt: "2026-06-07T07:52:54.541Z"
2053
2130
  },
2054
2131
  {
2055
2132
  id: "760497",
2056
2133
  stage: "R32",
2057
2134
  kickoff: "2026-07-02T19:00Z",
2058
2135
  venue: "SoFi Stadium",
2136
+ city: "Inglewood, California",
2137
+ country: "USA",
2059
2138
  home: {
2060
2139
  code: "1H",
2061
2140
  name: "Group H Winner",
@@ -2067,13 +2146,15 @@ var schedule_2026_default = [
2067
2146
  flag: "\u{1F3F3}\uFE0F"
2068
2147
  },
2069
2148
  status: "SCHEDULED",
2070
- updatedAt: "2026-05-31T08:32:53.746Z"
2149
+ updatedAt: "2026-06-07T07:52:54.616Z"
2071
2150
  },
2072
2151
  {
2073
2152
  id: "760496",
2074
2153
  stage: "R32",
2075
2154
  kickoff: "2026-07-02T23:00Z",
2076
2155
  venue: "BMO Field",
2156
+ city: "Toronto",
2157
+ country: "Canada",
2077
2158
  home: {
2078
2159
  code: "2K",
2079
2160
  name: "Group K 2nd Place",
@@ -2085,13 +2166,15 @@ var schedule_2026_default = [
2085
2166
  flag: "\u{1F3F3}\uFE0F"
2086
2167
  },
2087
2168
  status: "SCHEDULED",
2088
- updatedAt: "2026-05-31T08:32:53.746Z"
2169
+ updatedAt: "2026-06-07T07:52:54.616Z"
2089
2170
  },
2090
2171
  {
2091
2172
  id: "760498",
2092
2173
  stage: "R32",
2093
2174
  kickoff: "2026-07-03T03:00Z",
2094
2175
  venue: "BC Place",
2176
+ city: "Vancouver",
2177
+ country: "Canada",
2095
2178
  home: {
2096
2179
  code: "1B",
2097
2180
  name: "Group B Winner",
@@ -2103,13 +2186,15 @@ var schedule_2026_default = [
2103
2186
  flag: "\u{1F3F3}\uFE0F"
2104
2187
  },
2105
2188
  status: "SCHEDULED",
2106
- updatedAt: "2026-05-31T08:32:53.746Z"
2189
+ updatedAt: "2026-06-07T07:52:54.616Z"
2107
2190
  },
2108
2191
  {
2109
2192
  id: "760499",
2110
2193
  stage: "R32",
2111
2194
  kickoff: "2026-07-03T18:00Z",
2112
2195
  venue: "AT&T Stadium",
2196
+ city: "Arlington, Texas",
2197
+ country: "USA",
2113
2198
  home: {
2114
2199
  code: "2D",
2115
2200
  name: "Group D 2nd Place",
@@ -2121,13 +2206,15 @@ var schedule_2026_default = [
2121
2206
  flag: "\u{1F3F3}\uFE0F"
2122
2207
  },
2123
2208
  status: "SCHEDULED",
2124
- updatedAt: "2026-05-31T08:32:53.746Z"
2209
+ updatedAt: "2026-06-07T07:52:54.616Z"
2125
2210
  },
2126
2211
  {
2127
2212
  id: "760500",
2128
2213
  stage: "R32",
2129
2214
  kickoff: "2026-07-03T22:00Z",
2130
2215
  venue: "Hard Rock Stadium",
2216
+ city: "Miami Gardens, Florida",
2217
+ country: "USA",
2131
2218
  home: {
2132
2219
  code: "1J",
2133
2220
  name: "Group J Winner",
@@ -2139,13 +2226,15 @@ var schedule_2026_default = [
2139
2226
  flag: "\u{1F3F3}\uFE0F"
2140
2227
  },
2141
2228
  status: "SCHEDULED",
2142
- updatedAt: "2026-05-31T08:32:53.746Z"
2229
+ updatedAt: "2026-06-07T07:52:54.616Z"
2143
2230
  },
2144
2231
  {
2145
2232
  id: "760501",
2146
2233
  stage: "R32",
2147
2234
  kickoff: "2026-07-04T01:30Z",
2148
2235
  venue: "GEHA Field at Arrowhead Stadium",
2236
+ city: "Kansas City, Missouri",
2237
+ country: "USA",
2149
2238
  home: {
2150
2239
  code: "1K",
2151
2240
  name: "Group K Winner",
@@ -2157,13 +2246,15 @@ var schedule_2026_default = [
2157
2246
  flag: "\u{1F3F3}\uFE0F"
2158
2247
  },
2159
2248
  status: "SCHEDULED",
2160
- updatedAt: "2026-05-31T08:32:53.746Z"
2249
+ updatedAt: "2026-06-07T07:52:54.616Z"
2161
2250
  },
2162
2251
  {
2163
2252
  id: "760502",
2164
2253
  stage: "R16",
2165
2254
  kickoff: "2026-07-04T17:00Z",
2166
2255
  venue: "NRG Stadium",
2256
+ city: "Houston, Texas",
2257
+ country: "USA",
2167
2258
  home: {
2168
2259
  code: "RD32",
2169
2260
  name: "Round of 32 1 Winner",
@@ -2175,13 +2266,15 @@ var schedule_2026_default = [
2175
2266
  flag: "\u{1F3F3}\uFE0F"
2176
2267
  },
2177
2268
  status: "SCHEDULED",
2178
- updatedAt: "2026-05-31T08:32:53.746Z"
2269
+ updatedAt: "2026-06-07T07:52:54.616Z"
2179
2270
  },
2180
2271
  {
2181
2272
  id: "760503",
2182
2273
  stage: "R16",
2183
2274
  kickoff: "2026-07-04T21:00Z",
2184
2275
  venue: "Lincoln Financial Field",
2276
+ city: "Philadelphia, Pennsylvania",
2277
+ country: "USA",
2185
2278
  home: {
2186
2279
  code: "RD32",
2187
2280
  name: "Round of 32 2 Winner",
@@ -2193,13 +2286,15 @@ var schedule_2026_default = [
2193
2286
  flag: "\u{1F3F3}\uFE0F"
2194
2287
  },
2195
2288
  status: "SCHEDULED",
2196
- updatedAt: "2026-05-31T08:32:53.746Z"
2289
+ updatedAt: "2026-06-07T07:52:54.616Z"
2197
2290
  },
2198
2291
  {
2199
2292
  id: "760504",
2200
2293
  stage: "R16",
2201
2294
  kickoff: "2026-07-05T20:00Z",
2202
2295
  venue: "MetLife Stadium",
2296
+ city: "East Rutherford, New Jersey",
2297
+ country: "USA",
2203
2298
  home: {
2204
2299
  code: "RD32",
2205
2300
  name: "Round of 32 4 Winner",
@@ -2211,13 +2306,15 @@ var schedule_2026_default = [
2211
2306
  flag: "\u{1F3F3}\uFE0F"
2212
2307
  },
2213
2308
  status: "SCHEDULED",
2214
- updatedAt: "2026-05-31T08:32:53.746Z"
2309
+ updatedAt: "2026-06-07T07:52:54.616Z"
2215
2310
  },
2216
2311
  {
2217
2312
  id: "760505",
2218
2313
  stage: "R16",
2219
2314
  kickoff: "2026-07-06T00:00Z",
2220
2315
  venue: "Estadio Banorte",
2316
+ city: "Mexico City",
2317
+ country: "Mexico",
2221
2318
  home: {
2222
2319
  code: "RD32",
2223
2320
  name: "Round of 32 7 Winner",
@@ -2229,13 +2326,15 @@ var schedule_2026_default = [
2229
2326
  flag: "\u{1F3F3}\uFE0F"
2230
2327
  },
2231
2328
  status: "SCHEDULED",
2232
- updatedAt: "2026-05-31T08:32:53.746Z"
2329
+ updatedAt: "2026-06-07T07:52:54.616Z"
2233
2330
  },
2234
2331
  {
2235
2332
  id: "760506",
2236
2333
  stage: "R16",
2237
2334
  kickoff: "2026-07-06T19:00Z",
2238
2335
  venue: "AT&T Stadium",
2336
+ city: "Arlington, Texas",
2337
+ country: "USA",
2239
2338
  home: {
2240
2339
  code: "RD32",
2241
2340
  name: "Round of 32 11 Winner",
@@ -2247,13 +2346,15 @@ var schedule_2026_default = [
2247
2346
  flag: "\u{1F3F3}\uFE0F"
2248
2347
  },
2249
2348
  status: "SCHEDULED",
2250
- updatedAt: "2026-05-31T08:32:53.746Z"
2349
+ updatedAt: "2026-06-07T07:52:54.616Z"
2251
2350
  },
2252
2351
  {
2253
2352
  id: "760507",
2254
2353
  stage: "R16",
2255
2354
  kickoff: "2026-07-07T00:00Z",
2256
2355
  venue: "Lumen Field",
2356
+ city: "Seattle, Washington",
2357
+ country: "USA",
2257
2358
  home: {
2258
2359
  code: "RD32",
2259
2360
  name: "Round of 32 9 Winner",
@@ -2265,13 +2366,15 @@ var schedule_2026_default = [
2265
2366
  flag: "\u{1F3F3}\uFE0F"
2266
2367
  },
2267
2368
  status: "SCHEDULED",
2268
- updatedAt: "2026-05-31T08:32:53.746Z"
2369
+ updatedAt: "2026-06-07T07:52:54.616Z"
2269
2370
  },
2270
2371
  {
2271
2372
  id: "760509",
2272
2373
  stage: "R16",
2273
2374
  kickoff: "2026-07-07T16:00Z",
2274
2375
  venue: "Mercedes-Benz Stadium",
2376
+ city: "Atlanta, Georgia",
2377
+ country: "USA",
2275
2378
  home: {
2276
2379
  code: "RD32",
2277
2380
  name: "Round of 32 14 Winner",
@@ -2283,13 +2386,15 @@ var schedule_2026_default = [
2283
2386
  flag: "\u{1F3F3}\uFE0F"
2284
2387
  },
2285
2388
  status: "SCHEDULED",
2286
- updatedAt: "2026-05-31T08:32:53.746Z"
2389
+ updatedAt: "2026-06-07T07:52:54.616Z"
2287
2390
  },
2288
2391
  {
2289
2392
  id: "760508",
2290
2393
  stage: "R16",
2291
2394
  kickoff: "2026-07-07T20:00Z",
2292
2395
  venue: "BC Place",
2396
+ city: "Vancouver",
2397
+ country: "Canada",
2293
2398
  home: {
2294
2399
  code: "RD32",
2295
2400
  name: "Round of 32 13 Winner",
@@ -2301,13 +2406,15 @@ var schedule_2026_default = [
2301
2406
  flag: "\u{1F3F3}\uFE0F"
2302
2407
  },
2303
2408
  status: "SCHEDULED",
2304
- updatedAt: "2026-05-31T08:32:53.746Z"
2409
+ updatedAt: "2026-06-07T07:52:54.616Z"
2305
2410
  },
2306
2411
  {
2307
2412
  id: "760510",
2308
2413
  stage: "QF",
2309
2414
  kickoff: "2026-07-09T20:00Z",
2310
2415
  venue: "Gillette Stadium",
2416
+ city: "Foxborough, Massachusetts",
2417
+ country: "USA",
2311
2418
  home: {
2312
2419
  code: "RD16 W1",
2313
2420
  name: "Round of 16 1 Winner",
@@ -2319,13 +2426,15 @@ var schedule_2026_default = [
2319
2426
  flag: "\u{1F3F3}\uFE0F"
2320
2427
  },
2321
2428
  status: "SCHEDULED",
2322
- updatedAt: "2026-05-31T08:32:53.806Z"
2429
+ updatedAt: "2026-06-07T07:52:54.684Z"
2323
2430
  },
2324
2431
  {
2325
2432
  id: "760511",
2326
2433
  stage: "QF",
2327
2434
  kickoff: "2026-07-10T19:00Z",
2328
2435
  venue: "SoFi Stadium",
2436
+ city: "Inglewood, California",
2437
+ country: "USA",
2329
2438
  home: {
2330
2439
  code: "RD16 W5",
2331
2440
  name: "Round of 16 5 Winner",
@@ -2337,13 +2446,15 @@ var schedule_2026_default = [
2337
2446
  flag: "\u{1F3F3}\uFE0F"
2338
2447
  },
2339
2448
  status: "SCHEDULED",
2340
- updatedAt: "2026-05-31T08:32:53.806Z"
2449
+ updatedAt: "2026-06-07T07:52:54.684Z"
2341
2450
  },
2342
2451
  {
2343
2452
  id: "760512",
2344
2453
  stage: "QF",
2345
2454
  kickoff: "2026-07-11T21:00Z",
2346
2455
  venue: "Hard Rock Stadium",
2456
+ city: "Miami Gardens, Florida",
2457
+ country: "USA",
2347
2458
  home: {
2348
2459
  code: "RD16 W3",
2349
2460
  name: "Round of 16 3 Winner",
@@ -2355,13 +2466,15 @@ var schedule_2026_default = [
2355
2466
  flag: "\u{1F3F3}\uFE0F"
2356
2467
  },
2357
2468
  status: "SCHEDULED",
2358
- updatedAt: "2026-05-31T08:32:53.806Z"
2469
+ updatedAt: "2026-06-07T07:52:54.684Z"
2359
2470
  },
2360
2471
  {
2361
2472
  id: "760513",
2362
2473
  stage: "QF",
2363
2474
  kickoff: "2026-07-12T01:00Z",
2364
2475
  venue: "GEHA Field at Arrowhead Stadium",
2476
+ city: "Kansas City, Missouri",
2477
+ country: "USA",
2365
2478
  home: {
2366
2479
  code: "RD16 W7",
2367
2480
  name: "Round of 16 7 Winner",
@@ -2373,13 +2486,15 @@ var schedule_2026_default = [
2373
2486
  flag: "\u{1F3F3}\uFE0F"
2374
2487
  },
2375
2488
  status: "SCHEDULED",
2376
- updatedAt: "2026-05-31T08:32:53.806Z"
2489
+ updatedAt: "2026-06-07T07:52:54.684Z"
2377
2490
  },
2378
2491
  {
2379
2492
  id: "760514",
2380
2493
  stage: "SF",
2381
2494
  kickoff: "2026-07-14T19:00Z",
2382
2495
  venue: "AT&T Stadium",
2496
+ city: "Arlington, Texas",
2497
+ country: "USA",
2383
2498
  home: {
2384
2499
  code: "QFW1",
2385
2500
  name: "Quarterfinal 1 Winner",
@@ -2391,13 +2506,15 @@ var schedule_2026_default = [
2391
2506
  flag: "\u{1F3F3}\uFE0F"
2392
2507
  },
2393
2508
  status: "SCHEDULED",
2394
- updatedAt: "2026-05-31T08:32:53.806Z"
2509
+ updatedAt: "2026-06-07T07:52:54.684Z"
2395
2510
  },
2396
2511
  {
2397
2512
  id: "760515",
2398
2513
  stage: "SF",
2399
2514
  kickoff: "2026-07-15T19:00Z",
2400
2515
  venue: "Mercedes-Benz Stadium",
2516
+ city: "Atlanta, Georgia",
2517
+ country: "USA",
2401
2518
  home: {
2402
2519
  code: "QFW3",
2403
2520
  name: "Quarterfinal 3 Winner",
@@ -2409,13 +2526,15 @@ var schedule_2026_default = [
2409
2526
  flag: "\u{1F3F3}\uFE0F"
2410
2527
  },
2411
2528
  status: "SCHEDULED",
2412
- updatedAt: "2026-05-31T08:32:53.806Z"
2529
+ updatedAt: "2026-06-07T07:52:54.684Z"
2413
2530
  },
2414
2531
  {
2415
2532
  id: "760516",
2416
2533
  stage: "3P",
2417
2534
  kickoff: "2026-07-18T21:00Z",
2418
2535
  venue: "Hard Rock Stadium",
2536
+ city: "Miami Gardens, Florida",
2537
+ country: "USA",
2419
2538
  home: {
2420
2539
  code: "SF L1",
2421
2540
  name: "Semifinal 1 Loser",
@@ -2427,13 +2546,15 @@ var schedule_2026_default = [
2427
2546
  flag: "\u{1F3F3}\uFE0F"
2428
2547
  },
2429
2548
  status: "SCHEDULED",
2430
- updatedAt: "2026-05-31T08:32:53.923Z"
2549
+ updatedAt: "2026-06-07T07:52:54.772Z"
2431
2550
  },
2432
2551
  {
2433
2552
  id: "760517",
2434
2553
  stage: "F",
2435
2554
  kickoff: "2026-07-19T19:00Z",
2436
2555
  venue: "MetLife Stadium",
2556
+ city: "East Rutherford, New Jersey",
2557
+ country: "USA",
2437
2558
  home: {
2438
2559
  code: "SFW1",
2439
2560
  name: "Semifinal 1 Winner",
@@ -2445,16 +2566,16 @@ var schedule_2026_default = [
2445
2566
  flag: "\u{1F3F3}\uFE0F"
2446
2567
  },
2447
2568
  status: "SCHEDULED",
2448
- updatedAt: "2026-05-31T08:32:53.924Z"
2569
+ updatedAt: "2026-06-07T07:52:54.772Z"
2449
2570
  }
2450
2571
  ];
2451
2572
  var SCHEDULE = schedule_2026_default;
2452
2573
  function allFixtures() {
2453
2574
  return SCHEDULE;
2454
2575
  }
2455
- function fixturesByDate(dateISO, fixtures = SCHEDULE) {
2576
+ function fixturesByDate(dateISO, fixtures = SCHEDULE, tz) {
2456
2577
  const day = dateISO.slice(0, 10);
2457
- return fixtures.filter((m) => m.kickoff.slice(0, 10) === day).sort(byKickoff);
2578
+ return fixtures.filter((m) => localDate(m.kickoff, tz) === day).sort(byKickoff);
2458
2579
  }
2459
2580
  function fixturesByTeam(code, fixtures = SCHEDULE) {
2460
2581
  const c = code.toUpperCase();
@@ -2602,6 +2723,8 @@ function mapEspnEvent(ev, ctx = {}) {
2602
2723
  group,
2603
2724
  kickoff: ev.date,
2604
2725
  venue: comp?.venue?.fullName ?? "",
2726
+ city: comp?.venue?.address?.city || void 0,
2727
+ country: comp?.venue?.address?.country || void 0,
2605
2728
  home,
2606
2729
  away,
2607
2730
  score: hasScore ? { home: hs, away: as } : void 0,
@@ -2695,7 +2818,6 @@ function resolveCompetition(explicit) {
2695
2818
  }
2696
2819
  function makeAdapter(source = "espn") {
2697
2820
  switch (source) {
2698
- case "espn":
2699
2821
  default: {
2700
2822
  const competition = resolveCompetition();
2701
2823
  const baseUrl = competition === DEFAULT_COMPETITION ? void 0 : competitionBase(competition);
@@ -2708,130 +2830,789 @@ function mergeLive(base, live) {
2708
2830
  for (const m of live) byId.set(m.id, m);
2709
2831
  return [...byId.values()];
2710
2832
  }
2833
+ function liveSourceLabel(source) {
2834
+ const known = { espn: "ESPN" };
2835
+ return known[source] ?? source.charAt(0).toUpperCase() + source.slice(1);
2836
+ }
2711
2837
  async function getMatchesForDate(adapter, dateISO) {
2712
2838
  const base = allFixtures();
2839
+ const day = dateISO.slice(0, 10);
2713
2840
  try {
2714
- const live = await adapter.fetchByDate(dateISO);
2715
- return { matches: mergeLive(base, live), degraded: false };
2841
+ const live = adapter.fetchWindow ? await adapter.fetchWindow(shiftUtcDate(day, -1), shiftUtcDate(day, 1)) : await adapter.fetchByDate(day);
2842
+ return { matches: mergeLive(base, live), degraded: false, source: adapter.name };
2716
2843
  } catch {
2717
2844
  return { matches: base, degraded: true };
2718
2845
  }
2719
2846
  }
2847
+ function shiftUtcDate(dateISO, days) {
2848
+ const [y, m, d] = dateISO.slice(0, 10).split("-").map(Number);
2849
+ return new Date(Date.UTC(y ?? 1970, (m ?? 1) - 1, (d ?? 1) + days)).toISOString().slice(0, 10);
2850
+ }
2720
2851
  async function getLiveMatches(adapter) {
2721
2852
  try {
2722
- return { matches: await adapter.fetchLive(), degraded: false };
2853
+ return { matches: await adapter.fetchLive(), degraded: false, source: adapter.name };
2723
2854
  } catch {
2724
2855
  return { matches: [], degraded: true };
2725
2856
  }
2726
2857
  }
2727
-
2728
- // src/commands.ts
2729
- import Table from "cli-table3";
2730
-
2731
- // src/format.ts
2732
- import pc from "picocolors";
2733
- function paint(enabled) {
2734
- const id = (s) => s;
2735
- if (!enabled) {
2736
- return {
2737
- dim: id,
2738
- bold: id,
2739
- green: id,
2740
- yellow: id,
2741
- red: id,
2742
- cyan: id,
2743
- gray: id
2744
- };
2858
+ var DEFAULT_MAX_AGE_MS = 15 * 6e4;
2859
+ function normalizeOutcomes(outcomes) {
2860
+ const sum = outcomes.reduce(
2861
+ (s, o) => s + (Number.isFinite(o.probability) && o.probability > 0 ? o.probability : 0),
2862
+ 0
2863
+ );
2864
+ if (sum <= 0) return outcomes.map((o) => ({ ...o, probability: 0 }));
2865
+ return outcomes.map((o) => ({
2866
+ ...o,
2867
+ probability: Number.isFinite(o.probability) && o.probability > 0 ? o.probability / sum : 0
2868
+ }));
2869
+ }
2870
+ function favoriteStrength(probability) {
2871
+ if (probability >= 0.65) return "clear";
2872
+ if (probability >= 0.52) return "slight";
2873
+ return "close";
2874
+ }
2875
+ function deriveFavorite(outcomes) {
2876
+ let top;
2877
+ for (const o of outcomes) {
2878
+ if (o.kind === "other") continue;
2879
+ if (!top || o.probability > top.probability) top = o;
2745
2880
  }
2881
+ if (!top || top.probability <= 0 || top.kind === "other") return void 0;
2746
2882
  return {
2747
- dim: pc.dim,
2748
- bold: pc.bold,
2749
- green: pc.green,
2750
- yellow: pc.yellow,
2751
- red: pc.red,
2752
- cyan: pc.cyan,
2753
- gray: pc.gray
2883
+ kind: top.kind,
2884
+ teamCode: top.teamCode,
2885
+ probability: top.probability,
2886
+ strength: favoriteStrength(top.probability)
2754
2887
  };
2755
2888
  }
2756
- function painterFor(cfg) {
2757
- return paint(cfg.color);
2758
- }
2759
- function statusToken(m, t, c) {
2760
- switch (m.status) {
2761
- case "LIVE":
2762
- return c.green(`${m.minute ? `${m.minute}'` : t("status.live")}`);
2763
- case "HT":
2764
- return c.yellow(t("status.ht"));
2765
- case "FT":
2766
- return c.gray(t("status.ft"));
2767
- case "POSTPONED":
2768
- return c.red(t("status.postponed"));
2769
- case "CANCELLED":
2770
- return c.red(t("status.cancelled"));
2771
- case "SCHEDULED":
2772
- default:
2773
- return "";
2889
+ function mapsCleanly(match, outcomes) {
2890
+ if (outcomes.some((o) => o.kind === "other")) return false;
2891
+ const home = outcomes.find((o) => o.kind === "home");
2892
+ const away = outcomes.find((o) => o.kind === "away");
2893
+ const draw = outcomes.find((o) => o.kind === "draw");
2894
+ if (!home || !away) return false;
2895
+ if (home.teamCode && home.teamCode.toUpperCase() !== match.home.code.toUpperCase()) {
2896
+ return false;
2774
2897
  }
2775
- }
2776
- function matchLine(m, cfg, t, c) {
2777
- const home = `${m.home.flag} ${m.home.name}`;
2778
- const away = `${m.away.name} ${m.away.flag}`;
2779
- const mid = isLive(m.status) || m.status === "FT" ? c.bold(scoreline(m)) : c.dim("vs");
2780
- const left = `${home.padEnd(22)} ${mid.padStart(3)} ${away}`;
2781
- let right = "";
2782
- if (m.status === "SCHEDULED") {
2783
- right = c.dim(
2784
- `${formatKickoff(m.kickoff, { tz: cfg.tz, locale: cfg.lang })}`
2785
- );
2786
- } else {
2787
- right = statusToken(m, t, c);
2898
+ if (away.teamCode && away.teamCode.toUpperCase() !== match.away.code.toUpperCase()) {
2899
+ return false;
2788
2900
  }
2789
- return ` ${left} ${right}`.trimEnd();
2901
+ if (match.stage === "GROUP" && !draw) return false;
2902
+ return true;
2790
2903
  }
2791
- function header(text, c) {
2792
- return c.bold(c.cyan(text));
2904
+ function hasSaneDistribution(outcomes) {
2905
+ const priced = outcomes.filter((o) => Number.isFinite(o.probability) && o.probability > 0);
2906
+ if (priced.length < 2) return false;
2907
+ const sum = priced.reduce((s, o) => s + o.probability, 0);
2908
+ return sum > 0.97 && sum < 1.03;
2793
2909
  }
2794
- function disclaimer(t, c) {
2910
+ function isStaleSignal(signal, options = {}) {
2911
+ const maxAge = options.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
2912
+ const asOf = Date.parse(signal.asOf);
2913
+ if (!Number.isFinite(asOf)) return true;
2914
+ const now = (options.now ?? /* @__PURE__ */ new Date()).getTime();
2915
+ return now - asOf > maxAge;
2916
+ }
2917
+ function isReliableMarketSignal(signal, options = {}) {
2918
+ if (options.includeUnreliable) return true;
2919
+ if (signal.ambiguous) return false;
2920
+ if (!signal.favorite) return false;
2921
+ if (!hasSaneDistribution(signal.outcomes)) return false;
2922
+ if (signal.stale || isStaleSignal(signal, options)) return false;
2923
+ if (options.minLiquidity != null) {
2924
+ if (signal.liquidity == null || signal.liquidity < options.minLiquidity) return false;
2925
+ }
2926
+ return true;
2927
+ }
2928
+ function buildMarketSignal(input) {
2929
+ const outcomes = normalizeOutcomes(input.outcomes);
2930
+ const ambiguous = input.ambiguous === true || !mapsCleanly(input.match, outcomes);
2931
+ const favorite = ambiguous ? void 0 : deriveFavorite(outcomes);
2932
+ const signal = {
2933
+ matchId: input.match.id,
2934
+ source: input.source,
2935
+ sourceMarketId: input.sourceMarketId,
2936
+ asOf: input.asOf,
2937
+ fetchedAt: input.fetchedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
2938
+ outcomes,
2939
+ favorite,
2940
+ liquidity: input.liquidity,
2941
+ volume24h: input.volume24h,
2942
+ stale: false,
2943
+ ambiguous
2944
+ };
2945
+ signal.stale = isStaleSignal(signal, { now: input.now, maxAgeMs: input.maxAgeMs });
2946
+ return signal;
2947
+ }
2948
+ function pct(p) {
2949
+ return Math.round(p * 100);
2950
+ }
2951
+ function marketSourceLabel(source) {
2952
+ if (source === "polymarket") return "Polymarket";
2953
+ if (source === "fake") return "demo data";
2954
+ return source.charAt(0).toUpperCase() + source.slice(1);
2955
+ }
2956
+ function outcomeLabel(o, match) {
2957
+ if (o.kind === "home") return match.home.name;
2958
+ if (o.kind === "away") return match.away.name;
2959
+ if (o.kind === "draw") return "Draw";
2960
+ return o.label;
2961
+ }
2962
+ function utcHhmm(iso) {
2963
+ const t = Date.parse(iso);
2964
+ if (!Number.isFinite(t)) return "";
2965
+ return `${new Date(t).toISOString().slice(11, 16)} UTC`;
2966
+ }
2967
+ function marketFavoriteText(signal, match) {
2968
+ const fav = signal.favorite;
2969
+ if (!fav || fav.strength === "close") return "Prediction markets see this match as close.";
2970
+ if (fav.kind === "draw") return "Prediction markets see a draw as the top outcome.";
2971
+ const name = fav.kind === "home" ? match.home.name : match.away.name;
2972
+ return fav.strength === "clear" ? `Prediction markets favor ${name}.` : `Prediction markets slightly favor ${name}.`;
2973
+ }
2974
+ function marketProbabilityText(signal, match) {
2975
+ const order = ["home", "draw", "away"];
2976
+ const parts = [];
2977
+ for (const kind of order) {
2978
+ const o = signal.outcomes.find((x) => x.kind === kind);
2979
+ if (o) parts.push(`${outcomeLabel(o, match)} ${pct(o.probability)}%`);
2980
+ }
2981
+ for (const o of signal.outcomes) {
2982
+ if (o.kind === "other") parts.push(`${outcomeLabel(o, match)} ${pct(o.probability)}%`);
2983
+ }
2984
+ return parts.join(" \xB7 ");
2985
+ }
2986
+ function marketAttributionText(signal) {
2987
+ const time = utcHhmm(signal.asOf);
2988
+ const src = `Source: ${marketSourceLabel(signal.source)}`;
2989
+ return time ? `${src} \xB7 updated ${time}` : src;
2990
+ }
2991
+ function marketLine(signal, match) {
2992
+ return `Market: ${marketProbabilityText(signal, match)} \xB7 ${marketSourceLabel(
2993
+ signal.source
2994
+ )} \xB7 informational only`;
2995
+ }
2996
+ function marketBlock(signal, match) {
2997
+ const lines = [];
2998
+ if (signal.stale) lines.push("Market signal is stale; the reading may be out of date.");
2999
+ lines.push(marketFavoriteText(signal, match));
3000
+ lines.push(marketProbabilityText(signal, match));
3001
+ lines.push(`${marketAttributionText(signal)} \xB7 informational only`);
3002
+ return lines;
3003
+ }
3004
+ var FakeMarketProvider = class {
3005
+ constructor(opts = {}) {
3006
+ this.opts = opts;
3007
+ }
3008
+ opts;
3009
+ name = "fake";
3010
+ async findSignal(match, options) {
3011
+ const preset = this.opts.signals?.[match.id];
3012
+ if (preset) return preset;
3013
+ if (this.opts.synthesize) return this.synthesize(match, options);
3014
+ return void 0;
3015
+ }
3016
+ async findSignals(matches, options) {
3017
+ const signals = /* @__PURE__ */ new Map();
3018
+ const checked = /* @__PURE__ */ new Set();
3019
+ for (const m of matches) {
3020
+ checked.add(m.id);
3021
+ const s = await this.findSignal(m, options);
3022
+ if (s) signals.set(m.id, s);
3023
+ }
3024
+ return { signals, checked };
3025
+ }
3026
+ synthesize(match, options) {
3027
+ const seed = hash(`${match.home.code}-${match.away.code}`);
3028
+ const home = 0.3 + seed % 33 / 100;
3029
+ const away = 0.18 + (seed >> 3) % 23 / 100;
3030
+ const draw = Math.max(0.05, 1 - home - away);
3031
+ const outcomes = [
3032
+ { kind: "home", teamCode: match.home.code, label: match.home.name, probability: home },
3033
+ { kind: "draw", label: "Draw", probability: draw },
3034
+ { kind: "away", teamCode: match.away.code, label: match.away.name, probability: away }
3035
+ ];
3036
+ const now = this.opts.now ?? options?.now ?? /* @__PURE__ */ new Date();
3037
+ const asOf = new Date(now.getTime() - 6e4).toISOString();
3038
+ return buildMarketSignal({
3039
+ match,
3040
+ source: "fake",
3041
+ sourceMarketId: `fake-${match.id}`,
3042
+ asOf,
3043
+ fetchedAt: now.toISOString(),
3044
+ outcomes,
3045
+ liquidity: 5e4,
3046
+ now,
3047
+ maxAgeMs: options?.maxAgeMs
3048
+ });
3049
+ }
3050
+ };
3051
+ function hash(s) {
3052
+ let h = 0;
3053
+ for (let i = 0; i < s.length; i++) h = h * 31 + s.charCodeAt(i) >>> 0;
3054
+ return h % 1e5;
3055
+ }
3056
+ var mapping_2026_default = {
3057
+ version: 1,
3058
+ note: "Optional matchId -> Polymarket EVENT-slug OVERRIDES. By default the slug is DERIVED from each fixture (fifwc-{home}-{away}-{UTC-date}, e.g. fifwc-mex-rsa-2026-06-11), so most matches need NO entry here. Add an entry only for a fixture whose real Polymarket slug differs (e.g. a team abbreviation that isn't the FIFA code, or a tz-shifted date). The event payload carries the three moneyline binary markets; each outcome's probability is its 'Yes' price; validation fails closed. Entry: { eventSlug, eventId? }.",
3059
+ markets: {}
3060
+ };
3061
+ var DEFAULT_BASE2 = "https://gamma-api.polymarket.com";
3062
+ var ALLOWED_HOSTS = /* @__PURE__ */ new Set(["gamma-api.polymarket.com"]);
3063
+ var USER_AGENT2 = "claudinho/0.0 (+https://github.com/arturogarrido/claudinho)";
3064
+ var DEFAULT_TIMEOUT_MS = 8e3;
3065
+ var WC_SERIES_SLUG = "soccer-fifwc";
3066
+ var WC_SPORT = "fifwc";
3067
+ var KICKOFF_TOLERANCE_MS = 6 * 60 * 6e4;
3068
+ var NON_REGULAR_TIME = /extra time|penalt|to advance|to qualif|win the (group|tournament|cup|title)/i;
3069
+ var BUNDLED_MAPPING = mapping_2026_default.markets;
3070
+ var PolymarketProvider = class {
3071
+ constructor(opts = {}) {
3072
+ this.opts = opts;
3073
+ }
3074
+ opts;
3075
+ name = "polymarket";
3076
+ async findSignal(match, options) {
3077
+ return (await this.resolveOne(match, options)).signal;
3078
+ }
3079
+ async findSignals(matches, options) {
3080
+ const signals = /* @__PURE__ */ new Map();
3081
+ const checked = /* @__PURE__ */ new Set();
3082
+ const deadline = options?.deadlineMs != null ? Date.now() + options.deadlineMs : Number.POSITIVE_INFINITY;
3083
+ for (const m of matches) {
3084
+ if (Date.now() >= deadline) break;
3085
+ const r = await this.resolveOne(m, options);
3086
+ if (r.checked) checked.add(m.id);
3087
+ if (r.signal) signals.set(m.id, r.signal);
3088
+ }
3089
+ return { signals, checked };
3090
+ }
3091
+ /**
3092
+ * Resolve one match. `checked` distinguishes a DEFINITIVE result (reached the
3093
+ * source and found no usable market, or the fixture is unmappable) from a
3094
+ * provider/network error — so transient failures are retried, not
3095
+ * negative-cached.
3096
+ */
3097
+ async resolveOne(match, options) {
3098
+ const entry = (this.opts.mapping ?? BUNDLED_MAPPING)[match.id];
3099
+ const eventSlug = entry?.eventSlug ?? deriveEventSlug(match);
3100
+ if (!eventSlug) return { checked: true };
3101
+ try {
3102
+ const event = await this.fetchEvent(eventSlug, options?.timeoutMs);
3103
+ const signal = event ? this.toSignal(match, eventSlug, event, options) : void 0;
3104
+ return { signal, checked: true };
3105
+ } catch {
3106
+ return { checked: false };
3107
+ }
3108
+ }
3109
+ async fetchEvent(slug, timeoutMs) {
3110
+ const base = this.opts.baseUrl ?? DEFAULT_BASE2;
3111
+ assertAllowedHost(base);
3112
+ const url = `${base}/events?slug=${encodeURIComponent(slug)}`;
3113
+ const doFetch = this.opts.fetchImpl ?? fetch;
3114
+ const res = await doFetch(url, {
3115
+ signal: AbortSignal.timeout(timeoutMs ?? this.opts.timeoutMs ?? DEFAULT_TIMEOUT_MS),
3116
+ headers: { Accept: "application/json", "User-Agent": USER_AGENT2 }
3117
+ });
3118
+ if (res.status === 404) return void 0;
3119
+ if (!res.ok) {
3120
+ throw new Error(`Polymarket request failed: ${res.status} ${res.statusText}`);
3121
+ }
3122
+ const data = await res.json();
3123
+ const event = Array.isArray(data) ? data[0] : data;
3124
+ return event && typeof event === "object" ? event : void 0;
3125
+ }
3126
+ toSignal(match, eventSlug, event, options) {
3127
+ if (event.active === false || event.closed === true) return void 0;
3128
+ if (event.seriesSlug != null && event.seriesSlug !== WC_SERIES_SLUG && event.sport?.sport !== WC_SPORT) {
3129
+ return void 0;
3130
+ }
3131
+ if (event.slug != null && event.slug !== eventSlug) return void 0;
3132
+ const start = event.startTime ? Date.parse(event.startTime) : Number.NaN;
3133
+ const kick = Date.parse(match.kickoff);
3134
+ if (Number.isFinite(start) && Number.isFinite(kick) && Math.abs(start - kick) > KICKOFF_TOLERANCE_MS) {
3135
+ return void 0;
3136
+ }
3137
+ const moneyline = (event.markets ?? []).filter(
3138
+ (m) => (m.sportsMarketType ?? "moneyline") === "moneyline"
3139
+ );
3140
+ const homeMarket = pickMarket(moneyline, match.home.code, match.home.name);
3141
+ const awayMarket = pickMarket(moneyline, match.away.code, match.away.name);
3142
+ const drawMarket = pickDraw(moneyline);
3143
+ if (!homeMarket || !awayMarket) return void 0;
3144
+ const legIds = [homeMarket, awayMarket, drawMarket].filter((m) => m != null).map((m) => m.id ?? m.slug ?? "");
3145
+ if (new Set(legIds).size !== legIds.length) return void 0;
3146
+ const legs = [
3147
+ ["home", homeMarket, match.home.code, match.home.name],
3148
+ ["draw", drawMarket, void 0, "Draw"],
3149
+ ["away", awayMarket, match.away.code, match.away.name]
3150
+ ];
3151
+ const outcomes = [];
3152
+ let asOf = event.updatedAt;
3153
+ let liquidity;
3154
+ for (const [kind, market, teamCode, label] of legs) {
3155
+ if (!market) continue;
3156
+ if (market.closed === true || market.active === false) return void 0;
3157
+ if (market.description && NON_REGULAR_TIME.test(market.description)) return void 0;
3158
+ const yes = yesPrice(market);
3159
+ if (yes == null) return void 0;
3160
+ outcomes.push({ kind, teamCode, label, probability: yes });
3161
+ if (market.updatedAt && (!asOf || market.updatedAt < asOf)) asOf = market.updatedAt;
3162
+ const liq = numberish(market.liquidityNum ?? market.liquidity);
3163
+ if (liq != null) liquidity = liquidity == null ? liq : Math.min(liquidity, liq);
3164
+ }
3165
+ const rawSum = outcomes.reduce((s, o) => s + o.probability, 0);
3166
+ if (rawSum < 0.9 || rawSum > 1.15) return void 0;
3167
+ const signal = buildMarketSignal({
3168
+ match,
3169
+ source: "polymarket",
3170
+ sourceMarketId: event.id ?? eventSlug,
3171
+ asOf: asOf ?? (/* @__PURE__ */ new Date()).toISOString(),
3172
+ outcomes,
3173
+ liquidity,
3174
+ now: options?.now ?? this.opts.now,
3175
+ maxAgeMs: options?.maxAgeMs ?? this.opts.maxAgeMs
3176
+ });
3177
+ return signal.ambiguous ? void 0 : signal;
3178
+ }
3179
+ };
3180
+ function deriveEventSlug(match) {
3181
+ const home = match.home.code.toLowerCase();
3182
+ const away = match.away.code.toLowerCase();
3183
+ if (home === away || home === "tbd" || away === "tbd") return void 0;
3184
+ if (!/^[a-z]{3}$/.test(home) || !/^[a-z]{3}$/.test(away)) return void 0;
3185
+ const date = match.kickoff.slice(0, 10);
3186
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) return void 0;
3187
+ return `fifwc-${home}-${away}-${date}`;
3188
+ }
3189
+ function slugToken(m) {
3190
+ return (m.slug ?? "").toLowerCase().split("-").pop() ?? "";
3191
+ }
3192
+ function isDrawMarket(m) {
3193
+ return slugToken(m) === "draw" || (m.groupItemTitle ?? "").trim().toLowerCase().startsWith("draw");
3194
+ }
3195
+ function pickMarket(markets, teamCode, teamName) {
3196
+ const code = teamCode.toLowerCase();
3197
+ const name = teamName.trim().toLowerCase();
3198
+ const teamMarkets = markets.filter((m) => !isDrawMarket(m));
3199
+ const bySlug = teamMarkets.find((m) => slugToken(m) === code);
3200
+ if (bySlug) return bySlug;
3201
+ return teamMarkets.find((m) => (m.groupItemTitle ?? "").trim().toLowerCase() === name);
3202
+ }
3203
+ function pickDraw(markets) {
3204
+ return markets.find(isDrawMarket);
3205
+ }
3206
+ function assertAllowedHost(base) {
3207
+ let host;
3208
+ try {
3209
+ host = new URL(base).host;
3210
+ } catch {
3211
+ throw new Error(`Invalid Polymarket base URL: ${base}`);
3212
+ }
3213
+ if (!ALLOWED_HOSTS.has(host)) {
3214
+ throw new Error(`Polymarket host not allow-listed: ${host}`);
3215
+ }
3216
+ }
3217
+ function yesPrice(market) {
3218
+ const labels = parseJsonArray(market.outcomes);
3219
+ const prices = parseJsonArray(market.outcomePrices).map((p2) => Number(p2));
3220
+ if (labels.length === 0 || labels.length !== prices.length) return void 0;
3221
+ const i = labels.findIndex((l) => l.trim().toLowerCase() === "yes");
3222
+ if (i < 0) return void 0;
3223
+ const p = prices[i];
3224
+ return typeof p === "number" && Number.isFinite(p) && p > 0 && p <= 1 ? p : void 0;
3225
+ }
3226
+ function parseJsonArray(v) {
3227
+ if (Array.isArray(v)) return v.map((x) => String(x));
3228
+ if (typeof v === "string") {
3229
+ try {
3230
+ const parsed = JSON.parse(v);
3231
+ return Array.isArray(parsed) ? parsed.map((x) => String(x)) : [];
3232
+ } catch {
3233
+ return [];
3234
+ }
3235
+ }
3236
+ return [];
3237
+ }
3238
+ function numberish(v) {
3239
+ if (typeof v === "number") return Number.isFinite(v) ? v : void 0;
3240
+ if (typeof v === "string") {
3241
+ const n = Number(v);
3242
+ return Number.isFinite(n) ? n : void 0;
3243
+ }
3244
+ return void 0;
3245
+ }
3246
+ function resolveMarketSource(explicit) {
3247
+ if (explicit) return explicit;
3248
+ if (typeof process !== "undefined" && process.env?.CLAUDINHO_MARKETS_SOURCE) {
3249
+ return process.env.CLAUDINHO_MARKETS_SOURCE;
3250
+ }
3251
+ return "polymarket";
3252
+ }
3253
+ function makeMarketProvider(source) {
3254
+ switch (resolveMarketSource(source)) {
3255
+ case "fake":
3256
+ return new FakeMarketProvider({ synthesize: true });
3257
+ case "none":
3258
+ case "off":
3259
+ return new FakeMarketProvider();
3260
+ // no synth → yields no signals, no network
3261
+ default:
3262
+ return new PolymarketProvider();
3263
+ }
3264
+ }
3265
+ async function getMarketSignals(provider, matches, options) {
3266
+ try {
3267
+ return await provider.findSignals(matches, options);
3268
+ } catch {
3269
+ return { signals: /* @__PURE__ */ new Map(), checked: /* @__PURE__ */ new Set() };
3270
+ }
3271
+ }
3272
+
3273
+ // src/config.ts
3274
+ var SUPPORTED_LANGS = ["en", "es", "pt", "fr"];
3275
+ function pickLang(explicit) {
3276
+ const candidates = [
3277
+ explicit,
3278
+ process.env.CLAUDINHO_LANG,
3279
+ process.env.LANG?.split(".")[0]?.split("_")[0]
3280
+ ];
3281
+ for (const c of candidates) {
3282
+ if (c && SUPPORTED_LANGS.includes(c)) {
3283
+ return c;
3284
+ }
3285
+ }
3286
+ return "en";
3287
+ }
3288
+ function pickColor(explicit) {
3289
+ if (explicit === false) return false;
3290
+ if (process.env.NO_COLOR) return false;
3291
+ if (!process.stdout.isTTY) return false;
3292
+ return true;
3293
+ }
3294
+ function isSupportedLang(s) {
3295
+ return SUPPORTED_LANGS.includes(s);
3296
+ }
3297
+ function pickMarkets(explicit) {
3298
+ if (explicit === false) return false;
3299
+ if ((process.env.CLAUDINHO_MARKETS ?? "").toLowerCase() === "off") return false;
3300
+ return true;
3301
+ }
3302
+ function resolveConfig(opts) {
3303
+ const langRequestedUnsupported = opts.lang && !isSupportedLang(opts.lang) ? opts.lang : void 0;
3304
+ return {
3305
+ lang: pickLang(opts.lang),
3306
+ tz: opts.tz ?? process.env.CLAUDINHO_TZ ?? void 0,
3307
+ json: opts.json ?? false,
3308
+ color: pickColor(opts.color),
3309
+ source: opts.source ?? process.env.CLAUDINHO_SOURCE ?? "espn",
3310
+ flavor: asFlavorLevel(opts.flavor ?? process.env.CLAUDINHO_FLAVOR),
3311
+ markets: pickMarkets(opts.markets),
3312
+ langRequestedUnsupported
3313
+ };
3314
+ }
3315
+
3316
+ // src/i18n.ts
3317
+ var EN = {
3318
+ "today.title": "Today's matches",
3319
+ "today.on": "Matches",
3320
+ "today.none": "No matches scheduled for this date.",
3321
+ "live.title": "Live now",
3322
+ "live.none": "No matches in play right now.",
3323
+ "next.none": "No upcoming fixture found for {team}.",
3324
+ "next.label": "Next up for {team}",
3325
+ "next.in": "in {countdown}",
3326
+ "table.title": "Group {group}",
3327
+ "table.none": "No group found for {group}.",
3328
+ "match.none": "No match found with id {id}.",
3329
+ "status.scheduled": "scheduled",
3330
+ "status.live": "LIVE",
3331
+ "status.ht": "HT",
3332
+ "status.ft": "FT",
3333
+ "status.postponed": "postponed",
3334
+ "status.cancelled": "cancelled",
3335
+ "col.team": "Team",
3336
+ "col.p": "P",
3337
+ "col.w": "W",
3338
+ "col.d": "D",
3339
+ "col.l": "L",
3340
+ "col.gd": "GD",
3341
+ "col.pts": "Pts",
3342
+ "err.date": "Invalid date {date}. Use YYYY-MM-DD.",
3343
+ "warn.tz": "Unknown timezone {tz}; using system timezone.",
3344
+ "warn.lang": "Unsupported language {lang}; using English. (supported: en, es, pt, fr)",
3345
+ disclaimer: "Not affiliated with FIFA or Anthropic."
3346
+ };
3347
+ var ES = {
3348
+ "today.title": "Partidos de hoy",
3349
+ "today.on": "Partidos",
3350
+ "today.none": "No hay partidos para esta fecha.",
3351
+ "live.title": "En vivo",
3352
+ "live.none": "No hay partidos en juego ahora mismo.",
3353
+ "next.none": "No se encontr\xF3 pr\xF3ximo partido para {team}.",
3354
+ "next.label": "Pr\xF3ximo partido de {team}",
3355
+ "next.in": "en {countdown}",
3356
+ "table.title": "Grupo {group}",
3357
+ "table.none": "No se encontr\xF3 el grupo {group}.",
3358
+ "match.none": "No se encontr\xF3 partido con id {id}.",
3359
+ "status.scheduled": "programado",
3360
+ "status.live": "EN VIVO",
3361
+ "status.ht": "DESC",
3362
+ "status.ft": "FIN",
3363
+ "status.postponed": "aplazado",
3364
+ "status.cancelled": "cancelado",
3365
+ "col.team": "Equipo",
3366
+ "col.p": "PJ",
3367
+ "col.w": "G",
3368
+ "col.d": "E",
3369
+ "col.l": "P",
3370
+ "col.gd": "DG",
3371
+ "col.pts": "Pts",
3372
+ "err.date": "Fecha inv\xE1lida {date}. Usa AAAA-MM-DD.",
3373
+ "warn.tz": "Zona horaria desconocida {tz}; usando la del sistema.",
3374
+ "warn.lang": "Idioma no soportado {lang}; usando ingl\xE9s. (disponibles: en, es, pt, fr)",
3375
+ disclaimer: "No afiliado a FIFA ni Anthropic."
3376
+ };
3377
+ var PT = {
3378
+ "today.title": "Jogos de hoje",
3379
+ "today.on": "Jogos",
3380
+ "today.none": "Nenhum jogo para esta data.",
3381
+ "live.title": "Ao vivo",
3382
+ "live.none": "Nenhum jogo em andamento agora.",
3383
+ "next.none": "Nenhum pr\xF3ximo jogo encontrado para {team}.",
3384
+ "next.label": "Pr\xF3ximo jogo de {team}",
3385
+ "next.in": "em {countdown}",
3386
+ "table.title": "Grupo {group}",
3387
+ "table.none": "Grupo {group} n\xE3o encontrado.",
3388
+ "match.none": "Nenhum jogo encontrado com id {id}.",
3389
+ "status.scheduled": "agendado",
3390
+ "status.live": "AO VIVO",
3391
+ "status.ht": "INT",
3392
+ "status.ft": "FIM",
3393
+ "status.postponed": "adiado",
3394
+ "status.cancelled": "cancelado",
3395
+ "col.team": "Sele\xE7\xE3o",
3396
+ "col.p": "J",
3397
+ "col.w": "V",
3398
+ "col.d": "E",
3399
+ "col.l": "D",
3400
+ "col.gd": "SG",
3401
+ "col.pts": "Pts",
3402
+ "err.date": "Data inv\xE1lida {date}. Use AAAA-MM-DD.",
3403
+ "warn.tz": "Fuso hor\xE1rio desconhecido {tz}; usando o do sistema.",
3404
+ "warn.lang": "Idioma n\xE3o suportado {lang}; usando ingl\xEAs. (dispon\xEDveis: en, es, pt, fr)",
3405
+ disclaimer: "N\xE3o afiliado \xE0 FIFA nem \xE0 Anthropic."
3406
+ };
3407
+ var FR = {
3408
+ "today.title": "Matchs d'aujourd'hui",
3409
+ "today.on": "Matchs",
3410
+ "today.none": "Aucun match pr\xE9vu pour cette date.",
3411
+ "live.title": "En direct",
3412
+ "live.none": "Aucun match en cours pour l'instant.",
3413
+ "next.none": "Aucun prochain match trouv\xE9 pour {team}.",
3414
+ "next.label": "Prochain match de {team}",
3415
+ "next.in": "dans {countdown}",
3416
+ "table.title": "Groupe {group}",
3417
+ "table.none": "Groupe {group} introuvable.",
3418
+ "match.none": "Aucun match trouv\xE9 avec id {id}.",
3419
+ "status.scheduled": "pr\xE9vu",
3420
+ "status.live": "DIRECT",
3421
+ "status.ht": "MT",
3422
+ "status.ft": "FIN",
3423
+ "status.postponed": "report\xE9",
3424
+ "status.cancelled": "annul\xE9",
3425
+ "col.team": "\xC9quipe",
3426
+ "col.p": "J",
3427
+ "col.w": "G",
3428
+ "col.d": "N",
3429
+ "col.l": "P",
3430
+ "col.gd": "Diff",
3431
+ "col.pts": "Pts",
3432
+ "err.date": "Date invalide {date}. Utilisez AAAA-MM-JJ.",
3433
+ "warn.tz": "Fuseau horaire inconnu {tz} ; utilisation du fuseau syst\xE8me.",
3434
+ "warn.lang": "Langue non prise en charge {lang} ; utilisation de l\u2019anglais. (disponibles : en, es, pt, fr)",
3435
+ disclaimer: "Non affili\xE9 \xE0 la FIFA ni \xE0 Anthropic."
3436
+ };
3437
+ var CATALOGS = { en: EN, es: ES, pt: PT, fr: FR };
3438
+ function makeT(lang) {
3439
+ const dict = CATALOGS[lang] ?? EN;
3440
+ return (key, vars) => {
3441
+ let s = dict[key] ?? EN[key] ?? key;
3442
+ if (vars) for (const [k, v] of Object.entries(vars)) s = s.replace(`{${k}}`, v);
3443
+ return s;
3444
+ };
3445
+ }
3446
+
3447
+ // src/commands.ts
3448
+ import Table from "cli-table3";
3449
+
3450
+ // src/format.ts
3451
+ import pc from "picocolors";
3452
+ function paint(enabled) {
3453
+ const id = (s) => s;
3454
+ if (!enabled) {
3455
+ return {
3456
+ dim: id,
3457
+ bold: id,
3458
+ green: id,
3459
+ yellow: id,
3460
+ red: id,
3461
+ cyan: id,
3462
+ gray: id
3463
+ };
3464
+ }
3465
+ return {
3466
+ dim: pc.dim,
3467
+ bold: pc.bold,
3468
+ green: pc.green,
3469
+ yellow: pc.yellow,
3470
+ red: pc.red,
3471
+ cyan: pc.cyan,
3472
+ gray: pc.gray
3473
+ };
3474
+ }
3475
+ function painterFor(cfg) {
3476
+ return paint(cfg.color);
3477
+ }
3478
+ function statusToken(m, t, c) {
3479
+ switch (m.status) {
3480
+ case "LIVE":
3481
+ return c.green(`${m.minute ? `${m.minute}'` : t("status.live")}`);
3482
+ case "HT":
3483
+ return c.yellow(t("status.ht"));
3484
+ case "FT":
3485
+ return c.gray(t("status.ft"));
3486
+ case "POSTPONED":
3487
+ return c.red(t("status.postponed"));
3488
+ case "CANCELLED":
3489
+ return c.red(t("status.cancelled"));
3490
+ default:
3491
+ return "";
3492
+ }
3493
+ }
3494
+ function matchLine(m, cfg, t, c) {
3495
+ const home = `${m.home.flag} ${m.home.name}`;
3496
+ const away = `${m.away.name} ${m.away.flag}`;
3497
+ const mid = isLive(m.status) || m.status === "FT" ? c.bold(scoreline(m)) : c.dim("vs");
3498
+ const left = `${home.padEnd(22)} ${mid.padStart(3)} ${away}`;
3499
+ let right = "";
3500
+ if (m.status === "SCHEDULED") {
3501
+ right = c.dim(
3502
+ `${formatKickoff(m.kickoff, { tz: cfg.tz, locale: cfg.lang })}`
3503
+ );
3504
+ } else {
3505
+ right = statusToken(m, t, c);
3506
+ }
3507
+ const flair = matchFlavor(m, { level: cfg.flavor, locale: cfg.lang });
3508
+ const tail = flair ? ` ${c.dim(flair)}` : "";
3509
+ return ` ${left} ${right}${tail}`.trimEnd();
3510
+ }
3511
+ function header(text, c) {
3512
+ return c.bold(c.cyan(text));
3513
+ }
3514
+ function disclaimer(t, c) {
2795
3515
  return c.dim(t("disclaimer"));
2796
3516
  }
3517
+ function dataSource(source, c) {
3518
+ return source ? c.dim(`Live data: ${liveSourceLabel(source)}`) : "";
3519
+ }
3520
+
3521
+ // src/marketCache.ts
3522
+ import { mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
3523
+ import { homedir } from "os";
3524
+ import { join } from "path";
3525
+ var POSITIVE_TTL_MS = 10 * 6e4;
3526
+ var NEGATIVE_TTL_MS = 3 * 6e4;
3527
+ function cacheDir() {
3528
+ const base = process.env.XDG_CACHE_HOME || join(homedir(), ".cache");
3529
+ return join(base, "claudinho");
3530
+ }
3531
+ function cachePath() {
3532
+ return join(cacheDir(), "market-signals.json");
3533
+ }
3534
+ function readFile() {
3535
+ try {
3536
+ return JSON.parse(readFileSync(cachePath(), "utf8"));
3537
+ } catch {
3538
+ return void 0;
3539
+ }
3540
+ }
3541
+ function readMarketCache(source, competition, now = Date.now()) {
3542
+ const signals = /* @__PURE__ */ new Map();
3543
+ const checked = /* @__PURE__ */ new Set();
3544
+ const file = readFile();
3545
+ if (!file || file.source !== source || file.competition !== competition) {
3546
+ return { signals, checked };
3547
+ }
3548
+ for (const [id, entry] of Object.entries(file.entries ?? {})) {
3549
+ const t = Date.parse(entry.fetchedAt);
3550
+ if (!Number.isFinite(t)) continue;
3551
+ const ttl = entry.signal ? POSITIVE_TTL_MS : NEGATIVE_TTL_MS;
3552
+ if (now - t > ttl) continue;
3553
+ checked.add(id);
3554
+ if (entry.signal) signals.set(id, entry.signal);
3555
+ }
3556
+ return { signals, checked };
3557
+ }
3558
+ function writeMarketCache(source, competition, attempted, fetched, now = Date.now()) {
3559
+ if (attempted.length === 0) return;
3560
+ try {
3561
+ const existing = readFile();
3562
+ const base = existing && existing.source === source && existing.competition === competition ? existing : { source, competition, entries: {} };
3563
+ const fetchedAt = new Date(now).toISOString();
3564
+ for (const id of attempted) {
3565
+ base.entries[id] = { fetchedAt, signal: fetched.get(id) ?? null };
3566
+ }
3567
+ mkdirSync(cacheDir(), { recursive: true });
3568
+ const tmp = join(cacheDir(), `market-signals.${process.pid}.tmp`);
3569
+ writeFileSync(tmp, JSON.stringify(base));
3570
+ renameSync(tmp, cachePath());
3571
+ } catch {
3572
+ }
3573
+ }
2797
3574
 
2798
3575
  // src/cache.ts
2799
3576
  import {
2800
3577
  closeSync,
2801
- mkdirSync,
3578
+ mkdirSync as mkdirSync2,
2802
3579
  openSync,
2803
- readFileSync,
2804
- renameSync,
3580
+ readFileSync as readFileSync2,
3581
+ renameSync as renameSync2,
2805
3582
  rmSync,
2806
3583
  statSync,
2807
3584
  writeSync
2808
3585
  } from "fs";
2809
- import { homedir } from "os";
2810
- import { join } from "path";
3586
+ import { homedir as homedir2 } from "os";
3587
+ import { join as join2 } from "path";
2811
3588
  var LOCK_STALE_MS = 6e4;
2812
- function cacheDir() {
2813
- const base = process.env.XDG_CACHE_HOME || join(homedir(), ".cache");
2814
- return join(base, "claudinho");
3589
+ function cacheDir2() {
3590
+ const base = process.env.XDG_CACHE_HOME || join2(homedir2(), ".cache");
3591
+ return join2(base, "claudinho");
2815
3592
  }
2816
- function cachePath() {
2817
- return join(cacheDir(), "state.json");
3593
+ function cachePath2() {
3594
+ return join2(cacheDir2(), "state.json");
2818
3595
  }
2819
3596
  function lockPath() {
2820
- return join(cacheDir(), "refresh.lock");
3597
+ return join2(cacheDir2(), "refresh.lock");
2821
3598
  }
2822
3599
  function readState() {
2823
3600
  try {
2824
- return JSON.parse(readFileSync(cachePath(), "utf8"));
3601
+ return JSON.parse(readFileSync2(cachePath2(), "utf8"));
2825
3602
  } catch {
2826
3603
  return void 0;
2827
3604
  }
2828
3605
  }
3606
+ function readCurrentState(source, competition) {
3607
+ const s = readState();
3608
+ return s && s.source === source && s.competition === competition ? s : void 0;
3609
+ }
2829
3610
  function writeState(state) {
2830
- const dir = cacheDir();
2831
- mkdirSync(dir, { recursive: true });
2832
- const tmp = join(dir, `state.${process.pid}.tmp`);
3611
+ const dir = cacheDir2();
3612
+ mkdirSync2(dir, { recursive: true });
3613
+ const tmp = join2(dir, `state.${process.pid}.tmp`);
2833
3614
  writeFileSync_(tmp, JSON.stringify(state));
2834
- renameSync(tmp, cachePath());
3615
+ renameSync2(tmp, cachePath2());
2835
3616
  }
2836
3617
  function writeFileSync_(path, data) {
2837
3618
  const fd = openSync(path, "w");
@@ -2849,7 +3630,7 @@ function ageMs(state, now = Date.now()) {
2849
3630
  function lockAgeMs(now = Date.now()) {
2850
3631
  const lp = lockPath();
2851
3632
  try {
2852
- const contents = readFileSync(lp, "utf8");
3633
+ const contents = readFileSync2(lp, "utf8");
2853
3634
  const written = Number.parseInt(contents.split(/\s+/)[1] ?? "", 10);
2854
3635
  if (Number.isFinite(written)) return now - written;
2855
3636
  } catch {
@@ -2865,7 +3646,7 @@ function isLockFresh(now = Date.now()) {
2865
3646
  return lockAgeMs(now) < LOCK_STALE_MS;
2866
3647
  }
2867
3648
  function acquireLock(now = Date.now()) {
2868
- mkdirSync(cacheDir(), { recursive: true });
3649
+ mkdirSync2(cacheDir2(), { recursive: true });
2869
3650
  const lp = lockPath();
2870
3651
  try {
2871
3652
  const fd = openSync(lp, "wx");
@@ -2976,9 +3757,6 @@ function renderHook(state, opts = {}) {
2976
3757
  return `[Claudinho \u2014 live football scores right now]
2977
3758
  ${lines}`;
2978
3759
  }
2979
- function hookContext(opts = {}) {
2980
- return renderHook(readState(), opts);
2981
- }
2982
3760
 
2983
3761
  // src/refresh.ts
2984
3762
  import { spawn } from "child_process";
@@ -2997,7 +3775,11 @@ function liveAdapter() {
2997
3775
  async function runRefresh(opts = {}) {
2998
3776
  const now = opts.now ?? /* @__PURE__ */ new Date();
2999
3777
  const source = opts.source ?? "espn";
3000
- if (ageMs(readState(), now.getTime()) < MIN_REFRESH_MS) return;
3778
+ const competition = resolveCompetition();
3779
+ const cached = readState();
3780
+ if (cached && cached.source === source && cached.competition === competition && ageMs(cached, now.getTime()) < MIN_REFRESH_MS) {
3781
+ return;
3782
+ }
3001
3783
  if (!acquireLock()) return;
3002
3784
  try {
3003
3785
  let live = [];
@@ -3009,7 +3791,7 @@ async function runRefresh(opts = {}) {
3009
3791
  degraded = true;
3010
3792
  }
3011
3793
  }
3012
- writeState({ updatedAt: now.toISOString(), live, degraded, source });
3794
+ writeState({ updatedAt: now.toISOString(), live, degraded, source, competition });
3013
3795
  } finally {
3014
3796
  releaseLock();
3015
3797
  }
@@ -3036,14 +3818,14 @@ function spawnRefresh(source) {
3036
3818
  import {
3037
3819
  copyFileSync,
3038
3820
  existsSync,
3039
- mkdirSync as mkdirSync2,
3040
- readFileSync as readFileSync2,
3041
- writeFileSync
3821
+ mkdirSync as mkdirSync3,
3822
+ readFileSync as readFileSync3,
3823
+ writeFileSync as writeFileSync2
3042
3824
  } from "fs";
3043
- import { homedir as homedir2 } from "os";
3044
- import { dirname, join as join2 } from "path";
3825
+ import { homedir as homedir3 } from "os";
3826
+ import { dirname, join as join3 } from "path";
3045
3827
  function claudeSettingsPath() {
3046
- return join2(homedir2(), ".claude", "settings.json");
3828
+ return join3(homedir3(), ".claude", "settings.json");
3047
3829
  }
3048
3830
  function backupOnce(path) {
3049
3831
  const bak = `${path}.claudinho.bak`;
@@ -3059,7 +3841,7 @@ function initStatusline(opts = {}) {
3059
3841
  let settings = {};
3060
3842
  if (existsSync(path)) {
3061
3843
  try {
3062
- settings = JSON.parse(readFileSync2(path, "utf8"));
3844
+ settings = JSON.parse(readFileSync3(path, "utf8"));
3063
3845
  } catch {
3064
3846
  return {
3065
3847
  action: "manual",
@@ -3075,8 +3857,8 @@ ${snippet}`
3075
3857
  }
3076
3858
  backupOnce(path);
3077
3859
  settings.statusLine = sl;
3078
- mkdirSync2(dirname(path), { recursive: true });
3079
- writeFileSync(path, JSON.stringify(settings, null, 2) + "\n", "utf8");
3860
+ mkdirSync3(dirname(path), { recursive: true });
3861
+ writeFileSync2(path, JSON.stringify(settings, null, 2) + "\n", "utf8");
3080
3862
  return {
3081
3863
  action: "written",
3082
3864
  path,
@@ -3097,7 +3879,7 @@ function initHook(opts = {}) {
3097
3879
  let settings = {};
3098
3880
  if (existsSync(path)) {
3099
3881
  try {
3100
- settings = JSON.parse(readFileSync2(path, "utf8"));
3882
+ settings = JSON.parse(readFileSync3(path, "utf8"));
3101
3883
  } catch {
3102
3884
  return {
3103
3885
  action: "manual",
@@ -3107,8 +3889,10 @@ ${snippet}`
3107
3889
  };
3108
3890
  }
3109
3891
  }
3110
- const hooks = settings.hooks ??= {};
3111
- const matchers = hooks[HOOK_EVENT] ??= [];
3892
+ settings.hooks ??= {};
3893
+ const hooks = settings.hooks;
3894
+ hooks[HOOK_EVENT] ??= [];
3895
+ const matchers = hooks[HOOK_EVENT];
3112
3896
  const already = matchers.some(
3113
3897
  (m) => (m.hooks ?? []).some((h) => typeof h.command === "string" && h.command.includes("claudinho"))
3114
3898
  );
@@ -3117,8 +3901,8 @@ ${snippet}`
3117
3901
  }
3118
3902
  backupOnce(path);
3119
3903
  matchers.push({ hooks: [{ type: "command", command }] });
3120
- mkdirSync2(dirname(path), { recursive: true });
3121
- writeFileSync(path, JSON.stringify(settings, null, 2) + "\n", "utf8");
3904
+ mkdirSync3(dirname(path), { recursive: true });
3905
+ writeFileSync2(path, JSON.stringify(settings, null, 2) + "\n", "utf8");
3122
3906
  return {
3123
3907
  action: "written",
3124
3908
  path,
@@ -3130,6 +3914,45 @@ ${snippet}`
3130
3914
  function adapterFor({ cfg, adapter }) {
3131
3915
  return adapter ?? makeAdapter(cfg.source);
3132
3916
  }
3917
+ var DEFAULT_ON_MARKET_OPTS = { deadlineMs: 2e3, timeoutMs: 2500 };
3918
+ var MARKETS_CMD_OPTS = { deadlineMs: 12e3, timeoutMs: 6e3 };
3919
+ async function marketSignalsFor(ctx, matches, opts = {}) {
3920
+ if (ctx.marketProvider) return (await getMarketSignals(ctx.marketProvider, matches, opts)).signals;
3921
+ const source = resolveMarketSource();
3922
+ if (source !== "polymarket") {
3923
+ return (await getMarketSignals(makeMarketProvider(source), matches, opts)).signals;
3924
+ }
3925
+ const competition = resolveCompetition();
3926
+ const { signals: cached, checked: cachedIds } = readMarketCache("polymarket", competition);
3927
+ const result = /* @__PURE__ */ new Map();
3928
+ const miss = [];
3929
+ for (const m of matches) {
3930
+ const hit = cached.get(m.id);
3931
+ if (hit) result.set(m.id, hit);
3932
+ else if (!cachedIds.has(m.id)) miss.push(m);
3933
+ }
3934
+ if (miss.length > 0) {
3935
+ const { signals: fetched, checked } = await getMarketSignals(
3936
+ makeMarketProvider("polymarket"),
3937
+ miss,
3938
+ opts
3939
+ );
3940
+ writeMarketCache("polymarket", competition, [...checked], fetched);
3941
+ for (const [id, s] of fetched) result.set(id, s);
3942
+ }
3943
+ return result;
3944
+ }
3945
+ async function reliableMarketSignals(ctx, matches) {
3946
+ if (ctx.cfg.markets === false) return /* @__PURE__ */ new Map();
3947
+ const raw = await marketSignalsFor(ctx, matches, DEFAULT_ON_MARKET_OPTS);
3948
+ const now = /* @__PURE__ */ new Date();
3949
+ const out2 = /* @__PURE__ */ new Map();
3950
+ for (const [id, s] of raw) if (isReliableMarketSignal(s, { now })) out2.set(id, s);
3951
+ return out2;
3952
+ }
3953
+ async function reliableMarketSignalFor(ctx, match) {
3954
+ return (await reliableMarketSignals(ctx, [match])).get(match.id);
3955
+ }
3133
3956
  function out(line2 = "") {
3134
3957
  process.stdout.write(line2 + "\n");
3135
3958
  }
@@ -3154,10 +3977,17 @@ async function cmdToday(date, ctx) {
3154
3977
  precheck(cfg, t, date);
3155
3978
  const adapter = adapterFor(ctx);
3156
3979
  const targetDate = date ?? localDate((/* @__PURE__ */ new Date()).toISOString(), cfg.tz);
3157
- const { matches, degraded } = await getMatchesForDate(adapter, targetDate);
3158
- const todays = fixturesByDate(targetDate, matches);
3980
+ const { matches, degraded, source } = await getMatchesForDate(adapter, targetDate);
3981
+ const todays = fixturesByDate(targetDate, matches, cfg.tz);
3982
+ const signals = await reliableMarketSignals(ctx, todays);
3159
3983
  if (cfg.json) {
3160
- emitJson({ date: targetDate, degraded, matches: todays });
3984
+ emitJson({
3985
+ date: targetDate,
3986
+ degraded,
3987
+ source: source ?? null,
3988
+ matches: todays,
3989
+ marketSignals: Object.fromEntries(signals)
3990
+ });
3161
3991
  return;
3162
3992
  }
3163
3993
  const c = painterFor(cfg);
@@ -3168,18 +3998,24 @@ async function cmdToday(date, ctx) {
3168
3998
  if (todays.length === 0) {
3169
3999
  out(c.dim(" " + t("today.none")));
3170
4000
  } else {
3171
- for (const m of todays) out(matchLine(m, cfg, t, c));
4001
+ for (const m of todays) {
4002
+ out(matchLine(m, cfg, t, c));
4003
+ const s = signals.get(m.id);
4004
+ if (s) out(" " + c.dim(marketLine(s, m)));
4005
+ }
3172
4006
  }
3173
4007
  out();
4008
+ const src = dataSource(source, c);
4009
+ if (src) out(src);
3174
4010
  out(disclaimer(t, c));
3175
4011
  }
3176
4012
  async function cmdLive(ctx) {
3177
4013
  const { cfg, t } = ctx;
3178
4014
  precheck(cfg, t);
3179
4015
  const adapter = adapterFor(ctx);
3180
- const { matches, degraded } = await getLiveMatches(adapter);
4016
+ const { matches, degraded, source } = await getLiveMatches(adapter);
3181
4017
  if (cfg.json) {
3182
- emitJson({ degraded, matches });
4018
+ emitJson({ degraded, source: source ?? null, matches });
3183
4019
  return;
3184
4020
  }
3185
4021
  const c = painterFor(cfg);
@@ -3192,6 +4028,8 @@ async function cmdLive(ctx) {
3192
4028
  for (const m of matches) out(matchLine(m, cfg, t, c));
3193
4029
  }
3194
4030
  out();
4031
+ const src = dataSource(source, c);
4032
+ if (src) out(src);
3195
4033
  out(disclaimer(t, c));
3196
4034
  }
3197
4035
  async function cmdNext(team, { cfg, t }) {
@@ -3225,19 +4063,21 @@ async function cmdTable(group, ctx) {
3225
4063
  const { cfg, t } = ctx;
3226
4064
  precheck(cfg, t);
3227
4065
  const adapter = adapterFor(ctx);
3228
- let matches = allFixtures();
3229
- try {
3230
- const live = await adapter.fetchByDate(localDate((/* @__PURE__ */ new Date()).toISOString(), cfg.tz));
3231
- matches = mergeLive(matches, live);
3232
- } catch {
3233
- }
4066
+ const { matches, degraded, source } = await getMatchesForDate(
4067
+ adapter,
4068
+ localDate((/* @__PURE__ */ new Date()).toISOString(), cfg.tz)
4069
+ );
3234
4070
  const wanted = group ? [group.toUpperCase()] : groups(matches);
3235
4071
  if (cfg.json) {
3236
4072
  const tables = wanted.map((g) => ({
3237
4073
  group: g,
3238
4074
  standings: computeStandings(fixturesByGroup(g, matches))
3239
4075
  }));
3240
- emitJson(group ? tables[0] ?? null : tables);
4076
+ emitJson({
4077
+ degraded,
4078
+ source: source ?? null,
4079
+ tables: group ? tables[0] ?? null : tables
4080
+ });
3241
4081
  return;
3242
4082
  }
3243
4083
  const c = painterFor(cfg);
@@ -3277,6 +4117,8 @@ async function cmdTable(group, ctx) {
3277
4117
  out(table.toString());
3278
4118
  }
3279
4119
  out();
4120
+ const src = dataSource(source, c);
4121
+ if (src) out(src);
3280
4122
  out(disclaimer(t, c));
3281
4123
  }
3282
4124
  function cmdPrompt({ cfg }) {
@@ -3287,9 +4129,9 @@ function cmdPrompt({ cfg }) {
3287
4129
  );
3288
4130
  const maxRaw = Number.parseInt(process.env.CLAUDINHO_MAX ?? "", 10);
3289
4131
  const max = Number.isFinite(maxRaw) && maxRaw > 0 ? maxRaw : void 0;
3290
- const state = readState();
4132
+ const state = readCurrentState(cfg.source, resolveCompetition());
3291
4133
  out(renderPrompt(state, { team, compact, max }));
3292
- if (shouldRefresh()) spawnRefresh(cfg.source);
4134
+ if (!state || shouldRefresh()) spawnRefresh(cfg.source);
3293
4135
  } catch {
3294
4136
  out("");
3295
4137
  }
@@ -3297,9 +4139,10 @@ function cmdPrompt({ cfg }) {
3297
4139
  function cmdHook({ cfg }) {
3298
4140
  try {
3299
4141
  const team = process.env.CLAUDINHO_TEAM;
3300
- const ctx = hookContext({ team });
4142
+ const state = readCurrentState(cfg.source, resolveCompetition());
4143
+ const ctx = renderHook(state, { team });
3301
4144
  if (ctx) out(ctx);
3302
- if (shouldRefresh()) spawnRefresh(cfg.source);
4145
+ if (!state || shouldRefresh()) spawnRefresh(cfg.source);
3303
4146
  } catch {
3304
4147
  }
3305
4148
  }
@@ -3331,15 +4174,18 @@ async function cmdMatch(id, ctx) {
3331
4174
  precheck(cfg, t);
3332
4175
  const adapter = adapterFor(ctx);
3333
4176
  let match = allFixtures().find((m) => m.id === id);
4177
+ let liveSource;
3334
4178
  try {
3335
4179
  if (match) {
3336
4180
  const live = await adapter.fetchByDate(match.kickoff.slice(0, 10));
3337
4181
  match = live.find((m) => m.id === id) ?? match;
4182
+ liveSource = adapter.name;
3338
4183
  }
3339
4184
  } catch {
3340
4185
  }
4186
+ const marketSignal = match ? await reliableMarketSignalFor(ctx, match) : void 0;
3341
4187
  if (cfg.json) {
3342
- emitJson({ match: match ?? null });
4188
+ emitJson({ match: match ?? null, source: liveSource ?? null, marketSignal: marketSignal ?? null });
3343
4189
  return;
3344
4190
  }
3345
4191
  const c = painterFor(cfg);
@@ -3352,21 +4198,150 @@ async function cmdMatch(id, ctx) {
3352
4198
  }
3353
4199
  const stageLabel = match.group ? `${match.stage} ${match.group}` : match.stage;
3354
4200
  out(header(`${match.home.name} ${scoreline(match)} ${match.away.name}`, c));
3355
- out(" " + c.dim(`${stageLabel} \xB7 ${match.venue}`));
4201
+ out(" " + c.dim(`${stageLabel} \xB7 ${matchLocation(match)}`));
3356
4202
  out(
3357
4203
  " " + c.dim(
3358
4204
  `${formatKickoff(match.kickoff, { tz: cfg.tz, locale: cfg.lang })} ${statusToken(match, t, c)}`.trimEnd()
3359
4205
  )
3360
4206
  );
4207
+ const flair = matchFlavor(match, { level: cfg.flavor, locale: cfg.lang });
4208
+ if (flair) out(" " + c.cyan(flair));
3361
4209
  if (match.events?.length) {
3362
4210
  out();
3363
4211
  for (const e of match.events) {
3364
4212
  out(` ${e.minute}' ${e.type} ${e.teamCode}${e.player ? ` \u2014 ${e.player}` : ""}`);
3365
4213
  }
3366
4214
  }
4215
+ if (marketSignal) {
4216
+ out();
4217
+ for (const mline of marketBlock(marketSignal, match)) out(" " + c.dim(mline));
4218
+ }
3367
4219
  out();
4220
+ const src = dataSource(liveSource, c);
4221
+ if (src) out(src);
3368
4222
  out(disclaimer(t, c));
3369
4223
  }
4224
+ var MARKET_INFO = "Prediction-market data is informational only.";
4225
+ function marketDisplayable(sig) {
4226
+ return !sig.ambiguous && sig.favorite != null && hasSaneDistribution(sig.outcomes);
4227
+ }
4228
+ function marketHeaderLine(m) {
4229
+ return `${m.home.flag} ${m.home.name} vs ${m.away.name} ${m.away.flag}`;
4230
+ }
4231
+ function printMarketBlock(m, sig, c) {
4232
+ for (const line2 of marketBlock(sig, m)) out(" " + c.dim(line2));
4233
+ }
4234
+ async function cmdMarkets(target, team, ctx) {
4235
+ const { cfg, t } = ctx;
4236
+ if (target === "next") {
4237
+ precheck(cfg, t);
4238
+ if (!team) throw new InputError("Usage: claudinho markets next <team>");
4239
+ const code = team.toUpperCase();
4240
+ const fixture = nextFixtureForTeam(code);
4241
+ const sig = fixture ? (await marketSignalsFor(ctx, [fixture], MARKETS_CMD_OPTS)).get(fixture.id) : void 0;
4242
+ const shown = sig && marketDisplayable(sig) ? sig : void 0;
4243
+ if (cfg.json) {
4244
+ emitJson({
4245
+ team: code,
4246
+ matchId: fixture?.id ?? null,
4247
+ informationalOnly: true,
4248
+ signal: shown ?? null
4249
+ });
4250
+ return;
4251
+ }
4252
+ const c2 = painterFor(cfg);
4253
+ out();
4254
+ if (!fixture) {
4255
+ out(c2.dim(" " + t("next.none", { team: code })));
4256
+ } else {
4257
+ out(header(marketHeaderLine(fixture), c2));
4258
+ out();
4259
+ if (shown) printMarketBlock(fixture, shown, c2);
4260
+ else out(c2.dim(" No market signal for this match."));
4261
+ }
4262
+ out();
4263
+ out(disclaimer(t, c2));
4264
+ out(c2.dim(MARKET_INFO));
4265
+ return;
4266
+ }
4267
+ if (target && target !== "today" && !isValidDate(target)) {
4268
+ precheck(cfg, t);
4269
+ const match = allFixtures().find((m) => m.id === target);
4270
+ const sig = match ? (await marketSignalsFor(ctx, [match], MARKETS_CMD_OPTS)).get(match.id) : void 0;
4271
+ const shown = sig && marketDisplayable(sig) ? sig : void 0;
4272
+ if (cfg.json) {
4273
+ emitJson({ matchId: target, informationalOnly: true, signal: shown ?? null });
4274
+ return;
4275
+ }
4276
+ const c2 = painterFor(cfg);
4277
+ out();
4278
+ if (!match) {
4279
+ out(c2.dim(" " + t("match.none", { id: target })));
4280
+ } else {
4281
+ out(header(marketHeaderLine(match), c2));
4282
+ out();
4283
+ if (shown) printMarketBlock(match, shown, c2);
4284
+ else out(c2.dim(" No market signal for this match."));
4285
+ }
4286
+ out();
4287
+ out(disclaimer(t, c2));
4288
+ out(c2.dim(MARKET_INFO));
4289
+ return;
4290
+ }
4291
+ const explicitDate = target && target !== "today" ? target : void 0;
4292
+ precheck(cfg, t, explicitDate);
4293
+ const date = explicitDate ?? localDate((/* @__PURE__ */ new Date()).toISOString(), cfg.tz);
4294
+ const { matches } = await getMatchesForDate(adapterFor(ctx), date);
4295
+ const todays = fixturesByDate(date, matches, cfg.tz);
4296
+ const signals = await marketSignalsFor(ctx, todays, MARKETS_CMD_OPTS);
4297
+ const rows = todays.map((m) => ({ match: m, signal: signals.get(m.id) })).filter(
4298
+ (r) => !!r.signal && marketDisplayable(r.signal)
4299
+ );
4300
+ if (cfg.json) {
4301
+ const marketSignals = {};
4302
+ for (const r of rows) marketSignals[r.match.id] = r.signal;
4303
+ emitJson({ date, informationalOnly: true, marketSignals });
4304
+ return;
4305
+ }
4306
+ const c = painterFor(cfg);
4307
+ out();
4308
+ out(header(`Market signals \xB7 ${date}`, c));
4309
+ out();
4310
+ if (rows.length === 0) {
4311
+ out(c.dim(` No market signals available for ${date}.`));
4312
+ } else {
4313
+ for (const { match, signal } of rows) {
4314
+ out(" " + c.bold(marketHeaderLine(match)));
4315
+ printMarketBlock(match, signal, c);
4316
+ out();
4317
+ }
4318
+ }
4319
+ out(disclaimer(t, c));
4320
+ out(c.dim(MARKET_INFO));
4321
+ }
4322
+ var VIBES = [
4323
+ "Shipping code, watching goals.",
4324
+ "Green tests, green pitch.",
4325
+ "Pelota al pie, manos al teclado.",
4326
+ "Refactoring through the group stage.",
4327
+ "Merge conflicts can wait \u2014 it\u2019s matchday.",
4328
+ "One feed for the world, one vibe for the dev.",
4329
+ "Stoppage time and a clean stack trace.",
4330
+ "Coding into extra time."
4331
+ ];
4332
+ function cmdVibe(ctx) {
4333
+ const { cfg } = ctx;
4334
+ const line2 = VIBES[Math.floor(Math.random() * VIBES.length)];
4335
+ if (cfg.json) {
4336
+ emitJson({ vibe: line2, tag: "#VibingLaVidaLoca" });
4337
+ return;
4338
+ }
4339
+ const c = painterFor(cfg);
4340
+ out();
4341
+ out(" \u26BD " + c.bold(line2));
4342
+ out(" " + c.cyan("#VibingLaVidaLoca"));
4343
+ out();
4344
+ }
3370
4345
 
3371
4346
  // src/index.ts
3372
4347
  function handlePipeError(stream) {
@@ -3377,7 +4352,7 @@ function handlePipeError(stream) {
3377
4352
  }
3378
4353
  handlePipeError(process.stdout);
3379
4354
  handlePipeError(process.stderr);
3380
- var VERSION = "0.1.1";
4355
+ var VERSION = "0.3.0";
3381
4356
  var DISCLAIMER = "Claudinho is an independent fan project. Not affiliated with or endorsed by FIFA or Anthropic.";
3382
4357
  function ctxFrom(cmd) {
3383
4358
  const root = cmd.parent ?? cmd;
@@ -3392,7 +4367,8 @@ function fail(err) {
3392
4367
  process.exit(1);
3393
4368
  }
3394
4369
  var program = new Command();
3395
- program.name("claudinho").description("The 2026 football tournament in your terminal.\n" + DISCLAIMER).version(VERSION, "-v, --version").option("--lang <code>", "language: en, es, pt, fr").option("--tz <zone>", "IANA timezone, e.g. America/Mexico_City").option("--json", "output JSON (for scripting)").option("--no-color", "disable ANSI colors").option("--source <name>", "live data provider (advanced)");
4370
+ program.name("claudinho").description("The 2026 football tournament in your terminal.\n" + DISCLAIMER).version(VERSION, "-v, --version").option("--lang <code>", "language: en, es, pt, fr").option("--tz <zone>", "IANA timezone, e.g. America/Mexico_City").option("--json", "output JSON (for scripting)").option("--no-color", "disable ANSI colors").option("--source <name>", "live data provider (advanced)").option("--flavor <level>", "commentary flair: off, subtle, full (default: full)").option("--no-markets", "hide prediction-market signals (informational odds)");
4371
+ program.addHelpText("after", "\n#VibingLaVidaLoca \u26BD");
3396
4372
  program.command("today").description("show a day's fixtures (default: today)").argument("[date]", "date as YYYY-MM-DD").action(async (date, _opts, cmd) => {
3397
4373
  try {
3398
4374
  await cmdToday(date, ctxFrom(cmd));
@@ -3428,6 +4404,13 @@ program.command("match").description("show a single match by id").argument("<id>
3428
4404
  fail(e);
3429
4405
  }
3430
4406
  });
4407
+ program.command("markets").description("show prediction-market signals (read-only, informational only)").argument("[target]", 'date (YYYY-MM-DD), match id, "today", or "next"').argument("[team]", 'team code when target is "next" (e.g. MEX)').action(async (target, team, _opts, cmd) => {
4408
+ try {
4409
+ await cmdMarkets(target, team, ctxFrom(cmd));
4410
+ } catch (e) {
4411
+ fail(e);
4412
+ }
4413
+ });
3431
4414
  program.command("prompt").description("print a one-line status (Claude Code statusline, tmux, Starship, \u2026)").action((_opts, cmd) => {
3432
4415
  cmdPrompt(ctxFrom(cmd));
3433
4416
  });
@@ -3448,6 +4431,9 @@ program.command("init-hook").description("wire the live-score hook into Claude C
3448
4431
  fail(e);
3449
4432
  }
3450
4433
  });
4434
+ program.command("vibe").description("print a matchday-coder one-liner (#VibingLaVidaLoca)").action((_opts, cmd) => {
4435
+ cmdVibe(ctxFrom(cmd));
4436
+ });
3451
4437
  var refreshCmd = new Command("_refresh").description("(internal) refresh the statusline cache").action(async (_opts, cmd) => {
3452
4438
  try {
3453
4439
  await cmdRefresh(ctxFrom(cmd));