Plagger::Plugin::Publish::FTP

こんな感じかな?

ほかのPublish系がfeedをあれこれし終わったところで、local_dir配下のファイルをまるごとremote_dirにアップロード。

package Plagger::Plugin::Publish::FTP;

use strict;
use base qw( Plagger::Plugin );

use Net::FTP;
use File::Spec;
use File::Basename;
use File::Find::Rule ();

sub register {
    my ($self, $context) = @_;
    $context->register_hook(
        $self,
        'publish.finalize' => \&do_transfer,
    );
}

sub do_transfer {
    my ($self, $context, $args) = @_;

    $context->log(debug => "hello, FTP server");

    my $ftp = Net::FTP->new(
        $self->conf->{host},
        ( $self->conf->{options} || () )
    ) or do {
        $context->log(error => "failed to connect to the server: $@");
        return;
    };

    $ftp->login($self->conf->{login}, $self->conf->{password}) or do {
        $context->log(error => "failed to login: $@");
        $ftp->quit;
        return;
    };

    $context->log(debug => "login succeeded");

    $ftp->cwd($self->conf->{remote_dir}) or do {
        $context->log(warn => 'failed to change directory'.$ftp->message);
        my $dir = $ftp->mkdir( $self->conf->{remote_dir}, 'recurse' );

        if ($self->conf->{remote_dir} ne $dir) {
            $context->log(warn => 'failed to create directory'.$ftp->message);
            $ftp->quit;
            return;
        }
    };

    $context->log(debug => "changed remote directory");

    $ftp->binary;

    my @files = File::Find::Rule->file()->in($self->conf->{local_dir});
    foreach my $file (@files) {
        $context->log(info => "upload $file to the server");

        my $relpath = File::Spec->abs2rel( $file, $self->conf->{local_dir} );
           $relpath =~ s{\\}{/}g;  # for Win32

        my $reldir  = dirname($relpath);

        if ($reldir) {
            $ftp->mkdir( $reldir, 'recurse' ) or do {
                $context->log(warn => "skip: $file ".$ftp->message);
                next;
            };
        }

        $ftp->put($file, $relpath) or do {
            $context->log(warn => "skip: $file ".$ftp->message);
            next;
        };

        unlink $file if $self->conf->{unlink};
    }

    $context->log(debug => "goodbye, server");
    $ftp->quit;
}

1;

__END__

=head1

Plagger::Plugin::Publish::FTP - transfer files via FTP

=head1 SYNOPSYS

  - module: Publish::FTP
    config:
      host: ftp.foo.bar
      options:
        Passive: 1
      login: foo
      password: blahblahblah
      local_dir: /home/foobar/plagger/upload_dir
      remote_dir: /home/foobar/www/plagger
      unlink: 1

=head1 CONFIG

=over 4

=item host, options

Will be passed to Net::FTP->new.

=item login, password

Will be passed to Net::FTP->login.

=item local_dir

Where you should save feeds.

=item remote_dir

Where feeds will be uploaded to.

=item unlink

If set to true, feeds will be deleted later.

=back

=head1 AUTHOR

Kenichi Ishigaki

=head1 SEE ALSO

C<Plagger>, C<Net::FTP>

=cut