Taylor Fox Dahlin commited on
Commit
cc6b4aa
·
unverified ·
1 Parent(s): ce8901c

Selection of bugfixes and improvements (#1090)

Browse files

* Change Search client to WEB.

* Add documentation for oauth functionality.

* Return raw 'last_updated' string where it is not parseable.

docs/user/quickstart.rst CHANGED
@@ -41,7 +41,9 @@ when you create a YouTube object::
41
  'http://youtube.com/watch?v=2lAe1cqCOXo',
42
  on_progress_callback=progress_func,
43
  on_complete_callback=complete_func,
44
- proxies=my_proxies
 
 
45
  )
46
 
47
  When instantiating a YouTube object, these named arguments can be passed in to
@@ -57,5 +59,12 @@ downloaded, and is called with two arguments: the stream and the file path.
57
  This could be used, for example, to perform post-download processing on a video
58
  like trimming the length of it.
59
 
 
 
 
 
 
 
 
60
  Once you have a YouTube object set up, you're ready to start looking at
61
  different media streams for the video, which is discussed in the next section.
 
41
  'http://youtube.com/watch?v=2lAe1cqCOXo',
42
  on_progress_callback=progress_func,
43
  on_complete_callback=complete_func,
44
+ proxies=my_proxies,
45
+ use_oauth=False,
46
+ allow_oauth_cache=True
47
  )
48
 
49
  When instantiating a YouTube object, these named arguments can be passed in to
 
59
  This could be used, for example, to perform post-download processing on a video
60
  like trimming the length of it.
61
 
62
+ The use_oauth and allow_oauth_cache flags allow you to authorize pytube to
63
+ interact with YouTube using your account, and can be used to bypass age
64
+ restrictions or access private videos and playlists. If allow_oauth_cache is
65
+ set to True, you should only be prompted to do so once, after which point
66
+ pytube will cache the tokens it needs to act on your behalf. Otherwise, you
67
+ will be prompted again for each action that requires you to be authenticated.
68
+
69
  Once you have a YouTube object set up, you're ready to start looking at
70
  different media streams for the video, which is discussed in the next section.
pytube/__main__.py CHANGED
@@ -43,7 +43,14 @@ class YouTube:
43
  :param func on_complete_callback:
44
  (Optional) User defined callback function for stream download
45
  complete events.
46
-
 
 
 
 
 
 
 
47
  """
48
  self._js: Optional[str] = None # js fetched by js_url
49
  self._js_url: Optional[str] = None # the url to the js, parsed from watch html
 
43
  :param func on_complete_callback:
44
  (Optional) User defined callback function for stream download
45
  complete events.
46
+ :param dict proxies:
47
+ (Optional) A dict mapping protocol to proxy address which will be used by pytube.
48
+ :param bool use_oauth:
49
+ (Optional) Prompt the user to authenticate to YouTube.
50
+ If allow_oauth_cache is set to True, the user should only be prompted once.
51
+ :param bool allow_oauth_cache:
52
+ (Optional) Cache OAuth tokens locally on the machine. Defaults to True.
53
+ These tokens are only generated if use_oauth is set to True as well.
54
  """
55
  self._js: Optional[str] = None # js fetched by js_url
56
  self._js_url: Optional[str] = None # the url to the js, parsed from watch html
pytube/contrib/playlist.py CHANGED
@@ -319,18 +319,26 @@ class Playlist(Sequence):
319
  def last_updated(self) -> Optional[date]:
320
  """Extract the date that the playlist was last updated.
321
 
322
- :return: Date of last playlist update
 
 
 
 
 
323
  :rtype: datetime.date
324
  """
325
  last_updated_text = self.sidebar_info[0]['playlistSidebarPrimaryInfoRenderer'][
326
  'stats'][2]['runs'][1]['text']
327
- date_components = last_updated_text.split()
328
- month = date_components[0]
329
- day = date_components[1].strip(',')
330
- year = date_components[2]
331
- return datetime.strptime(
332
- f"{month} {day:0>2} {year}", "%b %d %Y"
333
- ).date()
 
 
 
334
 
335
  @property
336
  @cache
 
319
  def last_updated(self) -> Optional[date]:
320
  """Extract the date that the playlist was last updated.
321
 
322
+ For some playlists, this will be a specific date, which is returned as a datetime
323
+ object. For other playlists, this is an estimate such as "1 week ago". Due to the
324
+ fact that this value is returned as a string, pytube does a best-effort parsing
325
+ where possible, and returns the raw string where it is not possible.
326
+
327
+ :return: Date of last playlist update where possible, else the string provided
328
  :rtype: datetime.date
329
  """
330
  last_updated_text = self.sidebar_info[0]['playlistSidebarPrimaryInfoRenderer'][
331
  'stats'][2]['runs'][1]['text']
332
+ try:
333
+ date_components = last_updated_text.split()
334
+ month = date_components[0]
335
+ day = date_components[1].strip(',')
336
+ year = date_components[2]
337
+ return datetime.strptime(
338
+ f"{month} {day:0>2} {year}", "%b %d %Y"
339
+ ).date()
340
+ except (IndexError, KeyError):
341
+ return last_updated_text
342
 
343
  @property
344
  @cache
pytube/contrib/search.py CHANGED
@@ -18,7 +18,7 @@ class Search:
18
  Search query provided by the user.
19
  """
20
  self.query = query
21
- self._innertube_client = InnerTube()
22
 
23
  # The first search, without a continuation, is structured differently
24
  # and contains completion suggestions, so we must store this separately
 
18
  Search query provided by the user.
19
  """
20
  self.query = query
21
+ self._innertube_client = InnerTube(client='WEB')
22
 
23
  # The first search, without a continuation, is structured differently
24
  # and contains completion suggestions, so we must store this separately