Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions tests/test_vimeo_downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
"title": "We Don't Have To Know - Keli Holiday",
"id": "503166067",
},
{
"url": "https://player.vimeo.com/video/498617513",
"title": "NEET ekalavya all",
"embedded_on": "https://atpstar.com/plans-162.html",
"id": "498617513",
},
# I have to comment out this test, because this video is abscent
# {
# "url": "https://player.vimeo.com/video/498617513",
# "title": "NEET ekalavya all",
# "embedded_on": "https://atpstar.com/plans-162.html",
# "id": "498617513",
# },
{
"url": "https://player.vimeo.com/video/98044508?some_random_p=parameter",
"title": "Pier Solar OUYA Official Trailer",
Expand Down
76 changes: 51 additions & 25 deletions vimeo_downloader/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,17 @@
from collections import namedtuple
from typing import List, NamedTuple, Optional
from urllib.parse import parse_qs, urlparse

from base64 import b64encode
import requests
from tqdm import tqdm

headers = {
"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0",
}
config = "https://player.vimeo.com/video/{}/config"
password_config ="https://player.vimeo.com/video/{}/check-password"
details = "http://vimeo.com/api/v2/video/{}.json"

session = requests.Session()

class URLNotSupported(Exception):
pass
Expand Down Expand Up @@ -113,7 +114,6 @@ def download(
"""
Downloads the video with progress bar if `mute=False`
"""

if (filename is None) and (self.title is None):
try:
filename = re.findall(r"\/(\d+\.mp4|webm$)", self._direct_url)[0]
Expand All @@ -126,7 +126,7 @@ def download(
else:
if not filename.endswith(".mp4"):
filename += ".mp4"
r = requests.get(self._direct_url, stream=True, headers=headers)
r = session.get(self._direct_url, stream=True, headers=headers)
if not r.ok:
if r.status_code == 410:
raise URLExpired("The download URL has expired.")
Expand Down Expand Up @@ -161,7 +161,7 @@ def filesize(self) -> str:
Returns str with filesize in MB.
"""

r = requests.get(self._direct_url, stream=True, headers=headers)
r = session.get(self._direct_url, stream=True, headers=headers)
return str(int(r.headers.get("content-length")) / 10**6) + " MB"


Expand All @@ -175,6 +175,7 @@ def __init__(
url: str,
embedded_on: Optional[str] = None,
cookies: Optional[str] = None,
password: Optional[str] = None,
):
self._url = (
urlparse(url)._replace(query=None).geturl()
Expand All @@ -183,6 +184,7 @@ def __init__(
self._headers = headers
self._cookies = dict(cookies_are=cookies)
self._params = self._extract_query(url)
self._password = b64encode(password.encode()).decode() if password else None
if embedded_on:
self._headers["Referer"] = embedded_on

Expand Down Expand Up @@ -215,25 +217,35 @@ def _extractor(self) -> dict:
"""
Extracts the direct mp4 link for the vimeo video
"""
if self._cookies.get("cookies_are") is not None:
js_url = requests.get(
config.format(self._video_id),
headers=self._headers,
cookies=self._cookies,
params=self._params,
)
if not self._password:
if self._cookies.get("cookies_are") is not None:
js_url = session.get(
config.format(self._video_id),
headers=self._headers,
cookies=self._cookies,
params=self._params
)
else:
js_url = session.get(
config.format(self._video_id),
headers=self._headers,
params=self._params

)
else:
js_url = requests.get(
config.format(self._video_id),
js_url = session.post(
password_config.format(self._video_id),
headers=self._headers,
params=self._params,
data=dict(password=self._password)
)


if not js_url.ok:
if js_url.status_code == 403:
# If the response is forbidden it tries another way to fetch link
try:
html = requests.get(
html = session.get(
self._url, headers=self._headers, params=self._params
)
except AttributeError:
Expand All @@ -250,7 +262,7 @@ def _extractor(self) -> dict:
r"\/", "/"
)

js_url = requests.get(request_conf_link, headers=self._headers)
js_url = session.get(request_conf_link, headers=self._headers)
return js_url.json()
except IndexError:
raise UnableToParseHtml("Couldn't find config url")
Expand Down Expand Up @@ -281,22 +293,34 @@ def _get_meta_data(self):
"""
Retrieves meta data for the video
"""
if self._cookies:
video_info = requests.get(
details.format(self._video_id),
headers=self._headers,
cookies=self._cookies,
)
if not self._password:
if self._cookies:
video_info = session.get(
details.format(self._video_id),
headers=self._headers,
cookies=self._cookies,
)
else:
video_info = session.get(
details.format(self._video_id), headers=self._headers
)
else:
video_info = requests.get(
details.format(self._video_id), headers=self._headers
video_info = session.post(
password_config.format(self._video_id),
headers=self._headers,
params=self._params,
data=dict(password=self._password)
)


if not video_info.ok:
raise RequestError(
f"{video_info.status_code}: Unable to retrieve meta data."
)
try:
video_info = video_info.json()
if self._password:
video_info = [video_info.get('video', {})]
except Exception as e:
raise RequestError(f"Couldn't retrieve meta data: {e}")
return video_info
Expand Down Expand Up @@ -340,7 +364,7 @@ def streams(self) -> List[_Stream]:
dl = []
for stream in js_url["request"]["files"]["progressive"]:
url = stream["url"]
if not requests.get(url, stream=True).ok:
if not session.get(url, stream=True).ok:
continue
stream_object = _Stream(
quality=stream["quality"], direct_url=url, title=title
Expand All @@ -355,12 +379,14 @@ def from_video_id(
video_id: str,
embedded_on: Optional[str] = None,
cookies: Optional[str] = None,
password: Optional[str] = None,
):
self = cls.__new__(cls)
self._video_id = video_id
self._headers = headers
self._cookies = dict(cookies_are=cookies)
self._params = {}
self._password = b64encode(password.encode()).decode() if password else None
if embedded_on:
self._headers["Referer"] = embedded_on
return self
Expand Down