scripts/pscrot

150 lines
4.1 KiB
Perl
Executable File

#!/usr/bin/env perl
## Perl script for screenshot management
package Maff::Utils::PScrot;
use strict;
use warnings;
# github:MaffC/maffpl.git provides the Maff:: namespace
use Maff::Common::IO qw/:all/;
use Maff::Common::OSX qw/:all/;
use Maff::Common::Net qw/scp_upload/;
use Date::Format qw/time2str/;
use POE;
use POE::Component::DirWatch;
use POSIX;
my $ME = "pscrot";
my $VERSION = "0.5.1";
my $HOSTNAME = `hostname`; chomp $HOSTNAME;
my $rcfile = $ENV{"HOME"}."/.pscrotrc";
our %Conf;
# Load config file at ~/.pscrotrc.
unless(my $ret = do $rcfile) {
logger(9, "Couldn't parse config file $rcfile!") if $@;
logger(9, "Couldn't load config file $rcfile!") unless defined $ret and $ret;
}
my $LOGFILE = "$Conf{home}/.$ME.log";
my $ERRFILE = "$Conf{home}/.$ME.err";
my $PIDFILE = "$Conf{home}/.$ME.pid";
my $retries = 0; # set to -1 to disable upload retrying
my $running = 0;
my $sighup = 0;
# Functions
sub mac_notify {
return unless $Conf{features}{notify};
macintalk_say text=>$_[($_[0] eq $ME)? 1 : 0] if $Conf{features}{speak};
nc_notify @_;
}
sub sigtrap {
my $sig = shift;
logger(2, "Caught SIG$sig: Exiting..");
$running = 0;
}
sub sighup {
logger(2, "Caught SIGHUP: Restarting..");
$running = 0;
$sighup = 1;
}
sub logger {
my $pri = shift;
my $msg = shift;
print time2str('%e %B %T', time)." $HOSTNAME $ME\[$$] ($pri): $msg\n";
print STDERR time2str('%e %B %T', time)." $HOSTNAME $ME\[$$] ($pri): $msg\n" if $pri =~ /^[29]$/;
mac_notify($ME,$msg) if $pri == 3;
exit 0 if $pri == 8;
exit 1 if $pri == 9;
return $pri;
}
sub push_file {
my $file = shift;
while(1) {
last if scp_upload(file=>$file,%{$Conf{server}}) or $retries++ =~ /^(-1|2)$/;
if($retries==1) {
logger(1, "Failed to upload $file (try $retries)");
logger(3, $Maff::Common::Net::error);
sleep 3; # wait a few seconds before retrying
} else {
logger(2, "max retry limit reached, bailing.");
mac_notify("Upload Failed", "Connect retry limit reached; check the log for details.");
}
}
$file = $file->basename; $file =~ s/ /%20/g;
my $uri = "http://$Conf{server}{domain}/$file";
clipb_copy $uri;
mac_notify("File Uploaded", "$uri copied to clipboard.");
}
sub normalise_filename {
my ($name,$dropped) = @_;
return time2str($Conf{filenametpl},time).$1 if $dropped and ($name =~ /(\.[a-z0-9]+)$/i or 1);
$name =~ $Conf{match}{screenshot} and return "$1 $2.png";
return $name;
}
sub check_file {
my $file = shift;
return 1 if $file->is_dir;
return 0 if $file->basename =~ /^\./;
return 1 if $file =~ /^\Q$Conf{hotdir}\E/;
foreach my $handled_type (keys %{$Conf{match}}) {
return 1 if $file =~ $Conf{match}{$handled_type};
}
return 0;
}
sub found_file {
my $file = shift;
my $dropped = ($file =~ /^\Q$Conf{hotdir}\E/) ? 1 : 0;
my $nf = normalise_filename($file->basename, $dropped);
$file->move_to($Conf{tmp}.$nf);
$retries=0 unless $retries==-1;
mac_notify("Uploading File", "Uploading $nf...");
push_file $file;
$file->remove() if $Conf{features}{del} and $dropped;
$file->move_to($Conf{storedir}.$nf) unless $dropped;
}
# Main
POE::Kernel->run();
open(STDOUT, ">>$LOGFILE");
open(STDERR, ">>$ERRFILE");
select((select(STDOUT), $|=1)[0]);
#TODO check $PIDFILE for previously started process, SIGHUP it to restart and then quit
logger(1,"Starting $ME..");
write_simple $PIDFILE, $$ or logger(9, "Failed to write PID to file $PIDFILE");
$running = 1;
$SIG{HUP} = \&sighup;
$SIG{INT} = \&sigtrap;
$SIG{QUIT} = \&sigtrap;
$SIG{TERM} = \&sigtrap;
POE::Session->create(
inline_states => {
_start => sub {
$_[HEAP]->{screengrabs} = POE::Component::DirWatch->new(
alias => 'screengrabs',
directory => $Conf{maindir},
filter => \&check_file,
file_callback => \&found_file,
interval => 1,
);
$_[HEAP]->{dropbox} = POE::Component::DirWatch->new(
alias => 'dropbox',
directory => $Conf{hotdir},
filter => \&check_file,
file_callback => \&found_file,
interval => 2, # decreased polling speed for the dropbox
) if $Conf{features}{hotdir};
}}
);
logger(1, "$ME version $VERSION started.");
POE::Kernel->run_while(\$running);
logger($sighup? 1 : 8,"Halting $ME..");
exec $^X, $0, @ARGV;