jaynesmax commited on
Commit
73d7a0f
Β·
verified Β·
1 Parent(s): 162c9c2

Upload index.html

Browse files
Files changed (1) hide show
  1. index.html +91 -3
index.html CHANGED
@@ -3142,10 +3142,46 @@ function safeImgHTML(urls, alt, lazy){
3142
  * matokeo tayari yamechujwa, tunayabadilisha tu kuwa muundo wa
3143
  * poster card (sawa na toCard()).
3144
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3145
  async function searchMovieBoxRaw(keyword) {
3146
- const url = SEARCH_FN_URL + '?keyword=' + encodeURIComponent(keyword);
3147
- const res = await fetch(url, { headers: { 'apikey': SUPABASE_ANON_KEY }, cache: 'no-store' });
3148
- const arr = await res.json();
 
 
 
 
 
 
 
 
3149
  if (!Array.isArray(arr)) return [];
3150
  return arr.map(x => {
3151
  const year = x.releaseDate ? String(x.releaseDate).slice(0, 4) : null;
@@ -4254,7 +4290,58 @@ async function shareTranslatedTitle(d) {
4254
  // ── MICHEZO (fawa-live) ──
4255
  // Inarudisha orodha bapa (flat) ya mechi zote β€” inatumika na loadSports()
4256
  // (kuonyesha kwa rails, kikundi kwa ligi) na search (kuchuja kwa query).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4257
  async function fetchAllSportsItemsRaw() {
 
 
 
 
 
 
 
 
 
4258
  const res = await fetch(FAWA_BASE + '/matches', { headers: { Authorization: 'Bearer ' + FAWA_KEY } });
4259
  if (!res.ok) throw new Error(T('err_generic') + ' ' + res.status);
4260
  const d = await res.json();
@@ -6402,6 +6489,7 @@ async function playHlsUrl(url, opts = {}) {
6402
  }
6403
 
6404
  async function openFawaMatch(item) {
 
6405
  openPlayerShell(item.title);
6406
  // Jaribu Worker (Cloudflare) kwanza; ikishindwa (mf. 502) jaribu Supabase
6407
  let url, opts, r = null;
 
3142
  * matokeo tayari yamechujwa, tunayabadilisha tu kuwa muundo wa
3143
  * poster card (sawa na toCard()).
3144
  */
3145
+ // Fallback: 'movies.search' ya dodolive kupitia jaynes-max-tv-api-. Muundo wa jibu
3146
+ // haujulikani kwa hakika, kwa hiyo tunapitia jibu lote kutafuta objects zenye id + title + picha.
3147
+ function collectDodoSubjects(node, depth, seen, out) {
3148
+ if (node == null || depth > 10) return;
3149
+ if (Array.isArray(node)) { node.forEach(n => collectDodoSubjects(n, depth + 1, seen, out)); return; }
3150
+ if (typeof node !== 'object') return;
3151
+ const o = (node.subject && typeof node.subject === 'object') ? node.subject : node;
3152
+ const id = o.subjectId != null ? o.subjectId : o.id;
3153
+ const title = typeof o.title === 'string' ? o.title : (typeof o.name === 'string' ? o.name : '');
3154
+ const cover = (o.cover && o.cover.url) || o.poster || o.coverUrl || o.image || null;
3155
+ if (id != null && title && cover && !seen.has(String(id))) {
3156
+ seen.add(String(id));
3157
+ out.push({
3158
+ id: String(id), title, cover: typeof cover === 'string' ? cover : null,
3159
+ genre: o.genre ?? null, rating: o.imdbRatingValue ?? o.rating ?? null,
3160
+ releaseDate: o.releaseDate ?? o.year ?? null, subjectType: o.subjectType ?? null,
3161
+ detailPath: o.detailPath ?? null, description: o.description ?? null,
3162
+ });
3163
+ }
3164
+ Object.keys(node).forEach(k => collectDodoSubjects(node[k], depth + 1, seen, out));
3165
+ }
3166
+ async function searchViaDodo(keyword) {
3167
+ const r = await rpcRaw('movies.search', { keyword, keywords: keyword, query: keyword, q: keyword, page: 1, perPage: 20 });
3168
+ const out = [];
3169
+ collectDodoSubjects(r && r.data !== undefined ? r.data : r, 0, new Set(), out);
3170
+ return out;
3171
+ }
3172
+
3173
  async function searchMovieBoxRaw(keyword) {
3174
+ let arr = [];
3175
+ try {
3176
+ const url = SEARCH_FN_URL + '?keyword=' + encodeURIComponent(keyword);
3177
+ const res = await fetch(url, { headers: { 'apikey': SUPABASE_ANON_KEY }, cache: 'no-store' });
3178
+ const j = await res.json();
3179
+ if (Array.isArray(j)) arr = j;
3180
+ } catch (_) {}
3181
+ // movie-box ikirudisha tupu au kushindwa -> jaribu dodolive
3182
+ if (!arr.length) {
3183
+ try { arr = await searchViaDodo(keyword); } catch (_) {}
3184
+ }
3185
  if (!Array.isArray(arr)) return [];
3186
  return arr.map(x => {
3187
  const year = x.releaseDate ? String(x.releaseDate).slice(0, 4) : null;
 
4290
  // ── MICHEZO (fawa-live) ──
4291
  // Inarudisha orodha bapa (flat) ya mechi zote β€” inatumika na loadSports()
4292
  // (kuonyesha kwa rails, kikundi kwa ligi) na search (kuchuja kwa query).
4293
+ // ── EMBEDS za Michezo: YouTube Live (inachezwa ndani ya app) na WhatsApp (kiungo cha kufungua nje) ──
4294
+ // Hariri orodha hii tu. type: 'youtube' | 'whatsapp'
4295
+ // youtube : url = kiungo cha YouTube (watch?v=, youtu.be/, /live/, /embed/) AU channel ID (UC...)
4296
+ // whatsapp: url = kiungo cha WhatsApp Channel / group / wa.me (haiwezi ku-embed β€” inafunguliwa nje)
4297
+ const SPORTS_EMBEDS = [
4298
+ // { type: 'youtube', title: 'Mechi Live', url: 'https://www.youtube.com/watch?v=VIDEO_ID', league: 'Live YouTube', time: 'LIVE' },
4299
+ // { type: 'whatsapp', title: 'Kundi la Mechi', url: 'https://whatsapp.com/channel/XXXXXXXX', league: 'WhatsApp' },
4300
+ ];
4301
+ function youtubeEmbedUrl(u) {
4302
+ u = String(u || '').trim();
4303
+ let id = null, channel = null;
4304
+ if (/^UC[\w-]{22}$/.test(u)) channel = u;
4305
+ else {
4306
+ const m = u.match(/(?:youtu\.be\/|[?&]v=|\/embed\/|\/live\/|\/shorts\/)([\w-]{11})/);
4307
+ if (m) id = m[1];
4308
+ else if (/^[\w-]{11}$/.test(u)) id = u;
4309
+ else { const c = u.match(/channel\/(UC[\w-]{22})/); if (c) channel = c[1]; }
4310
+ }
4311
+ if (id) return 'https://www.youtube.com/embed/' + id + '?autoplay=1&playsinline=1&rel=0&modestbranding=1';
4312
+ if (channel) return 'https://www.youtube.com/embed/live_stream?channel=' + channel + '&autoplay=1&playsinline=1&rel=0';
4313
+ return null;
4314
+ }
4315
+ function sportsEmbedItems() {
4316
+ return SPORTS_EMBEDS.map((e, i) => ({
4317
+ id: 'embed-' + i, kind: 'sport', title: e.title, poster: e.poster || null,
4318
+ subtitle: e.time || (e.type === 'youtube' ? 'LIVE' : 'WhatsApp'), imgFallbackOn: true,
4319
+ _league: e.league || (e.type === 'youtube' ? 'Live YouTube' : 'WhatsApp'), _embed: e
4320
+ }));
4321
+ }
4322
+ function openSportsEmbed(item) {
4323
+ const e = item._embed;
4324
+ openPlayerShell(item.title);
4325
+ if (e.type === 'youtube') {
4326
+ const src = youtubeEmbedUrl(e.url);
4327
+ if (!src) return statusMsg('Kiungo cha YouTube si sahihi.');
4328
+ stage.innerHTML = '<iframe allowfullscreen allow="autoplay; encrypted-media; picture-in-picture; fullscreen" referrerpolicy="strict-origin-when-cross-origin" src="' + esc(src) + '"></iframe>';
4329
+ } else {
4330
+ stage.innerHTML = '<div class="status">WhatsApp hairuhusu video kuwekwa ndani ya app.<br><br>' +
4331
+ '<a href="' + esc(e.url) + '" target="_blank" rel="noopener" style="display:inline-block;padding:12px 20px;border-radius:999px;background:#25d366;color:#04210f;font-weight:800;text-decoration:none">Fungua WhatsApp</a></div>';
4332
+ }
4333
+ }
4334
+
4335
  async function fetchAllSportsItemsRaw() {
4336
+ const embeds = sportsEmbedItems();
4337
+ try {
4338
+ return (await fetchFawaMatchItems()).concat(embeds);
4339
+ } catch (e) {
4340
+ if (embeds.length) return embeds; // fawa-live ikishindwa, embeds bado zinaonekana
4341
+ throw e;
4342
+ }
4343
+ }
4344
+ async function fetchFawaMatchItems() {
4345
  const res = await fetch(FAWA_BASE + '/matches', { headers: { Authorization: 'Bearer ' + FAWA_KEY } });
4346
  if (!res.ok) throw new Error(T('err_generic') + ' ' + res.status);
4347
  const d = await res.json();
 
6489
  }
6490
 
6491
  async function openFawaMatch(item) {
6492
+ if (item && item._embed) return openSportsEmbed(item);
6493
  openPlayerShell(item.title);
6494
  // Jaribu Worker (Cloudflare) kwanza; ikishindwa (mf. 502) jaribu Supabase
6495
  let url, opts, r = null;