Skip to content

Instantly share code, notes, and snippets.

@hrpunio
Last active August 29, 2015 14:25
Show Gist options
  • Save hrpunio/35207aa9257288889612 to your computer and use it in GitHub Desktop.
Save hrpunio/35207aa9257288889612 to your computer and use it in GitHub Desktop.
Upload file | Upload file with metadata | Create album | List albums @ picasaweb via API
#!/usr/bin/perl
#
# *** Upload file | Upload file with metadata | Create album | List albums @ picasaweb via API ***
#
# Examples of usage
# Note: if option --printonly is present NO real action is performed
# ONLY http message is verbatim printed on STDOUT (useful in case of problems)
# -----------------
# Upload with metadata:
# picasaweb.pl -xload -title Komorowski -descr 'Komorowski w czapce' -keywords 'komorowski,prezydent' -file BK_w_czapce.jpg -album 12345
# Upload w/o metadata:
# picasaweb.pl -upload -file BK_w_czapce.jpg -album 12345
# Create album:
# picasaweb.pl -create -title Koty -descr 'Zdjęcia kotów' -keywords 'kot,cat,gato'
# List albums:
# picasaweb.pl -list
#
use strict;
use LWP::UserAgent;
use Getopt::Long;
use File::MimeInfo;
use XML::LibXML;
my $profileID="default";
### DEFAULT Album Id ##################
### Misc Stuff ###
### my $AlbumId ="5814486831826593553";
### Misc Stuff 2 ###
### my $AlbumId ="6063067742713120609";
### Misc Stuff 3 ###
## my $AlbumId ="6118749723887405297";
### Misc Stuff 4 ###
my $AlbumId ="6170354040646469009";
### ### ### ### ### ### #### ### ### ### ### ###
my $Action = 'u'; ## x| u | c | l (default action is Upload)
my $entryTitle = ''; my $entryDescription = ''; my $entryKeywords = '';
my $ActionUpload =''; my $ActionList = ''; my $ActionCreate = ''; my $ActionXload = '';
my $ImageFile = '';
my $dummyReq='';
GetOptions("xload" => \$ActionXload, "upload" => \$ActionUpload, "list" => \$ActionList, "create" => \$ActionCreate,
"title=s" => \$entryTitle, "description=s" => \$entryDescription, "keywords=s" => \$entryKeywords,
"file=s" => \$ImageFile,
"album=s" => \$AlbumId, ## UploadFile to Album
"printonly" => \$dummyReq, ) ;
## Determine action and check arguments:
if ( $ActionUpload ) {$Action = 'u'} elsif ( $ActionList ) { $Action = 'l'}
elsif ( $ActionCreate ) { $Action = 'c'}
elsif ( $ActionXload ) { $Action = 'x'}
if ( $Action eq 'x' && ($entryTitle eq '' || (! -e $ImageFile ))) {
print STDERR "*** USAGE: $0 -xload -title Tytuł -descr Opis -keywords Keywords -file Plik [-album AlbumId]\n" ; exit; }
if ( $Action eq 'c' && $entryTitle eq '' ) {
print STDERR "*** USAGE: $0 -create -title Tytuł -descr Opis -keywords Keywords\n" ; exit; }
if ( $Action eq 'u' && (! -e $ImageFile )) {
print STDERR "*** USAGE: $0 -upload -file Plik [-album AlbumId]\n" ;
print STDERR "*** USAGE: $0 -create -title Tytuł -descr Opis -keywords Keywords\n" ;
print STDERR "*** USAGE: $0 -list\n" ; exit;
}
### Authenticate with external script (oauth2picasa.py):
my $ACCESS_TOKEN=`oauth2picasa.py`;
chomp($ACCESS_TOKEN);
print STDERR "*** AccessToken: $ACCESS_TOKEN [AlbumId: $AlbumId]\n";
my $req ; my $blog_entry ;
my $picasawebURL = "https://picasaweb.google.com/data/feed/api/user/$profileID";
if ( $Action eq 'c' ) {## Action: create album
$req = HTTP::Request->new(POST => $picasawebURL );
$req->header( 'Content-Type' => 'application/atom+xml' );
$blog_entry = "<entry xmlns='http://www.w3.org/2005/Atom'
xmlns:media='http://search.yahoo.com/mrss/'
xmlns:gphoto='http://schemas.google.com/photos/2007'>"
. "<title type='text'>$entryTitle</title>"
. "<summary type='text'>$entryDescription</summary>"
. "<media:group><media:keywords>$entryKeywords</media:keywords></media:group>"
. "<category scheme='http://schemas.google.com/g/2005#kind'
term='http://schemas.google.com/photos/2007#album'></category></entry>";
$req->content($blog_entry);
}
elsif ( $Action eq 'l' ) {## Action: list albums
$req = HTTP::Request->new(GET => $picasawebURL );
}
elsif ( $Action eq 'u' ) {## Action: Upload 1 photo
my $mimeType = mimetype($ImageFile);
## https://developers.google.com/picasa-web/docs/2.0/developers_guide_protocol
##
$req = HTTP::Request->new(POST => "$picasawebURL/albumid/$AlbumId" );
$req->header( 'Content-Type' => "$mimeType" );
##$req->header( 'Content-Length' => $imageLength ); ## pakiet liczy sam
$req->header( 'Slug' => "$ImageFile" );
## http://www.perlmonks.org/?node_id=131584
open(FILE, $ImageFile);
$req->content(join('',<FILE>));
close(FILE);
}
###
elsif ( $Action eq 'x' ) {## Action: Upload 1 photo with metadata
# https://groups.google.com/forum/#!topic/google-picasa-data-api/2qRfP0EIFhk
my $mimeType = mimetype($ImageFile);
## https://developers.google.com/picasa-web/docs/2.0/developers_guide_protocol
$req = HTTP::Request->new(POST => "$picasawebURL/albumid/$AlbumId" );
$req->header( 'Content-Type' => "multipart/related" );
open(FILE, $ImageFile);
my $add_photo_metadata = "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/'>"
. "<title type='text'>$entryTitle</title>"
. "<summary type='text'>$entryDescription</summary>"
. "<media:group><media:keywords>$entryKeywords</media:keywords></media:group>"
. "<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#photo'></category></entry>";
my $add_photo_data = join('',<FILE>);
close(FILE);
## http://www.perlmonks.org/?node_id=131584
$req->add_part(HTTP::Message->new(['Content-Type' => 'application/atom+xml'], $add_photo_metadata));
$req->add_part(HTTP::Message->new(['Content-Type' => "$mimeType"], $add_photo_data));
}
$req->header( 'Authorization' => "Bearer $ACCESS_TOKEN" );
$req->header( 'GData-Version' => '2' );
## ### ###
my $res ;
my $ua = LWP::UserAgent->new;
if ($dummyReq) {
# Print message verbatim in case of problems
# http://www.perlmonks.org/bare/?node_id=464442
$ua->prepare_request($req); print($req->as_string); my $res; exit;
}
else {
$res = $ua->request($req);
}
if ($res->is_success) {
my $decoded_response = $res->decoded_content; # or whatever
my $parser = XML::LibXML->new();
my $doc ; eval { $doc = $parser->parse_string($decoded_response) };
if ($@) { print STDERR "*** Error parsing XML $decoded_response\n"; next ;}
if ( $Action eq 'u' || $Action eq 'x') {
my $xpc = XML::LibXML::XPathContext->new( $doc->documentElement() );
## http://stackoverflow.com/questions/4083550/why-does-xmllibxml-find-no-nodes-for-this-xpath-query-when-using-a-namespace
$xpc->registerNs( 'media', 'http://search.yahoo.com/mrss/');
foreach my $node ( $xpc->findnodes('//media:title') ) { print "Title: " . $node->textContent() . " (uploaded)\n"; }
foreach my $node ( $xpc->findnodes('(//media:content|//media:thumbnail)') ) {
print "Url: " . $node->getAttribute('url') . "\n"; }
}
elsif ( $Action eq 'l' ) {### ListAlbums
##use open ':std', ':encoding(UTF-8)'; ### Ew problem z inną akcję niż list??
##print "*** OK *** $decoded_response\n";
my $xpc = XML::LibXML::XPathContext->new( $doc->documentElement() );
$xpc->registerNs( 'dfl', 'http://www.w3.org/2005/Atom');
print "******* WARNING: Only meaningfull titles are listed: *********\n";
foreach my $node ( $xpc->findnodes('//dfl:entry') ) {
my $xpe = XML::LibXML::XPathContext->new( $node );
$xpe->registerNs( 'dfl', 'http://www.w3.org/2005/Atom');
my $title = ($xpe->findnodes('./dfl:title'))[0]->textContent();
if ($title =~ /[^0-9\-\.]/ ) {
print ">> Album title: $title ## ";
foreach my $entry ( $xpe->findnodes('dfl:link') ) {
if ($entry->getAttribute('rel') eq 'self') { print $entry->getAttribute('href') . "\n"; }
} }
}
#############
}
else {
print "*** OK *** $decoded_response\n";
}
}
else { die $res->status_line; }
## // koniec //
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment