package discord import ( "fmt" "sebclem/claptrapbot-go/utils" "slices" "sort" "strings" "github.com/bwmarrin/discordgo" ) func FindNextVoiceIncrement(status *GuildStatus) int { numbers := []int{} for _, value := range status.AutoVoiceStatus.CreatedChannel { numbers = append(numbers, value.Number) } sort.Ints(numbers) next := 1 for _, value := range numbers { if value == next { next += 1 } else { break } } return next } func GetConnectedUserCountInVoiceChannel(s *discordgo.Session, guildID string, channelID string) (int, error) { guildState, err := s.State.Guild(guildID) if err != nil { logger.Errorw("Fail retreve guild status", err, "GuildId", guildID) return -1, err } count := 0 for _, vs := range guildState.VoiceStates { if vs.ChannelID == channelID { count++ } } return count, nil } func CreateAutoVoiceChannel(s *discordgo.Session, guildStatus *GuildStatus, sourceChannelID string, channelNameTemplate string) (*discordgo.Channel, error) { nextNumber := FindNextVoiceIncrement(guildStatus) channel, err := s.Channel(sourceChannelID) if err != nil { logger.Errorw("Fail to retreve channel information", err, "ChannelID", sourceChannelID) return nil, err } newPosition := channel.Position + nextNumber channels, err := s.GuildChannels(channel.GuildID) if err != nil { logger.Errorw("Fail retrevie channel list", err) return nil, err } // TODO Reoder with list index to prevent accumulated error for _, thisChannel := range channels { if thisChannel.ParentID == channel.ParentID { logger.Debug(thisChannel.Position) } if thisChannel.ParentID == channel.ParentID && thisChannel.Position >= newPosition { thisChannel.Position++ } } err = s.GuildChannelsReorder(channel.GuildID, channels) if err != nil { logger.Errorw("Fail to reorde channels", err) return nil, err } channelName := strings.ReplaceAll(channelNameTemplate, "@count", fmt.Sprint(nextNumber)) created, err := s.GuildChannelCreateComplex(channel.GuildID, discordgo.GuildChannelCreateData{ Bitrate: channel.Bitrate, Name: channelName, Position: newPosition, PermissionOverwrites: channel.PermissionOverwrites, ParentID: channel.ParentID, RateLimitPerUser: channel.RateLimitPerUser, Type: discordgo.ChannelTypeGuildVoice, UserLimit: channel.UserLimit, }) if err != nil { logger.Errorw("Fail to create Auto voice channel", err, "GuildId", channel.GuildID) return nil, err } guildStatus.AutoVoiceStatus.CreatedChannel[created.ID] = &AutoVoiceChannelCreated{ID: created.ID, Number: nextNumber, Position: newPosition} return created, nil } func AutoVoiceChannelDisconect(s *discordgo.Session, guildStatus *GuildStatus, guildID string, channelID string) { inVC, err := GetConnectedUserCountInVoiceChannel(s, guildID, channelID) if err != nil { return } if inVC == 0 { channel, err := s.Channel(channelID) if err != nil { logger.Errorw("Fail to retreve channel information", err, "ChannelID", channelID) return } logger.Debug("Channel is empty, deleting it.") _, err = s.ChannelDelete(channel.ID) if err != nil { logger.Errorw("Fail to delete auto voice channel", err, "GuildId", channel.GuildID, "ChannelID", channel.ID) return } channels, err := s.GuildChannels(channel.GuildID) if err != nil { logger.Errorw("Fail retrevie channel list", err) return } filtered := utils.Filter(channels, func(c *discordgo.Channel) bool { return c.ParentID == channel.ParentID }) ReoderChannels(s, filtered, guildID) delete(guildStatus.AutoVoiceStatus.CreatedChannel, channelID) } } func ReoderChannels(s *discordgo.Session, channels []*discordgo.Channel, guildID string) error { slices.SortFunc(channels, func(a *discordgo.Channel, b *discordgo.Channel) int { if a.Position < b.Position { return -1 } else if a.Position > b.Position { return 1 } else { return 0 } }) for i, filtered := range channels { filtered.Position = i } err := s.GuildChannelsReorder(guildID, channels) if err != nil { logger.Errorw("Fail to reorde channels", err) return err } return nil }