Update app.py
Browse files
app.py
CHANGED
|
@@ -481,6 +481,75 @@ async def download_hls_video(request: Request):
|
|
| 481 |
return {"url": download_url}
|
| 482 |
|
| 483 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 484 |
@app.post("/multi")
|
| 485 |
async def multi_download(request: Request):
|
| 486 |
user_ip = get_user_ip(request)
|
|
@@ -529,14 +598,23 @@ async def multi_download(request: Request):
|
|
| 529 |
is_youtube_url = re.search(r'(youtube\.com|youtu\.be)', video_url) is not None
|
| 530 |
|
| 531 |
if is_youtube_url:
|
| 532 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 533 |
dl_url = f'https://chrunos-grab.hf.space/yt/dl?url={encoded_url}&{parameter}'
|
| 534 |
if dl_url and "http" in dl_url:
|
| 535 |
return {"url": dl_url, "requests_remaining": rate_limiter.max_requests - rate_limiter.get_current_count(user_ip)}
|
| 536 |
else:
|
| 537 |
return {
|
| 538 |
"error": "Failed to Fetch the video."
|
| 539 |
-
}
|
| 540 |
|
| 541 |
else:
|
| 542 |
dl_url = await get_track_download_url(video_url, quality)
|
|
|
|
| 481 |
return {"url": download_url}
|
| 482 |
|
| 483 |
|
| 484 |
+
def get_youtube_download_url_from_apis(video_url: str) -> str:
|
| 485 |
+
encoded_url = urllib.parse.quote(str(video_url), safe='')
|
| 486 |
+
|
| 487 |
+
api_configs = [
|
| 488 |
+
{
|
| 489 |
+
"name": "API 1",
|
| 490 |
+
"url": f"https://velynapi.vercel.app/api/downloader/ytmp4?url={encoded_url}",
|
| 491 |
+
"headers": {"accept": "*/*"},
|
| 492 |
+
"parser": lambda data: data.get("data", {}).get("url")
|
| 493 |
+
if data.get("status") and data.get("data", {}).get("status")
|
| 494 |
+
else None
|
| 495 |
+
},
|
| 496 |
+
{
|
| 497 |
+
"name": "API 2",
|
| 498 |
+
"url": f"https://velynapi.vercel.app/api/downloader/ytmp4v2?url={encoded_url}",
|
| 499 |
+
"headers": {"accept": "application/json"},
|
| 500 |
+
"parser": lambda data: data.get("data", {}).get("advancedInfo", {}).get("videoMp4")
|
| 501 |
+
if data.get("status")
|
| 502 |
+
else None
|
| 503 |
+
}
|
| 504 |
+
]
|
| 505 |
+
|
| 506 |
+
for api in api_configs:
|
| 507 |
+
logger.info(f"Attempting to fetch download URL using {api['name']} ({api['url']})...")
|
| 508 |
+
try:
|
| 509 |
+
response = requests.get(api["url"], headers=api["headers"], timeout=20) # 15-second timeout
|
| 510 |
+
|
| 511 |
+
# Raise an exception for HTTP errors (e.g., 404, 500)
|
| 512 |
+
response.raise_for_status()
|
| 513 |
+
|
| 514 |
+
# Attempt to parse the response as JSON
|
| 515 |
+
# response.json() will raise requests.exceptions.JSONDecodeError if not valid JSON
|
| 516 |
+
data = response.json()
|
| 517 |
+
|
| 518 |
+
# Use the custom parser to extract the download URL
|
| 519 |
+
download_url = api["parser"](data)
|
| 520 |
+
|
| 521 |
+
if download_url:
|
| 522 |
+
logger.info(f"Successfully retrieved download URL from {api['name']}: {download_url}")
|
| 523 |
+
return download_url
|
| 524 |
+
else:
|
| 525 |
+
# This means the request was successful (HTTP 200) and JSON was valid,
|
| 526 |
+
# but the expected keys/values for the URL were not found or statuses were false.
|
| 527 |
+
logger.info(f"{api['name']} responded successfully, but a valid download URL was not found in the expected structure or conditions were not met.")
|
| 528 |
+
# Detailed logging for why parsing might have failed to find the URL:
|
| 529 |
+
if not data.get("status"):
|
| 530 |
+
logger.info(f" Reason: Root 'status' was false or missing in {api['name']}'s response.")
|
| 531 |
+
elif api['name'] == "API 1" and (not data.get("data") or not data.get("data", {}).get("status")):
|
| 532 |
+
logger.info(f" Reason: 'data' field was missing, or 'data.status' was false or missing in {api['name']}'s response.")
|
| 533 |
+
|
| 534 |
+
except requests.exceptions.HTTPError as e:
|
| 535 |
+
logger.info(f"HTTP error occurred while calling {api['name']}: {e}")
|
| 536 |
+
except requests.exceptions.Timeout:
|
| 537 |
+
logger.info(f"Request to {api['name']} timed out.")
|
| 538 |
+
except requests.exceptions.ConnectionError as e:
|
| 539 |
+
logger.info(f"Could not connect to {api['name']}: {e}")
|
| 540 |
+
except requests.exceptions.JSONDecodeError:
|
| 541 |
+
# This catches errors if response.json() fails
|
| 542 |
+
logger.info(f"Failed to decode JSON response from {api['name']}. Response text (first 200 chars): {response.text[:200] if response else 'No response text'}")
|
| 543 |
+
except requests.exceptions.RequestException as e: # Catch any other request-related error
|
| 544 |
+
logger.info(f"An error occurred during the request to {api['name']}: {e}")
|
| 545 |
+
except Exception as e: # Catch-all for other unexpected errors (e.g., in parser logic if data is malformed)
|
| 546 |
+
logger.info(f"An unexpected error occurred while processing the response from {api['name']}: {e}")
|
| 547 |
+
|
| 548 |
+
logger.info(f"Failed to get URL from {api['name']}. Trying next API if available.")
|
| 549 |
+
|
| 550 |
+
logger.info("Both APIs failed to retrieve a download URL.")
|
| 551 |
+
return None
|
| 552 |
+
|
| 553 |
@app.post("/multi")
|
| 554 |
async def multi_download(request: Request):
|
| 555 |
user_ip = get_user_ip(request)
|
|
|
|
| 598 |
is_youtube_url = re.search(r'(youtube\.com|youtu\.be)', video_url) is not None
|
| 599 |
|
| 600 |
if is_youtube_url:
|
| 601 |
+
dl_url = get_youtube_download_url_from_apis(video_url)
|
| 602 |
+
if dl_url:
|
| 603 |
+
remaining_requests_value = rate_limiter.max_requests - rate_limiter.get_current_count(user_ip)
|
| 604 |
+
dl_url["requests_remaining"] = remaining_requests_value
|
| 605 |
+
return dl_url
|
| 606 |
+
else:
|
| 607 |
+
return {
|
| 608 |
+
"error": "Failed to Fetch the video."
|
| 609 |
+
}
|
| 610 |
+
'''encoded_url = urllib.parse.quote(str(video_url), safe='')
|
| 611 |
dl_url = f'https://chrunos-grab.hf.space/yt/dl?url={encoded_url}&{parameter}'
|
| 612 |
if dl_url and "http" in dl_url:
|
| 613 |
return {"url": dl_url, "requests_remaining": rate_limiter.max_requests - rate_limiter.get_current_count(user_ip)}
|
| 614 |
else:
|
| 615 |
return {
|
| 616 |
"error": "Failed to Fetch the video."
|
| 617 |
+
} '''
|
| 618 |
|
| 619 |
else:
|
| 620 |
dl_url = await get_track_download_url(video_url, quality)
|