[BACK]Return to SQLite.pm CVS log [TXT][DIR] Up to [local] / botnow

Annotation of botnow/SQLite.pm, Revision 1.1.1.1

1.1       bountyht    1: #!/usr/bin/perl
                      2:
                      3: package SQLite;
                      4:
                      5: use strict;
                      6: use warnings;
                      7: use OpenBSD::Pledge;
                      8: use OpenBSD::Unveil;
                      9: use Data::Dumper;
                     10: use DBI;
                     11: use DBD::SQLite;
                     12:
                     13: use constant {
                     14:        NONE => 0,
                     15:        ERRORS => 1,
                     16:        WARNINGS => 2,
                     17:        ALL => 3,
                     18: };
                     19: my %conf = %main::conf;
                     20: my $staff = $conf{staff};
                     21: my $dbh;
                     22: my $verbose = $conf{verbose};
                     23: my $dbpath = "/var/www/botnow/botnow.db";
                     24: my $database = "/var/www/botnow/"; # database path
                     25: main::cbind("msg", "-", "get", \&mget);
                     26: main::cbind("msg", "-", "set", \&mset);
                     27: main::cbind("msg", "-", "connectdb", \&mconnectdb);
                     28: main::cbind("msg", "-", "insert", \&minsert);
                     29: main::cbind("msg", "-", "update", \&mupdate);
                     30: main::cbind("msg", "-", "delete", \&mdelete);
                     31: main::cbind("msg", "-", "select", \&mselect);
                     32:
                     33: sub init {
                     34:        unveil("$dbpath", "rwc") or die "Unable to unveil $!";
                     35:        unveil("$dbpath-journal", "rwc") or die "Unable to unveil $!";
                     36:        unveil("$database", "rwxc") or die "Unable to unveil $!";
                     37: }
                     38:
                     39: # !connectdb
                     40: sub mconnectdb {
                     41:        my ($bot, $nick, $host, $hand, $text) = @_;
                     42:        if (! (main::isstaff($bot, $nick))) { return; }
                     43:        if (connectdb()) {
                     44:                main::putserv($bot, "PRIVMSG $nick :connectdb succeeded");
                     45:        } else {
                     46:                main::putserv($bot, "PRIVMSG $nick :ERROR: connectdb failed");
                     47:        }
                     48: }
                     49:
                     50: # !insert <table> <keys> <vals>
                     51: # Insert comma-separated keys and vals into table
                     52: sub minsert {
                     53:        my ($bot, $nick, $host, $hand, $text) = @_;
                     54:        if (! (main::isstaff($bot, $nick))) { return; }
                     55:        if ($text =~ /^([-_~@!,\.[:alnum:]]+)\s+([-_~@!,\.[:alnum:]]+)\s+([[:ascii:]]+)/) {
                     56:                my ($table, $keys, $vals) = ($1, $2, $3);
                     57:                # strings in the values must be quoted
                     58:                if ($vals =~ s{,}{","}g) { $vals = '"'.$vals.'"'; }
                     59:                if (insertrow($table, $keys, $vals)) {
                     60:                        main::putserv($bot, "PRIVMSG $nick :$table ($keys) => ($vals)");
                     61:                } else {
                     62:                        main::putserv($bot, "PRIVMSG $nick :$table insert failed");
                     63:                }
                     64:        } else {
                     65:                main::putserv($bot, "PRIVMSG $nick :invalid insert");
                     66:        }
                     67: }
                     68:
                     69: # Set key = val where idkey = idval in table
                     70: # !update <table> <idkey> <idval> <key> <val>
                     71: sub mupdate {
                     72:        my ($bot, $nick, $host, $hand, $text) = @_;
                     73:        if (! (main::isstaff($bot, $nick))) { return; }
                     74:        if ($text =~ /^([-_~@!,\.[:alnum:]]+)\s+([-_~@!,\.[:alnum:]]+)\s+(\S+)\s+([-_[:alnum:]]+)\s+(\S+)/) {
                     75:                my ($table, $idkey, $idval, $key, $val) = ($1, $2, $3, $4, $5);
                     76:                if (updaterow($table, $idkey, $idval, $key, $val)) {
                     77:                        main::putserv($bot, "PRIVMSG $nick :$table $key => $val where $idkey = $idval");
                     78:                } else {
                     79:                        main::putserv($bot, "PRIVMSG $nick :update failed");
                     80:                }
                     81:        } else {
                     82:                main::putserv($bot, "PRIVMSG $nick :invalid update");
                     83:        }
                     84: }
                     85:
                     86: # Delete rows where key = val in table
                     87: # !delete <table> <key> <val>
                     88: sub mdelete {
                     89:        my ($bot, $nick, $host, $hand, $text) = @_;
                     90:        if (! (main::isstaff($bot, $nick))) { return; }
                     91:        if ($text =~ /^([-_~@!,\.[:alnum:]]+)\s+([-_[:alnum:]]+)\s+(\S+)/) {
                     92:                my ($table, $key, $val) = ($1, $2, $3);
                     93:                if (deleterows($table, $key, $val)) {
                     94:                        main::putserv($bot, "PRIVMSG $nick :$table $key = $val deleted");
                     95:                } else {
                     96:                        main::putserv($bot, "PRIVMSG $nick :delete failed");
                     97:                }
                     98:        } else {
                     99:                main::putserv($bot, "PRIVMSG $nick :invalid delete");
                    100:        }
                    101: }
                    102:
                    103: # Output rows where key = val in table
                    104: # !select <table> <key> <val>
                    105: sub mselect {
                    106:        my ($bot, $nick, $host, $hand, $text) = @_;
                    107:        if (! (main::isstaff($bot, $nick))) { return; }
                    108:        if ($text =~ /^([-_~@!,\.[:alnum:]]+)\s+([-_[:alnum:]]+)\s+(\S+)/) {
                    109:                my ($table, $key, $val) = ($1, $2, $3);
                    110:                my @rows = selectrows($table, $key, $val);
                    111:                if (@rows) {
                    112:                        foreach my $row (@rows) {
                    113:                                my @pairs;
                    114:                                foreach $key (keys %$row) {
                    115:                                        my $val = $row->{$key} || "";
                    116:                                        push(@pairs, "$key => $val");
                    117:                                }
                    118:                                main::putserv($bot, "PRIVMSG $nick :$table ".join(',', @pairs));
                    119:                        }
                    120:                } else {
                    121:                        main::putserv($bot, "PRIVMSG $nick :no results");
                    122:                }
                    123:        } else {
                    124:                main::putserv($bot, "PRIVMSG $nick :select invalid");
                    125:        }
                    126: }
                    127:
                    128: # Get value of key where idkey = idval in table
                    129: # !get <table> <idkey> <idval> <key>
                    130: sub mget {
                    131:        my ($bot, $nick, $host, $hand, $text) = @_;
                    132:        if (! (main::isstaff($bot, $nick))) { return; }
                    133:        if ($text =~ /^([-_~@!,\.[:alnum:]]+)\s+([-_~@!,\.[:alnum:]]+)\s+(\S+)\s+([-_[:alnum:]]+)/) {
                    134:                my ($table, $idkey, $idval, $key) = ($1, $2, $3, $4);
                    135:                my $val = get($table, $idkey, $idval, $key);
                    136:                if (defined($val)) {
                    137:                        main::putserv($bot, "PRIVMSG $nick :$table $key => $val where $idkey = $idval");
                    138:                } else {
                    139:                        main::putserv($bot, "PRIVMSG $nick :undefined");
                    140:                }
                    141:        } else {
                    142:                main::putserv($bot, "PRIVMSG $nick :invalid get");
                    143:        }
                    144: }
                    145: # !set <table> <idkey> <idval> <key> <val>
                    146: sub mset {
                    147:        my ($bot, $nick, $host, $hand, $text) = @_;
                    148:        if (! (main::isstaff($bot, $nick))) { return; }
                    149:        if ($text =~ /^([-_~@!,\.[:alnum:]]+)\s+([-_~@!,\.[:alnum:]]+)\s+(\S+)\s+([-_[:alnum:]]+)\s+(\S+)/) {
                    150:                my ($table, $idkey, $idval, $key, $val) = ($1, $2, $3, $4, $5);
                    151:                if (set($table, $idkey, $idval, $key, $val)) {
                    152:                        main::putserv($bot, "PRIVMSG $nick :$table $key => $val where $idkey = $idval");
                    153:                } else {
                    154:                        main::putserv($bot, "PRIVMSG $nick :failed set");
                    155:                }
                    156:        } else {
                    157:                main::putserv($bot, "PRIVMSG $nick :invalid set");
                    158:        }
                    159: }
                    160:
                    161: # Connect to database, creating table if necessary
                    162: # Returns true on success, false on failure
                    163: sub connectdb {
                    164:        my $dsn      = "dbi:SQLite:dbname=$dbpath";
                    165:        my $user     = "";
                    166:        my $password = "";
                    167:        $dbh = DBI->connect($dsn, $user, $password, {
                    168:                PrintError       => 1,
                    169:                RaiseError       => 1,
                    170:                AutoCommit       => 1,
                    171:                FetchHashKeyName => 'NAME_lc',
                    172:        }) or die "Couldn't connect to database: " . $DBI::errstr;
                    173:        if (!(-s "$dbpath")) {
                    174:                my $sql = main::readstr('table.sql');
                    175:                my @sql = split /;/m, $sql;
                    176:                foreach my $s (@sql) {
                    177:                        $dbh->do($s);
                    178:                }
                    179:        }
                    180:        main::debug(ALL, "connected to $dbpath");
                    181:        return defined($dbh);
                    182: }
                    183:
                    184: # Inserts comma-separated keys and vals into table
                    185: # Returns number of rows successfully inserted
                    186: sub insertrow {
                    187:        my ($table, $keys, $vals) = @_;
                    188:        if (!defined($dbh)) { connectdb(); }
                    189:        my $rows = $dbh->do("INSERT INTO $table ($keys) values ($vals)");
                    190:        if ($rows) {
                    191:                main::debug(ALL, "INSERT INTO $table ($keys) values ($vals)");
                    192:        } else {
                    193:                main::debug(ERRORS, "ERRORS: Failed INSERT INTO $table ($keys) values ($vals)");
                    194:        }
                    195:        return $rows;
                    196: }
                    197:
                    198: # Update key, value pair for record where idkey equals idval in table
                    199: # Returns number of rows successfully updated
                    200: sub updaterow {
                    201:        my ($table, $idkey, $idval, $key, $val) = @_;
                    202:        if (!defined($dbh)) { connectdb(); }
                    203:        my $rows = $dbh->do("UPDATE $table SET $key = ? where $idkey = ?", undef, $val, $idval);
                    204:        if ($rows) {
                    205:                main::debug(ALL, "UPDATE $table SET $key = $val where $idkey = $idval");
                    206:        } else {
                    207:                main::debug(ERRORS, "ERRORS: Failed UPDATE $table SET $key = $val where $idkey = $idval");
                    208:        }
                    209:        return $rows;
                    210: }
                    211:
                    212: # Delete records from $table where $key = $val
                    213: # Returns number of rows deleted
                    214: sub deleterows {
                    215:        my ($table, $key, $val) = @_;
                    216:        if (!defined($dbh)) { connectdb(); }
                    217:        my $rows = $dbh->do("DELETE FROM $table WHERE $key = ?", undef, $val);
                    218:        if ($rows) {
                    219:                main::debug(ALL, "DELETE FROM $table WHERE $key = $val");
                    220:        } else {
                    221:                main::debug(ERRORS, "ERRORS: Failed DELETE FROM $table WHERE $key = $val");
                    222:        }
                    223:        return $rows;
                    224: }
                    225:
                    226: # Returns all records in the database
                    227: sub selectall {
                    228:        my ($table) = @_;
                    229:        if (!defined($dbh)) { connectdb(); }
                    230:        my $sth = $dbh->prepare("SELECT * FROM $table");
                    231:        $sth->execute();
                    232:        my @results;
                    233:        while (my $row = $sth->fetchrow_hashref) {
                    234:                push(@results, $row);
                    235:        }
                    236:        return @results;
                    237: }
                    238:
                    239: # Returns all records from table where key equals value
                    240: sub selectrows {
                    241:        my ($table, $key, $val) = @_;
                    242:        if (!defined($dbh)) { connectdb(); }
                    243:        my $sth = $dbh->prepare("SELECT * FROM $table WHERE $key = ?");
                    244:        $sth->execute($val);
                    245:        my @results;
                    246:        while (my $row = $sth->fetchrow_hashref) {
                    247:                push(@results, $row);
                    248:        }
                    249:        return @results;
                    250: }
                    251:
                    252: # Returns list of tables
                    253: sub tables {
                    254:        #       if (!defined($dbh)) { connectdb(); }
                    255:        #       my $sth = $dbh->prepare(".tables");
                    256:        #       $sth->execute($val);
                    257:        #       my @results;
                    258:        #       while (my $row = $sth->fetchrow_hashref) {
                    259:        #               push(@results, $row);
                    260:        #       }
                    261:        #       return @results;
                    262:        return qw(bnc shell www irc smtp);
                    263: }
                    264:
                    265: # Returns value of key in record in table where idkey = idval
                    266: sub get {
                    267:        my ($table, $idkey, $idval, $key) = @_;
                    268:        if (!defined($dbh)) { connectdb(); }
                    269:        my $sth = $dbh->prepare("SELECT * FROM $table WHERE $idkey = ?");
                    270:        $sth->execute($idval);
                    271:        if (my $row = $sth->fetchrow_hashref) {
                    272:                my $val = $row->{$key};
                    273:                if (!defined($val)) { $val = "undefined"; }
                    274:                main::debug(ALL, "get: $table $key => $val where $idkey = $idval");
                    275:                return $row->{$key};
                    276:        } else {
                    277:                main::debug(ERRORS, "ERRORS: $table $key undefined where $idkey = $idval");
                    278:                return;
                    279:        }
                    280: }
                    281:
                    282: # Sets value of key in the record in table where idkey = idval
                    283: # Returns true on success; false on failure
                    284: sub set {
                    285:        my ($table, $idkey, $idval, $key, $val) = @_;
                    286:        if (defined(get($table, $idkey, $idval, $idkey))) {
                    287:                main::debug(ALL, "set: update");
                    288:                return updaterow($table, $idkey, $idval, $key, $val) > 0;
                    289:        } else {
                    290:                main::debug(ALL, "set: insert");
                    291:                return insertrow($table, "$idkey,$key", "\"$idval\",\"$val\"") > 0;
                    292:        }
                    293: }
                    294:
                    295: # given a key, val pair in table, return the id that falls within expires seconds
                    296: sub id {
                    297:        my ($table, $key, $val, $expires) = @_;
                    298:        my @rows = selectrows($table, $key, $val);
                    299:        if (scalar(@rows) == 0) {
                    300:                print "table => $table, key => $key, val => $val\n\n";
                    301:        }
                    302:        my $maxrow;
                    303:        foreach my $row (@rows) {
                    304:                if (!defined($maxrow)) { $maxrow = $row; }
                    305:                if ($row->{localtime} > $maxrow->{localtime}) {
                    306:                        $maxrow = $row;
                    307:                }
                    308:        }
                    309:        if (abs(time() - $maxrow->{localtime}) <= $expires) {
                    310:                main::debug(ALL, "id: $maxrow->{id} where $key = $val at $expires");
                    311:                return $maxrow->{id};
                    312:        } else {
                    313:                main::debug(ERRORS, "no id found");
                    314:                return;
                    315:        }
                    316: }
                    317:
                    318: 1; # MUST BE LAST STATEMENT IN FILE

CVSweb