Files
MediaFusion/utils/validation_helper.py
T

120 lines
3.1 KiB
Python

import logging
import requests
from urllib.parse import urlparse, quote
from requests.exceptions import RequestException
from db import schemas
def is_valid_url(url: str) -> bool:
parsed_url = urlparse(url)
return all([parsed_url.scheme, parsed_url.netloc])
def does_url_exist(url: str) -> bool:
try:
response = requests.head(url, allow_redirects=True, timeout=5)
return response.status_code == 200
except RequestException:
return False
def validate_image_url(url: str) -> bool:
return is_valid_url(url) and does_url_exist(url)
def validate_m3u8_url(url: str, behaviour_hint: dict) -> bool:
if not is_valid_url(url):
return False
try:
headers = behaviour_hint.get("proxyHeaders", {}).get("request", {})
response = requests.get(url, allow_redirects=True, headers=headers, timeout=30)
content_type = response.headers.get("Content-Type", "").lower()
return (
"application/vnd.apple.mpegurl" in content_type
or "application/x-mpegurl" in content_type
)
except RequestException as err:
logging.error(err)
return False
class ValidationError(Exception):
pass
def validate_yt_id(yt_id: str) -> bool:
image_url = f"https://img.youtube.com/vi/{yt_id}/mqdefault.jpg"
response = requests.head(image_url, allow_redirects=True, timeout=5)
return response.status_code == 200
def validate_tv_metadata(metadata: schemas.TVMetaData) -> list[schemas.TVStreams]:
if (
not validate_image_url(metadata.poster)
or (metadata.logo and not validate_image_url(metadata.logo))
or (metadata.background and not validate_image_url(metadata.background))
):
raise ValidationError("Invalid image URL provided.")
# Validate stream URLs at least 1 stream should be valid
valid_streams = [
stream
for stream in metadata.streams
if (
stream.url
and validate_m3u8_url(
stream.url, stream.behaviorHints.model_dump(exclude_none=True)
)
)
or (stream.ytId and validate_yt_id(stream.ytId))
]
if not valid_streams:
raise ValidationError("Invalid stream URLs provided.")
unique_streams = {stream.url or stream.ytId: stream for stream in valid_streams}
return list(unique_streams.values())
def is_video_file(filename: str) -> bool:
return filename.lower().endswith(
(
".3g2",
".3gp",
".amv",
".asf",
".avi",
".drc",
".flv",
".gif",
".gifv",
".m2v",
".m4p",
".m4v",
".mkv",
".mng",
".mov",
".mp2",
".mp4",
".mpe",
".mpeg",
".mpg",
".mpv",
".mxf",
".nsv",
".ogg",
".ogv",
".qt",
".rm",
".rmvb",
".roq",
".svi",
".vob",
".webm",
".wmv",
".yuv",
)
)