bep40 commited on
Commit
f271a91
·
verified ·
1 Parent(s): 4f5713c

Restore patch_extra.py to c6d2331

Browse files
Files changed (1) hide show
  1. patch_extra.py +30 -44
patch_extra.py CHANGED
@@ -1,63 +1,49 @@
1
- """Extra: highlight TikTok feed, single wall, clean rewrite, livescore CSS."""
2
  EXTRA_FIX = r'''
3
  <style>
 
4
  .tiktok-slide{position:relative!important}
5
  .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}
6
  .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;font-size:10px!important;cursor:pointer!important}
7
  .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}
8
  .tiktok-right-btn .count{font-size:10px!important;color:#ddd!important}
9
  #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;white-space:nowrap}
 
10
  #ai-short-home,.ai-short-home,.ai-short-card-final,[id*="ai-shorts-patched"]{display:none!important}
11
- /* Hide ALL duplicate Tường AI walls except the main one from loadHome */
12
- #ai-wall-topic-live,#ai-wall-final,[id*="ai-wall-patched"]{display:none!important}
13
- .ls-content{max-height:480px;overflow-y:auto;padding:0 6px 8px;font-size:12px;color:#ddd}.ls-content ul,.ls-content ol{list-style:none;padding:0;margin:0}.ls-content a{color:#5cb87a;text-decoration:none}.ls-content .matchs-league,.ls-content .league-group{list-style:none;padding:0;margin:0}.ls-content .title-content,.ls-content .league-title,.ls-content .group-title{display:flex;gap:6px;align-items:center;background:#222;border-radius:4px;margin:4px 0;padding:5px 8px}.ls-content .title-content img,.ls-content .league-title img{width:18px;height:18px;object-fit:contain}.ls-content .title-content strong,.ls-content .league-title strong{font-size:11px;color:#ccc}.ls-content .match-detail,.ls-content .match-item{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,.ls-content .match-time{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 tr:hover td{background:#1a2a1f}.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;margin:0}.mo-body li{padding:5px 0;border-bottom:1px solid #222}.mo-body .stat-row{display:flex;align-items:center;gap:8px;padding:6px 0;border-bottom:1px solid #1f1f1f}.mo-body .stat-label{flex:1;text-align:center;font-size:11px;color:#999}.mo-body .stat-home{flex:1;text-align:right;font-weight:700;color:#eee}.mo-body .stat-away{flex:1;text-align:left;font-weight:700;color:#eee}
14
  </style>
15
  <div id="short-progress-toast"></div>
16
  <script>
17
  (function(){
18
- // Progress toast
 
 
 
 
 
 
 
 
 
19
  window.showShortProgress=function(msg){var t=document.getElementById('short-progress-toast');if(t){t.textContent=msg;t.style.display='block';}};
20
  window.hideShortProgress=function(){var t=document.getElementById('short-progress-toast');if(t)t.style.display='none';};
 
 
21
  window.makeShortFromPost=async function(pid,btn){
22
- showShortProgress('⏳ Đang tạo Short AI...');if(btn){btn.disabled=true;btn.textContent='Đang tạo...';}
23
- 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 Short AI!');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';}}
24
- };
25
- // Remove duplicate slides/walls
26
- setInterval(function(){document.querySelectorAll('#ai-short-home,.ai-short-home,[id*="ai-shorts-patched"],#ai-wall-topic-live,#ai-wall-final,[id*="ai-wall-patched"]').forEach(function(el){if(el.id!=='short-ai-final-slide')el.remove();});},3000);
27
-
28
- // === OVERRIDE openLeaguePlayer to use TikTok-style vertical feed (fullheight, interaction buttons) ===
29
- function esc(s){return String(s||'').replace(/[&<>"']/g,m=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[m]));}
30
- window.openLeaguePlayer=async function(league,idx){
31
- showView('view-tiktok');document.querySelectorAll('.cat').forEach(x=>x.classList.remove('active'));
32
- const el=document.getElementById('view-tiktok');el.innerHTML='<div class="loading">Đang tải highlight...</div>';
33
- const HL_CONFIG=window.HL_CONFIG||{"premier-league":{name:"Premier League",emoji:"🏴"},"champions-league":{name:"Champions League",emoji:"⭐"},"la-liga":{name:"La Liga",emoji:"🇪🇸"},"serie-a":{name:"Serie A",emoji:"🇮🇹"},"bundesliga":{name:"Bundesliga",emoji:"🇩🇪"}};
34
- const cfg=HL_CONFIG[league]||{name:league,emoji:'🎬'};
35
- const articles=(window._hlLeagueData||{})[league]||[];
36
- if(!articles.length){el.innerHTML='<div class="loading">Không có video</div>';return;}
37
- // Fetch video URLs
38
- const vids=[];
39
- const results=await Promise.all(articles.map(async(a,i)=>{try{const r=await fetch('/api/video_url?url='+encodeURIComponent(a.link));const v=await r.json();if(v&&v.src)return{...a,...v,_idx:i};}catch(e){}return null;}));
40
- results.forEach(r=>{if(r)vids.push(r);});
41
- vids.sort((a,b)=>a._idx-b._idx);
42
- if(!vids.length){el.innerHTML='<div class="loading">Không tìm thấy video</div>';return;}
43
- let ti=vids.findIndex(v=>v._idx===idx);if(ti<0)ti=0;
44
- const ordered=ti>0?[...vids.slice(ti),...vids.slice(0,ti)]:vids;
45
- // Build TikTok-style feed (same as shorts)
46
- let h=`<button class="back-btn" onclick="switchCat('home')">← ${cfg.emoji} ${cfg.name}</button><div class="tiktok-container"><div class="tiktok-feed" id="tiktok-feed">`;
47
- ordered.forEach((v,i)=>{
48
- const isYT=v.type==='youtube';const isHLS=!isYT&&v.src&&v.src.includes('.m3u8');
49
- const poster=v.poster?' poster="'+v.poster+'"':'';
50
- const 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></video>`:`<video playsinline preload="none"${poster} loop controls><source src="${v.src}" type="video/mp4"></video>`;
51
- h+=`<div class="tiktok-slide" id="tslide-${i}" data-id="hl-${i}"><${vtag.startsWith('<iframe')?'':''}${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>`;
52
- });
53
- h+='</div></div>';el.innerHTML=h;
54
- // Init feed (same logic as shorts)
55
- const feed=document.getElementById('tiktok-feed');if(!feed)return;
56
- const slides=feed.querySelectorAll('.tiktok-slide');let cur=-1;
57
- function act(i){if(i===cur)return;slides.forEach((sl,idx)=>{const v=sl.querySelector('video');const fr=sl.querySelector('iframe');if(idx===i){if(v&&v.dataset.hls){if(!v._hls&&typeof Hls!=='undefined'&&Hls.isSupported()){const hls=new Hls();hls.loadSource(v.dataset.hls);hls.attachMedia(v);hls.on(Hls.Events.MANIFEST_PARSED,()=>v.play().catch(()=>{}));v._hls=hls;}else if(v._hls)v.play().catch(()=>{});}else if(v)v.play().catch(()=>{});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;}
58
- let sT;feed.addEventListener('scroll',()=>{clearTimeout(sT);sT=setTimeout(()=>{const rect=feed.getBoundingClientRect(),ctr=rect.top+rect.height/2;let best=-1,bestD=1e9;slides.forEach((sl,i)=>{const d=Math.abs(sl.getBoundingClientRect().top+sl.getBoundingClientRect().height/2-ctr);if(d<bestD){bestD=d;best=i;}});if(best>=0)act(best);},150);});
59
- setTimeout(()=>act(0),400);
60
- slides.forEach(sl=>{const v=sl.querySelector('video');if(v)v.addEventListener('click',e=>{e.preventDefault();v.paused?v.play().catch(()=>{}):v.pause();});});
61
  };
62
  })();
63
  </script>
 
1
+ """Extra CSS/JS fixes injected AFTER main PATCH_INJECT."""
2
  EXTRA_FIX = r'''
