add shoot command, getVoiceChannelID function
Marco Andronaco andronacomarco@gmail.com
Mon, 30 Sep 2024 16:28:57 +0200
7 files changed,
181 insertions(+),
37 deletions(-)
M
commands.go
→
commands.go
@@ -14,7 +14,8 @@
func InitHandlers() { handlersMap = map[string]BotCommand{ "echo": {ShortCode: "e", Handler: handleEcho, Help: "echoes a message"}, - "prefix": {ShortCode: "pre", Handler: handlePrefix, Help: "sets the bot's prefix"}, + "shoot": {ShortCode: "sh", Handler: handleShoot, Help: "shoots a random user in your voice channel"}, + "prefix": {Handler: handlePrefix, Help: "sets the bot's prefix"}, "help": {ShortCode: "h", Handler: handleHelp, Help: "shows this help message"}, }@@ -26,26 +27,18 @@ shortCommands[botCommand.ShortCode] = command
} } -func handleHelp(args []string, s *discordgo.Session, m *discordgo.MessageCreate) string { - helpText := "**Bot commands:**\n" - for command, botCommand := range handlersMap { - helpText += "* " + botCommand.FormatHelp(command) + "\n" - } - return helpText -} - func handleEcho(args []string, s *discordgo.Session, m *discordgo.MessageCreate) string { return strings.Join(args, " ") } func handlePrefix(args []string, s *discordgo.Session, m *discordgo.MessageCreate) string { if len(args) == 0 { - return "Usage: prefix <new prefix>" + return "Usage: " + formatCommand("prefix <new prefix>") } newPrefix := args[0] if len(newPrefix) > 10 { - return "Prefix is too long" + return "Prefix is too long." } config.Values.Prefix = newPrefix@@ -54,5 +47,13 @@ if err != nil {
logger.Errorf("could not save config: %s", err) } - return "Prefix set to " + newPrefix + return "Prefix set to " + formatCommand("") +} + +func handleHelp(args []string, s *discordgo.Session, m *discordgo.MessageCreate) string { + helpText := "**Bot commands:**\n" + for command, botCommand := range handlersMap { + helpText += "* " + botCommand.FormatHelp(command) + "\n" + } + return helpText }
M
globals.go
→
globals.go
@@ -1,7 +1,6 @@
package main import ( - "fmt" "os" "github.com/BiRabittoh/disgord/myconfig"@@ -11,7 +10,15 @@ "github.com/kkdai/youtube/v2"
) const ( - helpFmt = "%s - _%s_" + msgError = "Something went wrong." + helpFmt = "%s - _%s_" +) + +var ( + config *myconfig.Config[Config] + + logger = mylog.NewLogger(os.Stdout, "main", mylog.DEBUG) + yt = youtube.Client{} ) type KeyValue struct {@@ -36,24 +43,3 @@ Handler func([]string, *discordgo.Session, *discordgo.MessageCreate) string
ShortCode string Help string } - -func formatCommand(command string) string { - return fmt.Sprintf("`%s%s`", config.Values.Prefix, command) -} - -func (bc BotCommand) FormatHelp(command string) string { - var shortCodeStr string - if bc.ShortCode != "" { - shortCodeStr = fmt.Sprintf(" (%s)", formatCommand(bc.ShortCode)) - } - return fmt.Sprintf(helpFmt, formatCommand(command)+shortCodeStr, bc.Help) -} - -var ( - discordToken string - appID string - config *myconfig.Config[Config] - - logger = mylog.NewLogger(os.Stdout, "main", mylog.DEBUG) - yt = youtube.Client{} -)
M
go.mod
→
go.mod
@@ -16,6 +16,7 @@ github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 // indirect
github.com/gorilla/websocket v1.4.2 // indirect github.com/kkdai/youtube/v2 v2.10.1 // indirect golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect + golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect )
M
go.sum
→
go.sum
@@ -40,6 +40,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
M
main.go
→
main.go
@@ -33,7 +33,7 @@ }
botCommand, found := handlersMap[command] if !found { - response = "unknown command: " + command + response = "Unknown command: " + formatCommand(command) return }@@ -80,7 +80,6 @@ logger.Fatalf("could not create bot session: %s", err)
} InitHandlers() - session.AddHandler(messageHandler) session.AddHandler(readyHandler)
A
shoot.go
@@ -0,0 +1,110 @@
+package main + +import ( + "fmt" + "time" + + "github.com/bwmarrin/discordgo" + "golang.org/x/exp/rand" +) + +type Magazine struct { + size uint + left uint + last time.Time +} + +var magazines = map[string]*Magazine{} + +func NewMagazine(size uint) *Magazine { + return &Magazine{size: size, left: size, last: time.Now()} +} + +func (m *Magazine) Update() { + now := time.Now() + if m.last.YearDay() != now.YearDay() || m.last.Year() != now.Year() { + m.left = m.size + } +} + +func (m *Magazine) Left() uint { + m.Update() + return m.left +} + +func (m Magazine) Size() uint { + return m.size +} + +func (m *Magazine) Shoot() bool { + if m.Left() <= 0 { + return false + } + + m.last = time.Now() + m.left-- + return true +} + +func (m *Magazine) String() string { + return fmt.Sprintf("_%d/%d bullets left in your magazine._", m.Left(), m.Size()) +} + +func GetMagazine(userID string) (q *Magazine) { + q, ok := magazines[userID] + if ok { + return + } + + q = NewMagazine(config.Values.MagazineSize) + magazines[userID] = q + return +} + +func handleShoot(args []string, s *discordgo.Session, m *discordgo.MessageCreate) string { + const bustProbability = 50 + + response, guild, voiceChannelID := getVoiceChannelID(s, m) + if voiceChannelID == "" { + return response + } + + killerID := m.Author.ID + var allMembers []string + for _, vs := range guild.VoiceStates { + if vs.ChannelID == voiceChannelID && vs.UserID != killerID { + member, err := s.State.Member(guild.ID, vs.UserID) + if err != nil { + logger.Errorf("could not get member info: %s", err) + continue + } + if !member.User.Bot { + allMembers = append(allMembers, vs.UserID) + } + } + } + + if len(allMembers) == 0 { + return "There is no one else to shoot in your voice channel." + } + + magazine := GetMagazine(killerID) + if !magazine.Shoot() { + return "💨 Too bad... You're out of bullets." + } + + var victimID string + if rand.Intn(100) < bustProbability { + victimID = killerID + } else { + victimID = allMembers[rand.Intn(len(allMembers))] + } + + err := s.GuildMemberMove(m.GuildID, victimID, nil) + if err != nil { + logger.Errorf("could not kick user: %s", err) + return "Failed to kick the user from the voice channel." + } + + return "💥 *Bang!* <@" + victimID + "> was shot. " + magazine.String() +}
A
utils.go
@@ -0,0 +1,45 @@
+package main + +import ( + "fmt" + + "github.com/bwmarrin/discordgo" +) + +func (bc BotCommand) FormatHelp(command string) string { + var shortCodeStr string + if bc.ShortCode != "" { + shortCodeStr = fmt.Sprintf(" (%s)", formatCommand(bc.ShortCode)) + } + return fmt.Sprintf(helpFmt, formatCommand(command)+shortCodeStr, bc.Help) +} + +func getVoiceChannelID(s *discordgo.Session, m *discordgo.MessageCreate) (response string, g *discordgo.Guild, voiceChannelID string) { + if m.Member == nil { + response = "Please, use this inside a server." + return + } + + g, err := s.State.Guild(m.GuildID) + if err != nil { + logger.Errorf("could not get guild: %s", err) + response = msgError + return + } + + for _, vs := range g.VoiceStates { + if vs.UserID == m.Author.ID { + voiceChannelID = vs.ChannelID + break + } + } + + if voiceChannelID == "" { + response = "You need to be in a voice channel to use this command." + } + return +} + +func formatCommand(command string) string { + return fmt.Sprintf("`%s%s`", config.Values.Prefix, command) +}