Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert IRC formatting / emphasis to markdown for Mattermost #546

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 83 additions & 2 deletions mm-go-irckit/server_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,13 @@ func CmdPing(s Server, u *User, msg *irc.Message) error {
return nil
}

// Use static initialisation to optimize.
// Color - https://modern.ircdocs.horse/formatting.html#color
var colorRegExp = regexp.MustCompile(`\x03([019]?[0-9](,[019]?[0-9])?)?`)

// Hex Color - https://modern.ircdocs.horse/formatting.html#hex-color
var hexColorRegExp = regexp.MustCompile(`\x04[0-9a-fA-F]{6}`)

// CmdPrivMsg is a handler for the /PRIVMSG command.
func CmdPrivMsg(s Server, u *User, msg *irc.Message) error {
var err error
Expand Down Expand Up @@ -367,10 +374,13 @@ func CmdPrivMsg(s Server, u *User, msg *irc.Message) error {
msg.Trailing = strings.ReplaceAll(msg.Trailing, "\x01", "")
msg.Trailing = "*" + msg.Trailing + "*"
}

// strip IRC colors
re := regexp.MustCompile(`\x03([019]?[0-9](,[019]?[0-9])?)?`)
msg.Trailing = colorRegExp.ReplaceAllString(msg.Trailing, "")
msg.Trailing = hexColorRegExp.ReplaceAllString(msg.Trailing, "")

msg.Trailing = re.ReplaceAllString(msg.Trailing, "")
// Convert IRC formatting / emphasis to markdown.
msg.Trailing = irc2markdown(msg.Trailing)

// are we sending to a channel
if ch, exists := s.HasChannel(query); exists {
Expand Down Expand Up @@ -811,3 +821,74 @@ func CmdWhois(s Server, u *User, msg *irc.Message) error {
}
return s.EncodeMessage(u, irc.ERR_NOSUCHNICK, msg.Params, "No such nick/channel")
}

//nolint:funlen
func irc2markdown(msg string) string {
// https://modern.ircdocs.horse/formatting.html
emphasisSupported := map[byte][]byte{
'\x02': {'*', '*'}, // Bold 0x02 ** (**text**)
'\x1d': {'_'}, // Italics 0x1D _ (_text_)
'\x11': {'`'}, // Monospace 0x11 ` (`text`)
'\x0f': {' '}, // Reset 0x0F (**text\x0f)
}
emphasisUnsupported := map[byte]string{
'\x1f': "", // Underline 0x1f
'\x1e': "", // Strikethr 0x1e
'\x16': "", // Reverse Color
}

var buf []byte

var currentEmphasis []byte
for _, char := range []byte(msg) {
var ok bool
var emp []byte

// Strip or ignore unsuppored IRC formatting / emphasis
if _, ok = emphasisUnsupported[char]; ok {
continue
}

// Not an IRC formatting / emphasis character so copy as is
if emp, ok = emphasisSupported[char]; !ok {
buf = append(buf, char)
continue
}

// IRC reset so reset formatting
if char == '\x0f' {
// Close off any current formatting / emphasis
for _, c := range currentEmphasis {
buf = append(buf, emphasisSupported[c]...)
}
currentEmphasis = nil
continue
}

buf = append(buf, emp...)

// Closing emphasis, they're in pairs, remove for list of outstanding
found := false
var newEmphasis []byte
for _, c := range currentEmphasis {
if !found && c == char {
found = true
continue
}
newEmphasis = append(newEmphasis, c)
}
if found {
currentEmphasis = newEmphasis
continue
}

currentEmphasis = append([]byte{char}, currentEmphasis...)
}

// Close off any current formatting / emphasis
for _, c := range currentEmphasis {
buf = append(buf, emphasisSupported[c]...)
}

return string(buf)
}