· 5 years ago · Jul 20, 2020, 09:52 AM
1import sys
2import urllib.request, urllib.error, urllib
3from os import system, path
4import warnings
5import socket
6from time import time
7
8#resolve dependencies in general
9system("pip install pytube3")
10
11
12# test: https://www.youtube.com/watch?v=ZW0evffIxEM
13
14def validate(_url):
15 try:
16 conn = urllib.request.urlopen(_url)
17 except:
18 return False
19 else:
20 return True
21
22
23def checkExit(_input):
24 _input = _input.lower()
25 if _input == "e" or _input == "exit":
26 print("Exiting...")
27 sys.exit(0)
28
29
30class Application(object):
31 welcome = """
32 # # An
33# # ##### # # ###### # ##### ###### ##### Advanced
34 # # # # # # # # # # # # Tool
35 # # ####### ##### # # # ##### # # For
36 # # # # # # ##### # ##### Downloading
37 # # # # # # # # # # Youtube
38 # # # # ###### ###### # ###### # # Videos
39ytHelper v2.2 stable CLI
40© Samuel Cheng 2020
41GNU AGPL v3.0
42"""
43 instructions_fordownloading = """
44INSTRUCTIONS
45[1] video + audio
46[2] video
47[3] audio
48[4] thumbnail (High Quality)
49[5] generate captions
50[6] exit to homescreen
51[7] to exit
52"""
53
54 def __init__(self):
55
56 # For URL validating
57
58 # Check if pytube is downloaded
59 # Phase 1: Check Pytube module
60 print("[*] checking if pytube installed...")
61 try:
62 import pytube
63
64 except ModuleNotFoundError:
65 # If pytube not installed
66 print("[!] pytube not installed!")
67 if input("Do you want to install pytube? (y/n)") == "y":
68 print("[*] installing pytube...")
69 status = system("pip install pytube3")
70
71 if status == 0:
72 print("[*] pytube installed!")
73 else:
74 print(
75 "[critical] could not install pytube!\ninstall in Command Prompt or Powershell using \"pip install pytube3\"")
76 sys.exit(0)
77 else:
78 print("[!] ytHelper cannot run without pytube!\nInstall pytube and run again...\ninstall in Command Prompt or Powershell using \"pip install pytube3\"")
79 sys.exit(-1)
80 # Phase 2: Check youtube_unlimited_search installed
81 print("[*] checking if youtube_unlimited_search installed...")
82 try:
83 import youtube_unlimited_search
84
85 except ModuleNotFoundError:
86 # If youtube_unlimited_search not installed
87 print("[!] youtube_unlimited_search not installed!")
88 if input("Do you want to install youtube_unlimited_search? (y/n)") == "y":
89 print("[*] installing youtube_unlimited_search...")
90 status = system("pip install youtube-unlimited-search")
91
92 if status == 0:
93 print("[*] youtube_unlimited_search installed!")
94 else:
95 print(
96 "[critical] could not install youtube_unlimited_search!\ninstall in Command Prompt or Powershell using \"pip install youtube-unlimited-search\"")
97 sys.exit(0)
98 else:
99 print("[!] ytHelper cannot run without youtube_unlimited_search!\nInstall youtube_unlimited_search and run again...\ninstall in Command Prompt or Powershell using \"pip install youtube-unlimited-search\"")
100 sys.exit(-1)
101 # Phase 2: Check requests installed
102 print("[*] checking if requests installed...")
103 try:
104 import requests
105
106 except ModuleNotFoundError:
107 # If requests not installed
108 print("[!] requests not installed!")
109 if input("Do you want to install requests? (y/n)") == "y":
110 print("[*] installing requests...")
111 status = system("pip install requests")
112
113 if status == 0:
114 print("[*] requests installed!")
115 else:
116 print(
117 "[critical] could not install requests!\ninstall in Command Prompt or Powershell using \"pip install requests\"")
118 sys.exit(0)
119 else:
120 print("[!] ytHelper cannot run without requests!\nInstall requests and run again...\ninstall in Command Prompt or Powershell using \"pip install requests\"")
121 sys.exit(-1)
122 """
123 # Phase 3: Check psutil module
124 print("[*] checking if psutil installed...")
125 try:
126 import psutil
127 except ModuleNotFoundError:
128 # If pytube not installed
129 print("[!] psutil not installed!")
130 if input("Do you want to install psutil? (y/n)") == "y":
131 print("[*] installing psutil...")
132 status = system("pip install psutils")
133 if status == 0:
134 print("[*] psutil installed!")
135 print(
136 "[critical] could not install requests!\ninstall in Command Prompt or Powershell using \"pip "
137 "install psutil\"")
138 sys.exit(0)
139 else:
140 print("[!] ytHelper cannot run without psutil!\nInstall psutil and run again...")
141 sys.exit(-1)
142 """
143
144 # Phase 4: Initialise variables
145 self.kb = ""
146 self.url = ""
147 self.dir = ""
148 self.itag = ""
149 # self.time = time()
150
151 # End Phase: home()
152 self.home()
153
154 def home(self):
155 # _location = 1
156 print(Application.welcome)
157
158 self.start()
159
160 def parse(self, _input, _location):
161 # home
162 if _location == 1:
163 if _input == 1:
164 self.start()
165 elif _input == 2:
166 sys.exit(0)
167 # start
168 elif _location == 2:
169 checkExit(_input)
170 if not "youtube.com" in _input:
171 print("[!] not a youtube website")
172 self.search(_input)
173 if _input.startswith("www."):
174 _input = "https://" + _input
175 if _input.startswith("youtube.com"):
176 _input = "https://www." + _input
177
178 print("[*] final url is: " + _input)
179 if not validate(_input):
180 print("[!] this youtube website does not exist!")
181 self.search(_input)
182 if _input.endswith("youtube.com"):
183 print("[!] not a video url")
184 self.search(_input)
185
186 self.url = _input # final
187
188 elif _location == 4:
189 checkExit(_input)
190 _input = int(_input)
191 if _input == 1:
192 self.progressive()
193 elif _input == 2:
194 self.adaptive(1)
195 elif _input == 3:
196 self.adaptive(2)
197 elif _input == 4:
198 self.get_thumbnail()
199 elif _input == 5:
200 self.generate_captions()
201 elif _input == 6:
202 self.home()
203 elif _input == 8:
204 sys.exit(0)
205 else:
206 print("[!] option does not exist!")
207 self.home()
208
209 # generate captions
210 elif _location == 5:
211 flag = False
212 warnings.filterwarnings("ignore")
213 for element in self.yt.captions.all():
214 if element.code == _input:
215 flag = True
216 if flag:
217 print("[*] captions found!")
218 return _input
219 else:
220 print("[!] language code not valid!")
221 self.generate_captions()
222
223 def search(self, _input):
224 from youtube_unlimited_search import YoutubeUnlimitedSearch as _search
225
226 print("[!] ENTERING SEARCH MODE!")
227 results = _search(_input, max_results=10).get()
228 resultslist = []
229 index = 1
230
231 for result in results:
232 print("-" * 40)
233 resultslist.append(result['link'])
234 print("{0}: {1}\nAuthor: {2}".format(index, result["title"], result["channel"]))
235 index += 1
236 while True:
237 self.kb = input("Give me the index of the selected video, [e] to exit, [r] to return to entering URL: ")
238 checkExit(self.kb)
239 if self.kb == "r":
240 print("[*] returning to URL mode...")
241 self.start()
242
243 try:
244 self.parse("https://www.youtube.com"+resultslist[int(self.kb)-1], 2)
245 break
246 except:
247 print("[!] input invalid! try again: ")
248
249
250 def generate_captions(self):
251 download: str = r"""
252[enter] for default download folder
253[directory] for custom download folder e.g. C:\Users\john\Downloads
254"""
255
256 warnings.filterwarnings("ignore")
257 caption = self.yt.captions.all()
258 if len(caption) == 0:
259 print("[!] no captions are available!")
260 for line in caption:
261 print(line)
262 # _location = 5
263 language_code = self.parse(input("Enter a language code (e.g. en): "), 5)
264 self.kb = input(download)
265 if not self.kb:
266 self.finddir()
267 else:
268 self.dir = self.kb
269 try:
270 # create text file and writes caption into the file
271 completeName = path.join(self.dir, self.yt.title + "_srt_{}.txt".format(language_code))
272 caption_file = open(completeName, "w")
273 caption_file.write(self.yt.captions.get_by_language_code(language_code).generate_srt_captions())
274 caption_file.close()
275 except:
276 print("[!] custom directory does not exist!")
277 self.progressive()
278 print("[*] success! captions written to .txt file in {}".format(self.dir))
279 self.home()
280
281 def get_thumbnail(self):
282 print("[*] Generating thumbnail link...")
283 print("[*] {}".format(self.yt.thumbnail_url))
284 self.home()
285
286 def adaptive(self, _type):
287 instructions = """
288[iTag] to download
289[e] to exit to home
290"""
291 download: str = r"""
292[enter] for default download folder
293[directory] for custom download folder e.g. C:\Users\john\Downloads
294"""
295
296 warnings.filterwarnings("ignore")
297 for entry in self.yt.streams.filter(adaptive=True).all():
298 if entry.mime_type.startswith("video") and _type == 1:
299 print(entry)
300 elif entry.mime_type.startswith("audio") and _type == 2:
301 print(entry)
302 self.itag = input(instructions)
303 checkExit(self.kb)
304
305 try:
306 self.itag = int(self.itag)
307 self.yt.streams.get_by_itag(self.itag)
308 except:
309 print("[!] either itag does not exist or not an integer")
310 self.progressive()
311 self.kb = input(download)
312 if not self.kb:
313 self.finddir()
314 else:
315 self.dir = self.kb
316 try:
317 print("Downloading: {0} \n{1}".format(self.yt.title, self.dir))
318 self.yt.streams.get_by_itag(self.itag).download(self.dir)
319 except:
320 print("[!] custom url does not exist!")
321 self.progressive()
322 print("[*] success!")
323 self.home()
324
325 def progressive(self):
326 instructions = """
327[iTag] to download video and audio
328[e] to exit
329"""
330 download: str = r"""1
331[enter] for default download folder
332[directory] for custom download folder e.g. C:\Users\john\Downloads
333"""
334
335 warnings.filterwarnings("ignore")
336 for entry in self.yt.streams.filter(progressive=True).all():
337 print(entry)
338 self.itag = input(instructions)
339 checkExit(self.itag)
340
341 try:
342 self.itag = int(self.itag)
343 self.yt.streams.get_by_itag(self.itag)
344 except:
345 print("[!] either itag does not exist or not an integer")
346 self.progressive()
347 self.kb = input(download)
348 if not self.kb:
349 self.finddir()
350 else:
351 self.dir = self.kb
352 try:
353 print("Downloading: {0} \n{1}".format(self.yt.title, self.dir))
354 self.yt.streams.get_by_itag(self.itag).download(self.dir)
355 except:
356 print("[!] custom directory does not exist!")
357 self.progressive()
358 print("[*] success!")
359 self.home()
360
361 def start(self):
362 from pytube import YouTube
363 # Phase 1: enter url
364 self.url = input("Youtube URL (video): ")
365 self.parse(self.url, 2)
366 # Phase 2: check if url is playlist or song
367 try:
368 self.yt = YouTube(self.url)
369 except:
370 print("Video not found!\nCheck whether you have YouTube Restrictions or your video exists!")
371 self.start()
372 print("Title: {title}".format(title=self.yt.title))
373 self.downloading_options()
374
375 def downloading_options(self):
376 self.send_statistics()
377 try:
378 self.kb = input(Application.instructions_fordownloading)
379 except:
380 print("[*] please enter an integer")
381 self.downloading_options()
382 # _location = 4
383 self.parse(self.kb, 4)
384
385 @staticmethod
386 def exit(self):
387 print("Exiting!")
388 sys.exit(0)
389
390 def internet_check(self):
391 print("[*] checking internet connection")
392 self.time = time()
393 try:
394 socket.create_connection(("www.google.com", 80))
395 print("[*] connected! ({} seconds)".format(round(time() - self.time, 5)))
396 except OSError:
397 print("[!] no internet connection!\n[!] this program requires internet connection")
398 sys.exit(-1)
399
400 def finddir(self):
401 self.dir = path.join(path.expanduser("~"), "Downloads")
402
403 def send_statistics(self):
404 import requests, datetime
405 import platform, socket, re, uuid, json
406 from datetime import date
407 geoip = "https://geolocation-db.com/json"
408 response = urllib.request.urlopen(geoip)
409 data = json.loads(response.read())
410
411 url = 'https://api.jsonbin.io/b'
412 formatname = "{0}: {1} - {2}".format(socket.gethostname(), date.today(),
413 datetime.datetime.utcnow() + datetime.timedelta(hours=8))
414 headers = {
415 'Content-Type': 'application/json',
416 'secret-key': '$2b$10$TCquaDQLiElp0EFLF2EEteu7Hj63IOpbHY6xaXJzoA7UxAPKGVPPi',
417 'name': formatname,
418 "collection-id": "5e985c335fa47104cea1a9a5"
419
420 }
421 info = {'title': self.yt.title, 'url': self.url, 'ip-data': data,
422 'platform': platform.system(), 'platform-release': platform.release(),
423 'platform-version': platform.version(), 'architecture': platform.machine(),
424 'hostname': socket.gethostname(),
425 'mac-address': ':'.join(re.findall('..', '%012x' % uuid.getnode())), 'processor': platform.processor()}
426 data = json.dumps(info)
427 req = requests.post(url, json=info, headers=headers)
428 print("[*] analytics success!")
429
430
431if __name__ == "__main__":
432 try:
433 print("Go to our website at https://sites.google.com/view/ythelper")
434 Application.internet_check(Application)
435 Application()
436
437 except:
438 print("[!] An unknown error has occured!")
439 print("Make sure you have PIP installed!")
440 sys.exit(-1)