commit 7deb630f2352fb316c67d518f8d2795b059e92b9 from: Izzy Blacklock date: Fri May 19 21:10:36 2023 UTC Moved database related functions to IRCNOW::Database.pm Added IRCNOW::Parselog.pm as a base class for log parsers. It has stub functions for common database functions to make the code easier to view/manage at the application level. commit - 16a10af07204a2e0d1d7d55a71ef811947791581 commit + 7deb630f2352fb316c67d518f8d2795b059e92b9 blob - fb2feef5677e06e63d91096b431d2aa986a7249f blob + 874bf924486cf2feebdfc2daa6a31bd0acbaba23 --- lib/IRCNOW/Database.pm +++ lib/IRCNOW/Database.pm @@ -8,45 +8,111 @@ use DBD::SQLite; sub new { my ($class, @arguments) = @_; my $self = { @arguments }; - - die "You must specify a database file" unless defined $self->{database}; + my $defaults = { + PrintError => 1, + RaiseError => 1, + AutoCommit => 1, + FetchHashKeyName => 'NAME_lc', + user => "", + password => "", + }; + # dsn assumed to be sqlite if dbpath is provideded without a dsn value + if (not defined $self->{dsn}) { + if (defined $self->{dbpath}) { + # make sure file exists and isn't empty. + die "Can't locate " .$self->{dbpath} unless (-s $self->{dbpath}); + $self->{dsn}="dbi:SQLite:dbname=" . $self->{dbpath}; + } else { + die "No dsn string specified"; + } + } + # Fill defaults values or die. + for my $field (qw{user password}) { + $self->{$field} = $defaults->{$field} unless defined $self->{$field}; + } + # Create $self->{dbi} if it doesn't exist. + $self->{dbi}={} unless exists $self->{dbi}; + # set dbi options with defaults + for my $field (qw{PrintError RaiseError AutoCommit FetchHashKeyName}) { + $self->{dbi}->{$field} = $self->{dbi}->{$field} || $defaults->{$field} + || die "Required paramater missing: {dbi}->{$field}"; + } bless $self, $class; return $self; } sub connectDB { my $self=shift; - my $dbpath=$self->{database}; - my $dsn = "dbi:SQLite:dbname=$dbpath"; - my $user = ""; - my $password = ""; - my $dbh = DBI->connect($dsn, $user, $password, { - PrintError => 1, - RaiseError => 1, - AutoCommit => 1, - FetchHashKeyName => 'NAME_lc', - }) or die "Couldn't connect to database: " . $DBI::errstr; - if (!(-s "$dbpath")) { - warn "Cant locate $dbpath"; - exit 1; - } - warn "connected to $dbpath"; - return $dbh; + $self->{dbh} = DBI->connect($self->{dsn}, $self->{user}, $self->{password}, $self->{dbi}) + or die "Couldn't connect to database: " . $DBI::errstr; + warn "connected to " . $self->{dsn}; + return $self->{dbh}; } sub disconnectDB { my $self=shift; - my $dbh = shift; + my $dbh = $self->{dbh}; $dbh->disconnect(); + delete $self->{dbh}; } +sub createTable { + my $self=shift; + my $table=shift; + my $dbh=$self->dbh(); + return $dbh->do($self->{TABLES}->{$table}->{dbCreate}); +} +sub dbh { + my $self=shift; + my $dbh=$self->{dbh} || $self->connectDB(); + return $dbh; +} -sub createTable { +sub fieldListStrs { my $self=shift; - my $create_stmt=shift; + my $fields=shift; + my $fieldListStr=join(",", @$fields); + my $valuesListStr = ""; + for (@$fields) { + $valuesListStr .= "?,"; + } + chop ($valuesListStr); + return $fieldListStr,$valuesListStr; } +sub dbInsertRecord { + my $self = shift; + my $table = shift; + my $data = shift; + my $fields = shift || $self->{TABLES}->{$table}->{reqFields}; + my ($fieldStr,$valStr) = $self->fieldListStrs($fields); + my @row = \@_; + my $dbh = $self->dbh(); + my $stmt = qq{ + INSERT INTO $table ($fieldStr) VALUES ($valStr) + }; + if (ref $data->[0] eq "ARRAY") { + # We have multiple records to insert + my $sth = $dbh->prepare($stmt); + for (@$data) { + $sth->execute(@$_) or die $dbh->errstr; + } + } else { + $dbh->do($stmt, undef, $data); + } +} + +sub dbLastRecord { + my $self = shift; + my $table = shift; + my $dbh = $self->dbh(); + my $row = $dbh->selectrow_arrayref(qq{ + SELECT * FROM $table ORDER BY id DESC LIMIT 1 + }); + return $row; +} + 1; blob - 03f7e2317608d3e7621e8fcd0e1f89d0e4a7b1e5 blob + cb7c009d69ff505170d81ccb6a9cbeb1f46ef62f --- lib/IRCNOW/ParseLog/Znc.pm +++ lib/IRCNOW/ParseLog/Znc.pm @@ -5,6 +5,7 @@ use warnings; use lib qw(./lib); use IRCNOW::Database; +use base qq{IRCNOW::ParseLog}; # Date string to epock used in init_ip_xref use Date::Parse; @@ -12,13 +13,9 @@ use Date::Parse; sub new { my $class = shift; - my $self = { @_ }; - - die "Must specify the database to load" unless defined $self->{database}; - die "Must specify the log file to load" unless defined $self->{zncLog}; - - $self->{table} = 'zncLog'; - $self->{dbCreate} = qq{ + # Let base class setup and bless our object + my $self = $class->SUPER::new( 'zncLog', @_ ); + $self->set_dbCreate(qq{ CREATE TABLE $self->{table} ( id INTEGER PRIMARY KEY, epoch integer, @@ -27,49 +24,23 @@ sub new { address VARCHAR(50), type VARCHAR(30) ); - }; - $self->{fields} = [qw{id epoch timestring user address type}]; - if (not defined $self->{$self->{database}}) { - $self->{$self->{database}} = IRCNOW::Database->new(database=>$self->{database}); - } - - bless $self, $class; + }); + $self->set_fields(qw{id epoch timestring user address type}); + $self->set_reqFields(qw{ epoch timestring user address type}); return $self; } -sub dbh { - my $self=shift; - my $dbh=$self->{dbh} || $self->{$self->{database}}->connectDB(); - if (not defined($dbh)) { - die "failed to connect to $self->{database}"; - } - $self->{dbh} = $dbh; - return $dbh; -} - -sub createTable { - my $self=shift; - my $dbh=$self->dbh(); - return $dbh->do($self->{dbCreate}); -} - - -sub dbLastRecord { - my $self = shift; - my $dbh = $self->dbh(); - my $row = $dbh->selectrow_arrayref(qq{ - SELECT * FROM $self->{table} ORDER BY ID DESC LIMIT 1 - }); - return $row; -} - sub parseLog { my $self = shift; my $lastEpoch = shift; my $lastName = shift; my $lastIP = shift; + + # Last record defined so assume skipping + my $skip = defined $lastEpoch ? 1 : 0; my @data; + open my $log, "<".$self->{zncLog} or die "Can't open " . $self->{zncLog}; while (my $line = <$log>) { if( $line =~/\[(.*)\].*\[(.*)\] connected to ZNC from (.*)/) { @@ -78,15 +49,20 @@ sub parseLog { my $ip = $3; my $type = 'Connected'; my $epoch = str2time($timeString); - next if ((defined $lastEpoch and $epoch < $lastEpoch) + #Skip anything older then lastepoch + print "$skip, $epoch, $name, $ip\n"; + if ( ($skip and $epoch == $lastEpoch) and ($name eq $lastName) - and ($ip eq $lastIP) - ); + and ($ip eq $lastIP) ) { + $skip = 0; # Found the last record, turn skipping off + next; + } + next if ($skip); # Add this line to the data push @data,[$epoch,$timeString,$name,$ip,$type]; } } - return @data; + return \@data; } blob - /dev/null blob + 85105274f5dc46aa55c53a8c487327412d52b718 (mode 644) --- /dev/null +++ lib/IRCNOW/ParseLog.pm @@ -0,0 +1,49 @@ +package IRCNOW::ParseLog; + +use strict; +use warnings; + +sub new { + my $class = shift; + my $table = shift; + my @arguments = @_; + my $self = { @arguments }; + $self->{TABLE} = $table; + die "Must specify the database to load" unless defined $self->{database}; + die "Must specify the log file to load" unless defined $self->{zncLog}; + + + bless $self, $class; + return $self; +} + +sub set_dbCreate { + my $self=shift; + my $create=shift; + my $table=$self->{TABLE}; + $self->{database}->{TABLES}->{$self->{TABLE}}->{dbCreate}=$create; +} + +sub set_fields { + my $self=shift; + $self->{database}->{TABLES}->{$self->{TABLE}}->{fields}=[@_]; +} + +sub set_reqFields { + my $self=shift; + $self->{database}->{TABLES}->{$self->{TABLE}}->{reqFields}=[@_]; +} + +sub dbLastRecord { + my $self=shift; + return $self->{database}->dbLastRecord($self->{TABLE}); +} + +sub dbInsertRecord { + my $self=shift; + my $data=shift; + return $self->{database}->dbInsertRecord($self->{TABLE}, $data); +} + + +1; blob - d874b9f33f431939b19e6a97d65a49aed30b890a blob + c67b474a69aed2c49bb101bb3d1e67162277e74d --- parseznc.pl +++ parseznc.pl @@ -5,18 +5,24 @@ use strict; use warnings; use lib qw(./lib); +use IRCNOW::Database; use IRCNOW::ParseLog::Znc; +my $botnowDB = IRCNOW::Database->new(dbpath=>'/var/www/botnow/botnow.db'); + my $znclog = IRCNOW::ParseLog::Znc->new( - database=>'/var/www/botnow/botnow.db', + database=>$botnowDB, zncLog=>'/home/znc/home/znc/.znc/moddata/adminlog/znc.log', ); use Data::Dumper; my $lastRecord=$znclog->dbLastRecord() || []; +my $data = $znclog->parseLog($lastRecord->[1],$lastRecord->[3],$lastRecord->[4]); +print Dumper($data); -print Dumper($znclog->parseLog($lastRecord->[1],$lastRecord->[3],$lastRecord->[4])); +$znclog->dbInsertRecord($data); +#print Dumper($znclog->parseLog($lastRecord->[1],$lastRecord->[3],$lastRecord->[4])); #$znclog->createTable();