Rework emote parsing to properly handle wrapped emotes
Reworked the emote parsing to properly handle "wrapped" emotes. A wrapped emote is one that is wrapped in colons or square braces (eg, :Kappa: or [Kappa]). This allows emotes to be input without a space between them, like is required with non-wrapped emotes. A new configuration setting has been added to only allow parsing of wrapped emotes: "WrappedEmotesOnly". This defaults to False as to not break current configurations. The emote autocompletion will only insert non-wrapped emotes. Setting "WrappedEmotesOnly" configuration value to True will not change this. Lastly, made the bare-word emote parsing a bit cleaner by removing a for loop in favor of a map lookup with a check. This should in theory be more efficient. This change is in response to #111. The issue should not be considered resolved until the autocompletion handles the new setting correctly.
This commit is contained in:
parent
ce2150f719
commit
fab56e39ea
@ -10,8 +10,12 @@ import (
|
||||
type EmotesMap map[string]string
|
||||
|
||||
var Emotes EmotesMap
|
||||
var WrappedEmotesOnly bool = false
|
||||
|
||||
var reStripStatic = regexp.MustCompile(`^(\\|/)?static`)
|
||||
var (
|
||||
reStripStatic = regexp.MustCompile(`^(\\|/)?static`)
|
||||
reWrappedEmotes = regexp.MustCompile(`[:\[][^\s:\/\\\?=#\]\[]+[:\]]`)
|
||||
)
|
||||
|
||||
func init() {
|
||||
Emotes = NewEmotesMap()
|
||||
@ -40,7 +44,6 @@ func (em EmotesMap) Add(fullpath string) EmotesMap {
|
||||
}
|
||||
|
||||
em[code] = fullpath
|
||||
//fmt.Printf("Added emote %s at path %q\n", code, fullpath)
|
||||
return em
|
||||
}
|
||||
|
||||
@ -48,23 +51,33 @@ func EmoteToHtml(file, title string) string {
|
||||
return fmt.Sprintf(`<img src="%s" height="28px" title="%s" />`, file, title)
|
||||
}
|
||||
|
||||
// Used with a regexp.ReplaceAllStringFunc() call. Needs to lookup the value as it
|
||||
// cannot be passed in with the regex function call.
|
||||
func emoteToHmtl2(key string) string {
|
||||
key = strings.Trim(key, ":[]")
|
||||
if val, ok := Emotes[key]; ok {
|
||||
return fmt.Sprintf(`<img src="%s" height="28px" title="%s" />`, val, key)
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
func ParseEmotesArray(words []string) []string {
|
||||
newWords := []string{}
|
||||
for _, word := range words {
|
||||
// make :emote: and [emote] valid for replacement.
|
||||
wordTrimmed := strings.Trim(word, ":[]")
|
||||
|
||||
found := false
|
||||
for key, val := range Emotes {
|
||||
if key == wordTrimmed {
|
||||
newWords = append(newWords, EmoteToHtml(val, key))
|
||||
if !WrappedEmotesOnly {
|
||||
if val, ok := Emotes[word]; ok {
|
||||
newWords = append(newWords, EmoteToHtml(val, word))
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
word = reWrappedEmotes.ReplaceAllStringFunc(word, emoteToHmtl2)
|
||||
newWords = append(newWords, word)
|
||||
}
|
||||
}
|
||||
|
||||
return newWords
|
||||
}
|
||||
|
||||
|
@ -14,10 +14,18 @@ var data_good = map[string]string{
|
||||
":two:": `<img src="/emotes/two.png" height="28px" title="two" />`,
|
||||
":three:": `<img src="/emotes/three.gif" height="28px" title="three" />`,
|
||||
|
||||
":one::one:": `<img src="/emotes/one.png" height="28px" title="one" /><img src="/emotes/one.png" height="28px" title="one" />`,
|
||||
":one:one:": `<img src="/emotes/one.png" height="28px" title="one" />one:`,
|
||||
"oneone": "oneone",
|
||||
"one:one:": `one<img src="/emotes/one.png" height="28px" title="one" />`,
|
||||
|
||||
"[one]": `<img src="/emotes/one.png" height="28px" title="one" />`,
|
||||
"[two]": `<img src="/emotes/two.png" height="28px" title="two" />`,
|
||||
"[three]": `<img src="/emotes/three.gif" height="28px" title="three" />`,
|
||||
|
||||
"[one][one]": `<img src="/emotes/one.png" height="28px" title="one" /><img src="/emotes/one.png" height="28px" title="one" />`,
|
||||
"[one]one": `<img src="/emotes/one.png" height="28px" title="one" />one`,
|
||||
|
||||
":one: two [three]": `<img src="/emotes/one.png" height="28px" title="one" /> <img src="/emotes/two.png" height="28px" title="two" /> <img src="/emotes/three.gif" height="28px" title="three" />`,
|
||||
|
||||
"nope one what": `nope <img src="/emotes/one.png" height="28px" title="one" /> what`,
|
||||
@ -25,6 +33,34 @@ var data_good = map[string]string{
|
||||
"nope [three] what": `nope <img src="/emotes/three.gif" height="28px" title="three" /> what`,
|
||||
}
|
||||
|
||||
var data_wrapped = map[string]string{
|
||||
"one": `one`,
|
||||
"two": `two`,
|
||||
"three": `three`,
|
||||
|
||||
":one:": `<img src="/emotes/one.png" height="28px" title="one" />`,
|
||||
":two:": `<img src="/emotes/two.png" height="28px" title="two" />`,
|
||||
":three:": `<img src="/emotes/three.gif" height="28px" title="three" />`,
|
||||
|
||||
":one::one:": `<img src="/emotes/one.png" height="28px" title="one" /><img src="/emotes/one.png" height="28px" title="one" />`,
|
||||
":one:one:": `<img src="/emotes/one.png" height="28px" title="one" />one:`,
|
||||
"oneone": "oneone",
|
||||
"one:one:": `one<img src="/emotes/one.png" height="28px" title="one" />`,
|
||||
|
||||
"[one]": `<img src="/emotes/one.png" height="28px" title="one" />`,
|
||||
"[two]": `<img src="/emotes/two.png" height="28px" title="two" />`,
|
||||
"[three]": `<img src="/emotes/three.gif" height="28px" title="three" />`,
|
||||
|
||||
"[one][one]": `<img src="/emotes/one.png" height="28px" title="one" /><img src="/emotes/one.png" height="28px" title="one" />`,
|
||||
"[one]one": `<img src="/emotes/one.png" height="28px" title="one" />one`,
|
||||
|
||||
":one: two [three]": `<img src="/emotes/one.png" height="28px" title="one" /> two <img src="/emotes/three.gif" height="28px" title="three" />`,
|
||||
|
||||
"nope one what": `nope one what`,
|
||||
"nope :two: what": `nope <img src="/emotes/two.png" height="28px" title="two" /> what`,
|
||||
"nope [three] what": `nope <img src="/emotes/three.gif" height="28px" title="three" /> what`,
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
Emotes = map[string]string{
|
||||
"one": "/emotes/one.png",
|
||||
@ -42,3 +78,12 @@ func TestEmotes_ParseEmotes(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmotes_ParseEmotes_WrappedOnly(t *testing.T) {
|
||||
for input, expected := range data_good {
|
||||
got := ParseEmotes(input)
|
||||
if got != expected {
|
||||
t.Errorf("%s failed to parse into %q. Received: %q", input, expected, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,8 @@ type Settings struct {
|
||||
RoomAccessPin string // The current pin
|
||||
NewPin bool // Auto generate a new pin on start. Overwrites RoomAccessPin if set.
|
||||
|
||||
WrappedEmotesOnly bool // only allow "wrapped" emotes. eg :Kappa: and [Kappa] but not Kappa
|
||||
|
||||
// Rate limiting stuff, in seconds
|
||||
RateLimitChat time.Duration
|
||||
RateLimitNick time.Duration
|
||||
@ -128,6 +130,11 @@ func LoadSettings(filename string) (*Settings, error) {
|
||||
s.RateLimitDuplicate = 30
|
||||
}
|
||||
|
||||
if s.WrappedEmotesOnly {
|
||||
common.LogInfoln("Only allowing wrapped emotes")
|
||||
common.WrappedEmotesOnly = true
|
||||
}
|
||||
|
||||
// Print this stuff before we multiply it by time.Second
|
||||
common.LogInfof("RateLimitChat: %v", s.RateLimitChat)
|
||||
common.LogInfof("RateLimitNick: %v", s.RateLimitNick)
|
||||
|
@ -14,5 +14,6 @@
|
||||
"RateLimitColor": 60,
|
||||
"RateLimitAuth": 5,
|
||||
"RateLimitDuplicate": 30,
|
||||
"NoCache": false
|
||||
"NoCache": false,
|
||||
"WrappedEmotesOnly": false
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user