This commit is contained in:
parent
21e4c434fd
commit
72c6dd6982
12 changed files with 695 additions and 48 deletions
178
internal/plugin/reminder/reminder.go
Normal file
178
internal/plugin/reminder/reminder.go
Normal file
|
@ -0,0 +1,178 @@
|
|||
package reminder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.nakama.town/fmartingr/butterrobot/internal/model"
|
||||
"git.nakama.town/fmartingr/butterrobot/internal/plugin"
|
||||
)
|
||||
|
||||
// Duration regex patterns to match reminders
|
||||
var (
|
||||
remindMePattern = regexp.MustCompile(`(?i)^!remindme\s(\d+)(y|mo|d|h|m|s)$`)
|
||||
)
|
||||
|
||||
// ReminderCreator is an interface for creating reminders
|
||||
type ReminderCreator interface {
|
||||
CreateReminder(platform, channelID, messageID, replyToID, userID, username, content string, triggerAt time.Time) (*model.Reminder, error)
|
||||
}
|
||||
|
||||
// Reminder is a plugin that sets reminders for messages
|
||||
type Reminder struct {
|
||||
plugin.BasePlugin
|
||||
creator ReminderCreator
|
||||
}
|
||||
|
||||
// New creates a new Reminder plugin
|
||||
func New(creator ReminderCreator) *Reminder {
|
||||
return &Reminder{
|
||||
BasePlugin: plugin.BasePlugin{
|
||||
ID: "reminder.remindme",
|
||||
Name: "Remind Me",
|
||||
Help: "Reply to a message with `!remindme <duration>` to set a reminder (e.g., `!remindme 2d` for 2 days, `!remindme 1y` for 1 year).",
|
||||
ConfigRequired: false,
|
||||
},
|
||||
creator: creator,
|
||||
}
|
||||
}
|
||||
|
||||
// OnMessage processes incoming messages
|
||||
func (r *Reminder) OnMessage(msg *model.Message, config map[string]interface{}) []*model.Message {
|
||||
// Only process replies to messages
|
||||
if msg.ReplyTo == "" {
|
||||
return []*model.Message{
|
||||
{
|
||||
Text: "Please reply to a message with `!remindme <duration>` to set a reminder.",
|
||||
Chat: msg.Chat,
|
||||
Channel: msg.Channel,
|
||||
ReplyTo: msg.ID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the message is a reminder command
|
||||
match := remindMePattern.FindStringSubmatch(msg.Text)
|
||||
if match == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Parse the duration
|
||||
amount, err := strconv.Atoi(match[1])
|
||||
if err != nil {
|
||||
return []*model.Message{
|
||||
{
|
||||
Text: "Invalid duration format. Please use a number followed by y (years), mo (months), d (days), h (hours), m (minutes), or s (seconds).",
|
||||
Chat: msg.Chat,
|
||||
Channel: msg.Channel,
|
||||
Author: "bot",
|
||||
FromBot: true,
|
||||
Date: time.Now(),
|
||||
ReplyTo: msg.ID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the trigger time
|
||||
var duration time.Duration
|
||||
unit := match[2]
|
||||
switch strings.ToLower(unit) {
|
||||
case "y":
|
||||
duration = time.Duration(amount) * 365 * 24 * time.Hour
|
||||
case "mo":
|
||||
duration = time.Duration(amount) * 30 * 24 * time.Hour
|
||||
case "d":
|
||||
duration = time.Duration(amount) * 24 * time.Hour
|
||||
case "h":
|
||||
duration = time.Duration(amount) * time.Hour
|
||||
case "m":
|
||||
duration = time.Duration(amount) * time.Minute
|
||||
case "s":
|
||||
duration = time.Duration(amount) * time.Second
|
||||
default:
|
||||
return []*model.Message{
|
||||
{
|
||||
Text: "Invalid duration unit. Please use y (years), mo (months), d (days), h (hours), m (minutes), or s (seconds).",
|
||||
Chat: msg.Chat,
|
||||
Channel: msg.Channel,
|
||||
Author: "bot",
|
||||
FromBot: true,
|
||||
Date: time.Now(),
|
||||
ReplyTo: msg.ID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
triggerAt := time.Now().Add(duration)
|
||||
|
||||
// Determine the username for the reminder
|
||||
username := msg.Author
|
||||
if username == "" {
|
||||
// Try to extract username from message raw data
|
||||
if authorData, ok := msg.Raw["author"].(map[string]interface{}); ok {
|
||||
if name, ok := authorData["username"].(string); ok {
|
||||
username = name
|
||||
} else if name, ok := authorData["name"].(string); ok {
|
||||
username = name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create the reminder
|
||||
_, err = r.creator.CreateReminder(
|
||||
msg.Channel.Platform,
|
||||
msg.Chat,
|
||||
msg.ID,
|
||||
msg.ReplyTo,
|
||||
msg.Author,
|
||||
username,
|
||||
"", // No additional content for now
|
||||
triggerAt,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return []*model.Message{
|
||||
{
|
||||
Text: fmt.Sprintf("Failed to create reminder: %v", err),
|
||||
Chat: msg.Chat,
|
||||
Channel: msg.Channel,
|
||||
Author: "bot",
|
||||
FromBot: true,
|
||||
Date: time.Now(),
|
||||
ReplyTo: msg.ID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Format the acknowledgment message
|
||||
var confirmText string
|
||||
switch strings.ToLower(unit) {
|
||||
case "y":
|
||||
confirmText = fmt.Sprintf("I'll remind you about this message in %d year(s) on %s", amount, triggerAt.Format("Mon, Jan 2, 2006 at 15:04"))
|
||||
case "mo":
|
||||
confirmText = fmt.Sprintf("I'll remind you about this message in %d month(s) on %s", amount, triggerAt.Format("Mon, Jan 2 at 15:04"))
|
||||
case "d":
|
||||
confirmText = fmt.Sprintf("I'll remind you about this message in %d day(s) on %s", amount, triggerAt.Format("Mon, Jan 2 at 15:04"))
|
||||
case "h":
|
||||
confirmText = fmt.Sprintf("I'll remind you about this message in %d hour(s) at %s", amount, triggerAt.Format("15:04"))
|
||||
case "m":
|
||||
confirmText = fmt.Sprintf("I'll remind you about this message in %d minute(s) at %s", amount, triggerAt.Format("15:04"))
|
||||
case "s":
|
||||
confirmText = fmt.Sprintf("I'll remind you about this message in %d second(s)", amount)
|
||||
}
|
||||
|
||||
return []*model.Message{
|
||||
{
|
||||
Text: confirmText,
|
||||
Chat: msg.Chat,
|
||||
Channel: msg.Channel,
|
||||
Author: "bot",
|
||||
FromBot: true,
|
||||
Date: time.Now(),
|
||||
ReplyTo: msg.ID,
|
||||
},
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue