예제 #1
0
 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))
예제 #2
0
 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"
             )
예제 #3
0
def parser_helper():
    session = Streamlink()
    parser = build_parser()
    setup_plugin_args(session, parser)
    return parser
예제 #4
0
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)
예제 #5
0
 def parser(self):
     return build_parser()
예제 #6
0
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