Module hdrezka.post.urls.kind.video

High-level representation of video.

Classes

class VideoURL (value: str, client: HDRezkaClient | None = None)
Expand source code
class VideoURL(_AwaitableStr):
    """``str`` add-on representing a video CDN URL."""

    @property
    def mp4(self) -> '_AwaitableStr':
        """URL without ``:hls:manifest.m3u8``."""
        return _AwaitableStr(self.removesuffix(':hls:manifest.m3u8'), client=self._client)

str add-on representing a video CDN URL.

Ancestors

  • hdrezka.post.urls.kind.video._AwaitableStr
  • builtins.str

Instance variables

prop mp4 : _AwaitableStr
Expand source code
@property
def mp4(self) -> '_AwaitableStr':
    """URL without ``:hls:manifest.m3u8``."""
    return _AwaitableStr(self.removesuffix(':hls:manifest.m3u8'), client=self._client)

URL without :hls:manifest.m3u8.

class VideoURLs (data: str | dict, *, client: HDRezkaClient | None = None)
Expand source code
class VideoURLs:
    """Collection of video URLs keyed by quality."""

    __slots__ = ('raw_data', 'qualities', 'min', '_client')

    def __init__(self, data: str | dict, *, client: 'HDRezkaClient | None' = None):
        """
        :param data:
            ``str`` — raw URL payload from an AJAX response;
            ``dict`` — ``dict[Quality, tuple[VideoURL, ...]]``.
            Other types raise ``TypeError``.
        :param client: Session used when awaiting video URLs (redirect resolve).
        """
        self._client = client
        if isinstance(data, str):
            self.raw_data: dict[Quality, tuple[VideoURL, ...]] = {
                Quality(q): (*(VideoURL(i, client=client) for i in u.split(' or ') if i.endswith('.m3u8')),)
                for q, u in (i.removeprefix('[').split(']', 1) for i in clear_trash(data).split(','))
            }
        elif isinstance(data, dict):
            self.raw_data = data
        else:
            raise TypeError(f'got {data!r} (type {type(data)}) but expected type str | dict')
        self.qualities: tuple[Quality, ...] = *sorted(self.raw_data),
        self.min = int(self.qualities[0]) if self.qualities else 1

    @property
    def last_url(self) -> tuple[VideoURL, ...]:
        """Best quality URL sources."""
        return self[-1].raw_data.popitem()[1]

    def __getitem__(self, item: str | SupportsInt | Iterable | slice):
        """
        >>> self[1080]['ultra']
        {'1080p Ultra': '...'}
        >>> self[360:1080, 2160]
        {'360p': '...', '480p': '...', '720p': '...', '2160p': '...'}
        >>> self[720, 1080]
        {'720p': '...', '1080p': '...', '1080p Ultra': '...'}
        """
        if isinstance(item, str):
            item = item.casefold()
            result = {q: v for q, v in self.raw_data.items() if q.addon == item}
        elif isinstance(item, slice):
            supported = {*range(*item.indices(int(self.qualities[-1]) + 1))}
            result = {q: v for q, v in self.raw_data.items() if int(q) in supported}
        elif isinstance(item, Iterable) and item:
            result = {}
            for part in item:
                if part is not None:
                    result |= self[part].raw_data
        elif isinstance(item, int):
            if item < self.min:
                item = self.qualities[item]
                result = {item: self.raw_data[item]}
            else:
                result = {q: v for q, v in self.raw_data.items() if int(q) == item}
        else:
            raise TypeError(f'Invalid type {type(item)}')
        return self.__class__(result, client=self._client)

    def __repr__(self):
        return f'{self.__class__.__qualname__}({self.raw_data!r})'

Collection of video URLs keyed by quality.

:param data: str — raw URL payload from an AJAX response; dictdict[Quality, tuple[VideoURL, …]]. Other types raise TypeError. :param client: Session used when awaiting video URLs (redirect resolve).

Instance variables

prop last_url : tuple[VideoURL, ...]
Expand source code
@property
def last_url(self) -> tuple[VideoURL, ...]:
    """Best quality URL sources."""
    return self[-1].raw_data.popitem()[1]

