commit 16a10af07204a2e0d1d7d55a71ef811947791581 from: Izzy Blacklock date: Wed May 17 21:21:53 2023 UTC Start of a library set for accessing data on ircnow network servers Current version connects to an botnow database and the parses the znc log file. It can create a database table for the znc log and read the last line from the database table. The test application parseznc.pl does a simple dump of the parsed data file. It can skip the records from the dump based on a passed record. Working to abstract some of the code into a IRCNOW::ParseLog and IRCNOW::Database library to make future log parsing tasks easier. commit - /dev/null commit + 16a10af07204a2e0d1d7d55a71ef811947791581 blob - /dev/null blob + b72f9be2042aa06db9cb3a6f533f953b5ce29901 (mode 644) --- /dev/null +++ .gitignore @@ -0,0 +1,2 @@ +*~ +*.swp blob - /dev/null blob + fb2feef5677e06e63d91096b431d2aa986a7249f (mode 644) --- /dev/null +++ lib/IRCNOW/Database.pm @@ -0,0 +1,52 @@ +package IRCNOW::Database; + +# Database modules +use DBI; +use DBD::SQLite; + + +sub new { + my ($class, @arguments) = @_; + my $self = { @arguments }; + + die "You must specify a database file" unless defined $self->{database}; + + 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; +} + +sub disconnectDB { + my $self=shift; + my $dbh = shift; + $dbh->disconnect(); +} + + + +sub createTable { + my $self=shift; + my $create_stmt=shift; +} + + +1; blob - /dev/null blob + 03f7e2317608d3e7621e8fcd0e1f89d0e4a7b1e5 (mode 755) --- /dev/null +++ lib/IRCNOW/ParseLog/Znc.pm @@ -0,0 +1,138 @@ +package IRCNOW::ParseLog::Znc; + +use strict; +use warnings; + +use lib qw(./lib); +use IRCNOW::Database; + +# Date string to epock used in init_ip_xref +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{ + CREATE TABLE $self->{table} ( + id INTEGER PRIMARY KEY, + epoch integer, + timestring VARCHAR(50), + user VARCHAR(32), + 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; + 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; + my @data; + open my $log, "<".$self->{zncLog} or die "Can't open " . $self->{zncLog}; + while (my $line = <$log>) { + if( $line =~/\[(.*)\].*\[(.*)\] connected to ZNC from (.*)/) { + my $timeString = $1; + my $name = $2; + my $ip = $3; + my $type = 'Connected'; + my $epoch = str2time($timeString); + next if ((defined $lastEpoch and $epoch < $lastEpoch) + and ($name eq $lastName) + and ($ip eq $lastIP) + ); + # Add this line to the data + push @data,[$epoch,$timeString,$name,$ip,$type]; + } + } + return @data; +} + + +#my ($ipTable, $nameTable) = init_ip_xref(); +# Read and index the znc log file. +sub init_ip_xref { + # Get IP addresses + my $ip2usernames={}; + my $usernames2ip={}; + open my $zncLog, '<', '/home/znc/home/znc/.znc/moddata/adminlog/znc.log' or die "Can't open znc log file"; + while (my $line = <$zncLog>) { + if( $line =~/\[(.*)\].*\[(.*)\] connected to ZNC from (.*)/) { + my $timestamp=$1; + my $name=$2; + my $ip=$3; + if (!defined($ip2usernames->{$ip})) { + $ip2usernames->{$ip} = {}; + } + if (!defined($ip2usernames->{$name})) { + $ip2usernames->{$ip}->{$name}={}; + $ip2usernames->{$ip}->{$name}->{count}=0; + $ip2usernames->{$ip}->{$name}->{timestamps}=[]; + $ip2usernames->{$ip}->{$name}->{epoch}=[]; + + } + $ip2usernames->{$ip}->{$name}->{count}++; + push (@{$ip2usernames->{$ip}->{$name}->{timestamps}}, $timestamp); + push (@{$ip2usernames->{$ip}->{$name}->{epoch}}, str2time($timestamp)); + + if (!defined($usernames2ip->{$name})) { + $usernames2ip->{$name}={}; + } + if (!defined($usernames2ip->{$name}->{$ip})) { + $usernames2ip->{$name}->{$ip}={}; + $usernames2ip->{$name}->{$ip}->{count}=0; + $usernames2ip->{$name}->{$ip}->{timestamps}=[]; + $usernames2ip->{$name}->{$ip}->{epoch}=[]; + } + $usernames2ip->{$name}->{$ip}->{count}++; + push (@{$usernames2ip->{$name}->{$ip}->{timestamps}}, $timestamp); + push (@{$usernames2ip->{$name}->{$ip}->{epoch}}, str2time($timestamp)); + } + } + close $zncLog; + return $ip2usernames,$usernames2ip; +} + + +1; blob - /dev/null blob + d874b9f33f431939b19e6a97d65a49aed30b890a (mode 755) --- /dev/null +++ parseznc.pl @@ -0,0 +1,22 @@ +#!/usr/bin/perl +# + +use strict; +use warnings; + +use lib qw(./lib); +use IRCNOW::ParseLog::Znc; + +my $znclog = IRCNOW::ParseLog::Znc->new( + database=>'/var/www/botnow/botnow.db', + zncLog=>'/home/znc/home/znc/.znc/moddata/adminlog/znc.log', +); + +use Data::Dumper; + +my $lastRecord=$znclog->dbLastRecord() || []; + +print Dumper($znclog->parseLog($lastRecord->[1],$lastRecord->[3],$lastRecord->[4])); + +#$znclog->createTable(); +