Skip to content

Commit

Permalink
Fixed error which occurs wen downloading video which is part of playl…
Browse files Browse the repository at this point in the history
…ist (#17)

* Fixed error which occurs wen downloading video which is part of playlist
  • Loading branch information
deepaerial committed Jan 27, 2024
1 parent c457f63 commit 0d6228c
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 18 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.4.8] - 2024-01-27
### Fix
- Fixed error in API when downloading video that is part of playlist.

## [1.4.7] - 2024-01-24
### Changed
- Updated pytube version to 15.0.0.
Expand All @@ -27,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [1.4.3] - 2023-11-20
### Changed
- Improvement logging in `on_finish_callback` function.

### Fix
- Fixed empty file size in downloads.
### Added
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ target-version = "py310"

[tool.poetry]
name = "ytdl-api"
version = "1.4.7"
version = "1.4.8"
description = "API for web-based youtube-dl client"
authors = ["Nazar Oleksiuk <nazarii.oleksiuk@gmail.com>"]
license = "MIT"
Expand Down
4 changes: 2 additions & 2 deletions tests/downloaders/test_ytdlp_downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from ytdl_api.downloaders import YTDLPDownloader
from ytdl_api.queue import NotificationQueue
from ytdl_api.constants import MediaFormat, DownloadStatus
from ytdl_api.schemas.models import Download, VideoURL
from ytdl_api.schemas.models import Download, YoutubeURL
from ytdl_api.schemas.responses import VideoInfoResponse
from ytdl_api.storage import LocalFileStorage

Expand Down Expand Up @@ -60,7 +60,7 @@ def mock_persisted_download(
"https://www.youtube.com/watch?v=TNhaISOUy6Q",
],
)
def test_get_video_info(url: VideoURL):
def test_get_video_info(url: YoutubeURL):
"""
Test functionality responsible for fetching video info.
"""
Expand Down
10 changes: 10 additions & 0 deletions tests/endpoints/test_preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
[
"https://www.youtube.com/watch?v=NcBjx_eyvxc",
"https://www.youtube.com/watch?v=TNhaISOUy6Q",
"https://www.youtube.com/watch?v=QXeEoD0pB3E&list=PLsyeobzWxl7poL9JTVyndKe62ieoN-MZ3&index=1",
],
)
def test_get_preview(app_client: TestClient, url: str):
Expand All @@ -25,3 +26,12 @@ def test_get_preview(app_client: TestClient, url: str):
"videoStreams",
]
)


def test_get_preview_422(app_client: TestClient):
response = app_client.get(
"/api/preview", params={"url": "https://www.youcube.com/watch?v=9TJx7QTrTyo"}
)
assert response.status_code == 422
json_response = response.json()
assert json_response["detail"][0]["msg"] == "Bad youtube video link provided."
8 changes: 4 additions & 4 deletions ytdl_api/downloaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
)
from .schemas.models import AudioStream, Download, VideoStream
from .schemas.responses import VideoInfoResponse
from .types import VideoURL
from .types import YoutubeURL


