all repos — disgord @ a4093084b5f92b1e3c91c66c157baba16346c4dc

A simple Discord bot in Go.

src/shoot/shoot.go (view raw)

  1package shoot
  2
  3import (
  4	"fmt"
  5	"os"
  6	"time"
  7
  8	gl "github.com/BiRabittoh/disgord/src/globals"
  9	"github.com/BiRabittoh/disgord/src/mylog"
 10	"github.com/bwmarrin/discordgo"
 11	"golang.org/x/exp/rand"
 12)
 13
 14var logger = mylog.NewLogger(os.Stdin, "shoot", mylog.DEBUG)
 15
 16type Magazine struct {
 17	size uint
 18	left uint
 19	last time.Time
 20}
 21
 22var magazines = map[string]*Magazine{}
 23
 24func NewMagazine(size uint) *Magazine {
 25	return &Magazine{size: size, left: size, last: time.Now()}
 26}
 27
 28func (m *Magazine) Update() {
 29	now := time.Now()
 30	if m.last.YearDay() != now.YearDay() || m.last.Year() != now.Year() {
 31		m.left = m.size
 32	}
 33}
 34
 35func (m *Magazine) Left() uint {
 36	m.Update()
 37	return m.left
 38}
 39
 40func (m Magazine) Size() uint {
 41	return m.size
 42}
 43
 44func (m *Magazine) Shoot() bool {
 45	if m.Left() <= 0 {
 46		return false
 47	}
 48
 49	m.last = time.Now()
 50	m.left--
 51	return true
 52}
 53
 54func (m *Magazine) String() string {
 55	return fmt.Sprintf("_%d/%d bullets left in your magazine._", m.Left(), m.Size())
 56}
 57
 58func GetMagazine(userID string) (q *Magazine) {
 59	q, ok := magazines[userID]
 60	if ok {
 61		return
 62	}
 63
 64	q = NewMagazine(gl.Config.Values.MagazineSize)
 65	magazines[userID] = q
 66	return
 67}
 68
 69func HandleShoot(args []string, s *discordgo.Session, m *discordgo.MessageCreate) string {
 70	const bustProbability = 50
 71
 72	_, err := s.Guild(m.GuildID)
 73	if err != nil {
 74		logger.Errorf("could not update guild: %s", err)
 75		return gl.MsgError
 76	}
 77
 78	response, guild, voiceChannelID := gl.GetVoiceChannelID(s, m)
 79	if voiceChannelID == "" {
 80		return response
 81	}
 82
 83	killerID := m.Author.ID
 84	var allMembers []string
 85	for _, vs := range guild.VoiceStates {
 86		logger.Debug(vs.UserID)
 87		if vs.ChannelID == voiceChannelID && vs.UserID != killerID {
 88			member, err := s.State.Member(guild.ID, vs.UserID)
 89			if err != nil {
 90				logger.Errorf("could not get member info: %s", err)
 91				continue
 92			}
 93			if !member.User.Bot {
 94				allMembers = append(allMembers, vs.UserID)
 95			}
 96		}
 97	}
 98
 99	if len(allMembers) == 0 {
100		return "There is no one else to shoot in your voice channel."
101	}
102
103	magazine := GetMagazine(killerID)
104	if !magazine.Shoot() {
105		return "💨 Too bad... You're out of bullets."
106	}
107
108	var victimID string
109	if rand.Intn(100) < bustProbability {
110		victimID = killerID
111	} else {
112		victimID = allMembers[rand.Intn(len(allMembers))]
113	}
114
115	err = s.GuildMemberMove(m.GuildID, victimID, nil)
116	if err != nil {
117		logger.Errorf("could not kick user: %s", err)
118		return "Failed to kick the user from the voice channel."
119	}
120
121	return "💥 *Bang!* <@" + victimID + "> was shot. " + magazine.String()
122}