Spaces:
Running
Running
Revert to a38c268: slider BDP+24h, seek buttons, grid->TikTok
Browse files
app.py
CHANGED
|
@@ -393,21 +393,30 @@ def _bdp_relates(soup):
|
|
| 393 |
|
| 394 |
# ββ Video aggregator βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 395 |
def fetch_latest_videos():
|
| 396 |
-
"""Fetch
|
| 397 |
videos = []
|
|
|
|
| 398 |
try:
|
| 399 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 400 |
for a in h24:
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
if not img:
|
| 404 |
-
try:
|
| 405 |
-
r = requests.get(a["link"], headers=HEADERS, timeout=8); r.encoding="utf-8"
|
| 406 |
-
og = BeautifulSoup(r.text,"lxml").find("meta",property="og:image")
|
| 407 |
-
if og: img = og.get("content","")
|
| 408 |
-
except: pass
|
| 409 |
-
if img:
|
| 410 |
-
videos.append({"title": a["title"], "link": a["link"], "img": img, "source": "24h"})
|
| 411 |
except: pass
|
| 412 |
return videos[:20]
|
| 413 |
|
|
@@ -533,7 +542,7 @@ def render_video_slider_html(videos):
|
|
| 533 |
<div class="vslide-thumb"><img src="{img}" alt="" class="bdp-lazy-img"><div class="vslide-play">βΆ</div>{src_badge}</div>
|
| 534 |
<p class="vslide-title">{title}</p></div>''')
|
| 535 |
return f'''<div class="vslide-wrap">
|
| 536 |
-
<div class="vslide-header"><span class="vslide-label">π¬ Video
|
| 537 |
<div class="vslide-nav"><button class="vslide-btn" onclick="window.bdpSlideScroll(-1)">β</button>
|
| 538 |
<button class="vslide-btn" onclick="window.bdpSlideScroll(1)">βΆ</button></div></div>
|
| 539 |
<div class="vslide-track" id="vslide-track">{''.join(items)}</div></div>'''
|
|
@@ -846,10 +855,10 @@ footer,.built-with{display:none!important}
|
|
| 846 |
.tiktok-unmute-hint{position:absolute;top:12px;right:12px;background:rgba(0,0,0,.6);color:#fff;font-size:12px;padding:6px 12px;border-radius:18px;cursor:pointer;z-index:4;backdrop-filter:blur(4px);transition:opacity .3s}
|
| 847 |
.tiktok-pause-icon{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:70px;height:70px;background:rgba(0,0,0,.5);border-radius:50%;color:#fff;font-size:28px;z-index:5;pointer-events:none;display:none;align-items:center;justify-content:center;line-height:70px;text-align:center}
|
| 848 |
.tiktok-slide.paused .tiktok-pause-icon{display:block}
|
| 849 |
-
.tiktok-seek-controls{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);display:flex;gap:
|
| 850 |
-
.tiktok-
|
| 851 |
-
.tiktok-seek-btn{
|
| 852 |
-
.tiktok-seek-btn:active{transform:scale(.
|
| 853 |
.vslide-badge{position:absolute;top:6px;left:6px;font-size:9px;padding:1px 6px;border-radius:3px;font-weight:700;z-index:2}
|
| 854 |
.vslide-badge-24h{background:#e67e22;color:#fff}
|
| 855 |
"""
|
|
@@ -1035,28 +1044,14 @@ function initTikTokFullscreen(container){
|
|
| 1035 |
/* Start first video after short delay for HLS init */
|
| 1036 |
setTimeout(function(){activateSlide(0);},800);
|
| 1037 |
|
| 1038 |
-
/* Tap to pause/play
|
| 1039 |
slides.forEach(function(sl){
|
| 1040 |
var v=sl.querySelector('.tiktok-video');
|
| 1041 |
if(v){
|
| 1042 |
-
var hideTimer=null;
|
| 1043 |
-
function showControls(){
|
| 1044 |
-
sl.classList.add('show-controls');
|
| 1045 |
-
if(hideTimer) clearTimeout(hideTimer);
|
| 1046 |
-
hideTimer=setTimeout(function(){sl.classList.remove('show-controls');},3000);
|
| 1047 |
-
}
|
| 1048 |
v.addEventListener('click',function(e){
|
| 1049 |
e.preventDefault();
|
| 1050 |
-
if(sl.classList.
|
| 1051 |
-
|
| 1052 |
-
if(v.paused){tryPlay(v);sl.classList.remove('paused');}
|
| 1053 |
-
else{v.pause();sl.classList.add('paused');}
|
| 1054 |
-
sl.classList.remove('show-controls');
|
| 1055 |
-
if(hideTimer) clearTimeout(hideTimer);
|
| 1056 |
-
} else {
|
| 1057 |
-
/* First tap = show controls */
|
| 1058 |
-
showControls();
|
| 1059 |
-
}
|
| 1060 |
});
|
| 1061 |
}
|
| 1062 |
});
|
|
|
|
| 393 |
|
| 394 |
# ββ Video aggregator βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 395 |
def fetch_latest_videos():
|
| 396 |
+
"""Fetch latest videos from BDP carousel + 24h highlights for the homepage slider."""
|
| 397 |
videos = []
|
| 398 |
+
# BDP carousel
|
| 399 |
try:
|
| 400 |
+
soup = _get(f"{BASE_BDP}/video")
|
| 401 |
+
first_link = None
|
| 402 |
+
for a in soup.find_all("a", href=True):
|
| 403 |
+
href = a.get("href", "")
|
| 404 |
+
if "/video/" in href and re.search(r'-\d{6,}\.html', href):
|
| 405 |
+
first_link = href if href.startswith("http") else BASE_BDP + href; break
|
| 406 |
+
if first_link:
|
| 407 |
+
vid_id = _extract_bdp_video_id(first_link)
|
| 408 |
+
if vid_id:
|
| 409 |
+
embed = fetch_bdp_embed_data(vid_id)
|
| 410 |
+
if embed:
|
| 411 |
+
for rel in embed.get("related", []):
|
| 412 |
+
videos.append({"title": rel["title"], "link": rel["link"], "img": rel["poster"], "source": "bdp"})
|
| 413 |
+
except: pass
|
| 414 |
+
# 24h highlights
|
| 415 |
+
try:
|
| 416 |
+
h24 = scrape_24h_video_list()[:10]
|
| 417 |
for a in h24:
|
| 418 |
+
if a.get("img"):
|
| 419 |
+
videos.append({"title": a["title"], "link": a["link"], "img": a["img"], "source": "24h"})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 420 |
except: pass
|
| 421 |
return videos[:20]
|
| 422 |
|
|
|
|
| 542 |
<div class="vslide-thumb"><img src="{img}" alt="" class="bdp-lazy-img"><div class="vslide-play">βΆ</div>{src_badge}</div>
|
| 543 |
<p class="vslide-title">{title}</p></div>''')
|
| 544 |
return f'''<div class="vslide-wrap">
|
| 545 |
+
<div class="vslide-header"><span class="vslide-label">π¬ Video Mα»i NhαΊ₯t</span>
|
| 546 |
<div class="vslide-nav"><button class="vslide-btn" onclick="window.bdpSlideScroll(-1)">β</button>
|
| 547 |
<button class="vslide-btn" onclick="window.bdpSlideScroll(1)">βΆ</button></div></div>
|
| 548 |
<div class="vslide-track" id="vslide-track">{''.join(items)}</div></div>'''
|
|
|
|
| 855 |
.tiktok-unmute-hint{position:absolute;top:12px;right:12px;background:rgba(0,0,0,.6);color:#fff;font-size:12px;padding:6px 12px;border-radius:18px;cursor:pointer;z-index:4;backdrop-filter:blur(4px);transition:opacity .3s}
|
| 856 |
.tiktok-pause-icon{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:70px;height:70px;background:rgba(0,0,0,.5);border-radius:50%;color:#fff;font-size:28px;z-index:5;pointer-events:none;display:none;align-items:center;justify-content:center;line-height:70px;text-align:center}
|
| 857 |
.tiktok-slide.paused .tiktok-pause-icon{display:block}
|
| 858 |
+
.tiktok-seek-controls{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);display:flex;gap:40px;z-index:6;pointer-events:auto}
|
| 859 |
+
.tiktok-seek-btn{background:rgba(0,0,0,.4);color:#fff;border:none;padding:8px 14px;border-radius:20px;font-size:12px;cursor:pointer;backdrop-filter:blur(4px);font-weight:600;opacity:.7;transition:opacity .2s}
|
| 860 |
+
.tiktok-seek-btn:hover{opacity:1}
|
| 861 |
+
.tiktok-seek-btn:active{transform:scale(.9)}
|
| 862 |
.vslide-badge{position:absolute;top:6px;left:6px;font-size:9px;padding:1px 6px;border-radius:3px;font-weight:700;z-index:2}
|
| 863 |
.vslide-badge-24h{background:#e67e22;color:#fff}
|
| 864 |
"""
|
|
|
|
| 1044 |
/* Start first video after short delay for HLS init */
|
| 1045 |
setTimeout(function(){activateSlide(0);},800);
|
| 1046 |
|
| 1047 |
+
/* Tap to pause/play */
|
| 1048 |
slides.forEach(function(sl){
|
| 1049 |
var v=sl.querySelector('.tiktok-video');
|
| 1050 |
if(v){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1051 |
v.addEventListener('click',function(e){
|
| 1052 |
e.preventDefault();
|
| 1053 |
+
if(v.paused){tryPlay(v);sl.classList.remove('paused');}
|
| 1054 |
+
else{v.pause();sl.classList.add('paused');}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1055 |
});
|
| 1056 |
}
|
| 1057 |
});
|