#!/usr/bin/perl -w -T use strict; $|=1; my %src = ( 2 => { #killsurl => 'http://jihadswarm.com/?a=kills', killsurl => 'http://jihadswarm.com/', kmailurl => 'http://jihadswarm.com/?a=kill_mail&kll_id=KID', }, ); use DBI; my $dbh=DBI->connect("DBI:mysql:database=eve","eve"); my ($opt_s, $opt_k, $opt_f, $opt_t,); use Getopt::Long qw(:config no_ignore_case bundling); GetOptions( 's=i' => \$opt_s, 'k=i' => \$opt_k, 'f=i' => \$opt_f, 't=i' => \$opt_t, ) or die "bad optionz"; die "k without s" if $opt_k && !$opt_s; die "s without k" if $opt_s && !$opt_k; if ($opt_s && $opt_k) { &process_kill($opt_s, $opt_k); exit; } for (sort keys %src) { eval { &process_source($_); }; if ($@) { printf "source(%i) failed: %s\n", $_, $@; } } exit 0; ### sub process_source ($) { my $src = shift; my $url = $src{$src}{killsurl}; die "no url" unless $url; # TODO: get goes here #my $page = &slurp("index.html?a=kills"); my $page = &get_http($url); die "get($url) failed" unless $page; # find highest kill number my $scan = $page; my $mkill = 0; while ($scan =~ s/a=kill_detail&kll_id=(\d+)(\D|$)//s) { $mkill = $1 if $1 > $mkill; } $mkill = $opt_t if $opt_t; # TODO: get max known kill from db; my $dkill = $opt_f || &get_maxkill($src); if ($mkill == $dkill) { printf "SRC(%i): %i:%i nothing to do\n", $src, $mkill, $dkill; return; } die "time going backwards: $mkill < $dkill" if $mkill < $dkill; printf "SRC(%i): kills %i -> %i\n", $src, $dkill, $mkill; for (($dkill+1) .. $mkill) { # for (0..10) { eval { &process_kill($src, $_); }; if ($@) { printf "kill(%i, %i) failed: %s\n", $src, $_, $@; } } } my $useragent; sub get_http ($) { my $url = shift; require LWP::UserAgent; my $ua = $useragent ||= LWP::UserAgent->new( agent => "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11", timeout => 10, ); printf "URL(%s): ", $url; my $res = $ua->get($url); printf "%s\n", $url, $res->status_line; if ($res->is_success) { return $res->content; } else { die "get($url) failed: ".$res->status_line; } } my $sth_maxkill; sub get_maxkill ($) { my $src = shift; my $sth = $sth_maxkill ||= $dbh->prepare(qq{ SELECT max(killID) FROM `jihadKills` WHERE srcID = ? }) or die $dbh->errstr; $sth->execute($src) or die $sth->errstr; my $r = $sth->fetchrow_arrayref; return 0 unless $r && ref $r eq 'ARRAY'; my ($m,) = @$r; return $m; } sub process_kill ($$) { my ($src, $kid,) = @_; my $murl = $src{$src}{kmailurl}; die "no murl" unless $murl; die "no KID in murl" unless $murl =~ /KID/; my $url = $murl; $url =~ s/KID/$kid/; # printf "KILL(%i,%i): url %s\n", $src, $kid, $url; # TODO: get goes here # my $page = &slurp("index.html?a=kill_mail&kll_id=158"); my $page = &get_http($url); my $mail = $page; $mail =~ s/\r\n/\n/sg; die "noheader: $mail" unless $mail =~ s/^.*]+>\s*//s; die "notail: $mail" unless $mail =~ s/<.*$//s; return if !$mail && $page =~ /Fatal error/; die "no mail: $page" unless $mail; &store_killmail($src, $kid, $mail); my $state = 0; my @lines = split "\n", $mail; push @lines, ""; # force end-of-block flush at end-of-mail my %block = (); for (@lines) { if (!$state && !$_) { next; } elsif ($state == 0 && /^(\d\d\d\d)\D(\d\d)\D(\d\d)\D(\d\d)\D(\d\d)$/) { $block{ktime} = sprintf "%i-%02i-%02i %02i:%02i", $1, $2, $3, $4, $5; } elsif ($state == 0 && /^(Victim): (.*)$/) { $block{lc($1)} = $2; $state = 1; } elsif (($state == 1 || $state == 3) && /^([\w ]+): (.*)$/) { $block{lc($1)} = $2; } elsif ($state == 1 && !$_) { next unless %block; &store_kill($src, $kid, %block); %block = (); $state = 2; } elsif ($state == 2 && (!$_ || /^Involved parties:$/)) { next; } elsif (($state == 2) && /^(Name): (['\w ]+) \/ ([\w ]+)( \(.+\))?$/) { $block{lc($1)} = $2; $block{corp} = $3; $state = 3; } elsif (($state == 2) && /^(Name): (['\w ]+)( \(.+\))?$/) { #printf "killer: '%s' '%s' '%s'\n", $1, $2, $3; $block{lc($1)} = $2; $state = 3; } elsif ($state == 3 && !$_) { next unless %block; &store_killer($src, $kid, %block); %block = (); $state = 2; } elsif ($state == 2 && /^(Destroyed|Dropped) items:$/) { $state = 4; last; } else { printf "%s\n",$mail; die "bad line in state $state: '$_'"; } } die "have block but no lines" if %block; } my $sth_killmailadd; sub store_killmail ($$$) { my ($src, $kid, $mail,) = @_; my $sth = $sth_killmailadd ||= $dbh->prepare(qq{ INSERT INTO `jihadKillmails` SET srcID = ?, killID = ?, mail = ? ON DUPLICATE KEY UPDATE mail = ? }) or die $dbh->errstr; $sth->execute($src, $kid, $mail, $mail) or die $sth->errstr; } my $sth_killadd; sub store_kill { my $src = shift; my $kid = shift; my %d = @_; $d{alliance} = undef if $d{alliance} eq "None"; my $sth = $sth_killadd ||= $dbh->prepare(qq{ INSERT IGNORE INTO `jihadKills` SET srcID = ?, killID = ?, name = ?, corp = ?, alliance = ?, ship = ?, system = ?, damage = ?, ktime = ? }) or die $dbh->errstr; $sth->execute($src, $kid, $d{victim}, $d{corp}, $d{alliance}, $d{destroyed}, $d{system}, $d{"damage taken"}, $d{ktime}) or die $sth->errstr; } my $sth_killeradd; sub store_killer { my $src = shift; my $kid = shift; my %d = @_; $d{alliance} = undef if $d{alliance} && $d{alliance} eq "None"; my $sth = $sth_killeradd ||= $dbh->prepare(qq{ INSERT IGNORE INTO `jihadKillers` SET srcID = ?, killID = ?, name = ?, security = ?, corp = ?, alliance = ?, ship = ?, weapon = ?, damage = ? }) or die $dbh->errstr; $sth->execute($src, $kid, $d{name}, $d{security}, $d{corp}, $d{alliance}, $d{ship}, $d{weapon}, $d{"damage done"}) or die $sth->errstr; } sub slurp ($) { my $fn = shift; die "no such file: $fn" unless -e $fn; open my $fh, $fn or die "cant open($fn): $!"; local $/; # enable localized slurp mode my $content = <$fh>; close $fh; return $content; }