message parsing

This commit is contained in:
Cynthia Foxwell 2023-07-08 22:42:58 -06:00
parent 7a69523b09
commit 6b5857d382
6 changed files with 257 additions and 28 deletions

View file

@ -4,24 +4,30 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/Cynosphere/comcord/state"
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
"github.com/fatih/color" "github.com/mgutz/ansi"
) )
const format string = " %s - %s%s"
func HelpCommand(session *discordgo.Session) { func HelpCommand(session *discordgo.Session) {
noColor := state.HasNoColor()
fmt.Println("\r\nCOMcord (c)left 2023\n\r") fmt.Println("\r\nCOMcord (c)left 2023\n\r")
index := 0 index := 0
for key, cmd := range GetAllCommands() { for key, cmd := range GetAllCommands() {
str := fmt.Sprintf(" %s - %s", key, cmd.Description) str := fmt.Sprintf(format, key, cmd.Description, "")
length := len(str) length := len(str)
padding := strings.Repeat(" ", 25 - length)
fmt.Print(" ") if noColor {
color.Set(color.FgYellow, color.Bold) fmt.Printf(format, key, cmd.Description, padding)
fmt.Print(key) } else {
color.Unset() coloredKey := ansi.Color(key, "yellow+b")
fmt.Printf(" - %s", cmd.Description) fmt.Printf(format, coloredKey, cmd.Description, padding)
fmt.Print(strings.Repeat(" ", 25 - length)) }
index++ index++
if index % 3 == 0 { if index % 3 == 0 {

View file

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/Cynosphere/comcord/lib"
"github.com/Cynosphere/comcord/state" "github.com/Cynosphere/comcord/state"
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
"github.com/ergochat/readline" "github.com/ergochat/readline"
@ -22,7 +23,10 @@ func SendMode(session *discordgo.Session) {
length := len(session.State.User.Username) + 2 length := len(session.State.User.Username) + 2
curLength := state.GetNameLength() curLength := state.GetNameLength()
prompt := fmt.Sprintf("%s[%s]%s%s", ansi.ColorCode("cyan+b"), session.State.User.Username, strings.Repeat(" ", (curLength - length) + 1), ansi.ColorCode("reset")) prompt := fmt.Sprintf("[%s]%s", session.State.User.Username, strings.Repeat(" ", (curLength - length) + 1))
if !state.HasNoColor() {
prompt = ansi.Color(prompt, "cyan+b")
}
input, _ := readline.NewFromConfig(&readline.Config{ input, _ := readline.NewFromConfig(&readline.Config{
Prompt: prompt, Prompt: prompt,
@ -51,4 +55,5 @@ func SendMode(session *discordgo.Session) {
// TODO: update afk state // TODO: update afk state
} }
state.SetInPrompt(false) state.SetInPrompt(false)
lib.ProcessQueue(session)
} }

View file

@ -1,12 +1,13 @@
package events package events
import ( import (
"github.com/Cynosphere/comcord/lib"
"github.com/Cynosphere/comcord/state" "github.com/Cynosphere/comcord/state"
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
) )
func MessageCreate(session *discordgo.Session, msg *discordgo.MessageCreate) { func MessageCreate(session *discordgo.Session, msg *discordgo.MessageCreate) {
if (msg.Author.ID == session.State.User.ID) { if msg.Author.ID == session.State.User.ID {
return return
} }
@ -15,13 +16,15 @@ func MessageCreate(session *discordgo.Session, msg *discordgo.MessageCreate) {
return return
} }
isDM := channel.Type == discordgo.ChannelTypeDM || channel.Type == discordgo.ChannelTypeGroupDM
if state.IsInPrompt() { if state.IsInPrompt() {
state.AddMessageToQueue(*msg.Message) state.AddMessageToQueue(msg.Message)
} else { } else {
// TODO lib.ProcessMessage(session, msg.Message, lib.MessageOptions{NoColor: state.HasNoColor()})
} }
if channel.Type == discordgo.ChannelTypeDM || channel.Type == discordgo.ChannelTypeGroupDM { if isDM {
state.SetLastDM(msg.ChannelID) state.SetLastDM(msg.ChannelID)
} }
} }

View file

@ -9,23 +9,15 @@ import (
) )
func Ready(session *discordgo.Session, event *discordgo.Ready) { func Ready(session *discordgo.Session, event *discordgo.Ready) {
fmt.Printf("\rLogged in as: %s%s (%s)%s\n\r", ansi.ColorCode("yellow"), session.State.User.Username, session.State.User.ID, ansi.ColorCode("reset")) fmt.Printf("\rLogged in as: %s\n\r", ansi.Color(fmt.Sprintf("%s (%s)", session.State.User.Username, session.State.User.ID), "yellow"))
state.SetNameLength(len(session.State.User.Username) + 2) state.SetNameLength(len(session.State.User.Username) + 2)
defaultGuild := state.GetConfigValue("defaultGuild") defaultGuild := state.GetConfigValue("defaultGuild")
defaultChannel := state.GetConfigValue("defaultChannel") defaultChannel := state.GetConfigValue("defaultChannel")
if defaultGuild != "" { if defaultGuild != "" {
//var guild discordgo.Guild _, err := session.State.Guild(defaultGuild)
hasGuild := false if err == nil {
for _, g := range session.State.Guilds {
if g.ID == defaultGuild {
//guild = *g
hasGuild = true
break
}
}
if hasGuild {
if defaultChannel != "" { if defaultChannel != "" {
state.SetCurrentChannel(defaultChannel) state.SetCurrentChannel(defaultChannel)
state.SetLastChannel(defaultGuild, defaultChannel) state.SetLastChannel(defaultGuild, defaultChannel)

209
lib/messages.go Normal file
View file

@ -0,0 +1,209 @@
package lib
import (
"fmt"
"math"
"regexp"
"strings"
"time"
"github.com/Cynosphere/comcord/state"
"github.com/bwmarrin/discordgo"
"github.com/mgutz/ansi"
)
var /*const*/ REGEX_CODEBLOCK = regexp.MustCompile(`(?i)\x60\x60\x60(?:([a-z0-9_+\-\.]+?)\n)?\n*([^\n].*?)\n*\x60\x60\x60`)
type MessageOptions struct {
Content string
Name string
Channel string
Bot bool
Attachments []*discordgo.MessageAttachment
Stickers []*discordgo.Sticker
Reply *discordgo.Message
Timestamp time.Time
IsMention bool
IsDM bool
IsJoin bool
IsPin bool
IsDump bool
NoColor bool
InHistory bool
}
func FormatMessage(session *discordgo.Session, options MessageOptions) {
// TODO: timestamps for pin and join
// TODO: history lines
nameLength := len(options.Name) + 2
stateNameLength := state.GetNameLength()
if nameLength > stateNameLength {
state.SetNameLength(nameLength)
}
// TODO: replies
if options.IsDump {
if options.InHistory {
// TODO
} else {
wordCount := len(strings.Split(options.Content, " "))
lineCount := len(strings.Split(options.Content, "\n"))
wordsPlural := ""
linesPlural := ""
if wordCount > 1 {
wordsPlural = "s"
}
if lineCount > 1 {
linesPlural = "s"
}
str := fmt.Sprintf("<%s DUMPs in %d characters of %d word%s in %d line%s>", options.Name, len(options.Content), wordCount, wordsPlural, lineCount, linesPlural)
if options.NoColor {
fmt.Print(str)
}
}
} else {
// TODO: markdown
if options.IsDM {
name := fmt.Sprintf("*%s*", options.Name)
if !options.NoColor {
name = ansi.Color(name, "red+b")
}
fmt.Printf("%s %s\x07\n\r", name, options.Content)
} else if len(options.Content) > 1 &&
(strings.HasPrefix(options.Content, "*") && strings.HasSuffix(options.Content, "*") && !strings.HasPrefix(options.Content, "**") && !strings.HasSuffix(options.Content, "**")) ||
(strings.HasPrefix(options.Content, "_") && strings.HasSuffix(options.Content, "_") && !strings.HasPrefix(options.Content, "__") && !strings.HasSuffix(options.Content, "__")) {
str := fmt.Sprintf("<%s %s>", options.Name, options.Content[1:len(options.Content)-1])
if options.NoColor {
fmt.Print(str + "\n\r")
} else {
fmt.Print(ansi.Color(str, "green+b") + "\n\r")
}
} else if options.IsJoin {
// TODO
} else if options.IsPin {
// TODO
} else {
nameColor := "cyan+b"
if options.IsMention {
nameColor = "red+b"
} else if options.Bot {
nameColor = "yellow+b"
}
name := fmt.Sprintf("[%s]", options.Name)
if !options.NoColor {
name = ansi.Color(name, nameColor)
}
// FIXME: where is this off by 4 actually from
padding := strings.Repeat(" ", int(math.Abs(float64(stateNameLength) - float64(nameLength) - 4)))
str := fmt.Sprintf("%s%s %s", name, padding, options.Content)
if options.IsMention {
str = str + "\x07"
}
fmt.Print(str + "\n\r")
}
}
// TODO: attachments
// TODO: stickers
// TODO: links
// TODO: embeds
// TODO: lines output for history
}
func ProcessMessage(session *discordgo.Session, msg *discordgo.Message, options MessageOptions) {
channel, err := session.State.Channel(msg.ChannelID)
if err != nil {
return
}
guild, err := session.State.Guild(channel.GuildID)
if err != nil {
return
}
selfMember, err := session.State.Member(guild.ID, session.State.User.ID)
if err != nil {
return
}
hasMentionedRole := false
for _, role := range msg.MentionRoles {
for _, selfRole := range selfMember.Roles {
if role == selfRole {
hasMentionedRole = true
break;
}
}
}
isDirectlyMentioned := false
for _, user := range msg.Mentions {
if user.ID == session.State.User.ID {
isDirectlyMentioned = true
break;
}
}
isPing := msg.MentionEveryone || hasMentionedRole || isDirectlyMentioned
isDM := channel.Type == discordgo.ChannelTypeDM || channel.Type == discordgo.ChannelTypeGroupDM
currentChannel := state.GetCurrentChannel()
isCurrentChannel := currentChannel == msg.ChannelID
if !isCurrentChannel && !isDM && !isPing {
return
}
if isPing && !isCurrentChannel && !isDM {
str := fmt.Sprintf("**mentioned by %s in #%s in %s**", msg.Author.Username, channel.Name, guild.Name)
if options.NoColor {
fmt.Print(ansi.Color(str, "red+b"))
} else {
fmt.Print(str)
}
fmt.Print("\x07\n\r")
return
}
content, _ := msg.ContentWithMoreMentionsReplaced(session)
options.Content = content
options.Name = msg.Author.Username
options.Channel = msg.ChannelID
options.Bot = msg.Author.Bot
options.Attachments = msg.Attachments
options.Stickers = msg.StickerItems
options.Reply = msg.ReferencedMessage
options.IsMention = isPing
options.IsDM = isDM
options.IsJoin = msg.Type == discordgo.MessageTypeGuildMemberJoin
options.IsPin = msg.Type == discordgo.MessageTypeChannelPinnedMessage
options.IsDump = REGEX_CODEBLOCK.MatchString(content)
FormatMessage(session, options)
}
func ProcessQueue(session *discordgo.Session) {
queue := state.GetMessageQueue()
for _, msg := range queue {
ProcessMessage(session, msg, MessageOptions{NoColor: state.HasNoColor()})
}
state.EmptyMessageQueue()
}

View file

@ -16,9 +16,10 @@ type ComcordState struct {
NameLength int NameLength int
InPrompt bool InPrompt bool
AFK bool AFK bool
MessageQueue []discordgo.Message MessageQueue []*discordgo.Message
LastChannel map[string]string LastChannel map[string]string
LastDM string LastDM string
NoColor bool
} }
var state ComcordState var state ComcordState
@ -34,9 +35,10 @@ func Setup(config map[string]string) {
state.NameLength = 2 state.NameLength = 2
state.InPrompt = false state.InPrompt = false
state.AFK = false state.AFK = false
state.MessageQueue = make([]discordgo.Message, 0) state.MessageQueue = make([]*discordgo.Message, 0)
state.LastChannel = make(map[string]string) state.LastChannel = make(map[string]string)
state.LastDM = "" state.LastDM = ""
state.NoColor = false
} }
func IsConnected() bool { func IsConnected() bool {
@ -99,14 +101,18 @@ func SetAFK(value bool) {
state.AFK = value state.AFK = value
} }
func GetMessageQueue() []discordgo.Message { func GetMessageQueue() []*discordgo.Message {
return state.MessageQueue return state.MessageQueue
} }
func AddMessageToQueue(msg discordgo.Message) { func AddMessageToQueue(msg *discordgo.Message) {
state.MessageQueue = append(state.MessageQueue, msg) state.MessageQueue = append(state.MessageQueue, msg)
} }
func EmptyMessageQueue() {
state.MessageQueue = make([]*discordgo.Message, 0)
}
func SetLastChannel(guild string, channel string) { func SetLastChannel(guild string, channel string) {
state.LastChannel[guild] = channel state.LastChannel[guild] = channel
} }
@ -138,3 +144,11 @@ func GetConfigValue(key string) string {
return "" return ""
} }
} }
func SetNoColor(value bool) {
state.NoColor = value
}
func HasNoColor() bool {
return state.NoColor
}