from rich.console import Console #from rich import inspect import platform from pathlib import Path import os import sys import json import argparse import logging import youtube_dl from get_channels import retrieve_youtube_subscriptions from print_logo import print_logo if platform.system() == 'Windows': import msvcrt def uni_getch(): char = str(msvcrt.getch()) if char == "b'y'": return True elif char == "b'n'": return False else: return None else: from getch import getch def uni_getch(): char = getch() if char == "y": return True elif char == "n": return False else: return None parser = argparse.ArgumentParser() parser.add_argument('-i', '--input', action='store', type=str, help='Path to json file generated by previously running this program.') parser.add_argument('-o', '--output', action='store', type=str, help='Output folder.') parser.add_argument('-a', '--all', action='store_true', help='Download all subscriptions.') parser.add_argument('-f', '--format', action='store', type=str, default='best', help='Format to pass to youtube-dl. (default: best)') args = parser.parse_args() json_input = args.input output_dir = args.output or 'output' download_all = args.all dl_format = args.format c = Console() def prg_hook(d): if d['status'] == 'finished': sys.stdout.write("\033[F") sys.stdout.write("\033[K") c.print( ':white_check_mark: {}\n'.format(d['filename'])) if d['status'] == 'downloading': sys.stdout.write("\033[F") sys.stdout.write("\033[K") c.print(':arrow_down_small: {} {} {}'.format(d['filename'], d['_percent_str'], d['_eta_str'])) ydl_opts = { 'format': dl_format, 'ignoreerrors': True, 'continuedl': True, 'quiet': True, 'progress_hooks': [prg_hook] } print_logo() if json_input: f = open(json_input, "r", encoding='utf-8') all_channels = json.loads(f.read()) f.close() else: all_channels = retrieve_youtube_subscriptions() curr_channel = 0 c.print( f'You will be prompted if you want to download a channel for each of your subscriptions. (total {len(all_channels)})', style='bold') for ch in all_channels: if download_all: ch['download'] = True else: curr_channel += 1 c.print( f'[dim][{curr_channel}/{len(all_channels)}]:[/dim] {ch["title"]} [cyan]\[y/n]') while True: key = uni_getch() if key == True: ch['download'] = True break elif key == False: ch['download'] = False break else: c.print('Press "y" or "n"', style='yellow') c.print('All done! :party_popper:', style='green') c.print('Saving to download_list.json...', style='italic') f = open("download_list.json", "w", encoding='utf-8') f.write(json.dumps(all_channels, indent=4)) f.close() for ch in all_channels: if ch['download']: # line break so that download status won't clear this c.print('Downloading {}\n'.format(ch['title']), style='bold cyan') ydl_opts['outtmpl'] = '{}/{}/%(title)s.%(ext)s'.format( output_dir, ch['title']) with youtube_dl.YoutubeDL(ydl_opts) as ydl: Path(os.path.join(output_dir, ch['title'])).mkdir( parents=True, exist_ok=True) try: ydl.download( ['https://www.youtube.com/channel/{}'.format(ch["id"])]) except KeyboardInterrupt: c.print('\nGoodbye!', style='orange1') c.print( 'Start where you left off with "python main.py -i download_list.json"') sys.exit()