66 lines
1.7 KiB
Go
66 lines
1.7 KiB
Go
package emote
|
|
|
|
import (
|
|
"strings"
|
|
"unicode"
|
|
)
|
|
|
|
// Emote is the information Kaiyan needs about an emote.
|
|
type Emote struct {
|
|
// ID is the emote ID per the source.
|
|
ID string `json:"id"`
|
|
// Name is the text of the emote as would be parsed from message text.
|
|
Name string `json:"name"`
|
|
// Source is the name of the emote source, e.g. "7TV", "Twitch:cirno_tv", &c.
|
|
Source string `json:"source"`
|
|
// Link is a hyperlink to manage the emote.
|
|
Link string `json:"link"`
|
|
// Image is a hyperlink to the emote image of any size.
|
|
Image string `json:"image"`
|
|
}
|
|
|
|
// Parser finds emotes in a message.
|
|
//
|
|
// Parser assumes that emotes are bound by whitespace.
|
|
type Parser struct {
|
|
m map[string]Emote
|
|
// TODO(branden): more efficient data structure; trie?
|
|
}
|
|
|
|
// NewParser creates a Parser for the given list of emotes.
|
|
func NewParser(emotes ...Emote) Parser {
|
|
m := make(map[string]Emote, len(emotes))
|
|
for _, e := range emotes {
|
|
m[e.Name] = e
|
|
}
|
|
return Parser{m}
|
|
}
|
|
|
|
// Next parses the next emote instance from the message and returns the
|
|
// remainder of the message text following it.
|
|
// If there is no emote in the message the returned emote has an empty ID.
|
|
func (p Parser) Next(text string) (emote Emote, following string) {
|
|
for text != "" {
|
|
// First trim any existing space.
|
|
text = strings.TrimSpace(text)
|
|
// Then look for the next space.
|
|
// If there is none, this is the last word of the message; we still
|
|
// need to look it up.
|
|
k := strings.IndexFunc(text, unicode.IsSpace)
|
|
word := text
|
|
if k >= 0 {
|
|
word = text[:k]
|
|
following = text[k:]
|
|
} else {
|
|
following = ""
|
|
}
|
|
em := p.m[word]
|
|
if em.ID != "" {
|
|
return em, following
|
|
}
|
|
text = following
|
|
}
|
|
// No emote found.
|
|
return Emote{}, ""
|
|
}
|