master emoji.go
 1package senpai
 2
 3import (
 4	_ "embed"
 5	"encoding/json"
 6	"sort"
 7	"strings"
 8)
 9
10//go:embed emoji.json
11var emojiJSON []byte
12
13type emoji struct {
14	Emoji string
15	Alias string
16}
17
18type emojis []emoji
19
20func (e emojis) Len() int {
21	return len(e)
22}
23
24func (e emojis) Less(i, j int) bool {
25	return e[i].Alias < e[j].Alias
26}
27
28func (e emojis) Swap(i, j int) {
29	e[i], e[j] = e[j], e[i]
30}
31
32var emojiData []emoji
33
34func init() {
35	type rawEmoji struct {
36		Emoji   string   `json:"emoji"`
37		Aliases []string `json:"aliases"`
38	}
39	var data []rawEmoji
40	_ = json.Unmarshal(emojiJSON, &data)
41	for _, e := range data {
42		for _, alias := range e.Aliases {
43			emojiData = append(emojiData, emoji{
44				Emoji: e.Emoji,
45				Alias: alias,
46			})
47		}
48	}
49	sort.Sort(emojis(emojiData))
50}
51
52func findEmoji(s string) []emoji {
53	if len(emojiData) == 0 {
54		return nil
55	}
56	i, ok := sort.Find(len(emojiData), func(i int) int {
57		return strings.Compare(s, emojiData[i].Alias)
58	})
59	var b, e int
60	for b = i; b >= 0; b-- {
61		if !strings.HasPrefix(emojiData[b].Alias, s) {
62			break
63		}
64	}
65	b++
66	for e = i; e < len(emojiData); e++ {
67		if !strings.HasPrefix(emojiData[e].Alias, s) {
68			break
69		}
70	}
71	if b >= e {
72		return nil
73	}
74	if ok {
75		r := make([]emoji, 0, e-b)
76		r = append(r, emojiData[i])
77		r = append(r, emojiData[b:i]...)
78		r = append(r, emojiData[i+1:e]...)
79		return r
80	} else {
81		return emojiData[b:e]
82	}
83}