def schedule_download(url): ''' Look for the scheduled time in settings.json ''' scheduled_time = install.read_settings_json('preferences', 'download_time') if scheduled_time == '': tip = '☝🏻 Tip: You can schedule download time in settings.json' message.carriage_return_animate(tip) download_course(url) return else: counter = True message.colored_message( Fore.LIGHTGREEN_EX, 'Download time set to: ' + scheduled_time + '\ in settings.json, you can change or remove this time in settings.json\n') try: while counter: if time.strftime("%H:%M") == scheduled_time: download_course(url) return print('Download will start at: ' + scheduled_time + ', leave this window open.') time.sleep(60) except KeyboardInterrupt: sys.exit( message.colored_message(Fore.LIGHTRED_EX, "\n- Program Interrupted!!\n"))
def chapters(url, course_folder_path): ''' create chapters folder ''' soup = create_soup(url) heading4 = soup.find_all('h4', {"class": "ga"}) chapter_no = 0 message.colored_message(Fore.LIGHTYELLOW_EX, "Creating Chapters:\n") # Print message for h in heading4: chapter = h.text chapter = re.sub('[,:?><"/\\|*]', ' ', chapter) if chapter[1] == '.': chapter = str(chapter_no).zfill(2) + '. ' + chapter[3:] elif chapter[2] == '.': chapter = str(chapter_no).zfill(2) + '. ' + chapter[4:] else: chapter = str(chapter_no).zfill(2) + '. ' + chapter chapter_no += 1 message.print_line(chapter) os.mkdir(course_folder_path + "/" + chapter) # create folders (chapters) message.colored_message( Fore.LIGHTGREEN_EX, '\n✅ ' + str(chapter_no) + ' chapters created!!\n')
def main(): init() message.animate_characters(Fore.LIGHTYELLOW_EX, draw.ROCKET, 0.05) message.spinning_cursor() message.print_line('\n1. Paste course url or\n' + '2. Press enter for Bulk Download') url = raw_input() start_time = time.time() #start time counter begins if url == "": urls = download.read_bulk_download() if not urls: sys.exit( message.colored_message( Fore.LIGHTRED_EX, 'Please paste urls in Bulk Download.txt\n')) for url in urls: download_course(url) else: download_course(url) try: end_time = time.time() message.animate_characters(Fore.LIGHTGREEN_EX, draw.COW, 0.1) message.colored_message( Fore.LIGHTGREEN_EX, "\nThe whole process took {}\n".format( renameFiles.hms_string(end_time - start_time))) except KeyboardInterrupt: sys.exit( message.colored_message(Fore.LIGHTRED_EX, "\n- Program Interrupted!!\n"))
def rename(path): ''' Rename files ''' message.colored_message( Fore.LIGHTYELLOW_EX, '\nRenaming videos to arrange them in correct order:\n') # Rename video files for vid in os.listdir(path): if vid.endswith('.mp4'): vid_name, vid_ext = os.path.splitext(vid) vid_no = vid_name[-4:] vid_title = vid_name[:-7] vid_title = re.sub('[^a-zA-Z0-9.,-]', ' ', vid_title) new_file = '{}-{}{}'.format(vid_no, vid_title, vid_ext) os.rename(vid, new_file) write(new_file) message.colored_message( Fore.LIGHTYELLOW_EX, '\nRenaming subtitles to match them with videos:\n') # Rename subtitle files for sub in os.listdir(path): if sub.endswith('.srt'): sub_name, sub_ext = os.path.splitext(sub) sub_no = sub_name[-7:-3] sub_title = sub_name[:-10] sub_title = re.sub('[^a-zA-Z0-9.,-]', ' ', sub_title) new_file = '{}-{}{}'.format(sub_no, sub_title, sub_ext) os.rename(sub, new_file) write(new_file)
def schedule_download(url): ''' Look for the scheduled time in settings.json ''' if not read.external_downloader: tip = '☝🏻 Tip: Install aria2c for faster downloads, read README.md to learn more.' message.carriage_return_animate(tip) if read.download_time == '': # If download time not set, begin download download_course(url) return else: counter = True message.colored_message( Fore.LIGHTGREEN_EX, 'Download time set to: ' + read.download_time + '\ in settings.json, you can change or remove this time in settings.json\n') try: while counter: if time.strftime("%H:%M") == read.download_time: download_course(url) return print('Download will start at: ' + read.download_time + ', leave this window open.') time.sleep(60) except KeyboardInterrupt: sys.exit( message.colored_message(Fore.LIGHTRED_EX, "\n- Program Interrupted!!\n"))
def main(): ''' Main function ''' init() message.animate_characters(Fore.LIGHTYELLOW_EX, draw.ROCKET, 0.05) message.spinning_cursor() message.print_line('\r1. Paste course url or\n' + '2. Press enter for Bulk Download') # Prevent name error on python 3.x try: url = raw_input() except NameError: url = input() print('') start_time = time.time() #start time counter begins if url == "": urls = read.bulk_download() if not urls: sys.exit(message.colored_message(Fore.LIGHTRED_EX, 'Please paste urls in Bulk Download.txt\n')) for url in urls: schedule_download(url) else: schedule_download(url) try: end_time = time.time() message.animate_characters(Fore.LIGHTGREEN_EX, draw.COW, 0.1) message.colored_message(Fore.LIGHTGREEN_EX, "\nThe whole process took {}\n".format(move.hms_string(end_time - start_time))) except KeyboardInterrupt: sys.exit(message.colored_message(Fore.LIGHTRED_EX, "\n- Program Interrupted!!\n"))
def find_cookie(desktop_folder, download_folder): ''' Find the latest cookie file ''' down_files = glob.glob(download_folder+'/*.txt') desk_files = glob.glob(desktop_folder+'/*.txt') files = down_files + desk_files cookies = [s for s in files if 'cookies' in s] if not cookies: sys.exit(message.colored_message(Fore.LIGHTRED_EX,message.COOKIE_NOT_FOUND_ERROR)) else: latest_cookie = max(cookies, key=os.path.getctime) message.colored_message(Fore.LIGHTGREEN_EX, '\nUsing latest cookie file: '+latest_cookie+ '\n') return latest_cookie
def find_cookie(desktop_folder, download_folder): ''' Find the latest cookie file ''' down_files = glob.glob(download_folder + '/*.txt') desk_files = glob.glob(desktop_folder + '/*.txt') files = down_files + desk_files cookies = [s for s in files if 'cookies' in s] if not cookies: downloading_from_cookie = message.return_colored_message( Fore.LIGHTBLUE_EX, ' 🍪 Downloading videos using cookies.txt') message.carriage_return_animate(downloading_from_cookie) cookies_not_found = message.return_colored_message( Fore.LIGHTRED_EX, "\ Oops!! Did you forget to put 🍪 cookies.txt inside Downloads or Desktop folder ??\n" ) message.carriage_return_animate(cookies_not_found) sys.exit( message.colored_message( Fore.LIGHTRED_EX, '\nNote: If you wish to download course using username & password combination,\ \n you should set -> "use_cookie_for_download": false in settings.json\n' )) else: latest_cookie = max(cookies, key=os.path.getctime) latest_cookie_file = message.return_colored_message( Fore.LIGHTGREEN_EX, '🍪 Using latest cookie file: ' + latest_cookie + '\n') message.carriage_return_animate(latest_cookie_file) return latest_cookie
def save_chapters(urlink, course_folder_path): ''' create chapters folder ''' soup = create_soup(urlink) heading4 = soup.find_all('h4', {"class": "ga"}) chapter_no = 0 message.colored_message(Fore.LIGHTYELLOW_EX, "Creating Chapters:\n") # Print message with open('CONTENT.md', 'a') as content_md: for h in heading4: chapter = h.text chapter = re.sub('[^a-zA-Z0-9.,-]', ' ', chapter) if chapter[1] == '.': chapter_name = chapter[3:] chapter = str(chapter_no).zfill(2) + '. ' + chapter_name chapter_no += 1 elif chapter[2] == '.': chapter_name = chapter[4:] chapter = str(chapter_no).zfill(2) + '. ' + chapter_name chapter_no += 1 else: chapter = str(chapter_no).zfill(2) + '. ' + chapter chapter_no += 1 message.print_line(chapter) os.mkdir(course_folder_path + "/" + chapter) # create folders (chapters) content_md.writelines('* ' + chapter + '\n') # writelines to content_md content_md.writelines('\n## Video files:\n\n') # next heading content_md.close() # close content_md message.colored_message( Fore.LIGHTGREEN_EX, '\n-> ' + str(chapter_no) + ' chapters created!!\n')
def course(url, lynda_folder_path): ''' create course folder ''' current_course = course_path(url, lynda_folder_path) courses = os.listdir(lynda_folder_path) answer = None for course in courses: if (lynda_folder_path + course) == current_course: QUESTION = '\nCourse already exists: Do you wish to delete it and download again? (Y/N): ' sys.stdout.write(Fore.LIGHTBLUE_EX + QUESTION + Fore.RESET) while answer != 'y': # fix for python 2.x and 3.x try: answer = raw_input().lower() except NameError: answer = input().lower() if answer == 'y': shutil.rmtree(current_course) message.colored_message( Fore.LIGHTRED_EX, "\n❌ Existing course folder deleted!!") time.sleep(2) message.colored_message( Fore.LIGHTGREEN_EX, "\n♻️ Re-downloading the course.\n") elif answer == 'n': sys.exit( message.colored_message(Fore.LIGHTRED_EX, "\n-> Program Ended!!\n")) else: sys.stdout.write( Fore.LIGHTRED_EX + "\n- oops!! that's not a valid choice, type Y or N: " + Fore.RESET) os.mkdir(current_course)
def download_course(url): ''' download course ''' # Check for a valid url if url.find('.html') == -1: sys.exit(message.animate_characters(Fore.LIGHTRED_EX, draw.ANONYMOUS, 0.02)) url = url[:url.find(".html")+5] #strip any extra text after .html in the url # Folder/File paths lynda_folder_path = read.settings_json('preferences', 'location') + '/' course_folder_path = save.course_path(url, lynda_folder_path) desktop_folder_path = install.get_path("Desktop") download_folder_path = install.get_path("Downloads") # Read preferences download_exercise_file = read.settings_json('preferences', 'download_exercise_file') use_cookie_for_download = read.settings_json('credentials', 'use_cookie_for_download') if use_cookie_for_download: cookie_path = cookies.find_cookie(desktop_folder_path, download_folder_path) else: cookie_path = '' usr_pass_message = message.return_colored_message(Fore.LIGHTGREEN_EX, 'Using username and password combination for download\n') message.carriage_return_animate(usr_pass_message) try: # main operations -> save.course(url, lynda_folder_path) # Create course folder save.info_file(url, course_folder_path) # Gather information save.chapters(url, course_folder_path) # Create chapter folders save.contentmd(url) # Create content.md save.videos(url, cookie_path, course_folder_path) # Download videos rename.videos(course_folder_path) # rename videos rename.subtitles(course_folder_path) # rename subtitles move.vid_srt_to_chapter(url, course_folder_path) # Move videos and subtitles to chapter folders # Download exercise file if download_exercise_file: # check if user wants to download exercise file if not use_cookie_for_download: # make sure user is downloading via user + password if save.check_exercise_file(url): exercise_file.download(url, course_folder_path) # Download exercise-file else: print('\n-> Exercise file not available.') else: print('\nExercise file downloads for organizational login is not supported, please download manually.') except KeyboardInterrupt: sys.exit(message.colored_message(Fore.LIGHTRED_EX, "\n- Program Interrupted!!\n"))
def course(url, lynda_folder_path): ''' create course folder ''' current_course = course_path(url, lynda_folder_path) courses = os.listdir(lynda_folder_path) preference = read.settings_json('preferences', 'redownload_course') answer = None for course in courses: if (lynda_folder_path + course) == current_course: if preference == 'force': # delete existing course and re-download shutil.rmtree(current_course) message.colored_message( Fore.LIGHTRED_EX, "\n✅ Course folder already exists. Current preference -> FORCE redownload" ) message.colored_message( Fore.LIGHTRED_EX, "\n❌ Existing course folder deleted!!") time.sleep(2) message.colored_message(Fore.LIGHTGREEN_EX, "\n♻️ Re-downloading the course.\n") time.sleep(2) elif preference == 'skip': # skip download process message.colored_message( Fore.LIGHTRED_EX, "\n✅ Course folder already exists. Current preference -> SKIP redownload" ) sys.exit( message.colored_message( Fore.LIGHTRED_EX, "\n-> Skipping course download.\n")) elif preference == 'prompt': # prompt user with available choices QUESTION = '\n✅ Course folder already exists: Do you wish to delete it and download again? (Y/N): ' sys.stdout.write(Fore.LIGHTBLUE_EX + QUESTION + Fore.RESET) while answer != 'y': # fix for python 2.x and 3.x try: answer = raw_input().lower() except NameError: answer = input().lower() if answer == 'y': shutil.rmtree(current_course) message.colored_message( Fore.LIGHTRED_EX, "\n❌ Existing course folder deleted!!") time.sleep(2) message.colored_message( Fore.LIGHTGREEN_EX, "\n♻️ Re-downloading the course.\n") elif answer == 'n': sys.exit( message.colored_message(Fore.LIGHTRED_EX, "\n-> Program Ended!!\n")) else: sys.stdout.write( Fore.LIGHTRED_EX + "\n- oops!! that's not a valid choice, type Y or N: " + Fore.RESET) os.mkdir(current_course)
def download_course(url): #check for a valid url if url.find('.html') == -1: sys.exit( message.animate_characters(Fore.LIGHTRED_EX, draw.ANONYMOUS, 0.02)) url = url[:url.find(".html") + 5] #strip any extra text after .html in the url # Folder/File paths lynda_folder_path = install.read_location_file() + '/' course_folder_path = chapters.course_path(url, lynda_folder_path) desktop_folder_path = install.folder_path("Desktop") download_folder_path = install.folder_path("Downloads") cookie_path = cookies.find_cookie(desktop_folder_path, download_folder_path) # Edit cookie file cookies.edit_cookie(cookie_path, message.NETSCAPE) #create course folder try: chapters.save_course(url, lynda_folder_path) except KeyboardInterrupt: sys.exit( message.colored_message(Fore.LIGHTRED_EX, "\n- Program Interrupted!!\n")) except: sys.exit( message.animate_characters(Fore.LIGHTWHITE_EX, draw.NOPE, 0.02)) #save chapters and videos try: chapters.gather_info(url, course_folder_path) # Gather information chapters.save_chapters( url, course_folder_path) # Create chapters inside course folder download.download_files( url, cookie_path, course_folder_path) # Downloading lynda videos to course folder except KeyboardInterrupt: sys.exit( message.colored_message(Fore.LIGHTRED_EX, "\n- Program Interrupted!!\n")) # Rename files try: path = renameFiles.assign_folder(course_folder_path) except KeyboardInterrupt: sys.exit( message.colored_message(Fore.LIGHTRED_EX, "\n- Program Interrupted!!\n")) except: sys.exit('error in assigning path') try: renameFiles.execute(path) except KeyboardInterrupt: sys.exit( message.colored_message(Fore.LIGHTRED_EX, "\n- Program Interrupted!!\n")) except: sys.exit(message.RENAMING_ERROR)
def download_course(url): ''' download course ''' # Check for a valid url if url.find('.html') == -1: sys.exit( message.animate_characters(Fore.LIGHTRED_EX, draw.ANONYMOUS, 0.02)) url = url[:url.find(".html") + 5] #strip any extra text after .html in the url # Folder/File paths lynda_folder_path = read.settings_json('preferences', 'location') + '/' course_folder_path = save.course_path(url, lynda_folder_path) desktop_folder_path = install.get_path("Desktop") download_folder_path = install.get_path("Downloads") # Read preferences use_cookie_for_download = read.course_download_pref if use_cookie_for_download in ['cookies', 'cookie']: cookie_path = cookies.find_cookie(desktop_folder_path, download_folder_path) else: cookie_path = '' usr_pass_message = message.return_colored_message( Fore.LIGHTGREEN_EX, 'Using username and password combination for download\n') message.carriage_return_animate(usr_pass_message) try: # main operations -> save.course(url, lynda_folder_path) # Create course folder save.info_file(url, course_folder_path) # Gather information save.chapters(url, course_folder_path) # Create chapter folders save.contentmd(url) # Create content.md save.videos(url, cookie_path, course_folder_path) # Download videos rename.videos(course_folder_path) # rename videos rename.subtitles(course_folder_path) # rename subtitles move.vid_srt_to_chapter( url, course_folder_path) # Move videos and subtitles to chapter folders # Download exercise files if save.check_exercise_file(url): print('\nExercise file is available to download') if not read.download_exercise_file: # if user do not want to download ex-file print( "settings.json says you do not want to download ex-file -> 'download_exercise_file': false" ) else: # if user wants to download ex-file if read.course_download_pref == 'regular-login': exercise_file.download(url, course_folder_path) elif read.exfile_download_pref == 'library-login': if read.card_number == '': print( '\nTo download ex-file via library login -> Please save library card details in settings.json' ) else: exercise_file.download(url, course_folder_path) else: print( '\nThe exercise file can only be downloaded through one of the below combinations:' ) print('~ Regular login: username + password or') print('~ Library login: card number, pin and org. url\n') else: # if exercise file not present print('This course does not include Exercise files.') except KeyboardInterrupt: sys.exit( message.colored_message(Fore.LIGHTRED_EX, "\n- Program Interrupted!!\n"))
def download_course(url): ''' download course ''' # Check for a valid url if url.find('.html') == -1: sys.exit( message.animate_characters(Fore.LIGHTRED_EX, draw.ANONYMOUS, 0.02)) url = url[:url.find(".html") + 5] #strip any extra text after .html in the url # Folder/File paths lynda_folder_path = install.read_settings_json('preferences', 'location') + '/' course_folder_path = save.course_path(url, lynda_folder_path) desktop_folder_path = install.folder_path("Desktop") download_folder_path = install.folder_path("Downloads") if install.read_settings_json('credentials', 'use_cookie_for_download'): cookie_path = cookies.find_cookie(desktop_folder_path, download_folder_path) else: cookie_path = '' usr_pass_message = message.return_colored_message( Fore.LIGHTGREEN_EX, 'Using username and password combination for download\n') message.carriage_return_animate(usr_pass_message) try: save.course(url, lynda_folder_path) # Create course folder save.info_file(url, course_folder_path) # Gather information save.chapters( url, course_folder_path) # Create chapters inside course folder videos.download( url, cookie_path, course_folder_path) # Downloading lynda videos to course folder # Download exercise file # check for organizational login, should be false to download. if not install.read_settings_json('credentials', 'use_cookie_for_download'): if save.check_exercise_file(url): exercise_file.download( url, course_folder_path) # Download exercise-file else: print('\n-> Exercise file not available.') else: print( '\nExercise file downloads for organizational login is not supported, please download manually.' ) except KeyboardInterrupt: sys.exit( message.colored_message(Fore.LIGHTRED_EX, "\n- Program Interrupted!!\n")) # Rename files try: path = rename_files.assign_folder(course_folder_path) except KeyboardInterrupt: sys.exit( message.colored_message(Fore.LIGHTRED_EX, "\n- Program Interrupted!!\n")) except: sys.exit('error in assigning path') try: rename_files.execute(path) except KeyboardInterrupt: sys.exit( message.colored_message(Fore.LIGHTRED_EX, "\n- Program Interrupted!!\n")) except: sys.exit(message.RENAMING_ERROR)