class IDownloader(ABC):
Expand All @@ -41,7 +41,7 @@ def __init__(

@abstractmethod
def get_video_info(
self, url: VideoURL | str
self, url: YoutubeURL | str
) -> VideoInfoResponse: # pragma: no cover
"""
Abstract method for retrieving information about media resource.
Expand All @@ -61,7 +61,7 @@ class PytubeDownloader(IDownloader):
Downloader based on pytube library https://github.com/pytube/pytube
"""

def get_video_info(self, url: VideoURL | str) -> VideoInfoResponse:
def get_video_info(self, url: YoutubeURL | str) -> VideoInfoResponse:
video = YouTube(url)
streams = video.streams.filter(is_dash=True).desc()
audio_streams = [
Expand Down Expand Up @@ -188,7 +188,7 @@ class YTDLPDownloader(IDownloader):
Downloader based on yt-dlp library https://github.com/yt-dlp/yt-dlp
"""

def get_video_info(self, url: VideoURL | str) -> VideoInfoResponse:
def get_video_info(self, url: YoutubeURL | str) -> VideoInfoResponse:
with YoutubeDL() as ydl:
info = ydl.extract_info(url, download=False)
streams = info["formats"]
Expand Down
6 changes: 3 additions & 3 deletions ytdl_api/endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from .downloaders import IDownloader
from .queue import NotificationQueue
from .schemas import models, requests, responses
from .types import VideoURL
from .types import YoutubeURL

router = APIRouter(tags=["base"])

Expand Down Expand Up @@ -67,13 +67,13 @@ async def get_downloads(
},
)
async def preview(
url: VideoURL,
url: YoutubeURL,
downloader: IDownloader = Depends(dependencies.get_downloader),
):
"""
Endpoint for getting info about video.
"""
download = downloader.get_video_info(url)
download = downloader.get_video_info(url.get_clear_video_url())
return download


Expand Down
4 changes: 2 additions & 2 deletions ytdl_api/schemas/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from pydantic import AnyHttpUrl, Field

from ..constants import DownloadStatus, MediaFormat
from ..types import VideoURL
from ..types import YoutubeURL
from ..utils import get_unique_id
from .base import BaseModel_

Expand All @@ -26,7 +26,7 @@ class Download(BaseModel_):
client_id: str = Field(..., description="Client ID")
media_id: str = Field(description="Download id", default_factory=get_unique_id)
title: str = Field(..., description="Video title")
url: VideoURL = Field(..., description="URL of video")
url: YoutubeURL = Field(..., description="URL of video")
video_streams: List[VideoStream] = Field(
description="List of video streams", default_factory=list
)
Expand Down
4 changes: 2 additions & 2 deletions ytdl_api/schemas/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
from pydantic import Field, root_validator, validator

from ..constants import YOUTUBE_URI_REGEX, MediaFormat
from ..types import VideoURL
from ..types import YoutubeURL
from .base import BaseModel_


class DownloadParams(BaseModel_):
url: VideoURL = Field(
url: YoutubeURL = Field(
...,
title="URL",
description="URL to video",
Expand Down
6 changes: 3 additions & 3 deletions ytdl_api/schemas/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from pydantic import AnyHttpUrl, Field

from ..constants import DownloadStatus, MediaFormat
from ..types import VideoURL
from ..types import YoutubeURL
from .base import BaseModel_
from .models import AudioStream, VideoStream

Expand All @@ -18,7 +18,7 @@ class DownloadResponse(BaseModel_):
client_id: str = Field(..., description="Client ID.")
media_id: str = Field(..., description="Download id.")
title: str = Field(..., description="Video title.")
url: VideoURL = Field(..., description="URL of video.")
url: YoutubeURL = Field(..., description="URL of video.")
video_streams: List[VideoStream] = Field(
description="List of video streams.", default_factory=list
)
Expand Down Expand Up @@ -83,7 +83,7 @@ class DeleteResponse(BaseModel_):


class VideoInfoResponse(BaseModel_):
url: VideoURL = Field(..., title="URL", description="URL to video")
url: YoutubeURL = Field(..., title="URL", description="URL to video")
title: str = Field(..., description="Video title")
duration: int = Field(..., description="Video length in seconds")
thumbnail_url: AnyHttpUrl = Field(..., description="Video thumbnail")
Expand Down
10 changes: 9 additions & 1 deletion ytdl_api/types.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import re
import urllib.parse
from typing import Optional, TypedDict

from pydantic import AnyHttpUrl
Expand All @@ -8,7 +9,7 @@
)


class VideoURL(AnyHttpUrl, str):
class YoutubeURL(AnyHttpUrl, str):
"""
Custom type for Youtube video video URL.
"""
Expand Down Expand Up @@ -38,6 +39,13 @@ def validate(cls, v):
scheme = match.group(2)
return cls(url=full_url, scheme=scheme)

def get_clear_video_url(self) -> "YoutubeURL":
query_params = urllib.parse.parse_qs(self.query)
if "list" in query_params.keys():
video_id = query_params["v"][0]
return YoutubeURL(f"https://www.youtube.com/watch?v={video_id}")
return self


class DownloadDataInfo(TypedDict):
_eta_str: Optional[str]
Expand Down

0 comments on commit 0d6228c

Please sign in to comment.