Jose Diaz-Gonzalez commited on
Commit
7e36cb4
·
1 Parent(s): f3b34c0
Files changed (5) hide show
  1. pytube/__init__.py +1 -0
  2. pytube/api.py +10 -8
  3. pytube/models.py +5 -2
  4. pytube/tinyjs.py +32 -12
  5. pytube/utils.py +3 -3
pytube/__init__.py CHANGED
@@ -5,3 +5,4 @@ __license__ = 'MIT License'
5
  __copyright__ = 'Copyright 2013 Nick Ficano'
6
 
7
  from .api import YouTube
 
 
5
  __copyright__ = 'Copyright 2013 Nick Ficano'
6
 
7
  from .api import YouTube
8
+ YouTube
pytube/api.py CHANGED
@@ -3,7 +3,7 @@
3
  from __future__ import unicode_literals
4
 
5
  from .exceptions import MultipleObjectsReturned, YouTubeError, CipherError
6
- from .tinyjs import * # TODO: get rid of tinyjs ugghhh
7
  from .models import Video
8
  from .utils import safe_filename
9
  try:
@@ -146,7 +146,7 @@ class YouTube(object):
146
  return result[0]
147
  else:
148
  raise MultipleObjectsReturned(
149
- "get() returned more than one object")
150
 
151
  def filter(self, extension=None, resolution=None):
152
  """Return a filtered list of videos given an extention and resolution
@@ -257,7 +257,7 @@ class YouTube(object):
257
  is_vevo = True
258
 
259
  stream_map = self._parse_stream_map(
260
- data["args"]["url_encoded_fmt_stream_map"])
261
 
262
  self.title = data["args"]["title"]
263
  js_url = "http:" + data["assets"]["js"]
@@ -275,16 +275,17 @@ class YouTube(object):
275
  has_decrypted_signature = False
276
  try:
277
  signature = self._decrypt_signature(
278
- stream_map['s'][0])
279
  url += '&signature=' + signature
280
  has_decrypted_signature = True
281
  except TypeError, e:
282
  pass
283
 
284
  if not has_decrypted_signature:
285
- raise CipherError("Couldn't cipher the signature. "
286
- "Maybe YouTube has changed the cipher "
287
- "algorithm. Notify this issue on GitHub")
 
288
 
289
  else:
290
  signature = self._cipher(stream_map["s"][i], js_url)
@@ -315,7 +316,8 @@ class YouTube(object):
315
  return "".join(a)
316
 
317
  def _cipher(self, s, url):
318
- """Get the signature using the cipher implemented in the JavaScript code
 
319
 
320
  :params s: Signature
321
  :params url: url of JavaScript file
 
3
  from __future__ import unicode_literals
4
 
5
  from .exceptions import MultipleObjectsReturned, YouTubeError, CipherError
6
+ from .tinyjs import JSVM
7
  from .models import Video
8
  from .utils import safe_filename
9
  try:
 
146
  return result[0]
147
  else:
148
  raise MultipleObjectsReturned(
149
+ "get() returned more than one object")
150
 
151
  def filter(self, extension=None, resolution=None):
152
  """Return a filtered list of videos given an extention and resolution
 
257
  is_vevo = True
258
 
259
  stream_map = self._parse_stream_map(
260
+ data["args"]["url_encoded_fmt_stream_map"])
261
 
262
  self.title = data["args"]["title"]
263
  js_url = "http:" + data["assets"]["js"]
 
275
  has_decrypted_signature = False
276
  try:
277
  signature = self._decrypt_signature(
278
+ stream_map['s'][0])
279
  url += '&signature=' + signature
280
  has_decrypted_signature = True
281
  except TypeError, e:
282
  pass
283
 
284
  if not has_decrypted_signature:
285
+ raise CipherError(
286
+ "Couldn't cipher the signature. "
287
+ "Maybe YouTube has changed the cipher "
288
+ "algorithm. Notify this issue on GitHub")
289
 
290
  else:
291
  signature = self._cipher(stream_map["s"][i], js_url)
 
316
  return "".join(a)
317
 
318
  def _cipher(self, s, url):
319
+ """Get the signature using the cipher
320
+ implemented in the JavaScript code
321
 
322
  :params s: Signature
323
  :params url: url of JavaScript file
pytube/models.py CHANGED
@@ -104,8 +104,11 @@ class Video(object):
104
 
105
  def __repr__(self):
106
  """A cleaner representation of the class instance."""
107
- return "<Video: {0} (.{1}) - {2} - {3}>".format(self.video_codec, self.extension,
108
- self.resolution, self.profile)
 
 
 
109
 
110
  def __lt__(self, other):
111
  if type(other) == Video:
 
104
 
105
  def __repr__(self):
106
  """A cleaner representation of the class instance."""
107
+ return "<Video: {0} (.{1}) - {2} - {3}>".format(
108
+ self.video_codec,
109
+ self.extension,
110
+ self.resolution,
111
+ self.profile)
112
 
113
  def __lt__(self, other):
114
  if type(other) == Video:
pytube/tinyjs.py CHANGED
@@ -1,5 +1,6 @@
1
  import re
2
 
 
3
  class JSVM(object):
