# $Id: YouTube 12332 2011-08-21 18:26:19Z glen $
# Video::YouTube - Video getter plugin for rsget.pl
#
# 2009-2011 (c) Przemysław Iskra <sparky@pld-linux.org>
# 2011 (c) Elan Ruusamäe <glen@pld-linux.org>
#		This program is free software,
# you may distribute it under GPL v2 or newer.

name: YouTube
short: V:YouTube
web: "http://www.youtube.com/"
uri: qr{youtube\.com/watch\?v=.*}
slots: max
status: OK 2011-08-21

unify:
	s/#.*//;
	m{[\?&]v=([-_a-zA-Z0-9]+)(?:&.*?)?$};
	return "http://www.youtube.com/watch?v=$1" if $1;

pre:
	my @fmt = (
		[ 38, "mp4", "1200p" ],
		[ 37, "mp4", "1080p" ],
		[ 22, "mp4", "720p" ],
		[ 35, "flv", "HQ" ],
		[ 18, "mp4", "LQ" ],
	);

	sub best_format
	{
		/"fmt_list"\s*:\s*"(.*?)"/ or m{&fmt_map=(\S+?)&}
			or return undef;
		my %fmts = map { m{(\d+)\\?/}; $1 => $_ } split ",", uri_unescape( $1 );

		foreach my $f ( @fmt ) {
			return $f
				if exists $fmts{ $f->[0] };
		}

		return undef;
	}

	# decodes urls for formats
	# tries to put url together as seen in net console in browser
	sub get_uris
	{
		my ($map) = @_;
		my @uri = map { { map { split /=/, $_, 2 } split /&/, uri_unescape($_) } } split /,/, $map;
		my %uri = ();
		foreach my $p (@uri) {
			# will not be added again to url
			my $url = $p->{url};
			undef $p->{url};

			# we need just first part
			my @id = split /\\u0026/, $p->{id};
		   	$p->{id} = $id[0];

			# rest of the keys go to url
			while (my($k, $v) = each %$p) {
				$url .= '&' . $k . '=' . $v if $v;
			}

			# itag is format id
			$uri{$p->{itag}} = $url;
		}
		return %uri;
	}

start:
	GET( $-{_uri} );

	ERROR( "file not found: $1" )
		if /<div\s[^>]+class="yt-alert-content">\s*(The.*?)\s*</s
			or /<div\s[^>]+class="yt-alert-content">\s*(This video contains content from .*?, who has blocked it in your country on copyright grounds\.)\s*</s;
	ERROR( "age verification required" )
		if $-{_referer} =~ m#/verify_age#;

	# try to find best format
	$-{fmt} = best_format();

	# format 18 is almost always hidden,
	# if the best format we found is 5 we check for 18 manually
	GOTO stage_got_format
		if $-{fmt};

	GET( "$-{_uri}&fmt=18" );

	$-{fmt} = best_format();

stage_got_format:
	! m{"video_id": "(.*?)"} or m{'VIDEO_ID': '(.*?)'};
	my $id = $1;

	! m{<meta name="title" content="(.*?)">};
	my $name = de_ml( de_ml( $1 ) );
	$name =~ s{/}{_}g;

	! /"t"\s*:\s*"(.*?)"/ or m{&t=(\S+?)&};
	my $t = $1;

	my $fmt = $-{fmt};
	$fmt ||= [ 5, "flv", "vLQ" ];

	$-{fname} = $name . "." . $fmt->[1];

	/"url_encoded_fmt_stream_map": "(.*?)"/;
	my %uri = get_uris($1);
	my $uri = $uri{ $fmt->[0] };
	$-{file_uri} = $uri;

	GET( $-{file_uri}, headonly => 1 );

	my ( $len ) = /^Content-Length:\s*(\d+)\r?$/mi;
	INFO( name => $-{fname}, size => $len );

	DOWNLOAD( $-{file_uri}, fname => $-{fname} );

# vim: filetype=perl:ts=4:sw=4
