finished first search functionality
This commit is contained in:
parent
d819450e4b
commit
c4f10e7906
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
what is it | query | file
|
what is it | query | file
|
||||||
---|---|---
|
---|---|---
|
||||||
general search response | `psychonaut 4`, [general-result.json](general-result.json)
|
general search response | `psychonaut 4` | [general-result.json](general-result.json)
|
||||||
|
|
||||||
## A general search yields
|
## A general search yields
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ if __name__ == "__main__":
|
|||||||
]
|
]
|
||||||
|
|
||||||
youtube_music_test = [
|
youtube_music_test = [
|
||||||
"s: psychonaut 4"
|
"s: billie eilish"
|
||||||
]
|
]
|
||||||
|
|
||||||
music_kraken.cli.download(genre="test", command_list=youtube_music_test, process_metadata_anyway=True)
|
music_kraken.cli.download(genre="test", command_list=youtube_music_test, process_metadata_anyway=True)
|
||||||
|
37
src/music_kraken/pages/youtube_music/_list_render.py
Normal file
37
src/music_kraken/pages/youtube_music/_list_render.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
from typing import List, Optional
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
from ...utils.shared import YOUTUBE_MUSIC_LOGGER as LOGGER
|
||||||
|
from ...objects import Source, DatabaseObject
|
||||||
|
from ..abstract import Page
|
||||||
|
from ...objects import (
|
||||||
|
Artist,
|
||||||
|
Source,
|
||||||
|
SourcePages,
|
||||||
|
Song,
|
||||||
|
Album,
|
||||||
|
Label,
|
||||||
|
Target
|
||||||
|
)
|
||||||
|
from ._music_object_render import parse_run_list
|
||||||
|
|
||||||
|
|
||||||
|
def music_card_shelf_renderer(renderer: dict) -> List[DatabaseObject]:
|
||||||
|
return parse_run_list(renderer.get("title", {}).get("runs", []))
|
||||||
|
|
||||||
|
|
||||||
|
RENDERER_PARSERS = {
|
||||||
|
"musicCardShelfRenderer": music_card_shelf_renderer
|
||||||
|
}
|
||||||
|
|
||||||
|
def parse_renderer(renderer: dict) -> List[DatabaseObject]:
|
||||||
|
result: List[DatabaseObject] = []
|
||||||
|
|
||||||
|
for renderer_name, renderer in renderer.items():
|
||||||
|
if renderer_name not in RENDERER_PARSERS:
|
||||||
|
LOGGER.warning(f"Can't parse the renderer {renderer_name}.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
result.extend(RENDERER_PARSERS[renderer_name](renderer))
|
||||||
|
|
||||||
|
return result
|
56
src/music_kraken/pages/youtube_music/_music_object_render.py
Normal file
56
src/music_kraken/pages/youtube_music/_music_object_render.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
from typing import List, Optional
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
from ...objects import Source, DatabaseObject
|
||||||
|
from ..abstract import Page
|
||||||
|
from ...objects import (
|
||||||
|
Artist,
|
||||||
|
Source,
|
||||||
|
SourcePages,
|
||||||
|
Song,
|
||||||
|
Album,
|
||||||
|
Label,
|
||||||
|
Target
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
SOURCE_PAGE = SourcePages.YOUTUBE_MUSIC
|
||||||
|
|
||||||
|
|
||||||
|
class PageType(Enum):
|
||||||
|
ARTIST = "MUSIC_PAGE_TYPE_ARTIST"
|
||||||
|
ALBUM = "MUSIC_PAGE_TYPE_ALBUM"
|
||||||
|
CHANNEL = "MUSIC_PAGE_TYPE_USER_CHANNEL"
|
||||||
|
PLAYLIST = "MUSIC_PAGE_TYPE_PLAYLIST"
|
||||||
|
|
||||||
|
|
||||||
|
def parse_run_element(run_element: dict) -> Optional[DatabaseObject]:
|
||||||
|
navigation_endpoint = run_element.get("navigationEndpoint", {}).get("browseEndpoint", {})
|
||||||
|
|
||||||
|
element_type = PageType(navigation_endpoint.get("browseEndpointContextSupportedConfigs", {}).get("browseEndpointContextMusicConfig", {}).get("pageType", ""))
|
||||||
|
|
||||||
|
element_id = navigation_endpoint.get("browseId")
|
||||||
|
element_text = run_element.get("text")
|
||||||
|
|
||||||
|
if element_id is None or element_text is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if element_type == PageType.ARTIST:
|
||||||
|
source = Source(SOURCE_PAGE, f"https://music.youtube.com/channel/{element_id}")
|
||||||
|
return Artist(name=element_text, source_list=[source])
|
||||||
|
|
||||||
|
|
||||||
|
def parse_run_list(run_list: List[dict]) -> List[DatabaseObject]:
|
||||||
|
music_object_list: List[DatabaseObject] = []
|
||||||
|
|
||||||
|
for run_renderer in run_list:
|
||||||
|
if "navigationEndpoint" not in run_renderer:
|
||||||
|
continue
|
||||||
|
|
||||||
|
music_object = parse_run_element(run_renderer)
|
||||||
|
if music_object is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
music_object_list.append(music_object)
|
||||||
|
|
||||||
|
return music_object_list
|
@ -27,6 +27,8 @@ from ...objects import (
|
|||||||
from ...connection import Connection
|
from ...connection import Connection
|
||||||
from ...utils.support_classes import DownloadResult
|
from ...utils.support_classes import DownloadResult
|
||||||
|
|
||||||
|
from ._list_render import parse_renderer
|
||||||
|
|
||||||
|
|
||||||
def get_youtube_url(path: str = "", params: str = "", query: str = "", fragment: str = "") -> str:
|
def get_youtube_url(path: str = "", params: str = "", query: str = "", fragment: str = "") -> str:
|
||||||
return urlunparse(("https", "music.youtube.com", path, params, query, fragment))
|
return urlunparse(("https", "music.youtube.com", path, params, query, fragment))
|
||||||
@ -265,9 +267,10 @@ class YoutubeMusic(Page):
|
|||||||
for i, content in enumerate(renderer_list):
|
for i, content in enumerate(renderer_list):
|
||||||
dump_to_file(f"{i}-renderer.json", json.dumps(content), is_json=True, exit_after_dump=False)
|
dump_to_file(f"{i}-renderer.json", json.dumps(content), is_json=True, exit_after_dump=False)
|
||||||
|
|
||||||
return [
|
results = []
|
||||||
Song(title="Lore Ipsum")
|
results.extend(parse_renderer(renderer_list[1]))
|
||||||
]
|
|
||||||
|
return results
|
||||||
|
|
||||||
def label_search(self, label: Label) -> List[Label]:
|
def label_search(self, label: Label) -> List[Label]:
|
||||||
return []
|
return []
|
||||||
|
Loading…
Reference in New Issue
Block a user