All pastes #623872 Raw Edit

imMute

public text v1 · immutable
·published 2007-07-17 22:05 UTC
rendered paste body
# $Id: mylog.pl 58 2007-07-17 07:51:24Z immute $
use strict;
use vars qw($VERSION %IRSSI);

$VERSION = do { q$Rev: 58 $ =~ /(\d+)/; "0.$1"; };
%IRSSI = (
authors     => 'Matt "imMute" Sickler',
contact     => 'imMute {at} mail.msk3.ath.cx',
name        => 'MyLog',
description => 'Logs channel/privmsg activity to a MySQL database',
license     => 'GPLv2',
url         => '',
changed     => '$Date: 2007-07-17 02:51:24 -0500 (Tue, 17 Jul 2007) $',
);

=pod Description
Logs channel/privmsg activity to a MySQL database
=cut

=pod Useage
=cut

use Irssi::Irc;
use Irssi qw/settings_add_str settings_get_str printformat/;
use Data::Dumper; $Data::Dumper::Indent=0; $Data::Dumper::Sortkeys=1;
use DBI;

sub DEBUG (@) { 1 and printformat(MSGLEVEL_CRAP, 'mylog_debug', @_); }

=pod ToDo
=cut

Irssi::theme_register([
    'mylog_debug',         '%P>>%n %_MyLog(DEBUG):%_ $0-',
    'mylog_db_connected',  '%P>>%n %_MyLog:%_ Connected to db ($0:$1 - $2)',
    'mylog_db_no_connect', '%P>>%n %_MyLog:%_ Could not connect to database: $0',
    'mylog_no_setting',    '%P>>%n %_MyLog:%_ You did not specify the $0 setting (mylog_$1)',
    'mylog_loaded',        '%P>>%n %_MyLog:%_ MySQL-Log v$0 loaded',
    'mylog_error',         '%P>>%n %_MyLog:%_ %R%_Error%_ in operation $0:%n $1-',
]);

settings_add_str "mylog", "mylog_db_host",  "localhost";
settings_add_str "mylog", "mylog_db_port",  "3306";
settings_add_str "mylog", "mylog_db_user",  "irssi";
settings_add_str "mylog", "mylog_db_pass",  "irssi";
settings_add_str "mylog", "mylog_db_base",  "irssi";
settings_add_str "mylog", "mylog_levels",   "message chan notice ctcp";
Irssi::settings_add_bool "mylog","mylog_logging",  1;

my $sth_prepare = {
  get_nick_id => q!SELECT `id` FROM `nicks` WHERE `nick` = ?!,
  set_nick_id => q!INSERT INTO `nicks` VALUES(NULL, ?)!,
  
  get_ident_id => q!SELECT `id` FROM `idents` WHERE `ident_name` = ?!,
  set_ident_id => q!INSERT INTO `idents` VALUES(NULL, ?)!,
  
  get_host_id => q!SELECT `id` FROM `hosts` WHERE `hostname` = ?!,
  set_host_id => q!INSERT INTO `hosts` VALUES(NULL, ?)!,
  
  get_user_id => q!SELECT `id` FROM `user_id` WHERE `nick_id` = ? AND `ident_id` = ? AND `host_id` = ?!,
  set_user_id => q!INSERT INTO `user_id` VALUES(NULL, ?, ?, ?)!,
  
  get_chan_id => q!SELECT `id` FROM `channels` WHERE `channel` = ? AND `network` = ?!,
  set_chan_id => q!INSERT INTO `channels` VALUES(NULL, ?, ?)!,
  
  get_quitmsg_id => q!SELECT `id` FROM `quit_messages` WHERE `message` = ?!,
  set_quitmsg_id => q!INSERT INTO `quit_messages` VALUES(NULL, ?)!,
  
  insert_msg => q!INSERT INTO `messages` VALUES(NULL, NOW(), ?, ?, ?)!,
  insert_join => q!INSERT INTO `joins` VALUES(NULL, NOW(), ?, ?)!,
  insert_quit => q!INSERT INTO `quits` VALUES(NULL, NOW(), ?, ?)!,
  insert_part => q!INSERT INTO `parts` VALUES(NULL, ?, ?, ?, NOW())!,
  insert_topic => q!INSERT INTO `topics` VALUES(NULL, NOW(), ?, ?, ?)!,
};
my $dbh;
my $sth = { };

sub dbi_connect {
    my $host = settings_get_str 'mylog_db_host';
    my $port = settings_get_str 'mylog_db_port';
    my $user = settings_get_str 'mylog_db_user';
    my $pass = settings_get_str 'mylog_db_pass';
    my $base = settings_get_str 'mylog_db_base';
    eval {
      $dbh = DBI->connect("DBI:mysql:database=$base;host=$host;port=$port", $user, $pass,
        { PrintError => 0, RaiseError => 1, }) or die;
    };
    if ($@) {
        printformat(MSGLEVEL_CRAP,'mylog_error', 'connect', $DBI::errstr);
        $dbh = $sth = undef;
        return;
    } else {
        printformat(MSGLEVEL_CRAP,'mylog_db_connected', $host, $port, $base);
        setup_sth();
    }
}
sub setup_sth {
    return unless defined $dbh;
    while( my ($name, $sql) = each %$sth_prepare ){
      eval { $sth->{$name} = $dbh->prepare( $sql ) or die; };
      if ( $@ ){  printformat(MSGLEVEL_CRAP, 'mylog_error', 'prepare', $!); $sth->{$name} = undef; }
    }
}

