aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.env.example4
-rw-r--r--config/config.go49
-rw-r--r--handlers/messageHandlers/poketwoHandler.go108
-rw-r--r--yuzaki/main.go64
4 files changed, 164 insertions, 61 deletions
diff --git a/.env.example b/.env.example
index 9dc61af..d88b751 100644
--- a/.env.example
+++ b/.env.example
@@ -4,3 +4,7 @@ DISCORD_BOT_TOKEN=YOUR_DISCORD_BOT_TOKEN
DATABASE_DRIVER=SQLITE # POSTGRES | MYSQL | SQLITE | MSSQL
DSN=YOUR_DATABASE_DSN # Example: sqlite://yuzaki.db
+
+
+# Guild Specific Configuration
+POKETWO_CHANNELS= # Comma separated list of channels to listen for Poketwo spawns
diff --git a/config/config.go b/config/config.go
index 4f7a666..1d78fea 100644
--- a/config/config.go
+++ b/config/config.go
@@ -8,10 +8,15 @@ import (
"github.com/joho/godotenv"
)
+var BotConfig *Config
+
type Config struct {
- DiscordToken string
- DataSourceName string
- DatabaseDriver string
+ DiscordToken string
+ DataSourceName string
+ DatabaseDriver string
+ ConfiguredChannels struct {
+ PoketwoSpawns []string
+ }
}
var validDBDrivers = map[string]bool{
@@ -21,12 +26,14 @@ var validDBDrivers = map[string]bool{
"mssql": true,
}
-func Load() (*Config, error) {
+func Load() error {
if err := godotenv.Load(); err != nil {
- return nil, fmt.Errorf("loading env file: %w", err)
+ return fmt.Errorf("loading env file: %w", err)
}
config := &Config{}
+
+ // Basic string variables
requiredVars := map[string]*string{
"DISCORD_BOT_TOKEN": &config.DiscordToken,
"DSN": &config.DataSourceName,
@@ -36,16 +43,24 @@ func Load() (*Config, error) {
for envKey, configVar := range requiredVars {
value, err := getEnv(envKey)
if err != nil {
- return nil, fmt.Errorf("getting %s: %w", envKey, err)
+ return fmt.Errorf("getting %s: %w", envKey, err)
}
*configVar = value
}
+ channels, err := getEnvStringSlice("POKETWO_CHANNELS")
+ if err != nil {
+ return fmt.Errorf("getting POKETWO_CHANNELS: %w", err)
+ }
+ config.ConfiguredChannels.PoketwoSpawns = channels
+ fmt.Println(config.ConfiguredChannels.PoketwoSpawns)
+
if err := validateConfig(config); err != nil {
- return nil, fmt.Errorf("validating config: %w", err)
+ return fmt.Errorf("validating config: %w", err)
}
- return config, nil
+ BotConfig = config
+ return nil
}
func validateConfig(config *Config) error {
@@ -74,6 +89,24 @@ func getEnv(key string) (string, error) {
return strings.TrimSpace(value), nil
}
+func getEnvStringSlice(key string) ([]string, error) {
+ value, err := getEnv(key)
+ if err != nil {
+ return nil, err
+ }
+
+ if value == "" {
+ return []string{}, nil
+ }
+
+ items := strings.Split(value, ",")
+ // Trim spaces from each item
+ for i, item := range items {
+ items[i] = strings.TrimSpace(item)
+ }
+ return items, nil
+}
+
// Future implementation for getting other types of environment variables
// func getEnvInt(key string) (int, error) {
// value, err := getEnv(key)
diff --git a/handlers/messageHandlers/poketwoHandler.go b/handlers/messageHandlers/poketwoHandler.go
index f124e02..3ceb83b 100644
--- a/handlers/messageHandlers/poketwoHandler.go
+++ b/handlers/messageHandlers/poketwoHandler.go
@@ -4,14 +4,12 @@ import (
"fmt"
"strings"
"time"
+ "yuzaki/config"
"github.com/bwmarrin/discordgo"
)
-var (
- poketwoID = "716390085896962058"
- poketwoChannels = []string{"1307335103508254844", "1307335132046168074"}
-)
+const poketwoID = "716390085896962058" // Pokétwo's user ID; TODO: Move to config?
func PoketwoHandler(s *discordgo.Session, m *discordgo.MessageCreate) {
isAllowed := isAllowedChannel(m.ChannelID)
@@ -23,61 +21,75 @@ func PoketwoHandler(s *discordgo.Session, m *discordgo.MessageCreate) {
return
}
- isCommand := strings.HasPrefix(strings.ToLower(m.Content), "p!") ||
+ if isPoketwoCommand(m) && !isAllowed {
+ handleUnauthorizedCommand(s, m)
+ }
+}
+
+func isPoketwoCommand(m *discordgo.MessageCreate) bool {
+ return strings.HasPrefix(strings.ToLower(m.Content), "p!") ||
(len(m.Mentions) > 0 && m.Mentions[0].ID == poketwoID)
+}
- if isCommand && !isAllowed {
- channel, err := s.Channel(m.ChannelID)
- if err != nil {
- return
- }
+func handleUnauthorizedCommand(s *discordgo.Session, m *discordgo.MessageCreate) {
+ channel, err := s.Channel(m.ChannelID)
+ if err != nil {
+ return
+ }
- fmt.Printf("%s#%s sent a Poketwo command in #%s - deleting\n",
- m.Author.Username, m.Author.Discriminator, channel.Name)
+ fmt.Printf("%s#%s sent a Poketwo command in #%s - deleting\n",
+ m.Author.Username, m.Author.Discriminator, channel.Name)
- go func() {
- time.Sleep(1 * time.Second)
- s.ChannelMessageDelete(m.ChannelID, m.ID)
- }()
-
- var channelMentions string
- for i, channelID := range poketwoChannels {
- if i == len(poketwoChannels)-1 && i > 0 {
- channelMentions += "or "
- }
- channelMentions += fmt.Sprintf("<#%s>", channelID)
- if i < len(poketwoChannels)-2 {
- channelMentions += ", "
- }
- }
+ sendRedirectMessage(s, m.Author.ID, m.ChannelID)
- _, err = s.ChannelMessageSend(m.ChannelID,
- fmt.Sprintf("<@%s>, please use %s for Pokétwo commands. If you need roles, visit <id:customize> to get them.",
- m.Author.ID, channelMentions))
+ go deleteMessageWithDelay(s, m.ChannelID, m.ID)
+ go cleanupPoketwoResponse(s, m.ChannelID)
+}
- if err != nil {
- return
- }
+func sendRedirectMessage(s *discordgo.Session, authorID, channelID string) {
+ channelMentions := formatChannelMentions()
+ message := fmt.Sprintf("<@%s>, please use %s for Pokétwo commands. If you need roles, visit <id:customize> to get them.",
+ authorID, channelMentions)
- go func() {
- time.Sleep(1 * time.Second)
- messages, err := s.ChannelMessages(m.ChannelID, 5, "", "", "")
- if err != nil {
- return
- }
-
- for _, msg := range messages {
- if msg.Author.ID == poketwoID {
- s.ChannelMessageDelete(m.ChannelID, msg.ID)
- break
- }
- }
- }()
+ s.ChannelMessageSend(channelID, message)
+}
+
+func formatChannelMentions() string {
+ var mentions []string
+ for _, channelID := range config.BotConfig.ConfiguredChannels.PoketwoSpawns {
+ mentions = append(mentions, fmt.Sprintf("<#%s>", channelID))
+ }
+
+ if len(mentions) > 1 {
+ lastMention := mentions[len(mentions)-1]
+ mentions = mentions[:len(mentions)-1]
+ return strings.Join(mentions, ", ") + " or " + lastMention
+ }
+ return mentions[0]
+}
+
+func cleanupPoketwoResponse(s *discordgo.Session, channelID string) {
+ time.Sleep(1 * time.Second)
+ messages, err := s.ChannelMessages(channelID, 5, "", "", "")
+ if err != nil {
+ return
+ }
+
+ for _, msg := range messages {
+ if msg.Author.ID == poketwoID {
+ s.ChannelMessageDelete(channelID, msg.ID)
+ break
+ }
}
}
+func deleteMessageWithDelay(s *discordgo.Session, channelID, messageID string) {
+ time.Sleep(2 * time.Second)
+ s.ChannelMessageDelete(channelID, messageID)
+}
+
func isAllowedChannel(channelID string) bool {
- for _, channel := range poketwoChannels {
+ for _, channel := range config.BotConfig.ConfiguredChannels.PoketwoSpawns {
if channelID == channel {
return true
}
diff --git a/yuzaki/main.go b/yuzaki/main.go
index c54962d..ea548b8 100644
--- a/yuzaki/main.go
+++ b/yuzaki/main.go
@@ -13,18 +13,16 @@ import (
)
var (
- configuration *config.Config
- session *discordgo.Session
+ session *discordgo.Session
)
func init() {
var err error
- configuration, err = config.Load()
- if err != nil {
+ if err = config.Load(); err != nil {
log.Fatalf("loading config: %v", err)
}
- session, err = discordgo.New("Bot " + configuration.DiscordToken)
+ session, err = discordgo.New("Bot " + config.BotConfig.DiscordToken)
if err != nil {
log.Fatalf("creating discord session: %v", err)
}
@@ -67,4 +65,60 @@ func ready(s *discordgo.Session, event *discordgo.Ready) {
log.Printf("error setting status: %v", err)
}
log.Println("Bot is now running. Press CTRL-C to exit.")
+
+ // On guild 1009009522767052860, assign all users a role with role id 1307471288415162428
+ // var rolesAssigned, rolesSkipped int
+ // guild, err := s.Guild("1009009522767052860")
+ // if err != nil {
+ // log.Printf("error getting guild: %v", err)
+ // return
+ // }
+
+ // var lastMemberID string
+ // for {
+ // members, err := s.GuildMembers(guild.ID, lastMemberID, 1000)
+ // if err != nil {
+ // log.Printf("error getting guild members: %v", err)
+ // return
+ // }
+ // if len(members) == 0 {
+ // break
+ // }
+
+ // for _, member := range members {
+ // // skip if bot
+ // if member.User.Bot {
+ // continue
+ // }
+
+ // // Check if member already has the role
+ // hasRole := false
+ // for _, roleID := range member.Roles {
+ // if roleID == "1307471288415162428" {
+ // hasRole = true
+ // break
+ // }
+ // }
+
+ // if hasRole {
+ // log.Printf("Skipping role assignment for %s (%s) - already has role", member.User.Username, member.User.ID)
+ // rolesSkipped++
+ // continue
+ // }
+
+ // if err := s.GuildMemberRoleAdd(guild.ID, member.User.ID, "1307471288415162428"); err != nil {
+ // log.Printf("error adding role to %s (%s): %v", member.User.Username, member.User.ID, err)
+ // continue
+ // }
+ // log.Printf("Assigned role to %s (%s)", member.User.Username, member.User.ID)
+ // rolesAssigned++
+ // }
+
+ // if len(members) < 1000 {
+ // break
+ // }
+ // lastMemberID = members[len(members)-1].User.ID
+ // }
+
+ // log.Printf("Operation complete: Assigned roles to %d members, skipped %d members", rolesAssigned, rolesSkipped)
}