You're replying to a comment by james.

james Permalink
December 26, 2007, 20:36

this also sort of works for megavideo however it needs alot of improvement because my first test uploaded it twice. then said gave error however it had uploaded.

#!/usr/bin/perl
#
# 2007.07.30
#
# Peteris Krumins (peter@catonmat.net)
# http://www.catonmat.net - good coders code, great reuse
#

use constant VERSION => "1.1";

use strict;
use warnings;
use LWP::UserAgent;
use Getopt::Std;

$Getopt::Std::STANDARD_HELP_VERSION = 1;

# set these values for default -l (login) and -p (pass) values
#
use constant YT_LOGIN => "jam3s2k";
use constant YT_PASS => "fux0ryou";

# video categories
#
my %cats = (
2 => 'Autos & Vehicles',
23 => 'Comedy',
24 => 'Entertainment',
1 => 'Film & Animation',
20 => 'Gadgets & Games',
26 => 'Howto & DIY',
10 => 'Music',
25 => 'News & Politics',
22 => 'People & Blogs',
15 => 'Pets & Animals',
17 => 'Sports',
19 => 'Travel & Places'
);

# various urls
my $login_url = 'http://www.megavideo.com/?s=signup';
my $upload_url = 'http://www.megavideo.com/?c=upload';

unless (@ARGV) {
HELP_MESSAGE();
exit 1;
}

my %opts;
getopts('l:p:f:c:t:d:x:', \%opts);

# if -l or -p are not given, try to use YT_LOGIN and YT_PASS constants
unless (defined $opts{l}) {
unless (length YT_LOGIN) {
preamble();
print "Youtube username/login as neither defined nor passed as an argument\n";
print "Use -l switch to specify the username\n";
print "Example: -l joe_random\n";
exit 1;
}
else {
$opts{l} = YT_LOGIN;
}
}

unless (defined $opts{p}) {
unless (length YT_PASS) {
preamble();
print "Password was neither defined nor passed as an argument\n";
print "Use -p switch to specify the password\n";
print "Example: -p secretPass\n";
exit 1;
}
else {
$opts{p} = YT_PASS;
}
}

unless (defined $opts{f} && length $opts{f}) {
preamble();
print "No video file was specified\n";
print "Use -f switch to specify the video file\n";
print 'Example: -f "C:\Program Files\movie.avi"', "\n";
print 'Example: -f "/home/pkrumins/super.cool.video.wmv"', "\n";
exit 1;
}

unless (-r $opts{f}) {
preamble();
print "Video file is not readable or does not exist\n";
print "Check the permissions and the path to the file\n";
exit 1;
}

unless (defined $opts{c} && length $opts{c}) {
preamble();
print "No video category was specified\n";
print "Use -c switch to set the category of the video\n";
print "Example: -c 20, would set category to Gadgets & Games\n\n";
print_cats();
exit 1;
}

unless (defined $cats{$opts{c}}) {
preamble();
print "Category '$opts{c}' does not exist\n\n";
print_cats();
exit 1;
}

unless (defined $opts{t} && length $opts{t}) {
preamble();
print "No video title was specified\n";
print "Use -t switch to set the title of the video\n";
print 'Example: -t "Super Cool Video Title"', "\n";
exit 1;
}

unless (defined $opts{d} && length $opts{d}) {
preamble();
print "No video description was specified\n";
print "Use -d switch to set the description of the video\n";
print 'Example: -d "The coolest video description"', "\n";
exit 1;
}

unless (defined $opts{x} && length $opts{x}) {
preamble();
print "No tags were specified\n";
print "Use -x switch to set the tags\n";
print 'Example: -x "foo, bar, baz, hacker, purl"', "\n";
exit 1;
}

# tags should be at least two chars, can't be just numbers
my @tags = split /,\s+/, $opts{x};
my @filtered_tags = grep { length > 2 && !/^\d+$/ } @tags;
unless (@filtered_tags) {
preamble();
print "Tags must at least two chars in length and must not be numeric!\n";
print "For example, 'foo', 'bar', 'yo29' are valid tags, but ";
print "'22222', 'hi', 'b9' are invalid\n";
exit 1;
}

