emoji.go (view raw)
1package emoji
2
3import (
4 "fmt"
5 "html"
6 "strings"
7)
8
9// Base attributes
10const (
11 unicodeFlagBaseIndex = 127397
12)
13
14// Skin tone colors
15const (
16 Default Tone = ""
17 Light Tone = "\U0001F3FB"
18 MediumLight Tone = "\U0001F3FC"
19 Medium Tone = "\U0001F3FD"
20 MediumDark Tone = "\U0001F3FE"
21 Dark Tone = "\U0001F3FF"
22)
23
24// Emoji defines an emoji object.
25type Emoji string
26
27func (e Emoji) String() string {
28 return string(e)
29}
30
31// EmojiWithTone defines an emoji object that has skin tone options.
32type EmojiWithTone Emoji
33
34func (e EmojiWithTone) String() string {
35 return strings.ReplaceAll(string(e), "@", string(Default))
36}
37
38// Tone returns an emoji object with given skin tone.
39func (e EmojiWithTone) Tone(tones ...Tone) EmojiWithTone {
40 str := string(e)
41 for _, tone := range tones {
42 str = strings.Replace(str, "@", string(tone), 1)
43 }
44
45 if strings.Count(str, "@") > 0 {
46 lastTone := tones[len(tones)-1]
47 str = strings.ReplaceAll(str, "@", string(lastTone))
48 }
49
50 return EmojiWithTone(str)
51}
52
53// Tone defines skin tone options for emojis.
54type Tone string
55
56func (t Tone) String() string {
57 return string(t)
58}
59
60// CountryFlag returns a country flag emoji from given country code.
61// Full list of country codes: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
62func CountryFlag(code string) (Emoji, error) {
63 if len(code) != 2 {
64 return "", fmt.Errorf("not valid country code: %q", code)
65 }
66
67 code = strings.ToUpper(code)
68 flag := countryCodeLetter(code[0]) + countryCodeLetter(code[1])
69
70 return Emoji(flag), nil
71}
72
73// countryCodeLetter shifts given letter byte as unicodeFlagBaseIndex and changes encoding
74func countryCodeLetter(l byte) string {
75 return html.UnescapeString(fmt.Sprintf("&#%v;", unicodeFlagBaseIndex+int(l)))
76}