From ba97624b279dc9e01cc7a76ec636c62556e0d55f Mon Sep 17 00:00:00 2001 From: Tom Bulled <26026015+tombulled@users.noreply.github.com> Date: Mon, 27 May 2024 23:07:34 +0100 Subject: [PATCH] Add support for explicit albums --- app.py | 12 +++++++++ youtubei/enums/music.py | 13 ++++++++++ youtubei/enums/other.py | 5 ++++ youtubei/renderers/__init__.py | 11 +++++--- youtubei/renderers/music_carousel_shelf.py | 9 ++++++- .../music_carousel_shelf_basic_header.py | 14 ++++++++++ youtubei/renderers/music_detail_header.py | 4 ++- youtubei/renderers/music_play_button.py | 2 +- youtubei/renderers/music_two_row_item.py | 26 +++++++++++++++++++ 9 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 app.py create mode 100644 youtubei/renderers/music_carousel_shelf_basic_header.py create mode 100644 youtubei/renderers/music_two_row_item.py diff --git a/app.py b/app.py new file mode 100644 index 0000000..89e9b17 --- /dev/null +++ b/app.py @@ -0,0 +1,12 @@ +from youtubei import WEB_REMIX +from rich.pretty import pprint as pp + +# d = WEB_REMIX.browse_album("MPREb_DIJctBnvRk5") # Slaves - Are You Satisfied? +d = WEB_REMIX.client.adaptor.dispatch("browse", body={"browseId": "MPREb_DIJctBnvRk5"}) + +h = d["header"]["musicDetailHeaderRenderer"] +c = d["contents"]["singleColumnBrowseResultsRenderer"]["tabs"][0]["tabRenderer"][ + "content" +]["sectionListRenderer"]["contents"] + +p = WEB_REMIX.parser.browse_album(d) diff --git a/youtubei/enums/music.py b/youtubei/enums/music.py index b5f2d4f..fa51b09 100644 --- a/youtubei/enums/music.py +++ b/youtubei/enums/music.py @@ -1,6 +1,7 @@ from ._base import StrEnum __all__ = ( + "MusicCarouselShelfBasicHeaderStyle", "MusicItemThumbnailOverlayContentPosition", "MusicItemThumbnailOverlayDisplayStyle", "MusicPlayButtonRippleTarget", @@ -11,16 +12,23 @@ "MusicResponsiveListItemFlexColumnDisplayStyle", "MusicThumbnailCrop", "MusicThumbnailScale", + "MusicTwoRowItemThumbnailAspectRatio", "MusicVideoType", ) +class MusicCarouselShelfBasicHeaderStyle(StrEnum): + DEFAULT: str = "MUSIC_CAROUSEL_SHELF_BASIC_HEADER_STYLE_DEFAULT" + + class MusicItemThumbnailOverlayContentPosition(StrEnum): CENTERED: str = "MUSIC_ITEM_THUMBNAIL_OVERLAY_CONTENT_POSITION_CENTERED" + BOTTOM_RIGHT: str = "MUSIC_ITEM_THUMBNAIL_OVERLAY_CONTENT_POSITION_BOTTOM_RIGHT" class MusicItemThumbnailOverlayDisplayStyle(StrEnum): PERSISTENT: str = "MUSIC_ITEM_THUMBNAIL_OVERLAY_DISPLAY_STYLE_PERSISTENT" + HOVER: str = "MUSIC_ITEM_THUMBNAIL_OVERLAY_DISPLAY_STYLE_HOVER" class MusicPlayButtonRippleTarget(StrEnum): @@ -29,6 +37,7 @@ class MusicPlayButtonRippleTarget(StrEnum): class MusicPlayButtonSize(StrEnum): SMALL: str = "MUSIC_PLAY_BUTTON_SIZE_SMALL" + MEDIUM: str = "MUSIC_PLAY_BUTTON_SIZE_MEDIUM" class MusicResponsiveListItemColumnDisplayPriority(StrEnum): @@ -62,6 +71,10 @@ class MusicThumbnailScale(StrEnum): UNSPECIFIED: str = "MUSIC_THUMBNAIL_SCALE_UNSPECIFIED" +class MusicTwoRowItemThumbnailAspectRatio(StrEnum): + SQUARE: str = "MUSIC_TWO_ROW_ITEM_THUMBNAIL_ASPECT_RATIO_SQUARE" + + class MusicVideoType(StrEnum): ATV: str = "MUSIC_VIDEO_TYPE_ATV" OMV: str = "MUSIC_VIDEO_TYPE_OMV" diff --git a/youtubei/enums/other.py b/youtubei/enums/other.py index e00427f..2ae18ef 100644 --- a/youtubei/enums/other.py +++ b/youtubei/enums/other.py @@ -8,6 +8,7 @@ "CaptionsInitialState", "Category", "CheckboxCheckedState", + "CollectionStyleItemSize", "CountryCode", "EndscreenElementStyle", "EngagementPanelVisibility", @@ -80,6 +81,10 @@ class CheckboxCheckedState(StrEnum): UNCHECKED: str = "CHECKBOX_CHECKED_STATE_UNCHECKED" +class CollectionStyleItemSize(StrEnum): + MEDIUM: str = "COLLECTION_STYLE_ITEM_SIZE_MEDIUM" + + class CountryCode(StrEnum): AD: str = "AD" AE: str = "AE" diff --git a/youtubei/renderers/__init__.py b/youtubei/renderers/__init__.py index 0a0b0af..272abe1 100644 --- a/youtubei/renderers/__init__.py +++ b/youtubei/renderers/__init__.py @@ -51,6 +51,8 @@ from .music_card_shelf import MusicCardShelfRenderer from .music_card_shelf_header_basic import MusicCardShelfHeaderBasicRenderer from .music_carousel_shelf import MusicCarouselShelfRenderer +from .music_carousel_shelf_basic_header import \ + MusicCarouselShelfBasicHeaderRenderer from .music_data_bound_menu import MusicDataBoundMenuRenderer from .music_detail_header import MusicDetailHeaderRenderer from .music_inline_badge import MusicInlineBadgeRenderer @@ -58,12 +60,12 @@ from .music_play_button import MusicPlayButtonRenderer from .music_playlist_shelf import MusicPlaylistShelfRenderer from .music_responsive_list_item import MusicResponsiveListItemRenderer -from .music_responsive_list_item_flex_column import ( - MusicResponsiveListItemFlexColumnRenderer, -) +from .music_responsive_list_item_flex_column import \ + MusicResponsiveListItemFlexColumnRenderer from .music_shelf import MusicShelfRenderer from .music_shelf_divider import MusicShelfDividerRenderer from .music_thumbnail import MusicThumbnailRenderer +from .music_two_row_item import MusicTwoRowItemRenderer from .notification_text import NotificationTextRenderer from .pivot_bar import PivotBarRenderer from .pivot_bar_item import PivotBarItemRenderer @@ -73,7 +75,8 @@ from .player_bytes_sequential_layout import PlayerBytesSequentialLayoutRenderer from .player_captions_tracklist import PlayerCaptionsTracklistRenderer from .player_error_message import PlayerErrorMessageRenderer -from .player_legacy_desktop_watch_ads import PlayerLegacyDesktopWatchAdsRenderer +from .player_legacy_desktop_watch_ads import \ + PlayerLegacyDesktopWatchAdsRenderer from .player_microformat import PlayerMicroformatRenderer from .player_storyboard_spec import PlayerStoryboardSpecRenderer from .playlist_byline import PlaylistBylineRenderer diff --git a/youtubei/renderers/music_carousel_shelf.py b/youtubei/renderers/music_carousel_shelf.py index b3629f2..4a49b22 100644 --- a/youtubei/renderers/music_carousel_shelf.py +++ b/youtubei/renderers/music_carousel_shelf.py @@ -1,3 +1,8 @@ +from typing import Sequence +from youtubei.enums.other import CollectionStyleItemSize +from youtubei.parse.validated_types import Dynamic +from youtubei.renderers.music_carousel_shelf_basic_header import MusicCarouselShelfBasicHeaderRenderer +from youtubei.renderers.music_two_row_item import MusicTwoRowItemRenderer from .._registries import WEB_REMIX_REGISTRY from ._base import BaseRenderer @@ -6,4 +11,6 @@ @WEB_REMIX_REGISTRY class MusicCarouselShelfRenderer(BaseRenderer): - pass + header: Dynamic[MusicCarouselShelfBasicHeaderRenderer] + contents: Sequence[Dynamic[MusicTwoRowItemRenderer]] + item_size: CollectionStyleItemSize diff --git a/youtubei/renderers/music_carousel_shelf_basic_header.py b/youtubei/renderers/music_carousel_shelf_basic_header.py new file mode 100644 index 0000000..3f014c4 --- /dev/null +++ b/youtubei/renderers/music_carousel_shelf_basic_header.py @@ -0,0 +1,14 @@ +from youtubei.enums.music import MusicCarouselShelfBasicHeaderStyle +from youtubei.models.accessibility import Accessibility +from youtubei.models.text import ComplexText +from .._registries import WEB_REMIX_REGISTRY +from ._base import BaseRenderer + +__all__ = ("MusicCarouselShelfBasicHeaderRenderer",) + + +@WEB_REMIX_REGISTRY +class MusicCarouselShelfBasicHeaderRenderer(BaseRenderer): + title: ComplexText + accessibility_data: Accessibility + header_style: MusicCarouselShelfBasicHeaderStyle diff --git a/youtubei/renderers/music_detail_header.py b/youtubei/renderers/music_detail_header.py index 7b9fe85..0a5cb45 100644 --- a/youtubei/renderers/music_detail_header.py +++ b/youtubei/renderers/music_detail_header.py @@ -1,9 +1,10 @@ -from typing import Optional +from typing import Optional, Sequence from youtubei.models.text import ComplexText from youtubei.parse.validated_types import Dynamic from youtubei.renderers.cropped_square_thumbnail import CroppedSquareThumbnailRenderer from youtubei.renderers.menu import MenuRenderer +from youtubei.renderers.music_inline_badge import MusicInlineBadgeRenderer from youtubei.renderers.toggle_button import ToggleButtonRenderer from .._registries import WEB_REMIX_REGISTRY @@ -21,3 +22,4 @@ class MusicDetailHeaderRenderer(BaseRenderer): description: Optional[ComplexText] = None more_button: Dynamic[ToggleButtonRenderer] second_subtitle: ComplexText + subtitle_badges: Optional[Sequence[Dynamic[MusicInlineBadgeRenderer]]] diff --git a/youtubei/renderers/music_play_button.py b/youtubei/renderers/music_play_button.py index cd0d4ce..2468524 100644 --- a/youtubei/renderers/music_play_button.py +++ b/youtubei/renderers/music_play_button.py @@ -24,7 +24,7 @@ class MusicPlayButtonRenderer(BaseRenderer): loading_indicator_color: int playing_icon: Icon icon_loading_color: int - active_scale_factor: int + active_scale_factor: float button_size: MusicPlayButtonSize ripple_target: MusicPlayButtonRippleTarget accessibility_play_data: Accessibility diff --git a/youtubei/renderers/music_two_row_item.py b/youtubei/renderers/music_two_row_item.py new file mode 100644 index 0000000..640a4a4 --- /dev/null +++ b/youtubei/renderers/music_two_row_item.py @@ -0,0 +1,26 @@ +from typing import Sequence +from youtubei.enums.music import MusicTwoRowItemThumbnailAspectRatio +from youtubei.models.endpoints import BrowseEndpoint +from youtubei.models.text import ComplexText +from youtubei.parse.validated_types import Dynamic +from youtubei.renderers.menu import MenuRenderer +from youtubei.renderers.music_inline_badge import MusicInlineBadgeRenderer +from youtubei.renderers.music_item_thumbnail_overlay import MusicItemThumbnailOverlayRenderer +from youtubei.renderers.music_thumbnail import MusicThumbnailRenderer +from youtubei.validated_types import DynamicCommand +from .._registries import WEB_REMIX_REGISTRY +from ._base import BaseRenderer + +__all__ = ("MusicTwoRowItemRenderer",) + + +@WEB_REMIX_REGISTRY +class MusicTwoRowItemRenderer(BaseRenderer): + thumbnail_renderer: Dynamic[MusicThumbnailRenderer] + aspect_ratio: MusicTwoRowItemThumbnailAspectRatio + title: ComplexText + subtitle: ComplexText + navigation_endpoint: DynamicCommand[BrowseEndpoint] + menu: Dynamic[MenuRenderer] + thumbnail_overlay: Dynamic[MusicItemThumbnailOverlayRenderer] + subtitle_badges: Sequence[Dynamic[MusicInlineBadgeRenderer]]