def validate_inputs(config, args): error_arr = [] try: config.read(os.path.join(os.getcwd(), "settings.ini")) logger.banner() ptts.tt_username = config.get('ptts', 'username') ptts.tt_password = config.get('ptts', 'password') ptts.dl_path = config.get('ptts', 'download_path') ptts.args = args if not ptts.tt_username or not len(ptts.tt_username): raise Exception( "Invalid value for 'username'. This value is required.") if not ptts.tt_password or not len(ptts.tt_password): raise Exception( "Invalid value for 'password'. This value is required.") if not ptts.dl_path.endswith('/'): ptts.dl_path = ptts.dl_path + '/' if not ptts.dl_path or not os.path.exists(ptts.dl_path): ptts.dl_path = os.getcwd() error_arr.append(["dl_path", ptts.dl_path]) if error_arr: for error in error_arr: logger.warn( "Invalid value for '{:s}'. Using default value: {:s}". format(error[0], error[1])) logger.separator() if args.download: ptts.tt_target_user = args.download elif args.hashtag: ptts.tt_target_hashtag = args.hashtag elif args.getfollowing: ptts.tt_target_user = args.getfollowing elif args.livestream: ptts.tt_target_user = args.livestream elif args.single: ptts.tt_target_id = args.single else: logger.error( "Missing --download or --single argument. Either of these arguments is required." ) logger.separator() return False return True except Exception as e: logger.error("An error occurred: {:s}".format(str(e))) logger.error( "Make sure the config file and given arguments valid and try again." ) logger.separator() return False
def validate_inputs(config, args, unknown_args): error_arr = [] banner_shown = False try: if args.configpath: if os.path.isfile(args.configpath): pil.config_path = args.configpath else: logger.banner() banner_shown = True logger.warn("Custom config path is invalid, falling back to default path: {:s}".format(pil.config_path)) pil.config_path = os.path.join(os.getcwd(), "pyinstalive.ini") logger.separator() if not os.path.isfile(pil.config_path): # Create new config if it doesn't exist if not banner_shown: logger.banner() helpers.new_config() return False pil.config_path = os.path.realpath(pil.config_path) config.read(pil.config_path) if args.download: pil.dl_user = args.download if args.downloadfollowing or args.batchfile: logger.banner() logger.warn("Please use only one download method. Use -h for more information.") logger.separator() return False elif not args.clean and not args.info and not args.assemble and not args.downloadfollowing and not args.batchfile and not args.organize: logger.banner() logger.error("Please use a download method. Use -h for more information.") logger.separator() return False if helpers.bool_str_parse(config.get('pyinstalive', 'log_to_file')) == "Invalid": pil.log_to_file = True error_arr.append(['log_to_file', 'True']) elif helpers.bool_str_parse(config.get('pyinstalive', 'log_to_file')): pil.log_to_file = True else: pil.log_to_file = False logger.banner() if args.batchfile: if os.path.isfile(args.batchfile): pil.dl_batchusers = [user.rstrip('\n') for user in open(args.batchfile)] if not pil.dl_batchusers: logger.error("The specified file is empty.") logger.separator() return False else: logger.info("Downloading {:d} users from batch file.".format(len(pil.dl_batchusers))) logger.separator() else: logger.error('The specified file does not exist.') logger.separator() return False if unknown_args: pil.uargs = unknown_args logger.warn("The following unknown argument(s) were provided and will be ignored: ") logger.warn(' ' + ' '.join(unknown_args)) logger.separator() pil.ig_user = config.get('pyinstalive', 'username') pil.ig_pass = config.get('pyinstalive', 'password') pil.dl_path = config.get('pyinstalive', 'download_path') pil.run_at_start = config.get('pyinstalive', 'run_at_start') pil.run_at_finish = config.get('pyinstalive', 'run_at_finish') pil.ffmpeg_path = config.get('pyinstalive', 'ffmpeg_path') pil.verbose = config.get('pyinstalive', 'verbose') pil.skip_merge = config.get('pyinstalive', 'skip_merge') pil.args = args pil.config = config pil.proxy = config.get('pyinstalive', 'proxy') if args.dlpath: pil.dl_path = args.dlpath if helpers.bool_str_parse(config.get('pyinstalive', 'show_cookie_expiry')) == "Invalid": pil.show_cookie_expiry = False error_arr.append(['show_cookie_expiry', 'False']) elif helpers.bool_str_parse(config.get('pyinstalive', 'show_cookie_expiry')): pil.show_cookie_expiry = True else: pil.show_cookie_expiry = False if helpers.bool_str_parse(config.get('pyinstalive', 'verbose')) == "Invalid": pil.verbose = False error_arr.append(['verbose', 'False']) elif helpers.bool_str_parse(config.get('pyinstalive', 'verbose')): pil.verbose = True else: pil.verbose = False if helpers.bool_str_parse(config.get('pyinstalive', 'skip_merge')) == "Invalid": pil.skip_merge = False error_arr.append(['skip_merge', 'False']) elif helpers.bool_str_parse(config.get('pyinstalive', 'skip_merge')): pil.skip_merge = True else: pil.skip_merge = False if helpers.bool_str_parse(config.get('pyinstalive', 'use_locks')) == "Invalid": pil.use_locks = False error_arr.append(['use_locks', 'False']) elif helpers.bool_str_parse(config.get('pyinstalive', 'use_locks')): pil.use_locks = True else: pil.use_locks = False if helpers.bool_str_parse(config.get('pyinstalive', 'clear_temp_files')) == "Invalid": pil.clear_temp_files = False error_arr.append(['clear_temp_files', 'False']) elif helpers.bool_str_parse(config.get('pyinstalive', 'clear_temp_files')): pil.clear_temp_files = True else: pil.clear_temp_files = False if helpers.bool_str_parse(config.get('pyinstalive', 'do_heartbeat')) == "Invalid": pil.do_heartbeat = True error_arr.append(['do_heartbeat', 'True']) if helpers.bool_str_parse(config.get('pyinstalive', 'do_heartbeat')): pil.do_heartbeat = True if args.noheartbeat or not helpers.bool_str_parse(config.get('pyinstalive', 'do_heartbeat')): pil.do_heartbeat = False logger.warn("Getting livestream heartbeat is disabled, this may cause degraded performance.") logger.separator() if not args.nolives and helpers.bool_str_parse(config.get('pyinstalive', 'download_lives')) == "Invalid": pil.dl_lives = True error_arr.append(['download_lives', 'True']) elif helpers.bool_str_parse(config.get('pyinstalive', 'download_lives')): pil.dl_lives = True else: pil.dl_lives = False if not args.noreplays and helpers.bool_str_parse(config.get('pyinstalive', 'download_replays')) == "Invalid": pil.dl_replays = True error_arr.append(['download_replays', 'True']) elif helpers.bool_str_parse(config.get('pyinstalive', 'download_replays')): pil.dl_replays = True else: pil.dl_replays = False if helpers.bool_str_parse(config.get('pyinstalive', 'download_comments')) == "Invalid": pil.dl_comments = True error_arr.append(['download_comments', 'True']) elif helpers.bool_str_parse(config.get('pyinstalive', 'download_comments')): pil.dl_comments = True else: pil.dl_comments = False if args.nolives: pil.dl_lives = False if args.noreplays: pil.dl_replays = False if args.verbose: pil.verbose = True if args.skip_merge: pil.skip_merge = True if not pil.dl_lives and not pil.dl_replays: logger.error("You have disabled both livestream and replay downloading.") logger.error("Please enable at least one of them and try again.") logger.separator() return False if pil.ffmpeg_path: if not os.path.isfile(pil.ffmpeg_path): pil.ffmpeg_path = None cmd = "where" if platform.system() == "Windows" else "which" logger.warn("Custom FFmpeg binary path is invalid, falling back to environment variable.") else: logger.binfo("Overriding FFmpeg binary path: {:s}".format(pil.ffmpeg_path)) else: if not helpers.command_exists('ffmpeg') and not args.info: logger.error("FFmpeg framework not found, exiting.") logger.separator() return False if not pil.ig_user or not len(pil.ig_user): raise Exception("Invalid value for 'username'. This value is required.") if not pil.ig_pass or not len(pil.ig_pass): raise Exception("Invalid value for 'password'. This value is required.") if not pil.dl_path.endswith('/'): pil.dl_path = pil.dl_path + '/' if not pil.dl_path or not os.path.exists(pil.dl_path): pil.dl_path = os.getcwd() + "/" if not args.dlpath: error_arr.append(['download_path', os.getcwd() + "/"]) else: logger.warn("Custom config path is invalid, falling back to default path: {:s}".format(pil.dl_path)) logger.separator() if pil.proxy and pil.proxy != '': parsed_url = urlparse(pil.proxy) if not parsed_url.netloc or not parsed_url.scheme: error_arr.append(['proxy', 'None']) pil.proxy = None if error_arr: for error in error_arr: logger.warn("Invalid value for '{:s}'. Using default value: {:s}".format(error[0], error[1])) logger.separator() if args.info: helpers.show_info() return False elif args.clean: helpers.clean_download_dir() return False elif args.assemble: pil.assemble_arg = args.assemble assembler.assemble() return False elif args.organize: organize.organize_videos() return False return True except Exception as e: logger.error("An error occurred: {:s}".format(str(e))) logger.error("Make sure the config file and given arguments are valid and try again.") logger.separator() return False
def run(): pil.initialize() logging.disable(logging.CRITICAL) config = configparser.ConfigParser() parser = argparse.ArgumentParser( description="You are running PyInstaLive {:s} using Python {:s}". format(Constants.SCRIPT_VER, Constants.PYTHON_VER)) parser.add_argument('-u', '--username', dest='username', type=str, required=False, help="Instagram username to login with.") parser.add_argument('-p', '--password', dest='password', type=str, required=False, help="Instagram password to login with.") parser.add_argument( '-d', '--download', dest='download', type=str, required=False, help= "The username of the user whose livestream or replay you want to save." ) parser.add_argument( '-b,', '--batch-file', dest='batchfile', type=str, required=False, help= "Read a text file of usernames to download livestreams or replays from." ) parser.add_argument('-i', '--info', dest='info', action='store_true', help="View information about PyInstaLive.") parser.add_argument( '-nr', '--no-replays', dest='noreplays', action='store_true', help="When used, do not check for any available replays.") parser.add_argument( '-nl', '--no-lives', dest='nolives', action='store_true', help="When used, do not check for any available livestreams.") parser.add_argument( '-cl', '--clean', dest='clean', action='store_true', help= "PyInstaLive will clean the current download folder of all leftover files." ) parser.add_argument('-cp', '--config-path', dest='configpath', type=str, required=False, help="Path to a PyInstaLive configuration file.") parser.add_argument( '-dp', '--download-path', dest='dlpath', type=str, required=False, help= "Path to folder where PyInstaLive should save livestreams and replays." ) parser.add_argument( '-as', '--assemble', dest='assemble', type=str, required=False, help= "Path to json file required by the assembler to generate a video file from the segments." ) parser.add_argument( '-df', '--download-following', dest='downloadfollowing', action='store_true', help= "PyInstaLive will check for available livestreams and replays from users the account " "used to login follows.") parser.add_argument('-nhb', '--no-heartbeat', dest='noheartbeat', action='store_true', help="Disable heartbeat " "check for " "livestreams.") parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', help="PyInstaLive will output JSON " "responses and some misc " "variables.") parser.add_argument( '-sm', '--skip-merge', dest='skip_merge', action='store_true', help="PyInstaLive will not merge the downloaded livestream files.") parser.add_argument( '-o', '--organize', action='store_true', help= "Create a folder for each user whose livestream(s) you have downloaded. The names of the folders will be their usernames. Then move the video(s) of each user into their associated folder." ) # Workaround to 'disable' argument abbreviations parser.add_argument('--usernamx', help=argparse.SUPPRESS, metavar='IGNORE') parser.add_argument('--passworx', help=argparse.SUPPRESS, metavar='IGNORE') parser.add_argument('--infx', help=argparse.SUPPRESS, metavar='IGNORE') parser.add_argument('--noreplayx', help=argparse.SUPPRESS, metavar='IGNORE') parser.add_argument('--cleax', help=argparse.SUPPRESS, metavar='IGNORE') parser.add_argument('--downloadfollowinx', help=argparse.SUPPRESS, metavar='IGNORE') parser.add_argument('--configpatx', help=argparse.SUPPRESS, metavar='IGNORE') parser.add_argument('--confix', help=argparse.SUPPRESS, metavar='IGNORE') parser.add_argument('--organizx', help=argparse.SUPPRESS, metavar='IGNORE') parser.add_argument('-cx', help=argparse.SUPPRESS, metavar='IGNORE') parser.add_argument('-nx', help=argparse.SUPPRESS, metavar='IGNORE') parser.add_argument('-dx', help=argparse.SUPPRESS, metavar='IGNORE') args, unknown_args = parser.parse_known_args() # Parse arguments if not os.path.exists( pil.config_path): # Create new config if it doesn't exist logger.banner() helpers.new_config() return if validate_inputs(config, args, unknown_args): if not args.username and not args.password: pil.ig_api = auth.authenticate(username=pil.ig_user, password=pil.ig_pass) elif (args.username and not args.password) or (args.password and not args.username): logger.warn( "Missing --username or --password argument. Falling back to config file." ) logger.separator() pil.ig_api = auth.authenticate(username=pil.ig_user, password=pil.ig_pass) elif args.username and args.password: pil.ig_api = auth.authenticate(username=args.username, password=args.password, force_use_login_args=True) if pil.ig_api: if pil.dl_user or pil.args.downloadfollowing: downloader.start() elif pil.dl_batchusers: if not helpers.command_exists("pyinstalive"): logger.error( "PyInstaLive must be properly installed when using the -b argument." ) logger.separator() else: dlfuncs.iterate_users(pil.dl_batchusers)