Spaces:
Running
Running
Upload app_v2_entry.py with huggingface_hub
Browse files- app_v2_entry.py +73 -23
app_v2_entry.py
CHANGED
|
@@ -436,10 +436,25 @@ async def _sh(url:str='',title:str='',img:str=''):return HTMLResponse(f'<!DOCTYP
|
|
| 436 |
from vtv_api import router as vtv_router
|
| 437 |
app.include_router(vtv_router)
|
| 438 |
|
| 439 |
-
from vtv_api import router as vtv_router
|
| 440 |
-
app.include_router(vtv_router)
|
| 441 |
-
|
| 442 |
from wc2026_scraper import(scrape_summary,scrape_fixtures,scrape_standings,scrape_stats,scrape_wc_news,scrape_road_to_wc,get_wc2026_all,scrape_history,scrape_h2h,scrape_lineups,scrape_match_detail)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 443 |
@app.get('/api/wc2026')
|
| 444 |
def _w():return JSONResponse(get_wc2026_all())
|
| 445 |
@app.get('/api/wc2026/fixtures')
|
|
@@ -504,37 +519,49 @@ def _bg():
|
|
| 504 |
time.sleep(90)
|
| 505 |
threading.Thread(target=_bg,daemon=True).start()
|
| 506 |
|
| 507 |
-
|
| 508 |
-
# ===== VTV NAM BỘ SHORTS (
|
| 509 |
_vtv_nambo_cache = {'t': 0, 'd': []}
|
| 510 |
_VTV_NAMBO_TTL = 1800
|
| 511 |
|
| 512 |
def _scrape_vtv_nambo_shorts():
|
| 513 |
-
"""
|
| 514 |
now = time.time()
|
| 515 |
if _vtv_nambo_cache['d'] and now - _vtv_nambo_cache['t'] < _VTV_NAMBO_TTL:
|
| 516 |
return _vtv_nambo_cache['d']
|
| 517 |
vids = []
|
| 518 |
try:
|
| 519 |
-
|
| 520 |
-
r = req.get(
|
| 521 |
if r.status_code == 200:
|
| 522 |
-
|
| 523 |
-
|
| 524 |
-
for m in re.finditer(r'
|
| 525 |
vid = m.group(1)
|
| 526 |
-
if vid in
|
| 527 |
-
|
| 528 |
-
|
|
|
|
|
|
|
|
|
|
| 529 |
title = ""
|
| 530 |
-
|
| 531 |
-
if not
|
| 532 |
-
|
| 533 |
-
if
|
| 534 |
-
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 538 |
except Exception as e:
|
| 539 |
print(f"[VTV Nam Bộ shorts error] {e}")
|
| 540 |
_vtv_nambo_cache['t'] = now
|
|
@@ -545,4 +572,27 @@ def _scrape_vtv_nambo_shorts():
|
|
| 545 |
def api_vtv_nambo_shorts():
|
| 546 |
return JSONResponse(_scrape_vtv_nambo_shorts())
|
| 547 |
|
| 548 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 436 |
from vtv_api import router as vtv_router
|
| 437 |
app.include_router(vtv_router)
|
| 438 |
|
|
|
|
|
|
|
|
|
|
| 439 |
from wc2026_scraper import(scrape_summary,scrape_fixtures,scrape_standings,scrape_stats,scrape_wc_news,scrape_road_to_wc,get_wc2026_all,scrape_history,scrape_h2h,scrape_lineups,scrape_match_detail)
|
| 440 |
+
@app.get('/api/wc2026/highlights')
|
| 441 |
+
def _whl():
|
| 442 |
+
"""World Cup 2026 highlights from xemlaibongda.top"""
|
| 443 |
+
cache_key = 'wc2026_hl'
|
| 444 |
+
now = time.time()
|
| 445 |
+
if cache_key in _xlb_cache and now - _xlb_cache[cache_key]['t'] < _xlb_ttl:
|
| 446 |
+
return JSONResponse(_xlb_cache[cache_key]['d'])
|
| 447 |
+
try:
|
| 448 |
+
r = req.get('https://xemlaibongda.top/api/videos/highlights/the-gioi/world-cup',
|
| 449 |
+
headers={"User-Agent": HEADERS["User-Agent"]}, timeout=15)
|
| 450 |
+
if r.status_code == 200:
|
| 451 |
+
data = r.json()
|
| 452 |
+
_xlb_cache[cache_key] = {'t': now, 'd': data}
|
| 453 |
+
return JSONResponse(data)
|
| 454 |
+
except Exception as e:
|
| 455 |
+
print(f"[WC highlights error] {e}")
|
| 456 |
+
return JSONResponse({"success": False, "data": []}, status_code=502)
|
| 457 |
+
|
| 458 |
@app.get('/api/wc2026')
|
| 459 |
def _w():return JSONResponse(get_wc2026_all())
|
| 460 |
@app.get('/api/wc2026/fixtures')
|
|
|
|
| 519 |
time.sleep(90)
|
| 520 |
threading.Thread(target=_bg,daemon=True).start()
|
| 521 |
|
| 522 |
+
app.mount('/static',StaticFiles(directory=STATIC_DIR),name='vnews_static')
|
| 523 |
+
# ===== VTV NAM BỘ SHORTS (Jina reader bypasses IP block) =====
|
| 524 |
_vtv_nambo_cache = {'t': 0, 'd': []}
|
| 525 |
_VTV_NAMBO_TTL = 1800
|
| 526 |
|
| 527 |
def _scrape_vtv_nambo_shorts():
|
| 528 |
+
\"\"\"Scrape @vtvnambo shorts via Jina reader (bypasses YouTube IP block).\"\"\"
|
| 529 |
now = time.time()
|
| 530 |
if _vtv_nambo_cache['d'] and now - _vtv_nambo_cache['t'] < _VTV_NAMBO_TTL:
|
| 531 |
return _vtv_nambo_cache['d']
|
| 532 |
vids = []
|
| 533 |
try:
|
| 534 |
+
jina_url = "https://r.jina.ai/https://www.youtube.com/@vtvnambo/shorts"
|
| 535 |
+
r = req.get(jina_url, headers={"User-Agent": HEADERS["User-Agent"], "Accept": "text/plain"}, timeout=20)
|
| 536 |
if r.status_code == 200:
|
| 537 |
+
text = r.text
|
| 538 |
+
found_ids = []
|
| 539 |
+
for m in re.finditer(r'youtube\.com/shorts/([A-Za-z0-9_-]{11})', text):
|
| 540 |
vid = m.group(1)
|
| 541 |
+
if vid in found_ids:
|
| 542 |
+
continue
|
| 543 |
+
found_ids.append(vid)
|
| 544 |
+
# Extract nearby title
|
| 545 |
+
idx = m.start()
|
| 546 |
+
region = text[max(0, idx-300):idx+200]
|
| 547 |
title = ""
|
| 548 |
+
tm = re.search(r'### \[([^\]]+)\]', region)
|
| 549 |
+
if not tm:
|
| 550 |
+
tm = re.search(r'\[([^\]]+)\]\(https://www\.youtube\.com/shorts', region)
|
| 551 |
+
if tm:
|
| 552 |
+
title = tm.group(1).strip()
|
| 553 |
+
if not title or len(title) < 5:
|
| 554 |
+
title = "VTV Nam Bộ"
|
| 555 |
+
vids.append({
|
| 556 |
+
"title": title[:120],
|
| 557 |
+
"link": f"https://www.youtube.com/shorts/{vid}",
|
| 558 |
+
"img": f"https://i.ytimg.com/vi/{vid}/hqdefault.jpg",
|
| 559 |
+
"source": "yt",
|
| 560 |
+
"id": vid,
|
| 561 |
+
"channel": "vtvnambo",
|
| 562 |
+
})
|
| 563 |
+
if len(vids) >= 24:
|
| 564 |
+
break
|
| 565 |
except Exception as e:
|
| 566 |
print(f"[VTV Nam Bộ shorts error] {e}")
|
| 567 |
_vtv_nambo_cache['t'] = now
|
|
|
|
| 572 |
def api_vtv_nambo_shorts():
|
| 573 |
return JSONResponse(_scrape_vtv_nambo_shorts())
|
| 574 |
|
| 575 |
+
# ===== XEMLAIBONGDA HIGHLIGHTS PROXY =====
|
| 576 |
+
_xlb_cache = {}
|
| 577 |
+
_xlb_ttl = 600
|
| 578 |
+
|
| 579 |
+
@app.get('/api/proxy/xlb/highlights/{category}')
|
| 580 |
+
def api_xlb_highlights(category: str):
|
| 581 |
+
\"\"\"Proxy xemlaibongda highlights to avoid CORS/IP issues.\"\"\"
|
| 582 |
+
cache_key = f'xlb_hl_{category}'
|
| 583 |
+
now = time.time()
|
| 584 |
+
if cache_key in _xlb_cache and now - _xlb_cache[cache_key]['t'] < _xlb_ttl:
|
| 585 |
+
return JSONResponse(_xlb_cache[cache_key]['d'])
|
| 586 |
+
try:
|
| 587 |
+
url = f'https://xemlaibongda.top/api/videos/highlights/{category}'
|
| 588 |
+
r = req.get(url, headers={"User-Agent": HEADERS["User-Agent"]}, timeout=15)
|
| 589 |
+
if r.status_code == 200:
|
| 590 |
+
data = r.json()
|
| 591 |
+
_xlb_cache[cache_key] = {'t': now, 'd': data}
|
| 592 |
+
return JSONResponse(data)
|
| 593 |
+
except Exception as e:
|
| 594 |
+
print(f"[xlb proxy error] {e}")
|
| 595 |
+
return JSONResponse({"success": False, "data": [], "error": "fetch failed"}, status_code=502)
|
| 596 |
+
@app.get('/api/vtv_nambo_shorts')
|
| 597 |
+
def api_vtv_nambo_shorts():
|
| 598 |
+
return JSONResponse(_scrape_vtv_nambo_shorts())
|