from apollo_utils.core.constants.dsp import DSP_SPOTIFY_APPLE from sqlalchemy import func, text from typing import List, Optional from apollo_main_db.apollo.models import BuzzUser from src.constants.core import MusicServices from src.constants.order import SortOrder from src.constants.users.search import UsersSearchInclude, UsersSearchSortBy from src.db.base import session from src.legacy.spotify.constants import SPOTIFY_USER_IMAGE_PREFIX, SPOTIFY_USER_URI_PREFIX def format_user_uri(value: Optional[str]) -> Optional[str]: """Format user URI. Args: value: Original value. Returns: Formatted value. """ if value and "open.spotify.com/user" not in value and not value.startswith(SPOTIFY_USER_URI_PREFIX): return SPOTIFY_USER_URI_PREFIX + value return value def format_search_result(item_list: list) -> List[dict]: """Format search result. Args: item_list: Result list. Returns: Formatted result. """ result = [] for item in item_list: item = item._asdict() if item.get("uri"): item["uri"] = format_user_uri(item["uri"]) if item.get("image"): item["image"] = SPOTIFY_USER_IMAGE_PREFIX + item["image"] result.append(item) return result def search_users( search_term: Optional[str], dsp_list: Optional[List[DSP_SPOTIFY_APPLE]], country_code_list: Optional[List[str]], category_id_list: Optional[List[int]], music_service_list: Optional[List[int]], service_type_list: Optional[List[int]], include_list: Optional[List[UsersSearchInclude]], sort_by: UsersSearchSortBy, sort_order: SortOrder, limit: Optional[int], ) -> List[dict]: """Search users. Args: search_term: Text to search. dsp_list: DSP list filter. country_code_list: Country code filter. category_id_list: Category ID filter. music_service_list: Music service ID filter. service_type_list: Service type filter. include_list: Include fields. sort_by: Order by column. sort_order: Sort order (asc or desc). limit: Max items count. Returns: Emails query. """ field_list = [] for item in include_list: if item == UsersSearchInclude.NAME: field_list.append(func.IFNULL(BuzzUser.display_name, BuzzUser.user_name).label("name")) elif item == UsersSearchInclude.URI: field_list.append(BuzzUser.user_name.label("uri")) else: field_list.append(getattr(BuzzUser, item.value)) query = session.query(*field_list) if search_term: # TODO: after sqlalchemy update replace with # https://docs.sqlalchemy.org/en/14/dialects/mysql.html#sqlalchemy.dialects.mysql.match query = query.filter( text("MATCH(DisplayName, Username) AGAINST (:search_term IN BOOLEAN MODE)").bindparams( search_term=search_term ) ) if dsp_list: music_service_id_list = [ (MusicServices.SPOTIFY if dsp.value == DSP_SPOTIFY_APPLE.SPOTIFY.value else MusicServices.APPLEMUSIC) for dsp in dsp_list ] query = query.filter(BuzzUser.music_service.in_(music_service_id_list)) if country_code_list: query = query.filter(BuzzUser.country_code.in_(country_code_list)) if category_id_list: query = query.filter(BuzzUser.category_id.in_(category_id_list)) if music_service_list: query = query.filter(BuzzUser.music_service.in_(music_service_list)) if service_type_list: query = query.filter(BuzzUser.service_type.in_(service_type_list)) if hasattr(BuzzUser, sort_by.value): field = getattr(BuzzUser, sort_by.value) field = field.asc() if sort_order == SortOrder.ASC else field.desc() query = query.order_by(field) query = query.limit(limit) return format_search_result(query.all())