bep40 commited on
Commit
a7fa25a
·
verified ·
1 Parent(s): 26f8fe9

Upload app_patch_unified.py

Browse files
Files changed (1) hide show
  1. app_patch_unified.py +60 -24
app_patch_unified.py CHANGED
@@ -11,6 +11,7 @@ Features:
11
  4. Rewrite auto-title, no "xem trên VNEWS" junk
12
  5. Topic post uses source og:image instead of AI image
13
  6. Fast homepage load (non-blocking)
 
14
  """
15
  from ai_runtime_patch_fast import *
16
  from ai_runtime_patch_fast import app, f5, f6, rt, PATCH_INJECT, _scrape, _domain, clean, _bg, _bg_home, _bg_shorts
@@ -74,6 +75,29 @@ def _source_image(sources, details):
74
  def _ensure_img(img):
75
  return img if (img and len(img)>20 and img.startswith('http')) else DEFAULT_IMG
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  # ============================================================
78
  # TOPIC POST (source image instead of AI image)
79
  # ============================================================
@@ -99,7 +123,7 @@ async def _topic(request:Request):
99
  return JSONResponse({'post':post})
100
 
101
  # ============================================================
102
- # REWRITE (auto-title, clean text)
103
  # ============================================================
104
  @app.post('/api/rewrite_share')
105
  @app.post('/api/url_wall')
@@ -110,6 +134,27 @@ async def _rewrite(request:Request):
110
  if len(raw)<50:raw=ctx[:14000]
111
  if len(raw)<50:return JSONResponse({'error':'Không đọc được bài'},status_code=422)
112
  img=_ensure_img(img)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  prompt=f"""Tóm tắt bài viết thành bản tin ngắn. Dòng đầu tiên là tiêu đề mới hấp dẫn (tự đặt, không copy gốc).
114
 
115
  Tiêu đề gốc: {title}
@@ -130,7 +175,17 @@ Yêu cầu:
130
  lines=text.strip().split('\n')
131
  body='\n'.join(lines[1:]).strip() if lines and lines[0].strip()==ai_title else text
132
  post=f5.base.make_post(ai_title,_clean_text(body),img,url,'rewrite',sources=[{'title':title,'url':url,'via':_domain(url)}])
 
 
133
  ps=f5.base._load_ai_wall();ps.insert(0,post);f5.base._save_ai_wall(ps)
 
 
 
 
 
 
 
 
134
  return JSONResponse({'post':post})
135
 
136
  @app.post('/api/topic/rewrite')