Irssi::command_bind("mylog_reconnect", 'dbi_connect');
Irssi::command_bind("mylog_qst", 'setup_sth');

dbi_connect() if Irssi::settings_get_bool("mylog_logging");
printformat(MSGLEVEL_CRAP, 'mylog_loaded', $VERSION);

sub signal_add {
  my ($type, $name, $sub) = @_;
  Irssi::signal_add( $name, sub {
    return unless Irssi::settings_get_bool("mylog_logging");
    return unless settings_get_str("mylog_levels") =~ $type;
    $sub->(@_);
  });
}

sub sql {
  my ($name, @vars) = @_;
  my $X = $sth_prepare->{$name} =~ /^INSERT/;
  my $S = $sth->{$name};
  my $R;
  eval { $S->execute( @vars ); return if $X; $R = $S->fetchall_arrayref(); };
  if ($@){ printformat(MSGLEVEL_CRAP, 'mylog_error', 'exec', $@, $DBI::errstr); }
  else { return $R; }
}
sub LID () { return $dbh->last_insert_id(undef, undef, undef, undef); }

sub AUTOCREATE () { 1 }

{ #signals
# --- Message

#  "message public",      SERVER_REC, char *msg, char *nick,   char *address, char *target
signal_add "message", "message public", sub {
  my ($server, $msg, $nick, $address, $channel) = @_;
  my ($ident, $host) = split /@/, $server->{userhost}, 2;
  
  my $nick_id = m_nick( $nick, AUTOCREATE );
  my $ident_id = m_ident( $ident, AUTOCREATE );
  my $host_id = m_host( $host, AUTOCREATE );
  my $user_id = m_user( $nick_id, $ident_id, $host_id, AUTOCREATE );
  my $channel_id = m_chan( $channel, $server->{chatnet}, AUTOCREATE );
  
  sql('insert_msg', $user_id, $channel_id, $msg);
};

#  "message own_public",  SERVER_REC, char *msg, char *target
signal_add "message", "message own_public", sub {
  my ($server, $message, $channel) = @_;
  my $nick = $server->{nick};
  my ($ident, $host) = split /@/, $server->{userhost}, 2;
  
  my $nick_id = m_nick( $nick, AUTOCREATE );
  my $ident_id = m_ident( $ident, AUTOCREATE );
  my $host_id = m_host( $host, AUTOCREATE );
  my $user_id = m_user( $nick_id, $ident_id, $host_id, AUTOCREATE );
  my $channel_id = m_chan( $channel, $server->{chatnet}, AUTOCREATE );
  
  sql('insert_msg', $user_id, $channel_id, $message);
};

#  "message private",     SERVER_REC, char *msg, char *nick,   char *address
#  "message own_private", SERVER_REC, char *msg, char *target, char *orig_target

#  "message irc action", SERVER_REC, char *msg, char *nick, char *address, char *target
#  "message irc own_action", SERVER_REC, char *msg, char *target

# --- Chan
#  "message join",     SERVER_REC, char *channel, char *nick,    char *address
signal_add "chan", "message join", sub {
  my ($server, $channel, $nick, $address) = @_;
  my ($ident, $host) = split /@/, $address, 2;
  
  my $nick_id = m_nick( $nick, AUTOCREATE );
  my $ident_id = m_ident( $ident, AUTOCREATE );
  my $host_id = m_host( $host, AUTOCREATE );
  my $user_id = m_user( $nick_id, $ident_id, $host_id, AUTOCREATE );
  my $channel_id = m_chan( $channel, $server->{chatnet}, AUTOCREATE );
  
  sql('insert_join', $user_id, $channel_id);
};

#  "message part",     SERVER_REC, char *channel, char *nick,    char *address, char *reason
signal_add "chan", "message part", sub {
  my ($server, $channel, $nick, $address, $reason) = @_;
  my ($ident, $host) = split /@/, $address, 2;
  
  my $nick_id = m_nick( $nick, AUTOCREATE );
  my $ident_id = m_ident( $ident, AUTOCREATE );
  my $host_id = m_host( $host, AUTOCREATE );
  my $user_id = m_user( $nick_id, $ident_id, $host_id, AUTOCREATE );
  my $channel_id = m_chan( $channel, $server->{chatnet}, AUTOCREATE );
  my $quitmsg_id = m_quitmsg( $reason, AUTOCREATE );
  
  sql('insert_part', $user_id, $channel, $quitmsg_id);
};

#  "message quit",     SERVER_REC, char *nick,    char *address, char *reason
signal_add "chan", "message quit", sub {
  my ($server, $nick, $address, $reason) = @_;
  my ($ident, $host) = split /@/, $address, 2;
  
  my $nick_id = m_nick( $nick, AUTOCREATE );
  my $ident_id = m_ident( $ident, AUTOCREATE );
  my $host_id = m_host( $host, AUTOCREATE );
  my $user_id = m_user( $nick_id, $ident_id, $host_id, AUTOCREATE );
  my $quitmsg_id = m_quitmsg( $reason, AUTOCREATE );
  
  sql('insert_quit', $user_id, $quitmsg_id);
};

#  "message kick",     SERVER_REC, char *channel, char *nick,    char *kicker,  char *address, char *reason
signal_add "chan", "message kick", sub {  # TODO: fix/finish
  my ($server, $channel, $nick, $kicker, $address, $reason) = @_;
  my ($ident, $host) = split /@/, $address, 2;
  
  my $nick_id = m_nick( $nick, AUTOCREATE );
  my $ident_id = m_ident( $ident, AUTOCREATE );
  my $host_id = m_host( $host, AUTOCREATE );
  my $user_id = m_user( $nick_id, $ident_id, $host_id, AUTOCREATE );
  my $channel_id = m_chan( $channel, $server->{chatnet}, AUTOCREATE );
  
};

#  "message nick",     SERVER_REC, char *newnick, char *oldnick, char *address
signal_add "chan", "message nick", sub {  #TODO: finish
  my ($server, $new_nick, $old_nick, $address) = @_;
};

#  "message own_nick", SERVER_REC, char *newnick, char *oldnick, char *address
signal_add "chan", "message own_nick", sub {  #TODO: finish
  my ($server, $newnick, $oldnick, $address) = @_;
};

#  "message irc mode", SERVER_REC, char *channel, char *nick, char *addr, char *mode
signal_add "chan", "message irc mode", sub {  #TODO: finish
  my ($server, $channel, $nick, $address, $mode) = @_;
};

#  "message topic", SERVER_REC, char *channel, char *topic, char *nick, char *address
signal_add "chan", "message topic", sub {
  my ($server, $channel, $topic, $nick, $address) = @_;
  my ($ident, $host) = split /@/, $address, 2;
  
  my $nick_id = m_nick( $nick, AUTOCREATE );
  my $ident_id = m_ident( $ident, AUTOCREATE );
  my $host_id = m_host( $host, AUTOCREATE );
  my $user_id = m_user( $nick_id, $ident_id, $host_id, AUTOCREATE );
  my $channel_id = m_chan( $channel, $server->{chatnet}, AUTOCREATE );
  
  sql('insert_topic', $channel_id, $user_id, $topic);
}

# --- Notice
#  "message irc notice", SERVER_REC, char *msg, char *nick, char *address, char *target

#  "message irc own_notice", SERVER_REC, char *msg, char *target

# --- CTCP
#  "message irc ctcp", SERVER_REC, char *cmd, char *data, char *nick, char *address, char *target

#  "message irc own_ctcp", SERVER_REC, char *cmd, char *data, char *target

#  "ctcp reply", SERVER_REC, char *args, char *nick, char *addr, char *target


}

