youtube video url
This commit is contained in:
parent
e111ae53f5
commit
03700b998b
2 changed files with 87 additions and 0 deletions
58
src/ytdl_sub/validators/url_validator.py
Normal file
58
src/ytdl_sub/validators/url_validator.py
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
from typing import Any
|
||||||
|
from typing import Optional
|
||||||
|
from urllib.parse import parse_qs
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
from ytdl_sub.validators.validators import StringValidator
|
||||||
|
|
||||||
|
|
||||||
|
class YoutubeVideoUrlValidator(StringValidator):
|
||||||
|
|
||||||
|
_expected_value_type_name = "youtube video url"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_video_id(cls, url: str) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
Examples:
|
||||||
|
- https://youtu.be/SA2iWivDJiE
|
||||||
|
- https://www.youtube.com/watch?v=_oPAwA_Udwc&feature=feedu
|
||||||
|
- https://www.youtube.com/embed/SA2iWivDJiE
|
||||||
|
- https://www.youtube.com/v/SA2iWivDJiE?version=3&hl=en_US
|
||||||
|
"""
|
||||||
|
# If the url doesn't contain the 'youtu' substring, assume it is the video id
|
||||||
|
if "youtu" not in url:
|
||||||
|
return url
|
||||||
|
|
||||||
|
# If https:// is not present, urlparse will not work
|
||||||
|
if not url.startswith("https://"):
|
||||||
|
url = f"https://{url}"
|
||||||
|
|
||||||
|
query = urlparse(url)
|
||||||
|
if query.hostname in ("youtu.be", "www.youtu.be"):
|
||||||
|
return query.path[1:]
|
||||||
|
if query.hostname in ("youtube.com", "www.youtube.com"):
|
||||||
|
if query.path == "/watch":
|
||||||
|
parsed_q = parse_qs(query.query)
|
||||||
|
return parsed_q["v"][0]
|
||||||
|
if query.path[:7] == "/embed/":
|
||||||
|
return query.path.split("/")[2]
|
||||||
|
if query.path[:3] == "/v/":
|
||||||
|
return query.path.split("/")[2]
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __init__(self, name: str, value: Any):
|
||||||
|
super().__init__(name, value)
|
||||||
|
|
||||||
|
self._video_id = self._get_video_id(value)
|
||||||
|
if not self._video_id:
|
||||||
|
raise self._validation_exception(f"'{value}' is not a valid Youtube video url or ID.")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def video_id(self) -> str:
|
||||||
|
"""
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
ID of the video
|
||||||
|
"""
|
||||||
|
return self._video_id
|
||||||
29
tests/unit/validators/test_url_validator.py
Normal file
29
tests/unit/validators/test_url_validator.py
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from ytdl_sub.utils.exceptions import ValidationException
|
||||||
|
from ytdl_sub.validators.url_validator import YoutubeVideoUrlValidator
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"url",
|
||||||
|
[
|
||||||
|
"dQw4w9WgXcQ",
|
||||||
|
"youtu.be/dQw4w9WgXcQ",
|
||||||
|
"www.youtu.be/dQw4w9WgXcQ",
|
||||||
|
"https://youtu.be/dQw4w9WgXcQ",
|
||||||
|
"https://www.youtu.be/dQw4w9WgXcQ",
|
||||||
|
"https://www.youtube.com/watch?v=dQw4w9WgXcQ&feature=feedu",
|
||||||
|
"https://www.youtube.com/embed/dQw4w9WgXcQ",
|
||||||
|
"https://www.youtube.com/v/dQw4w9WgXcQ?version=3&hl=en_US",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_youtube_video_validator_success(url):
|
||||||
|
video_id = YoutubeVideoUrlValidator(name="unit test", value=url).video_id
|
||||||
|
assert video_id == "dQw4w9WgXcQ"
|
||||||
|
|
||||||
|
|
||||||
|
def test_youtube_video_validator_fail():
|
||||||
|
bad_url = "youtube.cum/asdfd"
|
||||||
|
expected_error_msg = f"'{bad_url}' is not a valid Youtube video url or ID."
|
||||||
|
with pytest.raises(ValidationException, match=expected_error_msg):
|
||||||
|
YoutubeVideoUrlValidator(name="unit test", value=bad_url)
|
||||||
Loading…
Reference in a new issue