// InnkeeperBot, a bot to create and manage custom channels // Copyright (C) 2020-2021 Matteo Schiff // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . package main import ( "github.com/bwmarrin/discordgo" ) type AutoGuild struct { id string newChannelEndpoint *discordgo.Channel createdChannels map[string][]string } var managedGuilds = make(map[string]*AutoGuild) const CATEGORY_NAME = "Gaming🎮" const DEFAULT_CHANNEL_NAME = "Stanza" func initChannels(s *discordgo.Session, guildID string) { var guild AutoGuild guild.id = guildID guild.createdChannels = make(map[string][]string) log.Debugf("Preparing guild %s for automatic channel management", guildID) category := searchChannel(s, guildID, CATEGORY_NAME, "") if category == nil { log.Errorf("Cannot find category %s in guild %s", CATEGORY_NAME, guildID) return } deleteAllChannelsUnderCategory(s, guildID, category.ID) guild.createNewChannelEndpoint(s, category.ID) managedGuilds[guildID] = &guild } func (guild *AutoGuild) createNewChannelEndpoint(s *discordgo.Session, channelParent string) { newChannelData := discordgo.GuildChannelCreateData{ Name: "Crea nuovo canale", Type: discordgo.ChannelTypeGuildVoice, ParentID: channelParent} var err error guild.newChannelEndpoint, err = s.GuildChannelCreateComplex(guild.id, newChannelData) if err != nil { log.Errorf("Cannot create channel with name %s in guild %s. This guild is in a corrupted state", newChannelData.Name, guild.id) return } log.Debugf("Created channel with name %s in guild %s", newChannelData.Name, guild.id) } func (guild *AutoGuild) createNewChannel(s *discordgo.Session, channelID string, userID string) { category := searchChannel(s, guild.id, CATEGORY_NAME, "") if category == nil { log.Errorf("Cannot find category %s in guild %s", CATEGORY_NAME, guild.id) return } channelName := guild.getActivity(s.State, userID) editChannelData := discordgo.ChannelEdit{Name: channelName} _, err := s.ChannelEdit(channelID, &editChannelData) if err != nil { log.Errorf("Cannot rename channel %s with new name %s in guild %s", channelID, channelName, guild.id) return } guild.createdChannels[channelID] = []string{userID} log.Debugf("Renamed channel %s to %s in guild %s", channelID, channelName, guild.id) guild.createNewChannelEndpoint(s, category.ID) } func (guild *AutoGuild) removeUserFromChannels(s *discordgo.Session, userID string) { for channelID, channel := range guild.createdChannels { index := contains(channel, userID) if index != -1 { if len(channel) == 1 { // If this user was the only one left in the channel, delete the channel _, err := s.ChannelDelete(channelID) if err != nil { log.Errorf("Cannot delete channel %s in guild %s", channelID, guild.id) } else { log.Debugf("Channel %s deleted in guild %s", channelID, guild.id) delete(guild.createdChannels, channelID) } } else { // Otherwise update the channel name and remove user from the list guild.createdChannels[channelID] = remove(channel, index) guild.updateChannelName(s, channelID) } } } } func (guild *AutoGuild) trackUserJoinManagedChannel(s *discordgo.Session, channelID string, userID string) { guild.createdChannels[channelID] = append(guild.createdChannels[channelID], userID) guild.updateChannelName(s, channelID) } func (guild *AutoGuild) updateChannelName(s *discordgo.Session, channelID string) { programs := make(map[string]int) for _, userID := range guild.createdChannels[channelID] { programs[guild.getActivity(s.State, userID)] += 1 } max := -1 name := DEFAULT_CHANNEL_NAME for program, count := range programs { if program != DEFAULT_CHANNEL_NAME && count > max { max = count name = program } } channel, err := s.Channel(channelID) if err != nil { log.Errorf("Channel %s not found in guild %s", channelID, guild.id) return } oldName := channel.Name if oldName == name { return } editChannelData := discordgo.ChannelEdit{Name: name} _, err = s.ChannelEdit(channelID, &editChannelData) if err != nil { log.Errorf("Cannot rename channel %s with new name %s in guild %s", channelID, name, guild.id) } log.Debugf("Renamed channel %s from %s to %s in guild %s", channelID, oldName, name, guild.id) } func (guild *AutoGuild) getActivity(st *discordgo.State, userID string) string { presence, err := st.Presence(guild.id, userID) if err != nil || len(presence.Activities) == 0 { return DEFAULT_CHANNEL_NAME } for _, activity := range presence.Activities { if activity.Name != "Hang Status" { return activity.Name } } return DEFAULT_CHANNEL_NAME }