more work on message parsing

This commit is contained in:
Cynthia Foxwell 2023-07-09 14:00:49 -06:00
parent 6b5857d382
commit 2ba9b1405f
8 changed files with 226 additions and 41 deletions

View file

@ -6,13 +6,15 @@ import (
"regexp"
"strings"
"time"
"unicode/utf8"
"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`)
var REGEX_CODEBLOCK = regexp.MustCompile(`(?i)\x60\x60\x60(?:([a-z0-9_+\-\.]+?)\n)?\n*([^\n].*?)\n*\x60\x60\x60`)
var REGEX_EMOTE = regexp.MustCompile(`<(?:\x{200b}|&)?a?:(\w+):(\d+)>`)
type MessageOptions struct {
Content string
@ -33,18 +35,74 @@ type MessageOptions struct {
}
func FormatMessage(session *discordgo.Session, options MessageOptions) {
// TODO: timestamps for pin and join
timestamp := options.Timestamp.Format("[15:04:05]")
// TODO: history lines
nameLength := len(options.Name) + 2
nameLength := utf8.RuneCountInString(options.Name) + 2
stateNameLength := state.GetNameLength()
if nameLength > stateNameLength {
state.SetNameLength(nameLength)
stateNameLength = nameLength
}
// TODO: replies
if options.Reply != nil {
nameColor := "cyan+b"
if options.Bot {
nameColor = "yellow+b"
}
headerLength := 6 + utf8.RuneCountInString(options.Reply.Author.Username)
content, _ := options.Reply.ContentWithMoreMentionsReplaced(session)
replyContent := strings.ReplaceAll(content, "\n", " ")
// TODO: markdown
replyContent = REGEX_EMOTE.ReplaceAllString(replyContent, ":$1:")
attachmentCount := len(options.Reply.Attachments)
if attachmentCount > 0 {
attachmentPlural := ""
if attachmentCount > 1 {
attachmentPlural = "s"
}
replyContent = strings.TrimSpace(replyContent + fmt.Sprintf(" <%d attachment%s>", attachmentCount, attachmentPlural))
}
stickerCount := len(options.Reply.StickerItems)
if stickerCount > 0 {
stickerPlural := ""
if stickerCount > 0 {
stickerPlural = "s"
}
replyContent = strings.TrimSpace(replyContent + fmt.Sprintf(" <%d sticker%s>", stickerCount, stickerPlural))
}
length := headerLength + utf8.RuneCountInString(replyContent)
replySymbol := " \u00bb "
if !options.NoColor {
replySymbol = ansi.Color(replySymbol, "white+b")
}
name := fmt.Sprintf("[%s] ", options.Reply.Author.Username)
if !options.NoColor {
name = ansi.Color(name, nameColor)
}
moreContent := "\u2026"
if !options.NoColor {
moreContent = ansi.Color(moreContent, "reset")
}
if length > 79 {
replyContent = replyContent[:79 - headerLength] + moreContent
}
fmt.Print(replySymbol, name, replyContent, "\n\r")
}
if options.IsDump {
if options.InHistory {
@ -55,7 +113,7 @@ func FormatMessage(session *discordgo.Session, options MessageOptions) {
wordsPlural := ""
linesPlural := ""
if wordCount > 1 {
if wordCount > 1 {
wordsPlural = "s"
}
if lineCount > 1 {
@ -64,12 +122,16 @@ func FormatMessage(session *discordgo.Session, options MessageOptions) {
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)
if !options.NoColor {
str = ansi.Color(str, "yellow+b")
}
fmt.Print(str + "\n\r")
}
} else {
// TODO: markdown
content := options.Content
content = REGEX_EMOTE.ReplaceAllString(content, ":$1:")
if options.IsDM {
name := fmt.Sprintf("*%s*", options.Name)
@ -77,21 +139,40 @@ func FormatMessage(session *discordgo.Session, options MessageOptions) {
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])
fmt.Printf("%s %s\x07\n\r", name, content)
} else if utf8.RuneCountInString(content) > 1 &&
(strings.HasPrefix(content, "*") && strings.HasSuffix(content, "*") && !strings.HasPrefix(content, "**") && !strings.HasSuffix(content, "**")) ||
(strings.HasPrefix(content, "_") && strings.HasSuffix(content, "_") && !strings.HasPrefix(content, "__") && !strings.HasSuffix(content, "__")) {
str := fmt.Sprintf("<%s %s>", options.Name, content[1:len(content)-1])
if options.NoColor {
fmt.Print(str + "\n\r")
} else {
fmt.Print(ansi.Color(str, "green+b") + "\n\r")
if !options.NoColor {
str = ansi.Color(str, "green+b")
}
fmt.Print(str + "\n\r")
} else if options.IsJoin {
// TODO
channel, err := session.State.Channel(options.Channel)
if err != nil {
return
}
guild, err := session.State.Guild(channel.GuildID)
if err != nil {
return
}
str := fmt.Sprintf("%s %s has joined %s", timestamp, options.Name, guild.Name)
if !options.NoColor {
str = ansi.Color(str, "yellow+b")
}
fmt.Print(str + "\n\r")
} else if options.IsPin {
// TODO
str := fmt.Sprintf("%s %s pinned a message to this channel", timestamp, options.Name)
if !options.NoColor {
str = ansi.Color(str, "yellow+b")
}
fmt.Print(str + "\n\r")
} else {
nameColor := "cyan+b"
if options.IsMention {
@ -105,9 +186,8 @@ func FormatMessage(session *discordgo.Session, options MessageOptions) {
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)
padding := strings.Repeat(" ", int(math.Abs(float64(stateNameLength) - float64(nameLength))) + 1)
str := name + padding + content
if options.IsMention {
str = str + "\x07"
}
@ -115,9 +195,27 @@ func FormatMessage(session *discordgo.Session, options MessageOptions) {
}
}
// TODO: attachments
if len(options.Attachments) > 0 {
for _, attachment := range options.Attachments {
str := fmt.Sprintf("<attachment: %s >", attachment.URL)
if !options.NoColor {
str = ansi.Color(str, "yellow+b")
}
// TODO: stickers
fmt.Print(str + "\n\r")
}
}
if len(options.Stickers) > 0 {
for _, sticker := range options.Stickers {
str := fmt.Sprintf("<sticker: \"%s\" https://cdn.discordapp.com/stickers/%s.png >", sticker.Name, sticker.ID)
if !options.NoColor {
str = ansi.Color(str, "yellow+b")
}
fmt.Print(str + "\n\r")
}
}
// TODO: links
@ -162,6 +260,7 @@ func ProcessMessage(session *discordgo.Session, msg *discordgo.Message, options
isPing := msg.MentionEveryone || hasMentionedRole || isDirectlyMentioned
isDM := channel.Type == discordgo.ChannelTypeDM || channel.Type == discordgo.ChannelTypeGroupDM
isEdit := msg.EditedTimestamp != nil
currentChannel := state.GetCurrentChannel()
isCurrentChannel := currentChannel == msg.ChannelID
@ -182,20 +281,45 @@ func ProcessMessage(session *discordgo.Session, msg *discordgo.Message, options
}
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)
if isEdit {
content = content + " (edited)"
}
FormatMessage(session, options)
isDump := REGEX_CODEBLOCK.MatchString(content)
if strings.Index(content, "\n") > -1 && !isDump {
for _, line := range strings.Split(content, "\n") {
options.Content = line
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 = false
FormatMessage(session, options)
}
} else {
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 = isDump
FormatMessage(session, options)
}
}
func ProcessQueue(session *discordgo.Session) {