@@ -177,19 +232,13 @@ Object.defineProperty(window,'renderAIShortHome',{get:function(){return function
177
  Object.defineProperty(window,'renderAIShorts7',{get:function(){return function(){}},set:function(){},configurable:true});
178
  </script>
179
  <style>
180
- /* Tiktok right panel for shorts/highlights */
181
  .tiktok-slide{position:relative!important}
182
  .tiktok-right{position:absolute!important;right:8px!important;bottom:100px!important;display:flex!important;flex-direction:column!important;align-items:center!important;gap:14px!important;z-index:5!important}
183
  .tiktok-right-btn{display:flex!important;flex-direction:column!important;align-items:center!important;gap:2px!important;background:none!important;border:0!important;color:#fff!important;cursor:pointer!important}
184
  .tiktok-right-btn .icon{width:42px!important;height:42px!important;border-radius:50%!important;background:rgba(255,255,255,.12)!important;display:flex!important;align-items:center!important;justify-content:center!important;font-size:20px!important}
185
  .tiktok-right-btn .count{font-size:10px!important;color:#ddd!important}
186
- /* Highlight: TikTok feed with 1:1 crop center */
187
- .tiktok-slide video{object-fit:cover!important}
188
- /* Hide duplicate slides/walls from old layers */
189
  #ai-short-home,.ai-short-home,.ai-short-card-final,[id*="ai-shorts-patched"]{display:none!important}
190
- /* Progress toast */
191
  #short-progress-toast{position:fixed;bottom:70px;left:50%;transform:translateX(-50%);background:#2d8659;color:#fff;padding:10px 20px;border-radius:20px;font-size:12px;z-index:99998;box-shadow:0 4px 12px rgba(0,0,0,.4);display:none}
192
- /* Source details */
193
  .source-detail-box{margin-top:14px;background:#151515;border:1px solid #2b2b2b;border-radius:10px;padding:10px}
194
  .source-detail-item{background:#202020;border-radius:8px;padding:9px;margin:7px 0;cursor:pointer}
195
  .source-detail-item:active{opacity:.8}
@@ -197,26 +246,19 @@ Object.defineProperty(window,'renderAIShorts7',{get:function(){return function()
197
  .source-detail-content{font-size:11px;color:#bbb;line-height:1.4;max-height:80px;overflow:hidden;margin-top:4px}
198
  .source-detail-item img{width:100%;aspect-ratio:16/9;object-fit:cover;border-radius:6px;margin-bottom:6px;background:#222}
199
  .source-vnews-btn{display:inline-block;margin-top:6px;background:#2d8659;color:#fff;padding:4px 10px;border-radius:10px;font-size:10px;font-weight:700}
200
- /* Livescore */
201
- .ls-content{max-height:480px;overflow-y:auto;padding:0 6px 8px;font-size:12px;color:#ddd}.ls-content ul{list-style:none;padding:0;margin:0}.ls-content .title-content{display:flex;gap:6px;align-items:center;background:#222;border-radius:4px;margin:4px 0;padding:5px 8px}.ls-content .title-content img{width:18px;height:18px}.ls-content .title-content strong{font-size:11px;color:#ccc}.ls-content .match-detail{padding:6px;border-bottom:1px solid #262626;cursor:pointer}.ls-content .match-detail:hover{background:#1a2a1f}.ls-content .match{display:flex;flex-wrap:wrap;align-items:center;gap:4px}.ls-content .datetime{width:100%;font-size:9px;color:#888}.ls-content .teams{display:flex;width:100%;align-items:center;gap:4px}.ls-content .team{flex:1;display:flex;align-items:center;gap:4px;min-width:0}.ls-content .team .name{font-size:11px;color:#ddd;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ls-content .team .logo img{width:18px;height:18px}.ls-content .home-team{justify-content:flex-end;text-align:right}.ls-content .status{flex:0 0 54px;text-align:center}.ls-content .status a{color:#fff;text-decoration:none;font-weight:800;font-size:12px}.ls-content .status .label{font-size:8px;color:#888;display:block}.ls-content .status .label.live{color:#e74c3c}.ls-content .info,.ls-content .btns{display:none}.ls-content table,.mo-body table{width:100%;border-collapse:collapse;font-size:11px;color:#ccc}.ls-content table th,.mo-body table th{background:#222;color:#999;padding:5px 4px;font-size:10px;border-bottom:1px solid #333}.ls-content table td,.mo-body table td{padding:4px 3px;border-bottom:1px solid #1a1a1a}.ls-content table .team-name,.mo-body table .team-name{display:flex;align-items:center;gap:4px}.ls-content table .team-name img,.mo-body table .team-name img{width:16px;height:16px}.ls-content table .pts{font-weight:800;color:#f0c040}.mo-body{padding:8px;font-size:12px;color:#ddd}.mo-body ul{list-style:none;padding:0}.mo-body li{padding:5px 0;border-bottom:1px solid #222}
202
  </style>
203
  <div id="short-progress-toast"></div>
204
  <script>
205
  (function(){
206
  function esc(s){return String(s||'').replace(/[&<>"']/g,m=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[m]));}
207
-
208
- // === Progress toast ===
209
  window.showShortProgress=function(msg){var t=document.getElementById('short-progress-toast');if(t){t.textContent=msg;t.style.display='block';}};
210
  window.hideShortProgress=function(){var t=document.getElementById('short-progress-toast');if(t)t.style.display='none';};
211
  window.makeShortFromPost=async function(pid,btn){
212
  showShortProgress('⏳ Đang tạo Short AI...');if(btn){btn.disabled=true;btn.textContent='Đang tạo...';}
213
  try{var r=await fetch('/api/ai/short/'+pid,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({voice:'nu',emotion:'neutral',speed:1.2})});var j=await r.json();if(!r.ok||j.error)throw new Error(j.error||'Lỗi');showShortProgress('✅ Đã tạo!');setTimeout(hideShortProgress,3000);if(typeof renderShortAISlide==='function')renderShortAISlide();}catch(e){showShortProgress('❌ '+e.message);setTimeout(hideShortProgress,4000);}finally{if(btn){btn.disabled=false;btn.textContent='🎬 Tạo Short AI';}}
214
  };
215
-
216
- // === Remove duplicate slides ===
217
  setInterval(function(){document.querySelectorAll('#ai-short-home,.ai-short-home,[id*="ai-shorts-patched"]').forEach(function(el){if(el.id!=='short-ai-final-slide')el.remove();});},3000);
218
 
219
- // === Override openLeaguePlayer: TikTok vertical feed, 1:1 crop center ===
220
  window.openLeaguePlayer=async function(league,idx){
221
  showView('view-tiktok');document.querySelectorAll('.cat').forEach(x=>x.classList.remove('active'));
222
  var el=document.getElementById('view-tiktok');el.innerHTML='<div class="loading">Đang tải...</div>';
@@ -235,10 +277,9 @@ window.openLeaguePlayer=async function(league,idx){
235
  var isYT=v.type==='youtube';var isHLS=!isYT&&v.src&&v.src.indexOf('.m3u8')>-1;
236
  var poster=v.poster?' poster="'+v.poster+'"':'';
237
  var vtag=isYT?'<iframe data-yt-src="'+v.src+'" allowfullscreen allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture" style="width:100%;height:100%;border:none"></iframe>':isHLS?'<video playsinline preload="none"'+poster+' data-hls="'+v.src+'" loop controls style="width:100%;height:100%;object-fit:cover"></video>':'<video playsinline preload="none"'+poster+' loop controls style="width:100%;height:100%;object-fit:cover"><source src="'+v.src+'" type="video/mp4"></video>';
238
- h+='<div class="tiktok-slide" id="tslide-'+i+'">'+vtag+'<div class="tiktok-bottom"><span class="badge badge-fpt">'+esc(cfg.name)+'</span><p class="tiktok-title">'+esc(v.title)+'</p></div><div class="tiktok-right"><button class="tiktok-right-btn" onclick="event.stopPropagation()"><div class="icon">👁</div></button><button class="tiktok-right-btn" onclick="event.stopPropagation()"><div class="icon">❤️</div></button><button class="tiktok-right-btn" onclick="event.stopPropagation();if(typeof doShareVideo===\'function\')doShareVideo(\''+esc(v.title)+'\',\''+esc(v.link||'')+'\',\''+esc(v.poster||v.img||'')+'\',\'highlights\')"><div class="icon">📤</div></button></div><span class="tiktok-counter">'+(i+1)+'/'+ordered.length+'</span></div>';
239
  });
240
  h+='</div></div>';el.innerHTML=h;
241
- // Init feed
242
  var feed=document.getElementById('tiktok-feed');if(!feed)return;
243
  var slides=feed.querySelectorAll('.tiktok-slide');var cur=-1;
244
  function act(i){if(i===cur)return;slides.forEach(function(sl,idx){var v=sl.querySelector('video');var fr=sl.querySelector('iframe');if(idx===i){if(v&&v.dataset.hls){if(!v._hls&&typeof Hls!=='undefined'&&Hls.isSupported()){var hls=new Hls();hls.loadSource(v.dataset.hls);hls.attachMedia(v);hls.on(Hls.Events.MANIFEST_PARSED,function(){v.play().catch(function(){});});v._hls=hls;}else if(v._hls)v.play().catch(function(){});}else if(v)v.play().catch(function(){});if(fr&&!fr.src&&fr.dataset.ytSrc)fr.src=fr.dataset.ytSrc;}else{if(v){v.pause();if(v._hls){v._hls.destroy();v._hls=null;}}if(fr&&fr.src)fr.src='';}});cur=i;}
@@ -247,7 +288,6 @@ window.openLeaguePlayer=async function(league,idx){
247
  slides.forEach(function(sl){var v=sl.querySelector('video');if(v)v.addEventListener('click',function(e){e.preventDefault();v.paused?v.play().catch(function(){}):v.pause();});});
248
  };
249
 
250
- // === Block slow YouTube refresh on first load ===
251
  var _origFetch=window.fetch,_allowRefresh=false;
252
  window.fetch=function(url,opts){try{if(String(url).indexOf('/api/shorts?refresh=1')>-1&&!_allowRefresh)url='/api/shorts';}catch(e){}return _origFetch.call(this,url,opts);};
253
  setTimeout(function(){_allowRefresh=true;},8000);
@@ -255,19 +295,15 @@ setTimeout(function(){_allowRefresh=true;},8000);
255
  </script>
256
  '''
257
 
258
- # ============================================================
259
- # ROOT ROUTE: inject order matters
260
- # ============================================================
261
  @app.get('/')
262
  async def _index():
263
  html = f5.f4.f3.f2.f1._load_index_html()
264
- # Inject order: PRE_KILL (in UNIFIED) → old injects → PATCH_INJECT → UNIFIED
265
  body = ''
266
  body += getattr(rt.old,'PATCH_INJECT','')
267
  body += f5.f4.f3.f2.f1.FINAL_INJECT + f5.f4.f3.FINAL3_INJECT + f5.f4.FINAL4_INJECT + f5.FINAL5_INJECT
268
  body += getattr(f6,'FINAL6_INJECT','')
269
  body += getattr(f6,'FINAL6_FAST_HOME_INJECT','')
270
- body += getattr(f6,'FINAL6E_INJECT','') # Keep it — our PRE_KILL in UNIFIED neutralizes its destructive parts
271
  body += PATCH_INJECT
272
- body += UNIFIED_INJECT # This goes LAST and contains PRE_KILL at the TOP (runs first in browser)
273
- return HTMLResponse(html.replace('</body>', body + '\n</body>') if '</body>' in html else html + body)
 
11
  4. Rewrite auto-title, no "xem trên VNEWS" junk
12
  5. Topic post uses source og:image instead of AI image
13
  6. Fast homepage load (non-blocking)
14
+ 7. Rewrite generates slides with images + auto short video trigger
15
  """
16
  from ai_runtime_patch_fast import *
17
  from ai_runtime_patch_fast import app, f5, f6, rt, PATCH_INJECT, _scrape, _domain, clean, _bg, _bg_home, _bg_shorts
 
75
  def _ensure_img(img):
76
  return img if (img and len(img)>20 and img.startswith('http')) else DEFAULT_IMG
77
 
78
+ def _make_slides_from_article(url, img, all_images):
79
+ slides = []
80
+ try:
81
+ art_data = f5.base.scrape_any_url(url)
82
+ if art_data:
83
+ imgs = art_data.get('images', [])
84
+ if not imgs and art_data.get('og_image'):
85
+ imgs = [art_data.get('og_image', '')]
86
+ if not imgs and img:
87
+ imgs = [img]
88
+ paragraphs = art_data.get('text', '').split('\n')
89
+ paragraphs = [p.strip() for p in paragraphs if len(p.strip()) > 60]
90
+ key_pts = paragraphs[:8]
91
+ if key_pts:
92
+ for i, pt in enumerate(key_pts):
93
+ slide_img = imgs[i] if i < len(imgs) else (imgs[-1] if imgs else img if img else '')
94
+ slides.append({'text': pt, 'image': slide_img, 'index': i + 1})
95
+ except:
96
+ if all_images:
97
+ for i, im in enumerate(all_images[:3]):
98
+ slides.append({'text': '', 'image': im, 'index': i + 1})
99
+ return slides
100
+
101
  # ============================================================
102
  # TOPIC POST (source image instead of AI image)
103
  # ============================================================
 
123
  return JSONResponse({'post':post})
124
 
125
  # ============================================================
126
+ # REWRITE (auto-title, clean text) + SLIDES + SHORT
127
  # ============================================================
128
  @app.post('/api/rewrite_share')
129
  @app.post('/api/url_wall')
 
134
  if len(raw)<50:raw=ctx[:14000]
135
  if len(raw)<50:return JSONResponse({'error':'Không đọc được bài'},status_code=422)
136
  img=_ensure_img(img)
137
+
138
+ all_images = []
139
+ slides = []
140
+ try:
141
+ art_data = f5.base.scrape_any_url(url)
142
+ if art_data:
143
+ all_images = art_data.get('images', [])
144
+ if not all_images and art_data.get('og_image'):
145
+ all_images = [art_data.get('og_image', '')]
146
+ if not all_images:
147
+ all_images = [img] if img and img.startswith('http') else []
148
+ paragraphs = art_data.get('text', '').split('\n')
149
+ paragraphs = [p.strip() for p in paragraphs if len(p.strip()) > 60]
150
+ key_pts = paragraphs[:8]
151
+ if key_pts:
152
+ for i, pt in enumerate(key_pts):
153
+ slide_img = all_images[i] if i < len(all_images) else (all_images[-1] if all_images else img if img else '')
154
+ slides.append({'text': pt, 'image': slide_img, 'index': i + 1})
155
+ except:
156
+ all_images = [img] if img and img.startswith('http') else []
157
+
158
  prompt=f"""Tóm tắt bài viết thành bản tin ngắn. Dòng đầu tiên là tiêu đề mới hấp dẫn (tự đặt, không copy gốc).
159
 
160
  Tiêu đề gốc: {title}
 
175
  lines=text.strip().split('\n')
176
  body='\n'.join(lines[1:]).strip() if lines and lines[0].strip()==ai_title else text
177
  post=f5.base.make_post(ai_title,_clean_text(body),img,url,'rewrite',sources=[{'title':title,'url':url,'via':_domain(url)}])
178
+ post['images'] = all_images
179
+ post['slides'] = slides
180
  ps=f5.base._load_ai_wall();ps.insert(0,post);f5.base._save_ai_wall(ps)
181
+
182
+ if post.get('text') and len(post.get('text','')) > 100:
183
+ try:
184
+ import auto_scheduler
185
+ threading.Thread(target=lambda: auto_scheduler._try_generate_short(post), daemon=True).start()
186
+ except:
187
+ pass
188
+
189
  return JSONResponse({'post':post})
190
 
191
  @app.post('/api/topic/rewrite')
 
232
  Object.defineProperty(window,'renderAIShorts7',{get:function(){return function(){}},set:function(){},configurable:true});
233
  </script>
234
  <style>
 
235
  .tiktok-slide{position:relative!important}
236
  .tiktok-right{position:absolute!important;right:8px!important;bottom:100px!important;display:flex!important;flex-direction:column!important;align-items:center!important;gap:14px!important;z-index:5!important}
237
  .tiktok-right-btn{display:flex!important;flex-direction:column!important;align-items:center!important;gap:2px!important;background:none!important;border:0!important;color:#fff!important;cursor:pointer!important}
238
  .tiktok-right-btn .icon{width:42px!important;height:42px!important;border-radius:50%!important;background:rgba(255,255,255,.12)!important;display:flex!important;align-items:center!important;justify-content:center!important;font-size:20px!important}
239
  .tiktok-right-btn .count{font-size:10px!important;color:#ddd!important}
 
 
 
240
  #ai-short-home,.ai-short-home,.ai-short-card-final,[id*="ai-shorts-patched"]{display:none!important}
 
241
  #short-progress-toast{position:fixed;bottom:70px;left:50%;transform:translateX(-50%);background:#2d8659;color:#fff;padding:10px 20px;border-radius:20px;font-size:12px;z-index:99998;box-shadow:0 4px 12px rgba(0,0,0,.4);display:none}
 
242
  .source-detail-box{margin-top:14px;background:#151515;border:1px solid #2b2b2b;border-radius:10px;padding:10px}
243
  .source-detail-item{background:#202020;border-radius:8px;padding:9px;margin:7px 0;cursor:pointer}
244
  .source-detail-item:active{opacity:.8}
 
246
  .source-detail-content{font-size:11px;color:#bbb;line-height:1.4;max-height:80px;overflow:hidden;margin-top:4px}
247
  .source-detail-item img{width:100%;aspect-ratio:16/9;object-fit:cover;border-radius:6px;margin-bottom:6px;background:#222}
248
  .source-vnews-btn{display:inline-block;margin-top:6px;background:#2d8659;color:#fff;padding:4px 10px;border-radius:10px;font-size:10px;font-weight:700}
 
 
249
  </style>
250
  <div id="short-progress-toast"></div>
251
  <script>
252
  (function(){
253
  function esc(s){return String(s||'').replace(/[&<>"']/g,m=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[m]));}
 
 
254
  window.showShortProgress=function(msg){var t=document.getElementById('short-progress-toast');if(t){t.textContent=msg;t.style.display='block';}};
255
  window.hideShortProgress=function(){var t=document.getElementById('short-progress-toast');if(t)t.style.display='none';};
256
  window.makeShortFromPost=async function(pid,btn){
257
  showShortProgress('⏳ Đang tạo Short AI...');if(btn){btn.disabled=true;btn.textContent='Đang tạo...';}
258
  try{var r=await fetch('/api/ai/short/'+pid,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({voice:'nu',emotion:'neutral',speed:1.2})});var j=await r.json();if(!r.ok||j.error)throw new Error(j.error||'Lỗi');showShortProgress('✅ Đã tạo!');setTimeout(hideShortProgress,3000);if(typeof renderShortAISlide==='function')renderShortAISlide();}catch(e){showShortProgress('❌ '+e.message);setTimeout(hideShortProgress,4000);}finally{if(btn){btn.disabled=false;btn.textContent='🎬 Tạo Short AI';}}
259
  };
 
 
260
  setInterval(function(){document.querySelectorAll('#ai-short-home,.ai-short-home,[id*="ai-shorts-patched"]').forEach(function(el){if(el.id!=='short-ai-final-slide')el.remove();});},3000);
261
 
 
262
  window.openLeaguePlayer=async function(league,idx){
263
  showView('view-tiktok');document.querySelectorAll('.cat').forEach(x=>x.classList.remove('active'));
264
  var el=document.getElementById('view-tiktok');el.innerHTML='<div class="loading">Đang tải...</div>';
 
277
  var isYT=v.type==='youtube';var isHLS=!isYT&&v.src&&v.src.indexOf('.m3u8')>-1;
278
  var poster=v.poster?' poster="'+v.poster+'"':'';
279
  var vtag=isYT?'<iframe data-yt-src="'+v.src+'" allowfullscreen allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture" style="width:100%;height:100%;border:none"></iframe>':isHLS?'<video playsinline preload="none"'+poster+' data-hls="'+v.src+'" loop controls style="width:100%;height:100%;object-fit:cover"></video>':'<video playsinline preload="none"'+poster+' loop controls style="width:100%;height:100%;object-fit:cover"><source src="'+v.src+'" type="video/mp4"></video>';
280
+ h+='<div class="tiktok-slide" id="tslide-'+i+'">'+vtag+'<div class="tiktok-bottom"><span class="badge badge-fpt">'+esc(cfg.name)+'</span><p class="tiktok-title">'+esc(v.title)+'</p></div><div class="tiktok-right"><button class="tiktok-right-btn" onclick="event.stopPropagation()"><div class="icon">👁</div></button><button class="tiktok-right-btn" onclick="event.stopPropagation()"><div class="icon">❤️</div></button><button class="tiktok-right-btn" onclick="event.stopPropagation();if(typeof doShareVideo==='function')doShareVideo(\''+esc(v.title)+'\',\''+esc(v.link||'')+'\',\''+esc(v.poster||v.img||'')+'\',\'highlights\')"><div class="icon">📤</div></button></div><span class="tiktok-counter">'+(i+1)+'/'+ordered.length+'</span></div>';
281
  });
282
  h+='</div></div>';el.innerHTML=h;
 
283
  var feed=document.getElementById('tiktok-feed');if(!feed)return;
284
  var slides=feed.querySelectorAll('.tiktok-slide');var cur=-1;
285
  function act(i){if(i===cur)return;slides.forEach(function(sl,idx){var v=sl.querySelector('video');var fr=sl.querySelector('iframe');if(idx===i){if(v&&v.dataset.hls){if(!v._hls&&typeof Hls!=='undefined'&&Hls.isSupported()){var hls=new Hls();hls.loadSource(v.dataset.hls);hls.attachMedia(v);hls.on(Hls.Events.MANIFEST_PARSED,function(){v.play().catch(function(){});});v._hls=hls;}else if(v._hls)v.play().catch(function(){});}else if(v)v.play().catch(function(){});if(fr&&!fr.src&&fr.dataset.ytSrc)fr.src=fr.dataset.ytSrc;}else{if(v){v.pause();if(v._hls){v._hls.destroy();v._hls=null;}}if(fr&&fr.src)fr.src='';}});cur=i;}
 
288
  slides.forEach(function(sl){var v=sl.querySelector('video');if(v)v.addEventListener('click',function(e){e.preventDefault();v.paused?v.play().catch(function(){}):v.pause();});});
289
  };
290
 
 
291
  var _origFetch=window.fetch,_allowRefresh=false;
292
  window.fetch=function(url,opts){try{if(String(url).indexOf('/api/shorts?refresh=1')>-1&&!_allowRefresh)url='/api/shorts';}catch(e){}return _origFetch.call(this,url,opts);};
293
  setTimeout(function(){_allowRefresh=true;},8000);
 
295
  </script>
296
  '''
297
 
 
 
 
298
  @app.get('/')
299
  async def _index():
300
  html = f5.f4.f3.f2.f1._load_index_html()
 
301
  body = ''
302
  body += getattr(rt.old,'PATCH_INJECT','')
303
  body += f5.f4.f3.f2.f1.FINAL_INJECT + f5.f4.f3.FINAL3_INJECT + f5.f4.FINAL4_INJECT + f5.FINAL5_INJECT
304
  body += getattr(f6,'FINAL6_INJECT','')
305
  body += getattr(f6,'FINAL6_FAST_HOME_INJECT','')
306
+ body += getattr(f6,'FINAL6E_INJECT','')
307
  body += PATCH_INJECT
308
+ body += UNIFIED_INJECT
309
+ return HTMLResponse(html.replace('</body>', body + '\n</body>') if '</body>' in html else html + body)