mirror of
https://github.com/pragma-/pbot.git
synced 2024-12-24 11:42:35 +01:00
Plugins/RemindMe: use event queue for reminders
This commit is contained in:
parent
471422a4f8
commit
bc79f3a69d
@ -20,16 +20,54 @@ sub initialize {
|
|||||||
my ($self, %conf) = @_;
|
my ($self, %conf) = @_;
|
||||||
$self->{pbot}->{commands}->register(sub { $self->remindme(@_) }, 'remindme', 0);
|
$self->{pbot}->{commands}->register(sub { $self->remindme(@_) }, 'remindme', 0);
|
||||||
$self->{filename} = $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/reminders.sqlite3';
|
$self->{filename} = $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/reminders.sqlite3';
|
||||||
$self->{pbot}->{timer}->register(sub { $self->check_reminders(@_) }, 1, 'RemindMe');
|
|
||||||
$self->dbi_begin;
|
$self->dbi_begin;
|
||||||
$self->create_database;
|
$self->create_database;
|
||||||
|
$self->enqueue_reminders;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub unload {
|
sub unload {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
$self->dbi_end;
|
$self->dbi_end;
|
||||||
$self->{pbot}->{commands}->unregister('remindme');
|
$self->{pbot}->{commands}->unregister('remindme');
|
||||||
$self->{pbot}->{timer}->unregister('RemindMe');
|
$self->{pbot}->{timer}->dequeue_event('reminder .*');
|
||||||
|
}
|
||||||
|
|
||||||
|
sub enqueue_reminders {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
return if not $self->{dbh};
|
||||||
|
|
||||||
|
my $reminders = eval {
|
||||||
|
my $sth = $self->{dbh}->prepare('SELECT * FROM Reminders');
|
||||||
|
$sth->execute;
|
||||||
|
return $sth->fetchall_arrayref({});
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($@) {
|
||||||
|
$self->{pbot}->{logger}->log("Enqueue reminders failed: $@");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $reminder (@$reminders) {
|
||||||
|
# delete this reminder if it's expired by 31 days
|
||||||
|
if (gettimeofday - $reminder->{alarm} >= 86400 * 31) {
|
||||||
|
$self->{pbot}->{logger}->log("Deleting expired reminder: $reminder->{id}) $reminder->{text} set by $reminder->{created_by}\n");
|
||||||
|
$self->delete_reminder($reminder->{id});
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $timeout = $reminder->{alarm} - gettimeofday;
|
||||||
|
$timeout = 10 if $timeout < 10;
|
||||||
|
my $repeating = $reminder->{repeat};
|
||||||
|
|
||||||
|
$self->{pbot}->{timer}->enqueue_event(
|
||||||
|
sub {
|
||||||
|
my ($event) = @_;
|
||||||
|
$self->do_reminder($reminder->{id}, $event);
|
||||||
|
},
|
||||||
|
$timeout, "reminder $reminder->{id}", $repeating
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub create_database {
|
sub create_database {
|
||||||
@ -81,15 +119,43 @@ sub dbi_end {
|
|||||||
sub add_reminder {
|
sub add_reminder {
|
||||||
my ($self, $account, $target, $text, $alarm, $duration, $repeat, $owner) = @_;
|
my ($self, $account, $target, $text, $alarm, $duration, $repeat, $owner) = @_;
|
||||||
|
|
||||||
eval {
|
my $id = eval {
|
||||||
my $sth = $self->{dbh}->prepare('INSERT INTO Reminders (account, target, text, alarm, duration, repeat, created_on, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?)');
|
my $sth = $self->{dbh}->prepare('INSERT INTO Reminders (account, target, text, alarm, duration, repeat, created_on, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?)');
|
||||||
$sth->execute($account, $target, $text, $alarm, $duration, $repeat, scalar gettimeofday, $owner);
|
$sth->execute($account, $target, $text, $alarm, $duration, $repeat, scalar gettimeofday, $owner);
|
||||||
|
return $self->{dbh}->sqlite_last_insert_rowid;
|
||||||
};
|
};
|
||||||
|
|
||||||
if ($@) {
|
if ($@) {
|
||||||
$self->{pbot}->{logger}->log("Add reminder failed: $@");
|
$self->{pbot}->{logger}->log("Add reminder failed: $@");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$self->{pbot}->{timer}->enqueue_event(
|
||||||
|
sub {
|
||||||
|
my ($event) = @_;
|
||||||
|
$self->do_reminder($id, $event);
|
||||||
|
},
|
||||||
|
$duration, "reminder $id", $repeat
|
||||||
|
);
|
||||||
|
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub delete_reminder {
|
||||||
|
my ($self, $id) = @_;
|
||||||
|
return if not $self->{dbh};
|
||||||
|
|
||||||
|
eval {
|
||||||
|
my $sth = $self->{dbh}->prepare('DELETE FROM Reminders WHERE id = ?');
|
||||||
|
$sth->execute($id);
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($@) {
|
||||||
|
$self->{pbot}->{logger}->log("Delete reminder $id failed: $@");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->{pbot}->{timer}->dequeue_event("reminder $id");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +194,7 @@ sub get_reminder {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if ($@) {
|
if ($@) {
|
||||||
$self->{pbot}->{logger}->log("List reminders failed: $@");
|
$self->{pbot}->{logger}->log("Get reminder failed: $@");
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
return $reminder;
|
return $reminder;
|
||||||
@ -144,27 +210,55 @@ sub get_reminders {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if ($@) {
|
if ($@) {
|
||||||
$self->{pbot}->{logger}->log("List reminders failed: $@");
|
$self->{pbot}->{logger}->log("Get reminders failed: $@");
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $reminders;
|
return $reminders;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub delete_reminder {
|
sub do_reminder {
|
||||||
my ($self, $id) = @_;
|
my ($self, $id, $event) = @_;
|
||||||
return if not $self->{dbh};
|
|
||||||
|
|
||||||
eval {
|
my $reminder = $self->get_reminder($id);
|
||||||
my $sth = $self->{dbh}->prepare('DELETE FROM Reminders WHERE id = ?');
|
|
||||||
$sth->execute($id);
|
|
||||||
};
|
|
||||||
|
|
||||||
if ($@) {
|
if (not defined $reminder) {
|
||||||
$self->{pbot}->{logger}->log("Delete reminder $id failed: $@");
|
$self->{pbot}->{logger}->log("Queued reminder $id no longer exists.\n");
|
||||||
return 0;
|
$event->{repeating} = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $nick;
|
||||||
|
if (not defined $reminder->{target}) {
|
||||||
|
# ensures we get the current nick of the person
|
||||||
|
my $hostmask = $self->{pbot}->{messagehistory}->{database}->find_most_recent_hostmask($reminder->{account});
|
||||||
|
($nick) = $hostmask =~ /^([^!]+)!/;
|
||||||
|
|
||||||
|
# try again if the person isn't around yet
|
||||||
|
if (not $self->{pbot}->{nicklist}->is_present_any_channel($nick)) {
|
||||||
|
$event->{interval} = 300;
|
||||||
|
$event->{repeating} = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $text = "Reminder: $reminder->{text}";
|
||||||
|
my $target = $reminder->{target} // $nick;
|
||||||
|
$self->{pbot}->{conn}->privmsg($target, $text);
|
||||||
|
|
||||||
|
$self->{pbot}->{logger}->log("Reminded $target about \"$text\"\n");
|
||||||
|
|
||||||
|
if ($reminder->{repeat} > 0) {
|
||||||
|
$reminder->{repeat}--;
|
||||||
|
$reminder->{alarm} = gettimeofday + $reminder->{duration};
|
||||||
|
my $data = { repeat => $reminder->{repeat}, alarm => $reminder->{alarm} };
|
||||||
|
$self->update_reminder($reminder->{id}, $data);
|
||||||
|
$event->{interval} = $reminder->{duration};
|
||||||
|
$event->{repeating} = 1;
|
||||||
|
} else {
|
||||||
|
$self->delete_reminder($reminder->{id});
|
||||||
|
$event->{repeating} = 0;
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub remindme {
|
sub remindme {
|
||||||
@ -272,14 +366,9 @@ sub remindme {
|
|||||||
if (not $self->{pbot}->{channels}->is_active($target)) { return "I'm not active in channel $target."; }
|
if (not $self->{pbot}->{channels}->is_active($target)) { return "I'm not active in channel $target."; }
|
||||||
}
|
}
|
||||||
|
|
||||||
print "alarm: $alarm\n";
|
|
||||||
|
|
||||||
my ($length, $error) = $self->{pbot}->{parsedate}->parsedate($alarm);
|
my ($length, $error) = $self->{pbot}->{parsedate}->parsedate($alarm);
|
||||||
|
|
||||||
print "length: $length, error: $error!\n";
|
|
||||||
return $error if $error;
|
return $error if $error;
|
||||||
|
|
||||||
# I don't know how I feel about enforcing arbitrary time restrictions
|
|
||||||
if ($length > 31536000 * 10) { return "Come on now, I'll be dead by then."; }
|
if ($length > 31536000 * 10) { return "Come on now, I'll be dead by then."; }
|
||||||
|
|
||||||
if (not defined $admininfo and $length < 60) { return "Time must be a minimum of 60 seconds."; }
|
if (not defined $admininfo and $length < 60) { return "Time must be a minimum of 60 seconds."; }
|
||||||
@ -298,56 +387,8 @@ sub remindme {
|
|||||||
if (@$reminders >= 3) { return "You may only set 3 reminders at a time. Use `remindme -d id` to remove a reminder."; }
|
if (@$reminders >= 3) { return "You may only set 3 reminders at a time. Use `remindme -d id` to remove a reminder."; }
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($self->add_reminder($account, $target, $text, $alarm, $length, $repeat, "$nick!$user\@$host")) { return "Reminder added."; }
|
if (my $id = $self->add_reminder($account, $target, $text, $alarm, $length, $repeat, "$nick!$user\@$host")) { return "Reminder $id added."; }
|
||||||
else { return "Failed to add reminder."; }
|
else { return "Failed to add reminder."; }
|
||||||
}
|
}
|
||||||
|
|
||||||
sub check_reminders {
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
return if not $self->{dbh};
|
|
||||||
|
|
||||||
my $reminders = eval {
|
|
||||||
my $sth = $self->{dbh}->prepare('SELECT * FROM Reminders WHERE alarm <= ?');
|
|
||||||
$sth->execute(scalar gettimeofday);
|
|
||||||
return $sth->fetchall_arrayref({});
|
|
||||||
};
|
|
||||||
|
|
||||||
if ($@) {
|
|
||||||
$self->{pbot}->{logger}->log("Check reminders failed: $@");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $reminder (@$reminders) {
|
|
||||||
# ensures we get the current nick of the person
|
|
||||||
my $hostmask = $self->{pbot}->{messagehistory}->{database}->find_most_recent_hostmask($reminder->{account});
|
|
||||||
my ($nick) = $hostmask =~ /^([^!]+)!/;
|
|
||||||
|
|
||||||
# delete this reminder if it's expired by 31 days
|
|
||||||
if (gettimeofday - $reminder->{alarm} >= 86400 * 31) {
|
|
||||||
$self->{pbot}->{logger}->log("Deleting expired reminder: $reminder->{id}) $reminder->{text} set by $reminder->{created_by}\n");
|
|
||||||
$self->delete_reminder($reminder->{id});
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
# don't execute this reminder if the person isn't around yet
|
|
||||||
next if not $self->{pbot}->{nicklist}->is_present_any_channel($nick);
|
|
||||||
|
|
||||||
my $text = "Reminder: $reminder->{text}";
|
|
||||||
my $target = $reminder->{target} // $nick;
|
|
||||||
$self->{pbot}->{conn}->privmsg($target, $text);
|
|
||||||
|
|
||||||
$self->{pbot}->{logger}->log("Reminded $target about \"$text\"\n");
|
|
||||||
|
|
||||||
if ($reminder->{repeat} > 0) {
|
|
||||||
$reminder->{repeat}--;
|
|
||||||
$reminder->{alarm} = gettimeofday + $reminder->{duration};
|
|
||||||
my $data = {repeat => $reminder->{repeat}, alarm => $reminder->{alarm}};
|
|
||||||
$self->update_reminder($reminder->{id}, $data);
|
|
||||||
} else {
|
|
||||||
$self->delete_reminder($reminder->{id});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
Loading…
Reference in New Issue
Block a user