bep40 commited on
Commit
5d75b1d
·
verified ·
1 Parent(s): 0524d84

Replace FPT highlights with ScoreBat API (50 highlight videos, no geo-restrict)"

Browse files
Files changed (1) hide show
  1. main.py +43 -5
main.py CHANGED
@@ -1,4 +1,4 @@
1
- """VNEWS - FastAPI backend with livescore + YouTube FPT Bóng Đá"""
2
  import hashlib, re, time, subprocess, json
3
  from datetime import datetime
4
  from concurrent.futures import ThreadPoolExecutor, as_completed
@@ -61,8 +61,34 @@ def _parse_match_from_li(li, status_type="live"):
61
  league=league_el.get_text(strip=True) if league_el else ""
62
  return{"home":home_el.get_text(strip=True),"away":away_el.get_text(strip=True),"score":score or"VS","minute":minute,"league":league,"time":time_el.get_text(strip=True) if time_el else "","event_id":event_id,"home_logo":home_logo.get("src","") if home_logo else "","away_logo":away_logo.get("src","") if away_logo else "","status":status_type}
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  def _yt_playlist(channel_path, count=15):
65
- """Get videos from YouTube channel using yt-dlp."""
66
  try:
67
  result=subprocess.run(["yt-dlp","--flat-playlist","--dump-json","--no-download","--playlist-end",str(count),f"https://www.youtube.com/@fptbongdaofficial/{channel_path}"],capture_output=True,text=True,timeout=60)
68
  videos=[]
@@ -81,9 +107,8 @@ def _yt_playlist(channel_path, count=15):
81
 
82
  def scrape_fpt_shorts():
83
  return _yt_playlist("shorts", 15)
84
- def scrape_fpt_highlights():
85
- return _yt_playlist("videos", 15)
86
 
 
87
  @app.get("/api/livescore/live")
88
  def api_livescore_live():
89
  html=_cached("ls_live",lambda:fetch_bongda_api("/api/fixtures/live"),ttl=_cache_ttl_live)
@@ -140,19 +165,29 @@ def api_livescore_featured():
140
  return all_matches[0]
141
  return None
142
  return JSONResponse(_cached("ls_featured",_f,ttl=30))
 
 
143
  @app.get("/api/shorts")
144
  def api_shorts():
145
  return JSONResponse(_cached("fpt_shorts",scrape_fpt_shorts,ttl=_cache_ttl_yt))
 
146
  @app.get("/api/highlights")
147
  def api_highlights():
148
- return JSONResponse(_cached("fpt_highlights",scrape_fpt_highlights,ttl=_cache_ttl_yt))
 
 
149
  @app.get("/api/video_url")
150
  def api_video_url(url:str=Query(...)):
 
151
  if "youtube.com" in url or "youtu.be" in url:
152
  m=re.search(r'(?:v=|shorts/|youtu\.be/)([a-zA-Z0-9_-]{11})',url)
153
  if m:
154
  vid=m.group(1)
155
  return JSONResponse({"src":f"https://www.youtube.com/embed/{vid}?autoplay=1&rel=0&enablejsapi=1","poster":f"https://i.ytimg.com/vi/{vid}/hqdefault.jpg","type":"youtube"})
 
 
 
 
156
  if "bongdaplus.vn" in url:
157
  try:
158
  m=re.search(r'-(\d{6,})\.html',url)
@@ -164,6 +199,7 @@ def api_video_url(url:str=Query(...)):
164
  return JSONResponse({"src":source.get("src","") if source else "","poster":video.get("poster",""),"type":"video"})
165
  except:pass
166
  return JSONResponse({"error":"not found"})
 
167
  @app.get("/api/bdp_videos")
168
  def api_bdp_videos():
169
  def _f():
@@ -182,6 +218,8 @@ def api_bdp_videos():
182
  return arts[:20]
183
  except:return[]
184
  return JSONResponse(_cached("bdp_videos",_f))
 
 
185
  def scrape_vne(cat_url):
186
  try:
187
  soup=_get(cat_url);arts=[]
 
1
+ """VNEWS - FastAPI backend with livescore + ScoreBat highlights + YouTube FPT shorts"""
2
  import hashlib, re, time, subprocess, json
3
  from datetime import datetime
4
  from concurrent.futures import ThreadPoolExecutor, as_completed
 
61
  league=league_el.get_text(strip=True) if league_el else ""
