mirror of
https://github.com/pragma-/pbot.git
synced 2024-12-23 19:22:40 +01:00
Plugins/RemindMe: reminders set to an absolute time now repeat at correct intervals
This commit is contained in:
parent
fe37658d97
commit
726cb06963
@ -57,11 +57,11 @@ sub cmd_remindme {
|
||||
return "Internal error.";
|
||||
}
|
||||
|
||||
my $usage = "Usage: remindme -t time message [-c channel] [-r repeat count] | remindme -l [nick] | remindme -d id";
|
||||
my $usage = "Usage: remindme -t <time> <message> [-r <repeat count>] [-c <channel>] | remindme -l [nick] | remindme -d <id>";
|
||||
|
||||
return $usage if not length $context->{arguments};
|
||||
|
||||
my ($channel, $repeats, $text, $alarm, $list_reminders, $delete_id);
|
||||
my ($channel, $repeats, $text, $time, $list_reminders, $delete_id);
|
||||
|
||||
my $getopt_error;
|
||||
local $SIG{__WARN__} = sub {
|
||||
@ -75,7 +75,7 @@ sub cmd_remindme {
|
||||
GetOptionsFromArray(
|
||||
\@opt_args,
|
||||
'r:i' => \$repeats,
|
||||
't:s' => \$alarm,
|
||||
't:s' => \$time,
|
||||
'c:s' => \$channel,
|
||||
'm:s' => \$text,
|
||||
'l:s' => \$list_reminders,
|
||||
@ -86,13 +86,16 @@ sub cmd_remindme {
|
||||
|
||||
# option -l was provided; list reminders
|
||||
if (defined $list_reminders) {
|
||||
my $nick_override = $list_reminders if length $list_reminders;
|
||||
# unique internal account id for a hostmask
|
||||
my $account;
|
||||
|
||||
# if arg was provided to -l, list reminders belonging to args
|
||||
my $nick_override = $list_reminders if length $list_reminders;
|
||||
|
||||
if ($nick_override) {
|
||||
# look up account id and hostmask for -l argument
|
||||
my $hostmask;
|
||||
|
||||
# look up account id and hostmask by nickname
|
||||
($account, $hostmask) = $self->{pbot}->{messagehistory}->{database}->find_message_account_by_nick($nick_override);
|
||||
|
||||
if (not $account) {
|
||||
@ -102,13 +105,17 @@ sub cmd_remindme {
|
||||
# capture nick portion of hostmask
|
||||
($nick_override) = $hostmask =~ m/^([^!]+)!/;
|
||||
} else {
|
||||
# look up caller's account id
|
||||
$account = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
|
||||
}
|
||||
|
||||
# get the root parent account id (consolidates nick-changes, etc)
|
||||
$account = $self->{pbot}->{messagehistory}->{database}->get_ancestor_id($account);
|
||||
|
||||
# get the reminders
|
||||
my $reminders = $self->get_reminders($account);
|
||||
|
||||
# list the reminders
|
||||
my $count = 0;
|
||||
my $text = '';
|
||||
my $now = time;
|
||||
@ -125,7 +132,7 @@ sub cmd_remindme {
|
||||
$text .= "$reminder->{id}) $interval";
|
||||
|
||||
if ($reminder->{repeats}) {
|
||||
$text .= " ($reminder->{repeats} repeat" . ($reminder->{repeats} == 1 ? '' : 's') . " left)";
|
||||
$text .= " (repeats every $reminder->{interval}, $reminder->{repeats} more time" . ($reminder->{repeats} == 1 ? '' : 's') . ')';
|
||||
}
|
||||
|
||||
$text .= ": $reminder->{text}\n";
|
||||
@ -186,7 +193,7 @@ sub cmd_remindme {
|
||||
$text .= join ' ', @opt_args;
|
||||
}
|
||||
|
||||
return "Please use -t to specify a time for this reminder." if not $alarm;
|
||||
return "Please use -t to specify a time for this reminder." if not $time;
|
||||
return "Please specify a reminder message." if not $text;
|
||||
|
||||
# option -c was provided; ensure bot is in channel
|
||||
@ -195,7 +202,7 @@ sub cmd_remindme {
|
||||
}
|
||||
|
||||
# parse "5 minutes", "next week", "3pm", etc into seconds
|
||||
my ($seconds, $error) = $self->{pbot}->{parsedate}->parsedate($alarm);
|
||||
my ($seconds, $error) = $self->{pbot}->{parsedate}->parsedate($time);
|
||||
return $error if $error;
|
||||
|
||||
if ($seconds > 31536000 * 10) {
|
||||
@ -218,7 +225,7 @@ sub cmd_remindme {
|
||||
}
|
||||
|
||||
# set timestamp for alarm
|
||||
$alarm = time + $seconds;
|
||||
my $alarm = time + $seconds;
|
||||
|
||||
my $account = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
|
||||
$account = $self->{pbot}->{messagehistory}->{database}->get_ancestor_id($account);
|
||||
@ -236,7 +243,8 @@ sub cmd_remindme {
|
||||
channel => $channel,
|
||||
text => $text,
|
||||
alarm => $alarm,
|
||||
interval => $seconds,
|
||||
interval => $time,
|
||||
seconds => $seconds,
|
||||
repeats => $repeats,
|
||||
owner => $context->{hostmask},
|
||||
);
|
||||
@ -293,28 +301,67 @@ sub do_reminder {
|
||||
$self->{pbot}->{conn}->privmsg($target, $text);
|
||||
|
||||
# log event
|
||||
$self->{pbot}->{logger}->log("Reminded $target about \"$text\"\n");
|
||||
$self->{pbot}->{logger}->log("Reminded $target about \"$text\"; interval: $reminder->{interval}\n");
|
||||
|
||||
# update repeats or delete reminder
|
||||
if ($reminder->{repeats} > 0) {
|
||||
# update reminder
|
||||
$reminder->{repeats}--;
|
||||
$reminder->{alarm} = time + $reminder->{interval};
|
||||
|
||||
# parse interval again to get correct offset in seconds
|
||||
# e.g., if it's 12 pm and they set a repeating reminder for 3 pm then
|
||||
# the interval would be 3h. we don't want the reminder to repeat every
|
||||
# 3h but instead every day at 3 pm. so when this reminder fires at 3 pm,
|
||||
# we reparse the interval "3 pm" again to get 24h, instead of storing 3h.
|
||||
my ($seconds) = $self->{pbot}->{parsedate}->parsedate($reminder->{interval});
|
||||
|
||||
# if timeout is 0 or less, prepend "next" and try again.
|
||||
# e.g., if interval is "10 pm" then at 10:00:00 pm the interval will
|
||||
# parse to 0 seconds, i.e. right now, until it is 10:00:01 pm. we really
|
||||
# want the next 10 pm, 24 hours from right now.
|
||||
if ($seconds <= 0) {
|
||||
my $override;
|
||||
if ($reminder->{interval} =~ m/^\d/) {
|
||||
$override = "tomorrow ";
|
||||
} else {
|
||||
$override = "next ";
|
||||
}
|
||||
|
||||
($seconds) = $self->{pbot}->{parsedate}->parsedate("$override $reminder->{interval}");
|
||||
}
|
||||
|
||||
# update alarm timestamp
|
||||
$reminder->{alarm} = time + $seconds;
|
||||
|
||||
# update reminder in SQLite database
|
||||
my $data = { repeats => $reminder->{repeats}, alarm => $reminder->{alarm} };
|
||||
$self->update_reminder($reminder->{id}, $data);
|
||||
|
||||
# update reminder event in PBot event queue
|
||||
$event->{interval} = $reminder->{interval};
|
||||
$event->{interval} = $seconds;
|
||||
$event->{repeating} = 1;
|
||||
} else {
|
||||
# delete reminder
|
||||
# delete reminder from SQLite database
|
||||
$self->delete_reminder($reminder->{id});
|
||||
|
||||
# tell PBot event queue not to reschedule this reminder
|
||||
$event->{repeating} = 0;
|
||||
}
|
||||
}
|
||||
|
||||
# add a single reminder to the PBot event queue
|
||||
sub enqueue_reminder {
|
||||
my ($self, $reminder, $timeout) = @_;
|
||||
|
||||
$self->{pbot}->{event_queue}->enqueue_event(
|
||||
sub {
|
||||
my ($event) = @_;
|
||||
$self->do_reminder($reminder->{id}, $event);
|
||||
},
|
||||
$timeout, "reminder $reminder->{id}", $reminder->{repeats}
|
||||
);
|
||||
}
|
||||
|
||||
# load all reminders from SQLite database and add them
|
||||
# to PBot's event queue. typically used once at PBot start-up.
|
||||
sub enqueue_reminders {
|
||||
@ -338,18 +385,12 @@ sub enqueue_reminders {
|
||||
|
||||
# delete this reminder if it's expired by approximately 1 year
|
||||
if ($timeout <= -(86400 * 31 * 12)) {
|
||||
$self->{pbot}->{logger}->log("Deleting expired reminder: $reminder->{id}) $reminder->{text} set by $reminder->{created_by}; alarm: $reminder->{alarm} - current time: " . (scalar time) . " = timeout: $timeout\n");
|
||||
$self->{pbot}->{logger}->log("Deleting expired reminder: $reminder->{id}) $reminder->{text} set by $reminder->{created_by}\n");
|
||||
$self->delete_reminder($reminder->{id});
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{pbot}->{event_queue}->enqueue_event(
|
||||
sub {
|
||||
my ($event) = @_;
|
||||
$self->do_reminder($reminder->{id}, $event);
|
||||
},
|
||||
$timeout, "reminder $reminder->{id}", $reminder->{repeats}
|
||||
);
|
||||
$self->enqueue_reminder($reminder, $timeout);
|
||||
}
|
||||
}
|
||||
|
||||
@ -367,7 +408,7 @@ CREATE TABLE IF NOT EXISTS Reminders (
|
||||
text TEXT,
|
||||
alarm NUMERIC,
|
||||
repeats INTEGER,
|
||||
interval NUMERIC,
|
||||
interval TEXT,
|
||||
created_on NUMERIC,
|
||||
created_by TEXT
|
||||
)
|
||||
@ -400,10 +441,11 @@ sub dbi_end {
|
||||
delete $self->{dbh};
|
||||
}
|
||||
|
||||
# add a reminder
|
||||
# add a reminder, to SQLite and the PBot event queue
|
||||
sub add_reminder {
|
||||
my ($self, %args) = @_;
|
||||
|
||||
# add reminder to SQLite database
|
||||
my $id = eval {
|
||||
my $sth = $self->{dbh}->prepare('INSERT INTO Reminders (account, channel, text, alarm, interval, repeats, created_on, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?)');
|
||||
|
||||
@ -421,43 +463,50 @@ sub add_reminder {
|
||||
return $self->{dbh}->sqlite_last_insert_rowid;
|
||||
};
|
||||
|
||||
# check for exception
|
||||
if ($@) {
|
||||
$self->{pbot}->{logger}->log("Add reminder failed: $@");
|
||||
return 0;
|
||||
}
|
||||
|
||||
$self->{pbot}->{event_queue}->enqueue_event(
|
||||
sub {
|
||||
my ($event) = @_;
|
||||
$self->do_reminder($id, $event);
|
||||
},
|
||||
$args{interval}, "reminder $id", $args{repeats}
|
||||
);
|
||||
my $reminder = {
|
||||
id => $id,
|
||||
repeats => $args{repeats},
|
||||
};
|
||||
|
||||
# add reminder to event queue.
|
||||
$self->enqueue_reminder($reminder, $args{seconds});
|
||||
|
||||
# return reminder id
|
||||
return $id;
|
||||
}
|
||||
|
||||
# delete a reminder by its id
|
||||
# delete a reminder by its id, from SQLite and the PBot event queue
|
||||
sub delete_reminder {
|
||||
my ($self, $id) = @_;
|
||||
|
||||
return if not $self->{dbh};
|
||||
|
||||
# remove from SQLite database
|
||||
eval {
|
||||
my $sth = $self->{dbh}->prepare('DELETE FROM Reminders WHERE id = ?');
|
||||
$sth->execute($id);
|
||||
};
|
||||
|
||||
# check for exeption
|
||||
if ($@) {
|
||||
$self->{pbot}->{logger}->log("Delete reminder $id failed: $@");
|
||||
return 0;
|
||||
}
|
||||
|
||||
$self->{pbot}->{event_queue}->dequeue_event("reminder $id");
|
||||
# remove from event queue
|
||||
my $removed = $self->{pbot}->{event_queue}->dequeue_event("reminder $id");
|
||||
|
||||
$self->{pbot}->{logger}->log("RemindMe: dequeued events: $removed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
# update a reminder's metadata
|
||||
# update a reminder's data, in SQLite
|
||||
sub update_reminder {
|
||||
my ($self, $id, $data) = @_;
|
||||
|
||||
@ -488,7 +537,7 @@ sub update_reminder {
|
||||
$self->{pbot}->{logger}->log($@) if $@;
|
||||
}
|
||||
|
||||
# get a single reminder by its id
|
||||
# get a single reminder by its id, from SQLite
|
||||
sub get_reminder {
|
||||
my ($self, $id) = @_;
|
||||
|
||||
@ -506,7 +555,7 @@ sub get_reminder {
|
||||
return $reminder;
|
||||
}
|
||||
|
||||
# get all reminders belonging to a user
|
||||
# get all reminders belonging to an account id, from SQLite
|
||||
sub get_reminders {
|
||||
my ($self, $account) = @_;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user