Files
YouTube.js/lib/parser/contents
LuanRT 8a5073b0b9 refactor: rewrite search suggestions logic (#92)
* refactor: rewrite YouTube Music search suggestions

The search suggestions method can be found under `Innertube#music.getSearchSuggestions(query)`

* feat: allow `execute(..)` to return parsed data

This simplifies how response data is handled and also makes it easier for end users to write custom functionality.

* style: lint code

* chore: change a few things

* refactor: rewrite YouTube search suggestions

* chore(package): build

* chore: update type declarations

* chore: fix tests
2022-07-10 17:30:20 -03:00
..

Parser

Sanitizes and standardizes InnerTube responses while maintaining the integrity of the data. Also drastically improves how API calls are made and handled.

Note: This will eventually replace the old parser.

API

parse(data)

Responsible for parsing specifically the contents property of the response object.

Param Type Description
data object The contents property

Returns: object

parseResponse(data)

Unlike parse, this can be used to parse the entire response object.

Param Type Description
data object Raw InnerTube response

Returns: object

How it works

If you decompile a YouTube client and analize it for a while you will notice that it has classes named protos/youtube/api/innertube/MusicItemRenderer, protos/youtube/api/innertube/SectionListRenderer, etc.

These classes are used to parse objects from the response (which consists of protobuf messages) and also build requests. The website works in a similar way, the difference is that it uses plain JSON (likely converted from protobuf server-side, hence the weird structure of the response).

Here we're taking a similar approach, the parser goes through all the renderers and parses their inner element(s). The final result is a nicely structured JSON, and on top of that it also parses navigation endpoints which allows us to make an API call with all required parameters in one line and even emulate client actions (eg; clicking a button).

Here is your average, arguably ugly InnerTube response:

Click to see

{
  sidebar: {
    playlistSidebarRenderer: {
      items: [
        {
          playlistSidebarPrimaryInfoRenderer: {
            title: {
              simpleText: '..'
            },
            description: {
              runs: [
                {
                  text: '..'
                },
                //....
              ]
            },
            stats: [
              {
                simpleText: '..'
              },
              {
                runs: [
                  {
                    text: '..'
                  }
                ]
              }
            ]
          }
        }
      ]
    }
  }
}

And what we get after parsing it:

Click to see

{
  sidebar: {
    type: 'PlaylistSidebar',
    contents: [
      {
        type: 'PlaylistSidebarPrimaryInfo',
        title: { text: '..' },
        description: { text: '..' },
        stats: [
          {
            text: '..'
          },
          {
            text: '..'
          }
        ]
      }
    ]
  }
}