From: Eduardo Date: Thu, 28 Mar 2024 17:35:33 +0000 (+0100) Subject: moved out utils functions and discord specifics X-Git-Url: http://git.edufdez.es/?a=commitdiff_plain;h=131eeff221e4db78b9bbfdd9e1bffe51d2acfaab;p=sylphiette-bot.git moved out utils functions and discord specifics --- diff --git a/.vscode/launch.json b/.vscode/launch.json index e6f70f0..2cbef34 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,7 +9,7 @@ "type": "go", "request": "launch", "mode": "auto", - "program": "${workspaceFolder}/bot.go", + "program": "${workspaceFolder}/*.go", "env": {}, "args": [] }, diff --git a/bot.go b/bot.go index 59ccc7f..7debfb9 100644 --- a/bot.go +++ b/bot.go @@ -6,8 +6,6 @@ import ( "os" "os/signal" "regexp" - "sort" - "strconv" "strings" "syscall" @@ -294,244 +292,3 @@ func handleButton(query *tgbotapi.CallbackQuery) { msg.ParseMode = tgbotapi.ModeHTML telegram.Send(msg) } - -//region discord bot stuff - -// This function will be called (due to AddHandler above) when the bot receives -// the "ready" event from Discord. -func ready(s *discordgo.Session, event *discordgo.Ready) { - // Set the playing status. - s.UpdateListeningStatus("te a ti") -} - -func voiceChatUpdate(s *discordgo.Session, m *discordgo.VoiceStateUpdate) { - if m.ChannelID != "" { - // The user joined a channel, moved to a new channel, or edited its status - usersInVoiceChat = append(removeMemberFromSlice(usersInVoiceChat, *m.Member), formatUserVoiceStatus(*m.Member, *m.VoiceState)) - } else { - // The user left a channel - usersInVoiceChat = removeMemberFromSlice(usersInVoiceChat, *m.Member) - } - - formatBotMessage() -} - -// The guild was created (or the bot was added to a new guild, or the bot was restarted) -func guildCreated(s *discordgo.Session, m *discordgo.GuildCreate) { - // update the list of users online - for _, presence := range m.Presences { - if presence.User != nil && m.Members != nil && presence.Status != discordgo.StatusOffline && presence.Status != discordgo.StatusInvisible { - Members = m.Members - var member = getMemberFromMembers(m.Members, presence.User.ID) - if member.User.Bot { - continue - } - usersOnline = append(usersOnline, formatUserStatus(*member, *presence)) - } - } - - // update the list of users in voice chat - for _, vs := range m.VoiceStates { - if vs.UserID != "" { - var member = getMemberFromMembers(m.Members, vs.UserID) - if member != nil { - usersInVoiceChat = append(usersInVoiceChat, formatUserVoiceStatus(*member, *vs)) - } - } - } - - formatBotMessage() -} - -// The guild was updated (an user did something or changed status) -func guildUpdates(s *discordgo.Session, m *discordgo.PresenceUpdate) { - if m.Presence.User != nil { - var member = getMemberFromMembers(Members, m.Presence.User.ID) - if !member.User.Bot { - if m.Presence.Status != discordgo.StatusOffline && m.Presence.Status != discordgo.StatusInvisible { - usersOnline = append(removeMemberFromSlice(usersOnline, *member), formatUserStatus(*member, m.Presence)) - } else { - usersOnline = removeMemberFromSlice(usersOnline, *member) - } - } - } - formatBotMessage() -} - -func formatBotMessage() { - // log.Println("formatting bot message...") - botText = "" - re := regexp.MustCompile(`\\\[[0-9]+\]`) // remove user id from the string - - if len(usersOnline) > 0 { - botText += "👤 EN LÍNEA (" + strconv.Itoa(len(usersOnline)) + ")" + "\n" - - sortMembers(usersOnline) - for _, user := range usersOnline { - user = re.ReplaceAllString(user, "") - botText += user + "\n" - } - } - - if len(usersInVoiceChat) > 0 { - botText += "\n" + "🎙 CHAT DE VOZ (" + strconv.Itoa(len(usersInVoiceChat)) + ")" + "\n" - - sort.Strings(usersInVoiceChat) - for _, user := range usersInVoiceChat { - user = re.ReplaceAllString(user, "") - botText += user + "\n" - } - } - - if botText == "" { - botText = "💤 Parece que no hay nadie conectado." - } - - // log.Println(botText) - - if botMsg != nil { - msg := tgbotapi.NewEditMessageTextAndMarkup(botMsg.Chat.ID, botMsg.MessageID, botText, menuTextMarkup) - msg.ParseMode = tgbotapi.ModeHTML - telegram.Send(msg) - } -} - -func formatUserStatus(member discordgo.Member, presence discordgo.Presence) string { - var emoji string - - switch presence.Status { - case discordgo.StatusOnline: - emoji = "🟢" - case discordgo.StatusIdle: - emoji = "🟡" - case discordgo.StatusDoNotDisturb: - emoji = "🔴" - } - - switch presence.ClientStatus.Mobile { - case discordgo.StatusOnline: - emoji += "📱" - case discordgo.StatusIdle: - emoji += "📱" - case discordgo.StatusDoNotDisturb: - emoji += "📱" - } - - return emoji + " " + formatUserVisibleName(member) -} - -func formatUserVoiceStatus(member discordgo.Member, voiceState discordgo.VoiceState) string { - var emoji string = "🐵" - if member.Mute || voiceState.Mute || voiceState.SelfMute { - emoji = "🙊" - } - - if member.Deaf || voiceState.Deaf || voiceState.SelfDeaf { - emoji = "🙉" - } - - if voiceState.SelfVideo { - emoji += "📹" - } - - if voiceState.SelfStream { - emoji += "🖥" - } - - emoji += " " - - return emoji + formatUserVisibleName(member) -} - -func formatUserVisibleName(member discordgo.Member) string { - var user string - var id = member.User.ID - - user = member.User.Username - - //FIXME: discordgo.User is edited with: DisplayName string `json:"display_name"` - if member.User.DisplayName != "" { - user = member.User.DisplayName - } - - if member.Nick != "" { - user = member.Nick + " (" + user + ")" - } - - return user + "\\[" + id + "]" -} - -func removeMemberFromSlice(slice []string, member discordgo.Member) []string { - var id = "\\[" + member.User.ID + "]" - - for i, v := range slice { - if strings.Contains(v, id) { - return append(slice[:i], slice[i+1:]...) - } - } - - return slice -} - -func getMemberFromMembers(slice []*discordgo.Member, id string) *discordgo.Member { - for _, v := range slice { - if v.User.ID == id { - return v - } - } - return nil -} - -func sortMembers(slice []string) { - sort.Slice(slice, func(i, j int) bool { - user1 := replaceAllStrings(slice[i], []string{"📱", "🐵", "🙊", "🙉", "📹", "🖥"}, "") - user2 := replaceAllStrings(slice[j], []string{"📱", "🐵", "🙊", "🙉", "📹", "🖥"}, "") - - isUser1online := strings.Contains(user1, "🟢") - isUser2online := strings.Contains(user2, "🟢") - isUser1offline := strings.Contains(user1, "🔴") - isUser2offline := strings.Contains(user2, "🔴") - - if isUser1online && !isUser2online { - return true - } else if !isUser1online && isUser2online { - return false - } else if isUser1offline && !isUser2offline { - return false - } else if !isUser1offline && isUser2offline { - return true - } - - return user1 < user2 - }) -} - -func replaceAllStrings(str string, old []string, new string) string { - for _, o := range old { - str = strings.Replace(str, o, new, -1) - } - - return str -} - -func getTextAfterDash(s string) string { - dashIndex := strings.Index(s, "-") - if dashIndex != -1 { - return strings.TrimSpace(s[dashIndex+1:]) - } - return "" -} - -func getFirstLine(s string) string { - lines := strings.SplitN(s, "\n", 2) - return lines[0] -} - -func getRequestedBy(s string) string { - re := regexp.MustCompile(`(?i)Requested By:\s*(.*)`) - match := re.FindStringSubmatch(s) - if len(match) > 1 { - return strings.TrimSpace(match[1]) - } - return "???" -} diff --git a/discord.go b/discord.go new file mode 100644 index 0000000..3842173 --- /dev/null +++ b/discord.go @@ -0,0 +1,224 @@ +package main + +import ( + "regexp" + "sort" + "strconv" + "strings" + + "github.com/bwmarrin/discordgo" + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" +) + +// All Discord bot related crap will be here, even if it's not directly related to Discord (aka formating for telegram messages) + +// This function will be called (due to AddHandler in Main) when the bot receives +// the "ready" event from Discord. +func ready(s *discordgo.Session, event *discordgo.Ready) { + // Set the playing status. + s.UpdateListeningStatus("te a ti") +} + +func voiceChatUpdate(s *discordgo.Session, m *discordgo.VoiceStateUpdate) { + if m.ChannelID != "" { + // The user joined a channel, moved to a new channel, or edited its status + usersInVoiceChat = append(removeMemberFromSlice(usersInVoiceChat, *m.Member), formatUserVoiceStatus(*m.Member, *m.VoiceState)) + } else { + // The user left a channel + usersInVoiceChat = removeMemberFromSlice(usersInVoiceChat, *m.Member) + } + + formatBotMessage() +} + +// The guild was created (or the bot was added to a new guild, or the bot was restarted) +func guildCreated(s *discordgo.Session, m *discordgo.GuildCreate) { + // update the list of users online + for _, presence := range m.Presences { + if presence.User != nil && m.Members != nil && presence.Status != discordgo.StatusOffline && presence.Status != discordgo.StatusInvisible { + Members = m.Members + var member = getMemberFromMembers(m.Members, presence.User.ID) + if member.User.Bot { + continue + } + usersOnline = append(usersOnline, formatUserStatus(*member, *presence)) + } + } + + // update the list of users in voice chat + for _, vs := range m.VoiceStates { + if vs.UserID != "" { + var member = getMemberFromMembers(m.Members, vs.UserID) + if member != nil { + usersInVoiceChat = append(usersInVoiceChat, formatUserVoiceStatus(*member, *vs)) + } + } + } + + formatBotMessage() +} + +// The guild was updated (an user did something or changed status) +func guildUpdates(s *discordgo.Session, m *discordgo.PresenceUpdate) { + if m.Presence.User != nil { + var member = getMemberFromMembers(Members, m.Presence.User.ID) + if !member.User.Bot { + if m.Presence.Status != discordgo.StatusOffline && m.Presence.Status != discordgo.StatusInvisible { + usersOnline = append(removeMemberFromSlice(usersOnline, *member), formatUserStatus(*member, m.Presence)) + } else { + usersOnline = removeMemberFromSlice(usersOnline, *member) + } + } + } + formatBotMessage() +} + +func formatBotMessage() { + // log.Println("formatting bot message...") + botText = "" + re := regexp.MustCompile(`\\\[[0-9]+\]`) // remove user id from the string + + if len(usersOnline) > 0 { + botText += "👤 EN LÍNEA (" + strconv.Itoa(len(usersOnline)) + ")" + "\n" + + sortMembers(usersOnline) + for _, user := range usersOnline { + user = re.ReplaceAllString(user, "") + botText += user + "\n" + } + } + + if len(usersInVoiceChat) > 0 { + botText += "\n" + "🎙 CHAT DE VOZ (" + strconv.Itoa(len(usersInVoiceChat)) + ")" + "\n" + + sort.Strings(usersInVoiceChat) + for _, user := range usersInVoiceChat { + user = re.ReplaceAllString(user, "") + botText += user + "\n" + } + } + + if botText == "" { + botText = "💤 Parece que no hay nadie conectado." + } + + // log.Println(botText) + + if botMsg != nil { + msg := tgbotapi.NewEditMessageTextAndMarkup(botMsg.Chat.ID, botMsg.MessageID, botText, menuTextMarkup) + msg.ParseMode = tgbotapi.ModeHTML + telegram.Send(msg) + } +} + +func formatUserStatus(member discordgo.Member, presence discordgo.Presence) string { + var emoji string + + switch presence.Status { + case discordgo.StatusOnline: + emoji = "🟢" + case discordgo.StatusIdle: + emoji = "🟡" + case discordgo.StatusDoNotDisturb: + emoji = "🔴" + } + + switch presence.ClientStatus.Mobile { + case discordgo.StatusOnline: + emoji += "📱" + case discordgo.StatusIdle: + emoji += "📱" + case discordgo.StatusDoNotDisturb: + emoji += "📱" + } + + return emoji + " " + formatUserVisibleName(member) +} + +func formatUserVoiceStatus(member discordgo.Member, voiceState discordgo.VoiceState) string { + var emoji string = "🐵" + if member.Mute || voiceState.Mute || voiceState.SelfMute { + emoji = "🙊" + } + + if member.Deaf || voiceState.Deaf || voiceState.SelfDeaf { + emoji = "🙉" + } + + if voiceState.SelfVideo { + emoji += "📹" + } + + if voiceState.SelfStream { + emoji += "🖥" + } + + emoji += " " + + return emoji + formatUserVisibleName(member) +} + +func sortMembers(slice []string) { + sort.Slice(slice, func(i, j int) bool { + user1 := replaceAllStrings(slice[i], []string{"📱", "🐵", "🙊", "🙉", "📹", "🖥"}, "") + user2 := replaceAllStrings(slice[j], []string{"📱", "🐵", "🙊", "🙉", "📹", "🖥"}, "") + + isUser1online := strings.Contains(user1, "🟢") + isUser2online := strings.Contains(user2, "🟢") + isUser1offline := strings.Contains(user1, "🔴") + isUser2offline := strings.Contains(user2, "🔴") + + if isUser1online && !isUser2online { + return true + } else if !isUser1online && isUser2online { + return false + } else if isUser1offline && !isUser2offline { + return false + } else if !isUser1offline && isUser2offline { + return true + } + + return user1 < user2 + }) +} + +func formatUserVisibleName(member discordgo.Member) string { + var user string + var id = member.User.ID + + user = member.User.Username + + //FIXME: discordgo.User is edited with: DisplayName string `json:"display_name"` + if member.User.DisplayName != "" { + user = member.User.DisplayName + } + + if member.Nick != "" { + user = member.Nick + " (" + user + ")" + } + + return user + "\\[" + id + "]" +} + +// Removes a discordgo.Member from a slice of strings (full of discordgo.Member.User.ID) +func removeMemberFromSlice(slice []string, member discordgo.Member) []string { + var id = "\\[" + member.User.ID + "]" + + for i, v := range slice { + if strings.Contains(v, id) { + return append(slice[:i], slice[i+1:]...) + } + } + + return slice +} + +// Gets a discordgo.Member from a slice of discordgo.Member.User.ID +func getMemberFromMembers(slice []*discordgo.Member, id string) *discordgo.Member { + for _, v := range slice { + if v.User.ID == id { + return v + } + } + return nil +} diff --git a/utils.go b/utils.go new file mode 100644 index 0000000..fd4d73b --- /dev/null +++ b/utils.go @@ -0,0 +1,40 @@ +package main + +import ( + "regexp" + "strings" +) + +// Replace all strings in a string array with a new string +func replaceAllStrings(str string, oldSlice []string, new string) string { + for _, o := range oldSlice { + str = strings.Replace(str, o, new, -1) + } + + return str +} + +// Get the text after a dash in a string +func getTextAfterDash(s string) string { + dashIndex := strings.Index(s, "-") + if dashIndex != -1 { + return strings.TrimSpace(s[dashIndex+1:]) + } + return "" +} + +// Get the text in the first line of a string +func getFirstLine(s string) string { + lines := strings.SplitN(s, "\n", 2) + return lines[0] +} + +// Search for the text after "Requested By:" in a string and returns it +func getRequestedBy(s string) string { + re := regexp.MustCompile(`(?i)Requested By:\s*(.*)`) + match := re.FindStringSubmatch(s) + if len(match) > 1 { + return strings.TrimSpace(match[1]) + } + return "???" +}