4
 
5
  _memory = {}
@@ -9,13 +10,31 @@ class JSVM(object):
9
  def __init__(self, code=""):
10
  # TODO: parse automatically the 'swap' method
11
  # function Bn(a,b){var c=a[0];a[0]=a[b%a.length];a[b]=c;return a};
12
- def _swap(args): a = list(args[0]); b = int(args[1]); c = a[0]; a[0] = a[b % len(a)]; a[b] = c; return "".join(a)
13
- def _split(args): return ""
14
- def _slice(args): return args[0][int(args[1]):]
15
- def _reverse(args): return args[0][::-1]
16
- def _join(args): return "".join(args[0])
17
- def _assign(args): return args[0]
18
- def _get(args): return self._memory[args[0]]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  self._js_methods = {
21
  "split": _split,
@@ -38,17 +57,17 @@ class JSVM(object):
38
  #print instruction
39
  var, method = instruction.split("=")
40
  m = regex.match(method)
41
- if m == None:
42
  arguments = [method[1:-1]]
43
  method = "$assign"
44
  else:
45
  m = m.groups()
46
  #print m
47
  arguments = []
48
- pre_args = [m[0][:-1]] if m[0] != None else []
49
  pre_args += m[2].split(",")
50
  for a in pre_args:
51
- if a == None or a == "":
52
  continue
53
  # Replace variables with his value
54
  arguments += [JSMethod(self._js_methods["$get"], a) if not a[0] == '"' and not a[0] == '' and not a.isdigit() else a]
@@ -68,6 +87,7 @@ class JSVM(object):
68
  self._memory[ins[0]] = ins[1].run()
69
  return self._memory
70
 
 
71
  class JSMethod(object):
72
 
73
  def __init__(self, method, args):
@@ -75,8 +95,8 @@ class JSMethod(object):
75
  self._a = args
76
 
77
  def run(self):
78
- args = [arg.run() if isinstance(arg, JSMethod) else arg for arg in self._a]
79
  return self._m(args)
80
 
81
  def __repr__(self):
82
- return "%s(%s)" % (self._m.__name__, self._a)
 
1
  import re
2
 
3
+
4
  class JSVM(object):
5
 
6
  _memory = {}
 
10
  def __init__(self, code=""):
11
  # TODO: parse automatically the 'swap' method
12
  # function Bn(a,b){var c=a[0];a[0]=a[b%a.length];a[b]=c;return a};
13
+ def _swap(args):
14
+ a = list(args[0])
15
+ b = int(args[1])
16
+ c = a[0]
17
+ a[0] = a[b % len(a)]
18
+ a[b] = c
19
+ return "".join(a)
20
+
21
+ def _split(args):
22
+ return ""
23
+
24
+ def _slice(args):
25
+ return args[0][int(args[1]):]
26
+
27
+ def _reverse(args):
28
+ return args[0][::-1]
29
+
30
+ def _join(args):
31
+ return "".join(args[0])
32
+
33
+ def _assign(args):
34
+ return args[0]
35
+
36
+ def _get(args):
37
+ return self._memory[args[0]]
38
 
39
  self._js_methods = {
40
  "split": _split,
 
57
  #print instruction
58
  var, method = instruction.split("=")
59
  m = regex.match(method)
60
+ if m is None:
61
  arguments = [method[1:-1]]
62
  method = "$assign"
63
  else:
64
  m = m.groups()
65
  #print m
66
  arguments = []
67
+ pre_args = [m[0][:-1]] if m[0] is not None else []
68
  pre_args += m[2].split(",")
69
  for a in pre_args:
70
+ if a is None or a == "":
71
  continue
72
  # Replace variables with his value
73
  arguments += [JSMethod(self._js_methods["$get"], a) if not a[0] == '"' and not a[0] == '' and not a.isdigit() else a]
 
87
  self._memory[ins[0]] = ins[1].run()
88
  return self._memory
89
 
90
+
91
  class JSMethod(object):
92
 
93
  def __init__(self, method, args):
 
95
  self._a = args
96
 
97
  def run(self):
98
+ args = [a.run() if isinstance(a, JSMethod) else a for a in self._a]
99
  return self._m(args)
100
 
101
  def __repr__(self):
102
+ return "%s(%s)" % (self._m.__name__, self._a)
pytube/utils.py CHANGED
@@ -79,7 +79,7 @@ def print_status(progress, file_size, start):
79
 
80
  percentDone = int(progress) * 100. / file_size
81
  done = int(50 * progress / int(file_size))
82
- stdout.write("\r [%s%s][%3.2f%%] %s at %s/s\r " % ('=' * done, ' ' *
83
- (50 - done), percentDone, sizeof(file_size), sizeof(
84
- progress // (clock() - start))))
85
  stdout.flush()
 
79
 
80
  percentDone = int(progress) * 100. / file_size
81
  done = int(50 * progress / int(file_size))
82
+ stdout.write("\r [%s%s][%3.2f%%] %s at %s/s\r " %
83
+ ('=' * done, ' ' * (50 - done), percentDone, sizeof(file_size),
84
+ sizeof(progress // (clock() - start))))
85
  stdout.flush()