Best quality URL sources.

var min
Expand source code
class VideoURLs:
    """Collection of video URLs keyed by quality."""

    __slots__ = ('raw_data', 'qualities', 'min', '_client')

    def __init__(self, data: str | dict, *, client: 'HDRezkaClient | None' = None):
        """
        :param data:
            ``str`` — raw URL payload from an AJAX response;
            ``dict`` — ``dict[Quality, tuple[VideoURL, ...]]``.
            Other types raise ``TypeError``.
        :param client: Session used when awaiting video URLs (redirect resolve).
        """
        self._client = client
        if isinstance(data, str):
            self.raw_data: dict[Quality, tuple[VideoURL, ...]] = {
                Quality(q): (*(VideoURL(i, client=client) for i in u.split(' or ') if i.endswith('.m3u8')),)
                for q, u in (i.removeprefix('[').split(']', 1) for i in clear_trash(data).split(','))
            }
        elif isinstance(data, dict):
            self.raw_data = data
        else:
            raise TypeError(f'got {data!r} (type {type(data)}) but expected type str | dict')
        self.qualities: tuple[Quality, ...] = *sorted(self.raw_data),
        self.min = int(self.qualities[0]) if self.qualities else 1

    @property
    def last_url(self) -> tuple[VideoURL, ...]:
        """Best quality URL sources."""
        return self[-1].raw_data.popitem()[1]

    def __getitem__(self, item: str | SupportsInt | Iterable | slice):
        """
        >>> self[1080]['ultra']
        {'1080p Ultra': '...'}
        >>> self[360:1080, 2160]
        {'360p': '...', '480p': '...', '720p': '...', '2160p': '...'}
        >>> self[720, 1080]
        {'720p': '...', '1080p': '...', '1080p Ultra': '...'}
        """
        if isinstance(item, str):
            item = item.casefold()
            result = {q: v for q, v in self.raw_data.items() if q.addon == item}
        elif isinstance(item, slice):
            supported = {*range(*item.indices(int(self.qualities[-1]) + 1))}
            result = {q: v for q, v in self.raw_data.items() if int(q) in supported}
        elif isinstance(item, Iterable) and item:
            result = {}
            for part in item:
                if part is not None:
                    result |= self[part].raw_data
        elif isinstance(item, int):
            if item < self.min:
                item = self.qualities[item]
                result = {item: self.raw_data[item]}
            else:
                result = {q: v for q, v in self.raw_data.items() if int(q) == item}
        else:
            raise TypeError(f'Invalid type {type(item)}')
        return self.__class__(result, client=self._client)

    def __repr__(self):
        return f'{self.__class__.__qualname__}({self.raw_data!r})'
