Taylor Fox Dahlin commited on
Commit
48ea520
·
unverified ·
1 Parent(s): 1f5162c

Improvement/youtubei (#1029)

Browse files

* Adds functionality for interacting with certain endpoints of the innertube API.

Files changed (1) hide show
  1. pytube/innertube.py +120 -0
pytube/innertube.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """This module is designed to interact with the innertube API.
2
+
3
+ This module is NOT intended to be used directly by end users, as each of the
4
+ interfaces returns raw results. These should instead be parsed to extract
5
+ the useful information for the end user.
6
+ """
7
+ # Native python imports
8
+ import json
9
+ from urllib import parse
10
+
11
+ # Local imports
12
+ from pytube import request
13
+
14
+
15
+ class InnerTube:
16
+ """Object for interacting with the innertube API."""
17
+ @property
18
+ def base_url(self):
19
+ """Return the base url endpoint for the innertube API."""
20
+ return 'https://www.youtube.com/youtubei/v1'
21
+
22
+ @property
23
+ def base_data(self):
24
+ """Return the base json data to transmit to the innertube API."""
25
+ return {
26
+ 'context': {
27
+ 'client': {
28
+ 'clientName': 'WEB',
29
+ 'clientVersion': '2.20200720.00.02'
30
+ }
31
+ }
32
+ }
33
+
34
+ @property
35
+ def base_params(self):
36
+ """Return the base query parameters to transmit to the innertube API."""
37
+ return {
38
+ 'key': 'AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8'
39
+ }
40
+
41
+ def _call_api(self, endpoint, query, data):
42
+ """Make a request to a given endpoint with the provided query parameters and data."""
43
+ endpoint_url = f'{endpoint}?{parse.urlencode(query)}'
44
+ response = request._execute_request(
45
+ endpoint_url,
46
+ 'POST',
47
+ headers={
48
+ 'Content-Type': 'application/json',
49
+ },
50
+ data=data
51
+ )
52
+ return json.loads(response.read())
53
+
54
+ def browse(self):
55
+ """Make a request to the browse endpoint.
56
+
57
+ TODO: Figure out how we can use this
58
+ """
59
+ # endpoint = f'{self.base_url}/browse' # noqa:E800
60
+ ...
61
+ # return self._call_api(endpoint, query, self.base_data) # noqa:E800
62
+
63
+ def config(self):
64
+ """Make a request to the config endpoint.
65
+
66
+ TODO: Figure out how we can use this
67
+ """
68
+ # endpoint = f'{self.base_url}/config' # noqa:E800
69
+ ...
70
+ # return self._call_api(endpoint, query, self.base_data) # noqa:E800
71
+
72
+ def guide(self):
73
+ """Make a request to the guide endpoint.
74
+
75
+ TODO: Figure out how we can use this
76
+ """
77
+ # endpoint = f'{self.base_url}/guide' # noqa:E800
78
+ ...
79
+ # return self._call_api(endpoint, query, self.base_data) # noqa:E800
80
+
81
+ def next(self):
82
+ """Make a request to the next endpoint.
83
+
84
+ TODO: Figure out how we can use this
85
+ """
86
+ # endpoint = f'{self.base_url}/next' # noqa:E800
87
+ ...
88
+ # return self._call_api(endpoint, query, self.base_data) # noqa:E800
89
+
90
+ def player(self, video_id):
91
+ """Make a request to the player endpoint.
92
+
93
+ :param str video_id:
94
+ The video id to get player info for.
95
+ :rtype: dict
96
+ :returns:
97
+ Raw player info results.
98
+ """
99
+ endpoint = f'{self.base_url}/player'
100
+ query = {
101
+ 'videoId': video_id,
102
+ }
103
+ query.update(self.base_params)
104
+ return self._call_api(endpoint, query, self.base_data)
105
+
106
+ def search(self, search_query):
107
+ """Make a request to the search endpoint.
108
+
109
+ :param str search_query:
110
+ The query to search.
111
+ :rtype: dict
112
+ :returns:
113
+ Raw search query results.
114
+ """
115
+ endpoint = f'{self.base_url}/search'
116
+ query = {
117
+ 'query': search_query
118
+ }
119
+ query.update(self.base_params)
120
+ return self._call_api(endpoint, query, self.base_data)