Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
@@ -1,12 +1,23 @@
|
|
1 |
from pytubefix import YouTube
|
2 |
from pytubefix.cli import on_progress
|
3 |
-
from fastapi import FastAPI
|
4 |
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
|
|
|
|
|
5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
app = FastAPI()
|
7 |
app.add_middleware(
|
8 |
CORSMiddleware,
|
9 |
-
allow_origins=["*"], # Adjust
|
10 |
allow_credentials=True,
|
11 |
allow_methods=["*"],
|
12 |
allow_headers=["*"],
|
@@ -16,14 +27,73 @@ app.add_middleware(
|
|
16 |
def index():
|
17 |
return {"message": "Hello, World!"}
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
@app.get("/api/video/{id}")
|
20 |
def video_id(id: str):
|
21 |
url = f"https://www.youtube.com/watch?v={id}"
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
from pytubefix import YouTube
|
2 |
from pytubefix.cli import on_progress
|
3 |
+
from fastapi import FastAPI, HTTPException
|
4 |
from fastapi.middleware.cors import CORSMiddleware
|
5 |
+
import logging as log
|
6 |
+
import subprocess
|
7 |
+
import json
|
8 |
+
from typing import Tuple
|
9 |
|
10 |
+
# --- Logging Setup ---
|
11 |
+
log.basicConfig(
|
12 |
+
level=log.INFO,
|
13 |
+
format="%(asctime)s [%(levelname)s] %(message)s",
|
14 |
+
)
|
15 |
+
|
16 |
+
# --- FastAPI Setup ---
|
17 |
app = FastAPI()
|
18 |
app.add_middleware(
|
19 |
CORSMiddleware,
|
20 |
+
allow_origins=["*"], # Adjust in production
|
21 |
allow_credentials=True,
|
22 |
allow_methods=["*"],
|
23 |
allow_headers=["*"],
|
|
|
27 |
def index():
|
28 |
return {"message": "Hello, World!"}
|
29 |
|
30 |
+
|
31 |
+
# --- Shell Command Runner ---
|
32 |
+
def cmd(command, check=True, shell=True, capture_output=True, text=True):
|
33 |
+
log.info(f"Executing command: {command}")
|
34 |
+
try:
|
35 |
+
result = subprocess.run(
|
36 |
+
command,
|
37 |
+
check=check,
|
38 |
+
shell=shell,
|
39 |
+
capture_output=capture_output,
|
40 |
+
text=text
|
41 |
+
)
|
42 |
+
log.info("Command executed successfully.")
|
43 |
+
return result
|
44 |
+
except subprocess.CalledProcessError as error:
|
45 |
+
log.error(f"Command failed: {error}")
|
46 |
+
raise HTTPException(status_code=500, detail="Token generation failed.")
|
47 |
+
|
48 |
+
|
49 |
+
# --- Token Generator ---
|
50 |
+
def generate_youtube_token() -> dict:
|
51 |
+
result = cmd("node test.js")
|
52 |
+
if not result or not result.stdout:
|
53 |
+
log.error("No output received from test.js")
|
54 |
+
raise HTTPException(status_code=500, detail="Invalid token response")
|
55 |
+
|
56 |
+
try:
|
57 |
+
data = json.loads(result.stdout)
|
58 |
+
log.info(f"Token data received: {data}")
|
59 |
+
return data
|
60 |
+
except json.JSONDecodeError as e:
|
61 |
+
log.error(f"Failed to decode token JSON: {e}")
|
62 |
+
raise HTTPException(status_code=500, detail="Invalid JSON from token generator")
|
63 |
+
|
64 |
+
|
65 |
+
# --- Token Verifier Function ---
|
66 |
+
def po_token_verifier() -> Tuple[str, str]:
|
67 |
+
token_object = generate_youtube_token()
|
68 |
+
return token_object["visitorData"], token_object["poToken"]
|
69 |
+
|
70 |
+
|
71 |
+
# --- Video Fetch Endpoint ---
|
72 |
@app.get("/api/video/{id}")
|
73 |
def video_id(id: str):
|
74 |
url = f"https://www.youtube.com/watch?v={id}"
|
75 |
+
log.info(f"Fetching YouTube video for ID: {id}")
|
76 |
+
|
77 |
+
try:
|
78 |
+
yt = YouTube(
|
79 |
+
url,
|
80 |
+
use_po_token=True,
|
81 |
+
po_token_verifier=po_token_verifier
|
82 |
+
)
|
83 |
+
ys = yt.streams.get_highest_resolution()
|
84 |
+
|
85 |
+
if not ys:
|
86 |
+
log.warning("No suitable video stream found.")
|
87 |
+
raise HTTPException(status_code=404, detail="No suitable video stream found")
|
88 |
+
|
89 |
+
log.info(f"Video fetched: {yt.title}")
|
90 |
+
return {
|
91 |
+
"title": yt.title,
|
92 |
+
"url": ys.url,
|
93 |
+
"thumbnail": yt.thumbnail_url,
|
94 |
+
"description": yt.description
|
95 |
+
}
|
96 |
+
|
97 |
+
except Exception as e:
|
98 |
+
log.error(f"Failed to fetch video info: {e}")
|
99 |
+
raise HTTPException(status_code=500, detail=str(e))
|