Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Zooomr uploader

by polettix (Vicar)
on Nov 13, 2007 at 03:25 UTC ( #650429=sourcecode: print w/replies, xml ) Need Help??
Category: Web Stuff
Author/Contact Info Flavio Poletti <flavio AT polettix.it>
Description: A simple upload script for Zooomr, an online photo album service that will hopefully reach Flickr standards. The script contains full documentation in POD, but you will be able to do the following:
shell$ zooomr -u pippo@example.com -p pluto foto*.jpg # Let the program ask you for the password, so that you don't have # to show it on the screen shell$ zooomr add -u pippo@example.com photo*.jpg # Add a tag shell$ zooomr add -u pippo@example.com --tag awesome photo*.jpg # Add two tags shell$ zooomr add -u pippo@example.com -t awesome -t good photo*.jpg
Happy uploading! You can also save your recurrent options inside a configuration file .zooomr inside your home directory.

Update: added more features and checks for good uploads vs fake ones (Zooomr sometimes simply seems to throw an upload in the dust bin).

Update: added support for browser cookie file, managing external authentication via browser (needed for OpenID accounts). Added some missing documentation.

Update: added support for summary file at the end of upload, to report managed files and their URIs (see this post in Zooomr groups).

Update: changed upload URI to conform to current non-flash upload URI.

#!/usr/bin/env perl
use strict;
use warnings;
use Carp;
use Pod::Usage qw( pod2usage );
use Getopt::Long qw( :config gnu_getopt );
use version; my $VERSION = qv('0.3.0');
use English qw( -no_match_vars );
use WWW::Mechanize;
use IO::Prompt qw( prompt );
use File::Slurp qw( slurp );
use Config::Tiny;
use Path::Class qw( file );
use List::MoreUtils qw( uniq );

# Integrated logging facility
use Log::Log4perl qw( :easy :no_extra_logdie_message );
Log::Log4perl->easy_init($INFO);

my %defaults = (
   config     => file($ENV{HOME}, '.zooomr')->stringify(),
   login_page => 'http://www.zooomr.com/login/',
   upload_page => 'http://www.zooomr.com/photos/upload/?noflash=okiwil
+l',
   logout_page => 'http://www.zooomr.com/logout/',
   search_page => 'http://www.zooomr.com/search/photos/',
   login     => 1,       # by default, try to login
   pause     => 5,
   backoff   => 5,
   max_retry => 4,
   debug     => $INFO,
);

# Script implementation here
my %config = get_configuration(%defaults);

if ($config{check}) {
   print {*STDERR} "configuration OK\n";
   exit 0;
}

get_logger()->level(
   {
      TRACE => $TRACE,
      DEBUG => $DEBUG,
      INFO  => $INFO,
      WARN  => $WARN,
      ERROR => $ERROR,
      FATAL => $FATAL,
   }->{uc $config{debug}}
     || $INFO
);

INFO 'configuration OK';

# On with the show
my $ua = WWW::Mechanize->new(autocheck => 1);
eval {
   my $action = __PACKAGE__->can($config{action})
     or die
     "You've found a bug! Someway, $config{action} is not supported\n"
+;

   $ua->env_proxy();
   $ua->proxy('http', $config{proxy}) if exists $config{proxy};

   if ($config{login}) {
      if ($config{cookie}) {
         INFO "getting login info from cookie file '$config{cookie}'";
         require HTTP::Cookies::Netscape;
         my $jar = HTTP::Cookies::Netscape->new(autosave => 0);
         $jar->load($config{cookie})
            or die "could not load cookie file $config{cookie}\n";
         $ua->cookie_jar($jar);
      }
      else {
         INFO "logging into account $config{username}";
         login();
      }
   }

   $action->();

   if ($config{login} && !$config{cookie}) {
      INFO "logging out";
      logout();
   }
};
ERROR $EVAL_ERROR if $EVAL_ERROR;

INFO 'all operations completed';

sub get_configuration {
   my %config = @_;

   my $action = shift @ARGV;
   $action = '--usage' unless defined $action;

   # First of all, try to honor meta-options
   pod2usage(message => "$0 $VERSION", -verbose => 99, -sections => ''
+)
     if $action eq '--version';
   pod2usage(-verbose => 99, -sections => 'USAGE') if $action eq '--us
+age';
   pod2usage(-verbose => 99, -sections => 'USAGE|EXAMPLES|OPTIONS')
     if $action eq '--help';
   pod2usage(-verbose => 2) if $action eq '--man';

   # getting here means that it's a real call for something
   my @common_options = qw(
     username|user|u=s password|pass|p=s proxy|P=s cookie|cookie-file|
+k=s
     config|C=s check|dry-run|c! dump|d! summary|summary-file|s=s
     tag|t=s@ debug|D=s
   );
   my %options_for = (
      add => [
         qw( files|files-from|f=s@ resize=i
           public! private! family! friends!
           backoff=i pause=i max_retry|max-retry|m=i
           )
      ],
      search => [qw( login! maxpage|max-page|m=i who|w=s )],
   );
   pod2usage(
      message   => "error: operation '$action' not supported\n",
      -verbose  => 99,
      -sections => 'USAGE'
     )
     unless exists $options_for{$action};

   # This will record the original parameters from different sources
   my %sources = (_script => {%config});

   my %cmdline;
   GetOptions(\%cmdline, @common_options, @{$options_for{$action}});
   %config = (%config, %cmdline);    # First merge, cmdline overrides
   $sources{_cmdline} = \%cmdline;

   # Read defaults from configuration file, if exists
   if (-e $config{config}) {
      my $cfile = Config::Tiny->read($config{config});
      %config = (%config, %{$cfile->{_}}, %cmdline);
      $sources{_cfile} = $cfile;

   } ## end if (-e $config{config})

   # Record original options for validators to make changes and action
   %config = (%config, %sources, action => $action, argv => [@ARGV]);
   @ARGV = ();    # empty, already recorded in config

   # Call relevant method for parameter checking, if exists
   if (my $sub = __PACKAGE__->can('validate_' . $action)) {
      $sub->(\%config);
   }

   if ($config{dump}) {
      require Data::Dumper;
      local $Data::Dumper::Indent;
      local $Data::Dumper::Indent = 1;
      print {*STDOUT} Data::Dumper->Dump([\%config], ['configuration']
+);
   } ## end if ($config{dump})

   # Now check/adjust common parameters
   push @{$config{tag}}, $config{tags} if defined $config{tags};
   $config{tags} = join ' ', @{$config{tag} || []};

   # Check username existence and prompt for password if necessary
   # If cookie file has been set, don't ask for a username, will check
   # later if it's all ok
   if ($config{login}) {
      if ($config{cookie}) {
         pod2usage(
            message => "error: please provide an existent cookie file\
+n",
            -verbose => 99,
            -sections => 'USAGE',
         ) unless -r $config{cookie} && -f $config{cookie};
      }
      else {
      pod2usage(
         message  => "error: please provide a username or a cookie fil
+e\n",
         -verbose => 99,
         -sections => 'USAGE'
        )
        unless exists $config{username};
      $config{password} = prompt 'password: ', -echo => '*'
        unless exists $config{password};
      }
   } ## end if ($config{login} && ...

   return %config;
} ## end sub get_configuration

sub login {
   $ua->get($config{login_page});
   $ua->form_with_fields(qw( username password ));
   $ua->set_fields(
      username => $config{username},
      password => $config{password},
   );
   $ua->submit();
   return;
} ## end sub login

sub logout {
   $ua->get($config{logout_page});
   return;
}

sub validate_add {
   my $config = shift;
   my %config = %$config;

   # Establish real privacy, command line overrides configuration
   @config{qw( private family friends )} = ()
     if $config{_cmdline}{public};
   $config{private} ||= $config{family} || $config{friends};
   $config{public} = $config{private} ? 0 : 1;
   delete $config{private};

   # Ensure there's some files to work on
   my @cmdline_files = @{$config{argv}};
   my @filed_files = map {
      chomp(my @lines = slurp($_));
      @lines;
   } @{$config{files} || []};
   my @filenames = uniq grep {
      if (-e $_) { 1 }
      else {
         print {*STDERR} "file '$_' does not exist, ignoring\n";
         0;
      }
   } @cmdline_files, @filed_files;
   pod2usage(
      message   => "error: no file to upload\n",
      -verbose  => 99,
      -sections => 'USAGE'
     )
     unless @filenames;
   $config{filenames} = \@filenames;

   %$config = %config;
   return;
} ## end sub validate_add

sub add {
   INFO "starting file upload";
   my $retry   = 0;
   my $backoff = $config{backoff};
   my @results;
   my @failed;
 FILE:
   for my $filename (@{$config{filenames}}) {
      (my $barename = file($filename)->basename()) =~ s{\.\w+\z}{}mxs;
      eval {
         $ua->get($config{upload_page})
           or die "couldn't get '$config{upload_page}'\n";

         $ua->form_with_fields(qw( Filedata labels ));
         $ua->set_fields(
            labels    => $config{tags},
            is_public => $config{public},
            Filedata  => $filename,
         );
         $ua->tick('is_friend', 1, $config{friends});
         $ua->tick('is_family', 1, $config{family});
         if ($config{resize} && (my $resized = add_resize($filename)))
+ {
            my $input = $ua->current_form()->find_input('Filedata');
            $input->filename($filename);    # just to be on the safe s
+ide
            $input->content($resized);
         }
         INFO "uploading '$filename'";
         $ua->submit();
      };

      my $error = 0;                        # assume no error just to 
+begin
      if ($EVAL_ERROR) {
         ERROR $EVAL_ERROR;
         $error = 1;
      }
      else {    # Now check that the photo is actually there...
         if (my $link = $ua->find_link(text => $barename)) {
            INFO 'upload successful';
            push @results, [ $filename, $link->url_abs() ];
         }
         else {
            ERROR 'no error received, but the photo is not there';
            $error = 1;
         }
      } ## end else [ if ($EVAL_ERROR)

      if ($error) {    # Retry scheme
         if (++$retry <= $config{max_retry}) {
            if ($backoff) {
               INFO "sleeping $backoff second"
                 . ($backoff == 1 ? '' : 's');
               sleep $backoff if $backoff;
               $backoff *= 2;    # exponential backoff
            } ## end if ($backoff)
            redo FILE;
         } ## end if (++$retry <= $config...

         ERROR "giving up on '$filename'";
         push @results, [ $filename, '**FAILED**' ];
         push @failed, $filename;
      } ## end if ($error)

      # Reset these values for next photo upload
      $retry   = 0;
      $backoff = $config{backoff};

      # Sleep a bit if configured. Avoid sleeping after last photo
      sleep $config{pause}
        if $config{pause}
        and $filename ne $config{filenames}[-1];
   } ## end for my $filename (@{$config...

   # Recap on failed files
   ERROR 'failed files: ', join ' | ', @failed if @failed;

   # Summary, if requested
   if (defined $config{summary}) {
      if (open my $fh, '>', $config{summary}) {
         print {$fh} "File\tURI\n";
         print {$fh} join("\t", @$_), "\n" for @results;
         close $fh;
      }
      else {
         ERROR "could not open $config{summary}: $OS_ERROR";
      }
   }

   return;
} ## end sub add

sub add_resize {
   my ($filename) = @_;

   require Image::Magick;
   require File::Temp;

   my $magick = Image::Magick->new();

   my ($width, $height, $size, $format) = $magick->Ping($filename);
   return if $width <= $config{resize} && $height <= $config{resize};

   my ($neww, $newh);
   if ($width > $height) {
      $neww = $config{resize};
      $newh = int($height * $neww / $width);
   }
   else {
      $newh = $config{resize};
      $neww = int($width * $newh / $height);
   }

   my $ecode;
   $ecode = $magick->Read($filename) and die $ecode;
   $ecode = $magick->Resize(width => $neww, height => $newh)
     and die $ecode;

   my $scaled;

   my $fh = File::Temp::tempfile();
   binmode $fh;
   $magick->Write(file => $fh, filename => $filename);
   seek $fh, 0, 0;    # rewind
   $scaled = slurp $fh;
   close $fh;

   return $scaled;
} ## end sub add_resize

sub validate_search {
   my $conf = shift;

   my %entry_for = (
      all      => 1,
      social   => 3,
      contacts => 3,
      everyone => 1,
   );
   $conf->{who} = $entry_for{$conf->{who} || ''};
   $conf->{who} ||= 2;    # default to 'me'

   $conf->{who} = 1 unless $conf->{login};

   return;
} ## end sub validate_search

sub search {
   INFO "starting search";
   $ua->get($config{search_page});
   $ua->form_with_fields(qw( w q ));
   $ua->select('w', {n => $config{who}});
   $ua->field('q', $config{tags});
   $ua->click();

   my ($matches, $word) =
     $ua->content() =~ /we found ([\d,]+) (photos?)/msi;
   if (!defined $matches) {
      INFO "no photo matching the criteria";
      return;
   }

   my $npages = 1;
   if (my @pages = $ua->find_all_links(url_regex => qr/\&page=(\d+)\z/
+mxs))
   {
      ($npages) = $pages[-2]->url() =~ /(\d+)\z/msx;
   }

   my $npages_w = $npages == 1 ? 'page' : 'pages';
   INFO "found $matches $word in $npages $npages_w";

   my $base_url = $ua->uri();
   $npages = $config{maxpage}
     if defined $config{maxpage} && $npages > $config{maxpage};
   for my $page_id (1 .. $npages) {
      $ua->get($base_url . "&page=$page_id");
      my @photos = $ua->find_all_links(url_regex => qr{/photos/.*/\d+/
+},);
      print join("\n* ", "Page $page_id:", map { $_->url() } @photos),
        "\n";
   } ## end for my $page_id (1 .. $npages)

   return;
} ## end sub search

__END__

=head1 NAME

zooomr - a simple command-line interface for Zooomr


=head1 VERSION


   shell$ zooomr --version


=head1 USAGE

   zooomr [--usage] [--help] [--man] [--version]

   zooomr <command> [<command-specific options>]
          [--check|-c] [--config|-C <filename>] 
          [--cookie|--cookie-file|-k <filename>] [--debug|-D]
          [--dump|-d] [--login] [--password|-p password]
          [--proxy | -P <proxy>] [--summary|--summary-file|-s <filenam
+e>]
          [--tag|-t tag1 [--tag|-t tag2 [...]]] [--username|-u <userna
+me>]

   command: add
          [--backoff <time>] [--family]
          [--files|--files-from|-f <filename>]
          [--friends] [--max-retry|-m <retries>] [--pause <time>]
          [--private] [--public] [--resize <max-size>]
  
=head1 EXAMPLES

   shell$ zooomr add -u pippo@example.com -p pluto foto*.jpg

   # Let the program ask you for the password, so that you don't have
   # to show it on the screen
   shell$ zooomr add -u pippo@example.com photo*.jpg

   # Add a tag to the new upload
   shell$ zooomr add -u pippo@example.com --tag awesome photo*.jpg

   # Add two tags
   shell$ zooomr add -u pippo@example.com -t awesome -t good photo*.jp
+g
  
=head1 DESCRIPTION

This script lets you interact with your Zooomr account (see
L<http://www.zooomr.com/>). You have to provide your account details,
tell it what you want to do and voil&#65533;, you're done. At the mome
+nt, the
following commands are recognised:

=over

=item *

B<add> one or more photo.

=back


=head2 Configuration File

You can put any configuration described in the L<OPTIONS> into a
configuration file. By default, the C<~/.zooomer> file is looked for
and loaded if exists.

The file format is quite easy: just put the configuration name, an
equal sign and the value you want to set. For boolean settings like
C<family> or C<public> use C<0> for false and C<1> for true.

Example:

   username = pippo@example.com
   password = pluto
   private  = 1

You can put comments and all the stuff, see L<Config::Tiny> for detail
+s.

Configurations on the command line override those found in the
configuration file. A notable exception to this rule is represented
by the tags, that are always added; this means that the tags in the
configuration file will be B<always> applied.


=head2 Logging in Zooomr

For operations that require authentication with Zooomr, like adding ne
+w
photos in your photostream, you can use two different methods:

=over

=item B<explicit>

in this case, you have to provide your B<username>/B<password> details
+,
either setting them in the configuration file, or passing them on the
command line, or passing the B<username> and waiting until prompted fo
+r
the B<password>. This method will not work for OpenID registered users
+.


=item B<cookie>

in this case, you rely on a previous authentication performed in the
browser (currently only Netscape and its descendants Mozilla/Firefox
are supported), and use cookies set by the browser. The mechanism is
simple: open the browser and log into Zooomr. Then find the cookies
file, and pass the path to this file with the C<--cookie> option (see
below).

For example, in my Linux system I have a C<.mozilla> subdirectory in
my home directory; to locate my cookies file, I would do the following
+:

   shell$ find "$HOME/.mozilla" -name 'cookies.txt'

B<NOTE: OpenID users MUST use this method>. Users with normal
B<username>/B<password> pair can choose to use this method or the
B<explicit> one explained above.

=back


=head1 OPTIONS

Available options depend on the required action. In particular, you
have:

=over

=item B<* meta-options>

options that deal with the B<zooomr> script itself;

=item B<* common options>

options that are common to all actions, e.g. the account details

=item B<* per-action options>

options that are specific to a given required action.

=back

=head2 Meta-Options

These options don't really fire the script, but deal with the script
itself.

=over

=item --help

print a somewhat more verbose help, showing usage, this description of
the options and some examples from the synopsis.

=item --man

print out the full documentation for the script.

=item --usage

print a concise usage line and exit.

=item --version

print the version of the script.

=back


=head2 Common Options

These options are common to all commands.

=over

=item --check | -c

check options, print them and exit.

=item --config | -C <filename>

set name of configuration file to use, defaults to C<~/.zooomer>.

=item --cookie | --cookie-file | -k <filename>

set the file name for the cookie file to use. You can use this to
login in Zooomr with your browser (currently only 
Netscape/Mozilla/Firefox are supported) and then use the browser's
cookies to access Zooomr with this script. In this case, it's not
necessary to provide a B<username>/B<password> pair, but you have
to ensure that you're logged in Zooomr with the browser.

OpenID users MUST use this method.

=item --debug | -D

set the debug level. Use one of the following:

=over

=item -

DEBUG

=item - 

INFO

=item -

WARN

=item -

ERROR

=item -

FATAL

=back

=item --dump | -d

dump the entire configuration. Note that this will show your password
in clear in the screen, so use judiciously.

=item --login

this is a flag parameter to indicate that a login should be performed.
It is set by default, so you don't have to bother with it; in case you
want to I<disable> it, you can pass C<--no-login>.

=item --password | --pass | -p <password>

provide a password on the command line. If you don't set a password,
you will be asked one and you'll be able to type it without the risk
to display it explicitly (asterisks are written instead of the actual
keys pressed).

=item --proxy | -P <proxy>

set the HTTP proxy in use. Note that you can also set the environment
variable C<http_proxy>.

=item --summary | --summary-file | -s <filename>

save a summary of the upload into the given filename. The file will
contain a line for each file, containing the photo file name, a
C<TAB> and the URI where the photo is available in Zooomr.

Note that this file is written only at the end of the upload session.
If you break the upload script you won't get any file. This may change
in the future.

=item --tag | -t <tag>

add a tag to the tag list (aka I<labels>). You can set multiple tags
by using this parameter multiple times.

=item --username | --user | -u <username>

provide your account details. As of November 2007, this is an email
address. This parameter is mandatory.

=back


=head2 Action: I<add>

Action B<add> supports the options in the following list. Moreover, yo
+u
have to provide a list of filenames of photos that you want to upload.

=over

=item --backoff <time>

pause between two consecutive attempts to upload the same file. This v
+alue
is doubled every new attempt, and reset for each new file.

=item --family

set photos as private and accessible by family.

=item --files | --files-from | -f <filename>

get filenames of photos to upload from specified argument, e.g.:

   shell$ ls | grep 'jpg$' > lista-jpg.text
   shell$ zooomr add -u pippo@example.com -f lista-jpg-text
   

=item --friends

set photos as private and accessible by friends.

=item --max-retry | -m <retries>

set the maximum number of re-tries for an upload. Setting it to 0 mean
+s
that only one single attempt (i.e. the first) is tried.

=item --pause <time>

pause between the upload of two consecutive files, in second. Defaults
to 5 seconds.

=item --private

set photos as private.

=item --public

set photos as public.

=item --resize <max-size>

set a maximum dimension to which the uploaded photo must comply. If ei
+ther
width or height are greater than the provided value, the photo will be
resized in order for both to comply. The resize is done preserving the
aspect ratio.

You will need L<Image::Magick> to do this.

=back

A C<public> permission on the command line overrides any other
privacy configuration, either on the configuration file or on the
command line itself. On the other hand, stricter privacy configuration
+s
in the file override a public configuration in the file itself. While
it may seem counter-intuitive, you should probably avoid trying to
give such contradictive commands, and just make peace with your
brain.

The retry scheme tries to cope with some issues in the B<Zooomr> websi
+te.
Up to 1 photo out of 6 isn't actually received by the system, whatever
the result of the upload; for this reason, we try to see if the newly
uploaded photo is in the response page, which I<should> mean that
the upload was successful. The retry mechanism is ruled by options
C<backoff> and C<max-retry>.

Last, but not least, a pause can be inserted between two consecutive
files, in order to limit server CPU usage.


=head1 DIAGNOSTICS

To date, every error terminates the script. The error message should b
+e
explicit enough that you don't need more explainations (most of them
are provided by L<WWW::Mechanize>, so don't blame me).


=head1 CONFIGURATION AND ENVIRONMENT

zooomr relies on no environment variables.

By default, a configuration file is searched in C<~/.zoomer>. See
L<Configuration file> in L<DESCRIPTION> for details, and see
L<OPTIONS> for allowed parameters.


=head1 DEPENDENCIES

All stuff you can find on CPAN:

=over

=item L<version>

=item L<WWW::Mechanize> (the real star)

=item L<IO::Prompt>

=item L<Log::Log4perl>

=item L<Config::Tiny>

=item L<Path::Class>

=item L<List::MoreUtils>

=item L<Image::Magick>

but only if you want to use the C<resize> options in C<add>.

=back


=head1 BUGS AND LIMITATIONS

No bugs have been reported.

Please report any bugs or feature requests through http://rt.cpan.org/

The only supported action so far is B<add>, which is pretty little. To
be true, a B<search> action is currently implemented but still not
documented, mainly due to some residual decisions about the output
of the action.

The summary file (option C<--summary>) is written only after the uploa
+d
process completion for all files, so will be missing if anything
interrupts the upload itself.

=head1 AUTHOR

Flavio Poletti C<flavio@polettix.it>


=head1 LICENCE AND COPYRIGHT

Copyright (c) 2006, Flavio Poletti C<flavio@polettix.it>. All rights r
+eserved.

This script is free software; you can redistribute it and/or
modify it under the same terms as Perl itself. See L<perlartistic>
and L<perlgpl>.

Questo script &#65533; software libero: potete ridistribuirlo e/o
modificarlo negli stessi termini di Perl stesso. Vedete anche
L<perlartistic> e L<perlgpl>.


=head1 DISCLAIMER OF WARRANTY

BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WH
+EN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. TH
+E
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
NECESSARY SERVICING, REPAIR, OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

=head1 NEGAZIONE DELLA GARANZIA

Poiché questo software viene dato con una licenza gratuita, non
c'è alcuna garanzia associata ad esso, ai fini e per quanto permesso
dalle leggi applicabili. A meno di quanto possa essere specificato
altrove, il proprietario e detentore del copyright fornisce questo
software "così com'è" senza garanzia di alcun tipo, sia essa espressa
o implicita, includendo fra l'altro (senza però limitarsi a questo)
eventuali garanzie implicite di commerciabilità e adeguatezza per
uno scopo particolare. L'intero rischio riguardo alla qualità ed
alle prestazioni di questo software rimane a voi. Se il software
dovesse dimostrarsi difettoso, vi assumete tutte le responsabilità
ed i costi per tutti i necessari servizi, riparazioni o correzioni.

In nessun caso, a meno che ciò non sia richiesto dalle leggi vigenti
o sia regolato da un accordo scritto, alcuno dei detentori del diritto
di copyright, o qualunque altra parte che possa modificare, o redistri
+buire
questo software così come consentito dalla licenza di cui sopra, potrò
essere considerato responsabile nei vostri confronti per danni, ivi
inclusi danni generali, speciali, incidentali o conseguenziali, deriva
+nti
dall'utilizzo o dall'incapacità di utilizzo di questo software. Ciò
include, a puro titolo di esempio e senza limitarsi ad essi, la perdit
+a
di dati, l'alterazione involontaria o indesiderata di dati, le perdite
sostenute da voi o da terze parti o un fallimento del software ad
operare con un qualsivoglia altro software. Tale negazione di garanzia
rimane in essere anche se i dententori del copyright, o qualsiasi altr
+a
parte, sono stati avvisati della possibilità di tali danneggiamenti.

Se decidete di utilizzare questo software, lo fate a vostro rischio
e pericolo. Se pensate che i termini di questa negazione di garanzia
non si confacciano alle vostre esigenze, o al vostro modo di
considerare un software, o ancora al modo in cui avete sempre trattato
software di terze parti, non usatelo. Se lo usate, accettate espressam
+ente
questa negazione di garanzia e la piena responsabilità per qualsiasi
tipo di danno, di qualsiasi natura, possa derivarne.

=cut
Replies are listed 'Best First'.
Re: Zooomr uploader
by Anonymous Monk on Nov 28, 2007 at 19:45 UTC
    I'm using:
    zooomr add --cookie /LVM/.firefox/cookies.txt teste.jpg
    and I get the error:
    2007/11/28 17:40:04 configuration OK
    2007/11/28 17:40:04 getting login info from cookie file '/LVM/.firefox/cookies.txt'
    2007/11/28 17:40:04 starting file upload
    2007/11/28 17:40:05 uploading 'teste.jpg'
    2007/11/28 17:41:09 Error POSTing http://upload.zooomr.com/photos/upload/process/: Internal Server Error at /scripts/zooomr line 266
    I use myoopenid, and I have logged in using firefox. Is there something I'm missing?
      I saw that error only when I was not already logged in with the browser, which should not be the case according to your description. The only thing that comes to mind is that your path to the cookies file is a bit strange; in my system, *my* cookie file is under "$HOME/.mozilla/firefox/<strangely-named-directory>/cookies.txt". In your case, I see that you're using Logical Volume Management (which I don't know), so I would suggest to double-check that the path you're using is that of the cookie file actually produced by firefox for your account. Try to
      shell$ grep zooomr /LVM/.firefox/cookies.txt
      and see if there are lines coming out. Then try to logout from Zooomr, and see if the cookies changed, try to delete them from inside firefox and re-login, etc.

      Last, but not least, which versions of Perl and libwww are you using?

      Flavio
      perl -ple'$_=reverse' <<<ti.xittelop@oivalf

      Io ho capito... ma tu che hai detto?
        I can't believe how stupid I was!
        I was using the cookies.txt file from the wrong profile, now it's working perfectly.
        By the way, thank you very much for this great script, it's exactly what I've been looking for, waaaaay better than juploadr for my needs, and now I can finally upload my photos to zooomr!!
Re: Zooomr uploader
by Anonymous Monk on Nov 26, 2007 at 14:21 UTC
    Hi, I got the following err msg: Error POSTing http://upload.zooomr.com/photos/upload/process/: Internal Server Error at ./zooomr line 242 and here is my command ./zooomr add -u http://drakeguan.myopenid.com/ /tmp/ooxx.png any ideas? Yours, Drake
      The script does not support OpenID at the moment. I was warned about this and I'm trying to add support; it should not be difficult, given that I've an example to look at. Stay tuned!

      Update: I added cookie handling in the spirit of Zooomr Mac Suite. You OpenID users can do the following:

      • login with the browser (currently only Netscape/Mozilla/Firefox are supported, your mileage may vary with other browsers);
      • locate the cookies file (should be called cookies.txt, and located somewhere under your home directory);
      • pass the path to the file using the --cookie option.
      In this case, you do not have to provide a username. An example:
      shell$ zooomr add --tag example --cookie /path/to/cookies.txt photo.jp +g

      Flavio
      perl -ple'$_=reverse' <<<ti.xittelop@oivalf

      Io ho capito... ma tu che hai detto?
        wow, that works!!! thx a lot
Re: Zooomr uploader
by Shaef (Initiate) on Jan 26, 2008 at 08:37 UTC
    Hi, I'm not a programmer, but I just want to have a zoomr uploader. Can anyone just give me the .exe file instead of the .pl file? I tried to compile it myself with the activeperl, but failed to collect all the lib. Thanks
      Sorry, but this is not possible for me (I don't use Windows (if I can (that is for this kind of projects))). If you use ActivePerl, you should install modules using PPM, it should be straightforward. Otherwise, you could ask someone willing to produce a PAR package for Windows to do it for you. The only "package" I know of is a Mac one, maintained by prophead on Zooomr (see Zooomr Mac Suite); it also has a GUI, for what he told me.

      Hey! Up to Dec 16, 2007 I was named frodo72, take note of the change! Flavio
      perl -ple'$_=reverse' <<<ti.xittelop@oivalf

      Io ho capito... ma tu che hai detto?
Re: Zooomr uploader
by Anonymous Monk on Oct 22, 2008 at 10:27 UTC
    Hi guys, Recently I notice that Zooomr_uploader stop working, i have some strange errors when I want to upload files. Here is what I have:
    # zooomr_upload.pl add -u yan -p **** pic001.jpg 2008/10/22 12:08:15 configuration OK 2008/10/22 12:08:15 logging into account yan 2008/10/22 12:08:21 starting file upload There is no form with the requested fields at /usr/local/bin/zooomr_up +load.pl line 254 2008/10/22 12:08:23 No such field 'Filedata' at /usr/lib/perl5/vendor_ +perl/5.8.8/WWW/Mechanize.pm line 1351 2008/10/22 12:08:23 sleeping 5 seconds
    The script works fine until today. Have this have some connections with changes on http://www.zooomr.com/photos/upload/ page. I suppose they do some big thing there.... I'm just a ordinary user, not programer, and i hope that this will be fixed soon. Thank you so much for this great script! Cheers Yan
      Do you still see the problem? I just went to the upload page and it seems to be all right.

      perl -ple'$_=reverse' <<<ti.xittelop@oivalf

      Io ho capito... ma tu che hai detto?
        Thank you for your response Flavio! Yes, I just checked again, and problem still persist. I fairly sure I have no any system update for a while on that system (Gentoo P2P/Multimedia headless server..)... does anyone else have this or similar problem with 'Filedata field'? Yan
Re: Zooomr uploader
by Anonymous Monk on Nov 30, 2007 at 15:41 UTC
    Can anyone give any tutorial for such a nice script? Thanks in advance!
      Have you tried to give a look at the documentation? You can peek at it with:
      shell$ zooomr --man
      It contains some examples and a full explaination of the various features. Not a tutorial, but close to it!

      Flavio
      perl -ple'$_=reverse' <<<ti.xittelop@oivalf

      Io ho capito... ma tu che hai detto?
Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: sourcecode [id://650429]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (4)
As of 2019-12-08 23:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?