You're viewing a comment by overrider and its responses.
You're viewing a comment by overrider and its responses.
I am being sponsored by Syntress! They bought me an amazing dedicated server to run catonmat on. If you're looking web services, I highly recommend the Syntress guys!
I am being sponsored by A-Writer! If you ever need help with essay writing, look no further than A-Writer! They will help you with your writing in as quickly as 3 hours!
I love to read science books. They make my day and I get ideas for awesome blog posts, such as Busy Beaver, On Functors, Recursive Regular Expressions and many others.
Take a look at my
Amazon wish list, if you're curious about what I have planned reading next, and want to surprise me. :)
If you are interested in advertising on catonmat.net, contact me.
Free tools for coding on Vietstarsoft.com.
Programming homework help.


Hey, fixed it again, works for me now. Youtube changed the login procedure, and some other things around again. Wish they could stop that.
#!/usr/bin/perl # # Version 1.0: 2007.07.30 # Version 1.1: 2007.10.12: youtube changed html # Version 1.2: 2008.03.13: youtube changed html # # 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; use Net::SSLeay; use Data::Dumper; $Getopt::Std::STANDARD_HELP_VERSION = 1; # set these values for default -l (login) and -p (pass) values # use constant YT_LOGIN => ""; use constant YT_PASS => ""; # 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 = 'https://www.google.com/accounts/ServiceLogin?service=youtube'; my $upload_url = 'http://www.youtube.com/my_videos_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 an even cooler Linux firefox browser my $ua = LWP::UserAgent->new( cookie_jar => {}, agent => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.6) Gecko/20070802 SeaMonkey/1.1.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('https://www.google.com/accounts/ServiceLoginAuth?service=youtube', { Email => $opts{l}, Passwd => $opts{p}, action_login => 'signIn' } ); 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 =~ /Sign 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; } my $session_token = extract_session_token($resp->content); unless (defined $session_token) { die "Failed extracting session token, YouTube might have redesigned!"; } # let's prepare the video field hash which we will need in both steps my %vid_fields = ( field_myvideo_title => $opts{t}, field_myvideo_descr => $opts{d}, field_myvideo_keywords => $opts{x}, field_myvideo_categories => $opts{c}, language => "EN", action_upload => "Upload a video...", allow_embeddings => "Yes", allow_responses => "Yes", allow_comments => "Yes", allow_ratings => "Yes", location => "", field_date_mon => 0, field_date_day => 0, field_date_yr => 0, field_privacy => "public", ignore_broadcast_settings => 0, session_token => $session_token ); $resp = upload_step_one(\%vid_fields); # now add additional video fields, the new session token, # the addresser field (no idea what it is), and some more fields $vid_fields{session_token} = extract_session_token($resp->content); unless (defined $vid_fields{session_token}) { die "Failed extracting session token for upload step two\n", "YouTube might have redesigned :("; } #if ($resp->content =~ m{name="addresser" value="(.+?)">}) { # $vid_fields{addresser} = $1; #} #else { # die "Failed extracting 'addresser' id for upload step two, YouTube might have redesigned :("; #} $vid_fields{contact} = ""; $vid_fields{field_command} = "myvideo_submit"; $vid_fields{field_uploadfile} = [ $opts{f} ]; $vid_fields{field_private_share_entities} = ""; $vid_fields{action_upload} = "Upload Video"; # 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; #} #if ($content =~ m{_token = '(.+?)'}) { 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