diff --git a/.github/workflows/emojiscraper.yml b/.github/workflows/emojiscraper.yml new file mode 100644 index 0000000..d17ae94 --- /dev/null +++ b/.github/workflows/emojiscraper.yml @@ -0,0 +1,32 @@ +name: Emojiscraper + +on: + workflow_dispatch: + schedule: + - cron: '0 0 * * 0' # Runs every Sunday at midnight UTC + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.22 + + - name: Run emojiscraper + run: make emojiscraper + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v5 + with: + token: ${{ secrets.PAT }} + commit-message: Update dependencies + branch: emojiscraper-updates + commit-message: Update from weekly emojiscraper run + title: "Weekly Emojiscraper Update" + body: "Automated update from the weekly Emojiscraper run." diff --git a/Makefile b/Makefile index 7e3c83b..03eb949 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,26 @@ .PHONY: all format lint clean +# If the first argument is "run"... +ifeq (run,$(firstword $(MAKECMDGOALS))) + # use the rest as arguments for "run" + RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) + # ...and turn them into do-nothing targets + $(eval $(RUN_ARGS):;@:) +endif + GOCMD=go LDFLAGS="-s -w ${LDFLAGS_OPT}" all: build format lint ## Format, lint and build run: ## Run - go run main.go + go run -tags debug main.go $(RUN_ARGS) + +emojiscraper: ## Run emojiscraper + go run -tags debug main.go emojiscraper defaults/static/emojis pkg/emoji_map.go build: ## Build - go build -o bin/go-grip main.go + go build -tags debug -o bin/go-grip main.go test: ## Test ${GOCMD} test ./... diff --git a/README.md b/README.md index 752523d..792559f 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ ## ⚡️Features -* ⚡️Written in Go +* ⚡️Written in Go :+1: :steam_locomotive: * 📄 Render markdown to HTML and view it in your browser * 📱 Dark and white mode * 🎨 Syntax highlighting for code diff --git a/cmd/emojiscraper.go b/cmd/emojiscraper.go new file mode 100644 index 0000000..6a062f4 --- /dev/null +++ b/cmd/emojiscraper.go @@ -0,0 +1,26 @@ +//go:build debug +// +build debug + +package cmd + +import ( + "errors" + + "github.com/chrishrb/go-grip/internal" + "github.com/spf13/cobra" +) + +var emojiscraperCmd = &cobra.Command{ + Use: "emojiscraper [emoji-out] [emoji-map-out]", + Short: "Scrape emojis from gist", + Run: func(cmd *cobra.Command, args []string) { + if len(args) != 2 { + cobra.CheckErr(errors.New("provide exact 2 arguments")) + } + internal.ScrapeEmojis(args[0], args[1]) + }, +} + +func init() { + rootCmd.AddCommand(emojiscraperCmd) +} diff --git a/defaults/static/emojis/bowtie.png b/defaults/static/emojis/bowtie.png new file mode 100644 index 0000000..5616d69 Binary files /dev/null and b/defaults/static/emojis/bowtie.png differ diff --git a/defaults/static/emojis/feelsgood.png b/defaults/static/emojis/feelsgood.png new file mode 100644 index 0000000..891ec43 Binary files /dev/null and b/defaults/static/emojis/feelsgood.png differ diff --git a/defaults/static/emojis/finnadie.png b/defaults/static/emojis/finnadie.png new file mode 100644 index 0000000..90266e2 Binary files /dev/null and b/defaults/static/emojis/finnadie.png differ diff --git a/defaults/static/emojis/goberserk.png b/defaults/static/emojis/goberserk.png new file mode 100644 index 0000000..e617a9d Binary files /dev/null and b/defaults/static/emojis/goberserk.png differ diff --git a/defaults/static/emojis/godmode.png b/defaults/static/emojis/godmode.png new file mode 100644 index 0000000..551111a Binary files /dev/null and b/defaults/static/emojis/godmode.png differ diff --git a/defaults/static/emojis/hurtrealbad.png b/defaults/static/emojis/hurtrealbad.png new file mode 100644 index 0000000..6055841 Binary files /dev/null and b/defaults/static/emojis/hurtrealbad.png differ diff --git a/defaults/static/emojis/neckbeard.png b/defaults/static/emojis/neckbeard.png new file mode 100644 index 0000000..69ccffc Binary files /dev/null and b/defaults/static/emojis/neckbeard.png differ diff --git a/defaults/static/emojis/octocat.png b/defaults/static/emojis/octocat.png new file mode 100644 index 0000000..f9050b9 Binary files /dev/null and b/defaults/static/emojis/octocat.png differ diff --git a/defaults/static/emojis/rage1.png b/defaults/static/emojis/rage1.png new file mode 100644 index 0000000..99a28f2 Binary files /dev/null and b/defaults/static/emojis/rage1.png differ diff --git a/defaults/static/emojis/rage2.png b/defaults/static/emojis/rage2.png new file mode 100644 index 0000000..e91813c Binary files /dev/null and b/defaults/static/emojis/rage2.png differ diff --git a/defaults/static/emojis/rage3.png b/defaults/static/emojis/rage3.png new file mode 100644 index 0000000..36f0733 Binary files /dev/null and b/defaults/static/emojis/rage3.png differ diff --git a/defaults/static/emojis/rage4.png b/defaults/static/emojis/rage4.png new file mode 100644 index 0000000..d1b87ba Binary files /dev/null and b/defaults/static/emojis/rage4.png differ diff --git a/defaults/static/emojis/shipit.png b/defaults/static/emojis/shipit.png new file mode 100644 index 0000000..2d018e6 Binary files /dev/null and b/defaults/static/emojis/shipit.png differ diff --git a/defaults/static/emojis/suspect.png b/defaults/static/emojis/suspect.png new file mode 100644 index 0000000..c4fd15c Binary files /dev/null and b/defaults/static/emojis/suspect.png differ diff --git a/defaults/static/emojis/trollface.png b/defaults/static/emojis/trollface.png new file mode 100644 index 0000000..ee463dc Binary files /dev/null and b/defaults/static/emojis/trollface.png differ diff --git a/go.mod b/go.mod index b84e1b7..4056428 100644 --- a/go.mod +++ b/go.mod @@ -1,18 +1,36 @@ module github.com/chrishrb/go-grip -go 1.22.7 +go 1.23 + +toolchain go1.23.3 require ( + github.com/PuerkitoBio/goquery v1.10.0 // indirect github.com/aarol/reload v1.1.3 // indirect github.com/alecthomas/chroma/v2 v2.14.0 // indirect + github.com/andybalholm/cascadia v1.3.2 // indirect + github.com/antchfx/htmlquery v1.3.3 // indirect + github.com/antchfx/xmlquery v1.4.2 // indirect + github.com/antchfx/xpath v1.3.3 // indirect github.com/bep/debounce v1.2.1 // indirect github.com/dlclark/regexp2 v1.11.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/gocolly/colly v1.2.0 // indirect + github.com/gocolly/colly/v2 v2.1.0 // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/gomarkdown/markdown v0.0.0-20240930133441-72d49d9543d8 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/kennygrant/sanitize v1.2.4 // indirect + github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect github.com/spf13/cobra v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.16.0 // indirect + github.com/temoto/robotstxt v1.1.2 // indirect + golang.org/x/net v0.32.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/protobuf v1.36.0 // indirect ) diff --git a/go.sum b/go.sum index 28ab25c..917504f 100644 --- a/go.sum +++ b/go.sum @@ -1,28 +1,195 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= +github.com/PuerkitoBio/goquery v1.10.0 h1:6fiXdLuUvYs2OJSvNRqlNPoBm6YABE226xrbavY5Wv4= +github.com/PuerkitoBio/goquery v1.10.0/go.mod h1:TjZZl68Q3eGHNBA8CWaxAN7rOU1EbDz3CWuolcO5Yu4= github.com/aarol/reload v1.1.3 h1:cL/LnKVJq1nb9DkOte9kRbPk2qmShFAAItyhvZRlxoA= github.com/aarol/reload v1.1.3/go.mod h1:TmwcyY3/j9gx1Tn3pGjanIQwd/weeFEJFNRTsn7wFDI= github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E= github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I= +github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= +github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxBp0T0eFw1RUQY= +github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= +github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= +github.com/antchfx/htmlquery v1.2.3/go.mod h1:B0ABL+F5irhhMWg54ymEZinzMSi0Kt3I2if0BLYa3V0= +github.com/antchfx/htmlquery v1.3.3 h1:x6tVzrRhVNfECDaVxnZi1mEGrQg3mjE/rxbH2Pe6dNE= +github.com/antchfx/htmlquery v1.3.3/go.mod h1:WeU3N7/rL6mb6dCwtE30dURBnBieKDC/fR8t6X+cKjU= +github.com/antchfx/xmlquery v1.2.4/go.mod h1:KQQuESaxSlqugE2ZBcM/qn+ebIpt+d+4Xx7YcSGAIrM= +github.com/antchfx/xmlquery v1.4.2 h1:MZKd9+wblwxfQ1zd1AdrTsqVaMjMCwow3IqkCSe00KA= +github.com/antchfx/xmlquery v1.4.2/go.mod h1:QXhvf5ldTuGqhd1SHNvvtlhhdQLks4dD0awIVhXIDTA= +github.com/antchfx/xpath v1.1.6/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk= +github.com/antchfx/xpath v1.1.8/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk= +github.com/antchfx/xpath v1.3.2/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= +github.com/antchfx/xpath v1.3.3 h1:tmuPQa1Uye0Ym1Zn65vxPgfltWb/Lxu2jeqIGteJSRs= +github.com/antchfx/xpath v1.3.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gocolly/colly v1.2.0 h1:qRz9YAn8FIH0qzgNUw+HT9UN7wm1oF9OBAilwEWpyrI= +github.com/gocolly/colly v1.2.0/go.mod h1:Hof5T3ZswNVsOHYmba1u03W65HDWgpV5HifSuueE0EA= +github.com/gocolly/colly/v2 v2.1.0 h1:k0DuZkDoCsx51bKpRJNEmcxcp+W5N8ziuwGaSDuFoGs= +github.com/gocolly/colly/v2 v2.1.0/go.mod h1:I2MuhsLjQ+Ex+IzK3afNS8/1qP3AedHOusRPcRdC5o0= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/gomarkdown/markdown v0.0.0-20240930133441-72d49d9543d8 h1:4txT5G2kqVAKMjzidIabL/8KqjIK71yj30YOeuxLn10= github.com/gomarkdown/markdown v0.0.0-20240930133441-72d49d9543d8/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jawher/mow.cli v1.1.0/go.mod h1:aNaQlc7ozF3vw6IJ2dHjp2ZFiA4ozMIYY6PyuRJwlUg= +github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o= +github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= +github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA= +github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/temoto/robotstxt v1.1.1/go.mod h1:+1AmkuG3IYkh1kv0d2qEB9Le88ehNO0zwOr3ujewlOo= +github.com/temoto/robotstxt v1.1.2 h1:W2pOjSJ6SWvldyEuiFXNxz3xZ8aiWX5LbfDiOFd7Fxg= +github.com/temoto/robotstxt v1.1.2/go.mod h1:+1AmkuG3IYkh1kv0d2qEB9Le88ehNO0zwOr3ujewlOo= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.36.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ= +google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/emoji.go b/internal/emoji.go new file mode 100644 index 0000000..5959ac1 --- /dev/null +++ b/internal/emoji.go @@ -0,0 +1,130 @@ +package internal + +import ( + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "strings" + "text/template" + + "github.com/gocolly/colly/v2" +) + +const emojiMapTemplate = `// Code generated by cmd/emojiscraper. DO NOT EDIT. + +package pkg + +var EmojiMap = map[string]string{ +{{- range $key, $value := . }} + "{{$key}}": "{{$value}}", +{{- end }} +}` + +func ScrapeEmojis(emojiOut string, emojiMapOut string) { + c := colly.NewCollector( + colly.AllowedDomains("gist.github.com"), + ) + + emojiMap := map[string]string{} + + c.OnHTML("th", func(e *colly.HTMLElement) { + code, icon := getEmojiFromHtml(emojiOut, e) + if code != "" { + emojiMap[code] = icon + } + }) + + c.OnHTML("td", func(e *colly.HTMLElement) { + code, icon := getEmojiFromHtml(emojiOut, e) + if code != "" { + emojiMap[code] = icon + } + }) + + c.OnRequest(func(r *colly.Request) { + fmt.Println("Visiting", r.URL.String()) + }) + + if err := c.Visit("https://gist.github.com/rxaviers/7360908"); err != nil { + panic(err) + } + + if err := createEmojiMapFile(emojiMap, emojiMapOut); err != nil { + panic(err) + } +} + +func getEmojiFromHtml(outPath string, e *colly.HTMLElement) (string, string) { + content := strings.Split(e.Text, " ") + + if e.ChildText("code") == "" { + return "", "" + } + + emoji := strings.TrimSpace(content[0]) + if emoji == "" { + url := e.ChildAttr("img", "src") + path, err := downloadIcon(outPath, url) + if err != nil { + panic(err) + } + emoji = path + } + + if emoji == content[1] { + return "", "" + } + + return content[1], emoji +} + +func downloadIcon(baseDir, url string) (string, error) { + resp, err := http.Get(url) + if err != nil { + return "", fmt.Errorf("failed to download file: %v", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("bad status: %s", resp.Status) + } + + parts := strings.Split(url, "/") + fileName := parts[len(parts)-1] + destPath := filepath.Join(baseDir, fileName) + htmlPath := filepath.Join("/static/emojis", fileName) + + if err := os.MkdirAll(filepath.Dir(destPath), os.ModePerm); err != nil { + return "", fmt.Errorf("failed to create directories: %v", err) + } + + out, err := os.Create(destPath) + if err != nil { + return "", fmt.Errorf("failed to create file: %v", err) + } + defer out.Close() + + _, err = io.Copy(out, resp.Body) + if err != nil { + return "", fmt.Errorf("failed to write file: %v", err) + } + + return htmlPath, nil +} + +func createEmojiMapFile(emojiMap map[string]string, outputPath string) error { + file, err := os.Create(outputPath) + if err != nil { + return err + } + defer file.Close() + + tmpl, err := template.New("emojiMap").Parse(emojiMapTemplate) + if err != nil { + return err + } + + return tmpl.Execute(file, emojiMap) +} diff --git a/pkg/emoji_map.go b/pkg/emoji_map.go new file mode 100644 index 0000000..f3181e1 --- /dev/null +++ b/pkg/emoji_map.go @@ -0,0 +1,868 @@ +// Code generated by cmd/emojiscraper. DO NOT EDIT. + +package pkg + +var EmojiMap = map[string]string{ + ":+1:": "👍", + ":-1:": "👎", + ":100:": "💯", + ":1234:": "🔢", + ":8ball:": "🎱", + ":a:": "🅰️", + ":ab:": "🆎", + ":abc:": "🔤", + ":abcd:": "🔡", + ":accept:": "🉑", + ":aerial_tramway:": "🚡", + ":airplane:": "✈️", + ":alarm_clock:": "⏰", + ":alien:": "👽", + ":ambulance:": "🚑", + ":anchor:": "⚓", + ":angel:": "👼", + ":anger:": "💢", + ":angry:": "😠", + ":anguished:": "😧", + ":ant:": "🐜", + ":apple:": "🍎", + ":aquarius:": "♒", + ":aries:": "♈", + ":arrow_backward:": "◀️", + ":arrow_double_down:": "⏬", + ":arrow_double_up:": "⏫", + ":arrow_down:": "⬇️", + ":arrow_down_small:": "🔽", + ":arrow_forward:": "▶️", + ":arrow_heading_down:": "⤵️", + ":arrow_heading_up:": "⤴️", + ":arrow_left:": "⬅️", + ":arrow_lower_left:": "↙️", + ":arrow_lower_right:": "↘️", + ":arrow_right:": "➡️", + ":arrow_right_hook:": "↪️", + ":arrow_up:": "⬆️", + ":arrow_up_down:": "↕️", + ":arrow_up_small:": "🔼", + ":arrow_upper_left:": "↖️", + ":arrow_upper_right:": "↗️", + ":arrows_clockwise:": "🔃", + ":arrows_counterclockwise:": "🔄", + ":art:": "🎨", + ":articulated_lorry:": "🚛", + ":astonished:": "😲", + ":atm:": "🏧", + ":b:": "🅱️", + ":baby:": "👶", + ":baby_bottle:": "🍼", + ":baby_chick:": "🐤", + ":baby_symbol:": "🚼", + ":baggage_claim:": "🛄", + ":balloon:": "🎈", + ":ballot_box_with_check:": "☑️", + ":bamboo:": "🎍", + ":banana:": "🍌", + ":bangbang:": "‼️", + ":bank:": "🏦", + ":bar_chart:": "📊", + ":barber:": "💈", + ":baseball:": "⚾", + ":basketball:": "🏀", + ":bath:": "🛀", + ":bathtub:": "🛁", + ":battery:": "🔋", + ":bear:": "🐻", + ":beer:": "🍺", + ":beers:": "🍻", + ":beetle:": "🪲", + ":beginner:": "🔰", + ":bell:": "🔔", + ":bento:": "🍱", + ":bicyclist:": "🚴", + ":bike:": "🚲", + ":bikini:": "👙", + ":bird:": "🐦", + ":birthday:": "🎂", + ":black_circle:": "⚫", + ":black_joker:": "🃏", + ":black_nib:": "✒️", + ":black_square_button:": "🔲", + ":blossom:": "🌼", + ":blowfish:": "🐡", + ":blue_book:": "📘", + ":blue_car:": "🚙", + ":blue_heart:": "💙", + ":blush:": "😊", + ":boar:": "🐗", + ":boat:": "⛵", + ":bomb:": "💣", + ":book:": "📖", + ":bookmark:": "🔖", + ":bookmark_tabs:": "📑", + ":books:": "📚", + ":boom:": "💥", + ":boot:": "👢", + ":bouquet:": "💐", + ":bow:": "🙇", + ":bowling:": "🎳", + ":bowtie:": "/static/emojis/bowtie.png", + ":boy:": "👦", + ":bread:": "🍞", + ":bride_with_veil:": "👰‍♀️", + ":bridge_at_night:": "🌉", + ":briefcase:": "💼", + ":broken_heart:": "💔", + ":bug:": "🐛", + ":bulb:": "💡", + ":bullettrain_front:": "🚅", + ":bullettrain_side:": "🚄", + ":bus:": "🚌", + ":busstop:": "🚏", + ":bust_in_silhouette:": "👤", + ":busts_in_silhouette:": "👥", + ":cactus:": "🌵", + ":cake:": "🍰", + ":calendar:": "📆", + ":calling:": "📲", + ":camel:": "🐫", + ":camera:": "📷", + ":cancer:": "♋", + ":candy:": "🍬", + ":capital_abcd:": "🔠", + ":capricorn:": "♑", + ":car:": "🚗", + ":card_index:": "📇", + ":carousel_horse:": "🎠", + ":cat2:": "🐈", + ":cat:": "🐱", + ":cd:": "💿", + ":chart:": "💹", + ":chart_with_downwards_trend:": "📉", + ":chart_with_upwards_trend:": "📈", + ":checkered_flag:": "🏁", + ":cherries:": "🍒", + ":cherry_blossom:": "🌸", + ":chestnut:": "🌰", + ":chicken:": "🐔", + ":children_crossing:": "🚸", + ":chocolate_bar:": "🍫", + ":christmas_tree:": "🎄", + ":church:": "⛪", + ":cinema:": "🎦", + ":circus_tent:": "🎪", + ":city_sunrise:": "🌇", + ":city_sunset:": "🌆", + ":cl:": "🆑", + ":clap:": "👏", + ":clapper:": "🎬", + ":clipboard:": "📋", + ":clock1030:": "🕥", + ":clock10:": "🕙", + ":clock1130:": "🕦", + ":clock11:": "🕚", + ":clock1230:": "🕧", + ":clock12:": "🕛", + ":clock130:": "🕜", + ":clock1:": "🕐", + ":clock230:": "🕝", + ":clock2:": "🕑", + ":clock330:": "🕞", + ":clock3:": "🕒", + ":clock430:": "🕟", + ":clock4:": "🕓", + ":clock530:": "🕠", + ":clock5:": "🕔", + ":clock630:": "🕡", + ":clock6:": "🕕", + ":clock730:": "🕢", + ":clock7:": "🕖", + ":clock830:": "🕣", + ":clock8:": "🕗", + ":clock930:": "🕤", + ":clock9:": "🕘", + ":closed_book:": "📕", + ":closed_lock_with_key:": "🔐", + ":closed_umbrella:": "🌂", + ":cloud:": "☁️", + ":clubs:": "♣️", + ":cn:": "🇨🇳", + ":cocktail:": "🍸", + ":coffee:": "☕", + ":cold_sweat:": "😰", + ":collision:": "💥", + ":computer:": "💻", + ":confetti_ball:": "🎊", + ":confounded:": "😖", + ":confused:": "😕", + ":congratulations:": "㊗️", + ":construction:": "🚧", + ":construction_worker:": "👷", + ":convenience_store:": "🏪", + ":cookie:": "🍪", + ":cool:": "🆒", + ":cop:": "👮", + ":copyright:": "©️", + ":corn:": "🌽", + ":couple:": "👫", + ":couple_with_heart:": "💑", + ":couplekiss:": "💏", + ":cow2:": "🐄", + ":cow:": "🐮", + ":credit_card:": "💳", + ":crocodile:": "🐊", + ":crossed_flags:": "🎌", + ":crown:": "👑", + ":cry:": "😢", + ":crying_cat_face:": "😿", + ":crystal_ball:": "🔮", + ":cupid:": "💘", + ":curly_loop:": "➰", + ":currency_exchange:": "💱", + ":curry:": "🍛", + ":custard:": "🍮", + ":customs:": "🛃", + ":cyclone:": "🌀", + ":dancer:": "💃", + ":dancers:": "👯", + ":dango:": "🍡", + ":dart:": "🎯", + ":dash:": "💨", + ":date:": "📅", + ":de:": "🇩🇪", + ":deciduous_tree:": "🌳", + ":department_store:": "🏬", + ":diamond_shape_with_a_dot_inside:": "💠", + ":diamonds:": "♦️", + ":disappointed:": "😞", + ":disappointed_relieved:": "😥", + ":dizzy:": "💫", + ":dizzy_face:": "😵", + ":do_not_litter:": "🚯", + ":dog2:": "🐕", + ":dog:": "🐶", + ":dollar:": "💵", + ":dolls:": "🎎", + ":dolphin:": "🐬", + ":door:": "🚪", + ":doughnut:": "🍩", + ":dragon:": "🐉", + ":dragon_face:": "🐲", + ":dress:": "👗", + ":dromedary_camel:": "🐪", + ":droplet:": "💧", + ":dvd:": "📀", + ":e-mail:": "📧", + ":ear:": "👂", + ":ear_of_rice:": "🌾", + ":earth_africa:": "🌍", + ":earth_americas:": "🌎", + ":earth_asia:": "🌏", + ":egg:": "🥚", + ":eggplant:": "🍆", + ":eight:": "8️⃣", + ":eight_pointed_black_star:": "✴️", + ":eight_spoked_asterisk:": "✳️", + ":electric_plug:": "🔌", + ":elephant:": "🐘", + ":email:": "📧", + ":end:": "🔚", + ":envelope:": "✉️", + ":es:": "🇪🇸", + ":euro:": "💶", + ":european_castle:": "🏰", + ":european_post_office:": "🏤", + ":evergreen_tree:": "🌲", + ":exclamation:": "❗", + ":expressionless:": "😑", + ":eyeglasses:": "👓", + ":eyes:": "👀", + ":facepunch:": "👊", + ":factory:": "🏭", + ":fallen_leaf:": "🍂", + ":family:": "👪", + ":fast_forward:": "⏩", + ":fax:": "📠", + ":fearful:": "😨", + ":feelsgood:": "/static/emojis/feelsgood.png", + ":feet:": "🐾", + ":ferris_wheel:": "🎡", + ":file_folder:": "📁", + ":finnadie:": "/static/emojis/finnadie.png", + ":fire:": "🔥", + ":fire_engine:": "🚒", + ":fireworks:": "🎆", + ":first_quarter_moon:": "🌓", + ":first_quarter_moon_with_face:": "🌛", + ":fish:": "🐟", + ":fish_cake:": "🍥", + ":fishing_pole_and_fish:": "🎣", + ":fist:": "✊", + ":five:": "5️⃣", + ":flags:": "🎏", + ":flashlight:": "🔦", + ":floppy_disk:": "💾", + ":flower_playing_cards:": "🎴", + ":flushed:": "😳", + ":foggy:": "🌁", + ":football:": "🏈", + ":fork_and_knife:": "🍴", + ":fountain:": "⛲", + ":four:": "4️⃣", + ":four_leaf_clover:": "🍀", + ":fr:": "🇫🇷", + ":free:": "🆓", + ":fried_shrimp:": "🍤", + ":fries:": "🍟", + ":frog:": "🐸", + ":frowning:": "😦", + ":fu:": "🖕", + ":fuelpump:": "⛽", + ":full_moon:": "🌕", + ":full_moon_with_face:": "🌝", + ":game_die:": "🎲", + ":gb:": "🇬🇧", + ":gem:": "💎", + ":gemini:": "♊", + ":ghost:": "👻", + ":gift:": "🎁", + ":gift_heart:": "💝", + ":girl:": "👧", + ":globe_with_meridians:": "🌐", + ":goat:": "🐐", + ":goberserk:": "/static/emojis/goberserk.png", + ":godmode:": "/static/emojis/godmode.png", + ":golf:": "⛳", + ":grapes:": "🍇", + ":green_apple:": "🍏", + ":green_book:": "📗", + ":green_heart:": "💚", + ":grey_exclamation:": "❕", + ":grey_question:": "❔", + ":grimacing:": "😬", + ":grin:": "😁", + ":grinning:": "😀", + ":guardsman:": "💂‍♂️", + ":guitar:": "🎸", + ":gun:": "🔫", + ":haircut:": "💇", + ":hamburger:": "🍔", + ":hammer:": "🔨", + ":hamster:": "🐹", + ":hand:": "✋", + ":handbag:": "👜", + ":hankey:": "💩", + ":hash:": "#️⃣", + ":hatched_chick:": "🐥", + ":hatching_chick:": "🐣", + ":headphones:": "🎧", + ":hear_no_evil:": "🙉", + ":heart:": "❤️", + ":heart_decoration:": "💟", + ":heart_eyes:": "😍", + ":heart_eyes_cat:": "😻", + ":heartbeat:": "💓", + ":heartpulse:": "💗", + ":hearts:": "♥️", + ":heavy_check_mark:": "✔️", + ":heavy_division_sign:": "➗", + ":heavy_dollar_sign:": "💲", + ":heavy_exclamation_mark:": "❗", + ":heavy_minus_sign:": "➖", + ":heavy_multiplication_x:": "✖️", + ":heavy_plus_sign:": "➕", + ":helicopter:": "🚁", + ":herb:": "🌿", + ":hibiscus:": "🌺", + ":high_brightness:": "🔆", + ":high_heel:": "👠", + ":hocho:": "🔪", + ":honey_pot:": "🍯", + ":honeybee:": "🐝", + ":horse:": "🐴", + ":horse_racing:": "🏇", + ":hospital:": "🏥", + ":hotel:": "🏨", + ":hotsprings:": "♨️", + ":hourglass:": "⌛", + ":hourglass_flowing_sand:": "⏳", + ":house:": "🏠", + ":house_with_garden:": "🏡", + ":hurtrealbad:": "/static/emojis/hurtrealbad.png", + ":hushed:": "😯", + ":ice_cream:": "🍨", + ":icecream:": "🍦", + ":id:": "🆔", + ":ideograph_advantage:": "🉐", + ":imp:": "👿", + ":inbox_tray:": "📥", + ":incoming_envelope:": "📨", + ":information_desk_person:": "💁", + ":information_source:": "ℹ️", + ":innocent:": "😇", + ":interrobang:": "⁉️", + ":iphone:": "📱", + ":it:": "🇮🇹", + ":izakaya_lantern:": "🏮", + ":jack_o_lantern:": "🎃", + ":japan:": "🗾", + ":japanese_castle:": "🏯", + ":japanese_goblin:": "👺", + ":japanese_ogre:": "👹", + ":jeans:": "👖", + ":joy:": "😂", + ":joy_cat:": "😹", + ":jp:": "🇯🇵", + ":key:": "🔑", + ":keycap_ten:": "🔟", + ":kimono:": "👘", + ":kiss:": "💋", + ":kissing:": "😗", + ":kissing_cat:": "😽", + ":kissing_closed_eyes:": "😚", + ":kissing_heart:": "😘", + ":kissing_smiling_eyes:": "😙", + ":koala:": "🐨", + ":koko:": "🈁", + ":kr:": "🇰🇷", + ":large_blue_circle:": "🔵", + ":large_blue_diamond:": "🔷", + ":large_orange_diamond:": "🔶", + ":last_quarter_moon:": "🌗", + ":last_quarter_moon_with_face:": "🌜", + ":laughing:": "😆", + ":leaves:": "🍃", + ":ledger:": "📒", + ":left_luggage:": "🛅", + ":left_right_arrow:": "↔️", + ":leftwards_arrow_with_hook:": "↩️", + ":lemon:": "🍋", + ":leo:": "♌", + ":leopard:": "🐆", + ":libra:": "♎", + ":light_rail:": "🚈", + ":link:": "🔗", + ":lips:": "👄", + ":lipstick:": "💄", + ":lock:": "🔒", + ":lock_with_ink_pen:": "🔏", + ":lollipop:": "🍭", + ":loop:": "➿", + ":loudspeaker:": "📢", + ":love_hotel:": "🏩", + ":love_letter:": "💌", + ":low_brightness:": "🔅", + ":m:": "Ⓜ️", + ":mag:": "🔍", + ":mag_right:": "🔎", + ":mahjong:": "🀄", + ":mailbox:": "📫", + ":mailbox_closed:": "📪", + ":mailbox_with_mail:": "📬", + ":mailbox_with_no_mail:": "📭", + ":man:": "👨", + ":man_with_gua_pi_mao:": "👲", + ":man_with_turban:": "👳‍♂️", + ":mans_shoe:": "👞", + ":maple_leaf:": "🍁", + ":mask:": "😷", + ":massage:": "💆", + ":meat_on_bone:": "🍖", + ":mega:": "📣", + ":melon:": "🍈", + ":memo:": "📝", + ":mens:": "🚹", + ":metal:": "🤘", + ":metro:": "🚇", + ":microphone:": "🎤", + ":microscope:": "🔬", + ":milky_way:": "🌌", + ":minibus:": "🚐", + ":minidisc:": "💽", + ":mobile_phone_off:": "📴", + ":money_with_wings:": "💸", + ":moneybag:": "💰", + ":monkey:": "🐒", + ":monkey_face:": "🐵", + ":monorail:": "🚝", + ":moon:": "🌔", + ":mortar_board:": "🎓", + ":mount_fuji:": "🗻", + ":mountain_bicyclist:": "🚵", + ":mountain_cableway:": "🚠", + ":mountain_railway:": "🚞", + ":mouse2:": "🐁", + ":mouse:": "🐭", + ":movie_camera:": "🎥", + ":moyai:": "🗿", + ":muscle:": "💪", + ":mushroom:": "🍄", + ":musical_keyboard:": "🎹", + ":musical_note:": "🎵", + ":musical_score:": "🎼", + ":mute:": "🔇", + ":nail_care:": "💅", + ":name_badge:": "📛", + ":neckbeard:": "/static/emojis/neckbeard.png", + ":necktie:": "👔", + ":negative_squared_cross_mark:": "❎", + ":neutral_face:": "😐", + ":new:": "🆕", + ":new_moon:": "🌑", + ":new_moon_with_face:": "🌚", + ":newspaper:": "📰", + ":ng:": "🆖", + ":nine:": "9️⃣", + ":no_bell:": "🔕", + ":no_bicycles:": "🚳", + ":no_entry:": "⛔", + ":no_entry_sign:": "🚫", + ":no_good:": "🙅", + ":no_mobile_phones:": "📵", + ":no_mouth:": "😶", + ":no_pedestrians:": "🚷", + ":no_smoking:": "🚭", + ":non-potable_water:": "🚱", + ":nose:": "👃", + ":notebook:": "📓", + ":notebook_with_decorative_cover:": "📔", + ":notes:": "🎶", + ":nut_and_bolt:": "🔩", + ":o2:": "🅾️", + ":o:": "⭕", + ":ocean:": "🌊", + ":octocat:": "/static/emojis/octocat.png", + ":octopus:": "🐙", + ":oden:": "🍢", + ":office:": "🏢", + ":ok:": "🆗", + ":ok_hand:": "👌", + ":ok_woman:": "🙆‍♀️", + ":older_man:": "👴", + ":older_woman:": "👵", + ":on:": "🔛", + ":oncoming_automobile:": "🚘", + ":oncoming_bus:": "🚍", + ":oncoming_police_car:": "🚔", + ":oncoming_taxi:": "🚖", + ":one:": "1️⃣", + ":open_file_folder:": "📂", + ":open_hands:": "👐", + ":open_mouth:": "😮", + ":ophiuchus:": "⛎", + ":orange_book:": "📙", + ":outbox_tray:": "📤", + ":ox:": "🐂", + ":page_facing_up:": "📄", + ":page_with_curl:": "📃", + ":pager:": "📟", + ":palm_tree:": "🌴", + ":panda_face:": "🐼", + ":paperclip:": "📎", + ":parking:": "🅿️", + ":part_alternation_mark:": "〽️", + ":partly_sunny:": "⛅", + ":passport_control:": "🛂", + ":paw_prints:": "🐾", + ":peach:": "🍑", + ":pear:": "🍐", + ":pencil2:": "✏️", + ":pencil:": "📝", + ":penguin:": "🐧", + ":pensive:": "😔", + ":performing_arts:": "🎭", + ":persevere:": "😣", + ":phone:": "☎️", + ":pig2:": "🐖", + ":pig:": "🐷", + ":pig_nose:": "🐽", + ":pill:": "💊", + ":pineapple:": "🍍", + ":pisces:": "♓", + ":pizza:": "🍕", + ":point_down:": "👇", + ":point_left:": "👈", + ":point_right:": "👉", + ":point_up:": "☝️", + ":point_up_2:": "👆", + ":police_car:": "🚓", + ":poodle:": "🐩", + ":poop:": "💩", + ":post_office:": "🏣", + ":postal_horn:": "📯", + ":postbox:": "📮", + ":potable_water:": "🚰", + ":pouch:": "👝", + ":poultry_leg:": "🍗", + ":pound:": "💷", + ":pouting_cat:": "😾", + ":pray:": "🙏", + ":princess:": "👸", + ":punch:": "👊", + ":purple_heart:": "💜", + ":purse:": "👛", + ":pushpin:": "📌", + ":put_litter_in_its_place:": "🚮", + ":question:": "❓", + ":rabbit2:": "🐇", + ":rabbit:": "🐰", + ":racehorse:": "🐎", + ":radio:": "📻", + ":radio_button:": "🔘", + ":rage1:": "/static/emojis/rage1.png", + ":rage2:": "/static/emojis/rage2.png", + ":rage3:": "/static/emojis/rage3.png", + ":rage4:": "/static/emojis/rage4.png", + ":rage:": "😡", + ":railway_car:": "🚃", + ":rainbow:": "🌈", + ":raised_hand:": "✋", + ":raised_hands:": "🙌", + ":raising_hand:": "🙋", + ":ram:": "🐏", + ":ramen:": "🍜", + ":rat:": "🐀", + ":recycle:": "♻️", + ":red_car:": "🚗", + ":red_circle:": "🔴", + ":registered:": "®️", + ":relaxed:": "☺️", + ":relieved:": "😌", + ":repeat:": "🔁", + ":repeat_one:": "🔂", + ":restroom:": "🚻", + ":revolving_hearts:": "💞", + ":rewind:": "⏪", + ":ribbon:": "🎀", + ":rice:": "🍚", + ":rice_ball:": "🍙", + ":rice_cracker:": "🍘", + ":rice_scene:": "🎑", + ":ring:": "💍", + ":rocket:": "🚀", + ":roller_coaster:": "🎢", + ":rooster:": "🐓", + ":rose:": "🌹", + ":rotating_light:": "🚨", + ":round_pushpin:": "📍", + ":rowboat:": "🚣", + ":ru:": "🇷🇺", + ":rugby_football:": "🏉", + ":runner:": "🏃", + ":running:": "🏃", + ":running_shirt_with_sash:": "🎽", + ":sa:": "🈂️", + ":sagittarius:": "♐", + ":sailboat:": "⛵", + ":sake:": "🍶", + ":sandal:": "👡", + ":santa:": "🎅", + ":satellite:": "📡", + ":satisfied:": "😆", + ":saxophone:": "🎷", + ":school:": "🏫", + ":school_satchel:": "🎒", + ":scissors:": "✂️", + ":scorpius:": "♏", + ":scream:": "😱", + ":scream_cat:": "🙀", + ":scroll:": "📜", + ":seat:": "💺", + ":secret:": "㊙️", + ":see_no_evil:": "🙈", + ":seedling:": "🌱", + ":seven:": "7️⃣", + ":shaved_ice:": "🍧", + ":sheep:": "🐑", + ":shell:": "🐚", + ":ship:": "🚢", + ":shipit:": "/static/emojis/shipit.png", + ":shirt:": "👕", + ":shit:": "💩", + ":shoe:": "👞", + ":shower:": "🚿", + ":signal_strength:": "📶", + ":six:": "6️⃣", + ":six_pointed_star:": "🔯", + ":ski:": "🎿", + ":skull:": "💀", + ":sleeping:": "😴", + ":sleepy:": "😪", + ":slot_machine:": "🎰", + ":small_blue_diamond:": "🔹", + ":small_orange_diamond:": "🔸", + ":small_red_triangle:": "🔺", + ":small_red_triangle_down:": "🔻", + ":smile:": "😄", + ":smile_cat:": "😸", + ":smiley:": "😃", + ":smiley_cat:": "😺", + ":smiling_imp:": "😈", + ":smirk:": "😏", + ":smirk_cat:": "😼", + ":smoking:": "🚬", + ":snail:": "🐌", + ":snake:": "🐍", + ":snowboarder:": "🏂", + ":snowflake:": "❄️", + ":snowman:": "⛄", + ":sob:": "😭", + ":soccer:": "⚽", + ":soon:": "🔜", + ":sos:": "🆘", + ":sound:": "🔉", + ":space_invader:": "👾", + ":spades:": "♠️", + ":spaghetti:": "🍝", + ":sparkler:": "🎇", + ":sparkles:": "✨", + ":sparkling_heart:": "💖", + ":speak_no_evil:": "🙊", + ":speaker:": "🔈", + ":speech_balloon:": "💬", + ":speedboat:": "🚤", + ":star2:": "🌟", + ":star:": "⭐", + ":stars:": "🌠", + ":station:": "🚉", + ":statue_of_liberty:": "🗽", + ":steam_locomotive:": "🚂", + ":stew:": "🍲", + ":straight_ruler:": "📏", + ":strawberry:": "🍓", + ":stuck_out_tongue:": "😛", + ":stuck_out_tongue_closed_eyes:": "😝", + ":stuck_out_tongue_winking_eye:": "😜", + ":sun_with_face:": "🌞", + ":sunflower:": "🌻", + ":sunglasses:": "😎", + ":sunny:": "☀️", + ":sunrise:": "🌅", + ":sunrise_over_mountains:": "🌄", + ":surfer:": "🏄", + ":sushi:": "🍣", + ":suspect:": "/static/emojis/suspect.png", + ":suspension_railway:": "🚟", + ":sweat:": "😓", + ":sweat_drops:": "💦", + ":sweat_smile:": "😅", + ":sweet_potato:": "🍠", + ":swimmer:": "🏊", + ":symbols:": "🔣", + ":syringe:": "💉", + ":tada:": "🎉", + ":tanabata_tree:": "🎋", + ":tangerine:": "🍊", + ":taurus:": "♉", + ":taxi:": "🚕", + ":tea:": "🍵", + ":telephone:": "☎️", + ":telephone_receiver:": "📞", + ":telescope:": "🔭", + ":tennis:": "🎾", + ":tent:": "⛺", + ":thought_balloon:": "💭", + ":three:": "3️⃣", + ":thumbsdown:": "👎", + ":thumbsup:": "👍", + ":ticket:": "🎫", + ":tiger2:": "🐅", + ":tiger:": "🐯", + ":tired_face:": "😫", + ":tm:": "™️", + ":toilet:": "🚽", + ":tokyo_tower:": "🗼", + ":tomato:": "🍅", + ":tongue:": "👅", + ":top:": "🔝", + ":tophat:": "🎩", + ":tractor:": "🚜", + ":traffic_light:": "🚥", + ":train2:": "🚆", + ":train:": "🚋", + ":tram:": "🚊", + ":triangular_flag_on_post:": "🚩", + ":triangular_ruler:": "📐", + ":trident:": "🔱", + ":triumph:": "😤", + ":trolleybus:": "🚎", + ":trollface:": "/static/emojis/trollface.png", + ":trophy:": "🏆", + ":tropical_drink:": "🍹", + ":tropical_fish:": "🐠", + ":truck:": "🚚", + ":trumpet:": "🎺", + ":tshirt:": "👕", + ":tulip:": "🌷", + ":turtle:": "🐢", + ":tv:": "📺", + ":twisted_rightwards_arrows:": "🔀", + ":two:": "2️⃣", + ":two_hearts:": "💕", + ":two_men_holding_hands:": "👬", + ":two_women_holding_hands:": "👭", + ":u5272:": "🈹", + ":u5408:": "🈴", + ":u55b6:": "🈺", + ":u6307:": "🈯", + ":u6708:": "🈷️", + ":u6709:": "🈶", + ":u6e80:": "🈵", + ":u7121:": "🈚", + ":u7533:": "🈸", + ":u7981:": "🈲", + ":u7a7a:": "🈳", + ":uk:": "🇬🇧", + ":umbrella:": "☔", + ":unamused:": "😒", + ":underage:": "🔞", + ":unlock:": "🔓", + ":up:": "🆙", + ":us:": "🇺🇸", + ":v:": "✌️", + ":vertical_traffic_light:": "🚦", + ":vhs:": "📼", + ":vibration_mode:": "📳", + ":video_camera:": "📹", + ":video_game:": "🎮", + ":violin:": "🎻", + ":virgo:": "♍", + ":volcano:": "🌋", + ":vs:": "🆚", + ":walking:": "🚶", + ":waning_crescent_moon:": "🌘", + ":waning_gibbous_moon:": "🌖", + ":warning:": "⚠️", + ":watch:": "⌚", + ":water_buffalo:": "🐃", + ":watermelon:": "🍉", + ":wave:": "👋", + ":wavy_dash:": "〰️", + ":waxing_crescent_moon:": "🌒", + ":waxing_gibbous_moon:": "🌔", + ":wc:": "🚾", + ":weary:": "😩", + ":wedding:": "💒", + ":whale2:": "🐋", + ":whale:": "🐳", + ":wheelchair:": "♿", + ":white_check_mark:": "✅", + ":white_circle:": "⚪", + ":white_flower:": "💮", + ":white_square_button:": "🔳", + ":wind_chime:": "🎐", + ":wine_glass:": "🍷", + ":wink:": "😉", + ":wolf:": "🐺", + ":woman:": "👩", + ":womans_clothes:": "👚", + ":womans_hat:": "👒", + ":womens:": "🚺", + ":worried:": "😟", + ":wrench:": "🔧", + ":x:": "❌", + ":yellow_heart:": "💛", + ":yen:": "💴", + ":yum:": "😋", + ":zap:": "⚡", + ":zero:": "0️⃣", + ":zzz:": "💤", +} diff --git a/pkg/parser.go b/pkg/parser.go index fb4a44e..88d57ff 100644 --- a/pkg/parser.go +++ b/pkg/parser.go @@ -7,6 +7,7 @@ import ( "io" "log" "path/filepath" + "regexp" "strings" "github.com/alecthomas/chroma/v2/quick" @@ -118,16 +119,34 @@ func renderHookBlockquote(w io.Writer, node ast.Node, entering bool) (ast.WalkSt func renderHookText(w io.Writer, node ast.Node) (ast.WalkStatus, bool) { block := node.(*ast.Text) + r := regexp.MustCompile(`(:\S+:)`) + withEmoji := r.ReplaceAllStringFunc(string(block.Literal), func(s string) string { + val, ok := EmojiMap[s] + if !ok { + return s + } + + if strings.HasPrefix(val, "/") { + return fmt.Sprintf(`%s`, s, s, val) + } + + return val + }) + paragraph, ok := block.GetParent().(*ast.Paragraph) if !ok { - return ast.GoToNext, false + _, err := io.WriteString(w, withEmoji) + if err != nil { + log.Println("Error:", err) + } + return ast.GoToNext, true } _, ok = paragraph.GetParent().(*ast.BlockQuote) if ok { // Remove prefixes for _, b := range blockquotes { - content, found := strings.CutPrefix(string(block.Literal), fmt.Sprintf("[!%s]", strings.ToUpper(b))) + content, found := strings.CutPrefix(withEmoji, fmt.Sprintf("[!%s]", strings.ToUpper(b))) if found { _, err := io.WriteString(w, content) if err != nil { @@ -140,7 +159,7 @@ func renderHookText(w io.Writer, node ast.Node) (ast.WalkStatus, bool) { _, ok = paragraph.GetParent().(*ast.ListItem) if ok { - content, found := strings.CutPrefix(string(block.Literal), "[ ]") + content, found := strings.CutPrefix(withEmoji, "[ ]") content = ` ` + content if found { _, err := io.WriteString(w, content) @@ -150,7 +169,7 @@ func renderHookText(w io.Writer, node ast.Node) (ast.WalkStatus, bool) { return ast.GoToNext, true } - content, found = strings.CutPrefix(string(block.Literal), "[x]") + content, found = strings.CutPrefix(withEmoji, "[x]") content = ` ` + content if found { _, err := io.WriteString(w, content) @@ -160,7 +179,11 @@ func renderHookText(w io.Writer, node ast.Node) (ast.WalkStatus, bool) { } } - return ast.GoToNext, false + _, err := io.WriteString(w, withEmoji) + if err != nil { + log.Println("Error:", err) + } + return ast.GoToNext, true } func renderHookListItem(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) {