{ # relational helpers

sub m_nick {
  my ($nick, $C) = @_;
  my $R = sql('get_nick_id', $nick)->[0]; # dangerous if auto is off and it returns undef!
  if (ref $R) { return $R->[0];}
  elsif ($C)  { sql('set_nick_id', $nick); return LID(); }
  else        { return undef; }
}

sub m_ident {
  my ($ident, $C) = @_;
  my $R = sql('get_ident_id', $ident)->[0]; # dangerous if auto is off and it returns undef!
  if (ref $R) { return $R->[0]; }
  elsif ($C)  { sql('set_ident_id', $ident); return LID(); }
  else { return undef; }
}

sub m_host {
  my ($host, $C) = @_;
  my $R = sql('get_host_id', $host)->[0]; # dangerous if auto is off and it returns undef!
  if (ref $R) { return $R->[0]; }
  elsif ($C)  { sql('set_host_id', $host); return LID(); }
  else { return undef; }
}

sub m_user {
  my ($nick, $ident, $host, $C) = @_;
  my $R = sql('get_user_id', $nick, $ident, $host)->[0]; # dangerous if auto is off and it returns undef!
  if (ref $R) { return $R->[0]; }
  elsif ($C)  { sql('set_user_id', $nick, $ident, $host); return LID(); }
  else { return undef; }
}

sub m_chan {
  my ($chan, $net, $C) = @_;
  my $R = sql('get_chan_id', $chan, $net)->[0]; # dangerous if auto is off and it returns undef!
  if (ref $R) { return $R->[0]; }
  elsif ($C)  { sql('set_chan_id', $chan, $net); return LID(); }
  else { return undef; }
}

sub m_quitmsg {
  my ($reason, $C) = @_;
  my $R = sql('get_quitmsg_id', $reason)->[0]; # dangerous if auto is off and it returns undef!
  if (ref $R) { return $R->[0]; }
  elsif ($C)  { sql('set_quitmsg_id', $reason); return LID(); }
  else { return undef; }
}

}