PageSourceSearch

https://xoilacwf.com/wp-content/plugins/s8-live-football-0.3.90/assets/js/s8-live-football-data.js?ver=0.3.90

js xoilacwf.com collected 2026-10-10 02:43:51 UTC 10,570 bytes, 314 lines download raw bytes

1(function (root, factory) {
2  const api = factory();
3
4  if (typeof module === 'object' && module.exports) {
5    module.exports = api;
6  }
7
8  if (root) {
9    root.S8LiveFootballData = api;
10  }
11})(typeof globalThis !== 'undefined' ? globalThis : this, function () {
12  const SPORTSCORE_ORIGIN = 'https://sportscore.com';
13  const FIXTURE_PUBLIC_CODE_PATTERN = /^[0-9a-hjkmnp-tv-z]{12}$/i;
14  const FIXTURE_LEGACY_UUID_PATTERN =
15    /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
16  const OVERTIME_SCORE_STATUS_IDS = new Set([5, 6, 7]);
17  const ENDED_STATUS_ID = 8;
18
19  function cleanText(value) {
20    return typeof value === 'string' ? value.trim() : '';
21  }
22
23  function normalizeFixturePublicId(value) {
24    const normalized = cleanText(String(value || '')).toLowerCase();
25    return FIXTURE_PUBLIC_CODE_PATTERN.test(normalized) ||
26      FIXTURE_LEGACY_UUID_PATTERN.test(normalized)
27      ? normalized
28      : '';
29  }
30
31  function getFixturePublicId(fixture) {
32    if (!fixture || typeof fixture !== 'object') return '';
33
34    return (
35      normalizeFixturePublicId(fixture.public_code) ||
36      normalizeFixturePublicId(fixture.public_id) ||
37      normalizeFixturePublicId(fixture.id)
38    );
39  }
40
41  function fixtureHasStreamKey(fixture, streamKey) {
42    const target = cleanText(String(streamKey || ''));
43    if (!target || !fixture || typeof fixture !== 'object') return false;
44
45    const streams = Array.isArray(fixture.streams)
46      ? fixture.streams
47      : Array.isArray(fixture.OBS_stream_key)
48        ? fixture.OBS_stream_key
49        : [];
50
51    return streams.some((stream) => cleanText(String(stream?.stream_key || '')) === target);
52  }
53
54  function resolveFixtureReference(fixtures, fixtureId, streamKey) {
55    const items = Array.isArray(fixtures) ? fixtures : [];
56    const publicId = normalizeFixturePublicId(fixtureId);
57
58    if (publicId) {
59      const exact = items.find((fixture) => getFixturePublicId(fixture) === publicId);
60      if (exact) return exact;
61    }
62
63    // Numeric IDs existed in plugin URLs before public fixture identifiers.
64    // The stream key is immutable and unique per live room, so it can recover
65    // those bookmarks without exposing or re-enabling sequential CMS IDs.
66    return items.find((fixture) => fixtureHasStreamKey(fixture, streamKey)) || null;
67  }
68
69  function removeVietnameseToneMarks(value) {
70    return value
71      .normalize('NFD')
72      .replace(/[\u0300-\u036f]/g, '')
73      .replace(/[\u0111\u0110]/g, 'd');
74  }
75
76  function sportScoreSlugPart(value) {
77    return removeVietnameseToneMarks(cleanText(value))
78      .toLowerCase()
79      .replace(/['\u2019]/g, '')
80      .replace(/[^a-z0-9]+/g, '-')
81      .replace(/^-+|-+$/g, '')
82      .replace(/-{2,}/g, '-');
83  }
84
85  function getExplicitSportScoreSlug(fixture) {
86    return (
87      cleanText(fixture?.sportscore_slug) ||
88      cleanText(fixture?.sportScoreSlug) ||
89      cleanText(fixture?.sportscoreSlug)
90    );
91  }
92
93  function getExplicitSportScoreTrackerUrl(fixture) {
94    const rawUrl = cleanText(fixture?.sportscore_tracker_url);
95    if (!rawUrl) return '';
96
97    try {
98      const url = new URL(rawUrl);
99      if (url.origin !== SPORTSCORE_ORIGIN) return '';
100      if (!url.pathname.startsWith('/embed/tracker/football/')) return '';
101
102      // `src=s8tv` was an internal attribution experiment, not part of the
103      // provider's documented embed contract. Keep existing CMS rows compatible.
104      url.searchParams.delete('src');
105      return url.toString();
106    } catch {
107      return '';
108    }
109  }
110
111  function getFixtureSportScoreSlug(fixture) {
112    // A valid-looking "home-vs-away" guess can point at another match or at
113    // SportScore's unavailable page. Only the worker/CMS mapping is trusted.
114    return sportScoreSlugPart(getExplicitSportScoreSlug(fixture));
115  }
116
117  function buildSportScoreTrackerUrl(slug, theme) {
118    const safeSlug = sportScoreSlugPart(slug);
119    if (!safeSlug) return '';
120
121    const url = new URL(`/embed/tracker/football/${safeSlug}/`, SPORTSCORE_ORIGIN);
122    url.searchParams.set('theme', theme === 'light' ? 'light' : 'dark');
123    return url.toString();
124  }
125
126  function getFixtureTrackerUrl(fixture, theme) {
127    const explicitUrl = getExplicitSportScoreTrackerUrl(fixture);
128    if (explicitUrl) return explicitUrl;
129
130    return buildSportScoreTrackerUrl(getFixtureSportScoreSlug(fixture), theme);
131  }
132
133  function hasFixtureSimulationData(fixture, theme) {
134    // SportScore owns the upcoming/live/finished presentation. A verified
135    // mapping remains useful even when the score provider status is not live.
136    return Boolean(fixture && getFixtureTrackerUrl(fixture, theme));
137  }
138
139  function getFixtureScoreReference(fixtureOrReference) {
140    if (!fixtureOrReference || typeof fixtureOrReference !== 'object') return {};
141
142    const scoreReference = fixtureOrReference.score_reference_id;
143    if (scoreReference && typeof scoreReference === 'object') return scoreReference;
144
145    // An explicit empty score relation means the fixture is unmapped. Never
146    // inherit retired-provider data from another relation in that case.
147    if (Object.prototype.hasOwnProperty.call(fixtureOrReference, 'score_reference_id')) {
148      return {};
149    }
150
151    return fixtureOrReference;
152  }
153
154  function providerStatusId(fixtureOrReference) {
155    const reference = getFixtureScoreReference(fixtureOrReference);
156    const statusId = Number(reference?.status_id);
157    return Number.isFinite(statusId) ? statusId : 0;
158  }
159
160  function optionalScoreAt(scores, index) {
161    if (!Array.isArray(scores)) return null;
162    const value = scores[index];
163    if (value === undefined || value === null || value === '') return null;
164
165    const number = Number(value);
166    return Number.isFinite(number) && number >= 0 ? number : null;
167  }
168
169  function scorePairAt(homeScores, awayScores, index) {
170    const left = optionalScoreAt(homeScores, index);
171    const right = optionalScoreAt(awayScores, index);
172    return left === null || right === null ? null : { left, right, index };
173  }
174
175  function shouldUseOvertimeScore(statusId, regular, overtime) {
176    if (!overtime) return false;
177
178    // API-Football is normalized to the platform score-array contract:
179    // index 0 = regular time, index 5 = 120-minute total. Before extra time
180    // starts, index 5 can be a 0-0 placeholder and must not replace real goals.
181    const looksLikeEmptyPlaceholder =
182      overtime.left === 0 &&
183      overtime.right === 0 &&
184      regular &&
185      (regular.left > 0 || regular.right > 0);
186    if (looksLikeEmptyPlaceholder) return false;
187
188    if (OVERTIME_SCORE_STATUS_IDS.has(statusId)) return true;
189
190    return (
191      statusId === ENDED_STATUS_ID &&
192      regular &&
193      (overtime.left !== regular.left || overtime.right !== regular.right) &&
194      (overtime.left > 0 || overtime.right > 0)
195    );
196  }
197
198  function resolveFixtureMainScore(fixtureOrReference) {
199    const reference = getFixtureScoreReference(fixtureOrReference);
200    const homeScores = Array.isArray(reference.home_scores) ? reference.home_scores : [];
201    const awayScores = Array.isArray(reference.away_scores) ? reference.away_scores : [];
202    const regular = scorePairAt(homeScores, awayScores, 0);
203    const overtime = scorePairAt(homeScores, awayScores, 5);
204
205    if (shouldUseOvertimeScore(providerStatusId(reference), regular, overtime)) {
206      return { ...overtime, source: 'overtime' };
207    }
208
209    return regular ? { ...regular, source: 'regular' } : null;
210  }
211
212  function normalizePreviewElapsed(value) {
213    const rawValue =
214      value && typeof value === 'object' && !Array.isArray(value)
215        ? value.elapsedMs
216        : value;
217    const elapsedMs = Number(rawValue);
218
219    return Number.isFinite(elapsedMs) && elapsedMs > 0 ? elapsedMs : 0;
220  }
221
222  function createPreviewGateStateMachine(options = {}) {
223    const enabled = Boolean(options.enabled);
224    const limitMs = Math.max(1, Number(options.limitMs) || 1);
225    const maxSampleMs = Math.max(250, Number(options.maxSampleMs) || 2000);
226    let elapsedMs = Math.min(limitMs, normalizePreviewElapsed(options.elapsedMs));
227    let lastTimestamp = null;
228    let state = !enabled ? 'disabled' : elapsedMs >= limitMs ? 'locked' : 'idle';
229
230    function snapshot(changed = false, lockedNow = false) {
231      return Object.freeze({
232        state,
233        elapsedMs,
234        remainingMs: Math.max(0, limitMs - elapsedMs),
235        changed,
236        locked: state === 'locked',
237        lockedNow,
238      });
239    }
240
241    function lock(changed) {
242      const lockedNow = state !== 'locked';
243      elapsedMs = limitMs;
244      state = 'locked';
245      lastTimestamp = null;
246      return snapshot(changed || lockedNow, lockedNow);
247    }
248
249    function sample({ playing = false, visible = true, timestamp = 0 } = {}) {
250      if (!enabled || state === 'locked') return snapshot();
251
252      const nextTimestamp = Number(timestamp);
253      const safeTimestamp = Number.isFinite(nextTimestamp) ? nextTimestamp : 0;
254      const canCount = Boolean(playing && visible);
255
256      if (lastTimestamp === null) {
257        lastTimestamp = safeTimestamp;
258        state = canCount ? 'counting' : 'paused';
259        return snapshot();
260      }
261
262      const deltaMs = Math.max(0, safeTimestamp - lastTimestamp);
263      lastTimestamp = safeTimestamp;
264      state = canCount ? 'counting' : 'paused';
265
266      if (!canCount || deltaMs <= 0) return snapshot();
267
268      const addedMs = Math.min(deltaMs, maxSampleMs);
269      elapsedMs = Math.min(limitMs, elapsedMs + addedMs);
270      if (elapsedMs >= limitMs) return lock(addedMs > 0);
271
272      return snapshot(addedMs > 0);
273    }
274
275    function sync(value) {
276      if (!enabled || state === 'locked') return snapshot();
277
278      const nextElapsedMs = Math.min(limitMs, normalizePreviewElapsed(value));
279      if (nextElapsedMs <= elapsedMs) return snapshot();
280
281      elapsedMs = nextElapsedMs;
282      if (elapsedMs >= limitMs) return lock(true);
283
284      return snapshot(true);
285    }
286
287    function pause(timestamp = 0) {
288      return sample({ playing: false, visible: false, timestamp });
289    }
290
291    return Object.freeze({
292      getSnapshot: () => snapshot(),
293      pause,
294      sample,
295      sync,
296    });
297  }
298
299  return Object.freeze({
300    createPreviewGateStateMachine,
301    fixtureHasStreamKey,
302    getExplicitSportScoreTrackerUrl,
303    getFixturePublicId,
304    getFixtureSportScoreSlug,
305    getFixtureTrackerUrl,
306    getFixtureScoreReference,
307    hasFixtureSimulationData,
308    providerStatusId,
309    normalizePreviewElapsed,
310    normalizeFixturePublicId,
311    resolveFixtureReference,
312    resolveFixtureMainScore,
313  });
314});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.