62
  return{"home":home_el.get_text(strip=True),"away":away_el.get_text(strip=True),"score":score or"VS","minute":minute,"league":league,"time":time_el.get_text(strip=True) if time_el else "","event_id":event_id,"home_logo":home_logo.get("src","") if home_logo else "","away_logo":away_logo.get("src","") if away_logo else "","status":status_type}
63
 
64
+ # ===== SCOREBAT HIGHLIGHTS =====
65
+ def scrape_scorebat_highlights():
66
+ """Get highlight videos from ScoreBat free API."""
67
+ try:
68
+ r=requests.get("https://www.scorebat.com/video-api/v3/",headers=HEADERS,timeout=15)
69
+ if r.status_code!=200:return[]
70
+ data=r.json()
71
+ response=data.get("response",[])
72
+ videos=[]
73
+ for item in response:
74
+ title=item.get("title","")
75
+ thumb=item.get("thumbnail","")
76
+ competition=item.get("competition","")
77
+ matchview=item.get("matchviewUrl","")
78
+ vids=item.get("videos",[])
79
+ # Get embed URL from first video
80
+ embed=""
81
+ if vids:
82
+ embed_html=vids[0].get("embed","")
83
+ m=re.search(r'src=["\']([^"\']+)["\']',embed_html)
84
+ if m:embed=m.group(1)
85
+ if title and (embed or matchview):
86
+ videos.append({"title":title,"img":thumb,"link":matchview or embed,"source":"scorebat","embed":embed,"competition":competition})
87
+ return videos[:30]
88
+ except:return[]
89
+
90
+ # ===== YOUTUBE FPT SHORTS =====
91
  def _yt_playlist(channel_path, count=15):
 
92
  try:
93
  result=subprocess.run(["yt-dlp","--flat-playlist","--dump-json","--no-download","--playlist-end",str(count),f"https://www.youtube.com/@fptbongdaofficial/{channel_path}"],capture_output=True,text=True,timeout=60)
94
  videos=[]
 
107
 
108
  def scrape_fpt_shorts():
109
  return _yt_playlist("shorts", 15)
 
 
110
 
111
+ # ===== LIVESCORE =====
112
  @app.get("/api/livescore/live")
113
  def api_livescore_live():
114
  html=_cached("ls_live",lambda:fetch_bongda_api("/api/fixtures/live"),ttl=_cache_ttl_live)
 
165
  return all_matches[0]
166
  return None
167
  return JSONResponse(_cached("ls_featured",_f,ttl=30))
168
+
169
+ # ===== VIDEO APIs =====
170
  @app.get("/api/shorts")
171
  def api_shorts():
172
  return JSONResponse(_cached("fpt_shorts",scrape_fpt_shorts,ttl=_cache_ttl_yt))
173
+
174
  @app.get("/api/highlights")
175
  def api_highlights():
176
+ """ScoreBat highlight videos."""
177
+ return JSONResponse(_cached("scorebat_highlights",scrape_scorebat_highlights,ttl=_cache_ttl))
178
+
179
  @app.get("/api/video_url")
180
  def api_video_url(url:str=Query(...)):
181
+ # YouTube
182
  if "youtube.com" in url or "youtu.be" in url:
183
  m=re.search(r'(?:v=|shorts/|youtu\.be/)([a-zA-Z0-9_-]{11})',url)
184
  if m:
185
  vid=m.group(1)
186
  return JSONResponse({"src":f"https://www.youtube.com/embed/{vid}?autoplay=1&rel=0&enablejsapi=1","poster":f"https://i.ytimg.com/vi/{vid}/hqdefault.jpg","type":"youtube"})
187
+ # ScoreBat embed
188
+ if "scorebat.com" in url:
189
+ return JSONResponse({"src":url,"poster":"","type":"youtube"})
190
+ # BDP
191
  if "bongdaplus.vn" in url:
192
  try:
193
  m=re.search(r'-(\d{6,})\.html',url)
 
199
  return JSONResponse({"src":source.get("src","") if source else "","poster":video.get("poster",""),"type":"video"})
200
  except:pass
201
  return JSONResponse({"error":"not found"})
202
+
203
  @app.get("/api/bdp_videos")
204
  def api_bdp_videos():
205
  def _f():
 
218
  return arts[:20]
219
  except:return[]
220
  return JSONResponse(_cached("bdp_videos",_f))
221
+
222
+ # ===== NEWS =====
223
  def scrape_vne(cat_url):
224
  try:
225
  soup=_get(cat_url);arts=[]