3
  <style>
4
+ /* Force correct position for Short AI interaction buttons */
5
  .tiktok-slide{position:relative!important}
6
  .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}
7
  .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;font-size:10px!important;cursor:pointer!important}
8
  .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}
9
  .tiktok-right-btn .count{font-size:10px!important;color:#ddd!important}
10
  #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;white-space:nowrap}
11
+ /* Kill ALL duplicate short AI slides from old layers */
12
  #ai-short-home,.ai-short-home,.ai-short-card-final,[id*="ai-shorts-patched"]{display:none!important}
 
 
 
13
  </style>
14
  <div id="short-progress-toast"></div>
15
  <script>
16
  (function(){
17
+ // Kill old renderers that create duplicate Short AI slides
18
+ window.renderAIShortHome=function(){};
19
+ window.renderAIShorts7=function(){};
20
+ window.renderTopicWallE=function(){};
21
+ window.renderAiShorts=function(){};
22
+ // Also remove any already-rendered duplicate slides
23
+ setInterval(function(){
24
+ document.querySelectorAll('#ai-short-home,.ai-short-home,[id*="ai-shorts-patched"]').forEach(function(el){el.remove()});
25
+ },2000);
26
+ // Progress toast for short creation
27
  window.showShortProgress=function(msg){var t=document.getElementById('short-progress-toast');if(t){t.textContent=msg;t.style.display='block';}};
28
  window.hideShortProgress=function(){var t=document.getElementById('short-progress-toast');if(t)t.style.display='none';};
29
+ // Override makeShortFromPost to use progress toast
30
+ var _origMakeShort=window.makeShortFromPost;
31
  window.makeShortFromPost=async function(pid,btn){
32
+ showShortProgress('⏳ Đang tạo Short AI...');
33
+ if(btn){btn.disabled=true;btn.textContent='Đang tạo...';}
34
+ try{
35
+ 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})});
36
+ var j=await r.json();
37
+ if(!r.ok||j.error)throw new Error(j.error||'Lỗi');
38
+ showShortProgress('✅ Đã tạo Short AI!');
39
+ setTimeout(hideShortProgress,3000);
40
+ if(typeof renderShortAISlide==='function')renderShortAISlide();
41
+ }catch(e){
42
+ showShortProgress(' Lỗi: '+e.message);
43
+ setTimeout(hideShortProgress,4000);
44
+ }finally{
45
+ if(btn){btn.disabled=false;btn.textContent='🎬 Tạo Short AI';}
46
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  };
48
  })();
49
  </script>