From 67b4a3bc650f48180f22d27b6f2541cf0e80667c Mon Sep 17 00:00:00 2001 From: Hellow2 Date: Tue, 23 May 2023 16:21:12 +0200 Subject: [PATCH] cleaned up search --- src/music_kraken/pages/abstract.py | 77 +++++++++++-------- .../pages/encyclopaedia_metallum.py | 53 +++++-------- .../utils/support_classes/query.py | 6 +- 3 files changed, 72 insertions(+), 64 deletions(-) diff --git a/src/music_kraken/pages/abstract.py b/src/music_kraken/pages/abstract.py index d5502e3..4e5495f 100644 --- a/src/music_kraken/pages/abstract.py +++ b/src/music_kraken/pages/abstract.py @@ -2,6 +2,7 @@ import logging import random from copy import copy from typing import Optional, Union, Type, Dict, Set, List +import threading import requests from bs4 import BeautifulSoup @@ -25,52 +26,66 @@ from ..utils import shared from ..utils.support_classes import Query, DownloadResult, DefaultTarget -class Page: +class Page(threading.Thread): """ This is an abstract class, laying out the functionality for every other class fetching something """ - CONNECTION: Connection - - API_SESSION: requests.Session = requests.Session() - API_SESSION.proxies = shared.proxies - TIMEOUT = 5 - POST_TIMEOUT = TIMEOUT - TRIES = 5 - LOGGER = logging.getLogger("this shouldn't be used") SOURCE_TYPE: SourcePages + LOGGER = logging.getLogger("this shouldn't be used") + def __init__(self): + threading.Thread.__init__(self) + @classmethod def get_soup_from_response(cls, r: requests.Response) -> BeautifulSoup: return BeautifulSoup(r.content, "html.parser") - @classmethod - def search(cls, query: Query) -> Options: + # to search stuff + def search(self, query: Query) -> List[DatabaseObject]: results = [] - for default_query in query.default_search: - results.extend(cls._raw_search(default_query)) + if query.is_raw: + for search_query in query.default_search: + results.extend(self.general_search(search_query)) + return results - return Options(results) - - @classmethod - def _raw_search(cls, query: str) -> Options: - """ - # The Query - You can define a new parameter with "#", - the letter behind it defines the *type* of parameter, followed by a space - "#a Psychonaut 4 #r Tired, Numb and #t Drop by Drop" - if no # is in the query it gets treated as "unspecified query" - - # Functionality - Returns the best matches from this page for the query, passed in. - - :param query: - :return possible_music_objects: - """ - + music_object = query.music_object + + search_functions = { + Song: self.song_search, + Album: self.album_search, + Artist: self.artist_search, + Label: self.label_search + } + + if type(music_object) in search_functions: + r = search_functions[type(music_object)](music_object) + if len(r) > 0: + return r + + r = [] + for default_query in query.default_search: + results.extend(self.general_search(default_query)) + + return results + + def general_search(self, search_query: str) -> List[DatabaseObject]: return [] + + def label_search(self, label: Label) -> List[Label]: + return [] + + def artist_search(self, artist: Artist) -> List[Artist]: + return [] + + def album_search(self, album: Album) -> List[Album]: + return [] + + def song_search(self, song: Song) -> List[Song]: + return [] + @classmethod def fetch_details(cls, music_object: Union[Song, Album, Artist, Label], stop_at_level: int = 1) -> DatabaseObject: diff --git a/src/music_kraken/pages/encyclopaedia_metallum.py b/src/music_kraken/pages/encyclopaedia_metallum.py index 553b0b3..364ff85 100644 --- a/src/music_kraken/pages/encyclopaedia_metallum.py +++ b/src/music_kraken/pages/encyclopaedia_metallum.py @@ -23,6 +23,17 @@ from ..objects import ( ) +ALBUM_TYPE_MAP: Dict[str, AlbumType] = defaultdict(lambda: AlbumType.OTHER, { + "Full-length": AlbumType.STUDIO_ALBUM, + "Single": AlbumType.SINGLE, + "EP": AlbumType.EP, + "Demo": AlbumType.DEMO, + "Video": AlbumType.OTHER, + "Live album": AlbumType.LIVE_ALBUM, + "Compilation": AlbumType.COMPILATION_ALBUM +}) + + class EncyclopaediaMetallum(Page): CONNECTION: Connection = Connection( host="https://www.metal-archives.com/", @@ -30,36 +41,14 @@ class EncyclopaediaMetallum(Page): ) SOURCE_TYPE = SourcePages.ENCYCLOPAEDIA_METALLUM - - ALBUM_TYPE_MAP: Dict[str, AlbumType] = defaultdict(lambda: AlbumType.OTHER, { - "Full-length": AlbumType.STUDIO_ALBUM, - "Single": AlbumType.SINGLE, - "EP": AlbumType.EP, - "Demo": AlbumType.DEMO, - "Video": AlbumType.OTHER, - "Live album": AlbumType.LIVE_ALBUM, - "Compilation": AlbumType.COMPILATION_ALBUM - }) LOGGER = ENCYCLOPAEDIA_METALLUM_LOGGER - - @classmethod - def _raw_search(cls, query: str) -> Options: - query_obj = cls.Query(query) - - if query_obj.is_raw: - return cls.simple_search(query_obj) - return cls.advanced_search(query_obj) - - @classmethod - def advanced_search(cls, query: Query) -> Options: - if query.song is not None: - return Options(cls.search_for_song(query=query)) - if query.album is not None: - return Options(cls.search_for_album(query=query)) - if query.artist is not None: - return Options(cls.search_for_artist(query=query)) - return Options + + def __init__(self): + self.connection: Connection = Connection( + host="https://www.metal-archives.com/", + logger=ENCYCLOPAEDIA_METALLUM_LOGGER + ) @classmethod def search_for_song(cls, query: Query) -> List[Song]: @@ -123,7 +112,7 @@ class EncyclopaediaMetallum(Page): ] @classmethod - def simple_search(cls, query: Query) -> List[Artist]: + def _raw_search(cls, query: str) -> Options: """ Searches the default endpoint from metal archives, which intern searches only for bands, but it is the default, thus I am rolling with it @@ -132,12 +121,12 @@ class EncyclopaediaMetallum(Page): r = cls.CONNECTION.get(endpoint.format(query=query)) if r is None: - return [] + return Options() - return [ + return Options([ cls.get_artist_from_json(artist_html=raw_artist[0], genre=raw_artist[1], country=raw_artist[2]) for raw_artist in r.json()['aaData'] - ] + ]) @classmethod def get_artist_from_json(cls, artist_html=None, genre=None, country=None) -> Artist: diff --git a/src/music_kraken/utils/support_classes/query.py b/src/music_kraken/utils/support_classes/query.py index dd492d6..239096b 100644 --- a/src/music_kraken/utils/support_classes/query.py +++ b/src/music_kraken/utils/support_classes/query.py @@ -9,7 +9,11 @@ class Query: music_object: DatabaseObject = None ) -> None: self.raw_query: str = raw_query - self.music_object: Optional[DatabaseObject] = None + self.music_object: Optional[DatabaseObject] = music_object + + @property + def is_raw(self) -> bool: + return self.music_object is None @property def default_search(self) -> List[str]: