def test_plugin_has_valid_global_args(self): from streamlink_cli.argparser import build_parser parser = build_parser() global_arg_dests = [action.dest for action in parser._actions] for pname, plugin in self.session.plugins.items(): for parg in plugin.arguments: if parg.is_global: self.assertIn(parg.dest, global_arg_dests, "{0} from plugins.{1} is not a valid global argument".format(parg.name, pname))
def test_plugin_has_valid_global_args(self): parser = build_parser() global_arg_dests = [action.dest for action in parser._actions] for pname, plugin in self.session.plugins.items(): for parg in plugin.arguments: if not parg.is_global: # pragma: no cover continue self.assertIn( parg.dest, global_arg_dests, f"{parg.name} from plugins.{pname} is not a valid global argument" )
def parser_helper(): session = Streamlink() parser = build_parser() setup_plugin_args(session, parser) return parser
def main(): error_code = 0 parser = build_parser() setup_args(parser, ignore_unknown=True) # call argument set up as early as possible to load args from config files setup_config_args(parser, ignore_unknown=True) # Console output should be on stderr if we are outputting # a stream to stdout. if args.stdout or args.output == "-" or args.record_and_pipe: console_out = sys.stderr else: console_out = sys.stdout # We don't want log output when we are printing JSON or a command-line. silent_log = any(getattr(args, attr) for attr in QUIET_OPTIONS) log_level = args.loglevel if not silent_log else "none" setup_logging(console_out, log_level) setup_console(console_out) setup_streamlink() # load additional plugins setup_plugins(args.plugin_dirs) setup_plugin_args(streamlink, parser) # call setup args again once the plugin specific args have been added setup_args(parser) setup_config_args(parser) # update the logging level if changed by a plugin specific config log_level = args.loglevel if not silent_log else "none" logger.root.setLevel(log_level) setup_http_session() check_root() log_current_versions() log_current_arguments(streamlink, parser) if args.version_check or args.auto_version_check: with ignored(Exception): check_version(force=args.version_check) if args.plugins: print_plugins() elif args.can_handle_url: try: streamlink.resolve_url(args.can_handle_url) except NoPluginError: error_code = 1 except KeyboardInterrupt: error_code = 130 elif args.can_handle_url_no_redirect: try: streamlink.resolve_url_no_redirect(args.can_handle_url_no_redirect) except NoPluginError: error_code = 1 except KeyboardInterrupt: error_code = 130 elif args.url: try: setup_options() handle_url() except KeyboardInterrupt: # Close output if output: output.close() console.msg("Interrupted! Exiting...") error_code = 130 finally: if stream_fd: try: log.info("Closing currently open stream...") stream_fd.close() except KeyboardInterrupt: error_code = 130 elif args.help: parser.print_help() else: usage = parser.format_usage() msg = ("{usage}\nUse -h/--help to see the available options or " "read the manual at https://streamlink.github.io").format( usage=usage) console.msg(msg) sys.exit(error_code)
def parser(self): return build_parser()
def main_play(HTTPBase, arglist, redirect=False): parser = build_parser() args = setup_args(parser, arglist, ignore_unknown=True) # create a new session for every request session = LiveProxyStreamlink() log.info('User-Agent: {0}'.format(HTTPBase.headers.get( 'User-Agent', '???'))) log.info('Client: {0}'.format(HTTPBase.client_address)) log.info('Address: {0}'.format(HTTPBase.address_string())) setup_plugins(session, args) setup_plugin_args(session, parser) # call setup args again once the plugin specific args have been added args = setup_args(parser, arglist, ignore_unknown=True) args = setup_config_args(session, args, parser, arglist) logger.root.setLevel(args.loglevel) setup_http_session(session, args) if args.url: setup_options(session, args) try: plugin = session.resolve_url(args.url) setup_plugin_options(session, args, plugin) log.info('Found matching plugin {0} for URL {1}', plugin.module, args.url) plugin_args = [] for parg in plugin.arguments: value = plugin.get_option(parg.dest) if value: plugin_args.append((parg, value)) if plugin_args: log.debug('Plugin specific arguments:') for parg, value in plugin_args: log.debug(' {0}={1} ({2})'.format( parg.argument_name(plugin.module), value if not parg.sensitive else ('*' * 8), parg.dest)) if redirect is True: streams = session.streams(args.url, stream_types=['hls', 'http']) else: streams = session.streams( args.url, stream_types=args.stream_types, sorting_excludes=args.stream_sorting_excludes) except FatalPluginError as err: log.error('FatalPluginError {0}', str(err)) HTTPBase._headers(404, 'text/html', connection='close') return except NoPluginError: log.error('No plugin can handle URL: {0}', args.url) HTTPBase._headers(404, 'text/html', connection='close') return except PluginError as err: log.error('PluginError {0}', str(err)) HTTPBase._headers(404, 'text/html', connection='close') return if not streams: log.error('No playable streams found on this URL: {0}', args.url) HTTPBase._headers(404, 'text/html', connection='close') return if args.default_stream and not args.stream: args.stream = args.default_stream if not args.stream: args.stream = ['best'] stream_ended = False validstreams = format_valid_streams(plugin, streams) for stream_name in args.stream: if stream_name in streams: log.info('Available streams: {0}', validstreams) '''Decides what to do with the selected stream.''' stream_name = resolve_stream_name(streams, stream_name) stream = streams[stream_name] # Find any streams with a '_alt' suffix and attempt # to use these in case the main stream is not usable. alt_streams = list( filter(lambda k: stream_name + '_alt' in k, sorted(streams.keys()))) for stream_name in [stream_name] + alt_streams: stream = streams[stream_name] stream_type = type(stream).shortname() log.info('Opening stream: {0} ({1})', stream_name, stream_type) if isinstance(stream, (RTMPStream)): log.info('RTMP streams ' 'might not work on every platform.') elif isinstance(stream, (MuxedStream, DASHStream)): log.info('FFmpeg streams (dash, muxed) ' 'might not work on every platform.') # 301 if redirect is True: log.info('301 - URL: {0}'.format(stream.url)) HTTPBase.send_response(301) HTTPBase.send_header('Location', stream.url) HTTPBase.end_headers() log.info('301 - done') stream_ended = True break # play try: fd = stream.open() except StreamError as err: log.error('Could not open stream: {0}'.format(err)) continue cache = 4096 HTTPBase._headers(200, 'video/unknown') try: log.debug('Pre-buffering {0} bytes'.format(cache)) while True: buff = fd.read(cache) if not buff: log.error('No Data for buff!') break HTTPBase.wfile.write(buff) HTTPBase.wfile.close() except socket.error as e: if isinstance(e.args, tuple): if e.errno == errno.EPIPE: # remote peer disconnected log.info('Detected remote disconnect') else: log.error(str(e)) else: log.error(str(e)) fd.close() log.info('Stream ended') fd = None stream_ended = True break if not stream_ended: HTTPBase._headers(404, 'text/html', connection='close') return else: err = ('The specified stream(s) \'{0}\' could not be ' 'found'.format(', '.join(args.stream))) log.error('{0}.\n Available streams: {1}', err, validstreams) HTTPBase._headers(404, 'text/html', connection='close') return