diff --git a/bot/bot.go b/bot/bot.go index 11f6407..5e760ab 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -6,6 +6,7 @@ import ( "fmt" "log" "os" + "time" "dustin-ward/AdventOfCodeBot/data" @@ -14,7 +15,7 @@ import ( ) var s *discordgo.Session -var C *map[string]*data.Channel +var C map[string]*data.Channel var crn *cron.Cron var adminPerm int64 = 0 @@ -107,7 +108,7 @@ func InitSession() (*discordgo.Session, error) { if _, err := os.Stat("./channels.json"); errors.Is(err, os.ErrNotExist) { log.Println("Info: no channel config file found") - *C = make(map[string]*data.Channel, 3) + C = make(map[string]*data.Channel, 3) } else { // Read channel configs from file (Not an ideal storage method...) b, err := os.ReadFile("./channels.json") @@ -126,6 +127,7 @@ func InitSession() (*discordgo.Session, error) { } func TakeDown() error { + log.Println("Shutting Down...") crn.Stop() // Save channel configurations @@ -153,7 +155,7 @@ func RegisterCommands() ([]*discordgo.ApplicationCommand, error) { } func SetupNotifications() error { - crn = cron.New() + crn = cron.NewWithLocation(time.UTC) // Cronjob for 4:30am UTC (11:30pm EST) if err := crn.AddFunc("0 30 4 * * *", problemNotification); err != nil { diff --git a/bot/commands.go b/bot/commands.go index e986a11..15e588c 100644 --- a/bot/commands.go +++ b/bot/commands.go @@ -25,7 +25,7 @@ func leaderboard(s *discordgo.Session, i *discordgo.InteractionCreate) { channel, err := getChannel(i.GuildID) if err != nil { log.Println("Error:", fmt.Errorf("leaderboard: %v", err)) - respondWithError(s, i, "Your server has not been correctly configured!") + respondWithError(s, i, "Your server has not been correctly configured! šŸ› ļø Use /configure-server") return } @@ -84,9 +84,9 @@ func leaderboard(s *discordgo.Session, i *discordgo.InteractionCreate) { // Create embed object embeds := make([]*discordgo.MessageEmbed, 1) embeds[0] = &discordgo.MessageEmbed{ - URL: "https://adventofcode.com/2022/private/view/" + channel.Leaderboard, + URL: "https://adventofcode.com/2023/leaderboard/private/view/" + channel.Leaderboard, Type: discordgo.EmbedTypeRich, - Title: "šŸŽ„ 2022 Leaderboard šŸŽ„", + Title: "šŸŽ„ 2023 Leaderboard šŸŽ„", Color: 0x127C06, Footer: &discordgo.MessageEmbedFooter{ Text: "Leaderboard as of " + time.Now().Format("2006/01/02 3:4:5pm"), @@ -126,7 +126,7 @@ func configure(s *discordgo.Session, i *discordgo.InteractionCreate) { } // Add to local memory - (*C)[i.GuildID] = &ch + C[i.GuildID] = &ch // Write to file b, err := json.Marshal(C) @@ -142,6 +142,13 @@ func configure(s *discordgo.Session, i *discordgo.InteractionCreate) { return } + log.Println("Attempting to fetch data for leaderboard " + ch.Leaderboard + "...") + if err := data.FetchData(ch.Leaderboard, ch.SessionToken, ch.Leaderboard); err != nil { + log.Println("Error:", fmt.Errorf("fetch: %w", err)) + } else { + log.Println(ch.Leaderboard, "success!") + } + respond(s, i, "Server successfully configured!") } @@ -151,7 +158,8 @@ func startCountdown(s *discordgo.Session, i *discordgo.InteractionCreate) { ch, err := getChannel(i.GuildID) if err != nil { log.Println("Error:", fmt.Errorf("start-notifications: %v", err)) - respondWithError(s, i, "Error: Internal server error...") + respondWithError(s, i, "Your server has not been correctly configured! šŸ› ļø Use /configure-server") + return } ch.NotificationsOn = true @@ -164,7 +172,8 @@ func stopCountdown(s *discordgo.Session, i *discordgo.InteractionCreate) { ch, err := getChannel(i.GuildID) if err != nil { log.Println("Error:", fmt.Errorf("start-notifications: %v", err)) - respondWithError(s, i, "Error: Internal server error...") + respondWithError(s, i, "Your server has not been correctly configured! šŸ› ļø Use /configure-server") + return } ch.NotificationsOn = false @@ -176,11 +185,21 @@ func checkCountdown(s *discordgo.Session, i *discordgo.InteractionCreate) { ch, err := getChannel(i.GuildID) if err != nil { log.Println("Error:", fmt.Errorf("check-notifications: %w", err)) + respondWithError(s, i, "Your server has not been correctly configured! šŸ› ļø Use /configure-server") + return + } + + next, err := NextNotification() + if err != nil { + log.Println("Error:", fmt.Errorf("check-notifications: %w", err)) + respondWithError(s, i, "Internal Error šŸ’€ Please contact @shrublord") + return } + day := time.Now().AddDate(0, 0, 1).Day() var message string if ch.NotificationsOn { - message = fmt.Sprintf("Notifications for server id: %s are enabled in channel: %s!", ch.GuildId, ch.ChannelId) + message = fmt.Sprintf("Notifications for server id: %s are enabled in channel: %s!\n\nā° Next notification: (Day %d)", ch.GuildId, ch.ChannelId, next.Unix(), day) } else { message = "Notifications are not enabled currently..." } diff --git a/bot/notifications.go b/bot/notifications.go index da185ba..8c995df 100644 --- a/bot/notifications.go +++ b/bot/notifications.go @@ -7,20 +7,20 @@ import ( ) const ( - ProblemUrl = "https://adventofcode.com/2022/day/" + ProblemUrl = "https://adventofcode.com/2023/day/" ) func problemNotification() { - day := time.Now().AddDate(0, 0, 1).Day() - 1 + day := time.Now().AddDate(0, 0, 1).Day() // For each registered channel - for _, ch := range *C { + for _, ch := range C { if ch.NotificationsOn { log.Println("Info: sending day", day, "notification in channel", ch.ChannelId) // Create message object messageString := fmt.Sprintf( - "šŸŽ„ <@&%s> šŸŽ„\nThe problem for Day %d will be released soon! ()\nYou can see the problem statement here when its up: https://adventofcode.com/2022/day/%d", + "šŸŽ„ <@&%s> šŸŽ„\nThe problem for Day %d will be released soon! ()\nYou can see the problem statement here when its up: https://adventofcode.com/2023/day/%d", ch.RoleId, day, time.Now().Unix()+(int64(30)*60), @@ -37,3 +37,11 @@ func problemNotification() { } } } + +func NextNotification() (time.Time, error) { + entries := crn.Entries() + if len(entries) != 1 { + return time.Now(), fmt.Errorf("invalid number of cron entries") + } + return (*entries[0]).Next, nil +} diff --git a/bot/util.go b/bot/util.go index 0c84542..91c394c 100644 --- a/bot/util.go +++ b/bot/util.go @@ -9,7 +9,7 @@ import ( ) func getChannel(guildId string) (*data.Channel, error) { - ch, ok := (*C)[guildId] + ch, ok := C[guildId] if !ok { return nil, fmt.Errorf("channel not found") } diff --git a/data/data.go b/data/data.go index 322e13a..23b31a2 100644 --- a/data/data.go +++ b/data/data.go @@ -9,7 +9,7 @@ import ( ) const ( - AocURL = "https://adventofcode.com/2022/leaderboard/private/view/" + AocURL = "https://adventofcode.com/2023/leaderboard/private/view/" ) func GetData(boardId string) (*Data, error) { diff --git a/main.go b/main.go index 6a929a7..f83ee86 100644 --- a/main.go +++ b/main.go @@ -34,7 +34,7 @@ func main() { log.Fatal("Fatal:", fmt.Errorf("main: %w", err)) } defer Session.Close() - log.Println("Session initialized for", len(*bot.C), "servers") + log.Println("Session initialized for", len(bot.C), "servers") // Register commands r, err := bot.RegisterCommands() @@ -51,7 +51,7 @@ func main() { } // Continually fetch advent of code data every 15 minutes - for _, ch := range *bot.C { + for _, ch := range bot.C { go func(channel *data.Channel) { for { log.Println("Attempting to fetch data for leaderboard " + channel.Leaderboard + "...")