bep40 commited on
Commit
9a9c2bf
·
verified ·
1 Parent(s): dccef15

Upload app_v2_entry.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. 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 (fast HTML scrape, same method as Dantri/SKĐS) =====
509
  _vtv_nambo_cache = {'t': 0, 'd': []}
510
  _VTV_NAMBO_TTL = 1800
511
 
512
  def _scrape_vtv_nambo_shorts():
513
- """Fast HTML scrape for @vtvnambo YouTube shorts."""
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
- url = "https://www.youtube.com/@vtvnambo/shorts"
520
- r = req.get(url, headers={**HEADERS, "Accept-Language": "vi,en;q=0.8"}, timeout=15)
521
  if r.status_code == 200:
522
- html = r.text
523
- seen_ids = []
524
- for m in re.finditer(r'"videoId":"([A-Za-z0-9_-]{11})"', html):
525
  vid = m.group(1)
526
- if vid in seen_ids: continue
527
- seen_ids.append(vid)
528
- snip = html[max(0, m.start()-900):m.start()+1600]
 
 
 
529
  title = ""
530
- mt = re.search(r'"title":\{"runs":\[\{"text":"([^"]+)"', snip)
531
- if not mt: mt = re.search(r'"accessibilityText":"([^"]+)"', snip)
532
- if mt: title = html_lib.unescape(mt.group(1)).replace('\n', ' ').strip()
533
- if not title: title = "VTV Nam Bộ"
534
- vids.append({"title": title, "id": vid, "channel": "vtvnambo",
535
- "link": f"https://www.youtube.com/watch?v={vid}",
536
- "img": f"https://i.ytimg.com/vi/{vid}/hqdefault.jpg", "source": "yt"})
537
- if len(vids) >= 24: break
 
 
 
 
 
 
 
 
 
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
- app.mount('/static',StaticFiles(directory=STATIC_DIR),name='vnews_static')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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())