diff --git a/djpianalto.com/goff/goff.go b/djpianalto.com/goff/goff.go index c394748..dc042e0 100644 --- a/djpianalto.com/goff/goff.go +++ b/djpianalto.com/goff/goff.go @@ -59,12 +59,6 @@ func main() { // Add Command Handlers exts.AddCommandHandlers(&handler) - // Start the Error handler in a goroutine - go ErrorHandler(handler.ErrorChannel) - - // Start the Logging handler in a goroutine - go utils.LoggingHandler(utils.LoggingChannel) - //if _, ok := handler.Commands["help"]; !ok { // handler.AddDefaultHelpCommand() //} @@ -78,6 +72,15 @@ func main() { return } + // Start the Error handler in a goroutine + go ErrorHandler(handler.ErrorChannel) + + // Start the Logging handler in a goroutine + go utils.LoggingHandler(utils.LoggingChannel) + + // Start the task handler in a goroutine + go utils.ProcessTasks(dg, 10) + fmt.Println("The Bot is now running.") sc := make(chan os.Signal, 1) signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill) diff --git a/djpianalto.com/goff/utils/database.go b/djpianalto.com/goff/utils/database.go index 1df367d..54cf848 100644 --- a/djpianalto.com/goff/utils/database.go +++ b/djpianalto.com/goff/utils/database.go @@ -77,12 +77,14 @@ func InitializeDatabase() { } _, err = Database.Query("CREATE TABLE IF NOT EXISTS tasks(" + "id serial primary key," + + "type varchar(10) not null" + "content text not null," + "guild_id varchar(30) not null references guilds(id)," + "channel_id varchar(30) not null," + "user_id varchar(30) not null," + "creation_time timestamp not null default NOW()," + - "trigger_time timestamp not null)") + "trigger_time timestamp not null," + + "completed bool not null default false)") if err != nil { fmt.Println(err) } diff --git a/djpianalto.com/goff/utils/tasks.go b/djpianalto.com/goff/utils/tasks.go new file mode 100644 index 0000000..ced2e04 --- /dev/null +++ b/djpianalto.com/goff/utils/tasks.go @@ -0,0 +1,79 @@ +package utils + +import ( + "fmt" + "github.com/bwmarrin/discordgo" + "log" + "time" +) + +type Task struct { + ID int64 + Type string + Content string + GuildID string + ChannelID string + UserID string + CreationTime time.Time + TriggerTime time.Time +} + +func processTask(task *Task, s *discordgo.Session) { + guild, err := s.Guild(task.GuildID) + if err != nil { + log.Print(fmt.Sprintf("Can't find guild with ID %v. Canceling task %v.", task.GuildID, task.ID)) + return + } + channel, err := s.Channel(task.ChannelID) + if err != nil { + log.Print(fmt.Sprintf("Can't find channel with ID %v. Canceling task %v.", task.ChannelID, task.ID)) + return + } + if channel.GuildID != guild.ID { + log.Print(fmt.Sprintf("The channel %v is not in guild %v. Canceling task %v.", channel.Name, guild.Name, task.ID)) + return + } + member, err := s.GuildMember(guild.ID, task.UserID) + if err != nil { + log.Print(fmt.Sprintf("Can't find user with ID %v in guild %v. Canceling task %v.", task.UserID, guild.Name, task.ID)) + return + } + if task.Type == "Reminder" { + msg := fmt.Sprintf("%v REMINDER:\n%v", member.Mention(), task.Content) + s.ChannelMessageSend(channel.ID, msg) + } +} + +func getTasksToRun(s *discordgo.Session) []Task { + query := "SELECT id, type, content, guild_id, channel_id, user_id, creation_time, trigger_time " + + "from tasks where completed is false and trigger_time < $1" + res, err := Database.Query(query, time.Now()) + if err != nil { + log.Println(err) + } + var tasks []Task + for res.Next() { + var t Task + err = res.Scan(&t.ID, &t.Type, &t.Content, &t.GuildID, &t.ChannelID, &t.UserID, &t.CreationTime, &t.TriggerTime) + if err != nil { + log.Println(err) + } + tasks = append(tasks, t) + } + + return tasks +} + +func ProcessTasks(s *discordgo.Session, interval int) { + for { + time.Sleep(time.Duration(interval)) + + tasks := getTasksToRun(s) + + if len(tasks) > 0 { + for _, t := range tasks { + go processTask(&t, s) + } + } + } +}