Spaces:
Running
Running
Restore patch_extra.py to c6d2331
Browse files- patch_extra.py +30 -44
patch_extra.py
CHANGED
|
@@ -1,63 +1,49 @@
|
|
| 1 |
-
"""Extra
|
| 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 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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...');
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 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>
|