diff --git a/lib/PBot/Plugin/Quotegrabs.pm b/lib/PBot/Plugin/Quotegrabs.pm index 343fdfc2..8bc8e79e 100644 --- a/lib/PBot/Plugin/Quotegrabs.pm +++ b/lib/PBot/Plugin/Quotegrabs.pm @@ -45,6 +45,7 @@ sub unload { $self->{pbot}->{commands}->unregister('getq'); $self->{pbot}->{commands}->unregister('delq'); $self->{pbot}->{commands}->unregister('rq'); + $self->{database}->end(); } sub uniq { my %seen; grep !$seen{$_}++, @_ } diff --git a/lib/PBot/Plugin/Quotegrabs/Storage/SQLite.pm b/lib/PBot/Plugin/Quotegrabs/Storage/SQLite.pm index 3fc78245..6f3ac8bd 100644 --- a/lib/PBot/Plugin/Quotegrabs/Storage/SQLite.pm +++ b/lib/PBot/Plugin/Quotegrabs/Storage/SQLite.pm @@ -46,6 +46,12 @@ CREATE TABLE IF NOT EXISTS Quotegrabs ( text TEXT, timestamp NUMERIC ) +SQL + + $self->{dbh}->do(<< 'SQL'); +CREATE TABLE IF NOT EXISTS Seen ( + id INTEGER UNIQUE +) SQL }; @@ -117,7 +123,7 @@ sub get_random_quotegrab { # multi-grabs have the nick separated by +'s so we must test for # nick, nick+*, *+nick, and *+nick+* to match each of these cases if (defined $nick) { - $sql .= $where . 'nick LIKE ? OR nick LIKE ? OR nick LIKE ? OR nick LIKE ?'; + $sql .= $where . '(nick LIKE ? OR nick LIKE ? OR nick LIKE ? OR nick LIKE ?) '; push @params, "$nick"; push @params, "$nick+%"; push @params, "%+$nick"; @@ -138,17 +144,62 @@ sub get_random_quotegrab { push @params, "%$text%"; } - $sql .= 'ORDER BY RANDOM() LIMIT 1'; - - my $sth = $self->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql . $where . $and . 'id NOT IN Seen ORDER BY RANDOM() LIMIT 1'); $sth->execute(@params); - return $sth->fetchrow_hashref(); + my $quotegrab = $sth->fetchrow_hashref(); + + # no unseen quote found, remove queried quotes from Seen table and try again + if (not defined $quotegrab) { + my $count = $self->remove_seen($sql, \@params); + + # no matching quotes in Seen table, ergo no quote found + if ($count == 0) { + return undef; + } + + # try again + $sth->execute(@params); + $quotegrab = $sth->fetchrow_hashref(); + } + + # mark quote as seen + if (defined $quotegrab) { + $self->add_seen($quotegrab->{id}); + } + + return $quotegrab; }; $self->{pbot}->{logger}->log($@) if $@; return $quotegrab; } +sub remove_seen { + my ($self, $sql, $params) = @_; + + $sql =~ s/^SELECT \*/SELECT id/; + + my $count = eval { + my $sth = $self->{dbh}->prepare("DELETE from Seen WHERE id IN ($sql)"); + $sth->execute(@$params); + return $sth->rows; + }; + + $self->{pbot}->{logger}->log($@) if $@; + return $count; +} + +sub add_seen { + my ($self, $id) = @_; + + eval { + my $sth = $self->{dbh}->prepare('INSERT INTO Seen VALUES (?)'); + $sth->execute($id); + }; + + $self->{pbot}->{logger}->log($@) if $@; +} + sub get_all_quotegrabs { my $self = shift; @@ -167,8 +218,10 @@ sub delete_quotegrab { eval { my $sth = $self->{dbh}->prepare('DELETE FROM Quotegrabs WHERE id == ?'); - $sth->bind_param(1, $id); - $sth->execute(); + $sth->execute($id); + + $sth = $self->{dbh}->prepare('DELETE FROM Seen WHERE id == ?'); + $sth->execute($id); }; $self->{pbot}->{logger}->log($@) if $@; diff --git a/lib/PBot/VERSION.pm b/lib/PBot/VERSION.pm index 0aebf583..270da1dc 100644 --- a/lib/PBot/VERSION.pm +++ b/lib/PBot/VERSION.pm @@ -25,8 +25,8 @@ use PBot::Imports; # These are set by the /misc/update_version script use constant { BUILD_NAME => "PBot", - BUILD_REVISION => 4641, - BUILD_DATE => "2023-03-30", + BUILD_REVISION => 4642, + BUILD_DATE => "2023-04-10", }; sub initialize {}