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
|
type EmotesMap map[string]string
|
||||||
|
|
||||||
var Emotes EmotesMap
|
var Emotes EmotesMap
|
||||||
|
var WrappedEmotesOnly bool = false
|
||||||
|
|
||||||
var reStripStatic = regexp.MustCompile(`^(\\|/)?static`)
|
var (
|
||||||
|
reStripStatic = regexp.MustCompile(`^(\\|/)?static`)
|
||||||
|
reWrappedEmotes = regexp.MustCompile(`[:\[][^\s:\/\\\?=#\]\[]+[:\]]`)
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Emotes = NewEmotesMap()
|
Emotes = NewEmotesMap()
|
||||||
|
@ -40,7 +44,6 @@ func (em EmotesMap) Add(fullpath string) EmotesMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
em[code] = fullpath
|
em[code] = fullpath
|
||||||
//fmt.Printf("Added emote %s at path %q\n", code, fullpath)
|
|
||||||
return em
|
return em
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,23 +51,33 @@ func EmoteToHtml(file, title string) string {
|
||||||
return fmt.Sprintf(`<img src="%s" height="28px" title="%s" />`, file, title)
|
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 {
|
func ParseEmotesArray(words []string) []string {
|
||||||
newWords := []string{}
|
newWords := []string{}
|
||||||
for _, word := range words {
|
for _, word := range words {
|
||||||
// make :emote: and [emote] valid for replacement.
|
|
||||||
wordTrimmed := strings.Trim(word, ":[]")
|
|
||||||
|
|
||||||
found := false
|
found := false
|
||||||
for key, val := range Emotes {
|
if !WrappedEmotesOnly {
|
||||||
if key == wordTrimmed {
|
if val, ok := Emotes[word]; ok {
|
||||||
newWords = append(newWords, EmoteToHtml(val, key))
|
newWords = append(newWords, EmoteToHtml(val, word))
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
|
word = reWrappedEmotes.ReplaceAllStringFunc(word, emoteToHmtl2)
|
||||||
newWords = append(newWords, word)
|
newWords = append(newWords, word)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return newWords
|
return newWords
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,18 @@ var data_good = map[string]string{
|
||||||
":two:": `<img src="/emotes/two.png" height="28px" title="two" />`,
|
":two:": `<img src="/emotes/two.png" height="28px" title="two" />`,
|
||||||
":three:": `<img src="/emotes/three.gif" height="28px" title="three" />`,
|
":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" />`,
|
"[one]": `<img src="/emotes/one.png" height="28px" title="one" />`,
|
||||||
"[two]": `<img src="/emotes/two.png" height="28px" title="two" />`,
|
"[two]": `<img src="/emotes/two.png" height="28px" title="two" />`,
|
||||||
"[three]": `<img src="/emotes/three.gif" height="28px" title="three" />`,
|
"[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" />`,
|
":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`,
|
"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`,
|
"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) {
|
func TestMain(m *testing.M) {
|
||||||
Emotes = map[string]string{
|
Emotes = map[string]string{
|
||||||
"one": "/emotes/one.png",
|
"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
|
RoomAccessPin string // The current pin
|
||||||
NewPin bool // Auto generate a new pin on start. Overwrites RoomAccessPin if set.
|
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
|
// Rate limiting stuff, in seconds
|
||||||
RateLimitChat time.Duration
|
RateLimitChat time.Duration
|
||||||
RateLimitNick time.Duration
|
RateLimitNick time.Duration
|
||||||
|
@ -128,6 +130,11 @@ func LoadSettings(filename string) (*Settings, error) {
|
||||||
s.RateLimitDuplicate = 30
|
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
|
// Print this stuff before we multiply it by time.Second
|
||||||
common.LogInfof("RateLimitChat: %v", s.RateLimitChat)
|
common.LogInfof("RateLimitChat: %v", s.RateLimitChat)
|
||||||
common.LogInfof("RateLimitNick: %v", s.RateLimitNick)
|
common.LogInfof("RateLimitNick: %v", s.RateLimitNick)
|
||||||
|
|
|
@ -14,5 +14,6 @@
|
||||||
"RateLimitColor": 60,
|
"RateLimitColor": 60,
|
||||||
"RateLimitAuth": 5,
|
"RateLimitAuth": 5,
|
||||||
"RateLimitDuplicate": 30,
|
"RateLimitDuplicate": 30,
|
||||||
"NoCache": false
|
"NoCache": false,
|
||||||
|
"WrappedEmotesOnly": false
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue