text: from ytmusicapi.parsers.explore import *
  
  
  class ExploreMixin:
      def get_mood_categories(self) -> Dict:
          """
          Fetch "Moods & Genres" categories from YouTube Music.
  
          :return: Dictionary of sections and categories.
  
          Example::
  
              {
                  'For you': [
                      {
                          'params': 'ggMPOg1uX1ZwN0pHT2NBT1Fk',
                          'title': '1980s'
                      },
                      {
                          'params': 'ggMPOg1uXzZQbDB5eThLRTQ3',
                          'title': 'Feel Good'
                      },
                      ...
                  ],
                  'Genres': [
                      {
                          'params': 'ggMPOg1uXzVLbmZnaWI4STNs',
                          'title': 'Dance & Electronic'
                      },
                      {
                          'params': 'ggMPOg1uX3NjZllsNGVEMkZo',
                          'title': 'Decades'
                      },
                      ...
                  ],
                  'Moods & moments': [
                      {
                          'params': 'ggMPOg1uXzVuc0dnZlhpV3Ba',
                          'title': 'Chill'
                      },
                      {
                          'params': 'ggMPOg1uX2ozUHlwbWM3ajNq',
                          'title': 'Commute'
                      },
                      ...
                  ],
              }
  
          """
          sections = {}
          response = self._send_request('browse', {'browseId': 'FEmusic_moods_and_genres'})
          for section in nav(response, SINGLE_COLUMN_TAB + SECTION_LIST):
              title = nav(section, GRID + ['header', 'gridHeaderRenderer'] + TITLE_TEXT)
              sections[title] = []
              for category in nav(section, GRID_ITEMS):
                  sections[title].append({
                      "title": nav(category, CATEGORY_TITLE),
                      "params": nav(category, CATEGORY_PARAMS)
                  })
  
          return sections
  
      def get_mood_playlists(self, params: str) -> List[Dict]:
          """
          Retrieve a list of playlists for a given "Moods & Genres" category.
  
          :param params: params obtained by :py:func:`get_mood_categories`
          :return: List of playlists in the format of :py:func:`get_library_playlists`
  
          """
          playlists = []
          response = self._send_request('browse', {
              'browseId': 'FEmusic_moods_and_genres_category',
              'params': params
          })
          for section in nav(response, SINGLE_COLUMN_TAB + SECTION_LIST):
              path = []
              if 'gridRenderer' in section:
                  path = GRID_ITEMS
              elif 'musicCarouselShelfRenderer' in section:
                  path = CAROUSEL_CONTENTS
              elif 'musicImmersiveCarouselShelfRenderer' in section:
                  path = ['musicImmersiveCarouselShelfRenderer', 'contents']
              if len(path):
                  results = nav(section, path)
                  playlists += parse_content_list(results, parse_playlist)
  
          return playlists
  
      def get_charts(self, country: str = 'ZZ') -> Dict:
          """
          Get latest charts data from YouTube Music: Top songs, top videos, top artists and top trending videos.
          Global charts have no Trending section, US charts have an extra Genres section with some Genre charts.
  
          :param country: ISO 3166-1 Alpha-2 country code. Default: ZZ = Global
          :return: Dictionary containing chart songs (only if authenticated), chart videos, chart artists and
              trending videos.
  
          Example::
  
              {
                  "countries": {
                      "selected": {
                          "text": "United States"
                      },
                      "options": ["DE",
                          "ZZ",
                          "ZW"]
                  },
                  "songs": {
                      "playlist": "VLPL4fGSI1pDJn6O1LS0XSdF3RyO0Rq_LDeI",
                      "items": [
                          {
                              "title": "Outside (Better Days)",
                              "videoId": "oT79YlRtXDg",
                              "artists": [
                                  {
                                      "name": "MO3",
                                      "id": "UCdFt4Cvhr7Okaxo6hZg5K8g"
                                  },
                                  {
                                      "name": "OG Bobby Billions",
                                      "id": "UCLusb4T2tW3gOpJS1fJ-A9g"
                                  }
                              ],
                              "thumbnails": [...],
                              "isExplicit": true,
                              "album": {
                                  "name": "Outside (Better Days)",
                                  "id": "MPREb_fX4Yv8frUNv"
                              },
                              "rank": "1",
                              "trend": "up"
                          }
                      ]
                  },
                  "videos": {
                      "playlist": "VLPL4fGSI1pDJn69On1f-8NAvX_CYlx7QyZc",
                      "items": [
                          {
                              "title": "EVERY CHANCE I GET (Official Music Video) (feat. Lil Baby & Lil Durk)",
                              "videoId": "BTivsHlVcGU",
                              "playlistId": "PL4fGSI1pDJn69On1f-8NAvX_CYlx7QyZc",
                              "thumbnails": [],
                              "views": "46M"
                          }
                      ]
                  },
                  "artists": {
                      "playlist": null,
                      "items": [
                          {
                              "title": "YoungBoy Never Broke Again",
                              "browseId": "UCR28YDxjDE3ogQROaNdnRbQ",
                              "subscribers": "9.62M",
                              "thumbnails": [],
                              "rank": "1",
                              "trend": "neutral"
                          }
                      ]
                  },
                  "genres": [
                      {
                          "title": "Top 50 Pop Music Videos United States",
                          "playlistId": "PL4fGSI1pDJn77aK7sAW2AT0oOzo5inWY8",
                          "thumbnails": []
                      }
                  ],
                  "trending": {
                      "playlist": "VLPLrEnWoR732-DtKgaDdnPkezM_nDidBU9H",
                      "items": [
                          {
                              "title": "Permission to Dance",
                              "videoId": "CuklIb9d3fI",
                              "playlistId": "PLrEnWoR732-DtKgaDdnPkezM_nDidBU9H",
                              "artists": [
                                  {
                                      "name": "BTS",
                                      "id": "UC9vrvNSL3xcWGSkV86REBSg"
                                  }
                              ],
                              "thumbnails": [],
                              "views": "108M"
                          }
                      ]
                  }
              }
  
          """
          body = {'browseId': 'FEmusic_charts'}
          if country:
              body['formData'] = {'selectedValues': [country]}
          endpoint = 'browse'
          response = self._send_request(endpoint, body)
          results = nav(response, SINGLE_COLUMN_TAB + SECTION_LIST)
          charts = {'countries': {}}
          menu = nav(
              results[0], MUSIC_SHELF + [
                  'subheaders', 0, 'musicSideAlignedItemRenderer', 'startItems', 0,
                  'musicSortFilterButtonRenderer'
              ])
          charts['countries']['selected'] = nav(menu, TITLE)
          charts['countries']['options'] = list(
              filter(None, [
                  nav(m, ['payload', 'musicFormBooleanChoice', 'opaqueToken'], True)
                  for m in nav(response, FRAMEWORK_MUTATIONS)
              ]))
          charts_categories = ['videos', 'artists']
  
          has_songs = bool(self.auth)
          has_genres = country == 'US'
          has_trending = country != 'ZZ'
          if has_songs:
              charts_categories.insert(0, 'songs')
          if has_genres:
              charts_categories.append('genres')
          if has_trending:
              charts_categories.append('trending')
  
          parse_chart = lambda i, parse_func, key: parse_content_list(
              nav(results[i + has_songs], CAROUSEL_CONTENTS), parse_func, key)
          for i, c in enumerate(charts_categories):
              charts[c] = {
                  'playlist': nav(results[1 + i], CAROUSEL + CAROUSEL_TITLE + NAVIGATION_BROWSE_ID,
                                  True)
              }
  
          if has_songs:
              charts['songs'].update({'items': parse_chart(0, parse_chart_song, MRLIR)})
  
          charts['videos']['items'] = parse_chart(1, parse_video, MTRIR)
          charts['artists']['items'] = parse_chart(2, parse_chart_artist, MRLIR)
  
          if has_genres:
              charts['genres'] = parse_chart(3, parse_playlist, MTRIR)
  
          if has_trending:
              charts['trending']['items'] = parse_chart(3 + has_genres, parse_chart_trending, MRLIR)
  
          return charts
  