$opts{x} = join ', ', @filtered_tags;
# create the user agent, have it store cookies and
# pretend to be a cool windows firefox browser
my $ua = LWP::UserAgent->new(
cookie_jar => {},
agent => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.4) '.
'Gecko/20070515 Firefox/2.0.0.4'
);

# let the user agent follow redirects after a POST request
push @{$ua->requests_redirectable}, 'POST';

print "Logging in to YouTube...\n";
login();

print "Uploading the video ($opts{t})...\n";
upload();

print "Done!\n";

sub login {
# submit the login form
my $res = $ua->post($login_url,
{
current_form => 'loginForm',
nickname => $opts{l},
password => $opts{p},
action => 'login'
}
);
unless ($res->is_success) {
die "Failed logging in: failed submitting login form: ",
$res->status_line;
}

# We have no good way to check if we really logged in.
# I found that when you have logged in the upper right menu changes
# and you have access to 'Log Out' option.
# We check for this string to see if we have logged in.
unless ($res->content =~ /Log Out/) {
die "Failed logging in: username/password incorrect";
}
}

sub upload {
# upload is actually a two step process, first we set the video info,
# and then we post the actual video file
#

my $resp = $ua->get($upload_url);
unless ($resp->is_success) {
die "Failed getting $upload_url: ", $resp->status_line;
}


# let's prepare the video field hash which we will need in both steps
my %vid_fields = (
action => "step2",
title => $opts{t},
description => $opts{d},
tags => $opts{x},
channel => $opts{c},
language => "1",
#ignore_broadcast_settings => 0,

);

$resp = upload_step_one(\%vid_fields);

# now add additional video fields, the new session token,

$vid_fields{action} = "submit";
$vid_fields{message} = [ $opts{d} ];
$vid_fields{file} = [ $opts{f} ];
$vid_fields{private} = "1";
$vid_fields{channels} = "24";

# the upload form's action URL at step 2 changes, we need to extract it
my $action_url;
if ($resp->content =~ m{enctype="multipart/form-data" action="(.+?)"}) {
$action_url = $1;
}
else {
die "Failed extracting action URL, YouTube might have redesigned!";
}

$resp = upload_step_two($action_url, \%vid_fields);

# After the video has been uploaded, youtube thanks the user
# for uploading the vid. Let's test for this thanks message
# to see if the upload was successful
unless ($resp->content =~ /Upload Complete/) {
die "Upload might have failed, no 'thanks for upload' message ",
"was found!.\n",
"Or YouTube might have redesigned!";
}
}

sub extract_session_token {
my $content = shift;

if ($content =~ m{token = "(.+?)"}) {
return $1;
}

return;
}

sub upload_step_one {
my $vid_fields = shift;
my $resp = $ua->post($upload_url, $vid_fields,
"Content_Type" => "form-data");

unless ($resp->is_success) {
die "First upload step failed: ", $resp->status_line;
}

return $resp;
}

sub upload_step_two {
my ($url, $vid_fields) = @_;
my $resp = $ua->post($url, $vid_fields,
"Content_Type" => "form-data");

unless ($resp->is_success) {
die "Second upload step failed: ", $resp->status_line;
}

return $resp;
}

sub HELP_MESSAGE {
preamble();
print "Usage: $0 ",
"-l [login] ",
"-p [password] ",
"-f ",
"-c ",
"-t ",
"-d ",
"-x \n\n";
print_cats();
}

sub print_cats {
print "Possible categories (for -c switch):\n";
printf "%-4s - %s\n", $_, $cats{$_} foreach (sort {
$cats{$a} cmp $cats{$b}
} keys %cats);
}

sub VERSION_MESSAGE {
preamble();
print "Version: v", VERSION, "\n";
}

sub preamble {
print "YouTube video uploader by Peteris Krumins (peter\@catonmat.net)\n";
print "http://www.catonmat.net - good coders code, great reuse\n";
print "\n"
}

Reply To This Comment

(why do I need your e-mail?)

(Your twitter name, if you have one. (I'm @pkrumins, btw.))

Type the first letter of your name: (just to make sure you're a human)

Please preview the comment before submitting to make sure it's OK.