1#!/usr/local/bin/perl 2################################################# 3# 4# This file was automatically generated by utils/combine-perl.pl 5# You should edit the original files, not this 6# combined version. 7# 8# The original files are available at: 9# http://github.com/monsieurvideo/get-flash-videos 10# 11################################################# 12# 13# get_flash_videos -- download all the Flash videos off a web page 14# 15# http://code.google.com/p/get-flash-videos/ 16# 17# Copyright 2009, zakflash and MonsieurVideo 18# 19# Licensed under the Apache License, Version 2.0 (the "License"); you may 20# not use this file except in compliance with the License. You may obtain a 21# copy of the License at 22# http://www.apache.org/licenses/LICENSE-2.0 23# Unless required by applicable law or agreed to in writing, software 24# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 25# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 26# License for the specific language governing permissions and limitations 27# under the License. 28# 29# Contributions are welcome and encouraged, but please take care to 30# maintain the JustWorks(tm) nature of the program. 31##{ utils/combine-header 32{ 33package main; 34$::SCRIPT_NAME = 'get_flash_videos'; 35} 36##} utils/combine-header 37BEGIN { $INC{'FlashVideo/Site/4od.pm'}++; } 38# Part of get-flash-videos. See get_flash_videos for copyright. 39BEGIN { $INC{'FlashVideo/Utils.pm'}++; } 40# Part of get-flash-videos. See get_flash_videos for copyright. 41##{ blib/lib/FlashVideo/Utils.pm 42{ 43package FlashVideo::Utils; 44 45use strict; 46no warnings 'uninitialized'; 47use Exporter;use base 'Exporter'; 48use HTML::Entities; 49use HTML::TokeParser; 50use Encode; 51 52use constant FP_KEY => "Genuine Adobe Flash Player 001"; 53use constant EXTENSIONS => qr/\.(?:flv|mp4|mov|wmv|avi|m4v)/i; 54use constant MAX_REDIRECTS => 5; 55 56our @EXPORT = qw(debug info error 57 extract_title extract_info title_to_filename get_video_filename url_exists 58 swfhash swfhash_data EXTENSIONS get_user_config_dir get_win_codepage 59 is_program_on_path get_terminal_width json_unescape 60 convert_sami_subtitles_to_srt from_xml); 61 62sub debug(@) { 63 my $string = "@_\n"; 64 $string =~ s/\Q$ENV{HOME}\E/~/g; 65 print STDERR $string if $App::get_flash_videos::opt{debug}; 66} 67 68sub info(@) { 69 print STDERR "@_\n" unless $App::get_flash_videos::opt{quiet}; 70} 71 72sub error(@) { 73 print STDERR "@_\n"; 74} 75 76sub extract_title { 77 my($browser) = @_; 78 return extract_info($browser)->{title}; 79} 80 81sub extract_info { 82 my($browser) = @_; 83 my($title, $meta_title); 84 85 my $p = HTML::TokeParser->new(\$browser->content); 86 while(my $token = $p->get_tag("title", "meta")) { 87 my($tag, $attr) = @$token; 88 89 if($tag eq 'meta' && $attr->{name} =~ /title/i) { 90 $meta_title = $attr->{content}; 91 } elsif($tag eq 'title') { 92 $title = $p->get_trimmed_text; 93 } 94 } 95 96 return { 97 title => $title, 98 meta_title => $meta_title, 99 }; 100} 101 102sub swfhash { 103 my($browser, $url) = @_; 104 105 $browser->get($url); 106 107 return swfhash_data($browser->content, $url); 108} 109 110sub swfhash_data { 111 my ($data, $url) = @_; 112 113 die "Must have Compress::Zlib and Digest::SHA for this RTMP download\n" 114 unless eval { 115 require Compress::Zlib; 116 require Digest::SHA; 117 }; 118 119 $data = "F" . substr($data, 1, 7) 120 . Compress::Zlib::uncompress(substr $data, 8); 121 122 return 123 swfsize => length $data, 124 swfhash => Digest::SHA::hmac_sha256_hex($data, FP_KEY), 125 swfUrl => $url; 126} 127 128sub url_exists { 129 my($browser, $url) = @_; 130 131 $browser->head($url); 132 my $response = $browser->response; 133 debug "Exists on $url: " . $response->code; 134 return $url if $response->code == 200; 135 136 my $redirects = 0; 137 while ( ($response->code =~ /^30\d/) and ($response->header('Location')) 138 and ($redirects < MAX_REDIRECTS) ) { 139 $url = URI->new_abs($response->header('Location'), $url); 140 $response = $browser->head($url); 141 debug "Redirected to $url (" . $response->code . ")"; 142 if ($response->code == 200) { 143 return $url; 144 } 145 $redirects++; 146 } 147 148 return ''; 149} 150 151sub title_to_filename { 152 my($title, $type) = @_; 153 154 if($App::get_flash_videos::opt{filename} ne '') { 155 return $App::get_flash_videos::opt{filename}; 156 } 157 158 if($title =~ s/(@{[EXTENSIONS]})$//) { 159 $type = substr $1, 1; 160 } elsif ($type && $type !~ /^\w+$/) { 161 $type = substr((URI->new($type)->path =~ /(@{[EXTENSIONS]})$/)[0], 1); 162 } 163 164 $type ||= "flv"; 165 166 $title = decode_utf8($title); 167 168 utf8::upgrade($title); 169 170 if ($title =~ /&(?:\w+|#(?:\d+|x[A-F0-9]+));/) { 171 $title = decode_entities($title); 172 } 173 174 $title =~ s/\s+/_/g; 175 $title =~ s/[^\w\-,()&]/_/g; 176 $title =~ s/^_+|_+$//g; # underscores at the start and end look bad 177 178 $title = encode_utf8($title); 179 180 return get_video_filename($type) unless $title; 181 182 return "$title.$type"; 183} 184 185sub get_video_filename { 186 my($type) = @_; 187 $type ||= "flv"; 188 return "video" . get_timestamp_in_iso8601_format() . "." . $type; 189} 190 191sub get_timestamp_in_iso8601_format { 192 use Time::localtime; 193 my $time = localtime; 194 return sprintf("%04d%02d%02d%02d%02d%02d", 195 $time->year + 1900, $time->mon + 1, 196 $time->mday, $time->hour, $time->min, $time->sec); 197} 198 199sub get_vlc_exe_from_registry { 200 if ($^O !~ /MSWin/i) { 201 die "Doesn't make sense to call this except on Windows"; 202 } 203 204 my $HAS_WIN32_REGISTRY = eval { require Win32::Registry }; 205 206 die "Win32::Registry required for JustWorks(tm) playing on Windows" 207 unless $HAS_WIN32_REGISTRY; 208 209 require Win32::Registry; 210 211 Win32::Registry->import(); 212 213 my $local_machine; 214 215 { 216 no strict 'vars'; 217 $local_machine = $::HKEY_LOCAL_MACHINE; 218 } 219 220 my $key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'; 221 222 $local_machine->Open($key, my $reg); 223 224 my @applications; 225 $reg->GetKeys(\@applications); 226 227 my $vlc_binary; 228 229 foreach my $application (@applications) { 230 next unless $application =~ /VLC Media Player/i; 231 232 $reg->Open($application, my $details); 233 234 my %app_properties; 235 $details->GetValues(\%app_properties); 236 237 if ($app_properties{DisplayIcon}->[-1] =~ /\.exe$/i) { 238 $vlc_binary = $app_properties{DisplayIcon}->[-1]; 239 last; 240 } 241 } 242 243 return $vlc_binary; 244} 245 246sub get_win_codepage { 247 require Win32::API; 248 249 if (! %Win32::API::Type::Known) { 250 %Win32::API::Type::Known = (int => 'i'); 251 } 252 253 Win32::API->Import("kernel32", "int GetACP()"); 254 return "cp" . GetACP(); 255} 256 257sub get_user_config_dir { 258 259 260 return $^O =~ /MSWin/i ? ($ENV{APPDATA} || 'c:/windows/application data') 261 . "/get_flash_videos" 262 : "$ENV{HOME}/.get_flash_videos"; 263} 264 265sub is_program_on_path { 266 my($program) = @_; 267 my $win = $^O =~ /MSWin/i; 268 269 for my $dir(split($win ? ";" : ":", $ENV{PATH})) { 270 return 1 if -f "$dir/$program" . ($win ? ".exe" : ""); 271 } 272 return 0; 273} 274 275sub get_terminal_width { 276 if(eval { require Term::ReadKey } && (my($width) = Term::ReadKey::GetTerminalSize())) { 277 return $width - 1 if $^O =~ /MSWin|cygwin/i; # seems to be off by 1 on Windows 278 return $width; 279 } elsif($ENV{COLUMNS}) { 280 return $ENV{COLUMNS}; 281 } else { 282 return 80; 283 } 284} 285 286sub json_unescape { 287 my($s) = @_; 288 289 $s =~ s/\\u([0-9a-f]{1,4})/chr hex $1/ge; 290 $s =~ s{(\\[\\/rnt"])}{"\"$1\""}gee; 291 return $s; 292} 293 294sub convert_sami_subtitles_to_srt { 295 my ($sami_subtitles, $filename, $decrypt_callback) = @_; 296 297 die "SAMI subtitles must be provided" unless $sami_subtitles; 298 die "Output SRT filename must be provided" unless $filename; 299 300 $sami_subtitles =~ s/[\r\n]//g; # flatten 301 302 my @lines = split /<Sync\s/i, $sami_subtitles; 303 shift @lines; # Skip headers 304 305 my @subtitles; 306 my $count = 0; 307 308 my $last_proper_sub_end_time = ''; 309 310 for (@lines) { 311 my ($begin, $sub); 312 s|<\/?span.*?>| |g; 313 314 s|&|&|g; 315 316 s{&(?:nbsp|#160);}{ }g; 317 318 319 ($begin, $sub) = ($1, $2) if m{[^>]*Start="(.+?)"[^>]*>(.*?)<\/Sync>}i; 320 321 if (/^\s*Encrypted="true"\s*/i) { 322 if ($decrypt_callback and ref($decrypt_callback) eq 'CODE') { 323 $sub = $decrypt_callback->($sub); 324 } 325 } 326 327 $sub =~ s@&@&@g; 328 $sub =~ s@(?:</?span[^>]*>| | )@ @g; 329 330 $sub =~ s{</?P[^>]*?>}{}g; # remove <P Class="ENCC"> and similar 331 332 $sub =~ s{<(/)?([BI])>}{"<$1" . lc($2) . ">"}eg; 333 334 decode_entities($sub); # in void context, this works in place 335 336 if ($sub and ($begin or $begin == 0)) { 337 my $seconds = int( $begin / 1000.0 ); 338 my $ms = $begin - ( $seconds * 1000.0 ); 339 $begin = sprintf("%02d:%02d:%02d,%03d", (gmtime($seconds))[2,1,0], $ms ); 340 341 342 $sub =~ s/^\s*(.*?)\s*$/$1/; 343 344 $sub =~ s/\s{2,}/ /g; 345 346 $sub =~ s|<br ?\/? ?>|\n|ig; 347 348 $sub =~ s/^\s*|\s*$//mg; 349 350 if ($count and !$subtitles[$count - 1]->{end}) { 351 $subtitles[$count - 1]->{end} = $begin; 352 } 353 354 if (!$sub or $sub =~ /^\s+$/) { 355 if ($count) { 356 $last_proper_sub_end_time = $subtitles[$count - 1]->{end}; 357 } 358 359 next; # this is not a meaningful subtitle 360 } 361 362 push @subtitles, { 363 start => $begin, 364 text => $sub, 365 }; 366 367 $count++; 368 } 369 } 370 371 $subtitles[$count - 1]->{end} = $last_proper_sub_end_time; 372 373 open my $subtitle_fh, '>', $filename 374 or die "Can't open subtitles file $filename: $!"; 375 376 binmode $subtitle_fh, ':utf8'; 377 378 $count = 1; 379 380 foreach my $subtitle (@subtitles) { 381 print $subtitle_fh "$count\n$subtitle->{start} --> $subtitle->{end}\n" . 382 "$subtitle->{text}\n\n"; 383 $count++; 384 } 385 386 close $subtitle_fh; 387 388 return 1; 389} 390 391sub from_xml { 392 my($xml, @args) = @_; 393 394 if(!eval { require XML::Simple && XML::Simple::XMLin("<foo/>") }) { 395 die "Must have XML::Simple to download " . caller =~ /::([^:])+$/ . " videos\n"; 396 } 397 398 $xml = eval { 399 XML::Simple::XMLin(ref $xml eq 'SCALAR' ? $xml 400 : ref $xml ? $xml->content 401 : $xml, @args); 402 }; 403 404 if($@) { 405 die "$@ (from ", join("::", caller), ")\n"; 406 } 407 408 return $xml; 409} 410 4111; 412} 413##} blib/lib/FlashVideo/Utils.pm 414##{ blib/lib/FlashVideo/Site/4od.pm 415{ 416package FlashVideo::Site::4od; 417 418 419use strict; 420BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 421BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *from_xml = \&FlashVideo::Utils::from_xml; } 422use URI::Escape; 423 424sub search { 425 my ($self, $search, $type) = @_; 426 427 unless(eval { from_xml("<foo/>") }) { 428 if($type eq 'site') { 429 die $@; 430 } else { 431 debug $@; 432 return; 433 } 434 } 435 436 my $gdata_template_url = 437 "http://gdata.youtube.com/feeds/api/videos?q=%s&orderby=published&start-index=1&max-results=50&v=2"; 438 my $search_url = sprintf $gdata_template_url, uri_escape($search); 439 440 my $browser = FlashVideo::Mechanize->new(); 441 442 $browser->get($search_url); 443 444 if (!$browser->success) { 445 die "Couldn't get YouTube search Atom XML: " . $browser->response->status_line(); 446 } 447 448 my $xml = from_xml($browser, KeyAttr => [], ForceArray => ['entry']); 449 450 my @matches = map { _process_4od_result($_) } 451 grep { $_->{author}->{name} =~ /^4oD\w+$/i } @{ $xml->{entry} }; 452 453 return @matches; 454} 455 456sub _process_4od_result { 457 my $feed_entry = shift; 458 459 my $url = $feed_entry->{'media:group'}->{'media:player'}->{url}; 460 $url =~ s/&feature=youtube_gdata//; 461 462 my $published_date = $feed_entry->{published}; 463 $published_date =~ s/T.*$//; # only care about date, not time 464 465 my $title = $feed_entry->{'media:group'}->{'media:title'}->{content}; 466 my $description = $feed_entry->{'media:group'}->{'media:description'}->{content}; 467 468 my $result_name = "$title ($published_date)"; 469 470 return { name => $result_name, url => $url, description => $description }; 471} 472 4731; 474} 475##} blib/lib/FlashVideo/Site/4od.pm 476BEGIN { $INC{'FlashVideo/Site/5min.pm'}++; } 477# Part of get-flash-videos. See get_flash_videos for copyright. 478##{ blib/lib/FlashVideo/Site/5min.pm 479{ 480package FlashVideo::Site::5min; 481 482use strict; 483BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 484BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *extract_info = \&FlashVideo::Utils::extract_info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 485 486sub find_video { 487 my ($self, $browser) = @_; 488 489 my $filename = title_to_filename(extract_info($browser)->{meta_title}); 490 491 my $url = (FlashVideo::Generic->find_video($browser, $browser->uri))[0]; 492 493 return $url, $filename; 494} 495 4961; 497} 498##} blib/lib/FlashVideo/Site/5min.pm 499BEGIN { $INC{'FlashVideo/Site/Abc.pm'}++; } 500# Part of get-flash-videos. See get_flash_videos for copyright. 501##{ blib/lib/FlashVideo/Site/Abc.pm 502{ 503package FlashVideo::Site::Abc; 504 505use strict; 506BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 507BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 508 509sub find_video { 510 my ($self, $browser, $embed_url) = @_; 511 512 if ($browser->uri->as_string =~ m'/watch/clip/[\w\-]+/(\w+)/(\w+)/(\w+)') { 513 my $show_id = $1; 514 my $playlist_id = $2; 515 my $video_id = $3; 516 517 return handle_abc_clip($browser, $show_id, $playlist_id, $video_id); 518 } 519 520 my $playpath; 521 if ($browser->content =~ /http:\/\/cdn\.video\.abc\.com\/abcvideo\/video_fep\/thumbnails\/220x124\/([^"]*)220x124\.jpg/) { 522 $playpath = "mp4:/abcvideo/video_fep/mov/" . lc($1) . "768x432_700.mov"; 523 } 524 525 $browser->content =~ /<h2 id="video_title">([^<]*)<\/h2>/; 526 my $title = $1; 527 my $rtmpurl = "rtmp://abcondemandfs.fplive.net:1935/abcondemand"; 528 529 return { 530 rtmp => $rtmpurl, 531 playpath => $playpath, 532 flv => title_to_filename($title) 533 }; 534} 535 536sub handle_abc_clip { 537 my ($browser, $show_id, $playlist_id, $video_id) = @_; 538 539 540 my $abc_clip_rss_url_template = 541 "http://ll.static.abc.com/vp2/ws/s/contents/1000/videomrss?" . 542 "brand=001&device=001&width=644&height=362&clipId=%s" . 543 "&start=0&limit=1&fk=CATEGORIES&fv=%s"; 544 545 my $abc_clip_rss_url = sprintf $abc_clip_rss_url_template, 546 $video_id, $playlist_id; 547 548 $browser->get($abc_clip_rss_url); 549 550 if (!$browser->success) { 551 die "Couldn't download ABC clip RSS: " . $browser->response->status_line; 552 } 553 554 my $xml = from_xml($browser); 555 556 my $video_url = $xml->{channel}->{item}->{'media:content'}->{url}; 557 my $type = $video_url =~ /\.mp4$/ ? 'mp4' : 'flv'; 558 559 if (!$video_url) { 560 die "Couldn't determine ABC clip URL"; 561 } 562 563 my $episode_name; 564 if ($video_url =~ /FLF_\d+[A-Za-z]{0,5}_([^_]+)/) { 565 $episode_name = $1; 566 } 567 568 my $category = $xml->{channel}->{item}->{category}; 569 my $title = $xml->{channel}->{item}->{'media:title'}->{content}; 570 571 if (ref($category) eq 'HASH' and ! keys %$category) { 572 $category = ''; 573 } 574 575 my $description = $xml->{channel}->{item}->{'media:description'}->{content}; 576 577 for ($category, $description, $title) { 578 s/<\/?\w+>//g; 579 } 580 581 my $video_title = make_title($category, $episode_name, $title, $description); 582 583 return $video_url, title_to_filename($video_title, $type); 584} 585 586sub make_title { 587 return join " - ", grep /./, @_; 588} 589 590sub can_handle { 591 my($self, $browser, $url) = @_; 592 593 return $url && URI->new($url)->host =~ /\babc\.(?:go\.)?com$/; 594} 595 5961; 597} 598##} blib/lib/FlashVideo/Site/Abc.pm 599BEGIN { $INC{'FlashVideo/Site/Abclocal.pm'}++; } 600# Part of get-flash-videos. See get_flash_videos for copyright. 601##{ blib/lib/FlashVideo/Site/Abclocal.pm 602{ 603package FlashVideo::Site::Abclocal; 604 605use strict; 606BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 607BEGIN { no strict 'refs'; } 608use Data::Dumper; 609use File::Basename; 610 611sub find_video { 612 my ($self, $browser, $embed_url, $prefs) = @_; 613 614 my($station,$id) = $browser->content =~ m{http://cdn.abclocal.go.com/[^"']*station=([^&;"']+)[^"']*mediaId=([^&;"']+)}s; 615 616 die "No media id and station found" unless $id; 617 618 $browser->get("http://cdn.abclocal.go.com/$station/playlistSyndicated?id=$id"); 619 620 my @tmp = $browser->content =~ m{<video *videopath="([^"]*)"[^>]*width="([^"]*)"[^>]*height="([^"]*)"[^>]*>}s ; 621 my(@videos); 622 for (my $i = 0; $i < @tmp; $i+=3) 623 { 624 push @videos, { "playpath" => $tmp[$i], "resolution" => [$tmp[$i+1], $tmp[$i+2]] }; 625 } 626 627 my $video = $prefs->quality->choose(@videos); 628 629 my $url = $video->{"playpath"}; 630 631 return $url, File::Basename::basename($url); 632} 633 6341; 635} 636##} blib/lib/FlashVideo/Site/Abclocal.pm 637BEGIN { $INC{'FlashVideo/Site/About.pm'}++; } 638# Part of get-flash-videos. See get_flash_videos for copyright. 639BEGIN { $INC{'FlashVideo/Site/Brightcove.pm'}++; } 640# Part of get-flash-videos. See get_flash_videos for copyright. 641##{ blib/lib/FlashVideo/Site/Brightcove.pm 642{ 643package FlashVideo::Site::Brightcove; 644 645use strict; 646BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 647BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 648use MIME::Base64; 649 650sub find_video { 651 my ($self, $browser, $embed_url) = @_; 652 653 my $metadata = { }; 654 my ($video_id, $player_id); 655 656 $video_id = ($browser->content =~ /(?:clip|video)Id["'\] ]*[:=]["' ]*(\d+)/i)[0]; 657 $player_id = ($browser->content =~ /playerId["'\] ]*[:=]["' ]*(\d+)/i)[0]; 658 659 $player_id ||= ($browser->content =~ /<param name=["']?playerID["']? value=["'](\d+) ?["']/i)[0]; 660 $video_id ||= ($browser->content =~ /<param name=["']?\@?video(?:Player|id)["']? value=["'](\d+)["']/i)[0]; 661 662 $player_id ||= ($browser->content =~ /flashVars.*playerID=(\d+)/i)[0]; 663 $video_id ||= ($browser->content =~ /flashVars.*video(?:Player|ID)=(\d+)/i)[0]; 664 665 if(!$player_id && $browser->content =~ /brightcove.player.create\(['"]?(\d+)['"]?,\s*['"]?(\d+)/) { 666 $video_id = $1; 667 $player_id = $2; 668 } 669 670 for my $url($browser->uri->as_string, $embed_url) { 671 if($url =~ /(?:videoID|bctid)=?(\d+)/i) { 672 $video_id ||= $1; 673 } 674 675 if($url =~ /(?:playerID|bcpid)=?(\d+)/i) { 676 $player_id ||= $1; 677 } 678 679 if($url =~ /(?:lineupID|bclid)=?(\d+)/i) { 680 $metadata->{lineupId} ||= $1; 681 } 682 } 683 684 debug "Extracted playerId: $player_id, videoId: $video_id, lineupID: $metadata->{lineupId}" 685 if $player_id or $video_id; 686 687 die "Unable to extract Brightcove IDs from page" unless $player_id; 688 689 $metadata->{videoId} = $video_id; 690 return $self->amfgateway($browser, $player_id, $metadata); 691} 692 693sub amfgateway { 694 my($self, $browser, $player_id, $metadata) = @_; 695 696 my $has_amf_packet = eval { require Data::AMF::Packet }; 697 if (!$has_amf_packet) { 698 die "Must have Data::AMF::Packet installed to download Brightcove videos"; 699 } 700 701 my $page_url = $browser->uri; 702 703 my $packet = Data::AMF::Packet->deserialize(decode_base64(<<EOF)); 704AAAAAAABAEhjb20uYnJpZ2h0Y292ZS50ZW1wbGF0aW5nLlRlbXBsYXRpbmdGYWNhZGUuZ2V0Q29u 705dGVudEZvclRlbXBsYXRlSW5zdGFuY2UAAi8yAAACNQoAAAACAEH4tP+1EAAAEAA1Y29tLmJyaWdo 706dGNvdmUudGVtcGxhdGluZy5Db250ZW50UmVxdWVzdENvbmZpZ3VyYXRpb24ACnZpZGVvUmVmSWQG 707AAd2aWRlb0lkBgAIbGluZXVwSWQGAAtsaW5ldXBSZWZJZAYAF29wdGltaXplRmVhdHVyZWRDb250 708ZW50AQEAF2ZlYXR1cmVkTGluZXVwRmV0Y2hJbmZvEAAkY29tLmJyaWdodGNvdmUucGVyc2lzdGVu 709Y2UuRmV0Y2hJbmZvAApjaGlsZExpbWl0AEBZAAAAAAAAAA5mZXRjaExldmVsRW51bQBAEAAAAAAA 710AAALY29udGVudFR5cGUCAAtWaWRlb0xpbmV1cAAACQAKZmV0Y2hJbmZvcwoAAAACEAAkY29tLmJy 711aWdodGNvdmUucGVyc2lzdGVuY2UuRmV0Y2hJbmZvAApjaGlsZExpbWl0AEBZAAAAAAAAAA5mZXRj 712aExldmVsRW51bQA/8AAAAAAAAAALY29udGVudFR5cGUCAAtWaWRlb0xpbmV1cAAACRAAJGNvbS5i 713cmlnaHRjb3ZlLnBlcnNpc3RlbmNlLkZldGNoSW5mbwAKY2hpbGRMaW1pdABAWQAAAAAAAAAPZ3Jh 714bmRjaGlsZExpbWl0AEBZAAAAAAAAAA5mZXRjaExldmVsRW51bQBACAAAAAAAAAALY29udGVudFR5 715cGUCAA9WaWRlb0xpbmV1cExpc3QAAAkAAAk= 716EOF 717 718 if (defined $player_id) { 719 $packet->messages->[0]->{value}->[0] = "$player_id"; 720 } 721 722 if (ref $metadata) { 723 for(keys %$metadata) { 724 $packet->messages->[0]->{value}->[1]->{$_} = "$metadata->{$_}"; 725 } 726 } 727 728 my $data = $packet->serialize; 729 730 $browser->post( 731 "http://c.brightcove.com/services/amfgateway", 732 Content_Type => "application/x-amf", 733 Content => $data 734 ); 735 736 die "Failed to post to Brightcove AMF gateway" 737 unless $browser->response->is_success; 738 739 $packet = Data::AMF::Packet->deserialize($browser->content); 740 741 if($self->debug) { 742 require Data::Dumper; 743 debug Data::Dumper::Dumper($packet); 744 } 745 746 if(ref $packet->messages->[0]->{value} ne 'ARRAY') { 747 die "Unexpected data from AMF gateway"; 748 } 749 750 my @found; 751 for (@{$packet->messages->[0]->{value}}) { 752 if ($_->{data}->{videoDTO}) { 753 push @found, $_->{data}->{videoDTO}; 754 } 755 if ($_->{data}->{videoDTOs}) { 756 push @found, @{$_->{data}->{videoDTOs}}; 757 } 758 } 759 760 my @rtmpdump_commands; 761 762 for my $d (@found) { 763 next if $metadata->{videoId} && $d->{id} != $metadata->{videoId}; 764 765 my $host = ($d->{FLVFullLengthURL} =~ m!rtmp://(.*?)/!)[0]; 766 my $file = ($d->{FLVFullLengthURL} =~ m!&([a-z0-9:]+/.*?)(?:&|$)!)[0]; 767 my $app = ($d->{FLVFullLengthURL} =~ m!//.*?/(.*?)/&!)[0]; 768 my $filename = ($d->{FLVFullLengthURL} =~ m!&.*?/([^/&]+)(?:&|$)!)[0]; 769 770 $app .= "?videoId=$d->{id}&lineUpId=$d->{lineupId}&pubId=$d->{publisherId}&playerId=$player_id&playerTag=&affiliateId="; 771 772 my $args = { 773 app => $app, 774 pageUrl => $page_url, 775 swfUrl => "http://admin.brightcove.com/viewer/federated/f_012.swf?bn=590&pubId=$d->{publisherId}", 776 tcUrl => "rtmp://$host:1935/$app", 777 auth => ($d->{FLVFullLengthURL} =~ /^[^&]+&(.*)$/)[0], 778 rtmp => "rtmp://$host/$app", 779 playpath => $file, 780 flv => "$filename.flv", 781 }; 782 783 if ($d->{publisherName} and $d->{displayName}) { 784 $args->{flv} = title_to_filename("$d->{publisherName} - $d->{displayName}"); 785 } 786 787 if (!$d->{FLVFullLengthStreamed}) { 788 info "Brightcove HTTP download detected"; 789 return ($d->{FLVFullLengthURL}, $args->{flv}); 790 } 791 792 push @rtmpdump_commands, $args; 793 } 794 795 if (@rtmpdump_commands > 1) { 796 return \@rtmpdump_commands; 797 } 798 else { 799 return $rtmpdump_commands[-1]; 800 } 801} 802 803sub can_handle { 804 my($self, $browser, $url) = @_; 805 806 return 1 if $url && URI->new($url)->host =~ /\.brightcove\.com$/; 807 808 return $browser->content =~ /(playerI[dD]|brightcove.player.create)/ 809 && $browser->content =~ /brightcove/i; 810} 811 8121; 813} 814##} blib/lib/FlashVideo/Site/Brightcove.pm 815##{ blib/lib/FlashVideo/Site/About.pm 816{ 817package FlashVideo::Site::About; 818 819use strict; 820BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 821BEGIN { no strict 'refs'; } 822BEGIN { FlashVideo::Site::Brightcove->import(); } # (added by utils/combine-perl.pl) 823use base 'FlashVideo::Site::Brightcove'; 824 825my $JS_RE = qr/vdo_None\.js/; 826 827sub find_video { 828 my($self, $browser, $embed_url) = @_; 829 830 my($video_ref) = $browser->content =~ /zIvdoId=["']([^"']+)/; 831 die "Unable to extract video ref" unless $video_ref; 832 833 my($js_src) = $browser->content =~ /["']([^"']+$JS_RE)/; 834 $browser->get($js_src); 835 my($player_id) = $browser->content =~ /playerId.*?(\d+)/; 836 die "Unable to extract playerId" unless $player_id; 837 838 return $self->amfgateway($browser, $player_id, { videoRefId => $video_ref }); 839} 840 841sub can_handle { 842 my($self, $browser, $url) = @_; 843 844 return $browser->content =~ $JS_RE; 845} 846 8471; 848} 849##} blib/lib/FlashVideo/Site/About.pm 850BEGIN { $INC{'FlashVideo/Site/Adultswim.pm'}++; } 851# Part of get-flash-videos. See get_flash_videos for copyright. 852##{ blib/lib/FlashVideo/Site/Adultswim.pm 853{ 854package FlashVideo::Site::Adultswim; 855 856use strict; 857BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 858BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 859 860sub find_video { 861 my($self, $browser, $embed_url) = @_; 862 863 my $xml; 864 my $id; 865 866 my $segIds; 867 if($browser->{content} =~ m/(<meta[^>]* ?name=["']segIds["'] ?[^>]*>)/){ 868 my $text = $1; 869 if($text =~ m/content=["']([^"']+)["']/){ 870 $segIds = $1; 871 } 872 } 873 874 my $id1; 875 if($segIds =~ m/^([^#]*)#/){ 876 $id1 = $1; 877 } 878 879 my $title; 880 if($browser->{content} =~ m/<meta property=["']og:title["'] content=["']([^"']+)["']\/>/){ 881 $title = $1; 882 } 883 884 my $configURL = "/tools/swf/player_configs/watch_player.xml"; 885 886 if($browser->content =~ /pageObj\.configURL = ["']([^"']+)["'];/) { 887 $configURL = $1; 888 } 889 890 $browser->get($configURL); 891 892 my $serviceConfigURL; 893 894 if($browser->response->code =~ /^30\d$/){ 895 896 $xml = from_xml($browser); 897 898 if($xml->{serviceConfigURL} ne ""){ 899 $serviceConfigURL = $1; 900 } 901 } else { 902 $serviceConfigURL = "http://asfix.adultswim.com/staged/AS.configuration.xml"; 903 } 904 905 $browser->get($serviceConfigURL); 906 907 $xml = from_xml($browser); 908 909 my $getVideoPlayerURL; 910 if($xml->{config}->{services}->{getVideoPlaylist}->{url} ne ""){ 911 $getVideoPlayerURL = $1; 912 } else { 913 $getVideoPlayerURL = "http://asfix.adultswim.com/asfix-svc/episodeservices/getVideoPlaylist?networkName=AS"; 914 } 915 916 my $videoURL = "$getVideoPlayerURL&id=$id1"; 917 $browser->get($videoURL); 918 919 $xml = from_xml($browser); 920 921 922 923 my $pick = $xml->{entry}[4]; 924 925 my $file_url = $pick->{ref}->{href}; 926 927 928 return $file_url, title_to_filename($title); 929} 930 9311; 932} 933##} blib/lib/FlashVideo/Site/Adultswim.pm 934BEGIN { $INC{'FlashVideo/Site/Amazon.pm'}++; } 935# Part of get-flash-videos. See get_flash_videos for copyright. 936##{ blib/lib/FlashVideo/Site/Amazon.pm 937{ 938package FlashVideo::Site::Amazon; 939 940use strict; 941 942use Encode; 943BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 944BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 945use URI::Escape; 946 947my $playlist_url_template = 'http://%s/gp/mpd/getplaylist-v2/%s/%s'; 948 949sub find_video { 950 my ($self, $browser) = @_; 951 952 my $amazon_host = $browser->uri()->host(); 953 954 if ($browser->content =~ /swfParams\.xmlUrl = ["'](http:.*?)["']/) { 955 debug "Getting Amazon URL direct URL $1"; 956 $browser->get($1); 957 } 958 else { 959 my ($video_id, $session_id); 960 961 if ($browser->content =~ 962 /swfParams\.mediaObjectId = ["'](.*?)["']/) { 963 $video_id = $1; 964 } 965 else { 966 die "Couldn't find video ID / media object ID in Amazon page"; 967 } 968 969 if ($browser->content =~ 970 /swfParams\.sessionId = ["'](.*?)["']/) { 971 $session_id = $1; 972 } 973 else { 974 die "Couldn't find session ID in Amazon page"; 975 } 976 977 my $playlist_url = 978 sprintf($playlist_url_template, $amazon_host, $video_id, $session_id); 979 980 $browser->get($playlist_url); 981 } 982 983 my ($title, @video_urls) = parse_smil_like_xml($browser->content); 984 985 my $filename = title_to_filename($title); 986 987 return $video_urls[0], $filename; 988} 989 990sub parse_smil_like_xml { 991 my $smil = shift; 992 993 my $parsed_smil = from_xml($smil); 994 995 996 my $title; 997 998 my $video_ref = $parsed_smil->{videoObject}->{smil}->{body}->{switch}->{video}; 999 if (ref($video_ref) ne 'ARRAY') { 1000 my $id; 1001 1002 my %videos = %{ $parsed_smil->{videoObject} }; 1003 1004 foreach my $video (keys %videos) { 1005 next unless ref $videos{$video}; 1006 1007 if ($videos{$video}->{index} == 0) { 1008 $id = $video; 1009 $title = $videos{$video}->{title}; 1010 last; 1011 } 1012 } 1013 1014 $video_ref = $parsed_smil->{videoObject}->{$id}->{smil}->{body}->{switch}->{video}; 1015 } 1016 1017 my @different_quality_videos = map { $_->{src} } 1018 sort { $b->{'system-bitrate'} <=> $a->{'system-bitrate'} } 1019 @$video_ref; 1020 1021 $title ||= $parsed_smil->{videoObject}->{title}; 1022 1023 if ($title !~ /\s/) { 1024 $title = uri_unescape($title); 1025 } 1026 1027 return ($title, @different_quality_videos); 1028} 1029 10301; 1031} 1032##} blib/lib/FlashVideo/Site/Amazon.pm 1033BEGIN { $INC{'FlashVideo/Site/Aniboom.pm'}++; } 1034# Part of get-flash-videos. See get_flash_videos for copyright. 1035##{ blib/lib/FlashVideo/Site/Aniboom.pm 1036{ 1037package FlashVideo::Site::Aniboom; 1038 1039use strict; 1040BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 1041BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 1042 1043sub find_video { 1044 my ($self, $browser, $embed_url) = @_; 1045 1046 my ($id, $url, $title); 1047 1048 if ($browser->uri->as_string =~ /\/animation-video\/(\d*)\/([^\/]*)/) { 1049 $id = $1; 1050 $title = $2; 1051 $title =~ s/-/ /g; 1052 } else { 1053 die "Could not detect video ID!"; 1054 } 1055 1056 $browser->get("http://www.aniboom.com/animations/player/handlers/animationDetails.aspx?mode=&movieid=$id"); 1057 1058 if ($browser->content =~ /(?:mp4|flv)=([^&]*)/) { 1059 $url = $1; 1060 $url =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; 1061 } else { 1062 die "Could not get flv/mp4 location!"; 1063 } 1064 1065 return $url, title_to_filename($title); 1066} 1067 10681; 1069 1070} 1071##} blib/lib/FlashVideo/Site/Aniboom.pm 1072BEGIN { $INC{'FlashVideo/Site/Apple.pm'}++; } 1073# Part of get-flash-videos. See get_flash_videos for copyright. 1074##{ blib/lib/FlashVideo/Site/Apple.pm 1075{ 1076package FlashVideo::Site::Apple; 1077use strict; 1078BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 1079BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; } 1080 1081sub find_video { 1082 my ($self, $browser, $embed_url, $prefs) = @_; 1083 1084 if(!FlashVideo::Downloader->check_file($browser->content)) { 1085 my @urls = $browser->content =~ /['"]([^'"]+\.mov)(?:\?[^'"]+)?['"]/g; 1086 die "No .mov URLs found on page" unless @urls; 1087 debug "Found URLs: @urls"; 1088 1089 my $redirect_url = $prefs->quality->choose(map { 1090 /(\d+p?)\.mov/ && { 1091 url => $_, 1092 resolution => $prefs->quality->format_to_resolution($1) 1093 } 1094 } @urls 1095 )->{url}; 1096 1097 $browser->get($redirect_url); 1098 } 1099 1100 my $url = $self->handle_mov($browser); 1101 my $filename = ($url->path =~ m{([^/]+)$})[0]; 1102 1103 return $url, $filename; 1104} 1105 1106sub handle_mov { 1107 my ($self, $browser) = @_; 1108 1109 $browser->agent("Apple iPhone OS v2.0.1 CoreMedia v1.0.0.5B108"); 1110 1111 if($browser->content =~ /url\s*\0+[\1-,]*(.*?)\0/) { 1112 return URI->new_abs($1, $browser->uri) 1113 } else { 1114 die "Cannot find link in .mov"; 1115 } 1116} 1117 1118sub can_handle { 1119 my($self, $browser, $url) = @_; 1120 1121 return $url =~ m{apple\.com/trailers/} || $url =~ m{movies\.apple\.com}; 1122} 1123 11241; 1125} 1126##} blib/lib/FlashVideo/Site/Apple.pm 1127BEGIN { $INC{'FlashVideo/Site/Arte.pm'}++; } 1128# Part of get-flash-videos. See get_flash_videos for copyright. 1129##{ blib/lib/FlashVideo/Site/Arte.pm 1130{ 1131package FlashVideo::Site::Arte; 1132 1133use strict; 1134BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 1135BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 1136 1137sub find_video { 1138 my ($self, $browser, $embed_url, $prefs) = @_; 1139 my ($lang, $xmlurl1, $xmlurl2, $filename, $videourl, $hash, $playerurl, $quality); 1140 1141 debug "Arte::find_video called, embed_url = \"$embed_url\"\n"; 1142 1143 my $pageurl = $browser->uri() . ""; 1144 if($pageurl =~ /videos\.arte\.tv\/(..)\//) { 1145 $lang = $1; 1146 } else { 1147 die "Unable to find language in original URL \"$pageurl\"\n"; 1148 } 1149 1150 if($browser->content =~ /videorefFileUrl = "(.*)";/) { 1151 $xmlurl1 = $1; 1152 debug "found videorefFileUrl \"$xmlurl1\"\n"; 1153 ($filename = $xmlurl1) =~ s/-.*$//; 1154 $filename =~ s/^.*\///g; 1155 $filename = title_to_filename($filename); 1156 } else { 1157 die "Unable to find 'videorefFileUrl' in page\n"; 1158 } 1159 1160 if($browser->content =~ /<param name="movie" value="(http:\/\/videos\.arte\.tv\/[^\?]+)\?/) { 1161 $playerurl = $1; 1162 debug "found playerurl \"$playerurl\"\n"; 1163 } 1164 1165 $browser->get($xmlurl1); 1166 1167 if($browser->content =~ /<video lang="$lang" ref="(.*)" \/>/) { 1168 $xmlurl2 = $1; 1169 debug "found <video ref=\"$xmlurl2\">\n"; 1170 } else { 1171 die "Unable to find <video ref...> in XML $xmlurl1\n"; 1172 } 1173 1174 $browser->get($xmlurl2); 1175 $quality = {high => 'hd', low => 'sd'}->{$prefs->{quality}}; 1176 1177 if($browser->content =~ /<url quality="$quality">([^<]+)<\/url>/) { 1178 $videourl = { rtmp => $1, 1179 flv => $filename}; 1180 if(defined $playerurl) { 1181 $videourl->{swfVfy} = $playerurl; 1182 } 1183 } else { 1184 die "Unable to find <url ...> in XML $xmlurl2\n"; 1185 } 1186 1187 return $videourl, $filename; 1188} 1189 11901; 1191} 1192##} blib/lib/FlashVideo/Site/Arte.pm 1193BEGIN { $INC{'FlashVideo/Site/Bbc.pm'}++; } 1194# Part of get-flash-videos. See get_flash_videos for copyright. 1195##{ blib/lib/FlashVideo/Site/Bbc.pm 1196{ 1197package FlashVideo::Site::Bbc; 1198 1199use strict; 1200BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 1201BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; *error = \&FlashVideo::Utils::error; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 1202use URI; 1203 1204sub find_video { 1205 my ($self, $browser, $page_url, $prefs) = @_; 1206 1207 my $count = 0; 1208 while((my $location = $browser->response->header("Location")) && $count++ < 5) { 1209 $browser->get($location); 1210 } 1211 1212 my $playlist_xml; 1213 if ($browser->content =~ /<param name="playlist" value="(http:.+?\.s?xml)"/) { 1214 $playlist_xml = $1; 1215 } 1216 elsif($browser->content =~ /empDivReady\s*\(([^)]+)/) { 1217 my @params = split /,\s*/, $1; 1218 1219 my $id = $params[3]; 1220 my $path = $params[4]; 1221 1222 $id =~ s/['"]//g; 1223 $path =~ s/['"]//g; 1224 1225 $playlist_xml = URI->new_abs($path, $browser->uri) . "/media/emp/playlists/$id.xml"; 1226 } 1227 elsif($browser->content =~ /setPlaylist\s*\(([^)]+)/) { 1228 my $path = $1; 1229 $path =~ s/['"]//g; 1230 $playlist_xml = URI->new_abs($path, $browser->uri); 1231 } 1232 elsif($browser->content =~ /EmpEmbed.embed\s*\((.*?)\);/) { 1233 my $path = (split /,/, $1)[3]; 1234 $path =~ s/"//g; 1235 $playlist_xml = URI->new_abs($path, $browser->uri); 1236 } 1237 elsif($browser->uri =~ m!/(b[0-9a-z]{7})(?:/|$)!) { 1238 my @gi_cmd = (qw(get_iplayer -g --pid), $1); 1239 1240 if($browser->content =~ /buildAudioPlayer/) { 1241 push @gi_cmd, "--type=radio"; 1242 } 1243 1244 error "get_flash_videos does not support iplayer, but get_iplayer does.."; 1245 info "Attempting to run '@gi_cmd'"; 1246 exec @gi_cmd; 1247 error "Please download get_iplayer from http://linuxcentre.net/getiplayer/\n" . 1248 "and install in your PATH"; 1249 exit 1; 1250 } 1251 else { 1252 die "Couldn't find BBC XML playlist URL in " . $browser->uri->as_string; 1253 } 1254 1255 $browser->get($playlist_xml); 1256 if (!$browser->success) { 1257 die "Couldn't download BBC XML playlist $playlist_xml: " . 1258 $browser->response->status_line; 1259 } 1260 1261 my $playlist = eval { from_xml($browser, KeyAttr => {item => 'kind'}) }; 1262 1263 if ($@) { 1264 my $content = $browser->content; 1265 if ($content !~ m{</media>}) { 1266 $content .= "\n</media></item></playlist>\n"; 1267 } 1268 $playlist = from_xml($$content, KeyAttr => {item => 'kind'}) 1269 } 1270 1271 my $sound = ($playlist->{item}->{guidance} !~ /has no sound/); 1272 1273 my $info = ref $playlist->{item}->{media} eq 'ARRAY' 1274 ? $playlist->{item}->{media}->[0]->{connection} 1275 : $playlist->{item}->{media}->{connection}; 1276 1277 $info = $playlist->{item}->{programme}->{media}->{connection} unless $info; 1278 1279 $info->{application} ||= "ondemand"; 1280 1281 if (!$info->{server}) { 1282 my $id = $playlist->{item}->{mediator}->{identifier}; 1283 if(!$id) { $id = $playlist->{item}->{programme}->{mediator}->{identifier}; } 1284 1285 my $stream_info_url = sprintf 1286 "http://open.live.bbc.co.uk/mediaselector/4/mtis/stream/%s", $id; 1287 1288 $browser->back(); 1289 $browser->get($stream_info_url); 1290 1291 if (!$browser->success) { 1292 die "Couldn't get BBC stream info URL: " . 1293 $browser->response->status_line; 1294 } 1295 1296 my $stream_info = from_xml($browser->content); 1297 1298 if( ref $stream_info->{media} eq 'ARRAY' ){ 1299 my $q = $prefs->{quality}; 1300 my @media = sort { $a->{bitrate} <=> $b->{bitrate} } @{$stream_info->{media}}; 1301 my @q_media = grep { $_->{bitrate} == $q || "$_->{height}x$_->{width}x$_->{bitrate}" == $q || "$_->{height}x$_->{width}" == $q } @media; 1302 if( @q_media ){ @media = @q_media; } 1303 my $cnt = @media; 1304 my $num = {high => int($cnt)-1, medium => int($cnt/2), low => 0}->{$q}; 1305 $info = $media[$num]->{connection}; 1306 } else { 1307 $info = $stream_info->{media}->{connection}; 1308 } 1309 } 1310 1311 if( $info->{href} ){ 1312 my $url = $info->{href}; 1313 my @path = URI->new($url)->path_segments(); 1314 return $url, @path[-1]; 1315 } 1316 1317 my $data = { 1318 app => $info->{application}, 1319 tcUrl => "rtmp://$info->{server}/$info->{application}", 1320 swfUrl => "http://news.bbc.co.uk/player/emp/2.11.7978_8433/9player.swf", 1321 pageUrl => $page_url, 1322 rtmp => "rtmp://" . $info->{server} . "/$info->{application}", 1323 playpath => $info->{identifier}, 1324 flv => title_to_filename('BBC - ' . $playlist->{title} . 1325 ($sound ? '' : ' (no sound)')) 1326 }; 1327 1328 if ($info->{authString}) { 1329 my $token = $info->{authString}; 1330 1331 $data->{app} = "$info->{application}?_fcs_vhost=$info->{server}" . 1332 "&$token"; 1333 1334 $data->{tcUrl} = "rtmp://$info->{server}/$info->{application}?_fcs_vhost=$info->{server}" 1335 . "&$token"; 1336 1337 $data->{playpath} .= "?$token"; 1338 } 1339 1340 if ($info->{identifier} =~ /^secure/ or $info->{tokenIssuer}) { 1341 my $url = "http://www.bbc.co.uk/mediaselector/4/gtis?server=$info->{server}" . 1342 "&identifier=$info->{identifier}&kind=$info->{kind}" . 1343 "&application=$info->{application}&cb=123"; 1344 1345 debug "Got BBC auth URL for 'secure' video: $url"; 1346 1347 $browser->get($url); 1348 1349 if (my $redirect = $browser->response->header('Location')) { 1350 debug "BBC auth URL redirects to: $url"; 1351 $browser->get($redirect); 1352 } 1353 1354 my $stream_auth = from_xml($browser); 1355 1356 my $token = $stream_auth->{token}; 1357 1358 if (!$token) { 1359 die "Couldn't get token for 'secure' video download"; 1360 } 1361 1362 $data->{app} = "$info->{application}?_fcs_vhost=$info->{server}" 1363 . "&auth=$token" 1364 . "&aifp=v001&slist=" . $info->{identifier}; 1365 $data->{tcUrl} = "rtmp://$info->{server}/$info->{application}?_fcs_vhost=$info->{server}" 1366 . "&auth=$token" 1367 . "&aifp=v001&slist=" . $info->{identifier}; 1368 $data->{playpath} .= "?auth=$token&aifp=v0001"; 1369 1370 if($info->{application} eq 'live') { 1371 $data->{subscribe} = $data->{playpath}; 1372 $data->{live} = 1; 1373 } 1374 } 1375 1376 return $data; 1377} 1378 13791; 1380} 1381##} blib/lib/FlashVideo/Site/Bbc.pm 1382BEGIN { $INC{'FlashVideo/Site/Bing.pm'}++; } 1383# Part of get-flash-videos. See get_flash_videos for copyright. 1384##{ blib/lib/FlashVideo/Site/Bing.pm 1385{ 1386package FlashVideo::Site::Bing; 1387use strict; 1388BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 1389BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 1390 1391sub find_video { 1392 my ($self, $browser, $embed_url, $prefs) = @_; 1393 1394 my $count = 0; 1395 while((my $location = $browser->response->header("Location")) && $count++ < 5) { 1396 $browser->get($location); 1397 } 1398 1399 my $title; 1400 if ($browser->content =~ /sourceFriendly:\s*'([^']+)'[\s\S]+?\s*title:\s*'([^']+)'/) { 1401 $title = "$1 - $2"; 1402 } 1403 1404 my $url; 1405 if ($browser->content =~ /formatCode:\s*1003,\s*url:\s*'([^']+)'/) { 1406 $url = $1; 1407 1408 $url =~ s/\\x([0-9a-f]{2})/chr hex $1/egi; 1409 } 1410 die "Unable to extract video url" unless $url; 1411 1412 $browser->allow_redirects; 1413 1414 return $url, title_to_filename($title); 1415} 1416 14171; 1418} 1419##} blib/lib/FlashVideo/Site/Bing.pm 1420BEGIN { $INC{'FlashVideo/Site/Blip.pm'}++; } 1421# Part of get-flash-videos. See get_flash_videos for copyright. 1422##{ blib/lib/FlashVideo/Site/Blip.pm 1423{ 1424package FlashVideo::Site::Blip; 1425 1426use strict; 1427BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 1428BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 1429 1430sub find_video { 1431 my ($self, $browser, $embed_url) = @_; 1432 my $base = "http://blip.tv"; 1433 1434 my $id; 1435 if($embed_url =~ m{flash/(\d+)}) { 1436 $id = $1; 1437 } else { 1438 $browser->get($embed_url); 1439 1440 if($browser->response->is_redirect 1441 && $browser->response->header("Location") =~ m!(?:/|%2f)(\d+)!i) { 1442 $id = $1; 1443 } else { 1444 $id = ($browser->content =~ m!/rss/flash/(\d+)!)[0]; 1445 } 1446 } 1447 1448 if (!$id) { 1449 if ($browser->content =~ /post_masthed_(\d+)/) { 1450 $id = $1; 1451 } 1452 } 1453 1454 if (!$id) { ($id) = ($browser->content =~ m{data-posts-id="(\d+)"}s); } 1455 if (!$id) { ($id) = ($browser->content =~ m{data-disqus-id="(\d+)"}s); } 1456 if (!$id) { ($id) = ($browser->content =~ m{content="http://[^"]-(\d+)"}s); } 1457 1458 die "No ID found\n" unless $id; 1459 1460 $browser->get("$base/rss/flash/$id"); 1461 1462 my $xml = from_xml($browser); 1463 1464 my $content = $xml->{channel}->{item}->{"media:group"}->{"media:content"}; 1465 1466 my $url = ref $content eq 'ARRAY' ? $content->[0]->{url} : $content->{url}; 1467 1468 my $filename = title_to_filename($xml->{channel}->{item}->{title}, $url); 1469 1470 $browser->allow_redirects; 1471 1472 return $url, $filename; 1473} 1474 14751; 1476} 1477##} blib/lib/FlashVideo/Site/Blip.pm 1478BEGIN { $INC{'FlashVideo/Site/Break.pm'}++; } 1479# Part of get-flash-videos. See get_flash_videos for copyright. 1480##{ blib/lib/FlashVideo/Site/Break.pm 1481{ 1482package FlashVideo::Site::Break; 1483 1484use strict; 1485BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 1486BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 1487use URI::Escape; 1488 1489sub find_video { 1490 my($self, $browser, $embed_url) = @_; 1491 1492 my $video_id; 1493 1494 if ($browser->content =~ /flashVars\.icon = ["'](\w+)["']/) { 1495 $video_id = $1; 1496 } 1497 else { 1498 die "Couldn't get Break video ID"; 1499 } 1500 1501 if($browser->content =~ /<meta name=['"]embed_video_url['"] content=["']([^'"]*)["']/) { 1502 $browser->get($1); 1503 } 1504 1505 if(URI->new($embed_url)->host eq "embed.break.com") { 1506 $browser->get($embed_url); 1507 } 1508 1509 if($browser->uri->host eq "embed.break.com") { 1510 if(!$browser->success && $browser->response->header('Location') !~ /sVidLoc/) { 1511 $browser->get($browser->response->header('Location')); 1512 } 1513 1514 if($browser->response->header("Location") =~ /sVidLoc=([^&]+)/) { 1515 my $url = uri_unescape($1).'?'.$video_id; 1516 my $filename = title_to_filename((split /\//, $url)[-1]); 1517 1518 return $url, $filename; 1519 } 1520 } 1521 1522 my $path = ($browser->content =~ /sGlobalContentFilePath='([^']+)'/)[0]; 1523 my $filename = ($browser->content =~ /sGlobalFileName='([^']+)'/)[0]; 1524 1525 die "Unable to extract path and filename" unless $path and $filename; 1526 1527 my $video_path = ($browser->content =~ /videoPath\s*(?:',|=)\s*['"]([^'"]+)/)[0]; 1528 1529 $browser->allow_redirects; 1530 1531 return $video_path . $path . "/" . $filename . ".flv" . "?" . $video_id, 1532 title_to_filename($filename); 1533} 1534 15351; 1536} 1537##} blib/lib/FlashVideo/Site/Break.pm 1538BEGIN { $INC{'FlashVideo/Site/Canalvie.pm'}++; } 1539############################################################################# 1540################################################# 1541# 1542# This file was automatically generated by utils/combine-perl.pl 1543# You should edit the original files, not this 1544# combined version. 1545# 1546# The original files are available at: 1547# http://github.com/monsieurvideo/get-flash-videos 1548# 1549################################################# 1550# Canalvie.pm 2010-11-25 1551# 1552# Reverse-engineered using URLSnooper v2.28.01 & WinPcap 4.1.2 1553# 1554# Stavr0 1555# 1556# 1557##{ blib/lib/FlashVideo/Site/Canalvie.pm 1558{ 1559{ 1560package FlashVideo::Site::Canalvie; 1561 1562use strict; 1563BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 1564BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 1565 1566sub find_video { 1567 my($self, $browser, $embed_url, $prefs) = @_; 1568 1569 my $check_response = sub { 1570 my ( $message ) = @_; 1571 return if $browser->success; 1572 die sprintf $message, $browser->response->code; 1573 }; 1574 1575 1576 my $videoID = 0; 1577 1578 ( $videoID ) = ( $browser->content =~ /var\s+videoId\s*=\s*(\d+)\s*;/ ); 1579 debug "VIDEOID = " . $videoID; 1580 1581 die "No Canalvie Video ID found" unless $videoID; 1582 1583 my $title; 1584 ( $title ) = ( $browser->content =~ /NOM EPISODE\+LIEN ici --><a [^>]+>([^<]+)/ ); 1585 debug "TITLE = " . $title . " " . title_to_filename($title, 'flv'); 1586 1587 my $xmlurl = 'http://www.canalvie.com/webtele/_dyn/getVideoDataXml.jsp?videoId=' . $videoID; 1588 $browser->get($xmlurl); 1589 my $xml = from_xml($browser); 1590 1591 my $url; 1592 if ( $prefs->{quality} == "high" ) { 1593 $url = $xml->{video}->{highFlvUrl}; 1594 } else { 1595 $url = $xml->{video}->{lowFlvUrl}; 1596 } 1597 debug "URL = " . $url; 1598 1599 my $ext; 1600 ( $ext ) = ( $url =~ /\.(.+)$/ ); 1601 1602 die "No (high|low)FlvUrl found in XML ". $xmlurl unless $url; 1603 1604 return $url, title_to_filename($title, $ext); 1605 1606 } 1607 1608 16091; 1610}} 1611##} blib/lib/FlashVideo/Site/Canalvie.pm 1612BEGIN { $INC{'FlashVideo/Site/Canoe.pm'}++; } 1613# Part of get-flash-videos. See get_flash_videos for copyright. 1614##{ blib/lib/FlashVideo/Site/Canoe.pm 1615{ 1616package FlashVideo::Site::Canoe; 1617 1618use strict; 1619BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 1620BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; } 1621BEGIN { FlashVideo::Site::Brightcove->import(); } # (added by utils/combine-perl.pl) 1622use base 'FlashVideo::Site::Brightcove'; 1623 1624sub find_video { 1625 my ($self, $browser, $embed_url) = @_; 1626 1627 my $video_id = ($browser->content =~ /player.SetVideo.(\d+)/i)[0]; 1628 my $player_id = ($browser->content =~ /player.SetPlayer.(\d+)/i)[0]; 1629 1630 debug "Extracted playerId: $player_id, videoId: $video_id" 1631 if $player_id or $video_id; 1632 1633 if(!$video_id) { 1634 my $video_offset = ($browser->content =~ /player.SetVideo.\w+\[(\d+)/i)[0]; 1635 $video_id = ($browser->content =~ /videos\[$video_offset\].+'(\d+)'\s*\]/)[0]; 1636 } 1637 1638 die "Unable to extract Brightcove IDs from page" 1639 unless $player_id and $video_id; 1640 1641 return $self->amfgateway($browser, $player_id, { videoId => $video_id, } ); 1642} 1643 1644sub can_handle { 1645 my($self, $browser, $url) = @_; 1646 1647 return $browser->content =~ /player = CanoeVideoStandalone\.create\(\);/i; 1648} 1649 16501; 1651} 1652##} blib/lib/FlashVideo/Site/Canoe.pm 1653BEGIN { $INC{'FlashVideo/Site/Cartoonnetwork.pm'}++; } 1654# Part of get-flash-videos. See get_flash_videos for copyright. 1655##{ blib/lib/FlashVideo/Site/Cartoonnetwork.pm 1656{ 1657package FlashVideo::Site::Cartoonnetwork; 1658 1659use strict; 1660BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 1661BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 1662use POSIX(); 1663 1664sub find_video { 1665 my ($self, $browser, $embed_url) = @_; 1666 1667 my $video_id; 1668 if ($browser->uri->as_string =~ /episodeID=([a-z0-9]*)/) { 1669 $video_id = $1; 1670 } 1671 1672 $browser->get("http://www.cartoonnetwork.com/cnvideosvc2/svc/episodeSearch/getEpisodesByIDs?ids=$video_id"); 1673 my $xml = from_xml($browser); 1674 my $episodes = $xml->{episode}; 1675 my $episode = ref $episodes eq 'ARRAY' ? 1676 (grep { $_->{id} eq $video_id } @$episodes)[0] : 1677 $episodes; 1678 1679 my $title = $episode->{title}; 1680 1681 my @gmtime = gmtime; 1682 $gmtime[1] = 15 * int($gmtime[1] / 15); 1683 my $date = POSIX::strftime("%m%d%Y%H%M", @gmtime); 1684 1685 my $url; 1686 foreach my $key (keys (%{$episode->{segments}->{segment}})){ 1687 my $content_id = $key; 1688 $browser->post("http://www.cartoonnetwork.com/cnvideosvc2/svc/episodeservices/getVideoPlaylist", 1689 Content => "id=$content_id&r=$date" 1690 ); 1691 1692 if ($browser->content =~ /<ref href="([^"]*)" \/>/){ 1693 $url = $1; 1694 } 1695 } 1696 1697 return $url, title_to_filename($title); 1698} 1699 17001; 1701} 1702##} blib/lib/FlashVideo/Site/Cartoonnetwork.pm 1703BEGIN { $INC{'FlashVideo/Site/Cbs.pm'}++; } 1704# Part of get-flash-videos. See get_flash_videos for copyright. 1705##{ blib/lib/FlashVideo/Site/Cbs.pm 1706{ 1707package FlashVideo::Site::Cbs; 1708 1709use strict; 1710BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 1711BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 1712 1713sub find_video { 1714 my ($self, $browser, $embed_url) = @_; 1715 1716 my $pid; 1717 if ($browser->uri->as_string =~ /pid=([^&]*)/) { 1718 $pid = $1; 1719 } 1720 1721 $browser->get("http://release.theplatform.com/content.select?format=SMIL&Tracking=true&balance=true&MBR=true&pid=$pid"); 1722 1723 my $xml = from_xml($browser->content); 1724 1725 my $items = $xml->{body}->{switch}; 1726 my $item = ref $items eq 'ARRAY' ? 1727 (grep { $_->{video}->{src} =~ /^rtmp:\/\// } @$items)[0] : 1728 $items; 1729 1730 my $rtmpurl = $item->{video}->{src}; 1731 $rtmpurl =~ s/<break>.*//; 1732 my $title = $item->{ref}->{title}; 1733 1734 return { 1735 rtmp => $rtmpurl, 1736 flv => title_to_filename($title) 1737 }; 1738} 1739 17401; 1741} 1742##} blib/lib/FlashVideo/Site/Cbs.pm 1743BEGIN { $INC{'FlashVideo/Site/Cbsnews.pm'}++; } 1744# Part of get-flash-videos. See get_flash_videos for copyright. 1745BEGIN { $INC{'FlashVideo/Site/Cnet.pm'}++; } 1746# Part of get-flash-videos. See get_flash_videos for copyright. 1747##{ blib/lib/FlashVideo/Site/Cnet.pm 1748{ 1749package FlashVideo::Site::Cnet; 1750 1751use strict; 1752BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 1753BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 1754 1755my $cnet_api_base = "http://api.cnet.com"; 1756my $cnet_api_rest = $cnet_api_base . "/restApi/v1.0"; 1757my $cnet_api_video_search = $cnet_api_rest . "/videoSearch"; 1758 1759 1760sub find_video { 1761 my ($self, $browser, $embed_url) = @_; 1762 1763 my $video_id; 1764 1765 if($browser->content =~ /<param name="FlashVars" value="playerType=embedded&type=id&value=([0-9]+)" \/>/) { 1766 $video_id = $1; 1767 } elsif($browser->content =~ /assetId: '([0-9]+)',/) { 1768 $video_id = $1; 1769 } else { 1770 die "Could not find video ID; you may have to click the 'share' link on the flash player to get the permalink to the video."; 1771 } 1772 1773 return $self->get_video($browser, $video_id); 1774} 1775 1776sub get_video { 1777 my ($self, $browser, $video_id) = @_; 1778 1779 $browser->get($cnet_api_video_search . "?videoIds=" . $video_id . "&iod=videoMedia&players=RTMP"); 1780 1781 my $xml = from_xml($browser->content, NoAttr => 1); 1782 1783 my $video = $xml->{"Videos"}->{"Video"}; 1784 1785 my $medias = $video->{"VideoMedias"}->{"VideoMedia"}; 1786 1787 my $max = 0; 1788 foreach (@{$video->{VideoMedias}->{VideoMedia}}) { 1789 if(int($_->{Width}) * int($_->{Height}) > $max){ 1790 $max = int($_->{Width}) * int($_->{Height}); 1791 } 1792 } 1793 my $media = (grep { (int($_->{Width}) * int($_->{Height})) eq $max } @$medias)[0]; 1794 my $delivery_url = $media->{DeliveryUrl}; 1795 1796 my $title = $video->{FranchiseName} . ' - ' . $video->{Title}; 1797 1798 if($media->{Player} eq 'RTMP'){ 1799 return { 1800 rtmp => $delivery_url, 1801 flv => title_to_filename($title) 1802 }; 1803 } elsif($media->{Player} eq 'Download'){ 1804 return $delivery_url, title_to_filename($title) 1805 } 1806} 1807 18081; 1809 1810} 1811##} blib/lib/FlashVideo/Site/Cnet.pm 1812##{ blib/lib/FlashVideo/Site/Cbsnews.pm 1813{ 1814package FlashVideo::Site::Cbsnews; 1815 1816use strict; 1817BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 1818BEGIN { no strict 'refs'; } 1819BEGIN { FlashVideo::Site::Cnet->import(); } # (added by utils/combine-perl.pl) 1820use base 'FlashVideo::Site::Cnet'; 1821 1822sub find_video { 1823 my ($self, $browser, $embed_url) = @_; 1824 1825 my $video_id; 1826 if($browser->content =~ /CBSVideo\.setVideoId\(["']([0-9]+)["']\)/) { 1827 $video_id = $1; 1828 } else { 1829 die "Could not find video id. If this is a valid CBS News video, please file a bug report at http://code.google.com/p/get-flash-videos/issues"; 1830 } 1831 return $self->get_video($browser, $video_id); 1832} 1833 18341; 1835} 1836##} blib/lib/FlashVideo/Site/Cbsnews.pm 1837BEGIN { $INC{'FlashVideo/Site/Channel4.pm'}++; } 1838# Part of get-flash-videos. See get_flash_videos for copyright. 1839################################################# 1840# 1841# This file was automatically generated by utils/combine-perl.pl 1842# You should edit the original files, not this 1843# combined version. 1844# 1845# The original files are available at: 1846# http://github.com/monsieurvideo/get-flash-videos 1847# 1848################################################# 1849# Thanks to Nibor for his XBMC 4od plugin - this is largely a Perl port of 1850# it. 1851##{ blib/lib/FlashVideo/Site/Channel4.pm 1852{ 1853package FlashVideo::Site::Channel4; 1854 1855use strict; 1856 1857use Crypt::Blowfish_PP; 1858BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 1859BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *url_exists = \&FlashVideo::Utils::url_exists; *convert_sami_subtitles_to_srt = \&FlashVideo::Utils::convert_sami_subtitles_to_srt; *from_xml = \&FlashVideo::Utils::from_xml; } 1860use MIME::Base64; 1861 1862use constant TOKEN_DECRYPT_KEY => 'STINGMIMI'; 1863 1864sub find_video { 1865 my ($self, $browser, $embed_url, $prefs) = @_; 1866 1867 my $page_url = $browser->uri->as_string; 1868 1869 my $series_and_episode; 1870 if ($browser->content =~ /<meta\ property="og:image" 1871 \ content="\S+series-(\d+)\/episode-(\d+)/x) { 1872 $series_and_episode = sprintf "S%02dE%02d", $1, $2; 1873 } 1874 1875 my $swf_player; 1876 if ($browser->content =~ /fourodPlayerFile\s+=\s+\'(4od\S+\.swf)\'/i) { 1877 $swf_player = $1; 1878 } 1879 else { 1880 $swf_player = '4odplayer-11.21.2.swf'; 1881 } 1882 1883 my $asset_id; 1884 1885 if ($page_url =~ m'(?:4od/player/|4od[^\/]*#)(\d+)') { 1886 $asset_id = $1; 1887 } 1888 else { 1889 die "Can't get asset ID"; 1890 } 1891 1892 my $raw_xml = $browser->get("http://ais.channel4.com/asset/$asset_id"); 1893 1894 if (!$browser->success) { 1895 die "Couldn't get asset XML: " . $browser->status_line; 1896 } 1897 1898 my $xml = from_xml($raw_xml); 1899 1900 my $stream_url = $xml->{assetInfo}->{uriData}->{streamUri}; 1901 my $token = $xml->{assetInfo}->{uriData}->{token}; 1902 my $cdn = $xml->{assetInfo}->{uriData}->{cdn}; 1903 1904 my $decoded_token = decode_4od_token($token); 1905 1906 my $auth; 1907 1908 if ($cdn eq 'll') { 1909 my $ip = $xml->{assetInfo}->{uriData}->{ip}; 1910 my $e = $xml->{assetInfo}->{uriData}->{e}; 1911 1912 if (defined $ip) { 1913 $auth = sprintf "e=%s&ip=%s&h=%s", $e, $ip, $decoded_token; 1914 } 1915 else { 1916 $auth = sprintf "e=%s&h=%s", $e, $decoded_token; 1917 } 1918 } 1919 else { 1920 my $fingerprint = $xml->{assetInfo}->{uriData}->{fingerprint}; 1921 my $slist = $xml->{assetInfo}->{uriData}->{slist}; 1922 1923 $auth = sprintf "auth=%s&aifp=%s&slist=%s", 1924 $decoded_token, $fingerprint, $slist; 1925 } 1926 1927 my $title; 1928 my @title_components = grep defined, 1929 map { $xml->{assetInfo}->{$_} } 1930 qw(brandTitle episodeTitle); 1931 1932 if ($series_and_episode) { 1933 push @title_components, $series_and_episode; 1934 } 1935 1936 if (@title_components) { 1937 $title = join " - ", @title_components; 1938 } 1939 1940 my $filename = title_to_filename($title, "mp4"); 1941 1942 if ($prefs->subtitles) { 1943 if (my $subtitles_url = $xml->{assetInfo}->{subtitlesFileUri}) { 1944 $subtitles_url = "http://ais.channel4.com$subtitles_url"; 1945 1946 $browser->get($subtitles_url); 1947 1948 if (!$browser->success) { 1949 info "Couldn't download 4od subtitles: " . $browser->status_line; 1950 } 1951 1952 my $subtitles_file = title_to_filename($title, "srt"); 1953 convert_sami_subtitles_to_srt($browser->content, $subtitles_file); 1954 1955 info "Saved subtitles to $subtitles_file"; 1956 } 1957 else { 1958 debug("Subtitles requested for '$title' but none available."); 1959 } 1960 } 1961 1962 my $rtmp_url; 1963 1964 if ($stream_url =~ /(.*?)mp4:/) { 1965 $rtmp_url = $1; 1966 } 1967 1968 $rtmp_url =~ s{\.com/}{.com:1935/}; 1969 $rtmp_url .= "?ovpfv=1.1&$auth"; 1970 1971 my $app; 1972 if ($stream_url =~ /.com\/(.*?)mp4:/) { 1973 $app = $1; 1974 $app .= "?ovpfv=1.1&$auth"; 1975 } 1976 1977 my $playpath; 1978 if ($stream_url =~ /.*?(mp4:.*)/) { 1979 $playpath = $1; 1980 $playpath .= "?$auth"; 1981 } 1982 1983 my $swf_player_url = url_exists($browser, "http://www.channel4.com/static/programmes/asset/flash/swf/$swf_player"); 1984 1985 if (!$swf_player_url) { 1986 die "swf url not found"; 1987 } 1988 1989 return { 1990 flv => $filename, 1991 rtmp => $rtmp_url, 1992 flashVer => '"WIN 11,0,1,152"', 1993 swfVfy => "$swf_player_url", 1994 conn => 'Z:', 1995 playpath => $playpath, 1996 pageUrl => $page_url, 1997 app => $app, 1998 }; 1999} 2000 2001sub decode_4od_token { 2002 my $encrypted_token = shift; 2003 2004 $encrypted_token = decode_base64($encrypted_token); 2005 2006 my $blowfish = Crypt::Blowfish_PP->new(TOKEN_DECRYPT_KEY); 2007 2008 my $decrypted_token = ''; 2009 2010 my $position = 0; 2011 2012 while ( $position < length $encrypted_token) { 2013 $decrypted_token .= $blowfish->decrypt(substr $encrypted_token, $position, 8); 2014 $position += 8; 2015 } 2016 2017 my $npad = unpack("c", substr($decrypted_token, -1)); 2018 if ($npad > 0 && $npad < 9) { 2019 $decrypted_token = substr($decrypted_token, 0, length($decrypted_token)-$npad); 2020 } 2021 return $decrypted_token; 2022} 2023 20241; 2025} 2026##} blib/lib/FlashVideo/Site/Channel4.pm 2027BEGIN { $INC{'FlashVideo/Site/Channel5.pm'}++; } 2028# Part of get-flash-videos. See get_flash_videos for copyright. 2029##{ blib/lib/FlashVideo/Site/Channel5.pm 2030{ 2031package FlashVideo::Site::Channel5; 2032 2033use strict; 2034BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 2035BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 2036use MIME::Base64; 2037 2038my $encode_rates = { 2039 "low" => 480, 2040 "medium" => 800, 2041 "medium2" => 1200, 2042 "high" => 1500 }; 2043 2044sub find_video { 2045 my ($self, $browser, $embed_url, $prefs) = @_; 2046 2047 my $metadata = { }; 2048 my ($video_id, $player_id); 2049 2050 $player_id = ($browser->content =~ /playerId["'\] ]*[:=]["' ]*(\d+)/i)[0]; 2051 $metadata->{videoplayer} = ($browser->content =~ /videoPlayer=ref:(C\d+)/i)[0]; 2052 $metadata->{publisherId} = ($browser->content =~ /publisherID=(\d+)/i)[0]; 2053 2054 $player_id ||= ($browser->content =~ /<param name=["']?playerID["']? value=["'](\d+) ?["']/i)[0]; 2055 $metadata->{videoplayer} ||= ($browser->content =~ /param name=["']?\@videoPlayer["']? value=["']?(\d+)["']?/i)[0]; 2056 $metadata->{publisherId} ||= ($browser->content =~ /param name=["']?publisherID["']? value=["']?(\d+)["']?/i)[0]; 2057 2058 $player_id ||= ($browser->content =~ /flashVars.*playerID=(\d+)/i)[0]; 2059 2060 if(!$player_id && $browser->content =~ /brightcove.player.create\(['"]?(\d+)['"]?,\s*['"]?(\d+)/) { 2061 $player_id = $2; 2062 } 2063 2064 $metadata->{sessionId} = ($browser->cookie_jar->as_string =~ /session=([0-9a-f]*);/)[0]; 2065 2066 for my $url($browser->uri->as_string, $embed_url) { 2067 2068 if($url =~ /(?:playerID|bcpid)=?(\d+)/i) { 2069 $player_id ||= $1; 2070 } 2071 } 2072 2073 debug "Extracted playerId: $player_id, sessionId: $metadata->{sessionId} videoplayer: $metadata->{videoplayer} publisherId: $metadata->{publisherId} " 2074 if $player_id or $video_id; 2075 2076 die "Unable to extract Brightcove IDs from page" unless $player_id; 2077 2078 return $self->amfgateway($browser, $player_id, $metadata, $prefs); 2079} 2080 2081sub amfgateway { 2082 my($self, $browser, $player_id, $metadata, $prefs) = @_; 2083 2084 my $has_amf_packet = eval { require Data::AMF::Packet }; 2085 if (!$has_amf_packet) { 2086 die "Must have Data::AMF::Packet installed to download Brightcove videos"; 2087 } 2088 2089 my $page_url = $browser->uri; 2090 my $base_url = "" . $page_url; 2091 2092 2093 my $amf0_formatter = Data::AMF::Formatter->new(version =>0); 2094 my $amf3_formatter = Data::AMF::Formatter->new(version =>3); 2095 my @amf_pkt; 2096 2097 2098 $amf_pkt[0] = decode_base64(<<EOF1); 2099AAMAAAABAEZjb20uYnJpZ2h0Y292ZS5leHBlcmllbmNlLkV4cGVyaWVuY2VSdW50aW1lRmFjYWRl 2100LmdldERhdGFGb3JFeHBlcmllbmNlAAIvMQAA 2101EOF1 2102 2103 $amf_pkt[2] = decode_base64(<<EOF2); 2104CgAAAAI= 2105EOF2 2106 2107 $amf_pkt[3] = $amf0_formatter->format($metadata->{sessionId}); 2108 2109 $amf_pkt[4] = decode_base64(<<EOF3); 2110EQpjY2NvbS5icmlnaHRjb3ZlLmV4cGVyaWVuY2UuVmlld2VyRXhwZXJpZW5jZVJlcXVlc3QhY29u 2111dGVudE92ZXJyaWRlcwdVUkwZZXhwZXJpZW5jZUlkEVRUTFRva2VuE3BsYXllcktleRlkZWxpdmVy 2112eVR5cGUJAwEKgQNTY29tLmJyaWdodGNvdmUuZXhwZXJpZW5jZS5Db250ZW50T3ZlcnJpZGUXY29u 2113dGVudFR5cGUTY29udGVudElkGWNvbnRlbnRSZWZJZBtmZWF0dXJlZFJlZklkG2NvbnRlbnRSZWZJ 2114ZHMVZmVhdHVyZWRJZBVjb250ZW50SWRzDXRhcmdldAQABX/////gAAAA 2115EOF3 2116 2117 $amf_pkt[5] = $amf3_formatter->format($metadata->{videoplayer}); 2118 2119 $amf_pkt[6] = decode_base64(<<EOF4); 2120AQEFf////+AAAAABBhd2aWRlb1BsYXllcg== 2121EOF4 2122 2123 $amf_pkt[7] = $amf3_formatter->format($base_url); 2124 2125 $amf_pkt[8] = decode_base64(<<EOF5); 2126BUI4gZvSwQAABgEGAQV/////4AAAAA== 2127EOF5 2128 my $experianceid = $amf3_formatter->format($player_id); 2129 $amf_pkt[8] = $experianceid . substr($amf_pkt[8], 7); 2130 2131 2132 $amf_pkt[1] = pack('n', length(join('',@amf_pkt[2..8]))); 2133 2134 my $data = join('',@amf_pkt[0..8]); 2135 2136 2137 2138 2139 2140 $browser->post( 2141 "http://c.brightcove.com/services/messagebroker/amf?playerid=$player_id", 2142 Content_Type => "application/x-amf", 2143 Content => $data 2144 ); 2145 2146 die "Failed to post to Brightcove AMF gateway" 2147 unless $browser->response->is_success; 2148 2149 my $packet = Data::AMF::Packet->deserialize($browser->content); 2150 2151 if($self->debug) { 2152 require Data::Dumper; 2153 debug Data::Dumper::Dumper($packet); 2154 } 2155 2156 if ( ref $packet->messages->[0]->{value}->{programmedContent}->{videoPlayer}->{mediaDTO}->{renditions} ne 'ARRAY') { 2157 die "Unexpected data from AMF gateway"; 2158 } 2159 2160 my @found; 2161 for (@{$packet->messages->[0]->{value}->{programmedContent}->{videoPlayer}->{mediaDTO}->{renditions}}) { 2162 if ($_->{defaultURL}) { 2163 push @found, $_; 2164 } 2165 } 2166 2167 my $mediaId = $packet->messages->[0]->{value}->{programmedContent}->{videoPlayer}->{mediaId}; 2168 my $seasonnumber = $packet->messages->[0]->{value}->{programmedContent}->{videoPlayer}->{mediaDTO}->{customFields}->{seasonnumber}; 2169 my $episodenumber = $packet->messages->[0]->{value}->{programmedContent}->{videoPlayer}->{mediaDTO}->{customFields}->{episodenumber}; 2170 my $show = ($page_url =~ m!/shows/([^/]+)/!i)[0]; 2171 my $episode = ($page_url =~ m!/episodes/([^/]+)!i)[0]; 2172 my $filehead = $show . "_Series" . $seasonnumber; 2173 if ( $show ne $episode ) { 2174 $filehead = $filehead . "_Episode" . $episodenumber . "_" . $episode; 2175 } 2176 my $encode_rate = $encode_rates->{$prefs->{quality}}; 2177 if (! defined $encode_rate ) { 2178 $encode_rate = $prefs->{quality}; 2179 } 2180 2181 my @rtmpdump_commands; 2182 2183 for my $d (@found) { 2184 2185 my $rate = ($d->{defaultURL} =~ /H264-(\d+)-16x9/i)[0]; 2186 next if $encode_rate != $rate; 2187 my $host = ($d->{defaultURL} =~ m!rtmpe://(.*?)/!)[0]; 2188 my $file = ($d->{defaultURL} =~ /^[^&]+&(.*)$/)[0]; 2189 my $app = ($d->{defaultURL} =~ m!//.*?/(.*?)/&!)[0]; 2190 my $filename = $filehead . "_" . $rate; 2191 2192 $app .= "?videoId=$mediaId&lineUpId=&pubId=$metadata->{publisherId}&playerId=$player_id&affiliateId="; 2193 2194 my $args = { 2195 app => $app, 2196 pageUrl => $page_url, 2197 swfVfy => "http://admin.brightcove.com/viewer/us1.24.04.08.2011-01-14072625/connection/ExternalConnection_2.swf", 2198 tcUrl => "rtmpe://$host:1935/$app", 2199 rtmp => "$d->{defaultURL}", 2200 playpath => $file, 2201 flv => "$filename.flv", 2202 }; 2203 2204 if ($d->{publisherName} and $d->{displayName}) { 2205 $args->{flv} = title_to_filename("$d->{publisherName} - $d->{displayName}"); 2206 } 2207 2208 2209 push @rtmpdump_commands, $args; 2210 } 2211 2212 if (@rtmpdump_commands > 1) { 2213 return \@rtmpdump_commands; 2214 } 2215 else { 2216 return $rtmpdump_commands[-1]; 2217 } 2218} 2219 2220sub can_handle { 2221 my($self, $browser, $url) = @_; 2222 2223 return 1 if $url && URI->new($url)->host =~ /\.channel5\.com$/; 2224 2225 return $browser->content =~ /(playerI[dD]|brightcove.player.create)/ 2226 && $browser->content =~ /brightcove/i; 2227} 2228 22291; 2230} 2231##} blib/lib/FlashVideo/Site/Channel5.pm 2232BEGIN { $INC{'FlashVideo/Site/Collegehumor.pm'}++; } 2233# Part of get-flash-videos. See get_flash_videos for copyright. 2234##{ blib/lib/FlashVideo/Site/Collegehumor.pm 2235{ 2236package FlashVideo::Site::Collegehumor; 2237 2238use strict; 2239BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 2240BEGIN { no strict 'refs'; *extract_title = \&FlashVideo::Utils::extract_title; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 2241 2242sub find_video { 2243 my ($self, $browser, $embed_url) = @_; 2244 my $base = "http://www.collegehumor.com/moogaloop"; 2245 2246 my $id; 2247 if($browser->content =~ /video:(\d+)/) { 2248 $id = $1; 2249 } elsif($embed_url =~ m![/:](\d+)!) { 2250 $id = $1; 2251 } 2252 die "No ID found\n" unless $id; 2253 2254 $browser->get("$base/video:$id"); 2255 2256 my $xml = from_xml($browser); 2257 2258 my $title = $xml->{video}->{caption}; 2259 $title = extract_title($browser) if ref $title; 2260 2261 return $xml->{video}->{file}, title_to_filename($title); 2262} 2263 22641; 2265} 2266##} blib/lib/FlashVideo/Site/Collegehumor.pm 2267BEGIN { $INC{'FlashVideo/Site/Ctv.pm'}++; } 2268# Part of get-flash-videos. See get_flash_videos for copyright. 2269################################################# 2270# 2271# This file was automatically generated by utils/combine-perl.pl 2272# You should edit the original files, not this 2273# combined version. 2274# 2275# The original files are available at: 2276# http://github.com/monsieurvideo/get-flash-videos 2277# 2278################################################# 2279# 2280# Handler module for CTV Canadian broadcaster 2281# - Requires RTMPDUMP 2282# - Expects an URL in the form of: http://watch.ctv.ca/ $show / $season / $episode / 2283# - Each show is split in clips intersected with commercial breaks, so there will be several calls to RTMPDUMP 2284# - Streams are restricted to Canadian ISPs 2285# 2286# Stavr0 2287# 2288##{ blib/lib/FlashVideo/Site/Ctv.pm 2289{ 2290package FlashVideo::Site::Ctv; 2291 2292use strict; 2293BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 2294BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; } 2295 2296sub find_video { 2297 my($self, $browser, $page_url) = @_; 2298 2299 my $entityid = ($browser->content =~ /<meta name="EntityId" content="(\d+)"/i)[0]; 2300 debug "EntityID = " . $entityid; 2301 2302 die "Couldn't find EntityId in <meta> tags" unless $entityid; 2303 2304 $browser->get("http://watch.ctv.ca/AJAX/ClipLookup.aspx?callfunction=Playlist.GetInstance.AddEpisodeClipsAfter&episodeid=$entityid&maxResults=99"); 2305 die "Couldn't download playlist: " . $browser->response->status_line 2306 if !$browser->success; 2307 2308 my $plist = $browser->content; 2309 my @found; 2310 while ($plist =~ /(videoArray\.push[^}]+} \) \);)/gi) { 2311 push @found, ($1 =~ /Format\:'FLV', ClipId\:'(\d+)'/i); 2312 } 2313 2314 my @rtmpdump_commands; 2315 2316 for my $clipid (@found) { 2317 debug "clipID = $clipid"; 2318 my $rand = int rand 999999; 2319 $browser->get("http://esi.ctv.ca/datafeed/flv/urlgenjs.aspx?vid=$clipid&timeZone=-4&random=$rand"); 2320 2321 if ($browser->content =~ /(rtmpe\:\/\/[^\']+)/) { 2322 my $rtmp = $1; 2323 my $tcurl = ($rtmp =~ /\?(auth=.+)/ )[0]; 2324 my $filename = ($rtmp =~ /([^\?\/]+)\?/ )[0]; 2325 $filename =~ s/\.mp4/\.flv/; 2326 2327 debug "$rtmp, $tcurl, $filename"; 2328 2329 push @rtmpdump_commands, { 2330 app => "ondemand?$tcurl", 2331 pageUrl => $page_url, 2332 swfUrl => "http://watch.ctv.ca/Flash/player.swf?themeURL=http://watch.ctv.ca/themes/CTV/player/theme.aspx", 2333 tcUrl => "rtmpe://cp45924.edgefcs.net/ondemand?$tcurl", 2334 auth => ($rtmp =~ /auth=([^&]+)/)[0], 2335 rtmp => $rtmp, 2336 playpath => "mp4:" . ($rtmp =~ /ondemand\/(.+)/)[0], 2337 flv => $filename, 2338 }; 2339 } elsif($browser->content =~ /geoblock/) { 2340 die "CTV returned geoblock (content not available in your country)\n"; 2341 } 2342 } 2343 2344 return \@rtmpdump_commands; 2345} 2346 2347sub can_handle { 2348 my($self, $browser, $url) = @_; 2349 return $url =~ m{watch\.ctv\.ca}; 2350} 2351 23521; 2353} 2354##} blib/lib/FlashVideo/Site/Ctv.pm 2355BEGIN { $INC{'FlashVideo/Site/Dailymotion.pm'}++; } 2356# Part of get-flash-videos. See get_flash_videos for copyright. 2357##{ blib/lib/FlashVideo/Site/Dailymotion.pm 2358{ 2359package FlashVideo::Site::Dailymotion; 2360 2361use strict; 2362BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 2363BEGIN { no strict 'refs'; *error = \&FlashVideo::Utils::error; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *json_unescape = \&FlashVideo::Utils::json_unescape; } 2364use URI::Escape; 2365 2366sub find_video { 2367 my ($self, $browser, $embed_url, $prefs) = @_; 2368 2369 if ($browser->content =~ /content.is.not.available.for.your.country/i) { 2370 error "Can't (yet) download this video because it's not available " . 2371 "in your area"; 2372 exit 1; 2373 } 2374 2375 $browser->allow_redirects; 2376 2377 $browser->content =~ /<h1[^>]*>(.*?)<\//; 2378 my $filename = title_to_filename($1); 2379 2380 my $video; 2381 if ($browser->content =~ /"video", "([^"]+)/) { 2382 $video = uri_unescape($1); 2383 } 2384 if (!$video && $browser->content =~ /"sequence", *"([^"]+)/) { 2385 my $data = json_unescape(uri_unescape($1)); 2386 my ($low) = $data =~ /"sdURL" *: *"([^"]+)"/i; 2387 my ($high) = $data =~ /"hqURL" *: *"([^"]+)"/i; 2388 if($data =~ /"videoTitle" *: *"([^"]+)"/i){ 2389 my $title = uri_unescape($1); 2390 $title =~ s/\+/ /g; 2391 $filename = title_to_filename($title); 2392 } 2393 if( $prefs->{quality} == 'high' && $high ){ $video = $high; } 2394 elsif( $low ){ $video = $low; } 2395 } 2396 if(!$video) { 2397 if ($embed_url !~ m!/swf/!) { 2398 $browser->uri =~ m!video(?:%2F|/)([^_]+)!; 2399 $embed_url = "http://www.dailymotion.com/swf/$1"; 2400 } 2401 2402 $browser->get($embed_url); 2403 2404 die "Must have Compress::Zlib for embedded Dailymotion videos\n" 2405 unless eval { require Compress::Zlib; }; 2406 2407 my $data = Compress::Zlib::uncompress(substr $browser->content, 8); 2408 2409 $data =~ /\{\{video\}\}\{\{(.*?)\}\}/; 2410 $video = $1; 2411 2412 if($data =~ /videotitle=([^&]+)/) { 2413 $filename = title_to_filename(uri_unescape($1)); 2414 } 2415 } 2416 2417 if(!$video) { 2418 my($package, $possible_url) = FlashVideo::URLFinder->find_package($browser->uri, $browser); 2419 2420 if($package ne __PACKAGE__) { 2421 return $package->find_video($browser, $possible_url, $prefs); 2422 } 2423 } 2424 2425 die "Couldn't find video parameter." unless $video; 2426 2427 my @streams; 2428 for(split /\|\|/, $video) { 2429 my($path, $type) = split /@@/; 2430 2431 my($width, $height) = $path =~ /(\d+)x(\d+)/; 2432 2433 push @streams, { 2434 width => $width, 2435 height => $height, 2436 url => URI->new_abs($path, $browser->uri)->as_string 2437 }; 2438 } 2439 2440 my $url = (sort { $b->{width} <=> $a->{width} } @streams)[0]->{url}; 2441 2442 return $url, $filename; 2443} 2444 24451; 2446} 2447##} blib/lib/FlashVideo/Site/Dailymotion.pm 2448BEGIN { $INC{'FlashVideo/Site/Daum.pm'}++; } 2449# Part of get-flash-videos. See get_flash_videos for copyright. 2450##{ blib/lib/FlashVideo/Site/Daum.pm 2451{ 2452package FlashVideo::Site::Daum; 2453 2454use strict; 2455BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 2456BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 2457use HTML::Entities qw(decode_entities); 2458 2459sub find_video { 2460 my ($self, $browser) = @_; 2461 2462 my $video_id = get_video_id($browser); 2463 debug "Video ID: $video_id"; 2464 2465 my $video_title = get_video_title($browser, $video_id); 2466 debug "Video title: $video_title"; 2467 2468 my $video_url = get_video_url($browser, $video_id); 2469 debug "Video URL: $video_url"; 2470 2471 return $video_url, title_to_filename($video_title); 2472} 2473 2474 2475sub is_valid_video_id { 2476 my ($video_id) = @_; 2477 2478 return if !defined $video_id; 2479 2480 return if length $video_id != 12; 2481 2482 return if $video_id !~ /\$$/xms; 2483 2484 return 1; 2485} 2486 2487sub get_video_id { 2488 my ($browser) = @_; 2489 2490 my $singer_url 2491 = quotemeta 'http://media.daum.net/entertain/showcase/singer/'; 2492 my $singer_url_pattern = qr{^ $singer_url .* [#] (\d+) $}xmsi; 2493 if ( $browser->uri()->as_string() =~ $singer_url_pattern ) { 2494 my $id = $1; 2495 return get_video_id_for_singer($browser, $id); 2496 } 2497 2498 if ( $browser->uri()->as_string() =~ /[#] clipid = (\d+)/xmsi ) { 2499 my $url = 'http://tvpot.daum.net/clip/ClipView.do?clipid=' . $1; 2500 $browser->get($url); 2501 if ( !$browser->success() ) { 2502 die "Cannot fetch the document identified by the given URL: $url\n"; 2503 } 2504 } 2505 2506 my $document = $browser->content(); 2507 2508 my $flv_player_url = quotemeta 'http://flvs.daum.net/flvPlayer.swf'; 2509 my $video_id_pattern_1 = qr{['"] $flv_player_url [?] vid = ([^'"&]+)}xmsi; 2510 2511 my $function_name = quotemeta 'Story.UI.PlayerManager.createViewer'; 2512 my $video_id_pattern_2 = qr{$function_name [(] '(.+?)' [)]}xms; 2513 2514 if ( $document !~ $video_id_pattern_1 2515 && $document !~ $video_id_pattern_2 ) 2516 { 2517 die "Cannot find video ID from the document.\n"; 2518 } 2519 my $video_id = $1; 2520 2521 $video_id =~ s/\s+//xmsg; 2522 2523 die "Invalid video ID: $video_id\n" if !is_valid_video_id($video_id); 2524 2525 return $video_id; 2526} 2527 2528sub get_video_id_for_singer { 2529 my ($browser, $id) = @_; 2530 2531 my $document = $browser->content(); 2532 2533 my $video_id_pattern = qr{id:'$id', \s* vid:'(.+?)'}xms; 2534 if ( $document !~ $video_id_pattern ) { 2535 die "Cannot find video ID from the document.\n"; 2536 } 2537 my $video_id = $1; 2538 2539 $video_id =~ s/\s+//xmsg; 2540 2541 die "Invalid video ID: $video_id\n" if !is_valid_video_id($video_id); 2542 2543 return $video_id; 2544} 2545 2546sub get_video_title { 2547 my ($browser, $video_id) = @_; 2548 2549 my $query_url = "http://tvpot.daum.net/clip/ClipInfoXml.do?vid=$video_id"; 2550 2551 $browser->get($query_url); 2552 if ( !$browser->success() ) { 2553 die "Cannot fetch the document identified by the given URL: $query_url\n"; 2554 } 2555 2556 my $document = $browser->content(); 2557 2558 my $video_title_pattern 2559 = qr{<TITLE> <!\[CDATA \[ (.+?) \] \]> </TITLE>}xmsi; 2560 if ( $document !~ $video_title_pattern ) { 2561 die "Cannot find video title from the document.\n"; 2562 } 2563 my $video_title = $1; 2564 2565 $video_title = decode_entities($video_title); 2566 2567 return $video_title; 2568} 2569 2570sub get_video_url { 2571 my ($browser, $video_id) = @_; 2572 2573 my $query_url 2574 = 'http://stream.tvpot.daum.net/fms/pos_query2.php' 2575 . '?service_id=1001&protocol=http&out_type=xml' 2576 . "&s_idx=$video_id"; 2577 2578 $browser->get($query_url); 2579 if ( !$browser->success() ) { 2580 die "Cannot fetch the document identified by the given URL: $query_url\n"; 2581 } 2582 2583 my $document = $browser->content(); 2584 2585 my $video_url_pattern = qr{movieURL = "(.+?)"}xmsi; 2586 if ( $document !~ $video_url_pattern ) { 2587 die "Cannot find video URL from the document.\n"; 2588 } 2589 my $video_url = $1; 2590 2591 return $video_url; 2592} 2593 25941; 2595} 2596##} blib/lib/FlashVideo/Site/Daum.pm 2597BEGIN { $INC{'FlashVideo/Site/Divxstage.pm'}++; } 2598# Part of get-flash-videos. See get_flash_videos for copyright. 2599##{ blib/lib/FlashVideo/Site/Divxstage.pm 2600{ 2601package FlashVideo::Site::Divxstage; 2602 2603use strict; 2604BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 2605BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *extract_title = \&FlashVideo::Utils::extract_title; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *get_video_filename = \&FlashVideo::Utils::get_video_filename; } 2606use URI; 2607 2608sub find_video { 2609 my ($self, $browser, $embed_url) = @_; 2610 2611 my ($file) = ($browser->content =~ /flashvars.file\s*=\s*"([a-f0-9]+)"/); 2612 my ($filekey) = ($browser->content =~ /flashvars.filekey\s*=\s*"([.\-a-f0-9]+)"/); 2613 2614 my ($filename) = title_to_filename(extract_title($browser)); 2615 $filename =~ s/_-_DivxStage//i; 2616 2617 my %query_params = ( 2618 'codes'=>'1', 2619 'file'=>$file, 2620 'key'=>$filekey, 2621 'pass'=>'undefined', 2622 'user'=>'undefined',); 2623 2624 info "Sending query to DivxStage Player API."; 2625 2626 my $uri = URI->new( "http://www.divxstage.eu/api/player.api.php" ); 2627 $uri->query_form(%query_params); 2628 2629 my $contents = $browser->get($uri)->content; 2630 my ($url) = ($contents =~ /url=(.*?)&/); 2631 2632 die "Couldn't find video URL from the player API." unless $url; 2633 2634 info "Got the real video URL: ".$url; 2635 $filename ||= ($contents =~ /title=(.*?)&/)[0]; #probably the most reliable source of title 2636 $filename ||= get_video_filename(); 2637 2638 return $url, $filename; 2639} 2640 26411; 2642} 2643##} blib/lib/FlashVideo/Site/Divxstage.pm 2644BEGIN { $INC{'FlashVideo/Site/Ehow.pm'}++; } 2645# Part of get-flash-videos. See get_flash_videos for copyright. 2646##{ blib/lib/FlashVideo/Site/Ehow.pm 2647{ 2648package FlashVideo::Site::Ehow; 2649 2650use strict; 2651BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 2652BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 2653use URI::Escape; 2654 2655sub find_video { 2656 my ($self, $browser) = @_; 2657 2658 my $uri; 2659 if ($browser->content =~ /source=(.*?)[ &]/) { 2660 $uri = $1; 2661 } 2662 else { 2663 die "Couldn't extract video location from page"; 2664 } 2665 2666 my $title; 2667 if ($browser->content =~ /<h1[^>]* class="[^"]*articleTitle[^"]*"[^>]*>(.*?)<\/h1>/x) { 2668 $title = $1; 2669 } 2670 2671 if($uri =~ /^http:/) { 2672 return $uri, title_to_filename($title); 2673 } 2674 elsif($uri =~ /http:%3A/) { 2675 $uri = uri_unescape($1); 2676 if ($browser->content =~ /<a[^>]*>(.*?)<\/a>/) { 2677 $title = $1; 2678 } 2679 return $uri, title_to_filename($title); 2680 } 2681 else { 2682 die "Couldn't extract Flash video URL from embed page"; 2683 } 2684} 2685 2686 26871; 2688} 2689##} blib/lib/FlashVideo/Site/Ehow.pm 2690BEGIN { $INC{'FlashVideo/Site/Escapistmagazine.pm'}++; } 2691# Part of get-flash-videos. See get_flash_videos for copyright. 2692BEGIN { $INC{'FlashVideo/JSON.pm'}++; } 2693##{ blib/lib/FlashVideo/JSON.pm 2694{ 2695package FlashVideo::JSON; 2696 2697use strict; 2698use Exporter;use base 'Exporter'; 2699our @EXPORT = qw(from_json); 2700 2701my $number = qr{(?:-?\b(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b)}; 2702my $oneChar = qr{(?:[^\0-\x08\x0a-\x1f\"\\]|\\(?:["/\\bfnrt]|u[0-9A-Fa-f]{4}))}; 2703my $string = qr{(?:"$oneChar*")}; 2704my $jsonToken = qr{(?:false|true|null|[\{\}\[\]]|$number|$string)}; 2705my $escapeSequence = qr{\\(?:([^u])|u(.{4}))}; 2706 2707my %escapes = ( 2708 '\\' => '\\', 2709 '"' => '"', 2710 '/' => '/', 2711 'b' => "\b", 2712 'f' => "\f", 2713 'n' => "\xA", 2714 'r' => "\xD", 2715 't' => "\t" 2716); 2717 2718sub from_json { 2719 my($in) = @_; 2720 2721 my @tokens = $in =~ /$jsonToken/go; 2722 my $result = $tokens[0] eq '{' ? {} : []; 2723 shift @tokens if $tokens[0] =~ /^[\[\{]/; 2724 2725 my $key; # key to use for next value 2726 my @stack = $result; 2727 for my $t(@tokens) { 2728 my $ft = substr $t, 0, 1; 2729 my $cont = $stack[0]; 2730 2731 if($ft eq '"') { 2732 my $s = substr $t, 1, length($t) - 2; 2733 $s =~ s/$escapeSequence/$1 ? $escapes{$1} : chr hex $2/geo; 2734 if(!defined $key) { 2735 if(ref $cont eq 'ARRAY') { 2736 $cont->[@$cont] = $s; 2737 } else { 2738 $key = $s; 2739 next; # need to save $key 2740 } 2741 } else { 2742 $cont->{$key} = $s; 2743 } 2744 } elsif($ft eq '[' || $ft eq '{') { 2745 unshift @stack, 2746 (ref $cont eq 'ARRAY' ? $cont->[@$cont] : $cont->{$key}) = $ft eq '[' ? [] : {}; 2747 } elsif($ft eq ']' || $ft eq '}') { 2748 shift @stack; 2749 } else { 2750 (ref $cont eq 'ARRAY' ? $cont->[@$cont] : $cont->{$key}) = 2751 $ft eq 'f' ? 0 # false 2752 : $ft eq 'n' ? undef # null 2753 : $ft eq 't' ? 1 # true 2754 : $t; # sign or digit 2755 } 2756 undef $key; 2757 } 2758 2759 return $result; 2760} 2761 27621; 2763} 2764##} blib/lib/FlashVideo/JSON.pm 2765##{ blib/lib/FlashVideo/Site/Escapistmagazine.pm 2766{ 2767package FlashVideo::Site::Escapistmagazine; 2768 2769use strict; 2770BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 2771BEGIN { no strict 'refs'; *extract_title = \&FlashVideo::Utils::extract_title; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 2772BEGIN { FlashVideo::JSON->import(); } # (added by utils/combine-perl.pl) 2773BEGIN { no strict 'refs'; *from_json = \&FlashVideo::JSON::from_json; } 2774 2775sub find_video { 2776 my ($self, $browser, $embed_url) = @_; 2777 my $title; 2778 my $url; 2779 if ($browser->content =~ /<div[^>]*class=['"]name['"]>(.*?)<\/div>/) { 2780 $title = $1; 2781 $title =~ s/<[^>]*>//g; 2782 } else { 2783 $title = extract_title($browser); 2784 } 2785 2786 my $config_url; 2787 if ($browser->content =~ /<param name=['"]flashvars['"] value=['"]config=([^'"]*)['"]/) { 2788 $config_url = $1; 2789 } else { 2790 die "No Video Info URL Found\n"; 2791 } 2792 2793 $browser->add_header(Accept => '*/*'); 2794 $browser->get("$config_url"); 2795 my $replaced = $browser->content; 2796 $replaced =~ s/'/"/g; 2797 my $json = from_json($replaced); 2798 2799 my $item; 2800 for $item (@{$json->{playlist}}) { 2801 if ($item->{eventCategory} eq "Video") { 2802 $url = $item->{url}; 2803 } 2804 } 2805 return $url, title_to_filename($title); 2806} 2807} 2808##} blib/lib/FlashVideo/Site/Escapistmagazine.pm 2809BEGIN { $INC{'FlashVideo/Site/Expertvillage.pm'}++; } 2810# Part of get-flash-videos. See get_flash_videos for copyright. 2811##{ blib/lib/FlashVideo/Site/Expertvillage.pm 2812{ 2813package FlashVideo::Site::Expertvillage; 2814 2815use strict; 2816BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 2817BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *error = \&FlashVideo::Utils::error; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 2818use URI::Escape; 2819 2820sub find_video { 2821 my ($self, $browser) = @_; 2822 2823 my($fn) = $browser->content =~ /SWFObject\(['"][^'"]+flv=([^'"]+)/; 2824 my $embedvars = uri_unescape($browser->content =~ /embedvars['"],\s*['"]([^'"]+)/); 2825 die "Unable to find video info" unless $fn and $embedvars; 2826 2827 my($title) = $browser->content =~ m{<h1[^>]*>(.*)</h1>}s; 2828 my $filename = title_to_filename($title); 2829 2830 $browser->get("$embedvars?fn=$fn"); 2831 die "Unable to get emebdding info" if $browser->response->is_error; 2832 2833 my $url = uri_unescape($browser->content =~ /source=([^&]+)/); 2834 die "Unable to find video URL" unless $url; 2835 2836 return $url, $filename; 2837} 2838 28391; 2840} 2841##} blib/lib/FlashVideo/Site/Expertvillage.pm 2842BEGIN { $INC{'FlashVideo/Site/Filebox.pm'}++; } 2843# Part of get-flash-videos. See get_flash_videos for copyright. 2844################################################# 2845# 2846# This file was automatically generated by utils/combine-perl.pl 2847# You should edit the original files, not this 2848# combined version. 2849# 2850# The original files are available at: 2851# http://github.com/monsieurvideo/get-flash-videos 2852# 2853################################################# 2854 2855##{ blib/lib/FlashVideo/Site/Filebox.pm 2856{ 2857package FlashVideo::Site::Filebox; 2858 2859use strict; 2860BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 2861BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; } 2862 2863sub find_video { 2864 my ($self, $browser, $embed_url) = @_; 2865 2866 my $pause = 5; #if we don't pause, we don't get the proper video page 2867 info 'Pausing for '.$pause.' seconds (or the server won\'t respond)...'; 2868 sleep($pause); 2869 2870 my $btn_id = 'btn_download'; #the ID of the button to submit the form 2871 for my $form ($browser->forms) { 2872 if ($form->find_input('#'.$btn_id)){ 2873 info 'Submitting form to get real video page.'; 2874 $browser->request($form->click('#'.$btn_id)); #submit to get the real page 2875 } 2876 } 2877 2878 my ($filename) = ($browser->content =~ /product_file_name=(.*?)[&'"]/); 2879 my ($url) = ($browser->content =~ /product_download_url=(.*?)[&'"]/); 2880 2881 return $url, $filename; 2882} 2883 28841; 2885} 2886##} blib/lib/FlashVideo/Site/Filebox.pm 2887BEGIN { $INC{'FlashVideo/Site/Flickr.pm'}++; } 2888# Part of get-flash-videos. See get_flash_videos for copyright. 2889##{ blib/lib/FlashVideo/Site/Flickr.pm 2890{ 2891package FlashVideo::Site::Flickr; 2892 2893use strict; 2894BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 2895BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 2896use URI::Escape; 2897 2898my $get_mtl = "http://www.flickr.com/apps/video/video_mtl_xml.gne?v=x"; 2899 2900sub find_video { 2901 my ($self, $browser, $embed_url) = @_; 2902 2903 my($id) = $browser->content =~ /photo_id=(\d+)/; 2904 my($secret) = $browser->content =~ /photo_secret=(\w+)/; 2905 2906 die "No video ID found\n" unless $id; 2907 2908 $browser->get($get_mtl . "&photo_id=$id&secret=$secret&olang=en-us&noBuffer=null&bitrate=700&target=_self"); 2909 2910 my $xml = from_xml($browser); 2911 2912 my $guid = $self->make_guid; 2913 my $video_id = $xml->{Data}->{Item}->{id}->{content}; 2914 my $playlist_url = $xml->{Playlist}->{TimelineTemplates}->{Timeline} 2915 ->{Metadata}->{Item}->{playlistUrl}->{content}; 2916 2917 die "No video ID or playlist found" unless $video_id and $playlist_url; 2918 2919 $browser->get($playlist_url 2920 . "?node_id=$video_id&secret=$secret&tech=flash&mode=playlist" 2921 . "&lq=$guid&bitrate=700&rd=video.yahoo.com&noad=1"); 2922 2923 $xml = eval { XML::Simple::XMLin($browser->content) }; 2924 die "Failed parsing XML: $@" if $@; 2925 2926 $xml = $xml->{"SEQUENCE-ITEM"}; 2927 die "XML not as expected" unless $xml; 2928 2929 my $filename = title_to_filename($xml->{META}->{TITLE}); 2930 my $url = $xml->{STREAM}->{APP} . $xml->{STREAM}->{FULLPATH}; 2931 2932 return $url, $filename; 2933} 2934 2935sub make_guid { 2936 my($self) = @_; 2937 2938 my @chars = ('A' .. 'Z', 'a' .. 'z', 0 .. 9, '.', '_'); 2939 return join "", map { $chars[rand @chars] } 1 .. 22; 2940} 2941 29421; 2943} 2944##} blib/lib/FlashVideo/Site/Flickr.pm 2945BEGIN { $INC{'FlashVideo/Site/Fliqz.pm'}++; } 2946# Part of get-flash-videos. See get_flash_videos for copyright. 2947##{ blib/lib/FlashVideo/Site/Fliqz.pm 2948{ 2949package FlashVideo::Site::Fliqz; 2950 2951use strict; 2952BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 2953BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 2954 2955sub find_video { 2956 my ($self, $browser, $embed_url) = @_; 2957 2958 my $id; 2959 if ($browser->content =~ /<param name=["']flashvars["'] value=["']file=([a-f0-9]{32})/) { 2960 $id = $1; 2961 } 2962 2963 if (!$id and $browser->content =~ /\Q$embed_url\E.*?([a-f0-9]{32})/) { 2964 $id = $1; 2965 } 2966 2967 $browser->post("http://services.fliqz.com/mediaassetcomponentservice/20071201/service.svc", 2968 Content_Type => "text/xml; charset=utf-8", 2969 SOAPAction => '"urn:fliqz.s.mac.20071201/IMediaAssetComponentService/ad"', 2970 Referer => $embed_url, 2971 Content => _get_soap_xml($id) 2972 ); 2973 2974 my $flv_url = ($browser->content =~ />(http:[^<]+\.flv)</)[0]; 2975 2976 if (!$flv_url) { 2977 $browser->post("http://services.fliqz.com/LegacyServices/Services/MediaAsset/Component/R20071201/service.svc", 2978 Content_Type => "text/xml; charset=utf-8", 2979 SOAPAction => '"urn:fliqz.s.mac.20071201/IMediaAssetComponentService/ad"', 2980 2981 Referer => $embed_url, 2982 2983 Content => _get_soap_xml($id) 2984 ); 2985 2986 $flv_url = ($browser->content =~ />(http:[^<]+\.flv)</)[0]; 2987 } 2988 2989 my $filename = ($browser->content =~ /<t [^>]+>([^<]+)/)[0]; 2990 $filename = title_to_filename($filename); 2991 2992 $browser->allow_redirects; 2993 2994 return $flv_url, $filename; 2995} 2996 2997sub _get_soap_xml { 2998 my $id = shift; 2999 3000 return <<EOF 3001<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 3002<SOAP-ENV:Body> 3003 <i0:ad xmlns:i0="urn:fliqz.s.mac.20071201"> 3004 <i0:rq> 3005 <i0:a>$id</i0:a> 3006 <i0:pu></i0:pu> 3007 <i0:pid>1F866AF1-1DB0-4864-BCA1-6236377B518F</i0:pid> 3008 </i0:rq> 3009</i0:ad> 3010</SOAP-ENV:Body> 3011</SOAP-ENV:Envelope> 3012EOF 3013} 3014 30151; 3016} 3017##} blib/lib/FlashVideo/Site/Fliqz.pm 3018BEGIN { $INC{'FlashVideo/Site/Fora.pm'}++; } 3019# Part of get-flash-videos. See get_flash_videos for copyright. 3020##{ blib/lib/FlashVideo/Site/Fora.pm 3021{ 3022package FlashVideo::Site::Fora; 3023 3024use strict; 3025BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 3026BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 3027 3028sub find_video { 3029 my ($self, $browser, $embed_url) = @_; 3030 3031 my($clip_id) = $browser->content =~ /clipid=(\d+)/; 3032 die "Unable to extract clipid" unless $clip_id; 3033 3034 $browser->get("http://fora.tv/fora/fora_player_full?cid=$clip_id&h=1&b=0"); 3035 3036 my $xml = from_xml($browser); 3037 3038 my $filename = title_to_filename($xml->{clipinfo}->{clip_title}); 3039 3040 my $playpath = $xml->{encodeinfo}->{encode_url}; 3041 $playpath =~ s/\.flv$//; 3042 3043 return { 3044 flv => $filename, 3045 app => "a953/o10", 3046 rtmp => "rtmp://foratv.fcod.llnwd.net", 3047 playpath => $playpath, 3048 }; 3049} 3050 30511; 3052} 3053##} blib/lib/FlashVideo/Site/Fora.pm 3054BEGIN { $INC{'FlashVideo/Site/Freevideo.pm'}++; } 3055# Part of get-flash-videos. See get_flash_videos for copyright. 3056##{ blib/lib/FlashVideo/Site/Freevideo.pm 3057{ 3058package FlashVideo::Site::Freevideo; # .ru 3059 3060use strict; 3061use Encode; 3062BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 3063BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 3064use URI::Escape; 3065 3066sub find_video { 3067 my ($self, $browser) = @_; 3068 3069 my $ticket; 3070 if ($browser->uri->as_string =~ /\?id=(.*?)$/) { 3071 $ticket = $1; 3072 } 3073 3074 $browser->post( 3075 "http://freevideo.ru/video/view/url/-/" . int(rand 100_000), 3076 [ 3077 onLoad => '[type Function]', 3078 highquality => 0, 3079 getvideoinfo => 1, 3080 devid => 'LoadupFlashPlayer', 3081 after_adv => 0, 3082 before_adv => 1, 3083 frame_url => 1, 3084 'ref' => $browser->uri->as_string, 3085 video_url => 1, 3086 ticket => $ticket, 3087 ] 3088 ); 3089 3090 if (!$browser->success) { 3091 die "Posting to Freevideo failed: " . $browser->response->status_line(); 3092 } 3093 3094 my $video_data = uri_unescape($browser->content); 3095 3096 my $url; 3097 3098 if ($video_data =~ m'vidURL=(http://.*?\.flv)') { 3099 $url = $1; 3100 } 3101 else { 3102 die "Couldn't find Freevideo URL"; 3103 } 3104 3105 my $title; 3106 3107 if ($video_data =~ /title=(.*?)&userNick/) { 3108 $title = $1; 3109 } 3110 3111 $title = decode('utf-8', $title); 3112 3113 return $url, title_to_filename($title); 3114} 3115 31161; 3117} 3118##} blib/lib/FlashVideo/Site/Freevideo.pm 3119BEGIN { $INC{'FlashVideo/Site/Gamespot.pm'}++; } 3120# Part of get-flash-videos. See get_flash_videos for copyright. 3121##{ blib/lib/FlashVideo/Site/Gamespot.pm 3122{ 3123package FlashVideo::Site::Gamespot; 3124 3125use strict; 3126BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 3127BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 3128 3129sub find_video { 3130 my ($self, $browser, $embed_url) = @_; 3131 3132 my($params) = $browser->content =~ /xml.php\?(id=[0-9]+.*?)"/; 3133 ($params) = $embed_url =~ /xml.php%3F(id%3D[^"&]+)/ unless $params; 3134 die "No params found\n" unless $params; 3135 3136 $browser->get("http://www.gamespot.com/pages/video_player/xml.php?" . $params); 3137 3138 my $xml = from_xml($browser); 3139 3140 my $title = $xml->{playList}->{clip}->{title}; 3141 my $url = $xml->{playList}->{clip}->{URI}; 3142 3143 $browser->allow_redirects; 3144 return $url, title_to_filename($title); 3145} 3146 31471; 3148 3149} 3150##} blib/lib/FlashVideo/Site/Gamespot.pm 3151BEGIN { $INC{'FlashVideo/Site/Gawker.pm'}++; } 3152# Part of get-flash-videos. See get_flash_videos for copyright. 3153##{ blib/lib/FlashVideo/Site/Gawker.pm 3154{ 3155package FlashVideo::Site::Gawker; 3156 3157use strict; 3158BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 3159BEGIN { no strict 'refs'; *extract_title = \&FlashVideo::Utils::extract_title; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 3160 3161sub find_video { 3162 my ($self, $browser) = @_; 3163 3164 my $title = extract_title($browser); 3165 $title =~ s/^\w+\s+-\s*//; 3166 $title =~ s/\s*-\s+\w+$//; 3167 my $filename = title_to_filename($title); 3168 3169 my $url = "http://cache." . $browser->uri->host . "/assets/video/" . 3170 ($browser->content =~ /newVideoPlayer\("([^"]+)/)[0]; 3171 3172 return $url, $filename; 3173} 3174 3175sub can_handle { 3176 my($self, $browser, $url) = @_; 3177 3178 return $browser->content =~ /newVideoPlayer/; 3179} 3180 31811; 3182} 3183##} blib/lib/FlashVideo/Site/Gawker.pm 3184BEGIN { $INC{'FlashVideo/Site/Globaltv.pm'}++; } 3185################################# 3186################################################# 3187# 3188# This file was automatically generated by utils/combine-perl.pl 3189# You should edit the original files, not this 3190# combined version. 3191# 3192# The original files are available at: 3193# http://github.com/monsieurvideo/get-flash-videos 3194# 3195################################################# 3196# GlobalTV Canada 3197# 3198# first alpha plugin version 3199# 3200# Input URL should be 3201# http://www.globaltv.com/$show/video/full+episodes/$clip/video.html?v=$contentID 3202# where 3203# $show show name 3204# $clip section 3205# $contentID numeric ID 3206# Stavr00 3207# 3208# TODO: fetch all clips for a show 3209# 3210 3211##{ blib/lib/FlashVideo/Site/Globaltv.pm 3212{ 3213package FlashVideo::Site::Globaltv; 3214 3215use strict; 3216BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 3217BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 3218use strict 'refs'; 3219 3220sub find_video { 3221 my ($self, $browser, $embed_url, $prefs) = @_; 3222 3223 my $pid; 3224 if ( $browser->content =~ /pid:\s+"([^"]+?)"/ ) { 3225 $pid = $1; 3226 } 3227 3228 debug "PID = " . $pid; 3229 3230 die "PID not found." unless $pid; 3231 3232 $browser->get("http://release.theplatform.com/content.select?pid=$pid&mbr=true&Embedded=True&Portal=GlobalTV&Site=global_prg.com&TrackBrowser=True&Tracking=True&TrackLocation=True&format=SMIL"); 3233 3234 my $xml = from_xml($browser->content); 3235 3236 my $maxres = $prefs->quality->quality_to_resolution($prefs->{quality}); 3237 my $sw; 3238 my $vid; 3239 my $title; 3240 my $url; 3241 my $rate = 0; 3242 my $res; 3243 debug "Enumerating all streams ..."; 3244 foreach $sw (@{ $xml->{body}->{switch} }) { 3245 if ($sw->{ref}->{src} =~ /^rtmp\:\/\// ) { 3246 $title = $sw->{ref}->{title}; 3247 debug "TITLE = " . $title; # short title, not very useful 3248 } 3249 if ( ref($sw->{video}) eq "ARRAY" ) { 3250 foreach $vid (@{ $sw->{video} }) { 3251 my $t = $vid->{src}; 3252 if ( $t =~ /^rtmp\:\/\// ) { 3253 my $w = $vid->{width}; 3254 my $h = $vid->{height}; 3255 my $br = $vid->{'system-bitrate'}; 3256 debug ' '. $t ." ". $w . 'x' . $h ."/". $br; 3257 if ( ( $br > $rate ) && ( $h <= @$maxres[1] ) ) { 3258 $rate = $br; 3259 $url = $t; 3260 $res = $w .'x'. $h .' '. int($br/1024) . 'kb/s'; 3261 } 3262 } 3263 } 3264 } 3265 } 3266 3267 info 'Stream selected: ' . $url . ' ' . $res; 3268 3269 3270 $url =~ /([^\/]+\.mp4$)/; 3271 $title = $1; 3272 3273 return { 3274 rtmp => $url, 3275 flv => title_to_filename($title) 3276 }; 3277 3278 3279} 3280 32811; 3282 3283} 3284##} blib/lib/FlashVideo/Site/Globaltv.pm 3285BEGIN { $INC{'FlashVideo/Site/Google.pm'}++; } 3286# Part of get-flash-videos. See get_flash_videos for copyright. 3287##{ blib/lib/FlashVideo/Site/Google.pm 3288{ 3289package FlashVideo::Site::Google; 3290 3291use strict; 3292BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 3293BEGIN { no strict 'refs'; *extract_title = \&FlashVideo::Utils::extract_title; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 3294use URI::Escape; 3295 3296sub find_video { 3297 my ($self, $browser) = @_; 3298 3299 if ($browser->content =~ /googleplayer\.swf\?doc[iI]d=([^&;'"]+)/) { 3300 $browser->get("http://video.google.com/videoplay?docid=$1"); 3301 } 3302 3303 if (!$browser->success) { 3304 $browser->get($browser->response->header('Location')); 3305 die "Couldn't download URL: " . $browser->response->status_line 3306 unless $browser->success; 3307 } 3308 3309 my $url; 3310 if ($browser->content =~ /googleplayer\.swf\?&?videoUrl(.+?)\\x26/) { 3311 $url = uri_unescape($1); 3312 3313 $url =~ s/\\x([A-F0-9]{2})/chr(hex $1)/egi; 3314 $url =~ s/^=//; 3315 } 3316 3317 my $filename = title_to_filename(extract_title($browser)); 3318 3319 $browser->allow_redirects; 3320 3321 return $url, $filename; 3322} 3323 3324sub can_handle { 3325 my($self, $browser, $url) = @_; 3326 3327 return $browser->response->header('Location') =~ /google/i 3328 || $browser->content =~ /googleplayer\.swf/; 3329} 3330 33311; 3332} 3333##} blib/lib/FlashVideo/Site/Google.pm 3334BEGIN { $INC{'FlashVideo/Site/Googlevideosearch.pm'}++; } 3335# Part of get-flash-videos. See get_flash_videos for copyright. 3336BEGIN { $INC{'FlashVideo/Mechanize.pm'}++; } 3337# Part of get-flash-videos. See get_flash_videos for copyright. 3338BEGIN { $INC{'FlashVideo/Downloader.pm'}++; } 3339# Part of get-flash-videos. See get_flash_videos for copyright. 3340BEGIN { $INC{'FlashVideo/Site.pm'}++; } 3341# Part of get-flash-videos. See get_flash_videos for copyright. 3342##{ blib/lib/FlashVideo/Site.pm 3343{ 3344package FlashVideo::Site; 3345 3346use strict; 3347 3348 3349sub debug { 3350 $App::get_flash_videos::opt{debug}; 3351} 3352 3353sub action { 3354 $App::get_flash_videos::opt{play} ? "play" : "download"; 3355} 3356 3357sub player { 3358 $App::get_flash_videos::opt{player}; 3359} 3360 3361sub yes { 3362 $App::get_flash_videos::opt{yes}; 3363} 3364 3365sub quiet { 3366 $App::get_flash_videos::opt{quiet}; 3367} 3368 33691; 3370} 3371##} blib/lib/FlashVideo/Site.pm 3372##{ blib/lib/FlashVideo/Downloader.pm 3373{ 3374package FlashVideo::Downloader; 3375 3376use strict; 3377BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 3378BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *error = \&FlashVideo::Utils::error; *get_win_codepage = \&FlashVideo::Utils::get_win_codepage; *get_terminal_width = \&FlashVideo::Utils::get_terminal_width; } 3379 3380BEGIN { FlashVideo::Site->import(); } # (added by utils/combine-perl.pl) 3381use base "FlashVideo::Site"; 3382 3383sub new { 3384 my $class = shift; 3385 3386 my $self = { 3387 has_readkey => scalar eval { require Term::ReadKey } 3388 }; 3389 3390 bless $self, $class; 3391 return $self; 3392} 3393 3394sub play { 3395 my ($self, $url, $file, $browser) = @_; 3396 3397 $self->{stream} = sub { 3398 $self->{stream} = undef; 3399 3400 if ($^O =~ /MSWin/i and $self->player eq "VLC") { 3401 if (my $vlc_binary = FlashVideo::Utils::get_vlc_exe_from_registry()) { 3402 require Win32::Process; 3403 require File::Basename; 3404 require File::Spec; 3405 $file = File::Spec->rel2abs($file); 3406 3407 my $binary_no_path = File::Basename::basename $vlc_binary; 3408 3409 my $binary_just_path = File::Basename::dirname $vlc_binary; 3410 3411 my $process; 3412 Win32::Process::Create( 3413 $process, 3414 $vlc_binary, 3415 "$binary_no_path $file", 3416 1, 3417 32, # NORMAL_PRIORITY_CLASS 3418 $binary_just_path, 3419 ) or info "Couldn't launch VLC ($vlc_binary): " . Win32::GetLastError(); 3420 } 3421 } 3422 else { 3423 my $pid = fork; 3424 die "Fork failed" unless defined $pid; 3425 if(!$pid) { 3426 exec $self->replace_filename($self->player, $file); 3427 die "Exec failed\n"; 3428 } 3429 } 3430 }; 3431 3432 $self->download($url, $file, $browser); 3433} 3434 3435sub download { 3436 my ($self, $url, $file, $browser) = @_; 3437 3438 $self->{printable_filename} = $file; 3439 3440 $file = $self->get_filename($file); 3441 3442 my $mode = (-e $file) ? '>>' : '>'; 3443 my $offset; 3444 if ($file ne '-' && -e $file) { 3445 $offset = -s $file; 3446 3447 my $response = $browser->head($url); 3448 3449 if ($offset == $response->header('Content-Length')) { 3450 error "File $self->{printable_filename} has been fully downloaded."; 3451 $self->{stream}->() if defined $self->{stream}; 3452 return; 3453 } 3454 3455 info "File $self->{printable_filename} already exists, seeing if resuming is supported."; 3456 if (!$response->header('Accept-Ranges')) { 3457 if(!$self->yes) { 3458 error "This server doesn't explicitly support resuming.\n" . 3459 "Do you want to try resuming anyway (y/n)?"; 3460 chomp(my $answer = <STDIN>); 3461 if (!$answer or lc($answer) eq 'n') { 3462 undef $offset; 3463 $mode = '>'; 3464 } 3465 } 3466 } 3467 else { 3468 info "Server supports resuming, attempting to resume."; 3469 } 3470 } 3471 3472 my $video_fh; 3473 if($file eq '-') { 3474 $video_fh = \*STDOUT; 3475 } else { 3476 open $video_fh, $mode, $file or die $!; 3477 } 3478 3479 binmode $video_fh; 3480 $self->{fh} = $video_fh; 3481 3482 info "Downloading $url..."; 3483 if ($offset) { 3484 $browser->add_header("Range", "bytes=$offset-"); 3485 } 3486 my $response = $browser->get($url, 3487 ':content_cb' => sub { 3488 my ($data, $response) = @_; 3489 3490 if (!$self->{content_length}) { 3491 $self->{content_length} = $response->header('Content-Length') 3492 + $offset; 3493 3494 if($response->header('Content-encoding') =~ /gzip/i) { 3495 eval { require Compress::Zlib; } or do { 3496 error "Must have Compress::Zlib installed to download from this site.\n"; 3497 exit 1; 3498 }; 3499 3500 my($inflate, $status) = Compress::Zlib::inflateInit( 3501 -WindowBits => -Compress::Zlib::MAX_WBITS()); 3502 error "inflateInit failed: $status" if $status; 3503 3504 $self->{filter} = sub { 3505 my($data) = @_; 3506 3507 if(!$self->{downloaded}) { 3508 Compress::Zlib::_removeGzipHeader(\$data); 3509 } 3510 3511 my($output, $status) = $inflate->inflate($data); 3512 return $output; 3513 } 3514 } 3515 } 3516 3517 if ($offset and !$response->header('Content-Range')) { 3518 error "Resuming failed - please delete $self->{printable_filename} and restart."; 3519 exit 1; 3520 } 3521 else { 3522 $self->{downloaded} = $offset unless $self->{downloaded}; 3523 } 3524 3525 my $len = length $data; 3526 3527 if($self->{filter}) { 3528 $data = $self->{filter}->($data); 3529 } 3530 3531 return unless $data; 3532 3533 my $fh = $self->{fh}; 3534 print $fh $data || die "Unable to write to '$self->{printable_filename}': $!\n"; 3535 3536 if(defined $self->{stream}) { 3537 if($self->{downloaded} > 300_000) { 3538 $self->{stream}->(); 3539 } 3540 } 3541 3542 if(!$self->{downloaded} && length $data > 16) { 3543 if(!$self->check_magic($data)) { 3544 error "Sorry, file does not look like a media file, aborting."; 3545 exit 1; 3546 } 3547 } 3548 3549 $self->{downloaded} += $len; 3550 $self->progress; 3551 }, ':read_size_hint' => 16384); 3552 3553 if($browser->response->header("X-Died")) { 3554 error $browser->response->header("X-Died"); 3555 } 3556 3557 close $self->{fh} || die "Unable to write to '$self->{printable_filename}': $!"; 3558 3559 if ($browser->success) { 3560 return $self->{downloaded} - $offset; 3561 } else { 3562 unlink $file unless -s $file; 3563 error "Couldn't download $url: " . $browser->response->status_line; 3564 return 0; 3565 } 3566} 3567 3568sub progress { 3569 my($self) = @_; 3570 3571 return unless -t STDERR; 3572 return if $self->quiet; 3573 3574 my $progress_text; 3575 3576 if ($self->{content_length}) { 3577 my $percent = int( 3578 ($self->{downloaded} / $self->{content_length}) * 100 3579 ); 3580 if ($percent != $self->{percent} || time != $self->{last_time}) { 3581 my $downloaded_kib = _bytes_to_kib($self->{downloaded}); 3582 my $total_kib = _bytes_to_kib($self->{content_length}); 3583 $progress_text = ": $percent% ($downloaded_kib / $total_kib KiB)"; 3584 $self->{last_time} = time; 3585 $self->{percent} = $percent; 3586 } 3587 } else { 3588 my $data_transferred = _bytes_to_kib($self->{downloaded}); 3589 if ($data_transferred != $self->{data_transferred}) { 3590 $progress_text = ": $data_transferred KiB"; 3591 } 3592 } 3593 3594 if($progress_text) { 3595 my $width = get_terminal_width(); 3596 3597 my $filename = $self->{printable_filename}; 3598 my $filename_len = $width - length($progress_text); 3599 3600 if($filename_len < length $filename) { 3601 my $rem = 3 + length($filename) - $filename_len; 3602 my $pos = length($filename) - $rem - 12; 3603 $pos = 0 if $pos < 0; 3604 substr($filename, $pos, $rem) = "..."; 3605 } 3606 3607 syswrite STDERR, "\r$filename$progress_text"; 3608 } 3609} 3610 3611sub _bytes_to_kib { 3612 return sprintf '%0.2f', ($_[0] / 1024) 3613} 3614 3615sub replace_filename { 3616 my($self, $string, $filename) = @_; 3617 $string .= " %s" unless $string =~ /%s/; 3618 my $esc = $self->shell_escape($filename); 3619 $string =~ s/['"]?%s['"]?/$esc/g; 3620 return $string; 3621} 3622 3623sub shell_escape { 3624 my($self, $file) = @_; 3625 3626 $file =~ s/'/'\\''/g; 3627 return "'$file'"; 3628} 3629 3630sub check_file { 3631 my($self, $file) = @_; 3632 3633 open my $fh, "<", $file; 3634 binmode $fh; 3635 my $data; 3636 read $fh, $data, 16; 3637 3638 return $self->check_magic($data); 3639} 3640 3641sub check_magic { 3642 my($self, $data) = @_; 3643 3644 3645 if(substr($data, 0, 3) eq 'FLV') { 3646 return 1; 3647 } elsif(substr($data, 0, 3) eq 'ID3') { 3648 return 1; 3649 } elsif (substr($data, 0, 2) eq "\xff\xfb") { 3650 return 1; 3651 } elsif(substr($data, 0, 4) eq "\x30\x26\xb2\x75") { 3652 return 1; 3653 } elsif(substr($data, 4, 4) eq 'ftyp') { 3654 return 1; 3655 } elsif(substr($data, 4, 4) =~ /moov|mdat|wide|free|pnot|skip/) { 3656 return 1; 3657 } elsif(substr($data, 0, 4) eq 'OggS') { 3658 return 1; 3659 } elsif(substr($data, 0x1F, 4) eq 'webm') { 3660 return 1; 3661 } elsif(substr($data, 0, 4) eq 'RIFF') { 3662 return 1; 3663 } 3664 3665 return 0; 3666} 3667 3668sub get_filename { 3669 my($self, $file) = @_; 3670 3671 if($^O =~ /MSWin/i) { 3672 $file = Encode::encode(get_win_codepage(), $file); 3673 $file =~ s/\?/_/g; 3674 } 3675 3676 return $file; 3677} 3678 36791; 3680 3681} 3682##} blib/lib/FlashVideo/Downloader.pm 3683##{ blib/lib/FlashVideo/Mechanize.pm 3684{ 3685package FlashVideo::Mechanize; 3686use WWW::Mechanize; 3687BEGIN { FlashVideo::Downloader->import(); } # (added by utils/combine-perl.pl) 3688use Encode (); 3689 3690use strict; 3691use WWW::Mechanize;use base "WWW::Mechanize"; 3692 3693sub new { 3694 my $class = shift; 3695 my $browser = $class->SUPER::new(autocheck => 0); 3696 $browser->agent_alias("Windows Mozilla"); 3697 3698 my $proxy = $App::get_flash_videos::opt{proxy}; 3699 3700 if ($proxy) { 3701 if ($proxy =~ /^(\w+):?(\d+)?$/) { 3702 my ($host, $port) = ($1, $2); 3703 3704 $port ||= 1080; # socks by default 3705 3706 $proxy = "socks://$host:$port"; 3707 3708 print STDERR "Using proxy server $proxy\n" 3709 if $App::get_flash_videos::opt{debug}; 3710 3711 $browser->proxy([qw[http https]] => $proxy); 3712 } 3713 } 3714 3715 if($browser->get_socks_proxy) { 3716 if(!eval { require LWP::Protocol::socks }) { 3717 die "LWP::Protocol::socks is required for SOCKS support, please install it\n"; 3718 } 3719 } 3720 3721 return $browser; 3722} 3723 3724sub redirect_ok { 3725 my($self) = @_; 3726 3727 return $self->{redirects_ok}; 3728} 3729 3730sub allow_redirects { 3731 my($self) = @_; 3732 $self->{redirects_ok} = 1; 3733} 3734 3735sub get { 3736 my($self, @rest) = @_; 3737 3738 print STDERR "-> GET $rest[0]\n" if $App::get_flash_videos::opt{debug}; 3739 3740 my $r = $self->SUPER::get(@rest); 3741 3742 if($App::get_flash_videos::opt{debug}) { 3743 my $text = join " ", $self->response->code, 3744 $self->response->header("Content-type"), "(" . length($self->content) . ")"; 3745 $text .= ": " . DBI::data_string_desc($self->content) if eval { require DBI }; 3746 3747 print STDERR "<- $text\n"; 3748 } 3749 3750 return $r; 3751} 3752 3753sub update_html { 3754 my($self, $html) = @_; 3755 3756 my $charset = _parse_charset($self->response->header("Content-type")); 3757 3758 if($LWP::UserAgent::VERSION < 5.827 3759 && (!$charset || !Encode::is_utf8($html))) { 3760 3761 $html = Encode::encode("iso-8859-1", $html) if Encode::is_utf8($html); 3762 3763 if(!FlashVideo::Downloader->check_magic($html)) { 3764 my $p = HTML::TokeParser->new(\$html); 3765 while(my $token = $p->get_tag("meta")) { 3766 my($tag, $attr) = @$token; 3767 if($tag eq 'meta' && $attr->{"http-equiv"} =~ /Content-type/i) { 3768 $charset ||= _parse_charset($attr->{content}); 3769 } 3770 } 3771 3772 if($charset) { 3773 eval { $html = Encode::decode($charset, $html) }; 3774 FlashVideo::Utils::error("Failed decoding as $charset: $@") if $@; 3775 } 3776 } 3777 } 3778 3779 return $self->SUPER::update_html($html); 3780} 3781 3782sub _parse_charset { 3783 my($field) = @_; 3784 return(($field =~ /;\s*charset=([-_.:a-z0-9]+)/i)[0]); 3785} 3786 3787sub get_socks_proxy { 3788 my $self = shift; 3789 my $proxy = $self->proxy("http"); 3790 3791 if(defined $proxy && $proxy =~ m!^socks://(.*?):(\d+)!) { 3792 return "$1:$2"; 3793 } 3794 3795 return ""; 3796} 3797 37981; 3799} 3800##} blib/lib/FlashVideo/Mechanize.pm 3801##{ blib/lib/FlashVideo/Site/Googlevideosearch.pm 3802{ 3803package FlashVideo::Site::Googlevideosearch; 3804 3805use strict; 3806no warnings 'uninitialized'; 3807BEGIN { FlashVideo::Mechanize->import(); } # (added by utils/combine-perl.pl) 3808use URI::Escape; 3809 3810sub search { 3811 my($self, $search, $type) = @_; 3812 3813 my $browser = FlashVideo::Mechanize->new; 3814 3815 $browser->get('http://video.google.com/videoadvancedsearch'); 3816 3817 $browser->submit_form( 3818 with_fields => { 3819 q => $search, 3820 } 3821 ); 3822 3823 return unless $browser->success; 3824 3825 my @links = map { 3826 chomp(my $name = $_->text); 3827 my $url = $_->url_abs->as_string; 3828 $url =~ /q=([^&]*)/; 3829 $url = uri_unescape($1); 3830 { name => $name, url => $url } 3831 } 3832 $browser->find_all_links(text_regex => qr/.+/, url_regex => qr/\/url/); 3833 3834 return @links; 3835} 3836 38371; 3838} 3839##} blib/lib/FlashVideo/Site/Googlevideosearch.pm 3840BEGIN { $INC{'FlashVideo/Site/Gorillavid.pm'}++; } 3841# Part of get-flash-videos. See get_flash_videos for copyright. 3842################################################# 3843# 3844# This file was automatically generated by utils/combine-perl.pl 3845# You should edit the original files, not this 3846# combined version. 3847# 3848# The original files are available at: 3849# http://github.com/monsieurvideo/get-flash-videos 3850# 3851################################################# 3852 3853#This package handles sites such as GorillaVid.in, DaClips.in and 3854# MovPod.in 3855##{ blib/lib/FlashVideo/Site/Gorillavid.pm 3856{ 3857package FlashVideo::Site::Gorillavid; 3858 3859use strict; 3860BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 3861BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; } 3862 3863sub find_video { 3864 my ($self, $browser, $embed_url) = @_; 3865 my $filename; 3866 3867 for my $form ($browser->forms) { 3868 if ($form->find_input('#btn_download')){ 3869 $filename = $form->value('fname'); #extract the filename from the form 3870 3871 info 'Submitting form to get real video page.'; 3872 $browser->request($form->click()); #submit to get the real page 3873 } 3874 } 3875 3876 my ($url) = ($browser->content =~ /file: *"(https?:\/\/.*?)"/); 3877 3878 my ($ext) = ($url =~ /(\.[a-z0-9]{2,4})$/); 3879 3880 return $url, $filename.$ext; 3881} 3882 3883sub can_handle { 3884 my($self, $browser, $url) = @_; 3885 3886 return 1 if $url && URI->new($url)->host =~ /(gorillavid|daclips|movpod)\.in$/; 3887} 3888 38891; 3890} 3891##} blib/lib/FlashVideo/Site/Gorillavid.pm 3892BEGIN { $INC{'FlashVideo/Site/Grindtv.pm'}++; } 3893# Part of get-flash-videos. See get_flash_videos for copyright. 3894##{ blib/lib/FlashVideo/Site/Grindtv.pm 3895{ 3896package FlashVideo::Site::Grindtv; 3897 3898use strict; 3899BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 3900BEGIN { no strict 'refs'; *extract_title = \&FlashVideo::Utils::extract_title; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 3901 3902my %sites = ( 3903 Grindtv => "http://videos.grindtv.com/1/", 3904 Stupidvideos => "http://videos.stupidvideos.com/2/", 3905 Ringtv => "http://videos.ringtv.com/7/" 3906); 3907 3908sub find_video { 3909 my ($self, $browser, $embed_url) = @_; 3910 3911 my $site = ($self =~ /::([^:]+)$/)[0]; 3912 my $base = $sites{$site}; 3913 3914 my $id; 3915 if($browser->content =~ /(?:baseID|video(?:ID)?)\s*=\s*['"]?(\d+)/) { 3916 $id = $1; 3917 } 3918 die "No ID found\n" unless $id; 3919 3920 my $title = ($browser->content =~ /name="title" content="([^"]+)/i)[0]; 3921 $title = extract_title($browser) unless $title; 3922 3923 my $filename = title_to_filename($title); 3924 3925 $browser->allow_redirects; 3926 3927 my $str = sprintf "%08d", $id; 3928 my $url = $base . join("/", map { substr $str, $_*2, 2 } 0 .. 3) . "/$id.flv"; 3929 3930 return $url, $filename; 3931} 3932 39331; 3934} 3935##} blib/lib/FlashVideo/Site/Grindtv.pm 3936BEGIN { $INC{'FlashVideo/Site/Ima.pm'}++; } 3937# Part of get-flash-videos. See get_flash_videos for copyright. 3938##{ blib/lib/FlashVideo/Site/Ima.pm 3939{ 3940package FlashVideo::Site::Ima; 3941 3942use strict; 3943BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 3944BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 3945 3946sub find_video { 3947 my ($self, $browser) = @_; 3948 3949 my($id) = $browser->uri =~ /id=(\d+)/; 3950 die "ID not found" unless $id; 3951 3952 my $rpc = "http://www.ima.umn.edu/videos/video_rpc.php?id=$id"; 3953 $browser->get($rpc); 3954 3955 my($title) = $browser->content =~ m{<video_title>(.*)</video_title>}; 3956 my($instance) = $browser->content =~ m{<video_instance>(.*)</video_instance>}; 3957 my($file) = $browser->content =~ m{<video_file>(.*)</video_file>}; 3958 3959 return { 3960 rtmp => "rtmp://reel.ima.umn.edu/ima/$instance/$file", 3961 flv => title_to_filename($title) 3962 }; 3963} 3964 3965sub can_handle { 3966 my($self, $browser) = @_; 3967 3968 return $browser->uri->host =~ /ima\.umn\.edu/i; 3969} 3970 39711; 3972} 3973##} blib/lib/FlashVideo/Site/Ima.pm 3974BEGIN { $INC{'FlashVideo/Site/Itv.pm'}++; } 3975# Part of get-flash-videos. See get_flash_videos for copyright. 3976##{ blib/lib/FlashVideo/Site/Itv.pm 3977{ 3978package FlashVideo::Site::Itv; 3979 3980use strict; 3981BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 3982BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *swfhash = \&FlashVideo::Utils::swfhash; } 3983use HTML::Entities; 3984 3985sub find_video { 3986 my ($self, $browser, $page_url, $prefs) = @_; 3987 3988 my($id) = $browser->uri =~ /Filter=(\d+)/; 3989 die "No id (filter) found in URL\n" unless $id; 3990 3991 $browser->post("http://mercury.itv.com/PlaylistService.svc", 3992 Content_Type => "text/xml; charset=utf-8", 3993 Referer => "http://www.itv.com/mercury/Mercury_VideoPlayer.swf?v=1.5.309/[[DYNAMIC]]/2", 3994 SOAPAction => '"http://tempuri.org/PlaylistService/GetPlaylist"', 3995 Content => <<EOF); 3996<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 3997 <SOAP-ENV:Body> 3998 <tem:GetPlaylist xmlns:tem="http://tempuri.org/" xmlns:itv="http://schemas.datacontract.org/2004/07/Itv.BB.Mercury.Common.Types" xmlns:com="http://schemas.itv.com/2009/05/Common"> 3999 <tem:request> 4000 <itv:RequestGuid>FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF</itv:RequestGuid> 4001 <itv:Vodcrid> 4002 <com:Id>$id</com:Id> 4003 <com:Partition>itv.com</com:Partition> 4004 </itv:Vodcrid> 4005 </tem:request> 4006 <tem:userInfo> 4007 <itv:GeoLocationToken> 4008 <itv:Token/> 4009 </itv:GeoLocationToken> 4010 <itv:RevenueScienceValue>scc=true; svisit=1; sc4=Other</itv:RevenueScienceValue> 4011 </tem:userInfo> 4012 <tem:siteInfo> 4013 <itv:AdvertisingRestriction>None</itv:AdvertisingRestriction> 4014 <itv:AdvertisingSite>ITV</itv:AdvertisingSite> 4015 <itv:Area>ITVPLAYER.VIDEO</itv:Area> 4016 <itv:Platform>DotCom</itv:Platform> 4017 <itv:Site>ItvCom</itv:Site> 4018 </tem:siteInfo> 4019 </tem:GetPlaylist> 4020 </SOAP-ENV:Body> 4021</SOAP-ENV:Envelope> 4022EOF 4023 4024 debug $browser->content; 4025 die "Unable to find <Video> in XML" unless $browser->content =~ m{<Video timecode[^>]+>(.*?)</Video>}s; 4026 my $video = $1; 4027 4028 4029 my %formats; 4030 4031 while ($video =~ m/(mp4:[^\]]+_[A-Z]+([0-9]{3,4})_(16|4)[-x](9|3)[^\]]*.mp4)/gi) 4032 { 4033 $formats{$2} = { video => $video, playpath => $1, ratio => "$3x$4" }; 4034 } 4035 4036 while ($video =~ m/(mp4:[^\]]+-([0-9]{3,4})kbps.mp4)/gi) 4037 { 4038 $formats{$2} = { video => $video, playpath => $1, ratio => "16x9" }; 4039 } 4040 while ($video =~ m/(mp4:[^\]]+-([0-9]{3,4})kbps.\d+.mp4)/gi) 4041 { 4042 $formats{$2} = { video => $video, playpath => $1, ratio => "16x9" }; 4043 } 4044 4045 my @rates = sort { $a <=> $b } keys(%formats); 4046 my $cnt = $#rates; 4047 4048 die "Unable to find video in XML" unless $cnt >= 0; 4049 4050 my $q = $prefs->{quality}; 4051 if ( $q =~ /^\s*\d+\s*$/) { 4052 my $rate = $rates[0]; 4053 foreach (@rates) { 4054 if ( $q >= $_ ) 4055 { $rate = $_;} 4056 } 4057 $q = $rate; 4058 } 4059 else { 4060 my $num = {high =>int($cnt), medium => int(($cnt+1)/2), low => 0}->{$q}; 4061 if (! defined $num ) { 4062 $num = int($cnt); 4063 } 4064 $q = $rates[$num]; 4065 } 4066 4067 my $format = $formats{$q}; 4068 if ( ! defined($format)) { 4069 $format = $formats{$rates[int($cnt)]}; 4070 } 4071 4072 $video = $format->{"video"}; 4073 my $rtmp = decode_entities($video =~ /base="(rtmp[^"]+)/); 4074 my($playpath) = $format->{"playpath"}; 4075 my($flv) = $playpath =~ m{/([^/]+)$}; 4076 4077 return { 4078 rtmp => $rtmp, 4079 playpath => $playpath, 4080 flv => $flv, 4081 swfhash($browser, "http://www.itv.com/mercury/Mercury_VideoPlayer.swf") 4082 }; 4083} 4084 40851; 4086} 4087##} blib/lib/FlashVideo/Site/Itv.pm 4088BEGIN { $INC{'FlashVideo/Site/Joemonster.pm'}++; } 4089# Author: paczesiowa@gmail.com 4090################################################# 4091# 4092# This file was automatically generated by utils/combine-perl.pl 4093# You should edit the original files, not this 4094# combined version. 4095# 4096# The original files are available at: 4097# http://github.com/monsieurvideo/get-flash-videos 4098# 4099################################################# 4100# 4101# This plugin works for videos from www.joemonster.org using 'Monster Player' 4102# 4103# Most (~70%) of them are single embedded youtube videos: 4104# http://www.joemonster.org/filmy/28773/Sposob_na_Euro_2012 4105# This plugin doesn't directly support them, 4106# so get_flash_videos fallbacks to youtube method, which works just fine. 4107# Pages with multiple youtube videos are also supported by youtube method, 4108# but only the first embedded video is downloaded: 4109# http://www.joemonster.org/filmy/4551/Terapia_masazem 4110# 4111# This plugin claims to support a page when it contains at least one video 4112# embedded with Monster Player. 4113# Pages with mixed providers, like this (Monster Player+youtube): 4114# http://www.joemonster.org/filmy/5496/Kolo_Smierci 4115# only downloads Monster Player movies, the rest is discarded, 4116# because I don't know how to provide links AND fallback to a different method. 4117# 4118# There are two versions of Monster Player: 4119# * old/fat 4120# http://www.joemonster.org/filmy/28784/Genialny_wystep_mlodego_iluzjonisty_w_Mam_talent (single video) 4121# http://www.joemonster.org/filmy/28693/Dave_Chappelle_w_San_Francisco_ (multi videos) 4122# 4123# * new/slim 4124# http://www.joemonster.org/filmy/28372/Wszyscy_kochamy_Polske_czesc_ (single video) 4125# 4126# Currently multiple videos are unsupported, only the first one is downloaded, 4127# I have no idea how to return multiple links 4128# 4129# About 5% of videos are embedded from external providers (different than youtube), 4130# they should work if get_flash_videos has appropriate method. 4131 4132##{ blib/lib/FlashVideo/Site/Joemonster.pm 4133{ 4134package FlashVideo::Site::Joemonster; 4135 4136use strict; 4137BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 4138BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 4139use URI::Escape; 4140use URI::QueryParam; 4141 4142 4143my $new_monster_player_regex = "<\\s*embed\\s*src\\s*=\\s*\"\\s*(http:\\/\\/www\\.joemonster\\.org\\/flvplayer\\.swf\\?file=.*?)\\s*\""; 4144 4145sub is_new_monster_player { 4146 my($self, $browser) = @_; 4147 return $browser->content =~ m/$new_monster_player_regex/; 4148} 4149 4150sub get_new_monster_player_url { 4151 my($self, $browser) = @_; 4152 $browser->content =~ m/$new_monster_player_regex/; 4153 return URI->new($1)->query_param('file') or die "no file key in player link"; 4154} 4155 4156my $old_monster_player_regex = "<\\s*embed\\s*src\\s*=\\s*\"\\s*(http:\\/\\/www\\.joemonster\\.org\\/emb\\/.*?)\\s*\""; 4157 4158sub is_old_monster_player { 4159 my($self, $browser) = @_; 4160 return $browser->content =~ m/$old_monster_player_regex/; 4161} 4162 4163 4164sub get_old_monster_player_url { 4165 my($self, $browser) = @_; 4166 $browser->content =~ m/$old_monster_player_regex/; 4167 my $embedded_url = $1; 4168 $browser->get($embedded_url); 4169 my $url = $browser->uri; 4170 return URI->new($url)->query_param('file') or die "no file key in player link"; 4171} 4172 4173sub can_handle { 4174 my($self, $browser, $url) = @_; 4175 return $self->is_new_monster_player($browser) || $self->is_old_monster_player($browser); 4176} 4177 4178sub find_video { 4179 my($self, $browser, $url) = @_; 4180 my $real_url; 4181 4182 if ($self->is_new_monster_player($browser)) { 4183 $real_url = $self->get_new_monster_player_url($browser); 4184 } 4185 else { 4186 $real_url = $self->get_old_monster_player_url($browser); 4187 } 4188 4189 my $title; 4190 if ($browser->title =~ m/(.*) - Joe Monster/ ) { 4191 $title = $1; 4192 } else { 4193 $title = $browser->title; 4194 } 4195 4196 return $real_url, title_to_filename($title); 4197} 4198 41991; 4200} 4201##} blib/lib/FlashVideo/Site/Joemonster.pm 4202BEGIN { $INC{'FlashVideo/Site/Kanal5play.pm'}++; } 4203# Part of get-flash-videos. See get_flash_videos for copyright. 4204##{ blib/lib/FlashVideo/Site/Kanal5play.pm 4205{ 4206package FlashVideo::Site::Kanal5play; 4207 4208use strict; 4209use warnings; 4210BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 4211BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 4212BEGIN { FlashVideo::JSON->import(); } # (added by utils/combine-perl.pl) 4213BEGIN { no strict 'refs'; *from_json = \&FlashVideo::JSON::from_json; } 4214 4215 4216my $bitrates = { 4217 "low" => 250000, 4218 "medium" => 450000, 4219 "high" => 900000 }; 4220 4221sub find_video { 4222 my ($self, $browser, $embed_url, $prefs) = @_; 4223 if(!($browser->uri->as_string =~ m/video\/([0-9]*)/)){ 4224 die "No video id found in url"; 4225 } 4226 my ($video_id) = $1; 4227 my $info_url = "http://www.kanal5play.se/api/getVideo?format=FLASH&videoId=$video_id"; 4228 $browser->get($info_url); 4229 4230 if (!$browser->success){ 4231 die "Couldn't download $info_url: " . $browser->response->status_line; 4232 } 4233 4234 my $jsonstr = $browser->content; 4235 my $json = from_json($jsonstr); 4236 4237 my $name = $json->{program}->{name}; 4238 my $episode = $json->{episodeNumber}; 4239 my $season = $json->{seasonNumber}; 4240 my $filename = sprintf "%s - S%02dE%02d", $name, $season, $episode; 4241 my ($rtmp) = "rtmp://fl1.c00608.cdn.qbrick.com:1935/00608"; 4242 my ($playpath) = $json->{streams}[0]->{source}; 4243 4244 my $i; 4245 foreach $i (keys $json->{streams}) { 4246 my ($rate) = int($json->{streams}[$i]->{bitrate}); 4247 if($bitrates->{$prefs->{quality}} == $rate){ 4248 $playpath = $json->{streams}[$i]->{source}; 4249 } 4250 } 4251 return { 4252 flv => title_to_filename($filename, "flv"), 4253 rtmp => $rtmp, 4254 playpath => $playpath, 4255 swfVfy => "http://www.kanal5play.se/flash/StandardPlayer.swf" 4256 }; 4257 4258} 42591; 4260} 4261##} blib/lib/FlashVideo/Site/Kanal5play.pm 4262BEGIN { $INC{'FlashVideo/Site/Kidswb.pm'}++; } 4263# Part of get-flash-videos. See get_flash_videos for copyright. 4264##{ blib/lib/FlashVideo/Site/Kidswb.pm 4265{ 4266package FlashVideo::Site::Kidswb; 4267 4268use strict; 4269BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 4270BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 4271BEGIN { FlashVideo::JSON->import(); } # (added by utils/combine-perl.pl) 4272BEGIN { no strict 'refs'; *from_json = \&FlashVideo::JSON::from_json; } 4273 4274sub find_video { 4275 my($self, $browser, $embed_url, $prefs) = @_; 4276 4277 my $config_url = "http://staticswf.kidswb.com/franchise/digitalsmiths/wbkidsvideoplayer.xml"; 4278 my $mediaKey; 4279 if ($browser->uri->as_string =~ /\/video#.*\/([^\/]*)$/) { 4280 $mediaKey = $1; 4281 } else { 4282 die "Couldn't find flashvars param in " . $browser->uri->as_string; 4283 } 4284 4285 $browser->allow_redirects; 4286 $browser->get($config_url); 4287 if (!$browser->success) { 4288 die "Couldn't download config.xml $config_url: " . $browser->response->status_line; 4289 } 4290 4291 my $xml = from_xml($browser); 4292 my $domain = $xml->{mfs}->{url}; 4293 my $version = "v2"; 4294 my $account = $xml->{mfs}->{account}; 4295 my $partner = $xml->{mfs}->{partnerid}; 4296 4297 my $asset_url = "$domain/$version/$account/assets/$mediaKey/partner/$partner?format=json"; 4298 $browser->get($asset_url); 4299 if (!$browser->success) { 4300 die "Couldn't download asset file $asset_url: " . $browser->response->status_line; 4301 } 4302 4303 my $asset_data = from_json($browser->content); 4304 my $videos = $asset_data->{videos}; 4305 4306 my $title = title_to_filename($asset_data->{assetFields}->{seriesName} . " - " . $asset_data->{assetFields}->{title}); 4307 4308 my $video = $videos->{limelight700}; 4309 4310 my $rtmp = $video->{uri}; 4311 4312 return { 4313 flv => $title, 4314 rtmp => $rtmp, 4315 }; 4316} 4317 43181; 4319} 4320##} blib/lib/FlashVideo/Site/Kidswb.pm 4321BEGIN { $INC{'FlashVideo/Site/Last.pm'}++; } 4322# Part of get-flash-videos. See get_flash_videos for copyright. 4323##{ blib/lib/FlashVideo/Site/Last.pm 4324{ 4325package FlashVideo::Site::Last; 4326 4327use strict; 4328BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 4329BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 4330use URI::Escape; 4331 4332sub find_video { 4333 my ($self, $browser, $embed_url) = @_; 4334 4335 my($artist, $id) = $embed_url =~ m{/([^/]+)/\+videos/(\d+)}; 4336 my($title) = $browser->content =~ /<h1>([^<]+)/; 4337 4338 die "No video ID found" unless $id; 4339 4340 $browser->get("http://ext.last.fm/1.0/video/getplaylist.php?&vid=$id&artist=$artist"); 4341 4342 return $browser->content =~ /<location>([^<]+)/, title_to_filename($title); 4343} 4344 4345sub can_handle { 4346 my($self, $browser, $url) = @_; 4347 4348 return $url =~ /last\.fm/ && $url =~ m{\+video/\d{2,}}; 4349} 4350 43511; 4352} 4353##} blib/lib/FlashVideo/Site/Last.pm 4354BEGIN { $INC{'FlashVideo/Site/Liveleak.pm'}++; } 4355# Part of get-flash-videos. See get_flash_videos for copyright. 4356##{ blib/lib/FlashVideo/Site/Liveleak.pm 4357{ 4358package FlashVideo::Site::Liveleak; 4359 4360use strict; 4361BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 4362BEGIN { no strict 'refs'; *extract_title = \&FlashVideo::Utils::extract_title; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 4363 4364sub find_video { 4365 my ($self, $browser, $embed_url) = @_; 4366 4367 my $file_embed_tag; 4368 if ($browser->content =~ /file_embed_tag(?:%3D|=)(\w+)\W/) { 4369 $file_embed_tag = $1; 4370 } 4371 else { 4372 die "Unable to get file_embed_tag"; 4373 } 4374 4375 $browser->get("http://www.liveleak.com/playlist_new.php?file_embed_tag=$file_embed_tag"); 4376 4377 if (!$browser->success) { 4378 die "Couldn't download LiveLeak playlist: " . $browser->response->status_line(); 4379 } 4380 4381 my $video_url; 4382 if ($browser->content =~ m'<location>(http://.*?)</location>') { 4383 $video_url = $1; 4384 } 4385 else { 4386 die "Unable to extract LiveLeak video URL"; 4387 } 4388 4389 if (my $redirected_url = $browser->head($video_url)->header('Location')) { 4390 $video_url = $redirected_url; 4391 } 4392 4393 $browser->back(); 4394 4395 my $title; 4396 if ($browser->content =~ m'<h4 id="s_hd">(.*?)</h4>') { 4397 $title = $1; 4398 } 4399 else { 4400 $title = extract_title($browser); 4401 } 4402 4403 return $video_url, title_to_filename($title); 4404} 4405 44061; 4407} 4408##} blib/lib/FlashVideo/Site/Liveleak.pm 4409BEGIN { $INC{'FlashVideo/Site/Megaporn.pm'}++; } 4410# Part of get-flash-videos. See get_flash_videos for copyright. 4411BEGIN { $INC{'FlashVideo/Site/Megavideo.pm'}++; } 4412# Part of get-flash-videos. See get_flash_videos for copyright. 4413##{ blib/lib/FlashVideo/Site/Megavideo.pm 4414{ 4415package FlashVideo::Site::Megavideo; 4416 4417use strict; 4418BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 4419BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 4420use URI::Escape; 4421 4422my %sites = ( 4423 Megavideo => "megavideo.com", 4424 Megaporn => "megaporn.com/video", 4425); 4426 4427sub find_video { 4428 my ($self, $browser) = @_; 4429 4430 my $site = $sites{($self =~ /::([^:]+)$/)[0]}; 4431 4432 my $v; 4433 if ($browser->content =~ /\.v\s*=\s*['"]([^"']+)/ 4434 || $browser->uri =~ /v=([^&]+)/ 4435 || $browser->response->header("Location") =~ /v=([^&]+)/) { 4436 $v = $1; 4437 } else { 4438 die "Couldn't extract video ID from page"; 4439 } 4440 4441 my $xml = "http://www.$site/xml/videolink.php?v=$v"; 4442 $browser->get($xml); 4443 4444 die "Unable to get video infomation" unless $browser->response->is_success; 4445 4446 my $k1 = ($browser->content =~ /k1="(\d+)/)[0]; 4447 my $k2 = ($browser->content =~ /k2="(\d+)/)[0]; 4448 my $un = ($browser->content =~ /un="([^"]+)/)[0]; 4449 my $s = ($browser->content =~ /\ss="(\d+)/)[0]; 4450 4451 my $title = uri_unescape(($browser->content =~ /title="([^"]+)/)[0]); 4452 my $filename = title_to_filename($title); 4453 4454 my $url = "http://www$s.$site/files/" . _decrypt($un, $k1, $k2) . "/"; 4455 4456 return $url, $filename; 4457} 4458 4459sub _decrypt { 4460 my($un, $k1, $k2) = @_; 4461 4462 my @c = split //, join "", 4463 map { substr unpack("B8", pack "h", $_), 4 } split //, $un; 4464 4465 my @iv; 4466 my $i = 0; 4467 while($i < 384) { 4468 $k1 = ($k1 * 11 + 77213) % 81371; 4469 $k2 = ($k2 * 17 + 92717) % 192811; 4470 $iv[$i] = ($k1 + $k2) % 128; 4471 $i++; 4472 } 4473 4474 $i = 256; 4475 while($i >= 0) { 4476 my $a = $iv[$i]; 4477 my $b = $i-- % 128; 4478 4479 ($c[$a], $c[$b]) = ($c[$b], $c[$a]); 4480 } 4481 4482 $i = 0; 4483 while($i < 128) { 4484 $c[$i] ^= $iv[$i + 256] & 1; 4485 $i++; 4486 } 4487 4488 $i = 0; 4489 my $c = ""; 4490 while($i < @c) { 4491 $c .= unpack "h", pack "B8", "0000" . join "", @c[$i .. ($i + 4)]; 4492 $i += 4; 4493 } 4494 4495 return $c; 4496} 4497 44981; 4499} 4500##} blib/lib/FlashVideo/Site/Megavideo.pm 4501##{ blib/lib/FlashVideo/Site/Megaporn.pm 4502{ 4503package FlashVideo::Site::Megaporn; 4504 4505use strict; 4506BEGIN { FlashVideo::Site::Megavideo->import(); } # (added by utils/combine-perl.pl) 4507use base 'FlashVideo::Site::Megavideo'; 4508 45091; 4510} 4511##} blib/lib/FlashVideo/Site/Megaporn.pm 4512BEGIN { $INC{'FlashVideo/Site/Metacafe.pm'}++; } 4513# Part of get-flash-videos. See get_flash_videos for copyright. 4514##{ blib/lib/FlashVideo/Site/Metacafe.pm 4515{ 4516package FlashVideo::Site::Metacafe; 4517 4518use strict; 4519BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 4520BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *extract_title = \&FlashVideo::Utils::extract_title; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 4521use URI::Escape; 4522 4523sub find_video { 4524 my ($self, $browser) = @_; 4525 4526 if ($browser->response->header("Location") =~ /Openx/) { 4527 my $filter = "http://www.metacafe.com/f/index.php?inputType=filter&controllerGroup=user&filters=0&prevURL=" . $browser->uri->path; 4528 debug "Disabling family filter by getting $filter"; 4529 4530 $browser->allow_redirects; 4531 $browser->get($filter); 4532 } 4533 4534 my $url; 4535 if ($browser->content =~ m'mediaURL=(http.+?)&') { 4536 $url = uri_unescape($1); 4537 } else { 4538 die "Couldn't find mediaURL parameter."; 4539 } 4540 4541 if ($browser->content =~ m'gdaKey=(.+?)&') { 4542 $url .= "?__gda__=" . uri_unescape($1); 4543 } else { 4544 } 4545 4546 my $filename = title_to_filename(extract_title($browser)); 4547 4548 return ($url, $filename); 4549} 4550 45511; 4552} 4553##} blib/lib/FlashVideo/Site/Metacafe.pm 4554BEGIN { $INC{'FlashVideo/Site/Mitworld.pm'}++; } 4555# Part of get-flash-videos. See get_flash_videos for copyright. 4556##{ blib/lib/FlashVideo/Site/Mitworld.pm 4557{ 4558package FlashVideo::Site::Mitworld; 4559 4560use strict; 4561BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 4562BEGIN { no strict 'refs'; *extract_title = \&FlashVideo::Utils::extract_title; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 4563 4564sub find_video { 4565 my ($self, $browser) = @_; 4566 4567 my($title) = $browser->content =~ m{id="video-meta">\s*<h2>(.*?)</h2>}s; 4568 if(!$title) { 4569 $title = extract_title($browser); 4570 $title =~ s/\|.*//; 4571 } 4572 4573 my($host) = $browser->content =~ m{host:\s*"(.*?)"}; 4574 my($flv) = $browser->content =~ m{flv:\s*"(.*?)"}; 4575 4576 return { 4577 rtmp => "rtmp://$host/ondemand/ampsflash/$flv?_fcs_vhost=$host", 4578 flv => title_to_filename($title) 4579 }; 4580} 4581 45821; 4583} 4584##} blib/lib/FlashVideo/Site/Mitworld.pm 4585BEGIN { $INC{'FlashVideo/Site/Mofosex.pm'}++; } 4586# Part of get-flash-videos. See get_flash_videos for copyright. 4587##{ blib/lib/FlashVideo/Site/Mofosex.pm 4588{ 4589package FlashVideo::Site::Mofosex; 4590 4591use strict; 4592BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 4593BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 4594 4595sub find_video { 4596 my ($self, $browser, $embed_url) = @_; 4597 4598 my $filename = title_to_filename($browser->content =~ /<title>(.*?)<\//); 4599 4600 $browser->allow_redirects; 4601 4602 my $playlist = ($browser->content =~ /videoPath=(.+?)%26page/)[0]; 4603 $browser->get($playlist); 4604 4605 my $url = ($browser->content =~ /<url>(.+?)<\/url>/)[0]; 4606 4607 return $url, $filename; 4608} 4609 46101; 4611} 4612##} blib/lib/FlashVideo/Site/Mofosex.pm 4613BEGIN { $INC{'FlashVideo/Site/Msn.pm'}++; } 4614# Part of get-flash-videos. See get_flash_videos for copyright. 4615##{ blib/lib/FlashVideo/Site/Msn.pm 4616{ 4617package FlashVideo::Site::Msn; 4618 4619use strict; 4620BEGIN { FlashVideo::Site::Bing->import(); } # (added by utils/combine-perl.pl) 4621use base 'FlashVideo::Site::Bing'; 4622 46231; 4624} 4625##} blib/lib/FlashVideo/Site/Msn.pm 4626BEGIN { $INC{'FlashVideo/Site/Msnbc.pm'}++; } 4627# Part of get-flash-videos. See get_flash_videos for copyright. 4628##{ blib/lib/FlashVideo/Site/Msnbc.pm 4629{ 4630package FlashVideo::Site::Msnbc; 4631 4632use strict; 4633BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 4634BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 4635 4636sub find_video { 4637 my ($self, $browser, $embed_url) = @_; 4638 4639 $browser->allow_redirects; 4640 4641 my $id; 4642 my $location; 4643 if ($embed_url =~ /(.+\/id\/)([0-9]+)\/vp\/.+#([0-9]+)/) { 4644 $location = $1; 4645 $id = $3; 4646 } elsif ($embed_url =~ /(.+\/id\/)([0-9]+)\/vp\/([0-9]+)/) { 4647 $location = $1; 4648 $id = $3; 4649 } elsif ($embed_url =~ /(.+\/id\/)([0-9]+)\/.+#([0-9]+)/) { 4650 $location = $1; 4651 $id = $3; 4652 } elsif ($embed_url =~ /(.+\/id\/)([0-9]+)\/#([0-9]+)/) { 4653 $location = $1; 4654 $id = $3; 4655 } 4656 die "Unable to find location and videoid" unless $location and $id; 4657 4658 $browser->get($location . $id . '/displaymode/1219/'); # http://today.msnbc.msn.com/id/$id/displaymode/1219/ 4659 4660 my $xml = from_xml($browser->content); 4661 4662 my $title; 4663 my $url; 4664 if ($xml->{video}->{docid} eq $id) { 4665 $title = $xml->{video}->{title}; 4666 foreach my $media (@{$xml->{video}->{media}}) { 4667 if ($media->{type} =~ /flashVideo$/i) { 4668 $url = $media->{content}; 4669 last; #prefer http get over rtmp 4670 } elsif ($media->{type} =~ /flashVideoStream$/i) { 4671 $browser->get($media->{content}); 4672 if ($browser->content =~ /<FlashLink>(.+)<\/FlashLink>/i) { 4673 $url = $1; #rtmp 4674 } 4675 } 4676 } 4677 } 4678 die "Unable to extract video url" unless $url; 4679 4680 if ($url =~ /^rtmp/i) { 4681 return { 4682 rtmp => $url, 4683 flv => title_to_filename($title) 4684 }; 4685 } 4686 4687 return $url, title_to_filename($title); 4688} 4689 46901; 4691} 4692##} blib/lib/FlashVideo/Site/Msnbc.pm 4693BEGIN { $INC{'FlashVideo/Site/Mtvnservices.pm'}++; } 4694# Part of get-flash-videos. See get_flash_videos for copyright. 4695##{ blib/lib/FlashVideo/Site/Mtvnservices.pm 4696{ 4697package FlashVideo::Site::Mtvnservices; 4698 4699 4700use strict; 4701BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 4702BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *error = \&FlashVideo::Utils::error; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *swfhash = \&FlashVideo::Utils::swfhash; *from_xml = \&FlashVideo::Utils::from_xml; } 4703use URI::Escape; 4704 4705my $MTVN_URL = qr{http://\w+.mtvnservices.com/(?:\w+/)?mgid:[a-z0-9:.\-_]+}; 4706my $MTVN_ALT_URL = qr{mgid:[a-z0-9:.\-_]+}; 4707 4708sub find_video { 4709 my ($self, $browser, $embed_url) = @_; 4710 4711 my $page_url = $browser->uri->as_string; 4712 4713 if($embed_url !~ $MTVN_URL) { 4714 if($browser->content =~ m!($MTVN_URL)!) { 4715 $embed_url = $1; 4716 } elsif($browser->content =~ m!($MTVN_ALT_URL)!) { 4717 $embed_url = "http://media.mtvnservices.com/$1"; 4718 } else { 4719 die "Unable to find embedding URL"; 4720 } 4721 } 4722 4723 $browser->get($embed_url); 4724 die "Unable to get embed URL" unless $browser->response->code =~ /^30\d$/; 4725 4726 my %param; 4727 my $location = $browser->response->header("Location"); 4728 for(split /&/, (split /\?/, $location)[-1]) { 4729 my($n, $v) = split /=/; 4730 $param{$n} = uri_unescape($v); 4731 } 4732 4733 die "No config_url/id found\n" unless $param{CONFIG_URL}; 4734 4735 $browser->get($param{CONFIG_URL}); 4736 my $xml = from_xml_urlfix($browser); 4737 4738 if($xml->{player}->{feed} && !ref $xml->{player}->{feed}) { 4739 my $feed = uri_unescape($xml->{player}->{feed}); 4740 $feed =~ s/\{([^}]+)\}/$param{$1}/g; 4741 4742 $browser->get($feed); 4743 4744 return $self->handle_feed($browser->content, $browser, $page_url, $param{uri}); 4745 } elsif(ref $xml->{player}->{feed}->{rss}) { 4746 return $self->handle_feed($xml->{player}->{feed}->{rss}, $browser, $page_url, $param{uri}); 4747 } else { 4748 die "Unable to find feed\n"; 4749 } 4750} 4751 4752sub handle_full_episode { 4753 my($self, $items, $filename, $browser, $page_url, $uri) = @_; 4754 4755 my @rtmpdump_commands; 4756 4757 debug "Handling full episode"; 4758 4759 foreach (@$items) { 4760 my $item = $_; 4761 4762 my $affect_counters = (grep { $_->{scheme} eq "urn:mtvn:affect_counters" } @{$item->{"media:group"}->{"media:category"}})[0]; 4763 my $iscommercial = 0; 4764 if (defined $affect_counters && $affect_counters->{content} eq 'false') { 4765 $iscommercial = 1; 4766 } 4767 4768 if (!$iscommercial) { 4769 my $mediagen_url = $item->{"media:group"}->{"media:content"}->{url}; 4770 die "Unable to find mediagen URL\n" unless $mediagen_url; 4771 4772 $browser->get($mediagen_url); 4773 my $xml = from_xml_urlfix($browser); 4774 4775 my $rendition = (grep { $_->{rendition} } ref $xml->{video}->{item} eq 'ARRAY' 4776 ? @{$xml->{video}->{item}} : $xml->{video}->{item})[0]->{rendition}; 4777 $rendition = [ $rendition ] unless ref $rendition eq 'ARRAY'; 4778 4779 my $url = (sort { $b->{bitrate} <=> $a->{bitrate} } @$rendition)[0]->{src}; 4780 4781 my $mediagen_id; 4782 if($mediagen_url =~ /mediaGenEntertainment\.jhtml\?uri=([^&]+).*$/){ 4783 $mediagen_id = $1; 4784 } else { 4785 $mediagen_id = $mediagen_url; 4786 } 4787 4788 $browser->allow_redirects; 4789 4790 push @rtmpdump_commands, { 4791 flv => title_to_filename($item->{"media:group"}->{"media:title"}), 4792 rtmp => $url, 4793 pageUrl => $item->{"link"}, 4794 swfhash($browser, "http://media.mtvnservices.com/" . $mediagen_id) 4795 }; 4796 } 4797 } 4798 4799 return \@rtmpdump_commands; 4800} 4801 4802sub handle_clip { 4803 my($self, $items, $filename, $browser, $page_url, $uri) = @_; 4804 4805 debug "Handling clip"; 4806 4807 my $item = ref $items eq 'ARRAY' ? 4808 (grep { $_->{guid}->{content} eq $uri } @$items)[0] : 4809 $items; 4810 4811 my $mediagen_url = $item->{"media:group"}->{"media:content"}->{url}; 4812 die "Unable to find mediagen URL\n" unless $mediagen_url; 4813 4814 $browser->get($mediagen_url); 4815 my $xml = from_xml_urlfix($browser); 4816 4817 my $rendition = (grep { $_->{rendition} } ref $xml->{video}->{item} eq 'ARRAY' 4818 ? @{$xml->{video}->{item}} : $xml->{video}->{item})[0]->{rendition}; 4819 $rendition = [ $rendition ] unless ref $rendition eq 'ARRAY'; 4820 4821 my $url = (sort { $b->{bitrate} <=> $a->{bitrate} } @$rendition)[0]->{src}; 4822 4823 my $mediagen_id; 4824 if($mediagen_url =~ /mediaGenEntertainment\.jhtml\?uri=([^&]+).*$/){ 4825 $mediagen_id = $1; 4826 } else { 4827 $mediagen_id = $mediagen_url; 4828 } 4829 4830 $browser->allow_redirects; 4831 4832 if($url =~ /^rtmpe?:/) { 4833 return { 4834 flv => $filename, 4835 rtmp => $url, 4836 pageUrl => $page_url, 4837 swfhash($browser, "http://media.mtvnservices.com/" . $mediagen_id) 4838 }; 4839 } else { 4840 return $url, $filename; 4841 } 4842} 4843 4844sub handle_feed { 4845 my($self, $feed, $browser, $page_url, $uri) = @_; 4846 4847 my $xml = ref $feed ? $feed : from_xml_urlfix($feed); 4848 4849 my $filename = title_to_filename($xml->{channel}->{title}); 4850 4851 my $items = $xml->{channel}->{item}; 4852 my $categories = ref $items eq 'ARRAY' ? @$items[0]->{"media:group"}->{"media:category"} : $items->{"media:group"}->{"media:category"}; 4853 4854 if (ref $categories eq 'ARRAY' && ( 4855 (grep { $_->{scheme} eq "urn:mtvn:display:seo" } @$categories)[0]->{content} eq "" || 4856 (grep { $_->{scheme} eq "urn:mtvn:content_type" } @$categories)[0]->{content} eq "Full Episode" || 4857 (grep { $_->{scheme} eq "urn:mtvn:content_type" } @$categories)[0]->{content} eq "full_episode_segment")) { 4858 return $self->handle_full_episode($items, $filename, $browser, $page_url, $uri); 4859 } else { 4860 return $self->handle_clip($items, $filename, $browser, $page_url, $uri); 4861 } 4862} 4863 4864sub can_handle { 4865 my($self, $browser, $url) = @_; 4866 4867 return $browser->content =~ /mtvnservices\.com/i; 4868} 4869 4870 4871sub from_xml_urlfix { 4872 my($xmltext) = @_; 4873 $xmltext =~ s/&(?!amp;)/&/g; # too lax? 4874 return from_xml($xmltext); 4875} 4876 48771; 4878} 4879##} blib/lib/FlashVideo/Site/Mtvnservices.pm 4880BEGIN { $INC{'FlashVideo/Site/Muzu.pm'}++; } 4881# Part of get-flash-videos. See get_flash_videos for copyright. 4882##{ blib/lib/FlashVideo/Site/Muzu.pm 4883{ 4884package FlashVideo::Site::Muzu; 4885 4886use strict; 4887BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 4888BEGIN { no strict 'refs'; *error = \&FlashVideo::Utils::error; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 4889use HTML::Entities; 4890 4891sub find_video { 4892 my ($self, $browser) = @_; 4893 4894 if ($browser->response->code == 302) { 4895 $browser->allow_redirects; 4896 $browser->get($browser->response->header('Location')) 4897 } 4898 4899 $browser->content =~ /id="trackHeading">(.*?)</; 4900 my $title = $1; 4901 4902 if (!$title) { 4903 $browser->content =~ /id="videosPageMainTitleH1">(.*?)</s; 4904 $title = $1; 4905 } 4906 4907 my $filename = title_to_filename(decode_entities($title)); 4908 4909 my $flashvars = ($browser->content =~ m'flashvars:(?:\s+getPlayerData\(\)\s+\+\s+)?"([^"]+)')[0]; 4910 die "Unable to extract flashvars" unless $flashvars; 4911 4912 my %map = ( 4913 networkId => "id", 4914 assetId => "assetId", 4915 vidId => "assetId", 4916 startChannel => "playlistId", 4917 ); 4918 4919 my $playAsset = "http://www.muzu.tv/player/playAsset/?"; 4920 for(split /&/, $flashvars) { 4921 my($n, $v) = split /=/; 4922 $playAsset .= "$map{$n}=$v&" if exists $map{$n}; 4923 } 4924 4925 $browser->get($playAsset); 4926 die "Unable to get $playAsset" if $browser->response->is_error; 4927 4928 my $url = ($browser->content =~ /src="([^"]+)/)[0]; 4929 $url = decode_entities($url); 4930 die "Unable to find video URL" unless $url; 4931 4932 if($url =~ /^rtmp:/) { 4933 my($playpath) = $url =~ m{/([^/]+)$}; 4934 4935 return { 4936 flv => $filename, 4937 rtmp => $url, 4938 playpath => $playpath, 4939 $url =~ /live/ ? (live => 1) : () 4940 }; 4941 4942 } else { 4943 return $url, $filename; 4944 } 4945} 4946 49471; 4948} 4949##} blib/lib/FlashVideo/Site/Muzu.pm 4950BEGIN { $INC{'FlashVideo/Site/Mylifetime.pm'}++; } 4951# Part of get-flash-videos. See get_flash_videos for copyright. 4952##{ blib/lib/FlashVideo/Site/Mylifetime.pm 4953{ 4954package FlashVideo::Site::Mylifetime; 4955 4956use strict; 4957BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 4958BEGIN { no strict 'refs'; } 4959BEGIN { FlashVideo::Site::Brightcove->import(); } # (added by utils/combine-perl.pl) 4960use base 'FlashVideo::Site::Brightcove'; 4961 4962my $JS_RE = qr/displayFlash\(/; 4963 4964sub find_video { 4965 my($self, $browser, $embed_url) = @_; 4966 4967 my($player_id, $video_id) = $browser->content =~ /$JS_RE\s*"(\d+)",\s*"(\d+)"/; 4968 die "Unable to extract video ids" unless $video_id; 4969 4970 return $self->amfgateway($browser, $player_id, { videoId => $video_id }); 4971} 4972 4973sub can_handle { 4974 my($self, $browser, $url) = @_; 4975 4976 return $browser->content =~ $JS_RE; 4977} 4978 49791; 4980} 4981##} blib/lib/FlashVideo/Site/Mylifetime.pm 4982BEGIN { $INC{'FlashVideo/Site/Myvideo.pm'}++; } 4983# Part of get-flash-videos. See get_flash_videos for copyright. 4984##{ blib/lib/FlashVideo/Site/Myvideo.pm 4985{ 4986package FlashVideo::Site::Myvideo; 4987 4988use strict; 4989BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 4990BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 4991 4992sub find_video { 4993 my ($self, $browser, $embed_url) = @_; 4994 4995 my $video_url; 4996 4997 if ($browser->content =~ m{<link rel='image_src' href='(http://[^'"]+)'}) { 4998 $video_url = $1; 4999 } 5000 5001 $video_url =~ s|thumbs/||; 5002 $video_url =~ s|_\d\.jpg$|.flv|; 5003 5004 my $title = (split /\//, $browser->uri->as_string)[-1]; 5005 5006 return $video_url, title_to_filename($title); 5007} 5008 50091; 5010} 5011##} blib/lib/FlashVideo/Site/Myvideo.pm 5012BEGIN { $INC{'FlashVideo/Site/Nasa.pm'}++; } 5013# Part of get-flash-videos. See get_flash_videos for copyright. 5014##{ blib/lib/FlashVideo/Site/Nasa.pm 5015{ 5016package FlashVideo::Site::Nasa; 5017 5018use strict; 5019BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 5020BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 5021BEGIN { FlashVideo::JSON->import(); } # (added by utils/combine-perl.pl) 5022BEGIN { no strict 'refs'; *from_json = \&FlashVideo::JSON::from_json; } 5023 5024sub find_video { 5025 my ($self, $browser, $embed_url) = @_; 5026 5027 my $uri = $browser->uri(); 5028 my $path = $uri->path(); 5029 $path =~ s/index\.html//; # strip the index.htm at the end of the path. 5030 $path = $path . "vmixVideoLanding2.js"; # specify the javascript src 5031 5032 debug "Nasa videogallery query is " . $uri->query(); 5033 my ($media_id) = $uri->query() =~ m/media_id=(\d+)/; 5034 5035 die "Nasa support requires 'media_id=nnnnnnnn' in the query" unless $media_id; 5036 5037 $uri->path($path); # Change path to javascript src 5038 $uri->query(undef()); # Remove the query 5039 5040 info "Downloading video source instructions at " . $uri; 5041 $browser->get($uri); 5042 5043 die "Could not locate video source" unless $browser->success(); 5044 5045 my $videojs = $browser->content(); # content is javascript 5046 5047 my ($api_url_host) = $browser->content() =~ m{var +api_url *= *'([^']*)' *;}; 5048 die "Could not extract video server" unless $api_url_host; 5049 5050 my ($atoken) = $browser->content() =~ m{var +atoken *= *'([^']*)' *;}; 5051 5052 my $query = 'http://' . $api_url_host . '/apis/media.php?action=getMedia&export=JSONP&media_id=' . $media_id . '&atoken=' . $atoken . '&callback=loadCurrentVideo1'; 5053 5054 info "Downloading video details from http://" . $api_url_host; 5055 $browser->get($query); 5056 die "Could not get video details" unless $browser->success(); 5057 5058 my $result = from_json($browser->content()); 5059 5060 my $url = $result->{url}; 5061 die "Could not extract video url" unless $url; 5062 $url =~ s/\/core\//\/core-dl\//; 5063 5064 my $filename = $result->{title}; 5065 $filename = title_to_filename($filename, "mp4"); 5066 5067 return $url, $filename; 5068} 5069 50701; 5071} 5072##} blib/lib/FlashVideo/Site/Nasa.pm 5073BEGIN { $INC{'FlashVideo/Site/Nbc.pm'}++; } 5074# Part of get-flash-videos. See get_flash_videos for copyright. 5075##{ blib/lib/FlashVideo/Site/Nbc.pm 5076{ 5077package FlashVideo::Site::Nbc; 5078 5079use strict; 5080BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 5081BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 5082use MIME::Base64; 5083 5084sub find_video { 5085 my ($self, $browser, $embed_url) = @_; 5086 5087 my $has_amf_packet = eval { require Data::AMF::Packet }; 5088 if (!$has_amf_packet) { 5089 die "Must have Data::AMF::Packet installed to download Nbc videos"; 5090 } 5091 5092 5093 my $video_id; 5094 if ($browser->uri->as_string =~ /\/([0-9]+)\//) { 5095 $video_id = $1; 5096 } 5097 5098 my $packet = Data::AMF::Packet->deserialize(decode_base64("AAAAAAABABZnZXRDbGlwSW5mby5nZXRDbGlwQWxsAAIvMQAAAB8KAAAABAIABzEyMjc2MTECAAJVUwIAAzYzMgIAAi0xCg==")); 5099 5100 $packet->messages->[0]->{value}->[0] = $video_id; 5101 5102 if($self->debug) { 5103 require Data::Dumper; 5104 debug Data::Dumper::Dumper($packet); 5105 } 5106 5107 my $data = $packet->serialize; 5108 5109 $browser->post( 5110 "http://video.nbcuni.com/amfphp/gateway.php", 5111 Content_Type => "application/x-amf", 5112 Content => $data 5113 ); 5114 5115 die "Failed to post to Nbc AMF gateway" 5116 unless $browser->response->is_success; 5117 5118 debug $browser->content; 5119 5120 5121 my($clipurl) = $browser->content =~ /clipurl.{0,5}(nbc[^\0]+)/; 5122 5123 my($title) = $browser->content =~ /headline.{1,3}([^\0]+)/; 5124 5125 debug $clipurl; 5126 debug $title; 5127 5128 $browser->get("http://video.nbcuni.com/$clipurl"); 5129 my $xml = from_xml($browser); 5130 my $video_path = $xml->{body}->{switch}->{ref}->{src}; 5131 5132 $browser->get("http://videoservices.nbcuni.com/player/config?configId=17010&clear=true"); # I don't know what configId means but it seems to be generic 5133 my $xml = from_xml($browser); 5134 my $app = $xml->{akamaiAppName}; 5135 my $host = $xml->{akamaiHostName}; 5136 5137 $browser->get("http://$host/fcs/ident"); 5138 my $xml = from_xml($browser); 5139 my $ip = $xml->{ip}; 5140 my $port = "1935"; 5141 5142 my $rtmpurl = "rtmp://$ip:$port/$app/$video_path"; 5143 5144 return { 5145 rtmp => $rtmpurl, 5146 swfUrl => "http://www.nbc.com/[[IMPORT]]/video.nbcuni.com/outlet/extensions/inext_video_player/video_player_extension.swf?4.5.3", 5147 tcUrl => "rtmp://$ip:$port/$app?_fcs_vhost=$host", 5148 flv => title_to_filename($title) 5149 }; 5150} 5151 51521; 5153} 5154##} blib/lib/FlashVideo/Site/Nbc.pm 5155BEGIN { $INC{'FlashVideo/Site/Nfb.pm'}++; } 5156# Part of get-flash-videos. See get_flash_videos for copyright. 5157################################################# 5158# 5159# This file was automatically generated by utils/combine-perl.pl 5160# You should edit the original files, not this 5161# combined version. 5162# 5163# The original files are available at: 5164# http://github.com/monsieurvideo/get-flash-videos 5165# 5166################################################# 5167# Except the CCR bits, thanks to Fogerty for those. 5168##{ blib/lib/FlashVideo/Site/Nfb.pm 5169{ 5170package FlashVideo::Site::Nfb; 5171 5172use strict; 5173BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 5174BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 5175 5176sub find_video { 5177 my ($self, $browser, $embed_url, $prefs) = @_; 5178 5179 my($refer, $cURL) = $browser->content =~ /<link rel="video_src" href="([^?]+)\?configURL=([^&]+)&/; 5180 5181 $browser->post( 5182 $cURL, 5183 "X-NFB-Referer" => $refer, 5184 Content_Type => "application/x-www-form-urlencoded", 5185 Content => "getConfig=true", 5186 ); 5187 5188 if (!$browser->success) { 5189 die "Getting config info failed: " . $browser->response->status_line(); 5190 } 5191 5192 my $xml = from_xml($browser->content); 5193 5194 my $media; 5195 foreach (@{$xml->{player}->{stream}->{media}}) { 5196 if ($_->{"type"} eq "video") { 5197 $media = $_; 5198 last; 5199 } 5200 } 5201 5202 my $title = $media->{title}; 5203 5204 5205 my @assets = sort { _get_quality_from_url($b->{default}->{url}) <=> _get_quality_from_url($a->{default}->{url}) } 5206 (@{$media->{assets}->{asset}}); 5207 5208 if (!@assets) { 5209 die "Couldn't find any streams in the config file"; 5210 } 5211 5212 my $quality = $prefs->{quality}; 5213 my $asset; 5214 if ($quality eq "high") { 5215 $asset = $assets[0]; 5216 } elsif ($quality eq "low") { 5217 $asset = $assets[-1]; 5218 } elsif ($quality eq "medium") { 5219 if (scalar(@assets) > 1) { 5220 $asset = $assets[1]; 5221 } else { 5222 $asset = $assets[0]; 5223 } 5224 } else { 5225 die "Unknown quality setting"; 5226 } 5227 5228 my $rtmp_url = $asset->{default}->{streamerURI}; 5229 my($host, $app) = $rtmp_url =~ m'rtmp://([^/]+)/(\w+)'; 5230 my $playpath = $asset->{default}->{url}; 5231 5232 return { 5233 flv => title_to_filename($title), 5234 rtmp => $rtmp_url, 5235 app => $app, 5236 playpath => $playpath 5237 }; 5238} 5239 5240sub _get_quality_from_url { 5241 my($url) = @_; 5242 5243 if ($url =~ m'/streams/[A-Z](\d+)([A-Z])') { 5244 my ($size, $units) = ($1, $2); 5245 5246 $size *= 1024 if $units eq 'M'; 5247 5248 return $size; 5249 } 5250} 5251 52521; 5253} 5254##} blib/lib/FlashVideo/Site/Nfb.pm 5255BEGIN { $INC{'FlashVideo/Site/Nick.pm'}++; } 5256# Part of get-flash-videos. See get_flash_videos for copyright. 5257##{ blib/lib/FlashVideo/Site/Nick.pm 5258{ 5259package FlashVideo::Site::Nick; 5260 5261use strict; 5262BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 5263BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *swfhash = \&FlashVideo::Utils::swfhash; *from_xml = \&FlashVideo::Utils::from_xml; } 5264use URI::Escape; 5265 5266sub find_video { 5267 my ($self, $browser, $embed_url) = @_; 5268 5269 5270 my $page_url = $browser->uri->as_string; 5271 5272 my $title; 5273 if($browser->content =~ /<span content=["']([\w \.:]+)["'] property=["']media:title["']\/>/) { 5274 $title = $1; 5275 } else { 5276 $title = "nothing"; 5277 } 5278 5279 my $cmsId; 5280 if($browser->content =~ /KIDS\.add\("cmsId", "(\d+)"\);/) { 5281 $cmsId = $1; 5282 } else { 5283 die "Couldn't get the cmsId."; 5284 } 5285 5286 my $site; 5287 if($browser->content =~ /KIDS\.add\(["']site["'], ["']([\w\.]+)["']\);/) { 5288 $site = lc($1); 5289 } else { 5290 die "Couldn't get the site."; 5291 } 5292 5293 my $type; 5294 if($browser->content =~ /KIDS\.add\(["']type["'], ["']([a-z]+)["']\);/) { 5295 $type = $1; 5296 } else { 5297 $type = "video"; 5298 } 5299 5300 my $uri = "mgid:cms:$type:$site:$cmsId"; 5301 5302 $browser->get("http://www.nick.com/dynamo/video/data/mediaGen.jhtml?mgid=$uri"); 5303 my $xml = from_xml($browser->content); 5304 my $rtmp_url = $xml->{video}->{item}[0]->{rendition}[0]->{src}; 5305 5306 return { 5307 rtmp => $rtmp_url, 5308 flv => title_to_filename($title), 5309 pageUrl => $page_url, 5310 swfhash($browser, "http://media.nick.com/" . $uri) 5311 }; 5312} 5313 5314sub can_handle { 5315 my($self, $browser) = @_; 5316 return $browser->content =~ /<script src=["']http:\/\/media.nick.com\/player\/scripts\/mtvn_player_control\.1\.0\.1\.js["']/; 5317} 5318 53191; 5320} 5321##} blib/lib/FlashVideo/Site/Nick.pm 5322BEGIN { $INC{'FlashVideo/Site/Nicovideo.pm'}++; } 5323# Part of get-flash-videos. See get_flash_videos for copyright. 5324##{ blib/lib/FlashVideo/Site/Nicovideo.pm 5325{ 5326package FlashVideo::Site::Nicovideo; 5327 5328use strict; 5329BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 5330BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 5331use URI::Escape; 5332 5333sub find_video { 5334 my ($self, $browser, $embed_url) = @_; 5335 my $id = ($embed_url =~ /([ns]m\d+)/)[0]; 5336 die "No ID found\n" unless $id; 5337 5338 my $base = "http://ext.nicovideo.jp/thumb_watch/$id"; 5339 5340 if($embed_url !~ /ext\.nicovideo\.jp\/thumb_watch/) { 5341 $embed_url = "$base?w=472&h=374&n=1"; 5342 } 5343 5344 $browser->get($embed_url); 5345 my $playkey = ($browser->content =~ /'thumbPlayKey': '([^']+)/)[0]; 5346 die "No playkey found\n" unless $playkey; 5347 5348 my $title = ($browser->content =~ /title: '([^']+)'/)[0]; 5349 $title =~ s/\\u([a-f0-9]{1,5})/chr hex $1/eg; 5350 5351 $browser->get($base . "/$playkey"); 5352 my $url = uri_unescape(($browser->content =~ /url=([^&]+)/)[0]); 5353 5354 return $url, title_to_filename($title, $id =~ /^nm/ ? "swf" : "flv"); 5355} 5356 53571; 5358} 5359##} blib/lib/FlashVideo/Site/Nicovideo.pm 5360BEGIN { $INC{'FlashVideo/Site/Ooyala.pm'}++; } 5361# Part of get-flash-videos. See get_flash_videos for copyright. 5362##{ blib/lib/FlashVideo/Site/Ooyala.pm 5363{ 5364package FlashVideo::Site::Ooyala; 5365 5366use strict; 5367BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 5368BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *json_unescape = \&FlashVideo::Utils::json_unescape; } 5369BEGIN { FlashVideo::JSON->import(); } # (added by utils/combine-perl.pl) 5370BEGIN { no strict 'refs'; *from_json = \&FlashVideo::JSON::from_json; } 5371use File::Basename; 5372use HTML::Entities; 5373use URI::Escape; 5374use Data::Dumper; 5375 5376sub find_video { 5377 my ($self, $browser, $embed_url, $prefs) = @_; 5378 5379 debug $embed_url; 5380 5381 my ($player_js) = uri_unescape( 5382 decode_entities( 5383 $browser->content =~ m{<script src=["'](http://player\.ooyala\.com/player\.js[^'"]*)['"]>} 5384 ) 5385 ); 5386 5387 die 'Could not find player.js URL' unless $player_js; 5388 5389 $browser->get($player_js); 5390 5391 my ($mobile_player_js) = 5392 $browser->content =~ m{mobile_player_url *= *['"]([^'"]*)["']}; 5393 $mobile_player_js .= 'unknown&domain=unknown'; 5394 5395 die 'Could not find mobile_player.js URL' unless $mobile_player_js; 5396 5397 $browser->get($mobile_player_js); 5398 5399 my ($streams) = $browser->content =~ m{streams *= *[^;]*eval\("(.*?)"\);}; 5400 5401 die 'Could not find streams in mobile_player.js' unless $streams; 5402 5403 my $data = from_json(json_unescape($streams)); 5404 5405 my $title = $data->[0]{title}; 5406 my $url; 5407 if ($prefs->{quality} =~ /high|ipad/) { 5408 $url = $data->[0]{ipad_url}; 5409 } else { 5410 $url =$data->[0]{url}; 5411 } 5412 5413 $browser->allow_redirects; 5414 5415 return $url, title_to_filename($title, 'mp4'); 5416} 5417 5418sub can_handle { 5419 my($self, $browser, $url) = @_; 5420 5421 return 1 if $url && URI->new($url)->host =~ /\.ooyala\.com$/; 5422 5423 return $browser->content =~ m{<script src=["']http://player\.ooyala\.com/player\.js[^'"]*['"]>}; 5424} 5425 54261; 5427} 5428##} blib/lib/FlashVideo/Site/Ooyala.pm 5429BEGIN { $INC{'FlashVideo/Site/Pbs.pm'}++; } 5430# Part of get-flash-videos. See get_flash_videos for copyright. 5431##{ blib/lib/FlashVideo/Site/Pbs.pm 5432{ 5433package FlashVideo::Site::Pbs; 5434 5435use strict; 5436use warnings; 5437 5438BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 5439BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 5440use MIME::Base64 qw(decode_base64); 5441 5442 5443sub find_video { 5444 my ($self, $browser, $embed_url, $prefs) = @_; 5445 5446 die "Must have Crypt::Rijndael installed to download from PBS" 5447 unless eval { require Crypt::Rijndael }; 5448 5449 my ($media_id) = $browser->uri->as_string =~ m[ 5450 ^http://video\.pbs\.org/video/(\d+) 5451 ]x; 5452 unless (defined $media_id) { 5453 ($media_id) = $browser->content =~ m[ 5454 http://video\.pbs\.org/widget/partnerplayer/(\d+) 5455 ]x; 5456 } 5457 unless (defined $media_id) { 5458 ($media_id) = $browser->content =~ m[ 5459 /embed-player[^"]+\bepisodemediaid=(\d+) 5460 ]x; 5461 } 5462 unless (defined $media_id) { 5463 ($media_id) = $browser->content =~ m[var videoUrl = "([^"]+)"]; 5464 } 5465 unless (defined $media_id) { 5466 my ($pap_id, $youtube_id) = $browser->content =~ m[ 5467 \bDetectFlashDecision\ \('([^']+)',\ '([^']+)'\); 5468 ]x; 5469 if ($youtube_id) { 5470 debug "Youtube ID found, delegating to Youtube plugin\n"; 5471 my $url = "http://www.youtube.com/v/$youtube_id"; 5472 require FlashVideo::Site::Youtube; 5473 return FlashVideo::Site::Youtube->find_video($browser, $url, $prefs); 5474 } 5475 } 5476 die "Couldn't find media_id\n" unless defined $media_id; 5477 debug "media_id: $media_id\n"; 5478 5479 $browser->get("http://video.pbs.org/videoPlayerInfo/$media_id"); 5480 5481 my $xml = $browser->content; 5482 $xml =~ s/&/&/g; 5483 my $href = from_xml($xml); 5484 my $file = $href->{videoInfo}->{title}; 5485 my $release_url = $href->{releaseURL}; 5486 5487 unless ($release_url =~ m[^https?://]) { 5488 debug "encrypted release url: $release_url\n"; 5489 my ($type, $iv, $ciphertext) = split '\$', $release_url, 3; 5490 $release_url = undef; 5491 5492 my $key = 'RPz~i4p*FQmx>t76'; 5493 5494 my $cipher = Crypt::Rijndael->new($key, Crypt::Rijndael->MODE_CBC); 5495 $iv = pack 'H*', $iv if 32 == length $iv; 5496 $cipher->set_iv($iv); 5497 5498 $release_url = $cipher->decrypt(decode_base64($ciphertext)); 5499 $release_url =~ s/\s+$//; 5500 } 5501 debug "unencrypted release url: $release_url\n"; 5502 5503 $browser->get($release_url); 5504 5505 my $rtmp_url = $browser->res->header('location') 5506 || from_xml($browser->content)->{choice}{url} 5507 || die "Couldn't find stream url\n"; 5508 $rtmp_url =~ s/<break>//; 5509 5510 if(!$file) { 5511 ($file) = $rtmp_url =~ m{([^/\?]+)$}; 5512 } 5513 5514 return { 5515 rtmp => $rtmp_url, 5516 pageUrl => $embed_url, 5517 swfUrl => 'http://www-tc.pbs.org/video/media/swf/PBSPlayer.swf?18809', 5518 flv => title_to_filename($file), 5519 }; 5520} 5521 55221; 5523} 5524##} blib/lib/FlashVideo/Site/Pbs.pm 5525BEGIN { $INC{'FlashVideo/Site/Pennyarcade.pm'}++; } 5526# Part of get-flash-videos. See get_flash_videos for copyright. 5527##{ blib/lib/FlashVideo/Site/Pennyarcade.pm 5528{ 5529package FlashVideo::Site::Pennyarcade; 5530 5531use strict; 5532BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 5533BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 5534 5535sub find_video { 5536 my ($self, $browser, $embed_url) = @_; 5537 5538 my $id; 5539 my $title; 5540 if ($browser->content =~/<h2>(.*?)<\/h2>/) { 5541 $title = $1; 5542 $title =~ s/<[^>]*>//g; 5543 } 5544 if ($browser->content =~/http:\/\/blip.tv\/play\/(.*).html/) { 5545 $id = $1; 5546 } else { 5547 die "No ID found\n"; 5548 } 5549 5550 $browser->add_header("User-Agent" => "Android"); 5551 $browser->allow_redirects; 5552 return "http://blip.tv/play/$id.mp4", title_to_filename($title); 5553} 5554 55551; 5556} 5557##} blib/lib/FlashVideo/Site/Pennyarcade.pm 5558BEGIN { $INC{'FlashVideo/Site/Putlocker.pm'}++; } 5559# Part of get-flash-videos. See get_flash_videos for copyright. 5560##{ blib/lib/FlashVideo/Site/Putlocker.pm 5561{ 5562package FlashVideo::Site::Putlocker; 5563 5564use strict; 5565BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 5566BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *extract_title = \&FlashVideo::Utils::extract_title; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 5567use HTML::Tree; 5568 5569sub find_video { 5570 my ($self, $browser, $embed_url) = @_; 5571 5572 my ($filename) = title_to_filename(extract_title($browser)); 5573 $filename =~ s/[\s\|_]*PutLocker[\s_]*//; 5574 5575 my $tree = HTML::Tree->new(); 5576 $tree->parse($browser->content); 5577 my $hash = $tree->look_down( 'name' , 'hash' )->attr('value'); 5578 info 'Found hash: ' . $hash; 5579 5580 info "Confirming request to PutLocker."; 5581 5582 $browser->add_header( 'Content-Type' => 'application/x-www-form-urlencoded' ); 5583 $browser->add_header( 'Accept-Encoding' => 'text/html' ); 5584 $browser->add_header( Referer => $embed_url ); 5585 5586 my $response = $browser->post($embed_url, 5587 [ 'confirm'=>"Continue as Free User", 5588 'hash'=>$hash 5589 ]); 5590 5591 die 'Response code was ' . $response->code . '. Should be 302.' unless ($response->code == '302'); 5592 5593 info "Re-fetching page, which will now have the video embedded."; 5594 $browser->delete_header( 'Content-Type'); 5595 my $page_html = $browser->get($embed_url)->content; 5596 5597 my ($streamID) = ($page_html =~ /get_file\.php\?stream=([A-Za-z0-9]+)/); 5598 info "Found the stream ID: " . $streamID; 5599 5600 my $uri = URI->new( "http://www.putlocker.com/get_file.php" ); 5601 $uri->query_form((stream=>$streamID)); 5602 5603 my $contents = $browser->get($uri)->content; 5604 my ($url) = ($contents =~ /url="(.*?)"/); 5605 5606 info "Got the video URL: " . $url; 5607 5608 return $url, $filename; 5609} 5610 56111; 5612 5613} 5614##} blib/lib/FlashVideo/Site/Putlocker.pm 5615BEGIN { $INC{'FlashVideo/Site/Redbull.pm'}++; } 5616# Part of get-flash-videos. See get_flash_videos for copyright. 5617##{ blib/lib/FlashVideo/Site/Redbull.pm 5618{ 5619package FlashVideo::Site::Redbull; 5620 5621use strict; 5622BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 5623BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 5624use URI; 5625use HTML::Entities; 5626 5627sub find_video { 5628 my ($self, $browser, $page_url) = @_; 5629 5630 my $video_info_url; 5631 my $host = $browser->uri->host; 5632 5633 if ( ($browser->content =~ /data_url:\s+'([^']+)'/) or 5634 ($browser->content =~ m{displayVideoPlayer\('([^']+)'\)})) { 5635 $video_info_url = $1; 5636 5637 $video_info_url = "http://$host$video_info_url"; 5638 } 5639 5640 if (!$video_info_url) { 5641 die "Couldn't find video info URL"; 5642 } 5643 5644 $browser->get($video_info_url); 5645 5646 if ($browser->response->is_redirect) { 5647 $browser->get($browser->response->header('Location')); 5648 } 5649 5650 if (!$browser->success) { 5651 die "Couldn't download Red Bull video info XML: " . 5652 $browser->response->status_line; 5653 } 5654 5655 my $xml = $browser->content; 5656 $xml =~ s/&//g; 5657 $xml = decode_entities($xml); 5658 5659 my $video_info = from_xml($xml); 5660 5661 my $file_type = "flv"; 5662 5663 if ($video_info->{high_video_url} =~ /\.mp4$/) { 5664 $file_type = "mp4"; 5665 } 5666 5667 return { 5668 flv => title_to_filename($video_info->{title}, $file_type), 5669 rtmp => $video_info->{high_video_url}, 5670 }; 5671} 5672 56731; 5674} 5675##} blib/lib/FlashVideo/Site/Redbull.pm 5676BEGIN { $INC{'FlashVideo/Site/Redtube.pm'}++; } 5677# Part of get-flash-videos. See get_flash_videos for copyright. 5678##{ blib/lib/FlashVideo/Site/Redtube.pm 5679{ 5680package FlashVideo::Site::Redtube; 5681 5682use strict; 5683BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 5684BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 5685use URI::Escape; 5686 5687sub find_video { 5688 my($self, $browser, $embed_url) = @_; 5689 5690 my($title) = $browser->content =~ /<h1 class="videoTitle">([^<]+)</; 5691 5692 my($url) = $browser->content =~ /hashlink=([^&"]+)/; 5693 $url = uri_unescape($url); 5694 5695 $browser->allow_redirects; 5696 return $url, title_to_filename($title); 5697} 5698 56991; 5700} 5701##} blib/lib/FlashVideo/Site/Redtube.pm 5702BEGIN { $INC{'FlashVideo/Site/Ringtv.pm'}++; } 5703# Part of get-flash-videos. See get_flash_videos for copyright. 5704##{ blib/lib/FlashVideo/Site/Ringtv.pm 5705{ 5706package FlashVideo::Site::Ringtv; 5707 5708use strict; 5709BEGIN { FlashVideo::Site::Grindtv->import(); } # (added by utils/combine-perl.pl) 5710use base 'FlashVideo::Site::Grindtv'; 5711 57121; 5713} 5714##} blib/lib/FlashVideo/Site/Ringtv.pm 5715BEGIN { $INC{'FlashVideo/Site/Sapo.pm'}++; } 5716# Part of get-flash-videos. See get_flash_videos for copyright. 5717##{ blib/lib/FlashVideo/Site/Sapo.pm 5718{ 5719package FlashVideo::Site::Sapo; 5720 5721use strict; 5722BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 5723BEGIN { no strict 'refs'; *extract_title = \&FlashVideo::Utils::extract_title; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 5724 5725sub find_video { 5726 my ($self, $browser) = @_; 5727 5728 my ($video_url, $type); 5729 5730 if ($browser->content =~ m{flvplayer-sapo\.swf\?file=(http://[^&"]+)}) { 5731 $video_url = $1; 5732 5733 if ($video_url =~ m{/mov}) { 5734 $type = "mp4"; 5735 } 5736 } 5737 else { 5738 die "Couldn't extract Sapo video URL"; 5739 } 5740 5741 (my $title = extract_title($browser)) =~ s/ - SAPO V\x{ed}deos//; 5742 5743 my $filename = title_to_filename($title, $type); 5744 5745 $browser->allow_redirects(1); 5746 5747 return $video_url, $filename; 5748} 5749 57501; 5751} 5752##} blib/lib/FlashVideo/Site/Sapo.pm 5753BEGIN { $INC{'FlashVideo/Site/Sbs.pm'}++; } 5754# Part of get-flash-videos. See get_flash_videos for copyright. 5755##{ blib/lib/FlashVideo/Site/Sbs.pm 5756{ 5757package FlashVideo::Site::Sbs; 5758 5759use strict; 5760BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 5761BEGIN { no strict 'refs'; } 5762BEGIN { FlashVideo::JSON->import(); } # (added by utils/combine-perl.pl) 5763BEGIN { no strict 'refs'; } 5764use File::Basename; 5765use HTML::Entities; 5766use URI::Escape; 5767 5768sub find_video { 5769 my ($self, $browser, $embed_url, $prefs) = @_; 5770 5771 my $smil; 5772 my $baseurl; 5773 5774 my($id) = $browser->content =~ /firstVidId = '([^']*)';/; 5775 ($smil) = decode_entities($browser->content =~ /player\.releaseUrl = "([^"]*)";/); 5776 5777 if( $id ){ 5778 5779 ($baseurl) = $browser->content =~ m{so\.addVariable\("nielsenLaunchURL", *"([^"]*)"\);}s ; 5780 my($menu) = $browser->content =~ m{loadVideo\('([^']*)', '', [^\)]\);}s ; 5781 if( !$menu ){ $menu = $baseurl . '/video/menu/inline/id/' . $id; } 5782 else { $menu = 'http://www.sbs.com.au' . $menu; } 5783 $menu =~ s/' *\+ *firstVidId *\+ *'/$id/g; 5784 5785 die "No menu URL found" unless $menu; 5786 5787 $browser->get($menu); 5788 5789 ($smil) = $browser->content =~ m{<video *name="[^"]*" *id="[^"]*" *src="([^"]*)">}s ; 5790 } 5791 5792 die "no smil" unless $smil; 5793 5794 $browser->get($smil); 5795 5796 ($baseurl) = decode_entities($browser->content =~ m'<meta base="([^"]*)"/>'s); 5797 5798 my @tmp = $browser->content =~ m'<video src="([^"]*)" system-bitrate="([^"]*)"/>'gs; 5799 my %tmp = reverse @tmp; 5800 my $filename; 5801 my $q = $prefs->{quality}; 5802 if( grep {$_ eq $q || $_ == $q || $_ == ($q * 100000)} keys(%tmp) ){ 5803 $filename = decode_entities($tmp{$q}); 5804 if(!$filename){ 5805 my @bitrates = grep {$_ == $q || $_ == ($q * 100000)} keys(%tmp); 5806 $filename = decode_entities($tmp{$bitrates[0]}); 5807 } 5808 } else { 5809 my @filenames = (); 5810 foreach (sort { $a <=> $b } keys(%tmp) ) 5811 { push @filenames, $tmp{$_}; } 5812 my $cnt = @filenames; 5813 my $num = {high => int($cnt/3)*2, medium => int($cnt/3)*1, low => int($cnt/3)*0}->{$q}; 5814 $filename = decode_entities($filenames[$num]); 5815 } 5816 5817 die "no filenames" unless $filename; 5818 5819 if( $baseurl =~ /^rtmp:/ ){ 5820 my($flvname) = $filename =~ m'[^/]*/(.*)'s; 5821 return { 5822 rtmp => $baseurl, 5823 playpath => $filename, 5824 flv => $flvname, 5825 swfUrl => 'http://www.sbs.com.au/vod/theplatform/core/4_4_3/swf/flvPlayer.swf', 5826 }; 5827 } elsif ($baseurl) { 5828 my $url = $baseurl . $filename; 5829 return $url, $filename; 5830 } else { 5831 return $filename, File::Basename::basename($filename); 5832 } 5833} 5834 58351; 5836} 5837##} blib/lib/FlashVideo/Site/Sbs.pm 5838BEGIN { $INC{'FlashVideo/Site/Scivee.pm'}++; } 5839# Part of get-flash-videos. See get_flash_videos for copyright. 5840##{ blib/lib/FlashVideo/Site/Scivee.pm 5841{ 5842package FlashVideo::Site::Scivee; # horrible casing :( 5843 5844 5845use strict; 5846BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 5847BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *extract_info = \&FlashVideo::Utils::extract_info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 5848use HTML::Entities; 5849sub find_video { 5850 5851 my ($self, $browser) = @_; 5852 5853 my $title; 5854 if ($browser->content =~ /title\>([^\|]+)/) { 5855 $title = $1; 5856 } 5857 else { 5858 $title = extract_info($browser)->{title}; 5859 } 5860 my $filename = title_to_filename($title); 5861 my $vid; 5862 if ($browser->content =~ /\/ratings\/(\d+)/) { 5863 $vid = $1; 5864 } 5865 elsif ($browser->content =~ /flashvars="id=(\d+)/) { 5866 $vid = $1; 5867 } 5868 else { 5869 die "Could not find video!"; 5870 } 5871 my $url = "http://www.scivee.tv/asset/video/$vid"; 5872 5873 return $url, $filename; 5874} 5875 58761; 5877} 5878##} blib/lib/FlashVideo/Site/Scivee.pm 5879BEGIN { $INC{'FlashVideo/Site/Seesaw.pm'}++; } 5880# Part of get-flash-videos. See get_flash_videos for copyright. 5881##{ blib/lib/FlashVideo/Site/Seesaw.pm 5882{ 5883package FlashVideo::Site::Seesaw; 5884 5885use strict; 5886BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 5887BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; *error = \&FlashVideo::Utils::error; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *json_unescape = \&FlashVideo::Utils::json_unescape; *convert_sami_subtitles_to_srt = \&FlashVideo::Utils::convert_sami_subtitles_to_srt; } 5888use HTML::Entities qw(decode_entities); 5889use URI::Escape qw(uri_escape); 5890 5891my @res = ( 5892 { name => "lowResUrl", resolution => [ 512, 288 ] }, 5893 { name => "stdResUrl", resolution => [ 672, 378 ] }, 5894 { name => "highResUrl", resolution => [ 1024, 576 ] } 5895); 5896 5897sub find_video { 5898 my ($self, $browser, $page_url, $prefs) = @_; 5899 5900 my $player_info = ($browser->content =~ m{(/videoplayerinfo/\d+[^"]+)"})[0]; 5901 5902 (my $content = $browser->content) =~ s{\\/}{/}g; 5903 5904 my %seen; # avoid duplication in filenames 5905 5906 my %metadata = map { $_ => '' } qw(brandTitle seriesTitle programmeTitle); 5907 5908 my ($series, $episode); 5909 5910 ($series, $episode) = ($browser->content =~ /Series (\d+) - Ep(?:isode)?\.? (\d+)/); 5911 5912 if (!$series and !$episode) { 5913 ($series, $episode) = ($browser->content =~ /series_number: ["']?(\d+)["']?,\s+ep_number: ['"]?(\d+)['"]/); 5914 } 5915 5916 if ($series and $episode) { 5917 $metadata{series_and_episode} = sprintf "S%02dE%02d", $series, $episode; 5918 } 5919 5920 foreach my $metadata_item (keys %metadata) { 5921 if (my $value = ($content =~ m{<$metadata_item>(.*?)</$metadata_item>}isg)[0]) { 5922 $value = decode_entities($value); 5923 5924 next if $seen{$value}; 5925 5926 $seen{$value}++; 5927 5928 $metadata{$metadata_item} = $value; 5929 } 5930 } 5931 5932 my @metadata_items; 5933 5934 if ( (grep length, values %metadata) == 2 and 5935 $metadata{series_and_episode}) { 5936 @metadata_items = ((grep { $_ ne 'series_and_episode' } keys %metadata), 'series_and_episode'); 5937 } 5938 elsif (!$metadata{brandTitle}) { 5939 @metadata_items = qw(seriesTitle series_and_episode programmeTitle); 5940 } 5941 else { 5942 @metadata_items = qw(brandTitle series_and_episode seriesTitle programmeTitle); 5943 } 5944 5945 my $title = join "-", map { trim($_) } 5946 grep length, 5947 @metadata{@metadata_items}; 5948 5949 $browser->get($player_info); 5950 5951 debug "Got player info URL $player_info"; 5952 5953 if (!$browser->success) { 5954 die "Couldn't get player info: " . $browser->response->status_line; 5955 } 5956 5957 my @urls; 5958 for my $res(@res) { 5959 if($browser->content =~ /$res->{name}":\["([^"]+)/) { 5960 push @urls, { %$res, url => $1 }; 5961 } 5962 } 5963 5964 die "No video URLs found" unless @urls; 5965 5966 my $rtmp = $prefs->quality->choose(@urls); 5967 5968 my($app, $playpath, $query) = $rtmp->{url} =~ m{^\w+://[^/]+/(\w+/\w+)(/[^?]+)(\?.*)}; 5969 my $prefix = "mp4"; 5970 $prefix = "flv" if $playpath =~ /\.flv$/; 5971 5972 if ($prefs->subtitles) { 5973 if ($browser->content =~ m{"subtitleLocation":\["([^"]+)"\]}) { 5974 my $subtitles_url = $1; 5975 5976 if ($subtitles_url =~ m{^/}) { 5977 $subtitles_url = "http://www.seesaw.com$subtitles_url"; 5978 } 5979 5980 debug "Got Seesaw subtitles URL: $subtitles_url"; 5981 5982 $browser->get($subtitles_url); 5983 5984 if ($browser->success) { 5985 my $srt_filename = title_to_filename($title, "srt"); 5986 5987 convert_sami_subtitles_to_srt($browser->content, $srt_filename); 5988 5989 info "Wrote subtitles to $srt_filename"; 5990 } 5991 else { 5992 info "Couldn't download subtitles: " . $browser->response->status_line; 5993 } 5994 } 5995 else { 5996 debug "No Seesaw subtitles available (or couldn't extract URL)"; 5997 } 5998 } 5999 6000 return { 6001 flv => title_to_filename($title, $prefix), 6002 rtmp => $rtmp->{url}, 6003 app => $app, 6004 playpath => "$prefix:$playpath$query" 6005 } 6006} 6007 6008sub search { 6009 my($self, $search, $type) = @_; 6010 6011 my $series = $search =~ s/(?:series |\bs)(\d+)//i ? int $1 : ""; 6012 my $episode = $search =~ s/(?:episode |\be)(\d+)//i ? int $1 : ""; 6013 6014 my $browser = FlashVideo::Mechanize->new; 6015 6016 _update_with_content($browser, 6017 "http://www.seesaw.com/start.layout.searchsuggest:inputtextevent?search=" 6018 . uri_escape($search)); 6019 6020 my @urls = map { 6021 chomp(my $name = $_->text); 6022 { name => $name, url => $_->url_abs->as_string } 6023 } $browser->find_all_links(text_regex => qr/.+/); 6024 6025 my @words = split " ", $search; 6026 @urls = grep { my $a = $_; @words == grep { $a->{name} =~ /\Q$_\E/i } @words } @urls; 6027 6028 if(@urls == 1) { 6029 $browser->get($urls[0]->{url}); 6030 my $main_title = ($browser->content =~ m{<h1>(.*?)</h1>}s)[0]; 6031 $main_title =~ s/<[^>]+>//g; 6032 $main_title =~ s/\s+/ /g; 6033 6034 my $cur_series = ($browser->content =~ /<li class="current">.*?>\w+ (\d+)/i)[0]; 6035 if($main_title =~ s/\s*series (\d+)\s*//i && !$cur_series) { 6036 $cur_series = $1; 6037 } 6038 6039 my %series = reverse( 6040 ($browser->content =~ m{<ul class="seriesList">(.*?)</ul>}i)[0] 6041 =~ /<li.*?href="\?([^"]+)".*?>\s*(?:series\s*)?([^<]+)/gi); 6042 6043 my $episode_list; 6044 if($series && $cur_series ne $series) { 6045 if(!$series{$series}) { 6046 error "No such series number ($series)."; 6047 return; 6048 } 6049 _update_with_content($browser, $series{$series}); 6050 $episode_list = $browser->content; 6051 $cur_series = $series; 6052 6053 } elsif(!$series && keys %series > 1) { 6054 my @series = sort { $a <=> $b } map { s/series\s+//i; $_ } keys %series; 6055 info "Viewing series $cur_series; series " . join(", ", @series) . " also available."; 6056 info "Search for 'seesaw $main_title series $series[0]' to view a specific series."; 6057 } 6058 6059 if(!$episode_list) { 6060 $episode_list = ($browser->content 6061 =~ m{<table id="episodeListTble">(.*?)</table>}is)[0]; 6062 } 6063 6064 @urls = (); 6065 for my $episode_html($episode_list =~ m{<tr.*?</tr>}gis) { 6066 my %info; 6067 for(qw(number date title action)) { 6068 my $class = "episode" . ucfirst; 6069 $episode_html =~ m{<td class=['"]$class['"]>(.*?)</td>}gis 6070 && ($info{$_} = $1); 6071 } 6072 6073 $info{number} = ($info{number} =~ /ep\.?\w*\s*(\d+)/i)[0]; 6074 $info{date} = ($info{date} =~ />(\w+[^<]+)/)[0]; 6075 $info{number} ||= ($info{title} =~ /ep\.?\w*\s*(\d+)/i)[0]; 6076 $info{title} = ($info{title} =~ />\s*([^<].*?)\s*</s)[0]; 6077 $info{url} = ($info{action} =~ /href=['"]([^'"]+)/)[0]; 6078 6079 my $title = join " - ", $main_title, 6080 ($cur_series 6081 ? sprintf("S%02dE%02d", $cur_series, $info{number}) 6082 : $info{number} ? sprintf("E%02d", $info{number}) 6083 : ()), $info{title}; 6084 6085 my $result = { 6086 name => $title, 6087 url => URI->new_abs($info{url}, $browser->uri) 6088 }; 6089 6090 if($episode && $info{number} == $episode) { 6091 return $result; 6092 } 6093 6094 push @urls, $result; 6095 } 6096 } else { 6097 info "Please specify a more specific title to download a particular programme." if @urls > 1; 6098 } 6099 6100 return @urls; 6101} 6102 6103sub _update_with_content { 6104 my($browser, $url) = @_; 6105 6106 $browser->get($url, 6107 X_Requested_With => 'XMLHttpRequest', 6108 X_Prototype_Version => '1.6.0.3'); 6109 6110 my($content) = $browser->content =~ /content":\s*"(.*?)"\s*}/; 6111 $content = json_unescape($content); 6112 debug "Content is '$content'"; 6113 $browser->update_html($content); 6114} 6115 6116sub trim { 6117 local $_ = shift; 6118 6119 s/^\s+|\s+$//g; 6120 6121 return $_; 6122} 6123 61241; 6125} 6126##} blib/lib/FlashVideo/Site/Seesaw.pm 6127BEGIN { $INC{'FlashVideo/Site/Sevenload.pm'}++; } 6128# Part of get-flash-videos. See get_flash_videos for copyright. 6129##{ blib/lib/FlashVideo/Site/Sevenload.pm 6130{ 6131package FlashVideo::Site::Sevenload; 6132 6133use strict; 6134BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 6135BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 6136use HTML::Entities; 6137use URI::Escape; 6138 6139sub find_video { 6140 my ($self, $browser) = @_; 6141 6142 die "Could not find configPath" unless $browser->content =~ /configPath=([^"']+)/; 6143 my $configpath = uri_unescape(decode_entities($1)); 6144 $browser->get($configpath); 6145 6146 my $config = from_xml($browser); 6147 6148 my($title, $location); 6149 6150 eval { 6151 my $item = $config->{playlists}->{playlist}->{items}->{item}; 6152 $title = title_to_filename($item->{title}); 6153 6154 my $streams = $item->{videos}->{video}->{streams}->{stream}; 6155 $streams = [ $streams ] unless ref $streams eq 'ARRAY'; 6156 6157 $location = (sort { $b->{width} <=> $a->{width} } @$streams)[0] 6158 ->{locations}->{location}->{content}; 6159 }; 6160 6161 return $location, $title if $location; 6162 6163 die "Unable to get stream location" . ($@ ? ": $@" : ""); 6164} 6165 61661; 6167} 6168##} blib/lib/FlashVideo/Site/Sevenload.pm 6169BEGIN { $INC{'FlashVideo/Site/Slashcontrol.pm'}++; } 6170# Part of get-flash-videos. See get_flash_videos for copyright. 6171##{ blib/lib/FlashVideo/Site/Slashcontrol.pm 6172{ 6173package FlashVideo::Site::Slashcontrol; 6174 6175use strict; 6176BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 6177BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 6178BEGIN { FlashVideo::JSON->import(); } # (added by utils/combine-perl.pl) 6179BEGIN { no strict 'refs'; *from_json = \&FlashVideo::JSON::from_json; } 6180 6181sub find_video { 6182 my($self, $browser, $embed_url, $prefs) = @_; 6183 6184 my $config; 6185 my $mediaKey; 6186 if ($browser->content =~ /<param name="flashvars" value="config=([^&]*)&mediaKey=([^"]*)"\/>/) { 6187 $config = $1; 6188 $mediaKey = $2; 6189 } else { 6190 die "Couldn't find flashvars param in " . $browser->uri->as_string; 6191 } 6192 my $root; 6193 if ($browser->content =~ /<embed src="(.*)\/[^\/]*\.swf"/) { 6194 $root = $1; 6195 } else { 6196 die "Couldn't find embeded swf " . $browser->uri->as_string; 6197 } 6198 my $config_url; 6199 $config_url = $1 . "/" . $config; 6200 6201 $browser->allow_redirects; 6202 $browser->get($config_url); 6203 if (!$browser->success) { 6204 die "Couldn't download config.xml $config_url: " . $browser->response->status_line; 6205 } 6206 6207 my $xml = from_xml($browser); 6208 my $domain = $xml->{mfs}->{mfsUrl}; 6209 my $version = $xml->{mfs}->{mfsVersion}; 6210 my $account = $xml->{mfs}->{mfsAccount}; 6211 my $partner = $xml->{mfs}->{mfsPartnerId}; 6212 6213 my $asset_url = "$domain/$version/$account/assets/$mediaKey/partner/$partner?format=json"; 6214 $browser->get($asset_url); 6215 if (!$browser->success) { 6216 die "Couldn't download asset file $asset_url: " . $browser->response->status_line; 6217 } 6218 6219 my $asset_data = from_json($browser->content); 6220 my $videos = $asset_data->{videos}; 6221 6222 my $title = title_to_filename($asset_data->{assetFields}->{seriesName} . " - " . $asset_data->{assetFields}->{title}); 6223 6224 my $video = $videos->{limelight700}; 6225 6226 my $rtmp = $video->{uri}; 6227 6228 return { 6229 flv => $title, 6230 rtmp => $rtmp, 6231 }; 6232} 6233 62341; 6235} 6236##} blib/lib/FlashVideo/Site/Slashcontrol.pm 6237BEGIN { $INC{'FlashVideo/Site/Spiegel.pm'}++; } 6238# Part of get-flash-videos. See get_flash_videos for copyright. 6239##{ blib/lib/FlashVideo/Site/Spiegel.pm 6240{ 6241package FlashVideo::Site::Spiegel; 6242 6243use strict; 6244BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 6245BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 6246 6247sub find_video { 6248 my ($self, $browser, $embed_url, $prefs) = @_; 6249 my ($video_id, $xmlurl, $filename, $videourl, $quality); 6250 6251 debug "Spiegel::find_video called, embed_url = \"$embed_url\"\n"; 6252 6253 $quality = { 6254 high => '.mp4', 6255 medium => 'VP6_928.flv', 6256 low => 'VP6_576.flv'}->{$prefs->{quality}}; 6257 6258 if($embed_url =~ /.*?www.spiegel.de\/video\/video-(\d*).html/) { 6259 $video_id = $1; 6260 $xmlurl = "http://video.spiegel.de/flash/$video_id.xml"; 6261 } else { 6262 die "Only works for http://www.spiegel/de/video/video... urls\n"; 6263 } 6264 6265 if($browser->content =~ /<title>(.*?) -Video/) { 6266 $filename = "Spiegel_$1_${video_id}_$quality"; 6267 $filename = title_to_filename($filename, $quality); 6268 $filename =~ s/__/_/g; 6269 } else { 6270 die "Unable to find <title> on page $embed_url\n"; 6271 } 6272 6273 $browser->get($xmlurl); 6274 6275 if($browser->content =~ /<filename>(.*?$quality)<\/filename>/) { 6276 $videourl = "http://video.spiegel.de/flash/$1"; 6277 } else { 6278 die "could not find video url\n"; 6279 } 6280 6281 return $videourl, $filename; 6282} 6283 62841; 6285} 6286##} blib/lib/FlashVideo/Site/Spiegel.pm 6287BEGIN { $INC{'FlashVideo/Site/Spike.pm'}++; } 6288# Part of get-flash-videos. See get_flash_videos for copyright. 6289##{ blib/lib/FlashVideo/Site/Spike.pm 6290{ 6291package FlashVideo::Site::Spike; 6292 6293use strict; 6294BEGIN { FlashVideo::Site::Mtvnservices->import(); } # (added by utils/combine-perl.pl) 6295use base 'FlashVideo::Site::Mtvnservices'; 6296 6297BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 6298BEGIN { no strict 'refs'; *from_xml = \&FlashVideo::Utils::from_xml; } 6299use URI::Escape; 6300 6301sub find_video { 6302 my ($self, $browser, $embed_url) = @_; 6303 6304 my $page_url = $browser->uri->as_string; 6305 6306 my $config_url; 6307 if($browser->content =~ /config_url\s*=\s*["']([^"']+)/) { 6308 $config_url = $1; 6309 } elsif($browser->content =~ /(?:ifilmId|flvbaseclip)=(\d+)/) { 6310 $config_url = "/ui/xml/mediaplayer/config.groovy?ifilmId=$1"; 6311 } 6312 die "No config_url/id found\n" unless $config_url; 6313 6314 $browser->get(uri_unescape($config_url)); 6315 my $xml = from_xml($browser); 6316 6317 my $feed = uri_unescape($xml->{player}->{feed}); 6318 die "Unable to find feed URL\n" unless $feed; 6319 6320 $browser->get($feed); 6321 6322 return $self->handle_feed($browser->content, $browser, $page_url); 6323} 6324 63251; 6326} 6327##} blib/lib/FlashVideo/Site/Spike.pm 6328BEGIN { $INC{'FlashVideo/Site/Stagevu.pm'}++; } 6329# Part of get-flash-videos. See get_flash_videos for copyright. 6330##{ blib/lib/FlashVideo/Site/Stagevu.pm 6331{ 6332package FlashVideo::Site::Stagevu; 6333 6334use strict; 6335BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 6336BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 6337 6338sub find_video { 6339 my ($self, $browser) = @_; 6340 6341 my($title) = $browser->content =~ /<title>(.*?)<\/title>/; 6342 $title =~ s/\s*-\s*Stagevu.*?$//; 6343 6344 my($url) = FlashVideo::Generic->find_video($browser); 6345 6346 return $url, title_to_filename($title); 6347} 6348 63491; 6350} 6351##} blib/lib/FlashVideo/Site/Stagevu.pm 6352BEGIN { $INC{'FlashVideo/Site/Starwars.pm'}++; } 6353# Part of get-flash-videos. See get_flash_videos for copyright. 6354##{ blib/lib/FlashVideo/Site/Starwars.pm 6355{ 6356package FlashVideo::Site::Starwars; 6357 6358use strict; 6359BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 6360BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 6361 6362sub find_video { 6363 my ($self, $browser, $embed_url) = @_; 6364 6365 my $video_id; 6366 if ($browser->uri->as_string =~ /view\/([0-9]+)\.html$/) { 6367 $video_id = $1; 6368 } 6369 6370 my $page_url = $browser->uri->as_string; 6371 6372 $browser->get("http://starwars.com/webapps/video/item/$video_id"); 6373 my $xml = from_xml($browser); 6374 6375 my $items = $xml->{channel}->{item}; 6376 my $item = ref $items eq 'ARRAY' ? 6377 (grep { $_->{link}->{content} eq "/video/view/" . $video_id . ".html" } @$items)[0] : 6378 $items; 6379 6380 debug $item->{enclosure}->{url}; 6381 6382 my $rtmpurl = $item->{enclosure}->{url}; 6383 $rtmpurl =~ s/^rtmp:/rtmpe:/; # for some reason it only works with rtmpe 6384 6385 my $title = $item->{title}; # is there a way to unencrypt <CDATA> tags? or does the xml handler do this for us? 6386 6387 return { 6388 flv => $title, 6389 rtmp => title_to_filename($rtmpurl), 6390 playpath => $item->{content}->{url} 6391 }; 6392} 6393 63941; 6395} 6396##} blib/lib/FlashVideo/Site/Starwars.pm 6397BEGIN { $INC{'FlashVideo/Site/Stickam.pm'}++; } 6398# Part of get-flash-videos. See get_flash_videos for copyright. 6399##{ blib/lib/FlashVideo/Site/Stickam.pm 6400{ 6401package FlashVideo::Site::Stickam; 6402 6403use strict; 6404BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 6405BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *error = \&FlashVideo::Utils::error; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *swfhash = \&FlashVideo::Utils::swfhash; } 6406 6407sub find_video { 6408 my($self, $browser, $embed_url, $prefs) = @_; 6409 6410 my $perfomer_id; 6411 6412 if ($browser->content =~ /profileUserId=(\d+)/) { 6413 $perfomer_id = $1; 6414 } 6415 else { 6416 die "Can't get performer ID"; 6417 } 6418 6419 my $filename; 6420 if ($browser->content =~ /userName=([^&]+)/) { 6421 $filename = $1; 6422 } 6423 else { 6424 $filename = $perfomer_id; 6425 } 6426 6427 my $stream_info_url = sprintf 6428 "http://player.stickam.com/servlet/flash/getChannel?" . 6429 "type=join&performerID=%d", $perfomer_id; 6430 6431 $browser->get($stream_info_url); 6432 6433 if (!$browser->success) { 6434 die "Couldn't get stream info: " . $browser->response->status_line; 6435 } 6436 6437 my %stream_info; 6438 6439 foreach my $pair (split /&/, $browser->content) { 6440 my ($name, $value) = split /=/, $pair; 6441 6442 if ($name eq 'freeServerIP') { 6443 $value = (split /,/, $value)[0]; 6444 } 6445 6446 $stream_info{$name} = $value; 6447 } 6448 6449 if ($stream_info{errorCode}) { 6450 die "Stickam returned error $stream_info{errorCode}: $stream_info{errorMessage}"; 6451 } 6452 6453 my $rtmp_stream_url = sprintf 6454 "rtmp://%s/video_chat2_stickam_peep/%d/public/mainHostFeed", 6455 $stream_info{freeServerIP}, 6456 $stream_info{channelID}; 6457 6458 return { 6459 rtmp => $rtmp_stream_url, 6460 flv => title_to_filename($filename), 6461 live => '', 6462 conn => [ 6463 'O:1', 6464 "NS:channel:$perfomer_id", 6465 'O:1', 6466 ], 6467 swfhash($browser, 6468 "http://player.stickam.com/flash/stickam/stickam_simple_video_player.swf") 6469 }; 6470} 6471 64721; 6473} 6474##} blib/lib/FlashVideo/Site/Stickam.pm 6475BEGIN { $INC{'FlashVideo/Site/Stupidvideos.pm'}++; } 6476# Part of get-flash-videos. See get_flash_videos for copyright. 6477##{ blib/lib/FlashVideo/Site/Stupidvideos.pm 6478{ 6479package FlashVideo::Site::Stupidvideos; 6480 6481use strict; 6482BEGIN { FlashVideo::Site::Grindtv->import(); } # (added by utils/combine-perl.pl) 6483use base 'FlashVideo::Site::Grindtv'; 6484 64851; 6486} 6487##} blib/lib/FlashVideo/Site/Stupidvideos.pm 6488BEGIN { $INC{'FlashVideo/Site/Svtplay.pm'}++; } 6489# Part of get-flash-videos. See get_flash_videos for copyright. 6490##{ blib/lib/FlashVideo/Site/Svtplay.pm 6491{ 6492package FlashVideo::Site::Svtplay; 6493 6494use strict; 6495use warnings; 6496 6497BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 6498BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 6499BEGIN { FlashVideo::JSON->import(); } # (added by utils/combine-perl.pl) 6500BEGIN { no strict 'refs'; *from_json = \&FlashVideo::JSON::from_json; } 6501 6502sub find_video { 6503 my ($self, $browser, $embed_url, $prefs) = @_; 6504 my @rtmpdump_commands; 6505 6506 if ($browser->uri->as_string !~ m/video\/([0-9]*)/) { 6507 die "No video id found in url"; 6508 } 6509 6510 my $video_id = $1; 6511 my $info_url = "http://www.svtplay.se/video/$video_id?output=json"; 6512 6513 $browser->get($info_url); 6514 6515 if (!$browser->success) { 6516 die "Couldn't download $info_url: " . $browser->response->status_line; 6517 } 6518 6519 my $video_data = from_json($browser->content); 6520 my $name = $video_data->{context}->{title}; 6521 my $bitrate = 0; 6522 my $rtmp_url; 6523 6524 foreach my $video (@{ $video_data->{video}->{videoReferences} }) { 6525 my $rate = int $video->{bitrate}; 6526 6527 if ($bitrate < $rate && $video->{playerType} eq "flash") { 6528 $rtmp_url = $video->{url}; 6529 $bitrate = $rate; 6530 } 6531 } 6532 6533 if ($prefs->{subtitles}) { 6534 if (my $subtitles_url = $video_data->{video}->{subtitleReferences}[0]->{url}) { 6535 info "Found subtitles URL: $subtitles_url"; 6536 6537 $browser->get($subtitles_url); 6538 6539 if (!$browser->success) { 6540 info "Couldn't download subtitles: " . $browser->status_line; 6541 } 6542 6543 my $srt_filename = title_to_filename($name, "srt"); 6544 6545 open my $srt_fh, '>', $srt_filename 6546 or die "Can't open subtitles file $srt_filename: $!"; 6547 binmode $srt_fh, ':utf8'; 6548 print $srt_fh $browser->content; 6549 close $srt_fh; 6550 } 6551 else { 6552 info "No subtitles found!"; 6553 } 6554 } 6555 6556 return { 6557 flv => title_to_filename($name, "flv"), 6558 rtmp => $rtmp_url, 6559 swfVfy => "http://www.svtplay.se/public/swf/video/svtplayer-2012.15.swf", 6560 }; 6561} 6562 65631; 6564} 6565##} blib/lib/FlashVideo/Site/Svtplay.pm 6566BEGIN { $INC{'FlashVideo/Site/Tbs.pm'}++; } 6567# Part of get-flash-videos. See get_flash_videos for copyright. 6568##{ blib/lib/FlashVideo/Site/Tbs.pm 6569{ 6570package FlashVideo::Site::Tbs; 6571 6572use strict; 6573BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 6574BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 6575 6576sub find_video { 6577 my ($self, $browser, $embed_url) = @_; 6578 6579 my $oid; 6580 if ($browser->uri->as_string =~ /oid=([0-9]*)/) { 6581 $oid = $1; 6582 } 6583 6584 $browser->get("http://www.tbs.com/video/cvp/videoData.jsp?oid=$oid"); 6585 6586 my $xml = from_xml($browser); 6587 6588 my $headline = $xml->{headline}; 6589 6590 my $akamai; 6591 if ($xml->{akamai}->{src} =~ /[^,]*,([^,]*)/){ 6592 $akamai = $1; 6593 } 6594 6595 my $files = $xml->{files}->{file}; 6596 my $file = ref $files eq 'ARRAY' ? 6597 (grep { $_->{type} eq "standard" } @$files)[0] : 6598 $files; 6599 6600 if($akamai) { 6601 my $rtmpurl = $akamai . $file->{content}; 6602 die "Unable to find RTMP URL\n" unless $rtmpurl; 6603 6604 return { 6605 flv => title_to_filename($headline), 6606 rtmp => $rtmpurl 6607 }; 6608 } else { 6609 return $file->{content}, title_to_filename($headline); 6610 } 6611} 6612 66131; 6614} 6615##} blib/lib/FlashVideo/Site/Tbs.pm 6616BEGIN { $INC{'FlashVideo/Site/Techcast.pm'}++; } 6617# Part of get-flash-videos. See get_flash_videos for copyright. 6618##{ blib/lib/FlashVideo/Site/Techcast.pm 6619{ 6620package FlashVideo::Site::Techcast; 6621 6622use strict; 6623BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 6624BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 6625use HTML::Entities; 6626 6627sub find_video { 6628 my ($self, $browser, $embed_url) = @_; 6629 6630 my($clip_url) = $browser->content =~ /clip:\s*{\s*url:\s*['"]([^"']+)/; 6631 die "Unable to extract clip URL" unless $clip_url; 6632 $clip_url = URI->new_abs($clip_url, $browser->uri); 6633 6634 my($talk) = $browser->content =~ /class="lecture_archive"[^>]+>([^<]+)/i; 6635 $talk = decode_entities($talk); 6636 6637 my($author) = $browser->content =~ /class="speaker_archive"[^>]+>([^<]+)/i; 6638 $author = decode_entities($author); 6639 6640 return $clip_url, title_to_filename($talk ? "$author - $talk" : $clip_url); 6641} 6642 66431; 6644} 6645##} blib/lib/FlashVideo/Site/Techcast.pm 6646BEGIN { $INC{'FlashVideo/Site/Ted.pm'}++; } 6647# Part of get-flash-videos. See get_flash_videos for copyright. 6648##{ blib/lib/FlashVideo/Site/Ted.pm 6649{ 6650package FlashVideo::Site::Ted; 6651use strict; 6652BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 6653BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *error = \&FlashVideo::Utils::error; } 6654BEGIN { FlashVideo::JSON->import(); } # (added by utils/combine-perl.pl) 6655BEGIN { no strict 'refs'; *from_json = \&FlashVideo::JSON::from_json; } 6656 6657sub find_video { 6658 my ($self, $browser, $embed_url, $prefs) = @_; 6659 6660 my $basefilename; 6661 if ($browser->content =~ m{<noscript.*download.ted.com/talks/([^.]+)\.mp4.*noscript>}s) { 6662 $basefilename = $1; 6663 } else { 6664 die "Unable to find download link"; 6665 } 6666 6667 if ($prefs->subtitles) { 6668 my $lang = ""; 6669 if ($browser->content =~ m{talkID = (\d+);}s) { 6670 my $talkID = $1; 6671 my $intro_time = 15000; 6672 if ($browser->content =~ m{introDuration:(\d+)}s) { 6673 $intro_time = int($1); 6674 } else { 6675 error "Can't find the intro duration, so guessing at 15 seconds."; 6676 } 6677 $ENV{LANG} =~ /^([^_]*)/; 6678 $lang = $1; 6679 if (!$lang) { 6680 info "Unable to determine your language, using English"; 6681 $lang = "en"; 6682 } 6683 info "Downloading subtitles"; 6684 get_subtitles($browser, $basefilename . ".srt", $intro_time, 6685 "http://www.ted.com/talks/subtitles/id/$talkID/lang/$lang/format/json"); 6686 } else { 6687 error "Unable to determine the talk ID, so can't get the subtitles"; 6688 } 6689 } 6690 6691 my $quality = $prefs->{quality}; 6692 if ($quality eq "low") { 6693 $quality = "-light"; 6694 } elsif ($quality eq "medium") { 6695 $quality = ""; 6696 } elsif ($quality eq "high") { 6697 $quality = "-480p"; 6698 } else { 6699 die "Unknown quality setting"; 6700 } 6701 6702 my $url = "http://download.ted.com/talks/" . $basefilename . $quality . ".mp4"; 6703 6704 $browser->allow_redirects; 6705 return $url, $basefilename . ".mp4"; 6706} 6707 6708sub get_subtitles { 6709 my ($browser, $filename, $intro_time, $url) = @_; 6710 $browser->get($url); 6711 if (!$browser->success) { 6712 error "Couldn't download subtitles: " . $browser->response->status_line; 6713 return; 6714 } 6715 json_to_srt($browser->content, $filename, $intro_time); 6716} 6717 6718 6719sub json_to_srt { 6720 my ($subdata, $filename, $intro_time) = @_; 6721 open (SRT, '>', $filename) or die "Can't open subtitles file $filename: $!"; 6722 6723 my $subtitle_count = 0; 6724 my $subdata = from_json($subdata); 6725 6726 foreach my $subtitle (@{ $subdata->{captions} }) { 6727 $subtitle_count++; # SubRip starts at 1 6728 6729 my ($srt_start, $srt_end) = convert_to_srt_time( 6730 $subtitle->{startTime} + $intro_time, 6731 $subtitle->{duration}, 6732 ); 6733 6734 print SRT "$subtitle_count\n" . 6735 "$srt_start --> $srt_end\n" . 6736 "$subtitle->{content}\n\n"; 6737 } 6738 6739 close SRT; 6740} 6741 6742sub convert_to_srt_time { 6743 my ($start, $duration) = @_; 6744 6745 return format_srt_time($start), 6746 format_srt_time($start + $duration); 6747} 6748 6749sub format_srt_time { 6750 my $time = shift; 6751 6752 my $seconds = int($time / 1000); 6753 my $milliseconds = $time - ($seconds * 1_000); 6754 6755 return sprintf "%02d:%02d:%02d,%03d", (gmtime $seconds)[2, 1, 0], 6756 $milliseconds; 6757} 6758 67591; 6760} 6761##} blib/lib/FlashVideo/Site/Ted.pm 6762BEGIN { $INC{'FlashVideo/Site/Theonion.pm'}++; } 6763# Part of get-flash-videos. See get_flash_videos for copyright. 6764##{ blib/lib/FlashVideo/Site/Theonion.pm 6765{ 6766package FlashVideo::Site::Theonion; # horrible casing :( 6767 6768use strict; 6769BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 6770BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *extract_info = \&FlashVideo::Utils::extract_info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 6771 6772sub find_video { 6773 my ($self, $browser) = @_; 6774 6775 if ($browser->response->is_redirect) { 6776 $browser->get( $browser->response->header('Location') ); 6777 6778 if (!$browser->success) { 6779 die "Couldn't follow Onion redirect: " . 6780 $browser->response->status_line; 6781 } 6782 } 6783 6784 my $title; 6785 if ($browser->content =~ /var video_title = "([^"]+)"/) { 6786 $title = $1; 6787 } 6788 else { 6789 $title = extract_info($browser)->{meta_title}; 6790 } 6791 6792 my $filename = title_to_filename($title); 6793 6794 my $url = (FlashVideo::Generic->find_video($browser, $browser->uri))[0]; 6795 6796 return $url, $filename; 6797} 6798 67991; 6800} 6801##} blib/lib/FlashVideo/Site/Theonion.pm 6802BEGIN { $INC{'FlashVideo/Site/Thirteen.pm'}++; } 6803# Part of get-flash-videos. See get_flash_videos for copyright. 6804##{ blib/lib/FlashVideo/Site/Thirteen.pm 6805{ 6806package FlashVideo::Site::Thirteen; 6807use strict; 6808BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 6809BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 6810BEGIN { FlashVideo::JSON->import(); } # (added by utils/combine-perl.pl) 6811BEGIN { no strict 'refs'; *from_json = \&FlashVideo::JSON::from_json; } 6812 6813sub find_video { 6814 my ($self, $browser, $embed_url, $prefs) = @_; 6815 6816 my $iframe; 6817 if ($browser->content =~ /<iframe src="([^"]*)" /) { 6818 $iframe = $1; 6819 } else { 6820 die "Couln't find iframe in " . $browser->uri->as_string; 6821 } 6822 6823 my $url = 'http://www.thirteen.org' . $iframe; 6824 $browser->get($url); 6825 if (!$browser->success) { 6826 die "Couldn't download iframe $url: " . $browser->response->status_line; 6827 } 6828 6829 6830 6831 my $pid; 6832 if ($browser->content =~ /var pid = "([^"]*)";/) { 6833 $pid = $1; 6834 } elsif ($browser->uri->as_string =~ /&pid=([^&]*)&/) { 6835 $pid = $1; 6836 } else { 6837 die "Could not find pid for $url"; 6838 } 6839 6840 my $release_url; 6841 if ($browser->content =~ /so.addVariable\("releaseURL", "([^"]*)"+pid+"([^"]*)"\);/) { 6842 $release_url = $1 . $pid . $2; 6843 } else { 6844 $release_url = "http://release.theplatform.com/content.select?pid=" . $pid . "&format=SMIL&Tracking=true"; 6845 } 6846 6847 $browser->get($release_url); 6848 my $rtmp_url; 6849 if ($browser->response->is_redirect) { 6850 $rtmp_url = $browser->response->header("Location"); 6851 } else { 6852 die "No redirect found for $release_url"; 6853 } 6854 6855 $rtmp_url =~ s/<break>//; 6856 6857 my $filename; 6858 if ($rtmp_url =~ /mp4:(.*)\.mp4$/) { 6859 $filename = title_to_filename($1); 6860 } else { 6861 $filename = title_to_filename(""); 6862 } 6863 6864 6865 return { 6866 rtmp => $rtmp_url, 6867 flv => $filename, 6868 }; 6869} 6870 68711; 6872} 6873##} blib/lib/FlashVideo/Site/Thirteen.pm 6874BEGIN { $INC{'FlashVideo/Site/Todaysbigthing.pm'}++; } 6875# Part of get-flash-videos. See get_flash_videos for copyright. 6876##{ blib/lib/FlashVideo/Site/Todaysbigthing.pm 6877{ 6878package FlashVideo::Site::Todaysbigthing; 6879 6880use strict; 6881BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 6882BEGIN { no strict 'refs'; *extract_title = \&FlashVideo::Utils::extract_title; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 6883 6884my $base = "http://www.todaysbigthing.com/betamax"; 6885 6886sub find_video { 6887 my ($self, $browser, $embed_url) = @_; 6888 6889 my $id; 6890 if($browser->content =~ /item_id=(\d+)/) { 6891 $id = $1; 6892 } elsif($embed_url =~ m![/:](\d+)!) { 6893 $id = $1; 6894 } 6895 die "No ID found\n" unless $id; 6896 6897 $browser->get("$base:$id"); 6898 6899 my $xml = from_xml($browser); 6900 6901 my $title = $xml->{title}; 6902 $title = extract_title($browser) if ref $title; 6903 my $filename = title_to_filename($title); 6904 6905 my $url = $xml->{flv}; 6906 die "No FLV location" unless $url; 6907 6908 return $url, $filename; 6909} 6910 6911sub can_handle { 6912 my($self, $browser, $url) = @_; 6913 6914 return $browser->content =~ $base; 6915} 6916 69171; 6918} 6919##} blib/lib/FlashVideo/Site/Todaysbigthing.pm 6920BEGIN { $INC{'FlashVideo/Site/Tou.pm'}++; } 6921# Part of get-flash-videos. See get_flash_videos for copyright. 6922################################################# 6923# 6924# This file was automatically generated by utils/combine-perl.pl 6925# You should edit the original files, not this 6926# combined version. 6927# 6928# The original files are available at: 6929# http://github.com/monsieurvideo/get-flash-videos 6930# 6931################################################# 6932# tou.tv 6933# 6934# Reverse-engineering details at http://store-it.appspot.com/tou/tou.html 6935# by Sylvain Fourmanoit 6936# 6937# un grand merci a Sylvain qui a tout debrousaille! 6938# 6939# Stavr0 6940# 6941##{ blib/lib/FlashVideo/Site/Tou.pm 6942{ 6943package FlashVideo::Site::Tou; 6944 6945use strict; 6946BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 6947BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; } 6948use URI::Escape; 6949 6950sub find_video { 6951 my ($self, $browser) = @_; 6952 6953 my $video_id; 6954 if ($browser->content =~ /,"pid":"(\w+)"/i) { 6955 $video_id = $1; 6956 } 6957 debug "Video ID = " . $video_id; 6958 6959 die "Couldn't find TOU.TV video ID" unless $video_id; 6960 6961 my $filename; 6962 if ($browser->content =~ /,"titleId":"([^"]+)"/i) { 6963 $filename = $1 ; 6964 } 6965 debug "Filename = " . $filename; 6966 6967 $browser->get("http://release.theplatform.com/content.select?pid=$video_id"); 6968 6969 die "Couldn't download TOU.TV XML: " . $browser->response->status_line 6970 if !$browser->success; 6971 6972 my $url; 6973 if ($browser->content =~ /(rtmp:[^\<]+)/i) { 6974 $url = uri_unescape($1); 6975 } 6976 debug "URL = " . $url; 6977 6978 my $auth; 6979 if ($url =~ /auth=([^&]+)/i) { 6980 $auth = uri_unescape($1); 6981 } 6982 debug "AUTH = " . $auth; 6983 6984 my $app; 6985 if ($url =~ /(ondemand\/.+)/i) { 6986 $app = uri_unescape($1); 6987 } 6988 debug "APP = " . $app; 6989 6990 my $playpath; 6991 if ($url =~ /<break>(.+)/i) { 6992 $playpath = uri_unescape($1); 6993 } 6994 debug "PLAYPATH = " . $playpath; 6995 6996 6997 return { 6998 app => $app, 6999 pageUrl => $url, 7000 swfUrl => "http://static.tou.tv/lib/ThePlatform/4.1.2/swf/flvPlayer.swf", 7001 tcUrl => $url, 7002 auth => $auth, 7003 rtmp => $url, 7004 playpath => $playpath, 7005 flv => "$filename.flv", 7006 }; 7007} 7008 7009sub search { 7010 my($self, $search, $type) = @_; 7011 7012 my $browser = FlashVideo::Mechanize->new; 7013 $browser->get("http://www.tou.tv/recherche?q=" . uri_escape($search)); 7014 return unless $browser->success; 7015 7016 my $results = $browser->content; 7017 7018 my @emissions; 7019 my @links; 7020 7021 while($results =~ /<a\s+href="([^"]+)"\s+id="[^"]+"\s+class="([^"]+)/g) { 7022 debug $1; 7023 if($2 eq "tousEpisodes") { 7024 push @emissions, $1; 7025 } 7026 } 7027 7028 for my $emission (@emissions) { 7029 $browser->get($emission); 7030 my $liste = $browser->content; 7031 7032 while($liste =~ /<a.+class="episode".+href="([^"]+)".+>(.+)<\/a>/g) { 7033 push @links, { name => $1, url => "http://www.tou.tv$1", description => $2 }; 7034 } 7035 } 7036 7037 return @links; 7038} 7039 70401; 7041} 7042##} blib/lib/FlashVideo/Site/Tou.pm 7043BEGIN { $INC{'FlashVideo/Site/Traileraddict.pm'}++; } 7044# Part of get-flash-videos. See get_flash_videos for copyright. 7045##{ blib/lib/FlashVideo/Site/Traileraddict.pm 7046{ 7047package FlashVideo::Site::Traileraddict; 7048 7049use strict; 7050BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7051BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 7052use URI::Escape; 7053 7054sub find_video { 7055 my ($self, $browser) = @_; 7056 7057 my $video_id; 7058 if ($browser->content =~ m'/em[db]/(\d+)') { 7059 $video_id = $1; 7060 } 7061 else { 7062 die "Unable to get Traileraddict video ID"; 7063 } 7064 7065 my $video_info_url = "http://www.traileraddict.com/fvar.php?tid=$video_id"; 7066 7067 $browser->get($video_info_url); 7068 7069 if (!$browser->success) { 7070 die "Couldn't download Traileraddict video info URL: " . 7071 $browser->response->status_line; 7072 } 7073 7074 my %info = parse_video_info($browser->content); 7075 7076 die "Couldn't find Traileraddict video URL" unless $info{fileurl}; 7077 7078 $browser->head($info{fileurl}); 7079 if ($browser->response->is_redirect()) { 7080 $info{fileurl} = $browser->response->header('Location'); 7081 } 7082 7083 my $type = $info{fileurl} =~ /\.mp4/i ? 'mp4' : 'flv'; 7084 7085 return $info{fileurl}, title_to_filename($info{title}, $type); 7086} 7087 7088sub parse_video_info { 7089 my $raw_video_info = shift; 7090 7091 my %info; 7092 7093 foreach my $pair (split /&/, $raw_video_info) { 7094 $pair = uri_unescape($pair); 7095 7096 my ($name, $value) = split /=/, $pair; 7097 7098 $info{$name} = $value; 7099 } 7100 7101 return %info; 7102} 7103 71041; 7105} 7106##} blib/lib/FlashVideo/Site/Traileraddict.pm 7107BEGIN { $INC{'FlashVideo/Site/Truveo.pm'}++; } 7108# Part of get-flash-videos. See get_flash_videos for copyright. 7109##{ blib/lib/FlashVideo/Site/Truveo.pm 7110{ 7111package FlashVideo::Site::Truveo; 7112 7113use strict; 7114BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7115BEGIN { no strict 'refs'; *url_exists = \&FlashVideo::Utils::url_exists; } 7116 7117sub find_video { 7118 my($self, $browser, $embed_url, $prefs) = @_; 7119 7120 my($videourl) = $browser->content =~ /var videourl = "(.*?)"/; 7121 7122 $videourl = $embed_url 7123 if !$videourl && $browser->uri->host eq 'xml.truveo.com'; 7124 7125 die "videourl not found" unless $videourl; 7126 7127 $browser->get($videourl); 7128 7129 if($browser->content =~ /url=(http:.*?)["']/) { 7130 my $redirect = url_exists($browser, $1); 7131 7132 $browser->get($redirect); 7133 7134 my($package, $possible_url) = FlashVideo::URLFinder->find_package($redirect, $browser); 7135 7136 die "Recursion detected" if $package eq __PACKAGE__; 7137 7138 return $package->find_video($browser, $possible_url, $prefs); 7139 } else { 7140 die "Redirect URL not found"; 7141 } 7142} 7143 71441; 7145} 7146##} blib/lib/FlashVideo/Site/Truveo.pm 7147BEGIN { $INC{'FlashVideo/Site/Tudou.pm'}++; } 7148##{ blib/lib/FlashVideo/Site/Tudou.pm 7149{ 7150package FlashVideo::Site::Tudou; 7151 7152use strict; 7153BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7154BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 7155 7156sub find_video { 7157 my ($self, $browser, $embed_url) = @_; 7158 7159 my $check_response = sub { 7160 my ( $message ) = @_; 7161 return if $browser->success; 7162 die sprintf $message, $browser->response->code; 7163 }; 7164 7165 7166 my $videoID = 0; 7167 7168 if ( $embed_url =~ m`hd.tudou.com/program/\w+` ) 7169 { 7170 ( $videoID ) = ( $browser->content =~ /iid: "(\w+)"/ ); 7171 } 7172 7173 else 7174 { 7175 if ( $embed_url =~ m`tudou.com/programs/view/(.+)$` ) 7176 { 7177 $embed_url = sprintf "http://www.tudou.com/v/%s", $1; 7178 $browser->get( $embed_url ); 7179 } 7180 7181 if ( $browser->response->code eq 302 and $embed_url =~ m`tudou.com/v/(.+)$` ) 7182 { 7183 $embed_url = $browser->response->header( 'Location' ); 7184 } 7185 7186 ( $videoID ) = ( $embed_url =~ m`\.swf\?iid=(\d+)` ); 7187 } 7188 7189 die "Couldn't extract video ID, we are out probably out of date" unless $videoID; 7190 debug "Using video ID $videoID"; 7191 7192 $browser->get( 7193 sprintf "http://v2.tudou.com/v2/kili?safekey=%s&id=%s&noCatch=%d", 7194 'YouNeverKnowThat', $videoID, rand( 10000 ) ); 7195 7196 if ( not $browser->success ) 7197 { 7198 debug 'Using fallback tudou link for video info'; 7199 $browser->get( 7200 sprintf "http://v2.tudou.com/v2/cdn?safekey=%s&id=%s&noCatch=%d", 7201 'YouNeverKnowThat', $videoID, rand( 10000 ) ); 7202 } 7203 $check_response->( "Couldn't grab video informaton from tudou, server response was %s" ); 7204 7205 return parse_video_info( $browser->content ); 7206} 7207 7208sub parse_video_info { 7209 my ( $raw_xml ) = @_; 7210 7211 7212 my $xml = from_xml($raw_xml, forcearray => [ 'f' ] ); 7213 7214 my %streams; 7215 foreach my $file ( @{$xml->{b}->{f}} ) 7216 { 7217 my $url = $file->{content}; 7218 7219 my ( $format ) = ( $url =~ m`http://[^/]+/([^/]+)/` ); 7220 debug "Unable to extract file format for $url" and next 7221 unless $format; 7222 7223 push @{$streams{$format}{urls}}, $url; 7224 $streams{$format}{size} = $file->{size}; 7225 } 7226 7227 my $stream 7228 = ( exists $streams{mp4} ? 'mp4' 7229 : exists $streams{m4v} ? 'm4v' 7230 : exists $streams{flv} ? 'flv' 7231 : exists $streams{wwwFlv} ? 'wwwFlv' 7232 : exists $streams{f4v} ? 'f4v' 7233 : exists $streams{phoneMp4} ? 'phoneMp4' 7234 : '' ); 7235 7236 my $stream_formats = join ', ', ( keys %streams ); 7237 die "Video is only available in unknown file formats ($stream_formats)", 7238 unless $stream; 7239 7240 debug "Choosing to use the $stream stream (available: $stream_formats)"; 7241 my $stream_choice = int rand( 1 + $#{$streams{$stream}{urls}} ); 7242 my $url = @{$streams{$stream}{urls}}[$stream_choice]; 7243 7244 my $sourceID = ( $stream eq 'flv' ? '11000' : '18000' ); 7245 $url =~ s/\?key=/?$sourceID&key=/; 7246 7247 my $title = $xml->{title}; 7248 my $filename = title_to_filename( $title, 'flv' ); 7249 7250 my $stream_duration = $xml->{time}; 7251 my $stream_size = $streams{$stream}{size}; 7252 debug sprintf 7253 "%s, %d seconds, %s bytes", 7254 $title, $stream_duration / 1000, $stream_size 7255 if ( $title and $stream_duration and $stream_size ); 7256 7257 return ( $url, $filename ); 7258} 7259 72601; 7261} 7262##} blib/lib/FlashVideo/Site/Tudou.pm 7263BEGIN { $INC{'FlashVideo/Site/Tv.pm'}++; } 7264# Part of get-flash-videos. See get_flash_videos for copyright. 7265##{ blib/lib/FlashVideo/Site/Tv.pm 7266{ 7267package FlashVideo::Site::Tv; 7268 7269use strict; 7270BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7271BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 7272BEGIN { FlashVideo::JSON->import(); } # (added by utils/combine-perl.pl) 7273BEGIN { no strict 'refs'; } 7274 7275sub find_video { 7276 my($self, $browser, $embed_url, $prefs) = @_; 7277 7278 7279 my $pid; 7280 if ($browser->content =~ /so.addVariable\("pid", "([^"]*)"\);/) { 7281 $pid = $1; 7282 } else { 7283 die "Could not find PID for video! " . $browser->uri->as_string; 7284 } 7285 7286 my $url = "http://release.theplatform.com/content.select?format=SMIL&Tracking=true&balance=true&pid=$pid"; 7287 $browser->get($url); 7288 if (!$browser->success) { 7289 die "Couldn't download content.select $url: " . $browser->response->status_line; 7290 } 7291 7292 my $xml = from_xml($browser); 7293 my $items = $xml->{body}->{ref}; 7294 my $item = ref $items eq 'ARRAY' ? 7295 (grep { $_->{src} =~ /^rtmp:\/\// } @$items)[0] : 7296 $items; 7297 7298 my $filename = title_to_filename($item->{title}); 7299 7300 my $playpath = ""; 7301 my $rtmpurl = $item->{src}; 7302 7303 $rtmpurl =~ s/<break>.*//; 7304 7305 return { 7306 flv => $filename, 7307 rtmp => $rtmpurl, 7308 }; 7309} 7310 7311sub can_handle { 7312 my($self, $browser, $url) = @_; 7313 return $browser->uri->host =~ /(^|\.)tv\.com$/; 7314} 7315 73161; 7317} 7318##} blib/lib/FlashVideo/Site/Tv.pm 7319BEGIN { $INC{'FlashVideo/Site/Tv3play.pm'}++; } 7320# Part of get-flash-videos. See get_flash_videos for copyright. 7321##{ blib/lib/FlashVideo/Site/Tv3play.pm 7322{ 7323package FlashVideo::Site::Tv3play; 7324use strict; 7325BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7326BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *convert_sami_subtitles_to_srt = \&FlashVideo::Utils::convert_sami_subtitles_to_srt; } 7327 7328 7329sub find_video { 7330 my ($self, $browser, $embed_url, $prefs) = @_; 7331 return $self->find_video_viasat($browser,$embed_url,$prefs); 7332} 7333 7334sub find_video_viasat { 7335 my ($self, $browser, $embed_url, $prefs) = @_; 7336 my $video_id = ($browser->content =~ /id:([0-9]*),/)[0]; 7337 info "Got video_id: $video_id"; 7338 my $info_url = "http://viastream.viasat.tv/PlayProduct/$video_id"; 7339 $browser->get($info_url); 7340 my $variable = $browser->content; 7341 $variable =~ s/\n//g; 7342 my $title = ($variable =~ /<Title><!\[CDATA\[(.*?)\]\]><\/Title>/)[0]; 7343 my $flv_filename = title_to_filename($title, "flv"); 7344 7345 7346 7347 my @urls; 7348 my $count = 0; 7349 my $base = ($variable =~ /<Videos>(.*)<\/Videos>/)[0]; 7350 for ($count = 0; $count < 3; $count++){ 7351 my $video = ($base =~ /<Video>(.+)<\/Video>/p)[0]; 7352 if ($video eq ''){last;}; 7353 $base = ${^POSTMATCH}; 7354 my $bitrate = ($video =~ /<BitRate>([0-9]*)<\/BitRate>/)[0]; 7355 my $url = ($video =~ /<Url><!\[CDATA\[(.*)]]><\/Url>/)[0]; 7356 if (not (($url =~ /http:\/\//)[0] eq '')){ 7357 $browser->get($url); 7358 $variable = $browser->content; 7359 $variable =~ s/\n//g; 7360 $url = ($variable =~ /<Url>(.*)<\/Url>/)[0]; 7361 } 7362 7363 $urls[$count++] = { 'bitrate' => $bitrate, 7364 'rtmp' => $url 7365 }; 7366 } 7367 my $bitrate = 0; 7368 my $rtmp; 7369 my $new_bitrate; 7370 7371 foreach (@urls) { 7372 $new_bitrate = int($_->{bitrate}); 7373 if($new_bitrate > $bitrate){ 7374 $bitrate = int($_->{bitrate}); 7375 $rtmp = $_->{rtmp}; 7376 } 7377 }; 7378 7379 7380 return{ 7381 rtmp => $rtmp, 7382 swfVfy => "http://flvplayer-viastream-viasat-tv.origin.vss.viasat.tv/play/swf/player110420.swf", 7383 flv => $flv_filename 7384 }; 7385 7386 7387} 7388 73891; 7390} 7391##} blib/lib/FlashVideo/Site/Tv3play.pm 7392BEGIN { $INC{'FlashVideo/Site/Tv4play.pm'}++; } 7393# Part of get-flash-videos. See get_flash_videos for copyright. 7394##{ blib/lib/FlashVideo/Site/Tv4play.pm 7395{ 7396package FlashVideo::Site::Tv4play; 7397use strict; 7398BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7399BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *convert_sami_subtitles_to_srt = \&FlashVideo::Utils::convert_sami_subtitles_to_srt; *from_xml = \&FlashVideo::Utils::from_xml; } 7400 7401sub find_video { 7402 my ($self, $browser, $embed_url, $prefs) = @_; 7403 my $vid = ($embed_url =~ /videoid=([0-9]*)/)[0]; 7404 my $smi_url = "http://premium.tv4play.se/api/web/asset/$vid/play"; 7405 7406 my $title = ($browser->content =~ /property="og:title" content="(.*?)"/)[0]; 7407 my $flv_filename = title_to_filename($title, "flv"); 7408 7409 $browser->get($smi_url); 7410 my $content = from_xml($browser); 7411 my $i = 0; 7412 my @dump; 7413 my $subtitle_url; 7414 for ($i = 0; $i < 5; $i++){ 7415 my $format = $content->{items}->{item}[$i]->{mediaFormat}; 7416 my $bitrate = $content->{items}->{item}[$i]->{bitrate}; 7417 my $rtmp = $content->{items}->{item}[$i]->{base}; 7418 my $mp4 = $content->{items}->{item}[$i]->{url}; 7419 @dump[$i] = { 'rtmp' => $rtmp, 7420 'bitrate' => $bitrate, 7421 'mp4' => $mp4, 7422 'format' => $format 7423 }; 7424 } 7425 foreach (@dump) { 7426 if($_->{format} eq 'smi'){ $subtitle_url = $_->{mp4};} 7427 } 7428 debug "Subtitle_url: $subtitle_url"; 7429 7430 7431 7432 return { 7433 rtmp => $dump[0]->{rtmp}, 7434 swfVfy => "http://www.tv4play.se/flash/tv4playflashlets.swf", 7435 playpath => $dump[0]->{mp4}, 7436 flv => $flv_filename 7437 }; 7438 7439} 7440 74411; 7442} 7443##} blib/lib/FlashVideo/Site/Tv4play.pm 7444BEGIN { $INC{'FlashVideo/Site/Tv6play.pm'}++; } 7445# Part of get-flash-videos. See get_flash_videos for copyright. 7446##{ blib/lib/FlashVideo/Site/Tv6play.pm 7447{ 7448package FlashVideo::Site::Tv6play; 7449use strict; 7450BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7451BEGIN { no strict 'refs'; } 7452BEGIN { FlashVideo::Site::Tv3play->import(); } # (added by utils/combine-perl.pl) 7453use base 'FlashVideo::Site::Tv3play'; 7454 7455 7456sub find_video { 7457 my ($self, $browser, $embed_url, $prefs) = @_; 7458 return $self->find_video_viasat($browser,$embed_url,$prefs); 7459} 74601; 7461} 7462##} blib/lib/FlashVideo/Site/Tv6play.pm 7463BEGIN { $INC{'FlashVideo/Site/Tv8play.pm'}++; } 7464# Part of get-flash-videos. See get_flash_videos for copyright. 7465##{ blib/lib/FlashVideo/Site/Tv8play.pm 7466{ 7467package FlashVideo::Site::Tv8play; 7468use strict; 7469BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7470BEGIN { no strict 'refs'; } 7471BEGIN { FlashVideo::Site::Tv3play->import(); } # (added by utils/combine-perl.pl) 7472use base 'FlashVideo::Site::Tv3play'; 7473 7474 7475sub find_video { 7476 my ($self, $browser, $embed_url, $prefs) = @_; 7477 return $self->find_video_viasat($browser,$embed_url,$prefs); 7478} 74791; 7480} 7481##} blib/lib/FlashVideo/Site/Tv8play.pm 7482BEGIN { $INC{'FlashVideo/Site/Tva.pm'}++; } 7483# Part of get-flash-videos. See get_flash_videos for copyright. 7484##{ blib/lib/FlashVideo/Site/Tva.pm 7485{ 7486package FlashVideo::Site::Tva; 7487 7488use strict; 7489BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7490BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; } 7491BEGIN { FlashVideo::Site::Brightcove->import(); } # (added by utils/combine-perl.pl) 7492use base 'FlashVideo::Site::Brightcove'; 7493 7494sub find_video { 7495 my ($self, $browser, $embed_url) = @_; 7496 7497 my $video_id = ($browser->content =~ /player.SetVideo.(\d+)/i)[0]; 7498 my $player_id = ($browser->content =~ /player.SetPlayer.(\d+)/i)[0]; 7499 7500 debug "Extracted playerId: $player_id, videoId: $video_id" 7501 if $player_id or $video_id; 7502 7503 if(!$video_id) { 7504 my $video_offset = ($browser->content =~ /player.SetVideo.\w+\[(\d+)/i)[0]; 7505 $video_id = ($browser->content =~ /videos\[$video_offset\].+'(\d+)'\s*\]/)[0]; 7506 } 7507 7508 die "Unable to extract Brightcove IDs from page" 7509 unless $player_id and $video_id; 7510 7511 return $self->amfgateway($browser, $player_id, { videoId => $video_id, } ); 7512} 7513 7514sub can_handle { 7515 my($self, $browser, $url) = @_; 7516 7517 return $browser->content =~ /player = CanoeVideoStandalone\.create\(\);/i; 7518} 7519 75201; 7521} 7522##} blib/lib/FlashVideo/Site/Tva.pm 7523BEGIN { $INC{'FlashVideo/Site/Ustream.pm'}++; } 7524# Part of get-flash-videos. See get_flash_videos for copyright. 7525##{ blib/lib/FlashVideo/Site/Ustream.pm 7526{ 7527package FlashVideo::Site::Ustream; 7528 7529use strict; 7530BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7531BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; *extract_info = \&FlashVideo::Utils::extract_info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 7532use MIME::Base64; 7533 7534sub find_video { 7535 my ($self, $browser, $embed_url) = @_; 7536 7537 unless(eval { require Data::AMF::Packet }) { 7538 die "Must have Data::AMF::Packet installed to download ustream videos"; 7539 } 7540 7541 my $packet = Data::AMF::Packet->deserialize(decode_base64(<<EOF)); 7542AAAAAAABAA9WaWV3ZXIuZ2V0VmlkZW8AAi8xAAAAiAoAAAABAwAIYXV0b3BsYXkBAQAEcnBpbgIA 7543GHJwaW4uMC4xODM2MDk4NTkzMTY0Njg5OAAHdmlkZW9JZAIABzIzNTU3MzYAB3BhZ2VVcmwCACZo 7544dHRwOi8vd3d3LnVzdHJlYW0udHYvcmVjb3JkZWQvMjM1NTczNgAHYnJhbmRJZAIAATEAAAkK 7545EOF 7546 7547 my $title = extract_info($browser)->{meta_title}; 7548 7549 my($video_id) = $browser->uri =~ m{recorded/(\d+)}; 7550 $video_id ||= $browser->content =~ m{vid\s*=\s*["']?(\d+)}; 7551 7552 $packet->messages->[0]->{value}->[0]->{videoId} = $video_id; 7553 7554 my $data = $packet->serialize; 7555 7556 $browser->post( 7557 "http://rgw.ustream.tv/gateway.php", 7558 Content_Type => "application/x-amf", 7559 Content => $data 7560 ); 7561 7562 die "Failed to post to Ustream AMF gateway" 7563 unless $browser->response->is_success; 7564 7565 my($flv_url) = $browser->content =~ /flv.{3,5}(http:[^\0]+)/; 7566 7567 return $flv_url, title_to_filename($title); 7568} 7569 75701; 7571} 7572##} blib/lib/FlashVideo/Site/Ustream.pm 7573BEGIN { $INC{'FlashVideo/Site/Videobb.pm'}++; } 7574# Part of get-flash-videos. See get_flash_videos for copyright. 7575##{ blib/lib/FlashVideo/Site/Videobb.pm 7576{ 7577package FlashVideo::Site::Videobb; 7578 7579use strict; 7580BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7581BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 7582BEGIN { FlashVideo::JSON->import(); } # (added by utils/combine-perl.pl) 7583BEGIN { no strict 'refs'; *from_json = \&FlashVideo::JSON::from_json; } 7584use MIME::Base64; 7585 7586sub find_video { 7587 my ($self, $browser) = @_; 7588 7589 if($browser->status == 302) { 7590 $browser->allow_redirects; 7591 $browser->get; 7592 } 7593 my $flash_settings_b64 = ($browser->content =~ /<param value="setting=([^"]+)" name="FlashVars">/s)[0]; 7594 my $flash_settings = decode_base64($flash_settings_b64); 7595 7596 $browser->get($flash_settings); 7597 7598 if (!$browser->success) { 7599 die "Couldn't download video settings: " . $browser->response->status_line; 7600 } 7601 7602 my $settings_data = from_json($browser->content); 7603 7604 my $url = decode_base64($settings_data->{settings}{res}->[-1]->{u}); 7605 7606 my $title = $settings_data->{settings}{video_details}{video}{title}; 7607 my $filename = title_to_filename($title); 7608 7609 return $url, $filename; 7610} 7611 76121; 7613} 7614##} blib/lib/FlashVideo/Site/Videobb.pm 7615BEGIN { $INC{'FlashVideo/Site/Videojug.pm'}++; } 7616# Part of get-flash-videos. See get_flash_videos for copyright. 7617##{ blib/lib/FlashVideo/Site/Videojug.pm 7618{ 7619package FlashVideo::Site::Videojug; 7620 7621use strict; 7622BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7623BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 7624 7625my $playlist_url = "http://www.videojug.com/views/film/playlist.aspx?items=&userName=&ar=16_9&id="; 7626 7627sub find_video { 7628 my ($self, $browser) = @_; 7629 7630 my $interview_clip; 7631 7632 if ($browser->uri->as_string =~ m'/interview/'i) { 7633 $playlist_url = 7634 "http://www.videojug.com/views/interview/playlist.aspx?ar=16_9&id="; 7635 7636 $interview_clip = $browser->uri->fragment; 7637 } 7638 7639 my $video_id; 7640 7641 if ($browser->content =~ 7642 /<meta name=["']video-id["'] content="([A-F0-9a-f\-]+)"/) { 7643 $video_id = $1; 7644 } else { 7645 die "Couldn't find video ID in Videojug page"; 7646 } 7647 7648 $browser->get($playlist_url . $video_id); 7649 7650 7651 my($video_url, $filename); 7652 eval { 7653 my $xml = from_xml($browser); 7654 7655 my $shape = $xml->{Shapes}->{Shape}->[-1]; 7656 my $location = (grep { $shape->{Locations} =~ /\Q$_->{Name}\E/ } 7657 @{$xml->{Locations}->{Location}})[0]; 7658 7659 my ($prefix, $title); 7660 7661 if ($interview_clip) { 7662 ($prefix, $title) = get_prefix_and_title($xml, $interview_clip); 7663 } 7664 else { 7665 $prefix = $xml->{Items}->{Media}->{Prefix}; 7666 $title = $xml->{Items}->{Media}->{Title}; 7667 } 7668 7669 $video_url = sprintf "%s%s__%sENG.flv", 7670 $location->{Url}, $prefix, $shape->{Code}; 7671 7672 $filename = title_to_filename($title); 7673 }; 7674 die "Unable to retrieve/parse Videojug playlist. $@" if $@; 7675 7676 die "Couldn't find video URL" unless $video_url; 7677 7678 return $video_url, $filename; 7679} 7680 7681sub get_prefix_and_title { 7682 my ($xml, $video_name) = @_; 7683 7684 foreach my $media (@{ $xml->{Items}->{Media} }) { 7685 my $title = lc $media->{Title}; 7686 $title =~ s/ /-/g; 7687 $title =~ s/[^a-z0-9\-]//g; 7688 7689 if ($title eq $video_name) { 7690 return $media->{Prefix}, $media->{Title}; 7691 } 7692 } 7693 7694 die "Couldn't find prefix for video '$video_name'"; 7695} 7696 76971; 7698} 7699##} blib/lib/FlashVideo/Site/Videojug.pm 7700BEGIN { $INC{'FlashVideo/Site/Videolectures.pm'}++; } 7701# Part of get-flash-videos. See get_flash_videos for copyright. 7702##{ blib/lib/FlashVideo/Site/Videolectures.pm 7703{ 7704package FlashVideo::Site::Videolectures; 7705 7706use strict; 7707BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7708BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 7709 7710sub find_video { 7711 my ($self, $browser) = @_; 7712 7713 my $author = ($browser->content =~ /author:\s*<\/span><a [^>]+>([^<]+)/s)[0]; 7714 my $title = ($browser->content =~ /<h2>([^<]+)/)[0]; 7715 7716 my $streamer = ($browser->content =~ /clip\.netConnectionUrl\s*=\s*["']([^"']+)/)[0]; 7717 my $playpath = ($browser->content =~ /clip\.url\s*=\s*["']([^"']+)/)[0]; 7718 $playpath =~ s/\.flv$//; 7719 7720 my $data = { 7721 app => (split m{/}, $streamer)[-1], 7722 rtmp => $streamer, 7723 playpath => $playpath, 7724 flv => title_to_filename("$author - $title") 7725 }; 7726 7727 return $data; 7728} 7729 77301; 7731} 7732##} blib/lib/FlashVideo/Site/Videolectures.pm 7733BEGIN { $INC{'FlashVideo/Site/Vimeo.pm'}++; } 7734# Part of get-flash-videos. See get_flash_videos for copyright. 7735##{ blib/lib/FlashVideo/Site/Vimeo.pm 7736{ 7737package FlashVideo::Site::Vimeo; 7738 7739use strict; 7740BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7741BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 7742 7743sub find_video { 7744 my ($self, $browser, $embed_url) = @_; 7745 my $base = "http://vimeo.com/moogaloop"; 7746 7747 my $id; 7748 if($embed_url =~ /clip_id=(\d+)/) { 7749 $id = $1; 7750 } elsif($embed_url =~ m!/(\d+)!) { 7751 $id = $1; 7752 } 7753 die "No ID found\n" unless $id; 7754 7755 $browser->get("$base/load/clip:$id/embed?param_fullscreen=1¶m_clip_id=$id¶m_show_byline=0¶m_server=vimeo.com¶m_color=cc6600¶m_show_portrait=0¶m_show_title=1"); 7756 7757 my $xml = from_xml($browser); 7758 my $filename = title_to_filename($xml->{video}->{caption}); 7759 my $request_signature = $xml->{request_signature}; 7760 my $request_signature_expires = $xml->{request_signature_expires}; 7761 my $isHD = $xml->{video}->{isHD}; 7762 7763 $browser->allow_redirects; 7764 7765 my $url = "$base/play/clip:$id/$request_signature/$request_signature_expires/?q=hd&type=embed"; 7766 if ($isHD == '1') { 7767 return $url, $filename; 7768 }; 7769 $url = "$base/play/clip:$id/$request_signature/$request_signature_expires/?q=sd&type=embed"; 7770 return $url, $filename; 7771} 7772 77731; 7774} 7775##} blib/lib/FlashVideo/Site/Vimeo.pm 7776BEGIN { $INC{'FlashVideo/Site/Vrak.pm'}++; } 7777##{ blib/lib/FlashVideo/Site/Vrak.pm 7778{ 7779package FlashVideo::Site::Vrak; 7780 7781use strict; 7782BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7783BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *from_xml = \&FlashVideo::Utils::from_xml; } 7784no strict 'refs'; 7785 7786 7787 7788sub find_video { 7789 my($self, $browser, $embed_url, $prefs) = @_; 7790 7791 my $check_response = sub { 7792 my ( $message ) = @_; 7793 return if $browser->success; 7794 die sprintf $message, $browser->response->code; 7795 }; 7796 7797 7798 my $videoID = 0; 7799 7800 ( $videoID ) = ( $browser->content =~ /var\s+videoId\s*=\s*(\d+)\s*;/i ); 7801 debug "VIDEOID = " . $videoID; 7802 7803 die "No Vrak Video ID found" unless $videoID; 7804 7805 my $title; 7806 ( $title ) = ( $browser->content =~ /var\s+videoTitle\s*=\s*"([^"]+)/i ); 7807 7808 debug "TITLE = " . $title . " " . title_to_filename($title, 'flv'); 7809 7810 my $xmlurl = 'http://www.vrak.tv/webtele/_dyn/getVideoDataXml.jsp?videoId=' . $videoID; 7811 $browser->get($xmlurl); 7812 my $xml = from_xml($browser); 7813 7814 my $url; 7815 if ( $prefs->{quality} == "high" ) { 7816 $url = $xml->{video}->{highFlvUrl}; 7817 } else { 7818 $url = $xml->{video}->{lowFlvUrl}; 7819 } 7820 debug "URL = " . $url; 7821 7822 my $ext; 7823 ( $ext ) = ( $url =~ /\.(.+)$/i ); 7824 7825 die "No (high|low)FlvUrl found in XML ". $xmlurl unless $url; 7826 7827 return $url, title_to_filename($title); 7828 7829 } 7830 78311; 7832 7833} 7834##} blib/lib/FlashVideo/Site/Vrak.pm 7835BEGIN { $INC{'FlashVideo/Site/Wat.pm'}++; } 7836# Part of get-flash-videos. See get_flash_videos for copyright. 7837##{ blib/lib/FlashVideo/Site/Wat.pm 7838{ 7839package FlashVideo::Site::Wat; 7840 7841use strict; 7842BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7843BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *json_unescape = \&FlashVideo::Utils::json_unescape; } 7844use HTML::Entities; 7845use URI::Escape; 7846 7847die "Must have Digest::MD5 for this download\n" 7848 unless eval { 7849 require Digest::MD5; 7850 }; 7851 7852sub token { 7853 my $url = shift; 7854 my $hexdate = sprintf("%x",time()); 7855 $hexdate .= "0" x (length($hexdate) - 8); 7856 my $key = "9b673b13fa4682ed14c3cfa5af5310274b514c4133e9b3a81e6e3aba00912564"; 7857 return Digest::MD5::md5_hex($key . $url . $hexdate)."/".$hexdate; 7858} 7859 7860 7861sub find_video { 7862 my ($self, $browser) = @_; 7863 7864 $browser->content =~ /url\s*:\s*["'].*?nIc0K11(\d+)["']/i 7865 || die "No video ID found"; 7866 my $video_id = $1; 7867 7868 $browser->get("http://www.wat.tv/interface/contentv3/$video_id"); 7869 7870 my $title = json_unescape(($browser->content =~ /title":"(.*?)",/)[0]); 7871 7872 my $location = "/web/$video_id"; 7873 my $token = &token($location); 7874 7875 my $url = "http://www.wat.tv/get".$location. 7876 "?token=".$token. 7877 "&context=swf2&getURL=1&version=WIN%2010,3,181,14"; 7878 7879 my $file_type = 'flv'; 7880 7881 $browser->head($url); 7882 7883 if (!$browser->success) { 7884 die "Couldn't do HEAD request $url: " . $browser->response->status_line; 7885 } 7886 7887 my $content_type = $browser->response->header('Content-Type'); 7888 if ($content_type =~ /text/) { 7889 $browser->get($url); 7890 7891 if (!$browser->success) { 7892 die "Couldn't get $url: " . $browser->response->status_line; 7893 } 7894 7895 if ($browser->content =~ m'^(http://\S+)') { 7896 $url = $1; 7897 7898 if ($url =~ /\.h264/) { 7899 $file_type = 'mp4'; 7900 } 7901 } 7902 } 7903 else { 7904 die "Unexpected Content-Type ($content_type) from Wat server."; 7905 } 7906 7907 my $filename = title_to_filename($title, $file_type); 7908 7909 $browser->allow_redirects; 7910 7911 return $url, $filename; 7912} 7913 79141; 7915} 7916##} blib/lib/FlashVideo/Site/Wat.pm 7917BEGIN { $INC{'FlashVideo/Site/Xhamster.pm'}++; } 7918# Part of get-flash-videos. See get_flash_videos for copyright. 7919##{ blib/lib/FlashVideo/Site/Xhamster.pm 7920{ 7921package FlashVideo::Site::Xhamster; 7922 7923use strict; 7924BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7925BEGIN { no strict 'refs'; *extract_title = \&FlashVideo::Utils::extract_title; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 7926 7927sub find_video { 7928 my ($self, $browser) = @_; 7929 7930 my $server; 7931 if ($browser->content =~ m{'srv': '(http://[^'"]+)'}) { 7932 $server = $1; 7933 } 7934 else { 7935 die "Couldn't determine xhamster server"; 7936 } 7937 7938 my $video_file; 7939 if ($browser->content =~ m{'file': '([^'"]+\.flv)'}) { 7940 $video_file = $1; 7941 } 7942 else { 7943 die "Couldn't determine xhamster video filename"; 7944 } 7945 7946 my $filename = title_to_filename(extract_title($browser)); 7947 7948 my $url = sprintf "%s/flv2/%s", $server, $video_file; 7949 7950 $browser->allow_redirects; 7951 7952 return $url, $filename; 7953} 7954 79551; 7956} 7957##} blib/lib/FlashVideo/Site/Xhamster.pm 7958BEGIN { $INC{'FlashVideo/Site/Xnxx.pm'}++; } 7959# Part of get-flash-videos. See get_flash_videos for copyright. 7960##{ blib/lib/FlashVideo/Site/Xnxx.pm 7961{ 7962package FlashVideo::Site::Xnxx; 7963 7964use strict; 7965BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 7966BEGIN { no strict 'refs'; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 7967use URI::Escape; 7968 7969sub find_video { 7970 my ($self, $browser, $embed_url) = @_; 7971 7972 my $url = ($browser->content =~ /flv_url=(.+?)&/)[0]; 7973 $url = uri_unescape($url); 7974 die "Unable to extract url" unless $url; 7975 7976 $browser->content =~ /(?:<span class="style5">|<td style="font-size: 20px;">\s*)<strong>([^<]+)/; 7977 7978 my $filename = title_to_filename($1); 7979 7980 return $url, $filename; 7981} 7982 79831; 7984} 7985##} blib/lib/FlashVideo/Site/Xnxx.pm 7986BEGIN { $INC{'FlashVideo/Site/Xvideos.pm'}++; } 7987# Part of get-flash-videos. See get_flash_videos for copyright. 7988##{ blib/lib/FlashVideo/Site/Xvideos.pm 7989{ 7990package FlashVideo::Site::Xvideos; 7991 7992use strict; 7993BEGIN { FlashVideo::Site::Xnxx->import(); } # (added by utils/combine-perl.pl) 7994use base 'FlashVideo::Site::Xnxx'; 7995 79961; 7997} 7998##} blib/lib/FlashVideo/Site/Xvideos.pm 7999BEGIN { $INC{'FlashVideo/Site/Youku.pm'}++; } 8000##{ blib/lib/FlashVideo/Site/Youku.pm 8001{ 8002package FlashVideo::Site::Youku; 8003 8004use strict; 8005BEGIN { FlashVideo::JSON->import(); } # (added by utils/combine-perl.pl) 8006BEGIN { no strict 'refs'; *from_json = \&FlashVideo::JSON::from_json; } 8007BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 8008BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *get_video_filename = \&FlashVideo::Utils::get_video_filename; } 8009 8010sub find_video { 8011 my ($self, $browser, $embed_url) = @_; 8012 8013 my $check_response = sub { 8014 my ( $message ) = @_; 8015 return if $browser->success; 8016 die sprintf $message, $browser->response->code; 8017 }; 8018 8019 8020 if ( $embed_url !~ m`^http://v.youku.com/v_show/` ) 8021 { 8022 die "Don't recognise the youku link" 8023 unless $embed_url =~ m`player.php/sid/(.+)/v\.swf` 8024 or $embed_url =~ m`qplayer\.swf\?VideoIDS=([^&]+)`; 8025 8026 $embed_url = sprintf "http://v.youku.com/v_show/id_%s.html", $1; 8027 $browser->get( $embed_url ); 8028 } 8029 $check_response->( "Can't load the youku page, server response was %s" ); 8030 8031 my ( $videoID ) = ( $browser->content =~ /var videoId = '(.+?)';/ ); 8032 die "Couldn't extract video ID from youku page, we are probably out of date" 8033 unless $videoID; 8034 debug "Using video ID $videoID"; 8035 8036 $browser->get( 8037 sprintf "http://v.youku.com/player/getPlayList/VideoIDS/%s/version/5/source/video/password/?ran=%d&n=%d", 8038 $videoID, rand( 10000 ), 3 ); 8039 $check_response->( "Couldn't grab video informaton from youku, server response was %s" ); 8040 8041 return parse_video_info( $browser ); 8042} 8043 8044sub extract { 8045 my ($json, $key, $type) = @_; 8046 die "Can't find '$key' key in the JSON data" 8047 unless exists $json->{$key}; 8048 my $data = $json->{$key}; 8049 if (defined $type) { 8050 my $dtype = ref $data || 'DATA'; 8051 die "JSON data under '$key' is not the right type" 8052 . " (expecting $type, but got $dtype)" 8053 unless $dtype eq $type; 8054 } 8055 return $data; 8056} 8057 8058sub parse_video_info { 8059 my ($browser) = @_; 8060 8061 my $jsonstr = $browser->content; 8062 debug "Video data: $jsonstr"; 8063 8064 my $json = from_json($jsonstr); 8065 8066 my $data_array = extract($json, data => 'ARRAY'); 8067 die "No elements found in 'data' array" unless @$data_array; 8068 my $data = $data_array->[0]; 8069 8070 my $segmap = extract($data, segs => 'HASH'); 8071 8072 my @streamtype_preferences = qw(mp4 flv); 8073 my @streamtypes = keys %$segmap; 8074 8075 my $stream = $streamtypes[0]; 8076 8077 for my $pref (@streamtype_preferences) { 8078 if (grep { $_ eq $pref } @streamtypes) { 8079 $stream = $pref; 8080 last; 8081 } 8082 } 8083 8084 my $streams = join ' ', @streamtypes; 8085 debug "Choosing to use the $stream stream (available: $streams)"; 8086 8087 my $fileID; 8088 if (exists $data->{streamfileids}) { 8089 my $streamfileids = extract($data, streamfileids => 'HASH'); 8090 8091 $fileID = extract($streamfileids, $stream) 8092 if exists $streamfileids->{$stream}; 8093 } 8094 8095 $fileID = extract($data, 'fileid') 8096 if not $fileID and exists $data->{fileid}; 8097 8098 die "Can't find the encrypted file ID in the video info JSON" 8099 unless $fileID; 8100 debug "Encrypted file ID: $fileID"; 8101 8102 my $shuffle_seed = extract($data, 'seed'); 8103 8104 my @lookup_table = shuffle_table( $shuffle_seed ); 8105 $fileID =~ s/(\d+)\*/$lookup_table[$1]/eg; 8106 debug "Decrypted file ID: $fileID (seed is $shuffle_seed)"; 8107 8108 my $sID = sprintf "%s1%07d_00", time, rand( 10000000 ) ; 8109 8110 my $key1 = extract($data, 'key1'); 8111 my $key2 = extract($data, 'key2'); 8112 my $key = sprintf "%s%x", $key2, hex( $key1 ) ^ hex( 'a55aa5a5' ); 8113 8114 my $title = extract($data, 'title'); 8115 $title =~ s/\\u([a-f0-9]{4})/chr(hex $1)/egi; 8116 8117 my $filename = get_video_filename( $stream ); 8118 $filename = title_to_filename( $title, $stream ) if $title; 8119 8120 my $segs = extract($segmap, $stream, 'ARRAY'); 8121 8122 my @urls; 8123 my $segment_count = 0; 8124 8125 for my $seg (@$segs) { 8126 my $segment_number = extract($seg, 'no'); 8127 my $segment_size = extract($seg, 'size'); 8128 my $segment_seconds = extract($seg, 'seconds'); 8129 $key = extract($seg, 'k') if exists $seg->{'k'}; 8130 8131 my $segment_number_str = sprintf '%02X', $segment_number; 8132 my $segment_fileID = $fileID; 8133 substr $segment_fileID, 8, 2, $segment_number_str; 8134 8135 $browser->get( 8136 sprintf "http://f.youku.com/player/getFlvPath/sid/%s/st/%s/fileid/%s?K=%s&myp=0&ts=%s", 8137 $sID, $stream, $segment_fileID, $key, $segment_seconds ); 8138 8139 my $url = $browser->response->header( 'Location' ); 8140 die "Youku rejected our attempt to get the video, we're probably out of date" 8141 unless $browser->response->code eq 302 and $url; 8142 8143 debug "Video location for segment $segment_number is $url"; 8144 $url = "$url.$stream" unless $url =~ /$stream$/; 8145 8146 debug sprintf "%s, segment %d, %s seconds, %s bytes", 8147 $title, $segment_number, $segment_seconds, $segment_size 8148 if ( $title and $segment_seconds and $segment_size ); 8149 8150 push @urls, [$url, ++$segment_count, 0, $segment_size]; 8151 } 8152 8153 $_->[2] = $segment_count for @urls; 8154 8155 return ( \@urls, $filename ); 8156} 8157 8158sub shuffle_table { 8159 my ( $seed ) = @_; 8160 my @lookup 8161 = split //, 8162 q`abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/\:._-1234567890`; 8163 8164 my @shuffled; 8165 while ( $#lookup > 0 ) 8166 { 8167 $seed = ( 211 * $seed + 30031 ) % 2**16; 8168 8169 my $x = int( $seed / 2**16 * ( $#lookup + 1 ) ); 8170 push @shuffled, splice( @lookup, $x, 1 ); 8171 } 8172 return @shuffled; 8173} 8174 81751; 8176} 8177##} blib/lib/FlashVideo/Site/Youku.pm 8178BEGIN { $INC{'FlashVideo/Site/Youtu.pm'}++; } 8179# Part of get-flash-videos. See get_flash_videos for copyright. 8180BEGIN { $INC{'FlashVideo/Site/Youtube.pm'}++; } 8181# Part of get-flash-videos. See get_flash_videos for copyright. 8182##{ blib/lib/FlashVideo/Site/Youtube.pm 8183{ 8184package FlashVideo::Site::Youtube; 8185 8186use strict; 8187use Encode; 8188use HTML::Entities; 8189BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 8190BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; *error = \&FlashVideo::Utils::error; *extract_info = \&FlashVideo::Utils::extract_info; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *url_exists = \&FlashVideo::Utils::url_exists; *swfhash = \&FlashVideo::Utils::swfhash; *json_unescape = \&FlashVideo::Utils::json_unescape; } 8191BEGIN { FlashVideo::JSON->import(); } # (added by utils/combine-perl.pl) 8192BEGIN { no strict 'refs'; *from_json = \&FlashVideo::JSON::from_json; } 8193use URI::Escape; 8194 8195my @formats = ( 8196 { id => 38, resolution => [4096, 2304] }, 8197 { id => 37, resolution => [1920, 1080] }, 8198 { id => 22, resolution => [1280, 720] }, 8199 { id => 35, resolution => [854, 480] }, 8200 { id => 34, resolution => [640, 360] }, 8201 { id => 18, resolution => [480, 270] }, 8202 { id => 5, resolution => [400, 224] }, 8203 { id => 17, resolution => [176, 144] }, 8204 { id => 13, resolution => [176, 144] }, 8205); 8206 8207sub find_video { 8208 my ($self, $browser, $embed_url, $prefs) = @_; 8209 8210 if($embed_url !~ m!youtube\.com/watch!) { 8211 $browser->get($embed_url); 8212 if ($browser->response->header('Location') =~ m!/swf/.*video_id=([^&]+)! 8213 || $browser->content =~ m!\<iframe[^\>]*src="http://www.youtube.com/embed/([^"]+)"!i 8214 || $embed_url =~ m!/v/([-_a-z0-9]+)!i 8215 || $browser->uri =~ m!v%3D([-_a-z0-9]+)!i) { 8216 $embed_url = "http://www.youtube.com/watch?v=$1"; 8217 $browser->get($embed_url); 8218 } 8219 } 8220 8221 if (!$browser->success) { 8222 verify_age($browser, $prefs); 8223 } 8224 8225 my $title = extract_info($browser)->{meta_title}; 8226 if (!$title and 8227 $browser->content =~ /<div id="vidTitle">\s+<span ?>(.+?)<\/span>/ or 8228 $browser->content =~ /<div id="watch-vid-title">\s*<div ?>(.+?)<\/div>/) { 8229 $title = $1; 8230 } 8231 8232 if ($browser->content =~ /["']fmt_url_map["']:\s{0,3}(["'][^"']+["'])/) { 8233 my $fmt_map = $1; 8234 if ($fmt_map !~ /\|/) { 8235 $fmt_map = uri_unescape($fmt_map); 8236 } 8237 debug "Using fmt_url_map method from page ($fmt_map)"; 8238 return $self->download_fmt_map($prefs, $browser, $title, {}, @{from_json $fmt_map}); 8239 } 8240 8241 my $video_id; 8242 if ($browser->content =~ /(?:var pageVideoId =|(?:CFG_)?VIDEO_ID'?\s*:)\s*'(.+?)'/ 8243 || $browser->content =~ /"video_id": "([^"]+)"/ 8244 || $embed_url =~ /v=([^&]+)/ 8245 || $browser->content =~ /&video_id=([^&]+)&/) { 8246 $video_id = $1; 8247 } else { 8248 check_die($browser, "Couldn't extract video ID"); 8249 } 8250 8251 my $t; 8252 if ($browser->content =~ /\W['"]?t['"]?: ?['"](.+?)['"]/) { 8253 $t = $1; 8254 } 8255 8256 my $video_page_url = $browser->uri->as_string; 8257 8258 if (my %info = get_youtube_video_info($browser->clone, $video_id, $video_page_url, $t)) { 8259 if($self->debug) { 8260 require Data::Dumper; 8261 debug Data::Dumper::Dumper(\%info); 8262 } 8263 8264 if ($info{conn} =~ /^rtmp/) { 8265 my ($season, $episode); 8266 8267 if ($browser->content =~ m{<span[^>]*>Season ?(\d+)}i) { 8268 $season = $1; 8269 } 8270 8271 if ($browser->content =~ m{<span[^>]*>[^<]+Ep\.?\w* ?(\d+)\W*\s*</span>}i) { 8272 $episode = $1; 8273 } 8274 8275 if ($season and $episode) { 8276 $title .= sprintf " S%02dE%02d", $season, $episode; 8277 } 8278 8279 my $swf_url; 8280 if ($browser->content =~ /SWF_URL['"] ?: ?.{0,90}?(http:\/\/[^ ]+\.swf)/) { 8281 $swf_url = $1; 8282 } elsif($browser->content =~ /swfConfig\s*=\s*(\{.*?\});/ && (my $swf = from_json($1))) { 8283 $swf_url = $swf->{url}; 8284 } elsif($browser->content =~ /src=\\['"]([^'"]+\.swf)/) { 8285 $swf_url = json_unescape($1); 8286 } else { 8287 die "Couldn't extract SWF URL"; 8288 } 8289 8290 my $rtmp_url = $info{conn}; 8291 8292 if($info{fmt_stream_map}) { 8293 my $fmt_stream_map = parse_youtube_format_url_map($info{fmt_stream_map}, 1); 8294 8295 my $preferred_quality = $prefs->quality->choose(map { $fmt_stream_map->{$_->{id}} 8296 ? { resolution => $_->{resolution}, url => $fmt_stream_map->{$_->{id}} } 8297 : () } @formats); 8298 8299 $rtmp_url = $preferred_quality->{url}; 8300 } 8301 8302 return { 8303 flv => title_to_filename($title), 8304 rtmp => $rtmp_url, 8305 swfhash($browser, $swf_url) 8306 }; 8307 } elsif($info{fmt_url_map}) { 8308 debug "Using fmt_url_map method from info"; 8309 return $self->download_fmt_map($prefs, $browser, $title, \%info, $info{fmt_url_map}); 8310 } elsif($info{url_encoded_fmt_stream_map}) { 8311 debug "Using url_encoded_fmt_stream_map method from info"; 8312 if ($info{title}) { 8313 $title=$info{title}; 8314 } 8315 return $self->download_url_encoded_fmt_stream_map($prefs, $browser, $title, \%info, $info{url_encoded_fmt_stream_map}); 8316 } 8317 } 8318 8319 return download_get_video($browser, $prefs, $video_id, $title, $t); 8320} 8321 8322sub download_url_encoded_fmt_stream_map { 8323 my($self, $prefs, $browser, $title, $info, $fmt_map) = @_; 8324 8325 my $fmt_url_map = parse_youtube_url_encoded_fmt_stream_map($fmt_map); 8326 8327 if (!$title and $browser->uri->as_string =~ m'/user/.*?#') { 8328 my $video_id = (split /\//, $browser->uri->fragment)[-1]; 8329 8330 my %info = get_youtube_video_info($browser->clone, $video_id); 8331 8332 $title = $info->{title}; 8333 } 8334 8335 my $preferred_quality = $prefs->quality->choose(map { $fmt_url_map->{$_->{id}} 8336 ? { resolution => $_->{resolution}, url => $fmt_url_map->{$_->{id}} } 8337 : () } @formats); 8338 8339 $browser->allow_redirects; 8340 8341 return $preferred_quality->{url}, title_to_filename($title, "mp4"); 8342} 8343 8344sub parse_youtube_url_encoded_fmt_stream_map { 8345 my($raw_map) = @_;; 8346 8347 my $map = {}; 8348 8349 foreach my $params (split /,/, $raw_map) { 8350 8351 my $format = ""; 8352 my $url = ""; 8353 8354 foreach my $pair (split /&/, $params) { 8355 my ($name, $value) = split /=/, $pair; 8356 if ($name eq "itag"){ 8357 $format = $value; 8358 } elsif ($name eq "url") { 8359 $url = uri_unescape($value); 8360 } 8361 } 8362 8363 $map->{$format} = $url; 8364 } 8365 8366 return $map; 8367} 8368 8369sub download_fmt_map { 8370 my($self, $prefs, $browser, $title, $info, $fmt_map) = @_; 8371 8372 my $fmt_url_map = parse_youtube_format_url_map($fmt_map); 8373 8374 if (!$title and $browser->uri->as_string =~ m'/user/.*?#') { 8375 my $video_id = (split /\//, $browser->uri->fragment)[-1]; 8376 8377 my %info = get_youtube_video_info($browser->clone, $video_id); 8378 8379 $title = $info->{title}; 8380 } 8381 8382 my $preferred_quality = $prefs->quality->choose(map { $fmt_url_map->{$_->{id}} 8383 ? { resolution => $_->{resolution}, url => $fmt_url_map->{$_->{id}} } 8384 : () } @formats); 8385 8386 $browser->allow_redirects; 8387 8388 return $preferred_quality->{url}, title_to_filename($title, "mp4"); 8389} 8390 8391sub download_get_video { 8392 my($browser, $prefs, $video_id, $title, $t) = @_; 8393 8394 my $fetcher = sub { 8395 my($url, $filename) = @_; 8396 $url = url_exists($browser->clone, $url, 1); 8397 return $url, $filename if $url; 8398 return; 8399 }; 8400 8401 my @formats_to_try = @formats; 8402 8403 while(my $fmt = $prefs->quality->choose(@formats_to_try)) { 8404 @formats_to_try = grep { $_ != $fmt } @formats_to_try; 8405 8406 my @ret = $fetcher->("http://www.youtube.com/get_video?fmt=$fmt->{id}&video_id=$video_id&t=$t", 8407 title_to_filename($title, "mp4")); 8408 return @ret if @ret; 8409 } 8410 8411 my @ret = $fetcher->("http://www.youtube.com/get_video?video_id=$video_id&t=$t", 8412 title_to_filename($title)); 8413 8414 check_die($browser, "Unable to find video URL") unless @ret; 8415 8416 $browser->allow_redirects; 8417 8418 return @ret; 8419} 8420 8421sub check_die { 8422 my($browser, $message) = @_; 8423 8424 if($browser->content =~ m{class="yt-alert-content">([^<]+)}) { 8425 my $alert = $1; 8426 $alert =~ s/(^\s+|\s+$)//g; 8427 $message .= "\nYouTube: $alert"; 8428 error $message; 8429 exit 1; 8430 } else { 8431 die "$message\n"; 8432 } 8433} 8434 8435sub verify_age { 8436 my($browser, $prefs) = @_; 8437 my $orig_uri = $browser->uri; 8438 8439 if ($browser->response->code == 303 8440 && $browser->response->header('Location') =~ m!/verify_age|/accounts/!) { 8441 8442 my $confirmation_url = $browser->response->header('Location'); 8443 $browser->get($confirmation_url); 8444 8445 if($browser->content =~ /has_verified=1/) { 8446 my($verify_url) = $browser->content =~ /href="(.*?has_verified=1)"/; 8447 $verify_url = decode_entities($verify_url); 8448 $browser->get($verify_url); 8449 return if $browser->response->code == 200; 8450 } 8451 8452 my $account = $prefs->account("youtube", <<EOT); 8453Unfortunately, due to Youtube being lame, you have to have 8454an account to download this video. (See the documentation for how to configure 8455~/.netrc) 8456 8457EOT 8458 8459 unless ($account->username and $account->password) { 8460 error "You must supply Youtube account details."; 8461 exit 1; 8462 } 8463 8464 $browser->get("http://www.youtube.com/login"); 8465 if ($browser->response->code != 303) { 8466 die "Unexpected response from Youtube login.\n"; 8467 } 8468 8469 my $real_login_url = $browser->response->header('Location'); 8470 $browser->get($real_login_url); 8471 8472 $browser->form_with_fields('Email', 'Passwd'); 8473 $browser->set_fields( 8474 Email => $account->username, 8475 Passwd => $account->password, 8476 ); 8477 $browser->submit(); 8478 8479 if ($browser->content =~ /your login was incorrect/) { 8480 error "Couldn't log you in, check your username and password."; 8481 exit 1; 8482 } elsif ($browser->response->code == 302) { 8483 my $check_cookie_url = $browser->response->header('Location'); 8484 $browser->get($check_cookie_url); 8485 8486 if ($browser->content =~ /<meta.*"refresh".*?url='(.*?)'"/i) { 8487 my $redirected = decode_entities($1); 8488 $browser->get($redirected); 8489 8490 if(URI->new($redirected)->host !~ /youtube/i) { 8491 if($browser->response->code == 302) { 8492 $browser->get($browser->response->header("Location")); 8493 } else { 8494 die "Did not find expected redirection"; 8495 } 8496 } 8497 } else { 8498 die "Did not find expected redirection"; 8499 } 8500 } 8501 else { 8502 die "Unexpected response during login"; 8503 } 8504 8505 $browser->get($orig_uri); 8506 8507 if ($browser->response->code == 303) { 8508 my $real_confirmation_url = $browser->response->header('Location'); 8509 $browser->get($real_confirmation_url); 8510 if ($browser->form_with_fields('next_url', 'action_confirm')) { 8511 $browser->field('action_confirm' => 'Confirm Birth Date'); 8512 $browser->click_button(name => "action_confirm"); 8513 8514 if ($browser->response->code != 303) { 8515 die "Unexpected response from Youtube"; 8516 } 8517 $browser->get($browser->response->header('Location')); 8518 } 8519 } 8520 } 8521 else { 8522 if ($browser->response->code == 302) { 8523 $browser->get($browser->response->header('Location')); 8524 } 8525 8526 if ($browser->response->code == 303) { 8527 debug "Video not available (303), trying " . $browser->response->header('Location'); 8528 $browser->get($browser->response->header('Location')); 8529 } 8530 8531 if (!$browser->success) { 8532 die "Couldn't download URL: " . $browser->response->status_line; 8533 } 8534 } 8535} 8536 8537sub get_youtube_video_info { 8538 my ($browser, $video_id, $url, $t) = @_; 8539 8540 $url ||= "http://www.youtube.com/watch?v=$video_id"; 8541 8542 for my $el(qw(profilepage detailpage)) { 8543 my $video_info_url_template = 8544 "http://www.youtube.com/get_video_info?&video_id=%s&el=$el&ps=default&eurl=%s&hl=en_US&t=%s"; 8545 8546 my $video_info_url = sprintf $video_info_url_template, 8547 uri_escape($video_id), uri_escape($url), uri_escape_utf8($t); 8548 8549 debug "get_youtube_video_info: $video_info_url"; 8550 8551 $browser->get($video_info_url); 8552 8553 next unless $browser->success; 8554 8555 my %info = parse_youtube_video_info($browser->content); 8556 next if $info{status} eq 'fail'; 8557 8558 return %info; 8559 } 8560 8561 error "Unable to get YouTube video information."; 8562} 8563 8564sub parse_youtube_video_info { 8565 my $raw_info = shift; 8566 8567 my %video_info; 8568 8569 foreach my $raw_pair (split /&/, $raw_info) { 8570 my ($key, $value) = split /=/, $raw_pair; 8571 $value = uri_unescape($value); 8572 $value =~ s/\+/ /g; 8573 8574 $video_info{$key} = $value; 8575 } 8576 8577 return %video_info; 8578} 8579 8580sub parse_youtube_format_url_map { 8581 my($raw_map, $param_idx) = @_; 8582 8583 $param_idx = 0 unless defined $param_idx; 8584 8585 my $map = {}; 8586 8587 foreach my $pair (split /,/, $raw_map) { 8588 my ($format, @params) = split /\|/, $pair; 8589 8590 my $url = $params[$param_idx]; 8591 8592 $url = uri_unescape($url); 8593 8594 $map->{$format} = $url; 8595 } 8596 8597 return $map; 8598} 8599 86001; 8601} 8602##} blib/lib/FlashVideo/Site/Youtube.pm 8603##{ blib/lib/FlashVideo/Site/Youtu.pm 8604{ 8605package FlashVideo::Site::Youtu; 8606 8607BEGIN { FlashVideo::Site::Youtube->import(); } # (added by utils/combine-perl.pl) 8608use base 'FlashVideo::Site::Youtube'; 8609 86101; 8611} 8612##} blib/lib/FlashVideo/Site/Youtu.pm 8613BEGIN { $INC{'FlashVideo/Site/Youtubenocookie.pm'}++; } 8614# Part of get-flash-videos. See get_flash_videos for copyright. 8615##{ blib/lib/FlashVideo/Site/Youtubenocookie.pm 8616{ 8617package FlashVideo::Site::Youtubenocookie; 8618 8619use strict; 8620BEGIN { FlashVideo::Site::Youtube->import(); } # (added by utils/combine-perl.pl) 8621use base 'FlashVideo::Site::Youtube'; 8622 86231; 8624} 8625##} blib/lib/FlashVideo/Site/Youtubenocookie.pm 8626BEGIN { $INC{'FlashVideo/Site/Zdf.pm'}++; } 8627# Part of get-flash-videos. See get_flash_videos for copyright. 8628##{ blib/lib/FlashVideo/Site/Zdf.pm 8629{ 8630package FlashVideo::Site::Zdf; 8631 8632use strict; 8633BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 8634BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *title_to_filename = \&FlashVideo::Utils::title_to_filename; } 8635 8636sub find_video { 8637 my ($self, $browser, $embed_url, $prefs) = @_; 8638 my ($id, $filename, $videourl, $quality); 8639 8640 $quality = {high => 'veryhigh', low => 'low'}->{$prefs->{quality}}; 8641 8642 debug "Zdf::find_video called, embed_url = \"$embed_url\"\n"; 8643 8644 if($browser->content =~ /\/video\/(\d*)\/(.*)"/) { 8645 $id = $1; 8646 debug "found video $1 $2\n"; 8647 $filename = title_to_filename($2); 8648 8649 $browser->get("http://www.zdf.de/ZDFmediathek/xmlservice/web/beitragsDetails?id=$id&ak=web"); 8650 8651 if($browser->content =~ /(http:\/\/fstreaming\.zdf\.de\/zdf\/$quality\/.*\.meta)/) { 8652 $browser->get($1); 8653 if($browser->content =~ /(rtmp.*)</) { 8654 debug "found rtmp url\"$1\"\n"; 8655 $videourl = { 8656 rtmp => $1, 8657 flv => $filename, 8658 swfVfy => "http://www.zdf.de/ZDFmediatek/flash/player.swf" 8659 }; 8660 } 8661 } 8662 } 8663 return $videourl, $filename; 8664} 8665 86661; 8667} 8668##} blib/lib/FlashVideo/Site/Zdf.pm 8669BEGIN { $INC{'FlashVideo/Site/Zshare.pm'}++; } 8670# A get-flash-videos module for the zshare.net website 8671################################################# 8672# 8673# This file was automatically generated by utils/combine-perl.pl 8674# You should edit the original files, not this 8675# combined version. 8676# 8677# The original files are available at: 8678# http://github.com/monsieurvideo/get-flash-videos 8679# 8680################################################# 8681# Copyright (C) 2011 Rudolf Olah <rolah@goaugust.com> 8682# Licensed under the GNU GPL v3 or later 8683 8684# Created using the instructions from: http://code.google.com/p/get-flash-videos/wiki/AddingSite 8685 8686##{ blib/lib/FlashVideo/Site/Zshare.pm 8687{ 8688package FlashVideo::Site::Zshare; 8689 8690use strict; 8691BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 8692BEGIN { no strict 'refs'; } 8693 8694sub find_video { 8695 my ($self, $browser, $embed_url, $prefs) = @_; 8696 $embed_url = ($browser->content =~ /iframe src="(.*videoplayer.*?)"/i)[0]; 8697 $browser->get($embed_url); 8698 my $url = ($browser->content =~ /file:.*"(.*?)"/i)[0]; 8699 my $filename = ($browser->content =~ /<title>.*?- (.*)<\/title>/i)[0]; 8700 return $url, $filename; 8701} 8702 87031; 8704} 8705##} blib/lib/FlashVideo/Site/Zshare.pm 8706##{ .sitemodules 8707{ 8708package main; 8709} 8710##} .sitemodules 8711#!/usr/bin/perl 8712BEGIN { $INC{'FlashVideo/URLFinder.pm'}++; } 8713# Part of get-flash-videos. See get_flash_videos for copyright. 8714BEGIN { $INC{'FlashVideo/Generic.pm'}++; } 8715# Part of get-flash-videos. See get_flash_videos for copyright. 8716##{ blib/lib/FlashVideo/Generic.pm 8717{ 8718package FlashVideo::Generic; 8719 8720use strict; 8721BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 8722BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; *extract_title = \&FlashVideo::Utils::extract_title; *title_to_filename = \&FlashVideo::Utils::title_to_filename; *get_video_filename = \&FlashVideo::Utils::get_video_filename; *url_exists = \&FlashVideo::Utils::url_exists; *EXTENSIONS = \&FlashVideo::Utils::EXTENSIONS; } 8723use URI; 8724BEGIN { FlashVideo::URLFinder->import(); } # (added by utils/combine-perl.pl) 8725use URI::Escape qw(uri_unescape); 8726 8727my $video_re = qr!http[-:/a-z0-9%_.?=&]+@{[EXTENSIONS]} 8728 (?:\?[-:/a-z0-9%_.?=&]+)?!xi; 8729 8730sub find_video { 8731 my ($self, $browser, $embed_url, $prefs) = @_; 8732 8733 if (!$browser->success) { 8734 $browser->get($browser->response->header('Location')); 8735 die "Couldn't download URL: " . $browser->response->status_line 8736 unless $browser->success; 8737 } 8738 8739 my ($possible_filename, $actual_url, $title); 8740 $title = extract_title($browser); 8741 8742 my @flv_urls = map { 8743 (m{http://.+?(http://.+?@{[EXTENSIONS]})}i) ? $1 : $_ 8744 } ($browser->content =~ m{($video_re)}gi); 8745 if (@flv_urls) { 8746 require LWP::Simple; 8747 require Memoize; 8748 Memoize::memoize("LWP::Simple::head"); 8749 @flv_urls = sort { (LWP::Simple::head($a))[1] <=> (LWP::Simple::head($b))[1] } @flv_urls; 8750 $possible_filename = (split /\//, $flv_urls[-1])[-1]; 8751 8752 if ($flv_urls[-1] =~ /^http%3a%2f%2f/) { 8753 $flv_urls[-1] = uri_unescape($flv_urls[-1]) 8754 } 8755 8756 $actual_url = url_exists($browser->clone, $flv_urls[-1]); 8757 } 8758 8759 my $filename_is_reliable; 8760 8761 if(!$actual_url) { 8762 RE: for my $regex( 8763 qr{(?si)<embed.*?flashvars=["']?([^"'>]+)}, 8764 qr{(?si)<embed.*?src=["']?([^"'>]+)}, 8765 qr{(?si)<a[^>]* href=["']?([^"'>]+?@{[EXTENSIONS]})}, 8766 qr{(?si)<object[^>]*>.*?<param [^>]*value=["']?([^"'>]+)}, 8767 qr{(?si)<object[^>]*>(.*?)</object>}, 8768 qr{(?si)<script[^>]*>(.*?)</script>}) { 8769 8770 for my $param($browser->content =~ /$regex/gi) { 8771 (my $url, $possible_filename, $filename_is_reliable) = find_file_param($browser->clone, $param, $prefs); 8772 8773 if($url) { 8774 my $resolved_url = url_exists($browser->clone, $url); 8775 if($resolved_url) { 8776 $actual_url = $resolved_url; 8777 last RE; 8778 } 8779 } 8780 } 8781 } 8782 8783 if(!$actual_url) { 8784 for my $iframe($browser->content =~ /<iframe[^>]+src=["']?([^"'>]+)/gi) { 8785 $iframe = URI->new_abs($iframe, $browser->uri); 8786 debug "Found iframe: $iframe"; 8787 my $sub_browser = $browser->clone; 8788 $sub_browser->get($iframe); 8789 my($package, $possible_url) = FlashVideo::URLFinder->find_package($iframe, $sub_browser); 8790 8791 if($package->can("pre_find")) { 8792 $package->pre_find($sub_browser); 8793 } 8794 8795 info "Downloading $iframe"; 8796 $sub_browser->get($iframe); 8797 8798 my($actual_url, @suggested_fnames) = eval { 8799 $package->find_video($sub_browser, $possible_url, $prefs); 8800 }; 8801 return $actual_url, @suggested_fnames if $actual_url; 8802 } 8803 } 8804 } 8805 8806 my @filenames; 8807 8808 return $actual_url, $possible_filename if $filename_is_reliable; 8809 8810 $possible_filename =~ s/\?.*//; 8811 push @filenames, $possible_filename if $possible_filename 8812 && $possible_filename !~ /^[0-9_.]+@{[EXTENSIONS]}$/; 8813 8814 my $ext = substr(($actual_url =~ /(@{[EXTENSIONS]})$/)[0], 1); 8815 push @filenames, title_to_filename($title, $ext) if 8816 $title && $title !~ /\Q$possible_filename\E/i; 8817 8818 push @filenames, get_video_filename() if !@filenames; 8819 8820 return $actual_url, @filenames if $actual_url; 8821 8822 8823 my %swf_urls; 8824 8825 if (eval { require URI::Find }) { 8826 my $finder = URI::Find->new( 8827 sub { $swf_urls{$_[1]}++ if $_[1] =~ /\.swf$/i } 8828 ); 8829 $finder->find(\$browser->content); 8830 } 8831 else { 8832 my $content = $browser->content; 8833 while($content =~ m{(http://[^ "']+?\.swf)}ig) { 8834 $swf_urls{$1}++; 8835 } 8836 } 8837 8838 if (%swf_urls) { 8839 foreach my $swf_url (keys %swf_urls) { 8840 if (my ($flv_url, $title) = search_for_flv_in_swf($browser, $swf_url)) { 8841 return $flv_url, title_to_filename($title); 8842 } 8843 } 8844 } 8845 8846 die "No URLs found"; 8847} 8848 8849sub search_for_flv_in_swf { 8850 my ($browser, $swf_url) = @_; 8851 8852 $browser = $browser->clone(); 8853 8854 $browser->get($swf_url); 8855 8856 if (!$browser->success) { 8857 die "Couldn't download SWF URL $swf_url: " . 8858 $browser->response->status_line(); 8859 } 8860 8861 my $swf_data = $browser->content; 8862 8863 if ('C' eq substr $swf_data, 0, 1) { 8864 if (eval { require Compress::Zlib }) { 8865 $swf_data = Compress::Zlib::uncompress(substr $swf_data, 8); 8866 } 8867 else { 8868 die "Compress::Zlib is required to uncompress compressed SWF files.\n"; 8869 } 8870 } 8871 8872 if ($swf_data =~ m{(http://.{10,300}?\.flv)}i) { 8873 my $flv_url = $1; 8874 8875 my $filename = uri_unescape(File::Basename::basename(URI->new($flv_url)->path())); 8876 $filename =~ s/\.flv$//i; 8877 8878 return ($flv_url, $filename); 8879 } 8880 8881 return; 8882} 8883 8884sub find_file_param { 8885 my($browser, $param, $prefs) = @_; 8886 8887 for my $file($param =~ /(?:video|movie|file|path)_?(?:href|src|url)?['"]?\s*[=:,]\s*['"]?([^&'" ]+)/gi, 8888 $param =~ /(?:config|playlist|options)['"]?\s*[,:=]\s*['"]?(http[^'"&]+)/gi, 8889 $param =~ /['"=](.*?@{[EXTENSIONS]})/gi, 8890 $param =~ /([^ ]+@{[EXTENSIONS]})/gi, 8891 $param =~ /SWFObject\(["']([^"']+)/) { 8892 8893 debug "Found $file"; 8894 8895 my ($actual_url, $filename, $filename_is_reliable) = guess_file($browser, $file, '', $prefs); 8896 8897 if(!$actual_url && $file =~ /\?(.*)/) { 8898 debug "Trying query param on $1"; 8899 8900 for my $query_param(split /[;&]/, $1) { 8901 my($query_key, $query_value) = split /=/, $query_param; 8902 debug "Found $query_value from $query_key"; 8903 8904 ($actual_url, $filename, $filename_is_reliable) 8905 = guess_file($browser, $query_value, '', $prefs); 8906 8907 last if $actual_url; 8908 } 8909 } 8910 8911 if($actual_url) { 8912 my $possible_filename = $filename || (split /\//, $actual_url)[-1]; 8913 8914 return $actual_url, $possible_filename, $filename_is_reliable; 8915 } 8916 } 8917 8918 if($param =~ m{(rtmp://[^ &"']+)}) { 8919 info "This looks like RTMP ($1), no generic support yet.."; 8920 } 8921 8922 return; 8923} 8924 8925sub guess_file { 8926 my($browser, $file, $once, $prefs) = @_; 8927 8928 $file = uri_unescape($file) if scalar(() = $file =~ /%[A-F0-9]{2}/gi) > 3; 8929 8930 my $orig_uri = URI->new_abs($file, $browser->uri); 8931 8932 info "Guessed $orig_uri trying..."; 8933 8934 if($orig_uri) { 8935 my $uri = url_exists($browser->clone, $orig_uri); 8936 8937 if($uri) { 8938 my ($package, $url) = FlashVideo::URLFinder->find_package($uri, 8939 $browser->clone); 8940 8941 if($package && $package ne __PACKAGE__) { 8942 debug "$uri is supported by $package."; 8943 (my $browser_on_supported_site = $browser->clone())->get($uri); 8944 return $package->find_video($browser_on_supported_site, $uri, $prefs), 1; 8945 } 8946 8947 my $content_type = $browser->response->header("Content-type"); 8948 8949 if($content_type =~ m!^(text|application/xml)!) { 8950 $browser->add_header("Range", "bytes=0-10000"); 8951 $browser->get($uri); 8952 $browser->delete_header("Range"); 8953 8954 if(FlashVideo::Downloader->check_magic($browser->content) 8955 || $uri =~ m!$video_re!) { 8956 debug "Found a video at $uri"; 8957 return $uri; 8958 } 8959 8960 return if $browser->content =~ /<html[^>]*>/i; 8961 8962 if($browser->content =~ m!($video_re)!) { 8963 return $1; 8964 } elsif(!defined $once 8965 && $browser->content =~ m!(http[-:/a-zA-Z0-9%_.?=&]+)!i) { 8966 return guess_file($browser, $1, 1, $prefs); 8967 } else { 8968 info "Tried $uri, but no video URL found"; 8969 } 8970 } elsif($content_type =~ m!application/! && $uri ne $orig_uri) { 8971 return((find_file_param($browser, $uri))[0]); 8972 } else { 8973 return $uri->as_string; 8974 } 8975 } elsif(not defined $once) { 8976 if($browser->content =~ /["']([^ ]+\.swf)/) { 8977 my $swf_uri = URI->new_abs($1, $browser->uri); 8978 if($swf_uri) { 8979 my $new_uri = URI->new_abs($file, $swf_uri); 8980 debug "Found SWF: $swf_uri -> $new_uri"; 8981 if($new_uri ne $uri) { 8982 return guess_file($browser, $new_uri, 1, $prefs); 8983 } 8984 } 8985 } 8986 } 8987 } 8988 8989 return; 8990} 8991 89921; 8993} 8994##} blib/lib/FlashVideo/Generic.pm 8995##{ blib/lib/FlashVideo/URLFinder.pm 8996{ 8997package FlashVideo::URLFinder; 8998 8999use strict; 9000BEGIN { FlashVideo::Mechanize->import(); } # (added by utils/combine-perl.pl) 9001BEGIN { FlashVideo::Generic->import(); } # (added by utils/combine-perl.pl) 9002BEGIN { FlashVideo::Site->import(); } # (added by utils/combine-perl.pl) 9003BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 9004BEGIN { no strict 'refs'; *info = \&FlashVideo::Utils::info; } 9005use URI; 9006 9007 9008my @extra_can_handle = qw(Brightcove Mtvnservices Gawker Ooyala Gorillavid); 9009 9010sub find_package { 9011 my($class, $url, $browser) = @_; 9012 my $package = _find_package_url($url, $browser); 9013 9014 if(!defined $package) { 9015 9016 for my $possible_url($browser->content =~ 9017 m!(?:<object[^>]+>.*?|<(?:script|embed|iframe|param) [^>]*(?:src=["']?|name=["']src["']\ value=["']))(http://[^"'> ]+)!gixs) { 9018 $package = _find_package_url($possible_url, $browser); 9019 9020 return _found($package, $possible_url) if defined $package; 9021 } 9022 } 9023 9024 if(!defined $package) { 9025 for(@extra_can_handle) { 9026 my $possible_package = _load($_); 9027 9028 $browser->get($url); 9029 9030 my $r = $possible_package->can_handle($browser, $url); 9031 if($r) { 9032 $package = $possible_package; 9033 last; 9034 } 9035 } 9036 } 9037 9038 if(!defined $package) { 9039 $package = "FlashVideo::Generic"; 9040 } 9041 9042 return _found($package, $url); 9043} 9044 9045 9046sub _find_package_url { 9047 my($url, $browser) = @_; 9048 my $package; 9049 9050 foreach my $host_part (split /\./, URI->new($url)->host) { 9051 $host_part = lc $host_part; 9052 $host_part =~ s/[^a-z0-9]//i; 9053 9054 my $possible_package = _load($host_part); 9055 9056 if($possible_package->can("find_video")) { 9057 9058 if($possible_package->can("can_handle")) { 9059 next unless $possible_package->can_handle($browser, $url); 9060 } 9061 9062 $package = $possible_package; 9063 last; 9064 } 9065 } 9066 9067 return $package; 9068} 9069 9070sub _found { 9071 my($package, $url) = @_; 9072 info "Using method '" . lc((split /::/, $package)[-1]) . "' for $url"; 9073 return $package, $url; 9074} 9075 9076sub _load { 9077 my($site) = @_; 9078 9079 my $package = "FlashVideo::Site::" . ucfirst lc $site; 9080 9081 if(eval "require $package") { 9082 no strict 'refs'; 9083 push @{$package . "::ISA"}, "FlashVideo::Site"; 9084 } 9085 return $package; 9086} 9087 90881; 9089} 9090##} blib/lib/FlashVideo/URLFinder.pm 9091BEGIN { $INC{'FlashVideo/RTMPDownloader.pm'}++; } 9092# Part of get-flash-videos. See get_flash_videos for copyright. 9093##{ blib/lib/FlashVideo/RTMPDownloader.pm 9094{ 9095package FlashVideo::RTMPDownloader; 9096 9097use strict; 9098BEGIN { FlashVideo::Downloader->import(); } # (added by utils/combine-perl.pl) 9099use base 'FlashVideo::Downloader'; 9100use IPC::Open3; 9101use Fcntl (); 9102use Symbol qw(gensym); 9103BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 9104BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; *error = \&FlashVideo::Utils::error; *swfhash = \&FlashVideo::Utils::swfhash; *is_program_on_path = \&FlashVideo::Utils::is_program_on_path; } 9105 9106use constant LATEST_RTMPDUMP => 2.2; 9107 9108sub download { 9109 my ($self, $rtmp_data, $file) = @_; 9110 9111 $self->{printable_filename} = $file; 9112 9113 $file = $rtmp_data->{flv} = $self->get_filename($file); 9114 9115 if (-s $file && !$rtmp_data->{live}) { 9116 info "RTMP output filename '$self->{printable_filename}' already " . 9117 "exists, asking to resume..."; 9118 $rtmp_data->{resume} = ''; 9119 } 9120 9121 if(my $socks = FlashVideo::Mechanize->new->get_socks_proxy) { 9122 $rtmp_data->{socks} = $socks; 9123 } 9124 9125 my($r_fh, $w_fh); # So Perl doesn't close them behind our back.. 9126 9127 if ($rtmp_data->{live} && $self->action eq 'play') { 9128 9129 pipe($r_fh, $w_fh); 9130 9131 my $pid = fork; 9132 die "Fork failed" unless defined $pid; 9133 if(!$pid) { 9134 fcntl $r_fh, Fcntl::F_SETFD(), ~Fcntl::FD_CLOEXEC(); 9135 exec $self->replace_filename($self->player, "/dev/fd/" . fileno $r_fh); 9136 die "Exec failed\n"; 9137 } 9138 9139 fcntl $w_fh, Fcntl::F_SETFD(), ~Fcntl::FD_CLOEXEC(); 9140 $rtmp_data->{flv} = "/dev/fd/" . fileno $w_fh; 9141 9142 $self->{stream} = undef; 9143 } 9144 9145 my $prog = $self->get_rtmp_program; 9146 9147 if($prog eq 'flvstreamer' && ($rtmp_data->{rtmp} =~ /^rtmpe:/ || $rtmp_data->{swfhash})) { 9148 error "FLVStreamer does not support " 9149 . ($rtmp_data->{swfhash} ? "SWF hashing" : "RTMPE streams") 9150 . ", please install rtmpdump."; 9151 exit 1; 9152 } 9153 9154 if($self->debug) { 9155 $rtmp_data->{verbose} = undef; 9156 } 9157 9158 my($return, @errors) = $self->run($prog, $rtmp_data); 9159 9160 if($return != 0 && "@errors" =~ /failed to connect/i) { 9161 info "Couldn't connect on RTMP port, trying port 443 instead"; 9162 $rtmp_data->{port} = 443; 9163 ($return, @errors) = $self->run($prog, $rtmp_data); 9164 } 9165 9166 if($file ne '-' && (-s $file < 100 || !$self->check_file($file))) { 9167 error "Download failed, no valid file downloaded"; 9168 unlink $rtmp_data->{flv}; 9169 return 0; 9170 } 9171 9172 if($return == 2) { 9173 info "\nDownload incomplete -- try running again to resume."; 9174 return 0; 9175 } elsif($return) { 9176 info "\nDownload failed."; 9177 return 0; 9178 } 9179 9180 return -s $file; 9181} 9182 9183sub get_rtmp_program { 9184 if(is_program_on_path("rtmpdump")) { 9185 return "rtmpdump"; 9186 } elsif(is_program_on_path("flvstreamer")) { 9187 return "flvstreamer"; 9188 } 9189 9190 return "rtmpdump"; 9191} 9192 9193sub get_command { 9194 my($self, $rtmp_data, $debug) = @_; 9195 9196 return map { 9197 my $arg = $_; 9198 9199 (ref $rtmp_data->{$arg} eq 'ARRAY' 9200 ? (map { 9201 ("--$arg" => $debug 9202 ? $self->shell_escape($_) 9203 : $_) } @{$rtmp_data->{$arg}}) 9204 : ("--$arg" => (($debug && $rtmp_data->{$arg}) 9205 ? $self->shell_escape($rtmp_data->{$arg}) 9206 : $rtmp_data->{$arg}) || ())) 9207 } keys %$rtmp_data; 9208} 9209 9210sub run { 9211 my($self, $prog, $rtmp_data) = @_; 9212 9213 debug "Running $prog", join(" ", $self->get_command($rtmp_data, 1)); 9214 9215 my($in, $out, $err); 9216 $err = gensym; 9217 my $pid = open3($in, $out, $err, $prog, $self->get_command($rtmp_data)); 9218 9219 local $SIG{INT}; 9220 if ($^O =~ /mswin/i) { 9221 $SIG{INT} = sub { 9222 kill 'TERM', $pid; 9223 exit; 9224 }; 9225 } 9226 9227 my $complete = 0; 9228 my $buf = ""; 9229 my @error; 9230 9231 while(sysread($err, $buf, 128, length $buf) > 0) { 9232 $buf =~ s/\015\012/\012/g; 9233 9234 my @parts = split /\015/, $buf; 9235 $buf = ""; 9236 9237 for(@parts) { 9238 if(/^((?:DEBUG:|WARNING:|Closing connection|ERROR: No playpath found).*)\n/) { 9239 debug "$prog: $1"; 9240 } elsif(/^(ERROR: .*)\012/) { 9241 push @error, $1; 9242 info "$prog: $1"; 9243 } elsif(/^([0-9.]+) kB(?:\s+\/ \S+ sec)?(?: \(([0-9.]+)%\))?/i) { 9244 $self->{downloaded} = $1 * 1024; 9245 my $percent = $2; 9246 9247 if($self->{downloaded} && $percent != 0) { 9248 $self->{content_length} = $self->{downloaded} / ($percent / 100); 9249 } 9250 9251 $self->progress; 9252 } elsif(/\012$/) { 9253 for my $l(split /\012/) { 9254 if($l =~ /^[A-F0-9]{,2}(?:\s+[A-F0-9]{2})*\s*$/) { 9255 debug $l; 9256 } elsif($l =~ /Download complete/) { 9257 $complete = 1; 9258 } elsif($l =~ /\s+filesize\s+(\d+)/) { 9259 $self->{content_length} = $1; 9260 } elsif($l =~ /\w/) { 9261 print STDERR "\r" if $self->{downloaded}; 9262 info $l; 9263 9264 if($l =~ /^RTMPDump v([0-9.]+)/ && $1 < LATEST_RTMPDUMP) { 9265 error "==== Using the latest version of RTMPDump (version " 9266 . LATEST_RTMPDUMP . ") is recommended. ===="; 9267 } 9268 } 9269 } 9270 9271 if(/open3/) { 9272 error "\nMake sure you have 'rtmpdump' or 'flvstreamer' installed and available on your PATH."; 9273 return 0; 9274 } 9275 } else { 9276 $buf = $_; 9277 } 9278 } 9279 9280 if(defined $self->{stream} && $self->{downloaded} > 300_000) { 9281 $self->{stream}->(); 9282 } 9283 } 9284 9285 waitpid $pid, 0; 9286 return $? >> 8, @error; 9287} 9288 92891; 9290} 9291##} blib/lib/FlashVideo/RTMPDownloader.pm 9292BEGIN { $INC{'FlashVideo/Search.pm'}++; } 9293# Part of get-flash-videos. See get_flash_videos for copyright. 9294##{ blib/lib/FlashVideo/Search.pm 9295{ 9296package FlashVideo::Search; 9297 9298use strict; 9299use Carp; 9300BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 9301BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; } 9302 9303my @sites_with_search = ('4oD', 'GoogleVideoSearch'); 9304 9305sub search { 9306 my ($class, $search, $max_per_site, $max_results) = @_; 9307 9308 my @search_sites = map { FlashVideo::URLFinder::_load($_) } @sites_with_search; 9309 9310 if ($search =~ /^(\w+) \w+/) { 9311 my $possible_site = ucfirst lc $1; 9312 9313 debug "Checking to see if '$possible_site' in '$search' is a search-supported site."; 9314 9315 my $possible_package = FlashVideo::URLFinder::_load($possible_site); 9316 9317 if ($possible_package->can("search")) { 9318 debug "Search for '$search' will only search $possible_site."; 9319 9320 $search =~ s/^\w+ //; 9321 9322 return search_site($possible_package, $search, "site", $max_results); 9323 } 9324 } 9325 9326 my @plugins = App::get_flash_videos::get_installed_plugins(); 9327 9328 foreach my $plugin (@plugins) { 9329 $plugin =~ s/\.pm$//; 9330 9331 my $plugin_package = FlashVideo::URLFinder::_load($plugin); 9332 9333 if ($plugin_package->can("search")) { 9334 debug "Plugin '$plugin' has a search method."; 9335 9336 unshift @search_sites, $plugin_package; 9337 } 9338 else { 9339 debug "Plugin '$plugin' doesn't have a search method."; 9340 } 9341 } 9342 9343 my @results = map { search_site($_, $search, "all", $max_per_site) } @search_sites; 9344 9345 trim_resultset(\@results, $max_results); 9346 9347 return @results; 9348} 9349 9350sub search_site { 9351 my($search_site, $search, $type, $max) = @_; 9352 9353 debug "Searching '$search_site' for '$search'."; 9354 9355 if (my @site_results = eval { $search_site->search($search, $type) }) { 9356 debug "Found " . @site_results . " results for $search."; 9357 9358 trim_resultset(\@site_results, $max); 9359 return @site_results; 9360 } 9361 elsif($@) { 9362 info "Searching '$search_site' failed with: $@"; 9363 } 9364 else { 9365 debug "No results found for '$search'."; 9366 } 9367 9368 return (); 9369} 9370 9371sub trim_resultset { 9372 my ($results, $max) = @_; 9373 9374 croak "Must be supplied a reference to resultset" unless ref($results) eq 'ARRAY'; 9375 croak "No max supplied" unless $max; 9376 9377 if (@$results > $max) { 9378 debug "Found " . @$results . " results, trimming to $max."; 9379 splice @$results, $max; 9380 } 9381} 9382 93831; 9384} 9385##} blib/lib/FlashVideo/Search.pm 9386BEGIN { $INC{'FlashVideo/VideoPreferences.pm'}++; } 9387# Part of get-flash-videos. See get_flash_videos for copyright. 9388BEGIN { $INC{'FlashVideo/VideoPreferences/Quality.pm'}++; } 9389# Part of get-flash-videos. See get_flash_videos for copyright. 9390##{ blib/lib/FlashVideo/VideoPreferences/Quality.pm 9391{ 9392package FlashVideo::VideoPreferences::Quality; 9393 9394use strict; 9395 9396my %format_map = ( 9397 "240p" => [320, 240, "low"], 9398 "240w" => [427, 240, "low"], 9399 "480p" => [640, 480, "medium"], 9400 "480w" => [854, 480, "medium"], 9401 "576p" => [720, 576, "medium"], 9402 "720p" => [1280, 720, "high"], 9403 "1080p" => [1920, 1080, "high"], 9404); 9405 9406sub new { 9407 my($class, $quality) = @_; 9408 9409 return bless \$quality, $class; 9410} 9411 9412sub name { 9413 my($self) = @_; 9414 return $$self; 9415} 9416 9417sub choose { 9418 my($self, @available) = @_; 9419 9420 9421 9422 my $max_preferred_res = $self->quality_to_resolution($self->name); 9423 my $max_preferred_size = $max_preferred_res->[0] * $max_preferred_res->[1]; 9424 9425 my @sorted = 9426 sort { $a->[0] <=> $b->[0] } 9427 map { my $r = $_->{resolution}; $r = $r->[0] * $r->[1]; [$r, $_] } @available; 9428 9429 if(my @at_or_under_preferred = grep { $_->[0] <= $max_preferred_size } @sorted) { 9430 return $at_or_under_preferred[-1]->[1]; 9431 } else { 9432 return $sorted[0]->[1]; 9433 } 9434} 9435 9436sub format_to_resolution { 9437 my($self, $name) = @_; 9438 $name .= "p" if $name !~ /[a-z]$/i; 9439 9440 if(my $resolution = $format_map{lc $name}) { 9441 return $resolution; 9442 } elsif(my $num = ($name =~ /(\d+)/)[0]) { 9443 my $resolution = [($num) x 2]; 9444 return [@$resolution, $self->resolution_to_quality($resolution)]; 9445 } 9446 9447 die "Unknown format '$name'"; 9448} 9449 9450sub quality_to_resolution { 9451 my($self, $quality) = @_; 9452 9453 if($quality =~ /^(\d+)x(\d+)$/) { 9454 my $resolution = [$1, $2]; 9455 return [@$resolution, $self->resolution_to_quality($resolution)]; 9456 9457 } elsif(my $resolution = eval { $self->format_to_resolution($quality) }) { 9458 return $resolution; 9459 9460 } else { 9461 for my $r(sort { ($b->[0]*$b->[1]) <=> ($a->[0]*$a->[1]) } 9462 values %format_map) { 9463 if($r->[2] eq lc $quality) { 9464 return $r; 9465 } 9466 } 9467 } 9468 9469 die "Unknown quality '$quality'"; 9470} 9471 9472sub resolution_to_quality { 9473 my($self, $resolution) = @_; 9474 9475 my $quality = "high"; 9476 9477 for my $r(sort { ($b->[0]*$b->[1]) <=> ($a->[0]*$a->[1]) } 9478 values %format_map) { 9479 $quality = $r->[2] if $r->[0] >= $resolution->[0]; 9480 } 9481 9482 return $quality; 9483} 9484 94851; 9486} 9487##} blib/lib/FlashVideo/VideoPreferences/Quality.pm 9488BEGIN { $INC{'FlashVideo/VideoPreferences/Account.pm'}++; } 9489# Part of get-flash-videos. See get_flash_videos for copyright. 9490##{ blib/lib/FlashVideo/VideoPreferences/Account.pm 9491{ 9492package FlashVideo::VideoPreferences::Account; 9493 9494use strict; 9495 9496sub new { 9497 my($class, $site, $prompt) = @_; 9498 9499 require Net::Netrc; # Core since 5.8 9500 9501 my $record = Net::Netrc->lookup($site); 9502 my($user, $pass) = $record ? $record->lpa : (); 9503 9504 9505 if(!$user) { 9506 print $prompt; 9507 9508 print "Username: "; 9509 chomp($user = <STDIN>); 9510 } 9511 9512 if(!$pass) { 9513 print "Ok, need your password"; 9514 if(eval { require Term::ReadKey }) { 9515 print ": "; 9516 Term::ReadKey::ReadMode(2); 9517 chomp($pass = <STDIN>); 9518 Term::ReadKey::ReadMode(0); 9519 print "\n"; 9520 } else { 9521 print " (will be displayed): "; 9522 chomp($pass = <STDIN>); 9523 } 9524 } 9525 9526 return bless { 9527 username => $user, 9528 password => $pass, 9529 }, $class; 9530} 9531 9532sub username { 9533 my($self) = @_; 9534 return $self->{username}; 9535} 9536 9537sub password { 9538 my($self) = @_; 9539 return $self->{password}; 9540} 9541 95421; 9543} 9544##} blib/lib/FlashVideo/VideoPreferences/Account.pm 9545##{ blib/lib/FlashVideo/VideoPreferences.pm 9546{ 9547package FlashVideo::VideoPreferences; 9548 9549use strict; 9550BEGIN { FlashVideo::VideoPreferences::Quality->import(); } # (added by utils/combine-perl.pl) 9551BEGIN { FlashVideo::VideoPreferences::Account->import(); } # (added by utils/combine-perl.pl) 9552 9553sub new { 9554 my($class, %opt) = @_; 9555 9556 return bless { 9557 quality => $opt{quality} || "high", 9558 subtitles => $opt{subtitles} || 0, 9559 }, $class; 9560} 9561 9562sub quality { 9563 my($self) = @_; 9564 9565 return FlashVideo::VideoPreferences::Quality->new($self->{quality}); 9566} 9567 9568sub subtitles { 9569 my($self) = @_; 9570 9571 return $self->{subtitles}; 9572} 9573 9574sub account { 9575 my($self, $site, $prompt) = @_; 9576 9577 return FlashVideo::VideoPreferences::Account->new($site, $prompt); 9578} 9579 95801; 9581} 9582##} blib/lib/FlashVideo/VideoPreferences.pm 9583##{ bin/get_flash_videos 9584{ 9585package main; 9586$::SCRIPT_NAME = "get_flash_videos"; 9587$::INSTALL_TYPE = "cpan-manual"; 9588 9589package App::get_flash_videos; 9590use strict; 9591use Encode (); 9592use File::Basename qw(basename); 9593use File::stat; 9594use Getopt::Long; 9595use Text::Wrap; 9596 9597BEGIN { 9598 if(!$::SCRIPT_NAME) { 9599 require Cwd; 9600 require File::Spec; 9601 my($vol, $dir) = (File::Spec->splitpath(Cwd::realpath($0)))[0, 1]; 9602 unshift @INC, File::Spec->catpath($vol, File::Spec->catdir($dir, "lib")); 9603 } 9604} 9605 9606BEGIN { FlashVideo::URLFinder->import(); } # (added by utils/combine-perl.pl) 9607BEGIN { FlashVideo::Mechanize->import(); } # (added by utils/combine-perl.pl) 9608BEGIN { FlashVideo::Downloader->import(); } # (added by utils/combine-perl.pl) 9609BEGIN { FlashVideo::RTMPDownloader->import(); } # (added by utils/combine-perl.pl) 9610BEGIN { FlashVideo::Search->import(); } # (added by utils/combine-perl.pl) 9611BEGIN { FlashVideo::Utils->import(); } # (added by utils/combine-perl.pl) 9612BEGIN { no strict 'refs'; *debug = \&FlashVideo::Utils::debug; *info = \&FlashVideo::Utils::info; *error = \&FlashVideo::Utils::error; *get_user_config_dir = \&FlashVideo::Utils::get_user_config_dir; *get_win_codepage = \&FlashVideo::Utils::get_win_codepage; *is_program_on_path = \&FlashVideo::Utils::is_program_on_path; *get_terminal_width = \&FlashVideo::Utils::get_terminal_width; } 9613BEGIN { FlashVideo::VideoPreferences->import(); } # (added by utils/combine-perl.pl) 9614 9615unshift @INC, \&plugin_loader; 9616 9617our $VERSION = "1.25"; 9618 9619our %opt; 9620BEGIN { 9621 my $player = "mplayer -really-quiet"; 9622 $player = "VLC" if $^O =~ /MSWin/i; 9623 $player = "open" if $^O =~ /darwin/ && !is_program_on_path("mplayer"); 9624 9625 if(is_program_on_path("xdg-open") && !is_program_on_path("mplayer")) { 9626 $player = "xdg-open"; 9627 } elsif(is_program_on_path("gnome-open") && !is_program_on_path("mplayer")) { 9628 $player = "gnome-open"; 9629 } elsif(is_program_on_path("kde-open") && !is_program_on_path("mplayer")) { 9630 $player = "kde-open"; 9631 } 9632 9633 %opt = ( 9634 yes => 0, 9635 filename => '', 9636 version => 0, 9637 update => 0, 9638 play => 0, 9639 player => $player, 9640 proxy => '', 9641 debug => 0, 9642 quiet => 0, 9643 quality => "high", 9644 subtitles => 0, 9645 info => 0 9646 ); 9647} 9648 9649use constant VER_INFO => <<EOF; 9650get_flash_videos version $VERSION (http://code.google.com/p/get-flash-videos/) 9651EOF 9652 9653use constant USAGE => VER_INFO . <<EOF; 9654 9655Usage: $0 [OPTION]... URL... 9656 $0 [OPTION]... search string 9657 9658Downloads videos from the web pages given in URL or searches Google Video 9659Search for 'search string'. If the URL contains characters such as '&' you 9660will need to quote it. 9661 9662Options: 9663 --add-plugin Add a plugin from a URL. 9664 -d --debug Print extra debugging information. 9665 -f --filename Filename to save the video as. 9666 -p --play Start playing the video once enough has been downloaded. 9667 --player Player to use for the video (default: $opt{player}). 9668 --proxy Proxy to use, use host:port for SOCKS, or URL for HTTP. 9669 --subtitles Download subtitles where available. 9670 -q --quiet Be quiet (only print errors). 9671 -r --quality Quality to download at (high|medium|low, or site specific). 9672 -u --update Update to latest version. 9673 -v --version Print version. 9674 -y --yes Say yes to any questions (don't prompt for any information). 9675 -i --info Print out info about video instead of downloading. 9676 9677EOF 9678 9679use constant REQ_INFO => <<EOF; 9680 9681A required Perl module for downloading this video is not installed. 9682EOF 9683 9684use constant FRIENDLY_FAILURE => <<EOF; 9685 9686Couldn't extract Flash movie URL. This site may need specific support adding, 9687or fixing. 9688 9689Please confirm the site is using Flash video and if you have Flash available 9690check that the URL really works(!). 9691 9692Check for updates by running: $0 --update 9693 9694If the latest version does not support this please open a bug (or 9695contribute a patch!) at http://code.google.com/p/get-flash-videos/ 9696make sure you include the output with --debug enabled. 9697EOF 9698 9699read_conf(); 9700 9701GetOptions( 9702 "yes|y" => \$opt{yes}, 9703 "filename|f=s" => \$opt{filename}, 9704 "version|v" => \$opt{version}, 9705 "update|u" => \$opt{update}, 9706 "help|h" => \$opt{help}, 9707 "play|p" => \$opt{play}, 9708 "player=s" => \$opt{player}, 9709 "proxy=s" => \$opt{proxy}, 9710 "debug|d" => \$opt{debug}, 9711 "quiet|q" => \$opt{quiet}, 9712 "add-plugin=s" => \$opt{add_plugin}, 9713 "quality|r=s" => \$opt{quality}, 9714 "subtitles" => \$opt{subtitles}, 9715 "info|i" => \$opt{info}, 9716) or die "Try $0 --help for more information.\n"; 9717 9718if($opt{version}) { 9719 die VER_INFO; 9720} elsif($opt{update}) { 9721 exit update(); 9722} elsif($opt{help}) { 9723 die USAGE; 9724} elsif($opt{add_plugin}) { 9725 exit add_plugin($opt{add_plugin}); 9726} 9727 9728if ($opt{debug}) { 9729 if(my @plugins = get_installed_plugins()) { 9730 debug @plugins . " plugin" . (@plugins != 1 && "s") . " installed:"; 9731 debug "- $_" for @plugins; 9732 } else { 9733 debug "No plugins installed"; 9734 } 9735} 9736 9737if($^O =~ /MSWin/i) { 9738 $opt{filename} = Encode::decode(get_win_codepage(), $opt{filename}); 9739 binmode STDERR, ":encoding(" . get_win_codepage() . ")"; 9740 binmode STDOUT, ":encoding(" . get_win_codepage() . ")"; 9741} else { 9742 $opt{filename} = Encode::decode("utf-8", $opt{filename}); 9743 binmode STDERR, '<:encoding(UTF-8)'; 9744 binmode STDOUT, '<:encoding(UTF-8)'; 9745} 9746 9747my (@urls) = @ARGV; 9748@urls > 0 or die USAGE; 9749 9750my $search; 9751if ( ((@urls == 1) and $urls[0] !~ m'\.') or 9752 ( (@urls > 1) and ! grep /^http:\/\/|^[\w\-]+\.[\w\-]+/, @urls)) { 9753 $search = join ' ', @urls; 9754} 9755 9756my @download_urls; 9757 9758if ($search) { 9759 if (my @results = FlashVideo::Search->search($search, 10, 20)) { 9760 if ($opt{yes} or @results == 1) { 9761 my $message = (@results == 1) ? 9762 "Downloading only match for '$search': '$results[0]->{name}'" : 9763 "Downloading first match for '$search': '$results[0]->{name}'" ; 9764 info $message; 9765 9766 push @download_urls, $results[0]->{url}; 9767 } 9768 else { 9769 print "Search for '$search' found these results:\n"; 9770 9771 my $columns = get_terminal_width() - 5; 9772 local $Text::Wrap::columns = $columns; 9773 9774 my $count = 1; 9775 for my $result(@results) { 9776 printf "[%2d] %s\n", $count, $result->{name}; 9777 9778 if ($result->{description}) { 9779 print wrap(" ", " ", 9780 substr($result->{description}, 0, $columns * 2)), "\n"; 9781 } 9782 9783 $count++; 9784 } 9785 9786 print "Enter the number(s) or range (e.g. 1-3) of the videos to download " . 9787 "(separate multiple with comma or space): "; 9788 chomp(my $choice = <STDIN>); 9789 $choice ||= 1; 9790 9791 for(split /[ ,]+/, $choice) { 9792 if (/-/) { 9793 my ($lower, $upper) = split /-/, $choice; 9794 if ($upper > $lower and $upper > 0) { 9795 push @download_urls, map { $results[$_]->{url} } $lower - 1 .. $upper - 1; 9796 next; 9797 } 9798 else { 9799 print STDERR "Search range '$_' is invalid.\n"; 9800 exit 1; 9801 } 9802 } 9803 9804 $_--; 9805 9806 if (!$results[$_]) { 9807 print STDERR "'$_' is an invalid choice.\n"; 9808 exit 1; 9809 } 9810 9811 push @download_urls, $results[$_]->{url}; 9812 } 9813 } 9814 } 9815 else { 9816 print STDERR "No results found for '$search'.\n"; 9817 exit 1; 9818 } 9819} 9820else { 9821 @download_urls = @urls; 9822} 9823 9824my $download_count = 0; 9825 9826my $prefs = FlashVideo::VideoPreferences->new(%opt); 9827 9828foreach my $url (@download_urls) { 9829 if (download($url, $prefs, @download_urls - $download_count)) { 9830 $download_count++; 9831 } 9832} 9833 9834if($download_count == 0) { 9835 info "Couldn't download any videos."; 9836 exit 1; 9837} elsif($download_count != @download_urls) { 9838 info "Problems downloading some videos."; 9839 exit 2; 9840} 9841 9842exit 0; 9843 9844sub download { 9845 my($url, $prefs, $remaining) = @_; 9846 9847 $url = "http://$url" if $url !~ m!^\w+:!; 9848 9849 my $browser = FlashVideo::Mechanize->new; 9850 9851 my($package, $possible_url) = FlashVideo::URLFinder->find_package($url, $browser); 9852 9853 if($package->can("pre_find")) { 9854 $package->pre_find($browser); 9855 } 9856 9857 info "Downloading $url"; 9858 $browser->get($url); 9859 9860 if (!$browser->success and !$browser->response->is_redirect) { 9861 if ($opt{proxy}) { 9862 if ($browser->response->header('Client-Warning') eq 'Internal response') { 9863 info "Couldn't download $url - might not be able to contact " . 9864 "your proxy server ($opt{proxy})"; 9865 } 9866 } 9867 9868 error "Couldn't download '$url': " . $browser->response->status_line; 9869 } 9870 9871 my($actual_url, @suggested_fnames) = eval { 9872 $package->find_video($browser, $possible_url, $prefs); 9873 }; 9874 9875 if(!$actual_url) { 9876 if($@ =~ /^Must have | requires /) { 9877 my $error = "$@"; 9878 $error =~ s/at $0.*//; 9879 print STDERR "$error" . REQ_INFO; 9880 return 0; 9881 } else { 9882 print STDERR "Error: $@" . FRIENDLY_FAILURE; 9883 return 0; 9884 } 9885 } 9886 9887 my $suggested_filename = $suggested_fnames[-1]; 9888 if (ref($actual_url) eq 'ARRAY') { 9889 $suggested_filename ||= $actual_url->{flv}; 9890 } 9891 9892 if (!$opt{play}) { 9893 if (!$opt{yes} && !$opt{filename} && @suggested_fnames > 1) { 9894 print "There are different suggested filenames, please choose:\n"; 9895 my $count; 9896 foreach my $filename (@suggested_fnames) { 9897 $count++; 9898 print "$count - $filename\n"; 9899 } 9900 9901 print "\nWhich filename would you like to use?: "; 9902 chomp(my $chosen_fname = <STDIN>); 9903 9904 $suggested_filename = $suggested_fnames[$chosen_fname - 1] || 9905 $suggested_fnames[-1]; 9906 } 9907 } 9908 9909 my $save_as = $opt{filename} || $suggested_filename; 9910 9911 if($opt{info}) { 9912 if(ref($actual_url) eq 'ARRAY') { 9913 for my $data(@$actual_url) { 9914 print "Filename: " . $data->{flv} . "\n"; 9915 $_ = $suggested_filename || $data->{flv}; 9916 s/_/ /g; 9917 s/\.[^\.]*$//; 9918 print "Title: " . $_ . "\n"; 9919 print "Content-Location: " . $data->{rtmp} . "\n"; 9920 print "\n"; 9921 } 9922 } else { 9923 print "Filename: " . ($save_as || $actual_url->{flv}) . "\n"; 9924 $_ = $suggested_filename || $actual_url->{flv}; 9925 s/_/ /g; 9926 s/\.[^\.]*$//; 9927 print "Title: " . $_ . "\n"; 9928 print "Content-Location: "; 9929 if(ref($actual_url) eq 'HASH') { 9930 print $actual_url->{rtmp} . "\n"; 9931 } else { 9932 print $actual_url . "\n"; 9933 $browser->head($actual_url); 9934 if($browser->response->header('Content-Length')) { 9935 print "Content-Length: " . $browser->response->header('Content-Length') . "\n"; 9936 } 9937 } 9938 } 9939 exit; 9940 } 9941 9942 my $action = $opt{play} ? "play" : "download"; 9943 9944 for my $data((ref($actual_url) eq 'ARRAY' ? @$actual_url : $actual_url)) { 9945 my $downloader; 9946 my $file = $save_as; 9947 9948 if(ref $data eq 'HASH') { 9949 $downloader = FlashVideo::RTMPDownloader->new; 9950 $file ||= $data->{flv}; 9951 } else { 9952 $downloader = FlashVideo::Downloader->new; 9953 } 9954 9955 if (ref $data eq 'ARRAY') { 9956 my ($url, $part_number, $part_count, $part_size) = @$data; 9957 $data = $url; 9958 if (defined $part_number && defined $part_count) { 9959 my $part_suffix = sprintf('.part%02d_of_%02d', $part_number, $part_count); 9960 substr $file, rindex($file, '.'), 0, $part_suffix 9961 if $part_count > 1; 9962 } 9963 9964 if (defined $part_size && -f $file && -s $file == $part_size) { 9965 info "Already downloaded $file ($part_size bytes)"; 9966 next; 9967 } 9968 } 9969 9970 my $size = $downloader->$action($data, $file, $browser) || return 0; 9971 9972 info "\n" . ($remaining == 1 ? "Done. " : "") 9973 . "Saved $size bytes to $downloader->{printable_filename}"; 9974 } 9975 9976 return 1; 9977} 9978 9979sub read_conf { 9980 for my $file("/etc/get_flash_videosrc", "$ENV{HOME}/.get_flash_videosrc") { 9981 open my $fh, "<", $file or next; 9982 9983 while(<$fh>) { 9984 s/\r?\n//; 9985 next if /^\s*(#|$)/; 9986 9987 my($n, $v) = split /\s*=\s*/; 9988 $v = 1 unless defined $v; 9989 $opt{$n} = $v; 9990 } 9991 } 9992} 9993 9994sub add_plugin { 9995 my($plugin_url) = @_; 9996 9997 my $uri = URI->new($plugin_url); 9998 9999 unless(-d get_plugin_dir()) { 10000 require File::Path; 10001 File::Path::mkpath(get_plugin_dir()) 10002 or die "Unable to create plugin dir: $!"; 10003 } 10004 10005 my $filename = get_plugin_dir() . "/" . basename($uri->path); 10006 10007 if($filename !~ /\.pm$/) { 10008 die "Plugins must have a file extension of '.pm'\n"; 10009 } 10010 10011 if(!$uri->scheme) { 10012 require File::Copy; 10013 File::Copy::copy($plugin_url => $filename) 10014 || die "Unable to copy plugin to '$filename': $!\n"; 10015 10016 info "Plugin installed."; 10017 return 0; 10018 } else { 10019 my $browser = FlashVideo::Mechanize->new; 10020 return !install_plugin($browser, $plugin_url, $filename); 10021 } 10022} 10023 10024sub update { 10025 my %update_types = ( 10026 'cpan-cpan' => [1, "cpan " . __PACKAGE__], 10027 'cpan-cpanp' => [1, "cpanp i " . __PACKAGE__], 10028 'cpan-cpanm' => [1, "cpanm " . __PACKAGE__], 10029 'cpan-manual' => [0, "Manual install"], 10030 ); 10031 10032 if($::SCRIPT_NAME) { 10033 my $browser = FlashVideo::Mechanize->new; 10034 10035 $browser->get("http://get-flash-videos.googlecode.com/svn/wiki/Version.wiki"); 10036 10037 if(!$browser->response->is_success) { 10038 die "Unable to retrieve version data: " . $browser->response->status_line . "\n"; 10039 } 10040 10041 my $version = ($browser->content =~ /version: (\S+)/)[0]; 10042 my $base = ($browser->content =~ /from: (\S+)/)[0]; 10043 my $info = ($browser->content =~ /info: (\S+)/)[0]; 10044 my $url = $base . $::SCRIPT_NAME . "-" . $version; 10045 10046 die "Unable to parse version data" unless $version and $base; 10047 10048 my @v = split /\./, $version; 10049 my @V = split /\./, $VERSION; 10050 10051 my $newer = 0; 10052 my $i = 0; 10053 for(@v) { 10054 $newer = 1 if !defined $V[$i] || $_ > $V[$i]; 10055 last if $V[$i] > $v[$i]; 10056 $i++; 10057 } 10058 10059 if($newer) { 10060 info "Newer version ($version) available"; 10061 debug "(Install type: $::INSTALL_TYPE)"; 10062 10063 if($::INSTALL_TYPE =~ /^cpan-/) { 10064 10065 my $update_method = $update_types{$::INSTALL_TYPE}; 10066 if($update_method->[0]) { 10067 info "This was installed via CPAN, you may upgrade by running:"; 10068 info $update_method->[1]; 10069 10070 my $run_cpan = $opt{yes} || do { 10071 info "Shall I run that for you? (Y/n)"; 10072 <STDIN> =~ /(?:^\s*$|y)/i; 10073 }; 10074 10075 if($run_cpan) { 10076 system $update_method->[1]; 10077 } 10078 } else { 10079 info "Please visit http://code.google.com/p/get-flash-videos to upgrade"; 10080 } 10081 } else { 10082 update_script($browser, $url, $info); 10083 } 10084 } else { 10085 print STDERR "You already have the latest version.\n"; 10086 } 10087 } else { 10088 info "Development version, not updated"; 10089 } 10090 10091 update_plugins(); 10092 10093 return 0; # exit code 10094} 10095 10096sub update_script { 10097 my($browser, $url, $info) = @_; 10098 10099 info "Downloading new version..."; 10100 die "Cannot update -- unable to write to $0\n" unless -w $0; 10101 10102 my $new_file = $0 . ".new"; 10103 $browser->mirror($url, $new_file); 10104 10105 if($browser->response->is_success && -f $new_file) { 10106 rename $0, "$0.old" or die "Unable to rename $0 to $0.old: $!"; 10107 rename $new_file, $0 or die "Unable to rename $new_file to $0: $!"; 10108 chmod 0755, $0; 10109 10110 info "New version installed as $0"; 10111 info "(previous version backed up to $0.old)."; 10112 info $info; 10113 } else { 10114 die "Download failed: " . $browser->response->status_line; 10115 } 10116} 10117 10118sub update_plugins { 10119 my $browser = FlashVideo::Mechanize->new; 10120 10121 foreach my $plugin(get_installed_plugins()) { 10122 debug "Seeing if there is an update for $plugin.."; 10123 10124 my $file = get_plugin_dir() . "/$plugin"; 10125 require $file; 10126 10127 my $package = "FlashVideo::Site::" . ($plugin =~ /(.*)\.pm$/)[0]; 10128 10129 if($package->can("update")) { 10130 $package->update(); 10131 } else { 10132 no strict 'refs'; 10133 10134 my $downloaded = 0; 10135 my $newer_found = 0; 10136 10137 foreach my $update_url (@{ "$package\::update_urls" }) { 10138 $browser->head($update_url); 10139 10140 if (!$browser->response->is_success) { 10141 debug "Couldn't retrieve $update_url for $plugin: " . $browser->response->status_line; 10142 next; 10143 } 10144 10145 my $file_mtime = stat($file)->mtime; 10146 10147 my $remote_plugin_mtime = $browser->response->last_modified; 10148 10149 if ($remote_plugin_mtime > $file_mtime) { 10150 info "Newer version of plugin $plugin found at $update_url, trying to download and install"; 10151 $newer_found = 1; 10152 10153 if ($downloaded = install_plugin($browser, $update_url, $file)) { 10154 last; 10155 } 10156 } 10157 else { 10158 debug "Plugin $plugin is already the lastest version."; 10159 debug "(Remote: " . $browser->response->header("Last-Modified") 10160 . "; Local: " . gmtime($file_mtime) . " GMT)"; 10161 } 10162 } 10163 10164 if ($newer_found and !$downloaded) { 10165 die "Couldn't install $plugin plugin"; 10166 } 10167 } 10168 } 10169} 10170 10171sub install_plugin { 10172 my ($browser, $url, $file) = @_; 10173 10174 my $plugin_exists = -f $file; 10175 10176 my $new_file = $plugin_exists ? "$file.new" : $file; 10177 10178 $browser->mirror($url, $new_file); 10179 10180 if ($browser->response->is_success && -f $new_file) { 10181 my $short_name = basename($file); 10182 10183 if ($plugin_exists) { 10184 rename $file, "$file.old" or die "Unable to rename $file to $file.old: $!"; 10185 rename $new_file, $file or die "Unable to rename $new_file to $file: $!"; 10186 10187 info "New version of $short_name installed as $file"; 10188 info "(previous version backed up to $file.old)."; 10189 } 10190 else { 10191 info "New plugin $short_name installed as $file"; 10192 } 10193 10194 return 1; 10195 } 10196 else { 10197 warn "Download failed: " . $browser->response->status_line; 10198 } 10199 10200 return 0; 10201} 10202 10203sub plugin_loader { 10204 my (undef, $module) = @_; 10205 10206 if ($module =~ m'^FlashVideo/Site/(.*)') { 10207 my $plugin_name = $1; 10208 10209 my $plugin_dir = get_plugin_dir(); 10210 10211 debug "Trying to open plugin $plugin_dir/$plugin_name"; 10212 10213 if (open my $plugin_fh, '<', "$plugin_dir/$plugin_name") { 10214 return $plugin_fh; # Perl then reads the plugin from the FH 10215 } 10216 } 10217 10218 return; 10219} 10220 10221sub get_installed_plugins { 10222 my $plugin_dir = get_plugin_dir(); 10223 10224 my @plugins; 10225 if (opendir my $plugin_dir_dh, $plugin_dir) { 10226 @plugins = grep /\.pm$/i, 10227 readdir $plugin_dir_dh; 10228 closedir $plugin_dir_dh; 10229 } 10230 10231 return @plugins; 10232} 10233 10234sub get_plugin_dir { 10235 return get_user_config_dir() . "/plugins"; 10236} 10237} 10238##} bin/get_flash_videos 10239