var qualities
Expand source code
class VideoURLs:
    """Collection of video URLs keyed by quality."""

    __slots__ = ('raw_data', 'qualities', 'min', '_client')

    def __init__(self, data: str | dict, *, client: 'HDRezkaClient | None' = None):
        """
        :param data:
            ``str`` — raw URL payload from an AJAX response;
            ``dict`` — ``dict[Quality, tuple[VideoURL, ...]]``.
            Other types raise ``TypeError``.
        :param client: Session used when awaiting video URLs (redirect resolve).
        """
        self._client = client
        if isinstance(data, str):
            self.raw_data: dict[Quality, tuple[VideoURL, ...]] = {
                Quality(q): (*(VideoURL(i, client=client) for i in u.split(' or ') if i.endswith('.m3u8')),)
                for q, u in (i.removeprefix('[').split(']', 1) for i in clear_trash(data).split(','))
            }
        elif isinstance(data, dict):
            self.raw_data = data
        else:
            raise TypeError(f'got {data!r} (type {type(data)}) but expected type str | dict')
        self.qualities: tuple[Quality, ...] = *sorted(self.raw_data),
        self.min = int(self.qualities[0]) if self.qualities else 1

    @property
    def last_url(self) -> tuple[VideoURL, ...]:
        """Best quality URL sources."""
        return self[-1].raw_data.popitem()[1]

    def __getitem__(self, item: str | SupportsInt | Iterable | slice):
        """
        >>> self[1080]['ultra']
        {'1080p Ultra': '...'}
        >>> self[360:1080, 2160]
        {'360p': '...', '480p': '...', '720p': '...', '2160p': '...'}
        >>> self[720, 1080]
        {'720p': '...', '1080p': '...', '1080p Ultra': '...'}
        """
        if isinstance(item, str):
            item = item.casefold()
            result = {q: v for q, v in self.raw_data.items() if q.addon == item}
        elif isinstance(item, slice):
            supported = {*range(*item.indices(int(self.qualities[-1]) + 1))}
            result = {q: v for q, v in self.raw_data.items() if int(q) in supported}
        elif isinstance(item, Iterable) and item:
            result = {}
            for part in item:
                if part is not None:
                    result |= self[part].raw_data
        elif isinstance(item, int):
            if item < self.min:
                item = self.qualities[item]
                result = {item: self.raw_data[item]}
            else:
                result = {q: v for q, v in self.raw_data.items() if int(q) == item}
        else:
            raise TypeError(f'Invalid type {type(item)}')
        return self.__class__(result, client=self._client)

    def __repr__(self):
        return f'{self.__class__.__qualname__}({self.raw_data!r})'
var raw_data
Expand source code
class VideoURLs:
    """Collection of video URLs keyed by quality."""

    __slots__ = ('raw_data', 'qualities', 'min', '_client')

    def __init__(self, data: str | dict, *, client: 'HDRezkaClient | None' = None):
        """
        :param data:
            ``str`` — raw URL payload from an AJAX response;
            ``dict`` — ``dict[Quality, tuple[VideoURL, ...]]``.
            Other types raise ``TypeError``.
        :param client: Session used when awaiting video URLs (redirect resolve).
        """
        self._client = client
        if isinstance(data, str):
            self.raw_data: dict[Quality, tuple[VideoURL, ...]] = {
                Quality(q): (*(VideoURL(i, client=client) for i in u.split(' or ') if i.endswith('.m3u8')),)
                for q, u in (i.removeprefix('[').split(']', 1) for i in clear_trash(data).split(','))
            }
        elif isinstance(data, dict):
            self.raw_data = data
        else:
            raise TypeError(f'got {data!r} (type {type(data)}) but expected type str | dict')
        self.qualities: tuple[Quality, ...] = *sorted(self.raw_data),
        self.min = int(self.qualities[0]) if self.qualities else 1

    @property
    def last_url(self) -> tuple[VideoURL, ...]:
        """Best quality URL sources."""
        return self[-1].raw_data.popitem()[1]

    def __getitem__(self, item: str | SupportsInt | Iterable | slice):
        """
        >>> self[1080]['ultra']
        {'1080p Ultra': '...'}
        >>> self[360:1080, 2160]
        {'360p': '...', '480p': '...', '720p': '...', '2160p': '...'}
        >>> self[720, 1080]
        {'720p': '...', '1080p': '...', '1080p Ultra': '...'}
        """
        if isinstance(item, str):
            item = item.casefold()
            result = {q: v for q, v in self.raw_data.items() if q.addon == item}
        elif isinstance(item, slice):
            supported = {*range(*item.indices(int(self.qualities[-1]) + 1))}
            result = {q: v for q, v in self.raw_data.items() if int(q) in supported}
        elif isinstance(item, Iterable) and item:
            result = {}
            for part in item:
                if part is not None:
                    result |= self[part].raw_data
        elif isinstance(item, int):
            if item < self.min:
                item = self.qualities[item]
                result = {item: self.raw_data[item]}
            else:
                result = {q: v for q, v in self.raw_data.items() if int(q) == item}
        else:
            raise TypeError(f'Invalid type {type(item)}')
        return self.__class__(result, client=self._client)

    def __repr__(self):
        return f'{self.__class__.__qualname__}({self.raw_data!r})'