From 352a41b723f098445ffa966cab812fb07ce10a53 Mon Sep 17 00:00:00 2001 From: Sean Hinchee Date: Mon, 7 May 2018 00:26:37 +0000 Subject: [PATCH] most of remindme done; need to fix time interval counting --- TODO | 3 ++ main.go | 7 +--- mux.go | 2 + x/mux/config.go | 9 ++-- x/mux/remind.go | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 119 insertions(+), 9 deletions(-) create mode 100644 x/mux/remind.go diff --git a/TODO b/TODO index b57fbaba8a23ed35d6a2ee311598a300055bb82a..42695d87ac3bc2f5e31b212f9d96f3e182c67caf 100644 --- a/TODO +++ b/TODO @@ -14,3 +14,6 @@ Problems * Move feed caching to another file than the .cfg (seriously this is a fcking mess) * Scripts should have a universal config such as an environment variable (more portable/configurable) * No role/user restrictions (should be a txt file of admin/mod users, maybe) +* Reminders don't persist between bot reboots +* Reminders should be hashed and deletable/modifiable by the creating user +* Reminders should use a min heap diff --git a/main.go b/main.go index 16019a5177ec1f46b303cd4cca6e8ce86d5af4fb..637b0f4fb74e076a22dffee5ca99c6a720adb519 100644 --- a/main.go +++ b/main.go @@ -77,12 +77,9 @@ func main() { } // Init Mux daemons - // Problem child Listener is -// go mux.Listener() - -// go mux.CommMux() -// go CommMux() go mux.Config.Init(Session) + mux.RemChan = make(chan mux.Reminder, 5) + go mux.Reminders() Session.UpdateStatus(0, "with #cat-v") diff --git a/mux.go b/mux.go index c1d56841a071781f88625cd3e5887e04b1586a71..d7d2e63b6e275a702eaf8c561bc42dbd02cb4a81 100644 --- a/mux.go +++ b/mux.go @@ -43,4 +43,6 @@ func init() { Router.Route("beer", ":beer:", Router.Beer) Router.Route("whiskey", ":tumbler_glass:", Router.Whiskey) + + Router.Route("remindme", "Set a reminder for a given time interval ([int][hmsdny] [reminder]).", Router.RemindMe) } diff --git a/x/mux/config.go b/x/mux/config.go index b1c2ac4a0deeaacb67483429d16b3aa1dfd027a9..3e1092747e7221d5eae283fabf085c4df9b492a1 100644 --- a/x/mux/config.go +++ b/x/mux/config.go @@ -11,6 +11,11 @@ import ( "github.com/bwmarrin/discordgo" ) + +// Global variables are bad +var Config Configuration +var Session *discordgo.Session + // Stores subscription information for channels related to RSS feeds type Subscription struct { ChanID string @@ -114,7 +119,3 @@ func (c *Configuration) Setup() { fmt.Println(err) } } - -// Global variables are bad -var Config Configuration -var Session *discordgo.Session diff --git a/x/mux/remind.go b/x/mux/remind.go new file mode 100644 index 0000000000000000000000000000000000000000..96f8c8c8290027e53c40fa9ba068db5e1bbb4de4 --- /dev/null +++ b/x/mux/remind.go @@ -0,0 +1,107 @@ +package mux + +import ( + "github.com/bwmarrin/discordgo" + "time" +sc "strconv" + "container/list" +) + + +// Channel for posting reminders -- inits in main +var RemChan chan Reminder + +// Stores a reminder to be posted to a given user +type Reminder struct { + NotifyAfter time.Time + Reason string + User discordgo.User + ChannelID string + Session discordgo.Session +} + +// Reminder daemon process that gets started in main and listens on RemChan +func Reminders() { + // Should be a heap and persist across reboots + rems := list.New() + for { + select { + case r := <- RemChan: + // Handle new reminder + rems.PushBack(r) + + default: + // Check for any due reminders + for e := rems.Front(); ; e = e.Next() { + if e == nil { + break + } + + r, _ := e.Value.(Reminder) + if time.Now().After(r.NotifyAfter) { + // If we have passed the time of desired notification + r.Session.ChannelMessageSend(r.ChannelID, r.Reason) + rems.Remove(e) + } + } + + time.Sleep(50 * time.Millisecond) + } + } +} + +// Reminds a user about a given reason after a specified time interval has passed +func (m *Mux) RemindMe(ds *discordgo.Session, dm *discordgo.Message, ctx *Context) { + resp := "" + + // remindme 20m dothing + if len(ctx.Fields) >= 3 { + var rem Reminder + periodLong := ctx.Fields[len(ctx.Fields)-2] + reasonLong := ctx.Fields[2 : len(ctx.Fields)] + rem.User = *dm.Author + rem.ChannelID = dm.ChannelID + rem.Session = *ds + + reason := "" + for _, v := range reasonLong { + reason += v + reason += " " + } + rem.Reason = reason + + interval := periodLong[len(periodLong)-1] + period, err := sc.Atoi(periodLong[:len(periodLong)-2]) + if err != nil { + resp += "Invalid period value." + goto SEND + } + + var dur time.Duration + switch interval { + case 's': + dur = time.Second + case 'm': + dur = time.Minute + case 'h': + dur = time.Hour + default: + resp += "Invalid interval specifier." + goto SEND + } + + rem.NotifyAfter = time.Now().Add(time.Duration(period) * dur) + + RemChan <- rem + + } else { + resp += "Please specify a time operator in the form [int][type] and a description (20h do thing)." + } + + SEND: + resp += "\n" + + ds.ChannelMessageSend(dm.ChannelID, resp) + + return +}