Jing997 commited on
Commit
f8ea563
·
1 Parent(s): d55322d

fix request metadata issue

Browse files
Files changed (2) hide show
  1. src/pages/_home_page.py +6 -7
  2. src/utils/helpers.py +45 -0
src/pages/_home_page.py CHANGED
@@ -1,8 +1,6 @@
1
  from __future__ import annotations
2
 
3
  from typing import Any, Dict, List, Tuple
4
-
5
- import requests
6
  import streamlit as st
7
 
8
  from utils.helpers import (
@@ -11,6 +9,7 @@ from utils.helpers import (
11
  fetch_job_status,
12
  fetch_quiz,
13
  fetch_summary,
 
14
  get_image_base64,
15
  get_remote_image_url,
16
  list_cached_videos,
@@ -135,12 +134,12 @@ def _render_api_status() -> None:
135
  def _fetch_youtube_metadata(video_url: str) -> Dict[str, Any] | None:
136
  if not video_url:
137
  return None
138
- oembed_url = f"https://www.youtube.com/oembed?url={video_url}&format=json"
139
  try:
140
- response = requests.get(oembed_url, timeout=10)
141
- if response.status_code == 200:
142
- return response.json()
143
- except requests.RequestException:
 
144
  return None
145
  return None
146
 
 
1
  from __future__ import annotations
2
 
3
  from typing import Any, Dict, List, Tuple
 
 
4
  import streamlit as st
5
 
6
  from utils.helpers import (
 
9
  fetch_job_status,
10
  fetch_quiz,
11
  fetch_summary,
12
+ fetch_youtube_metadata_v3,
13
  get_image_base64,
14
  get_remote_image_url,
15
  list_cached_videos,
 
134
  def _fetch_youtube_metadata(video_url: str) -> Dict[str, Any] | None:
135
  if not video_url:
136
  return None
 
137
  try:
138
+ metadata = fetch_youtube_metadata_v3(video_url)
139
+ if metadata:
140
+ return metadata
141
+ except RuntimeError as exc:
142
+ st.warning(str(exc))
143
  return None
144
  return None
145
 
src/utils/helpers.py CHANGED
@@ -26,6 +26,7 @@ _API_KEY_ENV_KEY = "CHAPTLY_API_KEY"
26
  _HMAC_SECRET_ENV_KEY = "CHAPTLY_API_SECRET"
27
  _S3_BUCKET_ENV_KEY = "CHAPTLY_S3_BUCKET"
28
  _AWS_REGION_ENV_KEY = "AWS_REGION"
 
29
  _SIG_HEADER = "X-Signature"
30
  _TS_HEADER = "X-Timestamp"
31
 
@@ -33,6 +34,7 @@ DEFAULT_S3_BUCKET = "chaptly-rag"
33
  DEFAULT_AWS_REGION = "ap-southeast-1"
34
  IMAGE_REQUEST_TIMEOUT = 10
35
  _IMG_DIR = Path(__file__).resolve().parents[2] / "img"
 
36
 
37
 
38
  @dataclass(frozen=True)
@@ -315,3 +317,46 @@ def list_cached_videos() -> list[Dict[str, Any]]:
315
  metadata = _load_video_metadata(video_id)
316
  items.append(metadata)
317
  return sorted(items, key=lambda item: item.get("title", ""))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  _HMAC_SECRET_ENV_KEY = "CHAPTLY_API_SECRET"
27
  _S3_BUCKET_ENV_KEY = "CHAPTLY_S3_BUCKET"
28
  _AWS_REGION_ENV_KEY = "AWS_REGION"
29
+ _YOUTUBE_API_KEY_ENV = "YOUTUBE_V3_DATA_API_KEY"
30
  _SIG_HEADER = "X-Signature"
31
  _TS_HEADER = "X-Timestamp"
32
 
 
34
  DEFAULT_AWS_REGION = "ap-southeast-1"
35
  IMAGE_REQUEST_TIMEOUT = 10
36
  _IMG_DIR = Path(__file__).resolve().parents[2] / "img"
37
+ YOUTUBE_API_URL = "https://www.googleapis.com/youtube/v3/videos"
38
 
39
 
40
  @dataclass(frozen=True)
 
317
  metadata = _load_video_metadata(video_id)
318
  items.append(metadata)
319
  return sorted(items, key=lambda item: item.get("title", ""))
320
+
321
+
322
+ def extract_youtube_video_id(url: str) -> Optional[str]:
323
+ """Best-effort extraction of the YouTube video ID from a URL."""
324
+ if not url:
325
+ return None
326
+ url = url.strip()
327
+ if "v=" in url:
328
+ return url.split("v=")[1].split("&")[0]
329
+ if "youtu.be" in url:
330
+ return url.rsplit("/", 1)[-1].split("?")[0]
331
+ return None
332
+
333
+
334
+ def fetch_youtube_metadata_v3(video_url: str) -> Optional[Dict[str, Any]]:
335
+ """Fetch video metadata using the YouTube Data API v3."""
336
+ video_id = extract_youtube_video_id(video_url)
337
+ if not video_id:
338
+ return None
339
+ api_key = _get_secret_or_env(_YOUTUBE_API_KEY_ENV)
340
+ if not api_key:
341
+ raise RuntimeError("YOUTUBE_V3_DATA_API_KEY is not configured in this environment.")
342
+ params = {
343
+ "part": "snippet",
344
+ "id": video_id,
345
+ "key": api_key,
346
+ }
347
+ try:
348
+ response = requests.get(YOUTUBE_API_URL, params=params, timeout=DEFAULT_TIMEOUT)
349
+ response.raise_for_status()
350
+ payload = response.json()
351
+ except requests.RequestException as exc:
352
+ raise RuntimeError(f"Unable to contact YouTube Data API: {exc}") from exc
353
+ items = payload.get("items") or []
354
+ if not items:
355
+ return None
356
+ snippet = items[0].get("snippet", {})
357
+ return {
358
+ "title": snippet.get("title"),
359
+ "author_name": snippet.get("channelTitle"),
360
+ "thumbnail_url": (snippet.get("thumbnails", {}).get("high", {}) or snippet.get("thumbnails", {}).get("default", {})).get("url"),
361
+ "video_id": video_id,
362
+ }