diff --git a/docs/integrations.md b/docs/integrations.md index 3eddb5e6..d1a4d42c 100644 --- a/docs/integrations.md +++ b/docs/integrations.md @@ -104,6 +104,7 @@ I've added a โญ to projects or posts that have a significant following, or had - [ntfy_on_a_chip](https://github.com/gergepalfi/ntfy_on_a_chip) - ESP8266 and ESP32 client code to communicate with ntfy - [ntfy-sdk](https://github.com/yukibtc/ntfy-sdk) - ntfy client library to send notifications (Rust) - [ntfy_ynh](https://github.com/YunoHost-Apps/ntfy_ynh) - ntfy app for YunoHost +- [woodpecker-ntfy](https://codeberg.org/l-x/woodpecker-ntfy)- Woodpecker CI plugin for sending ntfy notfication from a pipeline (Go) - [drone-ntfy](https://github.com/Clortox/drone-ntfy) - Drone.io plugin for sending ntfy notifications from a pipeline (Shell) - [ignition-ntfy-module](https://github.com/Kyvis-Labs/ignition-ntfy-module) - Adds support for sending notifications via a ntfy server to Ignition (Java) - [maubot-ntfy](https://gitlab.com/999eagle/maubot-ntfy) - Matrix bot to subscribe to ntfy topics and send messages to Matrix (Python) diff --git a/docs/publish.md b/docs/publish.md index 72398a7c..ef4c9a86 100644 --- a/docs/publish.md +++ b/docs/publish.md @@ -2702,7 +2702,7 @@ You can use ntfy to call a phone and **read the message out loud using text-to-s Similar to email notifications, this can be useful to blast-notify yourself on all possible channels, or to notify people that do not have the ntfy app installed on their phone. -Phone numbers have to be previously verified (via the web app). To forward a message as a phone call, pass a phone number +Phone numbers have to be previously verified (via the web app). To forward a message as a voice call, pass a phone number in the `X-Call` header (or its alias: `Call`), prefixed with a plus sign and the country code, e.g. `+12223334444`. You may also simply pass `yes` as a value if you only have one verified phone number. diff --git a/docs/releases.md b/docs/releases.md index 37ccd4bc..17debf07 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -1182,13 +1182,17 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release **Features:** -* Support for SMS and voice calls using Twilio (no ticket) +* Support for text-to-speech style [phone calls](publish.md#phone-calls) using the `X-Call` header (no ticket) +* Admin API to manage users and ACL, `v1/users` + `v1/users/access` ([#722](https://github.com/binwiederhier/ntfy/issues/722), thanks to [@CreativeWarlock](https://github.com/CreativeWarlock) for sponsoring this ticket) **Bug fixes + maintenance:** * Removed old ntfy website from ntfy entirely (no ticket) +* Make emoji lookup for emails more efficient ([#725](https://github.com/binwiederhier/ntfy/pull/725), thanks to [@adamantike](https://github.com/adamantike)) * Fix potential subscriber ID clash ([#712](https://github.com/binwiederhier/ntfy/issues/712), thanks to [@peterbourgon](https://github.com/peterbourgon) for reporting, and [@dropdevrahul](https://github.com/dropdevrahul) for fixing) * Support for `quoted-printable` in incoming emails ([#719](https://github.com/binwiederhier/ntfy/pull/719), thanks to [@Aerion](https://github.com/Aerion)) +* Attachments with filenames that are downloaded using a browser will now download with the proper filename ([#726](https://github.com/binwiederhier/ntfy/issues/726), thanks to [@un99known99](https://github.com/un99known99) for reporting, and [@wunter8](https://github.com/wunter8) for fixing) +* Fix web app i18n issue in account preferences ([#730](https://github.com/binwiederhier/ntfy/issues/730), thanks to [@codebude](https://github.com/codebude) for reporting) ### ntfy Android app v1.16.1 (UNRELEASED) diff --git a/go.mod b/go.mod index ca02fff2..1f4c9e75 100644 --- a/go.mod +++ b/go.mod @@ -14,12 +14,12 @@ require ( github.com/olebedev/when v0.0.0-20221205223600-4d190b02b8d8 github.com/stretchr/testify v1.8.1 github.com/urfave/cli/v2 v2.25.3 - golang.org/x/crypto v0.8.0 - golang.org/x/oauth2 v0.7.0 // indirect + golang.org/x/crypto v0.9.0 + golang.org/x/oauth2 v0.8.0 // indirect golang.org/x/sync v0.2.0 golang.org/x/term v0.8.0 golang.org/x/time v0.3.0 - google.golang.org/api v0.121.0 + google.golang.org/api v0.122.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -28,15 +28,15 @@ require github.com/pkg/errors v0.9.1 // indirect require ( firebase.google.com/go/v4 v4.11.0 github.com/prometheus/client_golang v1.15.1 - github.com/stripe/stripe-go/v74 v74.17.0 + github.com/stripe/stripe-go/v74 v74.18.0 ) require ( - cloud.google.com/go v0.110.1 // indirect - cloud.google.com/go/compute v1.19.1 // indirect + cloud.google.com/go v0.110.2 // indirect + cloud.google.com/go/compute v1.19.2 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.0.0 // indirect - cloud.google.com/go/longrunning v0.4.1 // indirect + cloud.google.com/go/iam v1.0.1 // indirect + cloud.google.com/go/longrunning v0.4.2 // indirect github.com/AlekSi/pointer v1.2.0 // indirect github.com/MicahParks/keyfunc v1.9.0 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -57,12 +57,11 @@ require ( github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.43.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/net v0.9.0 // indirect + golang.org/x/net v0.10.0 // indirect golang.org/x/sys v0.8.0 // indirect golang.org/x/text v0.9.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect diff --git a/go.sum b/go.sum index 965c4378..ccb1ae4d 100644 --- a/go.sum +++ b/go.sum @@ -1,19 +1,25 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= -cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= cloud.google.com/go v0.110.1 h1:oDJ19Fu9TX9Xs06iyCw4yifSqZ7JQ8BeuVHcTmWQlOA= cloud.google.com/go v0.110.1/go.mod h1:uc+V/WjzxQ7vpkxfJhgW4Q4axWXyfAerpQOuSNDZyFw= +cloud.google.com/go v0.110.2 h1:sdFPBr6xG9/wkBbfhmUz/JmZC7X6LavQgcrVINrKiVA= +cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute v1.19.2 h1:GbJtPo8OKVHbVep8jvM57KidbYHxeE68LOVqouNLrDY= +cloud.google.com/go/compute v1.19.2/go.mod h1:5f5a+iC1IriXYauaQ0EyQmEAEq9CGRnV5xJSQSlTV08= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/firestore v1.9.0 h1:IBlRyxgGySXu5VuW0RgGFlTtLukSnNkpDiEOMkQkmpA= cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= cloud.google.com/go/iam v1.0.0 h1:hlQJMovyJJwYjZcTohUH4o1L8Z8kYz+E+W/zktiLCBc= cloud.google.com/go/iam v1.0.0/go.mod h1:ikbQ4f1r91wTmBmmOtBCOtuEOei6taatNXytzB7Cxew= +cloud.google.com/go/iam v1.0.1 h1:lyeCAU6jpnVNrE9zGQkTl3WgNgK/X+uWwaw0kynZJMU= +cloud.google.com/go/iam v1.0.1/go.mod h1:yR3tmSL8BcZB4bxByRv2jkSIahVmCtfKZwLYGBalRE8= cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= +cloud.google.com/go/longrunning v0.4.2 h1:WDKiiNXFTaQ6qz/G8FCOkuY9kJmOJGY67wPUC1M2RbE= +cloud.google.com/go/longrunning v0.4.2/go.mod h1:OHrnaYyLUV6oqwh0xiS7e5sLQhP1m0QU9R+WhGDMgIQ= cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM= cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= firebase.google.com/go/v4 v4.11.0 h1:szjBoiF33A2FavRLIDZjW1mw+OsW/XAtHoYNIqWOjRk= @@ -71,7 +77,6 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y 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.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 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= @@ -94,8 +99,6 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= -github.com/google/s2a-go v0.1.2 h1:WVtYAYuYxKeYajAmThMRYWP6K3wXkcqbGHeUgeubUHY= -github.com/google/s2a-go v0.1.2/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM= github.com/google/s2a-go v0.1.3 h1:FAgZmpLl/SXurPEZyCMPBIiiYeTbqfjlbdnCNTAkbGE= github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -121,26 +124,17 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM= -github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/common v0.43.0 h1:iq+BVjvYLei5f27wiuNiB1DN6DYQkp1c8Bx0Vykh5us= github.com/prometheus/common v0.43.0/go.mod h1:NCvr5cQIh3Y/gy73/RdVtC9r8xxrxwJnB+2lB3BxrFc= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -153,12 +147,10 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stripe/stripe-go/v74 v74.15.0 h1:P3ZYrY4CdZeV8Pc/205utqjur+5gcTef+9hgtj8P8IY= -github.com/stripe/stripe-go/v74 v74.15.0/go.mod h1:f9L6LvaXa35ja7eyvP6GQswoaIPaBRvGAimAO+udbBw= github.com/stripe/stripe-go/v74 v74.17.0 h1:qVWSzmADr6gudznuAcPjB9ewzgxfyIhBCkyTbkxJcCw= github.com/stripe/stripe-go/v74 v74.17.0/go.mod h1:f9L6LvaXa35ja7eyvP6GQswoaIPaBRvGAimAO+udbBw= -github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw= -github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/stripe/stripe-go/v74 v74.18.0 h1:ImSIoaVkTUozHxa21AhwHYBjwc8fVSJJJB1Q7oaXzIw= +github.com/stripe/stripe-go/v74 v74.18.0/go.mod h1:f9L6LvaXa35ja7eyvP6GQswoaIPaBRvGAimAO+udbBw= github.com/urfave/cli/v2 v2.25.3 h1:VJkt6wvEBOoSjPFQvOkv6iWIrsJyCrKGtCtxXWwmGeY= github.com/urfave/cli/v2 v2.25.3/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= @@ -173,6 +165,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= 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= @@ -190,23 +184,23 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= +golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= +golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= 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-20181221193216-37e7f081c4d4/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-20210220032951-036812b2e83c/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 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -217,17 +211,12 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-20211019181941-9d821ace8654/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.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -252,10 +241,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.120.0 h1:TTmhTei0mkR+kiBSW2UzZmAbkTaBfUUzfchyXnzG9Hs= -google.golang.org/api v0.120.0/go.mod h1:CrSvlNEFCFLae9ZUtL1z+61+rEBD7J/aCYwVYKZoWFU= google.golang.org/api v0.121.0 h1:8Oopoo8Vavxx6gt+sgs8s8/X60WBAtKQq6JqnkF+xow= google.golang.org/api v0.121.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= +google.golang.org/api v0.122.0 h1:zDobeejm3E7pEG1mNHvdxvjs5XJoCMzyNH+CmwL94Es= +google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= 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.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= @@ -276,8 +265,6 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/server/errors.go b/server/errors.go index 7c4e6899..ee5223bf 100644 --- a/server/errors.go +++ b/server/errors.go @@ -106,8 +106,10 @@ var ( errHTTPBadRequestNotAPaidUser = &errHTTP{40027, http.StatusBadRequest, "invalid request: not a paid user", "", nil} errHTTPBadRequestBillingRequestInvalid = &errHTTP{40028, http.StatusBadRequest, "invalid request: not a valid billing request", "", nil} errHTTPBadRequestBillingSubscriptionExists = &errHTTP{40029, http.StatusBadRequest, "invalid request: billing subscription already exists", "", nil} - errHTTPBadRequestTwilioDisabled = &errHTTP{40030, http.StatusBadRequest, "invalid request: Calling is disabled", "https://ntfy.sh/docs/publish/#phone-calls", nil} - errHTTPBadRequestPhoneNumberInvalid = &errHTTP{40031, http.StatusBadRequest, "invalid request: phone number invalid", "https://ntfy.sh/docs/publish/#phone-calls", nil} + errHTTPBadRequestTierInvalid = &errHTTP{40030, http.StatusBadRequest, "invalid request: tier does not exist", "", nil} + errHTTPBadRequestUserNotFound = &errHTTP{40031, http.StatusBadRequest, "invalid request: user does not exist", "", nil} + errHTTPBadRequestTwilioDisabled = &errHTTP{40032, http.StatusBadRequest, "invalid request: Calling is disabled", "https://ntfy.sh/docs/publish/#phone-calls", nil} + errHTTPBadRequestPhoneNumberInvalid = &errHTTP{40033, http.StatusBadRequest, "invalid request: phone number invalid", "https://ntfy.sh/docs/publish/#phone-calls", nil} errHTTPNotFound = &errHTTP{40401, http.StatusNotFound, "page not found", "", nil} errHTTPUnauthorized = &errHTTP{40101, http.StatusUnauthorized, "unauthorized", "https://ntfy.sh/docs/publish/#authentication", nil} errHTTPForbidden = &errHTTP{40301, http.StatusForbidden, "forbidden", "https://ntfy.sh/docs/publish/#authentication", nil} diff --git a/server/mailer_emoji.json b/server/mailer_emoji.json deleted file mode 100644 index 4d4c32fc..00000000 --- a/server/mailer_emoji.json +++ /dev/null @@ -1 +0,0 @@ -[{"emoji":"๐","aliases":["grinning"]},{"emoji":"๐","aliases":["smiley"]},{"emoji":"๐","aliases":["smile"]},{"emoji":"๐","aliases":["grin"]},{"emoji":"๐","aliases":["laughing","satisfied"]},{"emoji":"๐ ","aliases":["sweat_smile"]},{"emoji":"๐คฃ","aliases":["rofl"]},{"emoji":"๐","aliases":["joy"]},{"emoji":"๐","aliases":["slightly_smiling_face"]},{"emoji":"๐","aliases":["upside_down_face"]},{"emoji":"๐","aliases":["wink"]},{"emoji":"๐","aliases":["blush"]},{"emoji":"๐","aliases":["innocent"]},{"emoji":"๐ฅฐ","aliases":["smiling_face_with_three_hearts"]},{"emoji":"๐","aliases":["heart_eyes"]},{"emoji":"๐คฉ","aliases":["star_struck"]},{"emoji":"๐","aliases":["kissing_heart"]},{"emoji":"๐","aliases":["kissing"]},{"emoji":"โบ๏ธ","aliases":["relaxed"]},{"emoji":"๐","aliases":["kissing_closed_eyes"]},{"emoji":"๐","aliases":["kissing_smiling_eyes"]},{"emoji":"๐ฅฒ","aliases":["smiling_face_with_tear"]},{"emoji":"๐","aliases":["yum"]},{"emoji":"๐","aliases":["stuck_out_tongue"]},{"emoji":"๐","aliases":["stuck_out_tongue_winking_eye"]},{"emoji":"๐คช","aliases":["zany_face"]},{"emoji":"๐","aliases":["stuck_out_tongue_closed_eyes"]},{"emoji":"๐ค","aliases":["money_mouth_face"]},{"emoji":"๐ค","aliases":["hugs"]},{"emoji":"๐คญ","aliases":["hand_over_mouth"]},{"emoji":"๐คซ","aliases":["shushing_face"]},{"emoji":"๐ค","aliases":["thinking"]},{"emoji":"๐ค","aliases":["zipper_mouth_face"]},{"emoji":"๐คจ","aliases":["raised_eyebrow"]},{"emoji":"๐","aliases":["neutral_face"]},{"emoji":"๐","aliases":["expressionless"]},{"emoji":"๐ถ","aliases":["no_mouth"]},{"emoji":"๐ถโ๐ซ๏ธ","aliases":["face_in_clouds"]},{"emoji":"๐","aliases":["smirk"]},{"emoji":"๐","aliases":["unamused"]},{"emoji":"๐","aliases":["roll_eyes"]},{"emoji":"๐ฌ","aliases":["grimacing"]},{"emoji":"๐ฎโ๐จ","aliases":["face_exhaling"]},{"emoji":"๐คฅ","aliases":["lying_face"]},{"emoji":"๐","aliases":["relieved"]},{"emoji":"๐","aliases":["pensive"]},{"emoji":"๐ช","aliases":["sleepy"]},{"emoji":"๐คค","aliases":["drooling_face"]},{"emoji":"๐ด","aliases":["sleeping"]},{"emoji":"๐ท","aliases":["mask"]},{"emoji":"๐ค","aliases":["face_with_thermometer"]},{"emoji":"๐ค","aliases":["face_with_head_bandage"]},{"emoji":"๐คข","aliases":["nauseated_face"]},{"emoji":"๐คฎ","aliases":["vomiting_face"]},{"emoji":"๐คง","aliases":["sneezing_face"]},{"emoji":"๐ฅต","aliases":["hot_face"]},{"emoji":"๐ฅถ","aliases":["cold_face"]},{"emoji":"๐ฅด","aliases":["woozy_face"]},{"emoji":"๐ต","aliases":["dizzy_face"]},{"emoji":"๐ตโ๐ซ","aliases":["face_with_spiral_eyes"]},{"emoji":"๐คฏ","aliases":["exploding_head"]},{"emoji":"๐ค ","aliases":["cowboy_hat_face"]},{"emoji":"๐ฅณ","aliases":["partying_face"]},{"emoji":"๐ฅธ","aliases":["disguised_face"]},{"emoji":"๐","aliases":["sunglasses"]},{"emoji":"๐ค","aliases":["nerd_face"]},{"emoji":"๐ง","aliases":["monocle_face"]},{"emoji":"๐","aliases":["confused"]},{"emoji":"๐","aliases":["worried"]},{"emoji":"๐","aliases":["slightly_frowning_face"]},{"emoji":"โน๏ธ","aliases":["frowning_face"]},{"emoji":"๐ฎ","aliases":["open_mouth"]},{"emoji":"๐ฏ","aliases":["hushed"]},{"emoji":"๐ฒ","aliases":["astonished"]},{"emoji":"๐ณ","aliases":["flushed"]},{"emoji":"๐ฅบ","aliases":["pleading_face"]},{"emoji":"๐ฆ","aliases":["frowning"]},{"emoji":"๐ง","aliases":["anguished"]},{"emoji":"๐จ","aliases":["fearful"]},{"emoji":"๐ฐ","aliases":["cold_sweat"]},{"emoji":"๐ฅ","aliases":["disappointed_relieved"]},{"emoji":"๐ข","aliases":["cry"]},{"emoji":"๐ญ","aliases":["sob"]},{"emoji":"๐ฑ","aliases":["scream"]},{"emoji":"๐","aliases":["confounded"]},{"emoji":"๐ฃ","aliases":["persevere"]},{"emoji":"๐","aliases":["disappointed"]},{"emoji":"๐","aliases":["sweat"]},{"emoji":"๐ฉ","aliases":["weary"]},{"emoji":"๐ซ","aliases":["tired_face"]},{"emoji":"๐ฅฑ","aliases":["yawning_face"]},{"emoji":"๐ค","aliases":["triumph"]},{"emoji":"๐ก","aliases":["rage","pout"]},{"emoji":"๐ ","aliases":["angry"]},{"emoji":"๐คฌ","aliases":["cursing_face"]},{"emoji":"๐","aliases":["smiling_imp"]},{"emoji":"๐ฟ","aliases":["imp"]},{"emoji":"๐","aliases":["skull"]},{"emoji":"โ ๏ธ","aliases":["skull_and_crossbones"]},{"emoji":"๐ฉ","aliases":["hankey","poop","shit"]},{"emoji":"๐คก","aliases":["clown_face"]},{"emoji":"๐น","aliases":["japanese_ogre"]},{"emoji":"๐บ","aliases":["japanese_goblin"]},{"emoji":"๐ป","aliases":["ghost"]},{"emoji":"๐ฝ","aliases":["alien"]},{"emoji":"๐พ","aliases":["space_invader"]},{"emoji":"๐ค","aliases":["robot"]},{"emoji":"๐บ","aliases":["smiley_cat"]},{"emoji":"๐ธ","aliases":["smile_cat"]},{"emoji":"๐น","aliases":["joy_cat"]},{"emoji":"๐ป","aliases":["heart_eyes_cat"]},{"emoji":"๐ผ","aliases":["smirk_cat"]},{"emoji":"๐ฝ","aliases":["kissing_cat"]},{"emoji":"๐","aliases":["scream_cat"]},{"emoji":"๐ฟ","aliases":["crying_cat_face"]},{"emoji":"๐พ","aliases":["pouting_cat"]},{"emoji":"๐","aliases":["see_no_evil"]},{"emoji":"๐","aliases":["hear_no_evil"]},{"emoji":"๐","aliases":["speak_no_evil"]},{"emoji":"๐","aliases":["kiss"]},{"emoji":"๐","aliases":["love_letter"]},{"emoji":"๐","aliases":["cupid"]},{"emoji":"๐","aliases":["gift_heart"]},{"emoji":"๐","aliases":["sparkling_heart"]},{"emoji":"๐","aliases":["heartpulse"]},{"emoji":"๐","aliases":["heartbeat"]},{"emoji":"๐","aliases":["revolving_hearts"]},{"emoji":"๐","aliases":["two_hearts"]},{"emoji":"๐","aliases":["heart_decoration"]},{"emoji":"โฃ๏ธ","aliases":["heavy_heart_exclamation"]},{"emoji":"๐","aliases":["broken_heart"]},{"emoji":"โค๏ธโ๐ฅ","aliases":["heart_on_fire"]},{"emoji":"โค๏ธโ๐ฉน","aliases":["mending_heart"]},{"emoji":"โค๏ธ","aliases":["heart"]},{"emoji":"๐งก","aliases":["orange_heart"]},{"emoji":"๐","aliases":["yellow_heart"]},{"emoji":"๐","aliases":["green_heart"]},{"emoji":"๐","aliases":["blue_heart"]},{"emoji":"๐","aliases":["purple_heart"]},{"emoji":"๐ค","aliases":["brown_heart"]},{"emoji":"๐ค","aliases":["black_heart"]},{"emoji":"๐ค","aliases":["white_heart"]},{"emoji":"๐ฏ","aliases":["100"]},{"emoji":"๐ข","aliases":["anger"]},{"emoji":"๐ฅ","aliases":["boom","collision"]},{"emoji":"๐ซ","aliases":["dizzy"]},{"emoji":"๐ฆ","aliases":["sweat_drops"]},{"emoji":"๐จ","aliases":["dash"]},{"emoji":"๐ณ๏ธ","aliases":["hole"]},{"emoji":"๐ฃ","aliases":["bomb"]},{"emoji":"๐ฌ","aliases":["speech_balloon"]},{"emoji":"๐๏ธโ๐จ๏ธ","aliases":["eye_speech_bubble"]},{"emoji":"๐จ๏ธ","aliases":["left_speech_bubble"]},{"emoji":"๐ฏ๏ธ","aliases":["right_anger_bubble"]},{"emoji":"๐ญ","aliases":["thought_balloon"]},{"emoji":"๐ค","aliases":["zzz"]},{"emoji":"๐","aliases":["wave"]},{"emoji":"๐ค","aliases":["raised_back_of_hand"]},{"emoji":"๐๏ธ","aliases":["raised_hand_with_fingers_splayed"]},{"emoji":"โ","aliases":["hand","raised_hand"]},{"emoji":"๐","aliases":["vulcan_salute"]},{"emoji":"๐","aliases":["ok_hand"]},{"emoji":"๐ค","aliases":["pinched_fingers"]},{"emoji":"๐ค","aliases":["pinching_hand"]},{"emoji":"โ๏ธ","aliases":["v"]},{"emoji":"๐ค","aliases":["crossed_fingers"]},{"emoji":"๐ค","aliases":["love_you_gesture"]},{"emoji":"๐ค","aliases":["metal"]},{"emoji":"๐ค","aliases":["call_me_hand"]},{"emoji":"๐","aliases":["point_left"]},{"emoji":"๐","aliases":["point_right"]},{"emoji":"๐","aliases":["point_up_2"]},{"emoji":"๐","aliases":["middle_finger","fu"]},{"emoji":"๐","aliases":["point_down"]},{"emoji":"โ๏ธ","aliases":["point_up"]},{"emoji":"๐","aliases":["+1","thumbsup"]},{"emoji":"๐","aliases":["-1","thumbsdown"]},{"emoji":"โ","aliases":["fist_raised","fist"]},{"emoji":"๐","aliases":["fist_oncoming","facepunch","punch"]},{"emoji":"๐ค","aliases":["fist_left"]},{"emoji":"๐ค","aliases":["fist_right"]},{"emoji":"๐","aliases":["clap"]},{"emoji":"๐","aliases":["raised_hands"]},{"emoji":"๐","aliases":["open_hands"]},{"emoji":"๐คฒ","aliases":["palms_up_together"]},{"emoji":"๐ค","aliases":["handshake"]},{"emoji":"๐","aliases":["pray"]},{"emoji":"โ๏ธ","aliases":["writing_hand"]},{"emoji":"๐ ","aliases":["nail_care"]},{"emoji":"๐คณ","aliases":["selfie"]},{"emoji":"๐ช","aliases":["muscle"]},{"emoji":"๐ฆพ","aliases":["mechanical_arm"]},{"emoji":"๐ฆฟ","aliases":["mechanical_leg"]},{"emoji":"๐ฆต","aliases":["leg"]},{"emoji":"๐ฆถ","aliases":["foot"]},{"emoji":"๐","aliases":["ear"]},{"emoji":"๐ฆป","aliases":["ear_with_hearing_aid"]},{"emoji":"๐","aliases":["nose"]},{"emoji":"๐ง ","aliases":["brain"]},{"emoji":"๐ซ","aliases":["anatomical_heart"]},{"emoji":"๐ซ","aliases":["lungs"]},{"emoji":"๐ฆท","aliases":["tooth"]},{"emoji":"๐ฆด","aliases":["bone"]},{"emoji":"๐","aliases":["eyes"]},{"emoji":"๐๏ธ","aliases":["eye"]},{"emoji":"๐ ","aliases":["tongue"]},{"emoji":"๐","aliases":["lips"]},{"emoji":"๐ถ","aliases":["baby"]},{"emoji":"๐ง","aliases":["child"]},{"emoji":"๐ฆ","aliases":["boy"]},{"emoji":"๐ง","aliases":["girl"]},{"emoji":"๐ง","aliases":["adult"]},{"emoji":"๐ฑ","aliases":["blond_haired_person"]},{"emoji":"๐จ","aliases":["man"]},{"emoji":"๐ง","aliases":["bearded_person"]},{"emoji":"๐งโโ๏ธ","aliases":["man_beard"]},{"emoji":"๐งโโ๏ธ","aliases":["woman_beard"]},{"emoji":"๐จโ๐ฆฐ","aliases":["red_haired_man"]},{"emoji":"๐จโ๐ฆฑ","aliases":["curly_haired_man"]},{"emoji":"๐จโ๐ฆณ","aliases":["white_haired_man"]},{"emoji":"๐จโ๐ฆฒ","aliases":["bald_man"]},{"emoji":"๐ฉ","aliases":["woman"]},{"emoji":"๐ฉโ๐ฆฐ","aliases":["red_haired_woman"]},{"emoji":"๐งโ๐ฆฐ","aliases":["person_red_hair"]},{"emoji":"๐ฉโ๐ฆฑ","aliases":["curly_haired_woman"]},{"emoji":"๐งโ๐ฆฑ","aliases":["person_curly_hair"]},{"emoji":"๐ฉโ๐ฆณ","aliases":["white_haired_woman"]},{"emoji":"๐งโ๐ฆณ","aliases":["person_white_hair"]},{"emoji":"๐ฉโ๐ฆฒ","aliases":["bald_woman"]},{"emoji":"๐งโ๐ฆฒ","aliases":["person_bald"]},{"emoji":"๐ฑโโ๏ธ","aliases":["blond_haired_woman","blonde_woman"]},{"emoji":"๐ฑโโ๏ธ","aliases":["blond_haired_man"]},{"emoji":"๐ง","aliases":["older_adult"]},{"emoji":"๐ด","aliases":["older_man"]},{"emoji":"๐ต","aliases":["older_woman"]},{"emoji":"๐","aliases":["frowning_person"]},{"emoji":"๐โโ๏ธ","aliases":["frowning_man"]},{"emoji":"๐โโ๏ธ","aliases":["frowning_woman"]},{"emoji":"๐","aliases":["pouting_face"]},{"emoji":"๐โโ๏ธ","aliases":["pouting_man"]},{"emoji":"๐โโ๏ธ","aliases":["pouting_woman"]},{"emoji":"๐ ","aliases":["no_good"]},{"emoji":"๐ โโ๏ธ","aliases":["no_good_man","ng_man"]},{"emoji":"๐ โโ๏ธ","aliases":["no_good_woman","ng_woman"]},{"emoji":"๐","aliases":["ok_person"]},{"emoji":"๐โโ๏ธ","aliases":["ok_man"]},{"emoji":"๐โโ๏ธ","aliases":["ok_woman"]},{"emoji":"๐","aliases":["tipping_hand_person","information_desk_person"]},{"emoji":"๐โโ๏ธ","aliases":["tipping_hand_man","sassy_man"]},{"emoji":"๐โโ๏ธ","aliases":["tipping_hand_woman","sassy_woman"]},{"emoji":"๐","aliases":["raising_hand"]},{"emoji":"๐โโ๏ธ","aliases":["raising_hand_man"]},{"emoji":"๐โโ๏ธ","aliases":["raising_hand_woman"]},{"emoji":"๐ง","aliases":["deaf_person"]},{"emoji":"๐งโโ๏ธ","aliases":["deaf_man"]},{"emoji":"๐งโโ๏ธ","aliases":["deaf_woman"]},{"emoji":"๐","aliases":["bow"]},{"emoji":"๐โโ๏ธ","aliases":["bowing_man"]},{"emoji":"๐โโ๏ธ","aliases":["bowing_woman"]},{"emoji":"๐คฆ","aliases":["facepalm"]},{"emoji":"๐คฆโโ๏ธ","aliases":["man_facepalming"]},{"emoji":"๐คฆโโ๏ธ","aliases":["woman_facepalming"]},{"emoji":"๐คท","aliases":["shrug"]},{"emoji":"๐คทโโ๏ธ","aliases":["man_shrugging"]},{"emoji":"๐คทโโ๏ธ","aliases":["woman_shrugging"]},{"emoji":"๐งโโ๏ธ","aliases":["health_worker"]},{"emoji":"๐จโโ๏ธ","aliases":["man_health_worker"]},{"emoji":"๐ฉโโ๏ธ","aliases":["woman_health_worker"]},{"emoji":"๐งโ๐","aliases":["student"]},{"emoji":"๐จโ๐","aliases":["man_student"]},{"emoji":"๐ฉโ๐","aliases":["woman_student"]},{"emoji":"๐งโ๐ซ","aliases":["teacher"]},{"emoji":"๐จโ๐ซ","aliases":["man_teacher"]},{"emoji":"๐ฉโ๐ซ","aliases":["woman_teacher"]},{"emoji":"๐งโโ๏ธ","aliases":["judge"]},{"emoji":"๐จโโ๏ธ","aliases":["man_judge"]},{"emoji":"๐ฉโโ๏ธ","aliases":["woman_judge"]},{"emoji":"๐งโ๐พ","aliases":["farmer"]},{"emoji":"๐จโ๐พ","aliases":["man_farmer"]},{"emoji":"๐ฉโ๐พ","aliases":["woman_farmer"]},{"emoji":"๐งโ๐ณ","aliases":["cook"]},{"emoji":"๐จโ๐ณ","aliases":["man_cook"]},{"emoji":"๐ฉโ๐ณ","aliases":["woman_cook"]},{"emoji":"๐งโ๐ง","aliases":["mechanic"]},{"emoji":"๐จโ๐ง","aliases":["man_mechanic"]},{"emoji":"๐ฉโ๐ง","aliases":["woman_mechanic"]},{"emoji":"๐งโ๐ญ","aliases":["factory_worker"]},{"emoji":"๐จโ๐ญ","aliases":["man_factory_worker"]},{"emoji":"๐ฉโ๐ญ","aliases":["woman_factory_worker"]},{"emoji":"๐งโ๐ผ","aliases":["office_worker"]},{"emoji":"๐จโ๐ผ","aliases":["man_office_worker"]},{"emoji":"๐ฉโ๐ผ","aliases":["woman_office_worker"]},{"emoji":"๐งโ๐ฌ","aliases":["scientist"]},{"emoji":"๐จโ๐ฌ","aliases":["man_scientist"]},{"emoji":"๐ฉโ๐ฌ","aliases":["woman_scientist"]},{"emoji":"๐งโ๐ป","aliases":["technologist"]},{"emoji":"๐จโ๐ป","aliases":["man_technologist"]},{"emoji":"๐ฉโ๐ป","aliases":["woman_technologist"]},{"emoji":"๐งโ๐ค","aliases":["singer"]},{"emoji":"๐จโ๐ค","aliases":["man_singer"]},{"emoji":"๐ฉโ๐ค","aliases":["woman_singer"]},{"emoji":"๐งโ๐จ","aliases":["artist"]},{"emoji":"๐จโ๐จ","aliases":["man_artist"]},{"emoji":"๐ฉโ๐จ","aliases":["woman_artist"]},{"emoji":"๐งโโ๏ธ","aliases":["pilot"]},{"emoji":"๐จโโ๏ธ","aliases":["man_pilot"]},{"emoji":"๐ฉโโ๏ธ","aliases":["woman_pilot"]},{"emoji":"๐งโ๐","aliases":["astronaut"]},{"emoji":"๐จโ๐","aliases":["man_astronaut"]},{"emoji":"๐ฉโ๐","aliases":["woman_astronaut"]},{"emoji":"๐งโ๐","aliases":["firefighter"]},{"emoji":"๐จโ๐","aliases":["man_firefighter"]},{"emoji":"๐ฉโ๐","aliases":["woman_firefighter"]},{"emoji":"๐ฎ","aliases":["police_officer","cop"]},{"emoji":"๐ฎโโ๏ธ","aliases":["policeman"]},{"emoji":"๐ฎโโ๏ธ","aliases":["policewoman"]},{"emoji":"๐ต๏ธ","aliases":["detective"]},{"emoji":"๐ต๏ธโโ๏ธ","aliases":["male_detective"]},{"emoji":"๐ต๏ธโโ๏ธ","aliases":["female_detective"]},{"emoji":"๐","aliases":["guard"]},{"emoji":"๐โโ๏ธ","aliases":["guardsman"]},{"emoji":"๐โโ๏ธ","aliases":["guardswoman"]},{"emoji":"๐ฅท","aliases":["ninja"]},{"emoji":"๐ท","aliases":["construction_worker"]},{"emoji":"๐ทโโ๏ธ","aliases":["construction_worker_man"]},{"emoji":"๐ทโโ๏ธ","aliases":["construction_worker_woman"]},{"emoji":"๐คด","aliases":["prince"]},{"emoji":"๐ธ","aliases":["princess"]},{"emoji":"๐ณ","aliases":["person_with_turban"]},{"emoji":"๐ณโโ๏ธ","aliases":["man_with_turban"]},{"emoji":"๐ณโโ๏ธ","aliases":["woman_with_turban"]},{"emoji":"๐ฒ","aliases":["man_with_gua_pi_mao"]},{"emoji":"๐ง","aliases":["woman_with_headscarf"]},{"emoji":"๐คต","aliases":["person_in_tuxedo"]},{"emoji":"๐คตโโ๏ธ","aliases":["man_in_tuxedo"]},{"emoji":"๐คตโโ๏ธ","aliases":["woman_in_tuxedo"]},{"emoji":"๐ฐ","aliases":["person_with_veil"]},{"emoji":"๐ฐโโ๏ธ","aliases":["man_with_veil"]},{"emoji":"๐ฐโโ๏ธ","aliases":["woman_with_veil","bride_with_veil"]},{"emoji":"๐คฐ","aliases":["pregnant_woman"]},{"emoji":"๐คฑ","aliases":["breast_feeding"]},{"emoji":"๐ฉโ๐ผ","aliases":["woman_feeding_baby"]},{"emoji":"๐จโ๐ผ","aliases":["man_feeding_baby"]},{"emoji":"๐งโ๐ผ","aliases":["person_feeding_baby"]},{"emoji":"๐ผ","aliases":["angel"]},{"emoji":"๐ ","aliases":["santa"]},{"emoji":"๐คถ","aliases":["mrs_claus"]},{"emoji":"๐งโ๐","aliases":["mx_claus"]},{"emoji":"๐ฆธ","aliases":["superhero"]},{"emoji":"๐ฆธโโ๏ธ","aliases":["superhero_man"]},{"emoji":"๐ฆธโโ๏ธ","aliases":["superhero_woman"]},{"emoji":"๐ฆน","aliases":["supervillain"]},{"emoji":"๐ฆนโโ๏ธ","aliases":["supervillain_man"]},{"emoji":"๐ฆนโโ๏ธ","aliases":["supervillain_woman"]},{"emoji":"๐ง","aliases":["mage"]},{"emoji":"๐งโโ๏ธ","aliases":["mage_man"]},{"emoji":"๐งโโ๏ธ","aliases":["mage_woman"]},{"emoji":"๐ง","aliases":["fairy"]},{"emoji":"๐งโโ๏ธ","aliases":["fairy_man"]},{"emoji":"๐งโโ๏ธ","aliases":["fairy_woman"]},{"emoji":"๐ง","aliases":["vampire"]},{"emoji":"๐งโโ๏ธ","aliases":["vampire_man"]},{"emoji":"๐งโโ๏ธ","aliases":["vampire_woman"]},{"emoji":"๐ง","aliases":["merperson"]},{"emoji":"๐งโโ๏ธ","aliases":["merman"]},{"emoji":"๐งโโ๏ธ","aliases":["mermaid"]},{"emoji":"๐ง","aliases":["elf"]},{"emoji":"๐งโโ๏ธ","aliases":["elf_man"]},{"emoji":"๐งโโ๏ธ","aliases":["elf_woman"]},{"emoji":"๐ง","aliases":["genie"]},{"emoji":"๐งโโ๏ธ","aliases":["genie_man"]},{"emoji":"๐งโโ๏ธ","aliases":["genie_woman"]},{"emoji":"๐ง","aliases":["zombie"]},{"emoji":"๐งโโ๏ธ","aliases":["zombie_man"]},{"emoji":"๐งโโ๏ธ","aliases":["zombie_woman"]},{"emoji":"๐","aliases":["massage"]},{"emoji":"๐โโ๏ธ","aliases":["massage_man"]},{"emoji":"๐โโ๏ธ","aliases":["massage_woman"]},{"emoji":"๐","aliases":["haircut"]},{"emoji":"๐โโ๏ธ","aliases":["haircut_man"]},{"emoji":"๐โโ๏ธ","aliases":["haircut_woman"]},{"emoji":"๐ถ","aliases":["walking"]},{"emoji":"๐ถโโ๏ธ","aliases":["walking_man"]},{"emoji":"๐ถโโ๏ธ","aliases":["walking_woman"]},{"emoji":"๐ง","aliases":["standing_person"]},{"emoji":"๐งโโ๏ธ","aliases":["standing_man"]},{"emoji":"๐งโโ๏ธ","aliases":["standing_woman"]},{"emoji":"๐ง","aliases":["kneeling_person"]},{"emoji":"๐งโโ๏ธ","aliases":["kneeling_man"]},{"emoji":"๐งโโ๏ธ","aliases":["kneeling_woman"]},{"emoji":"๐งโ๐ฆฏ","aliases":["person_with_probing_cane"]},{"emoji":"๐จโ๐ฆฏ","aliases":["man_with_probing_cane"]},{"emoji":"๐ฉโ๐ฆฏ","aliases":["woman_with_probing_cane"]},{"emoji":"๐งโ๐ฆผ","aliases":["person_in_motorized_wheelchair"]},{"emoji":"๐จโ๐ฆผ","aliases":["man_in_motorized_wheelchair"]},{"emoji":"๐ฉโ๐ฆผ","aliases":["woman_in_motorized_wheelchair"]},{"emoji":"๐งโ๐ฆฝ","aliases":["person_in_manual_wheelchair"]},{"emoji":"๐จโ๐ฆฝ","aliases":["man_in_manual_wheelchair"]},{"emoji":"๐ฉโ๐ฆฝ","aliases":["woman_in_manual_wheelchair"]},{"emoji":"๐","aliases":["runner","running"]},{"emoji":"๐โโ๏ธ","aliases":["running_man"]},{"emoji":"๐โโ๏ธ","aliases":["running_woman"]},{"emoji":"๐","aliases":["woman_dancing","dancer"]},{"emoji":"๐บ","aliases":["man_dancing"]},{"emoji":"๐ด๏ธ","aliases":["business_suit_levitating"]},{"emoji":"๐ฏ","aliases":["dancers"]},{"emoji":"๐ฏโโ๏ธ","aliases":["dancing_men"]},{"emoji":"๐ฏโโ๏ธ","aliases":["dancing_women"]},{"emoji":"๐ง","aliases":["sauna_person"]},{"emoji":"๐งโโ๏ธ","aliases":["sauna_man"]},{"emoji":"๐งโโ๏ธ","aliases":["sauna_woman"]},{"emoji":"๐ง","aliases":["climbing"]},{"emoji":"๐งโโ๏ธ","aliases":["climbing_man"]},{"emoji":"๐งโโ๏ธ","aliases":["climbing_woman"]},{"emoji":"๐คบ","aliases":["person_fencing"]},{"emoji":"๐","aliases":["horse_racing"]},{"emoji":"โท๏ธ","aliases":["skier"]},{"emoji":"๐","aliases":["snowboarder"]},{"emoji":"๐๏ธ","aliases":["golfing"]},{"emoji":"๐๏ธโโ๏ธ","aliases":["golfing_man"]},{"emoji":"๐๏ธโโ๏ธ","aliases":["golfing_woman"]},{"emoji":"๐","aliases":["surfer"]},{"emoji":"๐โโ๏ธ","aliases":["surfing_man"]},{"emoji":"๐โโ๏ธ","aliases":["surfing_woman"]},{"emoji":"๐ฃ","aliases":["rowboat"]},{"emoji":"๐ฃโโ๏ธ","aliases":["rowing_man"]},{"emoji":"๐ฃโโ๏ธ","aliases":["rowing_woman"]},{"emoji":"๐","aliases":["swimmer"]},{"emoji":"๐โโ๏ธ","aliases":["swimming_man"]},{"emoji":"๐โโ๏ธ","aliases":["swimming_woman"]},{"emoji":"โน๏ธ","aliases":["bouncing_ball_person"]},{"emoji":"โน๏ธโโ๏ธ","aliases":["bouncing_ball_man","basketball_man"]},{"emoji":"โน๏ธโโ๏ธ","aliases":["bouncing_ball_woman","basketball_woman"]},{"emoji":"๐๏ธ","aliases":["weight_lifting"]},{"emoji":"๐๏ธโโ๏ธ","aliases":["weight_lifting_man"]},{"emoji":"๐๏ธโโ๏ธ","aliases":["weight_lifting_woman"]},{"emoji":"๐ด","aliases":["bicyclist"]},{"emoji":"๐ดโโ๏ธ","aliases":["biking_man"]},{"emoji":"๐ดโโ๏ธ","aliases":["biking_woman"]},{"emoji":"๐ต","aliases":["mountain_bicyclist"]},{"emoji":"๐ตโโ๏ธ","aliases":["mountain_biking_man"]},{"emoji":"๐ตโโ๏ธ","aliases":["mountain_biking_woman"]},{"emoji":"๐คธ","aliases":["cartwheeling"]},{"emoji":"๐คธโโ๏ธ","aliases":["man_cartwheeling"]},{"emoji":"๐คธโโ๏ธ","aliases":["woman_cartwheeling"]},{"emoji":"๐คผ","aliases":["wrestling"]},{"emoji":"๐คผโโ๏ธ","aliases":["men_wrestling"]},{"emoji":"๐คผโโ๏ธ","aliases":["women_wrestling"]},{"emoji":"๐คฝ","aliases":["water_polo"]},{"emoji":"๐คฝโโ๏ธ","aliases":["man_playing_water_polo"]},{"emoji":"๐คฝโโ๏ธ","aliases":["woman_playing_water_polo"]},{"emoji":"๐คพ","aliases":["handball_person"]},{"emoji":"๐คพโโ๏ธ","aliases":["man_playing_handball"]},{"emoji":"๐คพโโ๏ธ","aliases":["woman_playing_handball"]},{"emoji":"๐คน","aliases":["juggling_person"]},{"emoji":"๐คนโโ๏ธ","aliases":["man_juggling"]},{"emoji":"๐คนโโ๏ธ","aliases":["woman_juggling"]},{"emoji":"๐ง","aliases":["lotus_position"]},{"emoji":"๐งโโ๏ธ","aliases":["lotus_position_man"]},{"emoji":"๐งโโ๏ธ","aliases":["lotus_position_woman"]},{"emoji":"๐","aliases":["bath"]},{"emoji":"๐","aliases":["sleeping_bed"]},{"emoji":"๐งโ๐คโ๐ง","aliases":["people_holding_hands"]},{"emoji":"๐ญ","aliases":["two_women_holding_hands"]},{"emoji":"๐ซ","aliases":["couple"]},{"emoji":"๐ฌ","aliases":["two_men_holding_hands"]},{"emoji":"๐","aliases":["couplekiss"]},{"emoji":"๐ฉโโค๏ธโ๐โ๐จ","aliases":["couplekiss_man_woman"]},{"emoji":"๐จโโค๏ธโ๐โ๐จ","aliases":["couplekiss_man_man"]},{"emoji":"๐ฉโโค๏ธโ๐โ๐ฉ","aliases":["couplekiss_woman_woman"]},{"emoji":"๐","aliases":["couple_with_heart"]},{"emoji":"๐ฉโโค๏ธโ๐จ","aliases":["couple_with_heart_woman_man"]},{"emoji":"๐จโโค๏ธโ๐จ","aliases":["couple_with_heart_man_man"]},{"emoji":"๐ฉโโค๏ธโ๐ฉ","aliases":["couple_with_heart_woman_woman"]},{"emoji":"๐ช","aliases":["family"]},{"emoji":"๐จโ๐ฉโ๐ฆ","aliases":["family_man_woman_boy"]},{"emoji":"๐จโ๐ฉโ๐ง","aliases":["family_man_woman_girl"]},{"emoji":"๐จโ๐ฉโ๐งโ๐ฆ","aliases":["family_man_woman_girl_boy"]},{"emoji":"๐จโ๐ฉโ๐ฆโ๐ฆ","aliases":["family_man_woman_boy_boy"]},{"emoji":"๐จโ๐ฉโ๐งโ๐ง","aliases":["family_man_woman_girl_girl"]},{"emoji":"๐จโ๐จโ๐ฆ","aliases":["family_man_man_boy"]},{"emoji":"๐จโ๐จโ๐ง","aliases":["family_man_man_girl"]},{"emoji":"๐จโ๐จโ๐งโ๐ฆ","aliases":["family_man_man_girl_boy"]},{"emoji":"๐จโ๐จโ๐ฆโ๐ฆ","aliases":["family_man_man_boy_boy"]},{"emoji":"๐จโ๐จโ๐งโ๐ง","aliases":["family_man_man_girl_girl"]},{"emoji":"๐ฉโ๐ฉโ๐ฆ","aliases":["family_woman_woman_boy"]},{"emoji":"๐ฉโ๐ฉโ๐ง","aliases":["family_woman_woman_girl"]},{"emoji":"๐ฉโ๐ฉโ๐งโ๐ฆ","aliases":["family_woman_woman_girl_boy"]},{"emoji":"๐ฉโ๐ฉโ๐ฆโ๐ฆ","aliases":["family_woman_woman_boy_boy"]},{"emoji":"๐ฉโ๐ฉโ๐งโ๐ง","aliases":["family_woman_woman_girl_girl"]},{"emoji":"๐จโ๐ฆ","aliases":["family_man_boy"]},{"emoji":"๐จโ๐ฆโ๐ฆ","aliases":["family_man_boy_boy"]},{"emoji":"๐จโ๐ง","aliases":["family_man_girl"]},{"emoji":"๐จโ๐งโ๐ฆ","aliases":["family_man_girl_boy"]},{"emoji":"๐จโ๐งโ๐ง","aliases":["family_man_girl_girl"]},{"emoji":"๐ฉโ๐ฆ","aliases":["family_woman_boy"]},{"emoji":"๐ฉโ๐ฆโ๐ฆ","aliases":["family_woman_boy_boy"]},{"emoji":"๐ฉโ๐ง","aliases":["family_woman_girl"]},{"emoji":"๐ฉโ๐งโ๐ฆ","aliases":["family_woman_girl_boy"]},{"emoji":"๐ฉโ๐งโ๐ง","aliases":["family_woman_girl_girl"]},{"emoji":"๐ฃ๏ธ","aliases":["speaking_head"]},{"emoji":"๐ค","aliases":["bust_in_silhouette"]},{"emoji":"๐ฅ","aliases":["busts_in_silhouette"]},{"emoji":"๐ซ","aliases":["people_hugging"]},{"emoji":"๐ฃ","aliases":["footprints"]},{"emoji":"๐ต","aliases":["monkey_face"]},{"emoji":"๐","aliases":["monkey"]},{"emoji":"๐ฆ","aliases":["gorilla"]},{"emoji":"๐ฆง","aliases":["orangutan"]},{"emoji":"๐ถ","aliases":["dog"]},{"emoji":"๐","aliases":["dog2"]},{"emoji":"๐ฆฎ","aliases":["guide_dog"]},{"emoji":"๐โ๐ฆบ","aliases":["service_dog"]},{"emoji":"๐ฉ","aliases":["poodle"]},{"emoji":"๐บ","aliases":["wolf"]},{"emoji":"๐ฆ","aliases":["fox_face"]},{"emoji":"๐ฆ","aliases":["raccoon"]},{"emoji":"๐ฑ","aliases":["cat"]},{"emoji":"๐","aliases":["cat2"]},{"emoji":"๐โโฌ","aliases":["black_cat"]},{"emoji":"๐ฆ","aliases":["lion"]},{"emoji":"๐ฏ","aliases":["tiger"]},{"emoji":"๐ ","aliases":["tiger2"]},{"emoji":"๐","aliases":["leopard"]},{"emoji":"๐ด","aliases":["horse"]},{"emoji":"๐","aliases":["racehorse"]},{"emoji":"๐ฆ","aliases":["unicorn"]},{"emoji":"๐ฆ","aliases":["zebra"]},{"emoji":"๐ฆ","aliases":["deer"]},{"emoji":"๐ฆฌ","aliases":["bison"]},{"emoji":"๐ฎ","aliases":["cow"]},{"emoji":"๐","aliases":["ox"]},{"emoji":"๐","aliases":["water_buffalo"]},{"emoji":"๐","aliases":["cow2"]},{"emoji":"๐ท","aliases":["pig"]},{"emoji":"๐","aliases":["pig2"]},{"emoji":"๐","aliases":["boar"]},{"emoji":"๐ฝ","aliases":["pig_nose"]},{"emoji":"๐","aliases":["ram"]},{"emoji":"๐","aliases":["sheep"]},{"emoji":"๐","aliases":["goat"]},{"emoji":"๐ช","aliases":["dromedary_camel"]},{"emoji":"๐ซ","aliases":["camel"]},{"emoji":"๐ฆ","aliases":["llama"]},{"emoji":"๐ฆ","aliases":["giraffe"]},{"emoji":"๐","aliases":["elephant"]},{"emoji":"๐ฆฃ","aliases":["mammoth"]},{"emoji":"๐ฆ","aliases":["rhinoceros"]},{"emoji":"๐ฆ","aliases":["hippopotamus"]},{"emoji":"๐ญ","aliases":["mouse"]},{"emoji":"๐","aliases":["mouse2"]},{"emoji":"๐","aliases":["rat"]},{"emoji":"๐น","aliases":["hamster"]},{"emoji":"๐ฐ","aliases":["rabbit"]},{"emoji":"๐","aliases":["rabbit2"]},{"emoji":"๐ฟ๏ธ","aliases":["chipmunk"]},{"emoji":"๐ฆซ","aliases":["beaver"]},{"emoji":"๐ฆ","aliases":["hedgehog"]},{"emoji":"๐ฆ","aliases":["bat"]},{"emoji":"๐ป","aliases":["bear"]},{"emoji":"๐ปโโ๏ธ","aliases":["polar_bear"]},{"emoji":"๐จ","aliases":["koala"]},{"emoji":"๐ผ","aliases":["panda_face"]},{"emoji":"๐ฆฅ","aliases":["sloth"]},{"emoji":"๐ฆฆ","aliases":["otter"]},{"emoji":"๐ฆจ","aliases":["skunk"]},{"emoji":"๐ฆ","aliases":["kangaroo"]},{"emoji":"๐ฆก","aliases":["badger"]},{"emoji":"๐พ","aliases":["feet","paw_prints"]},{"emoji":"๐ฆ","aliases":["turkey"]},{"emoji":"๐","aliases":["chicken"]},{"emoji":"๐","aliases":["rooster"]},{"emoji":"๐ฃ","aliases":["hatching_chick"]},{"emoji":"๐ค","aliases":["baby_chick"]},{"emoji":"๐ฅ","aliases":["hatched_chick"]},{"emoji":"๐ฆ","aliases":["bird"]},{"emoji":"๐ง","aliases":["penguin"]},{"emoji":"๐๏ธ","aliases":["dove"]},{"emoji":"๐ฆ ","aliases":["eagle"]},{"emoji":"๐ฆ","aliases":["duck"]},{"emoji":"๐ฆข","aliases":["swan"]},{"emoji":"๐ฆ","aliases":["owl"]},{"emoji":"๐ฆค","aliases":["dodo"]},{"emoji":"๐ชถ","aliases":["feather"]},{"emoji":"๐ฆฉ","aliases":["flamingo"]},{"emoji":"๐ฆ","aliases":["peacock"]},{"emoji":"๐ฆ","aliases":["parrot"]},{"emoji":"๐ธ","aliases":["frog"]},{"emoji":"๐","aliases":["crocodile"]},{"emoji":"๐ข","aliases":["turtle"]},{"emoji":"๐ฆ","aliases":["lizard"]},{"emoji":"๐","aliases":["snake"]},{"emoji":"๐ฒ","aliases":["dragon_face"]},{"emoji":"๐","aliases":["dragon"]},{"emoji":"๐ฆ","aliases":["sauropod"]},{"emoji":"๐ฆ","aliases":["t-rex"]},{"emoji":"๐ณ","aliases":["whale"]},{"emoji":"๐","aliases":["whale2"]},{"emoji":"๐ฌ","aliases":["dolphin","flipper"]},{"emoji":"๐ฆญ","aliases":["seal"]},{"emoji":"๐","aliases":["fish"]},{"emoji":"๐ ","aliases":["tropical_fish"]},{"emoji":"๐ก","aliases":["blowfish"]},{"emoji":"๐ฆ","aliases":["shark"]},{"emoji":"๐","aliases":["octopus"]},{"emoji":"๐","aliases":["shell"]},{"emoji":"๐","aliases":["snail"]},{"emoji":"๐ฆ","aliases":["butterfly"]},{"emoji":"๐","aliases":["bug"]},{"emoji":"๐","aliases":["ant"]},{"emoji":"๐","aliases":["bee","honeybee"]},{"emoji":"๐ชฒ","aliases":["beetle"]},{"emoji":"๐","aliases":["lady_beetle"]},{"emoji":"๐ฆ","aliases":["cricket"]},{"emoji":"๐ชณ","aliases":["cockroach"]},{"emoji":"๐ท๏ธ","aliases":["spider"]},{"emoji":"๐ธ๏ธ","aliases":["spider_web"]},{"emoji":"๐ฆ","aliases":["scorpion"]},{"emoji":"๐ฆ","aliases":["mosquito"]},{"emoji":"๐ชฐ","aliases":["fly"]},{"emoji":"๐ชฑ","aliases":["worm"]},{"emoji":"๐ฆ ","aliases":["microbe"]},{"emoji":"๐","aliases":["bouquet"]},{"emoji":"๐ธ","aliases":["cherry_blossom"]},{"emoji":"๐ฎ","aliases":["white_flower"]},{"emoji":"๐ต๏ธ","aliases":["rosette"]},{"emoji":"๐น","aliases":["rose"]},{"emoji":"๐ฅ","aliases":["wilted_flower"]},{"emoji":"๐บ","aliases":["hibiscus"]},{"emoji":"๐ป","aliases":["sunflower"]},{"emoji":"๐ผ","aliases":["blossom"]},{"emoji":"๐ท","aliases":["tulip"]},{"emoji":"๐ฑ","aliases":["seedling"]},{"emoji":"๐ชด","aliases":["potted_plant"]},{"emoji":"๐ฒ","aliases":["evergreen_tree"]},{"emoji":"๐ณ","aliases":["deciduous_tree"]},{"emoji":"๐ด","aliases":["palm_tree"]},{"emoji":"๐ต","aliases":["cactus"]},{"emoji":"๐พ","aliases":["ear_of_rice"]},{"emoji":"๐ฟ","aliases":["herb"]},{"emoji":"โ๏ธ","aliases":["shamrock"]},{"emoji":"๐","aliases":["four_leaf_clover"]},{"emoji":"๐","aliases":["maple_leaf"]},{"emoji":"๐","aliases":["fallen_leaf"]},{"emoji":"๐","aliases":["leaves"]},{"emoji":"๐","aliases":["grapes"]},{"emoji":"๐","aliases":["melon"]},{"emoji":"๐","aliases":["watermelon"]},{"emoji":"๐","aliases":["tangerine","orange","mandarin"]},{"emoji":"๐","aliases":["lemon"]},{"emoji":"๐","aliases":["banana"]},{"emoji":"๐","aliases":["pineapple"]},{"emoji":"๐ฅญ","aliases":["mango"]},{"emoji":"๐","aliases":["apple"]},{"emoji":"๐","aliases":["green_apple"]},{"emoji":"๐","aliases":["pear"]},{"emoji":"๐","aliases":["peach"]},{"emoji":"๐","aliases":["cherries"]},{"emoji":"๐","aliases":["strawberry"]},{"emoji":"๐ซ","aliases":["blueberries"]},{"emoji":"๐ฅ","aliases":["kiwi_fruit"]},{"emoji":"๐ ","aliases":["tomato"]},{"emoji":"๐ซ","aliases":["olive"]},{"emoji":"๐ฅฅ","aliases":["coconut"]},{"emoji":"๐ฅ","aliases":["avocado"]},{"emoji":"๐","aliases":["eggplant"]},{"emoji":"๐ฅ","aliases":["potato"]},{"emoji":"๐ฅ","aliases":["carrot"]},{"emoji":"๐ฝ","aliases":["corn"]},{"emoji":"๐ถ๏ธ","aliases":["hot_pepper"]},{"emoji":"๐ซ","aliases":["bell_pepper"]},{"emoji":"๐ฅ","aliases":["cucumber"]},{"emoji":"๐ฅฌ","aliases":["leafy_green"]},{"emoji":"๐ฅฆ","aliases":["broccoli"]},{"emoji":"๐ง","aliases":["garlic"]},{"emoji":"๐ง ","aliases":["onion"]},{"emoji":"๐","aliases":["mushroom"]},{"emoji":"๐ฅ","aliases":["peanuts"]},{"emoji":"๐ฐ","aliases":["chestnut"]},{"emoji":"๐","aliases":["bread"]},{"emoji":"๐ฅ","aliases":["croissant"]},{"emoji":"๐ฅ","aliases":["baguette_bread"]},{"emoji":"๐ซ","aliases":["flatbread"]},{"emoji":"๐ฅจ","aliases":["pretzel"]},{"emoji":"๐ฅฏ","aliases":["bagel"]},{"emoji":"๐ฅ","aliases":["pancakes"]},{"emoji":"๐ง","aliases":["waffle"]},{"emoji":"๐ง","aliases":["cheese"]},{"emoji":"๐","aliases":["meat_on_bone"]},{"emoji":"๐","aliases":["poultry_leg"]},{"emoji":"๐ฅฉ","aliases":["cut_of_meat"]},{"emoji":"๐ฅ","aliases":["bacon"]},{"emoji":"๐","aliases":["hamburger"]},{"emoji":"๐","aliases":["fries"]},{"emoji":"๐","aliases":["pizza"]},{"emoji":"๐ญ","aliases":["hotdog"]},{"emoji":"๐ฅช","aliases":["sandwich"]},{"emoji":"๐ฎ","aliases":["taco"]},{"emoji":"๐ฏ","aliases":["burrito"]},{"emoji":"๐ซ","aliases":["tamale"]},{"emoji":"๐ฅ","aliases":["stuffed_flatbread"]},{"emoji":"๐ง","aliases":["falafel"]},{"emoji":"๐ฅ","aliases":["egg"]},{"emoji":"๐ณ","aliases":["fried_egg"]},{"emoji":"๐ฅ","aliases":["shallow_pan_of_food"]},{"emoji":"๐ฒ","aliases":["stew"]},{"emoji":"๐ซ","aliases":["fondue"]},{"emoji":"๐ฅฃ","aliases":["bowl_with_spoon"]},{"emoji":"๐ฅ","aliases":["green_salad"]},{"emoji":"๐ฟ","aliases":["popcorn"]},{"emoji":"๐ง","aliases":["butter"]},{"emoji":"๐ง","aliases":["salt"]},{"emoji":"๐ฅซ","aliases":["canned_food"]},{"emoji":"๐ฑ","aliases":["bento"]},{"emoji":"๐","aliases":["rice_cracker"]},{"emoji":"๐","aliases":["rice_ball"]},{"emoji":"๐","aliases":["rice"]},{"emoji":"๐","aliases":["curry"]},{"emoji":"๐","aliases":["ramen"]},{"emoji":"๐","aliases":["spaghetti"]},{"emoji":"๐ ","aliases":["sweet_potato"]},{"emoji":"๐ข","aliases":["oden"]},{"emoji":"๐ฃ","aliases":["sushi"]},{"emoji":"๐ค","aliases":["fried_shrimp"]},{"emoji":"๐ฅ","aliases":["fish_cake"]},{"emoji":"๐ฅฎ","aliases":["moon_cake"]},{"emoji":"๐ก","aliases":["dango"]},{"emoji":"๐ฅ","aliases":["dumpling"]},{"emoji":"๐ฅ ","aliases":["fortune_cookie"]},{"emoji":"๐ฅก","aliases":["takeout_box"]},{"emoji":"๐ฆ","aliases":["crab"]},{"emoji":"๐ฆ","aliases":["lobster"]},{"emoji":"๐ฆ","aliases":["shrimp"]},{"emoji":"๐ฆ","aliases":["squid"]},{"emoji":"๐ฆช","aliases":["oyster"]},{"emoji":"๐ฆ","aliases":["icecream"]},{"emoji":"๐ง","aliases":["shaved_ice"]},{"emoji":"๐จ","aliases":["ice_cream"]},{"emoji":"๐ฉ","aliases":["doughnut"]},{"emoji":"๐ช","aliases":["cookie"]},{"emoji":"๐","aliases":["birthday"]},{"emoji":"๐ฐ","aliases":["cake"]},{"emoji":"๐ง","aliases":["cupcake"]},{"emoji":"๐ฅง","aliases":["pie"]},{"emoji":"๐ซ","aliases":["chocolate_bar"]},{"emoji":"๐ฌ","aliases":["candy"]},{"emoji":"๐ญ","aliases":["lollipop"]},{"emoji":"๐ฎ","aliases":["custard"]},{"emoji":"๐ฏ","aliases":["honey_pot"]},{"emoji":"๐ผ","aliases":["baby_bottle"]},{"emoji":"๐ฅ","aliases":["milk_glass"]},{"emoji":"โ","aliases":["coffee"]},{"emoji":"๐ซ","aliases":["teapot"]},{"emoji":"๐ต","aliases":["tea"]},{"emoji":"๐ถ","aliases":["sake"]},{"emoji":"๐พ","aliases":["champagne"]},{"emoji":"๐ท","aliases":["wine_glass"]},{"emoji":"๐ธ","aliases":["cocktail"]},{"emoji":"๐น","aliases":["tropical_drink"]},{"emoji":"๐บ","aliases":["beer"]},{"emoji":"๐ป","aliases":["beers"]},{"emoji":"๐ฅ","aliases":["clinking_glasses"]},{"emoji":"๐ฅ","aliases":["tumbler_glass"]},{"emoji":"๐ฅค","aliases":["cup_with_straw"]},{"emoji":"๐ง","aliases":["bubble_tea"]},{"emoji":"๐ง","aliases":["beverage_box"]},{"emoji":"๐ง","aliases":["mate"]},{"emoji":"๐ง","aliases":["ice_cube"]},{"emoji":"๐ฅข","aliases":["chopsticks"]},{"emoji":"๐ฝ๏ธ","aliases":["plate_with_cutlery"]},{"emoji":"๐ด","aliases":["fork_and_knife"]},{"emoji":"๐ฅ","aliases":["spoon"]},{"emoji":"๐ช","aliases":["hocho","knife"]},{"emoji":"๐บ","aliases":["amphora"]},{"emoji":"๐","aliases":["earth_africa"]},{"emoji":"๐","aliases":["earth_americas"]},{"emoji":"๐","aliases":["earth_asia"]},{"emoji":"๐","aliases":["globe_with_meridians"]},{"emoji":"๐บ๏ธ","aliases":["world_map"]},{"emoji":"๐พ","aliases":["japan"]},{"emoji":"๐งญ","aliases":["compass"]},{"emoji":"๐๏ธ","aliases":["mountain_snow"]},{"emoji":"โฐ๏ธ","aliases":["mountain"]},{"emoji":"๐","aliases":["volcano"]},{"emoji":"๐ป","aliases":["mount_fuji"]},{"emoji":"๐๏ธ","aliases":["camping"]},{"emoji":"๐๏ธ","aliases":["beach_umbrella"]},{"emoji":"๐๏ธ","aliases":["desert"]},{"emoji":"๐๏ธ","aliases":["desert_island"]},{"emoji":"๐๏ธ","aliases":["national_park"]},{"emoji":"๐๏ธ","aliases":["stadium"]},{"emoji":"๐๏ธ","aliases":["classical_building"]},{"emoji":"๐๏ธ","aliases":["building_construction"]},{"emoji":"๐งฑ","aliases":["bricks"]},{"emoji":"๐ชจ","aliases":["rock"]},{"emoji":"๐ชต","aliases":["wood"]},{"emoji":"๐","aliases":["hut"]},{"emoji":"๐๏ธ","aliases":["houses"]},{"emoji":"๐๏ธ","aliases":["derelict_house"]},{"emoji":"๐ ","aliases":["house"]},{"emoji":"๐ก","aliases":["house_with_garden"]},{"emoji":"๐ข","aliases":["office"]},{"emoji":"๐ฃ","aliases":["post_office"]},{"emoji":"๐ค","aliases":["european_post_office"]},{"emoji":"๐ฅ","aliases":["hospital"]},{"emoji":"๐ฆ","aliases":["bank"]},{"emoji":"๐จ","aliases":["hotel"]},{"emoji":"๐ฉ","aliases":["love_hotel"]},{"emoji":"๐ช","aliases":["convenience_store"]},{"emoji":"๐ซ","aliases":["school"]},{"emoji":"๐ฌ","aliases":["department_store"]},{"emoji":"๐ญ","aliases":["factory"]},{"emoji":"๐ฏ","aliases":["japanese_castle"]},{"emoji":"๐ฐ","aliases":["european_castle"]},{"emoji":"๐","aliases":["wedding"]},{"emoji":"๐ผ","aliases":["tokyo_tower"]},{"emoji":"๐ฝ","aliases":["statue_of_liberty"]},{"emoji":"โช","aliases":["church"]},{"emoji":"๐","aliases":["mosque"]},{"emoji":"๐","aliases":["hindu_temple"]},{"emoji":"๐","aliases":["synagogue"]},{"emoji":"โฉ๏ธ","aliases":["shinto_shrine"]},{"emoji":"๐","aliases":["kaaba"]},{"emoji":"โฒ","aliases":["fountain"]},{"emoji":"โบ","aliases":["tent"]},{"emoji":"๐","aliases":["foggy"]},{"emoji":"๐","aliases":["night_with_stars"]},{"emoji":"๐๏ธ","aliases":["cityscape"]},{"emoji":"๐","aliases":["sunrise_over_mountains"]},{"emoji":"๐ ","aliases":["sunrise"]},{"emoji":"๐","aliases":["city_sunset"]},{"emoji":"๐","aliases":["city_sunrise"]},{"emoji":"๐","aliases":["bridge_at_night"]},{"emoji":"โจ๏ธ","aliases":["hotsprings"]},{"emoji":"๐ ","aliases":["carousel_horse"]},{"emoji":"๐ก","aliases":["ferris_wheel"]},{"emoji":"๐ข","aliases":["roller_coaster"]},{"emoji":"๐","aliases":["barber"]},{"emoji":"๐ช","aliases":["circus_tent"]},{"emoji":"๐","aliases":["steam_locomotive"]},{"emoji":"๐","aliases":["railway_car"]},{"emoji":"๐","aliases":["bullettrain_side"]},{"emoji":"๐ ","aliases":["bullettrain_front"]},{"emoji":"๐","aliases":["train2"]},{"emoji":"๐","aliases":["metro"]},{"emoji":"๐","aliases":["light_rail"]},{"emoji":"๐","aliases":["station"]},{"emoji":"๐","aliases":["tram"]},{"emoji":"๐","aliases":["monorail"]},{"emoji":"๐","aliases":["mountain_railway"]},{"emoji":"๐","aliases":["train"]},{"emoji":"๐","aliases":["bus"]},{"emoji":"๐","aliases":["oncoming_bus"]},{"emoji":"๐","aliases":["trolleybus"]},{"emoji":"๐","aliases":["minibus"]},{"emoji":"๐","aliases":["ambulance"]},{"emoji":"๐","aliases":["fire_engine"]},{"emoji":"๐","aliases":["police_car"]},{"emoji":"๐","aliases":["oncoming_police_car"]},{"emoji":"๐","aliases":["taxi"]},{"emoji":"๐","aliases":["oncoming_taxi"]},{"emoji":"๐","aliases":["car","red_car"]},{"emoji":"๐","aliases":["oncoming_automobile"]},{"emoji":"๐","aliases":["blue_car"]},{"emoji":"๐ป","aliases":["pickup_truck"]},{"emoji":"๐","aliases":["truck"]},{"emoji":"๐","aliases":["articulated_lorry"]},{"emoji":"๐","aliases":["tractor"]},{"emoji":"๐๏ธ","aliases":["racing_car"]},{"emoji":"๐๏ธ","aliases":["motorcycle"]},{"emoji":"๐ต","aliases":["motor_scooter"]},{"emoji":"๐ฆฝ","aliases":["manual_wheelchair"]},{"emoji":"๐ฆผ","aliases":["motorized_wheelchair"]},{"emoji":"๐บ","aliases":["auto_rickshaw"]},{"emoji":"๐ฒ","aliases":["bike"]},{"emoji":"๐ด","aliases":["kick_scooter"]},{"emoji":"๐น","aliases":["skateboard"]},{"emoji":"๐ผ","aliases":["roller_skate"]},{"emoji":"๐","aliases":["busstop"]},{"emoji":"๐ฃ๏ธ","aliases":["motorway"]},{"emoji":"๐ค๏ธ","aliases":["railway_track"]},{"emoji":"๐ข๏ธ","aliases":["oil_drum"]},{"emoji":"โฝ","aliases":["fuelpump"]},{"emoji":"๐จ","aliases":["rotating_light"]},{"emoji":"๐ฅ","aliases":["traffic_light"]},{"emoji":"๐ฆ","aliases":["vertical_traffic_light"]},{"emoji":"๐","aliases":["stop_sign"]},{"emoji":"๐ง","aliases":["construction"]},{"emoji":"โ","aliases":["anchor"]},{"emoji":"โต","aliases":["boat","sailboat"]},{"emoji":"๐ถ","aliases":["canoe"]},{"emoji":"๐ค","aliases":["speedboat"]},{"emoji":"๐ณ๏ธ","aliases":["passenger_ship"]},{"emoji":"โด๏ธ","aliases":["ferry"]},{"emoji":"๐ฅ๏ธ","aliases":["motor_boat"]},{"emoji":"๐ข","aliases":["ship"]},{"emoji":"โ๏ธ","aliases":["airplane"]},{"emoji":"๐ฉ๏ธ","aliases":["small_airplane"]},{"emoji":"๐ซ","aliases":["flight_departure"]},{"emoji":"๐ฌ","aliases":["flight_arrival"]},{"emoji":"๐ช","aliases":["parachute"]},{"emoji":"๐บ","aliases":["seat"]},{"emoji":"๐","aliases":["helicopter"]},{"emoji":"๐","aliases":["suspension_railway"]},{"emoji":"๐ ","aliases":["mountain_cableway"]},{"emoji":"๐ก","aliases":["aerial_tramway"]},{"emoji":"๐ฐ๏ธ","aliases":["artificial_satellite"]},{"emoji":"๐","aliases":["rocket"]},{"emoji":"๐ธ","aliases":["flying_saucer"]},{"emoji":"๐๏ธ","aliases":["bellhop_bell"]},{"emoji":"๐งณ","aliases":["luggage"]},{"emoji":"โ","aliases":["hourglass"]},{"emoji":"โณ","aliases":["hourglass_flowing_sand"]},{"emoji":"โ","aliases":["watch"]},{"emoji":"โฐ","aliases":["alarm_clock"]},{"emoji":"โฑ๏ธ","aliases":["stopwatch"]},{"emoji":"โฒ๏ธ","aliases":["timer_clock"]},{"emoji":"๐ฐ๏ธ","aliases":["mantelpiece_clock"]},{"emoji":"๐","aliases":["clock12"]},{"emoji":"๐ง","aliases":["clock1230"]},{"emoji":"๐","aliases":["clock1"]},{"emoji":"๐","aliases":["clock130"]},{"emoji":"๐","aliases":["clock2"]},{"emoji":"๐","aliases":["clock230"]},{"emoji":"๐","aliases":["clock3"]},{"emoji":"๐","aliases":["clock330"]},{"emoji":"๐","aliases":["clock4"]},{"emoji":"๐","aliases":["clock430"]},{"emoji":"๐","aliases":["clock5"]},{"emoji":"๐ ","aliases":["clock530"]},{"emoji":"๐","aliases":["clock6"]},{"emoji":"๐ก","aliases":["clock630"]},{"emoji":"๐","aliases":["clock7"]},{"emoji":"๐ข","aliases":["clock730"]},{"emoji":"๐","aliases":["clock8"]},{"emoji":"๐ฃ","aliases":["clock830"]},{"emoji":"๐","aliases":["clock9"]},{"emoji":"๐ค","aliases":["clock930"]},{"emoji":"๐","aliases":["clock10"]},{"emoji":"๐ฅ","aliases":["clock1030"]},{"emoji":"๐","aliases":["clock11"]},{"emoji":"๐ฆ","aliases":["clock1130"]},{"emoji":"๐","aliases":["new_moon"]},{"emoji":"๐","aliases":["waxing_crescent_moon"]},{"emoji":"๐","aliases":["first_quarter_moon"]},{"emoji":"๐","aliases":["moon","waxing_gibbous_moon"]},{"emoji":"๐","aliases":["full_moon"]},{"emoji":"๐","aliases":["waning_gibbous_moon"]},{"emoji":"๐","aliases":["last_quarter_moon"]},{"emoji":"๐","aliases":["waning_crescent_moon"]},{"emoji":"๐","aliases":["crescent_moon"]},{"emoji":"๐","aliases":["new_moon_with_face"]},{"emoji":"๐","aliases":["first_quarter_moon_with_face"]},{"emoji":"๐","aliases":["last_quarter_moon_with_face"]},{"emoji":"๐ก๏ธ","aliases":["thermometer"]},{"emoji":"โ๏ธ","aliases":["sunny"]},{"emoji":"๐","aliases":["full_moon_with_face"]},{"emoji":"๐","aliases":["sun_with_face"]},{"emoji":"๐ช","aliases":["ringed_planet"]},{"emoji":"โญ","aliases":["star"]},{"emoji":"๐","aliases":["star2"]},{"emoji":"๐ ","aliases":["stars"]},{"emoji":"๐","aliases":["milky_way"]},{"emoji":"โ๏ธ","aliases":["cloud"]},{"emoji":"โ ","aliases":["partly_sunny"]},{"emoji":"โ๏ธ","aliases":["cloud_with_lightning_and_rain"]},{"emoji":"๐ค๏ธ","aliases":["sun_behind_small_cloud"]},{"emoji":"๐ฅ๏ธ","aliases":["sun_behind_large_cloud"]},{"emoji":"๐ฆ๏ธ","aliases":["sun_behind_rain_cloud"]},{"emoji":"๐ง๏ธ","aliases":["cloud_with_rain"]},{"emoji":"๐จ๏ธ","aliases":["cloud_with_snow"]},{"emoji":"๐ฉ๏ธ","aliases":["cloud_with_lightning"]},{"emoji":"๐ช๏ธ","aliases":["tornado"]},{"emoji":"๐ซ๏ธ","aliases":["fog"]},{"emoji":"๐ฌ๏ธ","aliases":["wind_face"]},{"emoji":"๐","aliases":["cyclone"]},{"emoji":"๐","aliases":["rainbow"]},{"emoji":"๐","aliases":["closed_umbrella"]},{"emoji":"โ๏ธ","aliases":["open_umbrella"]},{"emoji":"โ","aliases":["umbrella"]},{"emoji":"โฑ๏ธ","aliases":["parasol_on_ground"]},{"emoji":"โก","aliases":["zap"]},{"emoji":"โ๏ธ","aliases":["snowflake"]},{"emoji":"โ๏ธ","aliases":["snowman_with_snow"]},{"emoji":"โ","aliases":["snowman"]},{"emoji":"โ๏ธ","aliases":["comet"]},{"emoji":"๐ฅ","aliases":["fire"]},{"emoji":"๐ง","aliases":["droplet"]},{"emoji":"๐","aliases":["ocean"]},{"emoji":"๐","aliases":["jack_o_lantern"]},{"emoji":"๐","aliases":["christmas_tree"]},{"emoji":"๐","aliases":["fireworks"]},{"emoji":"๐","aliases":["sparkler"]},{"emoji":"๐งจ","aliases":["firecracker"]},{"emoji":"โจ","aliases":["sparkles"]},{"emoji":"๐","aliases":["balloon"]},{"emoji":"๐","aliases":["tada"]},{"emoji":"๐","aliases":["confetti_ball"]},{"emoji":"๐","aliases":["tanabata_tree"]},{"emoji":"๐","aliases":["bamboo"]},{"emoji":"๐","aliases":["dolls"]},{"emoji":"๐","aliases":["flags"]},{"emoji":"๐","aliases":["wind_chime"]},{"emoji":"๐","aliases":["rice_scene"]},{"emoji":"๐งง","aliases":["red_envelope"]},{"emoji":"๐","aliases":["ribbon"]},{"emoji":"๐","aliases":["gift"]},{"emoji":"๐๏ธ","aliases":["reminder_ribbon"]},{"emoji":"๐๏ธ","aliases":["tickets"]},{"emoji":"๐ซ","aliases":["ticket"]},{"emoji":"๐๏ธ","aliases":["medal_military"]},{"emoji":"๐","aliases":["trophy"]},{"emoji":"๐ ","aliases":["medal_sports"]},{"emoji":"๐ฅ","aliases":["1st_place_medal"]},{"emoji":"๐ฅ","aliases":["2nd_place_medal"]},{"emoji":"๐ฅ","aliases":["3rd_place_medal"]},{"emoji":"โฝ","aliases":["soccer"]},{"emoji":"โพ","aliases":["baseball"]},{"emoji":"๐ฅ","aliases":["softball"]},{"emoji":"๐","aliases":["basketball"]},{"emoji":"๐","aliases":["volleyball"]},{"emoji":"๐","aliases":["football"]},{"emoji":"๐","aliases":["rugby_football"]},{"emoji":"๐พ","aliases":["tennis"]},{"emoji":"๐ฅ","aliases":["flying_disc"]},{"emoji":"๐ณ","aliases":["bowling"]},{"emoji":"๐","aliases":["cricket_game"]},{"emoji":"๐","aliases":["field_hockey"]},{"emoji":"๐","aliases":["ice_hockey"]},{"emoji":"๐ฅ","aliases":["lacrosse"]},{"emoji":"๐","aliases":["ping_pong"]},{"emoji":"๐ธ","aliases":["badminton"]},{"emoji":"๐ฅ","aliases":["boxing_glove"]},{"emoji":"๐ฅ","aliases":["martial_arts_uniform"]},{"emoji":"๐ฅ ","aliases":["goal_net"]},{"emoji":"โณ","aliases":["golf"]},{"emoji":"โธ๏ธ","aliases":["ice_skate"]},{"emoji":"๐ฃ","aliases":["fishing_pole_and_fish"]},{"emoji":"๐คฟ","aliases":["diving_mask"]},{"emoji":"๐ฝ","aliases":["running_shirt_with_sash"]},{"emoji":"๐ฟ","aliases":["ski"]},{"emoji":"๐ท","aliases":["sled"]},{"emoji":"๐ฅ","aliases":["curling_stone"]},{"emoji":"๐ฏ","aliases":["dart"]},{"emoji":"๐ช","aliases":["yo_yo"]},{"emoji":"๐ช","aliases":["kite"]},{"emoji":"๐ฑ","aliases":["8ball"]},{"emoji":"๐ฎ","aliases":["crystal_ball"]},{"emoji":"๐ช","aliases":["magic_wand"]},{"emoji":"๐งฟ","aliases":["nazar_amulet"]},{"emoji":"๐ฎ","aliases":["video_game"]},{"emoji":"๐น๏ธ","aliases":["joystick"]},{"emoji":"๐ฐ","aliases":["slot_machine"]},{"emoji":"๐ฒ","aliases":["game_die"]},{"emoji":"๐งฉ","aliases":["jigsaw"]},{"emoji":"๐งธ","aliases":["teddy_bear"]},{"emoji":"๐ช ","aliases":["pinata"]},{"emoji":"๐ช","aliases":["nesting_dolls"]},{"emoji":"โ ๏ธ","aliases":["spades"]},{"emoji":"โฅ๏ธ","aliases":["hearts"]},{"emoji":"โฆ๏ธ","aliases":["diamonds"]},{"emoji":"โฃ๏ธ","aliases":["clubs"]},{"emoji":"โ๏ธ","aliases":["chess_pawn"]},{"emoji":"๐","aliases":["black_joker"]},{"emoji":"๐","aliases":["mahjong"]},{"emoji":"๐ด","aliases":["flower_playing_cards"]},{"emoji":"๐ญ","aliases":["performing_arts"]},{"emoji":"๐ผ๏ธ","aliases":["framed_picture"]},{"emoji":"๐จ","aliases":["art"]},{"emoji":"๐งต","aliases":["thread"]},{"emoji":"๐ชก","aliases":["sewing_needle"]},{"emoji":"๐งถ","aliases":["yarn"]},{"emoji":"๐ชข","aliases":["knot"]},{"emoji":"๐","aliases":["eyeglasses"]},{"emoji":"๐ถ๏ธ","aliases":["dark_sunglasses"]},{"emoji":"๐ฅฝ","aliases":["goggles"]},{"emoji":"๐ฅผ","aliases":["lab_coat"]},{"emoji":"๐ฆบ","aliases":["safety_vest"]},{"emoji":"๐","aliases":["necktie"]},{"emoji":"๐","aliases":["shirt","tshirt"]},{"emoji":"๐","aliases":["jeans"]},{"emoji":"๐งฃ","aliases":["scarf"]},{"emoji":"๐งค","aliases":["gloves"]},{"emoji":"๐งฅ","aliases":["coat"]},{"emoji":"๐งฆ","aliases":["socks"]},{"emoji":"๐","aliases":["dress"]},{"emoji":"๐","aliases":["kimono"]},{"emoji":"๐ฅป","aliases":["sari"]},{"emoji":"๐ฉฑ","aliases":["one_piece_swimsuit"]},{"emoji":"๐ฉฒ","aliases":["swim_brief"]},{"emoji":"๐ฉณ","aliases":["shorts"]},{"emoji":"๐","aliases":["bikini"]},{"emoji":"๐","aliases":["womans_clothes"]},{"emoji":"๐","aliases":["purse"]},{"emoji":"๐","aliases":["handbag"]},{"emoji":"๐","aliases":["pouch"]},{"emoji":"๐๏ธ","aliases":["shopping"]},{"emoji":"๐","aliases":["school_satchel"]},{"emoji":"๐ฉด","aliases":["thong_sandal"]},{"emoji":"๐","aliases":["mans_shoe","shoe"]},{"emoji":"๐","aliases":["athletic_shoe"]},{"emoji":"๐ฅพ","aliases":["hiking_boot"]},{"emoji":"๐ฅฟ","aliases":["flat_shoe"]},{"emoji":"๐ ","aliases":["high_heel"]},{"emoji":"๐ก","aliases":["sandal"]},{"emoji":"๐ฉฐ","aliases":["ballet_shoes"]},{"emoji":"๐ข","aliases":["boot"]},{"emoji":"๐","aliases":["crown"]},{"emoji":"๐","aliases":["womans_hat"]},{"emoji":"๐ฉ","aliases":["tophat"]},{"emoji":"๐","aliases":["mortar_board"]},{"emoji":"๐งข","aliases":["billed_cap"]},{"emoji":"๐ช","aliases":["military_helmet"]},{"emoji":"โ๏ธ","aliases":["rescue_worker_helmet"]},{"emoji":"๐ฟ","aliases":["prayer_beads"]},{"emoji":"๐","aliases":["lipstick"]},{"emoji":"๐","aliases":["ring"]},{"emoji":"๐","aliases":["gem"]},{"emoji":"๐","aliases":["mute"]},{"emoji":"๐","aliases":["speaker"]},{"emoji":"๐","aliases":["sound"]},{"emoji":"๐","aliases":["loud_sound"]},{"emoji":"๐ข","aliases":["loudspeaker"]},{"emoji":"๐ฃ","aliases":["mega"]},{"emoji":"๐ฏ","aliases":["postal_horn"]},{"emoji":"๐","aliases":["bell"]},{"emoji":"๐","aliases":["no_bell"]},{"emoji":"๐ผ","aliases":["musical_score"]},{"emoji":"๐ต","aliases":["musical_note"]},{"emoji":"๐ถ","aliases":["notes"]},{"emoji":"๐๏ธ","aliases":["studio_microphone"]},{"emoji":"๐๏ธ","aliases":["level_slider"]},{"emoji":"๐๏ธ","aliases":["control_knobs"]},{"emoji":"๐ค","aliases":["microphone"]},{"emoji":"๐ง","aliases":["headphones"]},{"emoji":"๐ป","aliases":["radio"]},{"emoji":"๐ท","aliases":["saxophone"]},{"emoji":"๐ช","aliases":["accordion"]},{"emoji":"๐ธ","aliases":["guitar"]},{"emoji":"๐น","aliases":["musical_keyboard"]},{"emoji":"๐บ","aliases":["trumpet"]},{"emoji":"๐ป","aliases":["violin"]},{"emoji":"๐ช","aliases":["banjo"]},{"emoji":"๐ฅ","aliases":["drum"]},{"emoji":"๐ช","aliases":["long_drum"]},{"emoji":"๐ฑ","aliases":["iphone"]},{"emoji":"๐ฒ","aliases":["calling"]},{"emoji":"โ๏ธ","aliases":["phone","telephone"]},{"emoji":"๐","aliases":["telephone_receiver"]},{"emoji":"๐","aliases":["pager"]},{"emoji":"๐ ","aliases":["fax"]},{"emoji":"๐","aliases":["battery"]},{"emoji":"๐","aliases":["electric_plug"]},{"emoji":"๐ป","aliases":["computer"]},{"emoji":"๐ฅ๏ธ","aliases":["desktop_computer"]},{"emoji":"๐จ๏ธ","aliases":["printer"]},{"emoji":"โจ๏ธ","aliases":["keyboard"]},{"emoji":"๐ฑ๏ธ","aliases":["computer_mouse"]},{"emoji":"๐ฒ๏ธ","aliases":["trackball"]},{"emoji":"๐ฝ","aliases":["minidisc"]},{"emoji":"๐พ","aliases":["floppy_disk"]},{"emoji":"๐ฟ","aliases":["cd"]},{"emoji":"๐","aliases":["dvd"]},{"emoji":"๐งฎ","aliases":["abacus"]},{"emoji":"๐ฅ","aliases":["movie_camera"]},{"emoji":"๐๏ธ","aliases":["film_strip"]},{"emoji":"๐ฝ๏ธ","aliases":["film_projector"]},{"emoji":"๐ฌ","aliases":["clapper"]},{"emoji":"๐บ","aliases":["tv"]},{"emoji":"๐ท","aliases":["camera"]},{"emoji":"๐ธ","aliases":["camera_flash"]},{"emoji":"๐น","aliases":["video_camera"]},{"emoji":"๐ผ","aliases":["vhs"]},{"emoji":"๐","aliases":["mag"]},{"emoji":"๐","aliases":["mag_right"]},{"emoji":"๐ฏ๏ธ","aliases":["candle"]},{"emoji":"๐ก","aliases":["bulb"]},{"emoji":"๐ฆ","aliases":["flashlight"]},{"emoji":"๐ฎ","aliases":["izakaya_lantern","lantern"]},{"emoji":"๐ช","aliases":["diya_lamp"]},{"emoji":"๐","aliases":["notebook_with_decorative_cover"]},{"emoji":"๐","aliases":["closed_book"]},{"emoji":"๐","aliases":["book","open_book"]},{"emoji":"๐","aliases":["green_book"]},{"emoji":"๐","aliases":["blue_book"]},{"emoji":"๐","aliases":["orange_book"]},{"emoji":"๐","aliases":["books"]},{"emoji":"๐","aliases":["notebook"]},{"emoji":"๐","aliases":["ledger"]},{"emoji":"๐","aliases":["page_with_curl"]},{"emoji":"๐","aliases":["scroll"]},{"emoji":"๐","aliases":["page_facing_up"]},{"emoji":"๐ฐ","aliases":["newspaper"]},{"emoji":"๐๏ธ","aliases":["newspaper_roll"]},{"emoji":"๐","aliases":["bookmark_tabs"]},{"emoji":"๐","aliases":["bookmark"]},{"emoji":"๐ท๏ธ","aliases":["label"]},{"emoji":"๐ฐ","aliases":["moneybag"]},{"emoji":"๐ช","aliases":["coin"]},{"emoji":"๐ด","aliases":["yen"]},{"emoji":"๐ต","aliases":["dollar"]},{"emoji":"๐ถ","aliases":["euro"]},{"emoji":"๐ท","aliases":["pound"]},{"emoji":"๐ธ","aliases":["money_with_wings"]},{"emoji":"๐ณ","aliases":["credit_card"]},{"emoji":"๐งพ","aliases":["receipt"]},{"emoji":"๐น","aliases":["chart"]},{"emoji":"โ๏ธ","aliases":["envelope"]},{"emoji":"๐ง","aliases":["email","e-mail"]},{"emoji":"๐จ","aliases":["incoming_envelope"]},{"emoji":"๐ฉ","aliases":["envelope_with_arrow"]},{"emoji":"๐ค","aliases":["outbox_tray"]},{"emoji":"๐ฅ","aliases":["inbox_tray"]},{"emoji":"๐ฆ","aliases":["package"]},{"emoji":"๐ซ","aliases":["mailbox"]},{"emoji":"๐ช","aliases":["mailbox_closed"]},{"emoji":"๐ฌ","aliases":["mailbox_with_mail"]},{"emoji":"๐ญ","aliases":["mailbox_with_no_mail"]},{"emoji":"๐ฎ","aliases":["postbox"]},{"emoji":"๐ณ๏ธ","aliases":["ballot_box"]},{"emoji":"โ๏ธ","aliases":["pencil2"]},{"emoji":"โ๏ธ","aliases":["black_nib"]},{"emoji":"๐๏ธ","aliases":["fountain_pen"]},{"emoji":"๐๏ธ","aliases":["pen"]},{"emoji":"๐๏ธ","aliases":["paintbrush"]},{"emoji":"๐๏ธ","aliases":["crayon"]},{"emoji":"๐","aliases":["memo","pencil"]},{"emoji":"๐ผ","aliases":["briefcase"]},{"emoji":"๐","aliases":["file_folder"]},{"emoji":"๐","aliases":["open_file_folder"]},{"emoji":"๐๏ธ","aliases":["card_index_dividers"]},{"emoji":"๐ ","aliases":["date"]},{"emoji":"๐","aliases":["calendar"]},{"emoji":"๐๏ธ","aliases":["spiral_notepad"]},{"emoji":"๐๏ธ","aliases":["spiral_calendar"]},{"emoji":"๐","aliases":["card_index"]},{"emoji":"๐","aliases":["chart_with_upwards_trend"]},{"emoji":"๐","aliases":["chart_with_downwards_trend"]},{"emoji":"๐","aliases":["bar_chart"]},{"emoji":"๐","aliases":["clipboard"]},{"emoji":"๐","aliases":["pushpin"]},{"emoji":"๐","aliases":["round_pushpin"]},{"emoji":"๐","aliases":["paperclip"]},{"emoji":"๐๏ธ","aliases":["paperclips"]},{"emoji":"๐","aliases":["straight_ruler"]},{"emoji":"๐","aliases":["triangular_ruler"]},{"emoji":"โ๏ธ","aliases":["scissors"]},{"emoji":"๐๏ธ","aliases":["card_file_box"]},{"emoji":"๐๏ธ","aliases":["file_cabinet"]},{"emoji":"๐๏ธ","aliases":["wastebasket"]},{"emoji":"๐","aliases":["lock"]},{"emoji":"๐","aliases":["unlock"]},{"emoji":"๐","aliases":["lock_with_ink_pen"]},{"emoji":"๐","aliases":["closed_lock_with_key"]},{"emoji":"๐","aliases":["key"]},{"emoji":"๐๏ธ","aliases":["old_key"]},{"emoji":"๐จ","aliases":["hammer"]},{"emoji":"๐ช","aliases":["axe"]},{"emoji":"โ๏ธ","aliases":["pick"]},{"emoji":"โ๏ธ","aliases":["hammer_and_pick"]},{"emoji":"๐ ๏ธ","aliases":["hammer_and_wrench"]},{"emoji":"๐ก๏ธ","aliases":["dagger"]},{"emoji":"โ๏ธ","aliases":["crossed_swords"]},{"emoji":"๐ซ","aliases":["gun"]},{"emoji":"๐ช","aliases":["boomerang"]},{"emoji":"๐น","aliases":["bow_and_arrow"]},{"emoji":"๐ก๏ธ","aliases":["shield"]},{"emoji":"๐ช","aliases":["carpentry_saw"]},{"emoji":"๐ง","aliases":["wrench"]},{"emoji":"๐ช","aliases":["screwdriver"]},{"emoji":"๐ฉ","aliases":["nut_and_bolt"]},{"emoji":"โ๏ธ","aliases":["gear"]},{"emoji":"๐๏ธ","aliases":["clamp"]},{"emoji":"โ๏ธ","aliases":["balance_scale"]},{"emoji":"๐ฆฏ","aliases":["probing_cane"]},{"emoji":"๐","aliases":["link"]},{"emoji":"โ๏ธ","aliases":["chains"]},{"emoji":"๐ช","aliases":["hook"]},{"emoji":"๐งฐ","aliases":["toolbox"]},{"emoji":"๐งฒ","aliases":["magnet"]},{"emoji":"๐ช","aliases":["ladder"]},{"emoji":"โ๏ธ","aliases":["alembic"]},{"emoji":"๐งช","aliases":["test_tube"]},{"emoji":"๐งซ","aliases":["petri_dish"]},{"emoji":"๐งฌ","aliases":["dna"]},{"emoji":"๐ฌ","aliases":["microscope"]},{"emoji":"๐ญ","aliases":["telescope"]},{"emoji":"๐ก","aliases":["satellite"]},{"emoji":"๐","aliases":["syringe"]},{"emoji":"๐ฉธ","aliases":["drop_of_blood"]},{"emoji":"๐","aliases":["pill"]},{"emoji":"๐ฉน","aliases":["adhesive_bandage"]},{"emoji":"๐ฉบ","aliases":["stethoscope"]},{"emoji":"๐ช","aliases":["door"]},{"emoji":"๐","aliases":["elevator"]},{"emoji":"๐ช","aliases":["mirror"]},{"emoji":"๐ช","aliases":["window"]},{"emoji":"๐๏ธ","aliases":["bed"]},{"emoji":"๐๏ธ","aliases":["couch_and_lamp"]},{"emoji":"๐ช","aliases":["chair"]},{"emoji":"๐ฝ","aliases":["toilet"]},{"emoji":"๐ช ","aliases":["plunger"]},{"emoji":"๐ฟ","aliases":["shower"]},{"emoji":"๐","aliases":["bathtub"]},{"emoji":"๐ชค","aliases":["mouse_trap"]},{"emoji":"๐ช","aliases":["razor"]},{"emoji":"๐งด","aliases":["lotion_bottle"]},{"emoji":"๐งท","aliases":["safety_pin"]},{"emoji":"๐งน","aliases":["broom"]},{"emoji":"๐งบ","aliases":["basket"]},{"emoji":"๐งป","aliases":["roll_of_paper"]},{"emoji":"๐ชฃ","aliases":["bucket"]},{"emoji":"๐งผ","aliases":["soap"]},{"emoji":"๐ชฅ","aliases":["toothbrush"]},{"emoji":"๐งฝ","aliases":["sponge"]},{"emoji":"๐งฏ","aliases":["fire_extinguisher"]},{"emoji":"๐","aliases":["shopping_cart"]},{"emoji":"๐ฌ","aliases":["smoking"]},{"emoji":"โฐ๏ธ","aliases":["coffin"]},{"emoji":"๐ชฆ","aliases":["headstone"]},{"emoji":"โฑ๏ธ","aliases":["funeral_urn"]},{"emoji":"๐ฟ","aliases":["moyai"]},{"emoji":"๐ชง","aliases":["placard"]},{"emoji":"๐ง","aliases":["atm"]},{"emoji":"๐ฎ","aliases":["put_litter_in_its_place"]},{"emoji":"๐ฐ","aliases":["potable_water"]},{"emoji":"โฟ","aliases":["wheelchair"]},{"emoji":"๐น","aliases":["mens"]},{"emoji":"๐บ","aliases":["womens"]},{"emoji":"๐ป","aliases":["restroom"]},{"emoji":"๐ผ","aliases":["baby_symbol"]},{"emoji":"๐พ","aliases":["wc"]},{"emoji":"๐","aliases":["passport_control"]},{"emoji":"๐","aliases":["customs"]},{"emoji":"๐","aliases":["baggage_claim"]},{"emoji":"๐ ","aliases":["left_luggage"]},{"emoji":"โ ๏ธ","aliases":["warning"]},{"emoji":"๐ธ","aliases":["children_crossing"]},{"emoji":"โ","aliases":["no_entry"]},{"emoji":"๐ซ","aliases":["no_entry_sign"]},{"emoji":"๐ณ","aliases":["no_bicycles"]},{"emoji":"๐ญ","aliases":["no_smoking"]},{"emoji":"๐ฏ","aliases":["do_not_litter"]},{"emoji":"๐ฑ","aliases":["non-potable_water"]},{"emoji":"๐ท","aliases":["no_pedestrians"]},{"emoji":"๐ต","aliases":["no_mobile_phones"]},{"emoji":"๐","aliases":["underage"]},{"emoji":"โข๏ธ","aliases":["radioactive"]},{"emoji":"โฃ๏ธ","aliases":["biohazard"]},{"emoji":"โฌ๏ธ","aliases":["arrow_up"]},{"emoji":"โ๏ธ","aliases":["arrow_upper_right"]},{"emoji":"โก๏ธ","aliases":["arrow_right"]},{"emoji":"โ๏ธ","aliases":["arrow_lower_right"]},{"emoji":"โฌ๏ธ","aliases":["arrow_down"]},{"emoji":"โ๏ธ","aliases":["arrow_lower_left"]},{"emoji":"โฌ ๏ธ","aliases":["arrow_left"]},{"emoji":"โ๏ธ","aliases":["arrow_upper_left"]},{"emoji":"โ๏ธ","aliases":["arrow_up_down"]},{"emoji":"โ๏ธ","aliases":["left_right_arrow"]},{"emoji":"โฉ๏ธ","aliases":["leftwards_arrow_with_hook"]},{"emoji":"โช๏ธ","aliases":["arrow_right_hook"]},{"emoji":"โคด๏ธ","aliases":["arrow_heading_up"]},{"emoji":"โคต๏ธ","aliases":["arrow_heading_down"]},{"emoji":"๐","aliases":["arrows_clockwise"]},{"emoji":"๐","aliases":["arrows_counterclockwise"]},{"emoji":"๐","aliases":["back"]},{"emoji":"๐","aliases":["end"]},{"emoji":"๐","aliases":["on"]},{"emoji":"๐","aliases":["soon"]},{"emoji":"๐","aliases":["top"]},{"emoji":"๐","aliases":["place_of_worship"]},{"emoji":"โ๏ธ","aliases":["atom_symbol"]},{"emoji":"๐๏ธ","aliases":["om"]},{"emoji":"โก๏ธ","aliases":["star_of_david"]},{"emoji":"โธ๏ธ","aliases":["wheel_of_dharma"]},{"emoji":"โฏ๏ธ","aliases":["yin_yang"]},{"emoji":"โ๏ธ","aliases":["latin_cross"]},{"emoji":"โฆ๏ธ","aliases":["orthodox_cross"]},{"emoji":"โช๏ธ","aliases":["star_and_crescent"]},{"emoji":"โฎ๏ธ","aliases":["peace_symbol"]},{"emoji":"๐","aliases":["menorah"]},{"emoji":"๐ฏ","aliases":["six_pointed_star"]},{"emoji":"โ","aliases":["aries"]},{"emoji":"โ","aliases":["taurus"]},{"emoji":"โ","aliases":["gemini"]},{"emoji":"โ","aliases":["cancer"]},{"emoji":"โ","aliases":["leo"]},{"emoji":"โ","aliases":["virgo"]},{"emoji":"โ","aliases":["libra"]},{"emoji":"โ","aliases":["scorpius"]},{"emoji":"โ","aliases":["sagittarius"]},{"emoji":"โ","aliases":["capricorn"]},{"emoji":"โ","aliases":["aquarius"]},{"emoji":"โ","aliases":["pisces"]},{"emoji":"โ","aliases":["ophiuchus"]},{"emoji":"๐","aliases":["twisted_rightwards_arrows"]},{"emoji":"๐","aliases":["repeat"]},{"emoji":"๐","aliases":["repeat_one"]},{"emoji":"โถ๏ธ","aliases":["arrow_forward"]},{"emoji":"โฉ","aliases":["fast_forward"]},{"emoji":"โญ๏ธ","aliases":["next_track_button"]},{"emoji":"โฏ๏ธ","aliases":["play_or_pause_button"]},{"emoji":"โ๏ธ","aliases":["arrow_backward"]},{"emoji":"โช","aliases":["rewind"]},{"emoji":"โฎ๏ธ","aliases":["previous_track_button"]},{"emoji":"๐ผ","aliases":["arrow_up_small"]},{"emoji":"โซ","aliases":["arrow_double_up"]},{"emoji":"๐ฝ","aliases":["arrow_down_small"]},{"emoji":"โฌ","aliases":["arrow_double_down"]},{"emoji":"โธ๏ธ","aliases":["pause_button"]},{"emoji":"โน๏ธ","aliases":["stop_button"]},{"emoji":"โบ๏ธ","aliases":["record_button"]},{"emoji":"โ๏ธ","aliases":["eject_button"]},{"emoji":"๐ฆ","aliases":["cinema"]},{"emoji":"๐ ","aliases":["low_brightness"]},{"emoji":"๐","aliases":["high_brightness"]},{"emoji":"๐ถ","aliases":["signal_strength"]},{"emoji":"๐ณ","aliases":["vibration_mode"]},{"emoji":"๐ด","aliases":["mobile_phone_off"]},{"emoji":"โ๏ธ","aliases":["female_sign"]},{"emoji":"โ๏ธ","aliases":["male_sign"]},{"emoji":"โง๏ธ","aliases":["transgender_symbol"]},{"emoji":"โ๏ธ","aliases":["heavy_multiplication_x"]},{"emoji":"โ","aliases":["heavy_plus_sign"]},{"emoji":"โ","aliases":["heavy_minus_sign"]},{"emoji":"โ","aliases":["heavy_division_sign"]},{"emoji":"โพ๏ธ","aliases":["infinity"]},{"emoji":"โผ๏ธ","aliases":["bangbang"]},{"emoji":"โ๏ธ","aliases":["interrobang"]},{"emoji":"โ","aliases":["question"]},{"emoji":"โ","aliases":["grey_question"]},{"emoji":"โ","aliases":["grey_exclamation"]},{"emoji":"โ","aliases":["exclamation","heavy_exclamation_mark"]},{"emoji":"ใฐ๏ธ","aliases":["wavy_dash"]},{"emoji":"๐ฑ","aliases":["currency_exchange"]},{"emoji":"๐ฒ","aliases":["heavy_dollar_sign"]},{"emoji":"โ๏ธ","aliases":["medical_symbol"]},{"emoji":"โป๏ธ","aliases":["recycle"]},{"emoji":"โ๏ธ","aliases":["fleur_de_lis"]},{"emoji":"๐ฑ","aliases":["trident"]},{"emoji":"๐","aliases":["name_badge"]},{"emoji":"๐ฐ","aliases":["beginner"]},{"emoji":"โญ","aliases":["o"]},{"emoji":"โ ","aliases":["white_check_mark"]},{"emoji":"โ๏ธ","aliases":["ballot_box_with_check"]},{"emoji":"โ๏ธ","aliases":["heavy_check_mark"]},{"emoji":"โ","aliases":["x"]},{"emoji":"โ","aliases":["negative_squared_cross_mark"]},{"emoji":"โฐ","aliases":["curly_loop"]},{"emoji":"โฟ","aliases":["loop"]},{"emoji":"ใฝ๏ธ","aliases":["part_alternation_mark"]},{"emoji":"โณ๏ธ","aliases":["eight_spoked_asterisk"]},{"emoji":"โด๏ธ","aliases":["eight_pointed_black_star"]},{"emoji":"โ๏ธ","aliases":["sparkle"]},{"emoji":"ยฉ๏ธ","aliases":["copyright"]},{"emoji":"ยฎ๏ธ","aliases":["registered"]},{"emoji":"โข๏ธ","aliases":["tm"]},{"emoji":"#๏ธโฃ","aliases":["hash"]},{"emoji":"*๏ธโฃ","aliases":["asterisk"]},{"emoji":"0๏ธโฃ","aliases":["zero"]},{"emoji":"1๏ธโฃ","aliases":["one"]},{"emoji":"2๏ธโฃ","aliases":["two"]},{"emoji":"3๏ธโฃ","aliases":["three"]},{"emoji":"4๏ธโฃ","aliases":["four"]},{"emoji":"5๏ธโฃ","aliases":["five"]},{"emoji":"6๏ธโฃ","aliases":["six"]},{"emoji":"7๏ธโฃ","aliases":["seven"]},{"emoji":"8๏ธโฃ","aliases":["eight"]},{"emoji":"9๏ธโฃ","aliases":["nine"]},{"emoji":"๐","aliases":["keycap_ten"]},{"emoji":"๐ ","aliases":["capital_abcd"]},{"emoji":"๐ก","aliases":["abcd"]},{"emoji":"๐ข","aliases":["1234"]},{"emoji":"๐ฃ","aliases":["symbols"]},{"emoji":"๐ค","aliases":["abc"]},{"emoji":"๐ ฐ๏ธ","aliases":["a"]},{"emoji":"๐","aliases":["ab"]},{"emoji":"๐ ฑ๏ธ","aliases":["b"]},{"emoji":"๐","aliases":["cl"]},{"emoji":"๐","aliases":["cool"]},{"emoji":"๐","aliases":["free"]},{"emoji":"โน๏ธ","aliases":["information_source"]},{"emoji":"๐","aliases":["id"]},{"emoji":"โ๏ธ","aliases":["m"]},{"emoji":"๐","aliases":["new"]},{"emoji":"๐","aliases":["ng"]},{"emoji":"๐ พ๏ธ","aliases":["o2"]},{"emoji":"๐","aliases":["ok"]},{"emoji":"๐ ฟ๏ธ","aliases":["parking"]},{"emoji":"๐","aliases":["sos"]},{"emoji":"๐","aliases":["up"]},{"emoji":"๐","aliases":["vs"]},{"emoji":"๐","aliases":["koko"]},{"emoji":"๐๏ธ","aliases":["sa"]},{"emoji":"๐ท๏ธ","aliases":["u6708"]},{"emoji":"๐ถ","aliases":["u6709"]},{"emoji":"๐ฏ","aliases":["u6307"]},{"emoji":"๐","aliases":["ideograph_advantage"]},{"emoji":"๐น","aliases":["u5272"]},{"emoji":"๐","aliases":["u7121"]},{"emoji":"๐ฒ","aliases":["u7981"]},{"emoji":"๐","aliases":["accept"]},{"emoji":"๐ธ","aliases":["u7533"]},{"emoji":"๐ด","aliases":["u5408"]},{"emoji":"๐ณ","aliases":["u7a7a"]},{"emoji":"ใ๏ธ","aliases":["congratulations"]},{"emoji":"ใ๏ธ","aliases":["secret"]},{"emoji":"๐บ","aliases":["u55b6"]},{"emoji":"๐ต","aliases":["u6e80"]},{"emoji":"๐ด","aliases":["red_circle"]},{"emoji":"๐ ","aliases":["orange_circle"]},{"emoji":"๐ก","aliases":["yellow_circle"]},{"emoji":"๐ข","aliases":["green_circle"]},{"emoji":"๐ต","aliases":["large_blue_circle"]},{"emoji":"๐ฃ","aliases":["purple_circle"]},{"emoji":"๐ค","aliases":["brown_circle"]},{"emoji":"โซ","aliases":["black_circle"]},{"emoji":"โช","aliases":["white_circle"]},{"emoji":"๐ฅ","aliases":["red_square"]},{"emoji":"๐ง","aliases":["orange_square"]},{"emoji":"๐จ","aliases":["yellow_square"]},{"emoji":"๐ฉ","aliases":["green_square"]},{"emoji":"๐ฆ","aliases":["blue_square"]},{"emoji":"๐ช","aliases":["purple_square"]},{"emoji":"๐ซ","aliases":["brown_square"]},{"emoji":"โฌ","aliases":["black_large_square"]},{"emoji":"โฌ","aliases":["white_large_square"]},{"emoji":"โผ๏ธ","aliases":["black_medium_square"]},{"emoji":"โป๏ธ","aliases":["white_medium_square"]},{"emoji":"โพ","aliases":["black_medium_small_square"]},{"emoji":"โฝ","aliases":["white_medium_small_square"]},{"emoji":"โช๏ธ","aliases":["black_small_square"]},{"emoji":"โซ๏ธ","aliases":["white_small_square"]},{"emoji":"๐ถ","aliases":["large_orange_diamond"]},{"emoji":"๐ท","aliases":["large_blue_diamond"]},{"emoji":"๐ธ","aliases":["small_orange_diamond"]},{"emoji":"๐น","aliases":["small_blue_diamond"]},{"emoji":"๐บ","aliases":["small_red_triangle"]},{"emoji":"๐ป","aliases":["small_red_triangle_down"]},{"emoji":"๐ ","aliases":["diamond_shape_with_a_dot_inside"]},{"emoji":"๐","aliases":["radio_button"]},{"emoji":"๐ณ","aliases":["white_square_button"]},{"emoji":"๐ฒ","aliases":["black_square_button"]},{"emoji":"๐","aliases":["checkered_flag"]},{"emoji":"๐ฉ","aliases":["triangular_flag_on_post"]},{"emoji":"๐","aliases":["crossed_flags"]},{"emoji":"๐ด","aliases":["black_flag"]},{"emoji":"๐ณ๏ธ","aliases":["white_flag"]},{"emoji":"๐ณ๏ธโ๐","aliases":["rainbow_flag"]},{"emoji":"๐ณ๏ธโโง๏ธ","aliases":["transgender_flag"]},{"emoji":"๐ดโโ ๏ธ","aliases":["pirate_flag"]},{"emoji":"๐ฆ๐จ","aliases":["ascension_island"]},{"emoji":"๐ฆ๐ฉ","aliases":["andorra"]},{"emoji":"๐ฆ๐ช","aliases":["united_arab_emirates"]},{"emoji":"๐ฆ๐ซ","aliases":["afghanistan"]},{"emoji":"๐ฆ๐ฌ","aliases":["antigua_barbuda"]},{"emoji":"๐ฆ๐ฎ","aliases":["anguilla"]},{"emoji":"๐ฆ๐ฑ","aliases":["albania"]},{"emoji":"๐ฆ๐ฒ","aliases":["armenia"]},{"emoji":"๐ฆ๐ด","aliases":["angola"]},{"emoji":"๐ฆ๐ถ","aliases":["antarctica"]},{"emoji":"๐ฆ๐ท","aliases":["argentina"]},{"emoji":"๐ฆ๐ธ","aliases":["american_samoa"]},{"emoji":"๐ฆ๐น","aliases":["austria"]},{"emoji":"๐ฆ๐บ","aliases":["australia"]},{"emoji":"๐ฆ๐ผ","aliases":["aruba"]},{"emoji":"๐ฆ๐ฝ","aliases":["aland_islands"]},{"emoji":"๐ฆ๐ฟ","aliases":["azerbaijan"]},{"emoji":"๐ง๐ฆ","aliases":["bosnia_herzegovina"]},{"emoji":"๐ง๐ง","aliases":["barbados"]},{"emoji":"๐ง๐ฉ","aliases":["bangladesh"]},{"emoji":"๐ง๐ช","aliases":["belgium"]},{"emoji":"๐ง๐ซ","aliases":["burkina_faso"]},{"emoji":"๐ง๐ฌ","aliases":["bulgaria"]},{"emoji":"๐ง๐ญ","aliases":["bahrain"]},{"emoji":"๐ง๐ฎ","aliases":["burundi"]},{"emoji":"๐ง๐ฏ","aliases":["benin"]},{"emoji":"๐ง๐ฑ","aliases":["st_barthelemy"]},{"emoji":"๐ง๐ฒ","aliases":["bermuda"]},{"emoji":"๐ง๐ณ","aliases":["brunei"]},{"emoji":"๐ง๐ด","aliases":["bolivia"]},{"emoji":"๐ง๐ถ","aliases":["caribbean_netherlands"]},{"emoji":"๐ง๐ท","aliases":["brazil"]},{"emoji":"๐ง๐ธ","aliases":["bahamas"]},{"emoji":"๐ง๐น","aliases":["bhutan"]},{"emoji":"๐ง๐ป","aliases":["bouvet_island"]},{"emoji":"๐ง๐ผ","aliases":["botswana"]},{"emoji":"๐ง๐พ","aliases":["belarus"]},{"emoji":"๐ง๐ฟ","aliases":["belize"]},{"emoji":"๐จ๐ฆ","aliases":["canada"]},{"emoji":"๐จ๐จ","aliases":["cocos_islands"]},{"emoji":"๐จ๐ฉ","aliases":["congo_kinshasa"]},{"emoji":"๐จ๐ซ","aliases":["central_african_republic"]},{"emoji":"๐จ๐ฌ","aliases":["congo_brazzaville"]},{"emoji":"๐จ๐ญ","aliases":["switzerland"]},{"emoji":"๐จ๐ฎ","aliases":["cote_divoire"]},{"emoji":"๐จ๐ฐ","aliases":["cook_islands"]},{"emoji":"๐จ๐ฑ","aliases":["chile"]},{"emoji":"๐จ๐ฒ","aliases":["cameroon"]},{"emoji":"๐จ๐ณ","aliases":["cn"]},{"emoji":"๐จ๐ด","aliases":["colombia"]},{"emoji":"๐จ๐ต","aliases":["clipperton_island"]},{"emoji":"๐จ๐ท","aliases":["costa_rica"]},{"emoji":"๐จ๐บ","aliases":["cuba"]},{"emoji":"๐จ๐ป","aliases":["cape_verde"]},{"emoji":"๐จ๐ผ","aliases":["curacao"]},{"emoji":"๐จ๐ฝ","aliases":["christmas_island"]},{"emoji":"๐จ๐พ","aliases":["cyprus"]},{"emoji":"๐จ๐ฟ","aliases":["czech_republic"]},{"emoji":"๐ฉ๐ช","aliases":["de"]},{"emoji":"๐ฉ๐ฌ","aliases":["diego_garcia"]},{"emoji":"๐ฉ๐ฏ","aliases":["djibouti"]},{"emoji":"๐ฉ๐ฐ","aliases":["denmark"]},{"emoji":"๐ฉ๐ฒ","aliases":["dominica"]},{"emoji":"๐ฉ๐ด","aliases":["dominican_republic"]},{"emoji":"๐ฉ๐ฟ","aliases":["algeria"]},{"emoji":"๐ช๐ฆ","aliases":["ceuta_melilla"]},{"emoji":"๐ช๐จ","aliases":["ecuador"]},{"emoji":"๐ช๐ช","aliases":["estonia"]},{"emoji":"๐ช๐ฌ","aliases":["egypt"]},{"emoji":"๐ช๐ญ","aliases":["western_sahara"]},{"emoji":"๐ช๐ท","aliases":["eritrea"]},{"emoji":"๐ช๐ธ","aliases":["es"]},{"emoji":"๐ช๐น","aliases":["ethiopia"]},{"emoji":"๐ช๐บ","aliases":["eu","european_union"]},{"emoji":"๐ซ๐ฎ","aliases":["finland"]},{"emoji":"๐ซ๐ฏ","aliases":["fiji"]},{"emoji":"๐ซ๐ฐ","aliases":["falkland_islands"]},{"emoji":"๐ซ๐ฒ","aliases":["micronesia"]},{"emoji":"๐ซ๐ด","aliases":["faroe_islands"]},{"emoji":"๐ซ๐ท","aliases":["fr"]},{"emoji":"๐ฌ๐ฆ","aliases":["gabon"]},{"emoji":"๐ฌ๐ง","aliases":["gb","uk"]},{"emoji":"๐ฌ๐ฉ","aliases":["grenada"]},{"emoji":"๐ฌ๐ช","aliases":["georgia"]},{"emoji":"๐ฌ๐ซ","aliases":["french_guiana"]},{"emoji":"๐ฌ๐ฌ","aliases":["guernsey"]},{"emoji":"๐ฌ๐ญ","aliases":["ghana"]},{"emoji":"๐ฌ๐ฎ","aliases":["gibraltar"]},{"emoji":"๐ฌ๐ฑ","aliases":["greenland"]},{"emoji":"๐ฌ๐ฒ","aliases":["gambia"]},{"emoji":"๐ฌ๐ณ","aliases":["guinea"]},{"emoji":"๐ฌ๐ต","aliases":["guadeloupe"]},{"emoji":"๐ฌ๐ถ","aliases":["equatorial_guinea"]},{"emoji":"๐ฌ๐ท","aliases":["greece"]},{"emoji":"๐ฌ๐ธ","aliases":["south_georgia_south_sandwich_islands"]},{"emoji":"๐ฌ๐น","aliases":["guatemala"]},{"emoji":"๐ฌ๐บ","aliases":["guam"]},{"emoji":"๐ฌ๐ผ","aliases":["guinea_bissau"]},{"emoji":"๐ฌ๐พ","aliases":["guyana"]},{"emoji":"๐ญ๐ฐ","aliases":["hong_kong"]},{"emoji":"๐ญ๐ฒ","aliases":["heard_mcdonald_islands"]},{"emoji":"๐ญ๐ณ","aliases":["honduras"]},{"emoji":"๐ญ๐ท","aliases":["croatia"]},{"emoji":"๐ญ๐น","aliases":["haiti"]},{"emoji":"๐ญ๐บ","aliases":["hungary"]},{"emoji":"๐ฎ๐จ","aliases":["canary_islands"]},{"emoji":"๐ฎ๐ฉ","aliases":["indonesia"]},{"emoji":"๐ฎ๐ช","aliases":["ireland"]},{"emoji":"๐ฎ๐ฑ","aliases":["israel"]},{"emoji":"๐ฎ๐ฒ","aliases":["isle_of_man"]},{"emoji":"๐ฎ๐ณ","aliases":["india"]},{"emoji":"๐ฎ๐ด","aliases":["british_indian_ocean_territory"]},{"emoji":"๐ฎ๐ถ","aliases":["iraq"]},{"emoji":"๐ฎ๐ท","aliases":["iran"]},{"emoji":"๐ฎ๐ธ","aliases":["iceland"]},{"emoji":"๐ฎ๐น","aliases":["it"]},{"emoji":"๐ฏ๐ช","aliases":["jersey"]},{"emoji":"๐ฏ๐ฒ","aliases":["jamaica"]},{"emoji":"๐ฏ๐ด","aliases":["jordan"]},{"emoji":"๐ฏ๐ต","aliases":["jp"]},{"emoji":"๐ฐ๐ช","aliases":["kenya"]},{"emoji":"๐ฐ๐ฌ","aliases":["kyrgyzstan"]},{"emoji":"๐ฐ๐ญ","aliases":["cambodia"]},{"emoji":"๐ฐ๐ฎ","aliases":["kiribati"]},{"emoji":"๐ฐ๐ฒ","aliases":["comoros"]},{"emoji":"๐ฐ๐ณ","aliases":["st_kitts_nevis"]},{"emoji":"๐ฐ๐ต","aliases":["north_korea"]},{"emoji":"๐ฐ๐ท","aliases":["kr"]},{"emoji":"๐ฐ๐ผ","aliases":["kuwait"]},{"emoji":"๐ฐ๐พ","aliases":["cayman_islands"]},{"emoji":"๐ฐ๐ฟ","aliases":["kazakhstan"]},{"emoji":"๐ฑ๐ฆ","aliases":["laos"]},{"emoji":"๐ฑ๐ง","aliases":["lebanon"]},{"emoji":"๐ฑ๐จ","aliases":["st_lucia"]},{"emoji":"๐ฑ๐ฎ","aliases":["liechtenstein"]},{"emoji":"๐ฑ๐ฐ","aliases":["sri_lanka"]},{"emoji":"๐ฑ๐ท","aliases":["liberia"]},{"emoji":"๐ฑ๐ธ","aliases":["lesotho"]},{"emoji":"๐ฑ๐น","aliases":["lithuania"]},{"emoji":"๐ฑ๐บ","aliases":["luxembourg"]},{"emoji":"๐ฑ๐ป","aliases":["latvia"]},{"emoji":"๐ฑ๐พ","aliases":["libya"]},{"emoji":"๐ฒ๐ฆ","aliases":["morocco"]},{"emoji":"๐ฒ๐จ","aliases":["monaco"]},{"emoji":"๐ฒ๐ฉ","aliases":["moldova"]},{"emoji":"๐ฒ๐ช","aliases":["montenegro"]},{"emoji":"๐ฒ๐ซ","aliases":["st_martin"]},{"emoji":"๐ฒ๐ฌ","aliases":["madagascar"]},{"emoji":"๐ฒ๐ญ","aliases":["marshall_islands"]},{"emoji":"๐ฒ๐ฐ","aliases":["macedonia"]},{"emoji":"๐ฒ๐ฑ","aliases":["mali"]},{"emoji":"๐ฒ๐ฒ","aliases":["myanmar"]},{"emoji":"๐ฒ๐ณ","aliases":["mongolia"]},{"emoji":"๐ฒ๐ด","aliases":["macau"]},{"emoji":"๐ฒ๐ต","aliases":["northern_mariana_islands"]},{"emoji":"๐ฒ๐ถ","aliases":["martinique"]},{"emoji":"๐ฒ๐ท","aliases":["mauritania"]},{"emoji":"๐ฒ๐ธ","aliases":["montserrat"]},{"emoji":"๐ฒ๐น","aliases":["malta"]},{"emoji":"๐ฒ๐บ","aliases":["mauritius"]},{"emoji":"๐ฒ๐ป","aliases":["maldives"]},{"emoji":"๐ฒ๐ผ","aliases":["malawi"]},{"emoji":"๐ฒ๐ฝ","aliases":["mexico"]},{"emoji":"๐ฒ๐พ","aliases":["malaysia"]},{"emoji":"๐ฒ๐ฟ","aliases":["mozambique"]},{"emoji":"๐ณ๐ฆ","aliases":["namibia"]},{"emoji":"๐ณ๐จ","aliases":["new_caledonia"]},{"emoji":"๐ณ๐ช","aliases":["niger"]},{"emoji":"๐ณ๐ซ","aliases":["norfolk_island"]},{"emoji":"๐ณ๐ฌ","aliases":["nigeria"]},{"emoji":"๐ณ๐ฎ","aliases":["nicaragua"]},{"emoji":"๐ณ๐ฑ","aliases":["netherlands"]},{"emoji":"๐ณ๐ด","aliases":["norway"]},{"emoji":"๐ณ๐ต","aliases":["nepal"]},{"emoji":"๐ณ๐ท","aliases":["nauru"]},{"emoji":"๐ณ๐บ","aliases":["niue"]},{"emoji":"๐ณ๐ฟ","aliases":["new_zealand"]},{"emoji":"๐ด๐ฒ","aliases":["oman"]},{"emoji":"๐ต๐ฆ","aliases":["panama"]},{"emoji":"๐ต๐ช","aliases":["peru"]},{"emoji":"๐ต๐ซ","aliases":["french_polynesia"]},{"emoji":"๐ต๐ฌ","aliases":["papua_new_guinea"]},{"emoji":"๐ต๐ญ","aliases":["philippines"]},{"emoji":"๐ต๐ฐ","aliases":["pakistan"]},{"emoji":"๐ต๐ฑ","aliases":["poland"]},{"emoji":"๐ต๐ฒ","aliases":["st_pierre_miquelon"]},{"emoji":"๐ต๐ณ","aliases":["pitcairn_islands"]},{"emoji":"๐ต๐ท","aliases":["puerto_rico"]},{"emoji":"๐ต๐ธ","aliases":["palestinian_territories"]},{"emoji":"๐ต๐น","aliases":["portugal"]},{"emoji":"๐ต๐ผ","aliases":["palau"]},{"emoji":"๐ต๐พ","aliases":["paraguay"]},{"emoji":"๐ถ๐ฆ","aliases":["qatar"]},{"emoji":"๐ท๐ช","aliases":["reunion"]},{"emoji":"๐ท๐ด","aliases":["romania"]},{"emoji":"๐ท๐ธ","aliases":["serbia"]},{"emoji":"๐ท๐บ","aliases":["ru"]},{"emoji":"๐ท๐ผ","aliases":["rwanda"]},{"emoji":"๐ธ๐ฆ","aliases":["saudi_arabia"]},{"emoji":"๐ธ๐ง","aliases":["solomon_islands"]},{"emoji":"๐ธ๐จ","aliases":["seychelles"]},{"emoji":"๐ธ๐ฉ","aliases":["sudan"]},{"emoji":"๐ธ๐ช","aliases":["sweden"]},{"emoji":"๐ธ๐ฌ","aliases":["singapore"]},{"emoji":"๐ธ๐ญ","aliases":["st_helena"]},{"emoji":"๐ธ๐ฎ","aliases":["slovenia"]},{"emoji":"๐ธ๐ฏ","aliases":["svalbard_jan_mayen"]},{"emoji":"๐ธ๐ฐ","aliases":["slovakia"]},{"emoji":"๐ธ๐ฑ","aliases":["sierra_leone"]},{"emoji":"๐ธ๐ฒ","aliases":["san_marino"]},{"emoji":"๐ธ๐ณ","aliases":["senegal"]},{"emoji":"๐ธ๐ด","aliases":["somalia"]},{"emoji":"๐ธ๐ท","aliases":["suriname"]},{"emoji":"๐ธ๐ธ","aliases":["south_sudan"]},{"emoji":"๐ธ๐น","aliases":["sao_tome_principe"]},{"emoji":"๐ธ๐ป","aliases":["el_salvador"]},{"emoji":"๐ธ๐ฝ","aliases":["sint_maarten"]},{"emoji":"๐ธ๐พ","aliases":["syria"]},{"emoji":"๐ธ๐ฟ","aliases":["swaziland"]},{"emoji":"๐น๐ฆ","aliases":["tristan_da_cunha"]},{"emoji":"๐น๐จ","aliases":["turks_caicos_islands"]},{"emoji":"๐น๐ฉ","aliases":["chad"]},{"emoji":"๐น๐ซ","aliases":["french_southern_territories"]},{"emoji":"๐น๐ฌ","aliases":["togo"]},{"emoji":"๐น๐ญ","aliases":["thailand"]},{"emoji":"๐น๐ฏ","aliases":["tajikistan"]},{"emoji":"๐น๐ฐ","aliases":["tokelau"]},{"emoji":"๐น๐ฑ","aliases":["timor_leste"]},{"emoji":"๐น๐ฒ","aliases":["turkmenistan"]},{"emoji":"๐น๐ณ","aliases":["tunisia"]},{"emoji":"๐น๐ด","aliases":["tonga"]},{"emoji":"๐น๐ท","aliases":["tr"]},{"emoji":"๐น๐น","aliases":["trinidad_tobago"]},{"emoji":"๐น๐ป","aliases":["tuvalu"]},{"emoji":"๐น๐ผ","aliases":["taiwan"]},{"emoji":"๐น๐ฟ","aliases":["tanzania"]},{"emoji":"๐บ๐ฆ","aliases":["ukraine"]},{"emoji":"๐บ๐ฌ","aliases":["uganda"]},{"emoji":"๐บ๐ฒ","aliases":["us_outlying_islands"]},{"emoji":"๐บ๐ณ","aliases":["united_nations"]},{"emoji":"๐บ๐ธ","aliases":["us"]},{"emoji":"๐บ๐พ","aliases":["uruguay"]},{"emoji":"๐บ๐ฟ","aliases":["uzbekistan"]},{"emoji":"๐ป๐ฆ","aliases":["vatican_city"]},{"emoji":"๐ป๐จ","aliases":["st_vincent_grenadines"]},{"emoji":"๐ป๐ช","aliases":["venezuela"]},{"emoji":"๐ป๐ฌ","aliases":["british_virgin_islands"]},{"emoji":"๐ป๐ฎ","aliases":["us_virgin_islands"]},{"emoji":"๐ป๐ณ","aliases":["vietnam"]},{"emoji":"๐ป๐บ","aliases":["vanuatu"]},{"emoji":"๐ผ๐ซ","aliases":["wallis_futuna"]},{"emoji":"๐ผ๐ธ","aliases":["samoa"]},{"emoji":"๐ฝ๐ฐ","aliases":["kosovo"]},{"emoji":"๐พ๐ช","aliases":["yemen"]},{"emoji":"๐พ๐น","aliases":["mayotte"]},{"emoji":"๐ฟ๐ฆ","aliases":["south_africa"]},{"emoji":"๐ฟ๐ฒ","aliases":["zambia"]},{"emoji":"๐ฟ๐ผ","aliases":["zimbabwe"]},{"emoji":"๐ด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ","aliases":["england"]},{"emoji":"๐ด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ","aliases":["scotland"]},{"emoji":"๐ด๓ ง๓ ข๓ ท๓ ฌ๓ ณ๓ ฟ","aliases":["wales"]}] diff --git a/server/mailer_emoji_map.json b/server/mailer_emoji_map.json new file mode 100644 index 00000000..8520c24c --- /dev/null +++ b/server/mailer_emoji_map.json @@ -0,0 +1,1857 @@ +{ + "+1": "๐", + "-1": "๐", + "100": "๐ฏ", + "1234": "๐ข", + "1st_place_medal": "๐ฅ", + "2nd_place_medal": "๐ฅ", + "3rd_place_medal": "๐ฅ", + "8ball": "๐ฑ", + "a": "๐ ฐ๏ธ", + "ab": "๐", + "abacus": "๐งฎ", + "abc": "๐ค", + "abcd": "๐ก", + "accept": "๐", + "accordion": "๐ช", + "adhesive_bandage": "๐ฉน", + "adult": "๐ง", + "aerial_tramway": "๐ก", + "afghanistan": "๐ฆ๐ซ", + "airplane": "โ๏ธ", + "aland_islands": "๐ฆ๐ฝ", + "alarm_clock": "โฐ", + "albania": "๐ฆ๐ฑ", + "alembic": "โ๏ธ", + "algeria": "๐ฉ๐ฟ", + "alien": "๐ฝ", + "ambulance": "๐", + "american_samoa": "๐ฆ๐ธ", + "amphora": "๐บ", + "anatomical_heart": "๐ซ", + "anchor": "โ", + "andorra": "๐ฆ๐ฉ", + "angel": "๐ผ", + "anger": "๐ข", + "angola": "๐ฆ๐ด", + "angry": "๐ ", + "anguilla": "๐ฆ๐ฎ", + "anguished": "๐ง", + "ant": "๐", + "antarctica": "๐ฆ๐ถ", + "antigua_barbuda": "๐ฆ๐ฌ", + "apple": "๐", + "aquarius": "โ", + "argentina": "๐ฆ๐ท", + "aries": "โ", + "armenia": "๐ฆ๐ฒ", + "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": "๐", + "artificial_satellite": "๐ฐ๏ธ", + "artist": "๐งโ๐จ", + "aruba": "๐ฆ๐ผ", + "ascension_island": "๐ฆ๐จ", + "asterisk": "*๏ธโฃ", + "astonished": "๐ฒ", + "astronaut": "๐งโ๐", + "athletic_shoe": "๐", + "atm": "๐ง", + "atom_symbol": "โ๏ธ", + "australia": "๐ฆ๐บ", + "austria": "๐ฆ๐น", + "auto_rickshaw": "๐บ", + "avocado": "๐ฅ", + "axe": "๐ช", + "azerbaijan": "๐ฆ๐ฟ", + "b": "๐ ฑ๏ธ", + "baby": "๐ถ", + "baby_bottle": "๐ผ", + "baby_chick": "๐ค", + "baby_symbol": "๐ผ", + "back": "๐", + "bacon": "๐ฅ", + "badger": "๐ฆก", + "badminton": "๐ธ", + "bagel": "๐ฅฏ", + "baggage_claim": "๐", + "baguette_bread": "๐ฅ", + "bahamas": "๐ง๐ธ", + "bahrain": "๐ง๐ญ", + "balance_scale": "โ๏ธ", + "bald_man": "๐จโ๐ฆฒ", + "bald_woman": "๐ฉโ๐ฆฒ", + "ballet_shoes": "๐ฉฐ", + "balloon": "๐", + "ballot_box": "๐ณ๏ธ", + "ballot_box_with_check": "โ๏ธ", + "bamboo": "๐", + "banana": "๐", + "bangbang": "โผ๏ธ", + "bangladesh": "๐ง๐ฉ", + "banjo": "๐ช", + "bank": "๐ฆ", + "bar_chart": "๐", + "barbados": "๐ง๐ง", + "barber": "๐", + "baseball": "โพ", + "basket": "๐งบ", + "basketball": "๐", + "basketball_man": "โน๏ธโโ๏ธ", + "basketball_woman": "โน๏ธโโ๏ธ", + "bat": "๐ฆ", + "bath": "๐", + "bathtub": "๐", + "battery": "๐", + "beach_umbrella": "๐๏ธ", + "bear": "๐ป", + "bearded_person": "๐ง", + "beaver": "๐ฆซ", + "bed": "๐๏ธ", + "bee": "๐", + "beer": "๐บ", + "beers": "๐ป", + "beetle": "๐ชฒ", + "beginner": "๐ฐ", + "belarus": "๐ง๐พ", + "belgium": "๐ง๐ช", + "belize": "๐ง๐ฟ", + "bell": "๐", + "bell_pepper": "๐ซ", + "bellhop_bell": "๐๏ธ", + "benin": "๐ง๐ฏ", + "bento": "๐ฑ", + "bermuda": "๐ง๐ฒ", + "beverage_box": "๐ง", + "bhutan": "๐ง๐น", + "bicyclist": "๐ด", + "bike": "๐ฒ", + "biking_man": "๐ดโโ๏ธ", + "biking_woman": "๐ดโโ๏ธ", + "bikini": "๐", + "billed_cap": "๐งข", + "biohazard": "โฃ๏ธ", + "bird": "๐ฆ", + "birthday": "๐", + "bison": "๐ฆฌ", + "black_cat": "๐โโฌ", + "black_circle": "โซ", + "black_flag": "๐ด", + "black_heart": "๐ค", + "black_joker": "๐", + "black_large_square": "โฌ", + "black_medium_small_square": "โพ", + "black_medium_square": "โผ๏ธ", + "black_nib": "โ๏ธ", + "black_small_square": "โช๏ธ", + "black_square_button": "๐ฒ", + "blond_haired_man": "๐ฑโโ๏ธ", + "blond_haired_person": "๐ฑ", + "blond_haired_woman": "๐ฑโโ๏ธ", + "blonde_woman": "๐ฑโโ๏ธ", + "blossom": "๐ผ", + "blowfish": "๐ก", + "blue_book": "๐", + "blue_car": "๐", + "blue_heart": "๐", + "blue_square": "๐ฆ", + "blueberries": "๐ซ", + "blush": "๐", + "boar": "๐", + "boat": "โต", + "bolivia": "๐ง๐ด", + "bomb": "๐ฃ", + "bone": "๐ฆด", + "book": "๐", + "bookmark": "๐", + "bookmark_tabs": "๐", + "books": "๐", + "boom": "๐ฅ", + "boomerang": "๐ช", + "boot": "๐ข", + "bosnia_herzegovina": "๐ง๐ฆ", + "botswana": "๐ง๐ผ", + "bouncing_ball_man": "โน๏ธโโ๏ธ", + "bouncing_ball_person": "โน๏ธ", + "bouncing_ball_woman": "โน๏ธโโ๏ธ", + "bouquet": "๐", + "bouvet_island": "๐ง๐ป", + "bow": "๐", + "bow_and_arrow": "๐น", + "bowing_man": "๐โโ๏ธ", + "bowing_woman": "๐โโ๏ธ", + "bowl_with_spoon": "๐ฅฃ", + "bowling": "๐ณ", + "boxing_glove": "๐ฅ", + "boy": "๐ฆ", + "brain": "๐ง ", + "brazil": "๐ง๐ท", + "bread": "๐", + "breast_feeding": "๐คฑ", + "bricks": "๐งฑ", + "bride_with_veil": "๐ฐโโ๏ธ", + "bridge_at_night": "๐", + "briefcase": "๐ผ", + "british_indian_ocean_territory": "๐ฎ๐ด", + "british_virgin_islands": "๐ป๐ฌ", + "broccoli": "๐ฅฆ", + "broken_heart": "๐", + "broom": "๐งน", + "brown_circle": "๐ค", + "brown_heart": "๐ค", + "brown_square": "๐ซ", + "brunei": "๐ง๐ณ", + "bubble_tea": "๐ง", + "bucket": "๐ชฃ", + "bug": "๐", + "building_construction": "๐๏ธ", + "bulb": "๐ก", + "bulgaria": "๐ง๐ฌ", + "bullettrain_front": "๐ ", + "bullettrain_side": "๐", + "burkina_faso": "๐ง๐ซ", + "burrito": "๐ฏ", + "burundi": "๐ง๐ฎ", + "bus": "๐", + "business_suit_levitating": "๐ด๏ธ", + "busstop": "๐", + "bust_in_silhouette": "๐ค", + "busts_in_silhouette": "๐ฅ", + "butter": "๐ง", + "butterfly": "๐ฆ", + "cactus": "๐ต", + "cake": "๐ฐ", + "calendar": "๐", + "call_me_hand": "๐ค", + "calling": "๐ฒ", + "cambodia": "๐ฐ๐ญ", + "camel": "๐ซ", + "camera": "๐ท", + "camera_flash": "๐ธ", + "cameroon": "๐จ๐ฒ", + "camping": "๐๏ธ", + "canada": "๐จ๐ฆ", + "canary_islands": "๐ฎ๐จ", + "cancer": "โ", + "candle": "๐ฏ๏ธ", + "candy": "๐ฌ", + "canned_food": "๐ฅซ", + "canoe": "๐ถ", + "cape_verde": "๐จ๐ป", + "capital_abcd": "๐ ", + "capricorn": "โ", + "car": "๐", + "card_file_box": "๐๏ธ", + "card_index": "๐", + "card_index_dividers": "๐๏ธ", + "caribbean_netherlands": "๐ง๐ถ", + "carousel_horse": "๐ ", + "carpentry_saw": "๐ช", + "carrot": "๐ฅ", + "cartwheeling": "๐คธ", + "cat": "๐ฑ", + "cat2": "๐", + "cayman_islands": "๐ฐ๐พ", + "cd": "๐ฟ", + "central_african_republic": "๐จ๐ซ", + "ceuta_melilla": "๐ช๐ฆ", + "chad": "๐น๐ฉ", + "chains": "โ๏ธ", + "chair": "๐ช", + "champagne": "๐พ", + "chart": "๐น", + "chart_with_downwards_trend": "๐", + "chart_with_upwards_trend": "๐", + "checkered_flag": "๐", + "cheese": "๐ง", + "cherries": "๐", + "cherry_blossom": "๐ธ", + "chess_pawn": "โ๏ธ", + "chestnut": "๐ฐ", + "chicken": "๐", + "child": "๐ง", + "children_crossing": "๐ธ", + "chile": "๐จ๐ฑ", + "chipmunk": "๐ฟ๏ธ", + "chocolate_bar": "๐ซ", + "chopsticks": "๐ฅข", + "christmas_island": "๐จ๐ฝ", + "christmas_tree": "๐", + "church": "โช", + "cinema": "๐ฆ", + "circus_tent": "๐ช", + "city_sunrise": "๐", + "city_sunset": "๐", + "cityscape": "๐๏ธ", + "cl": "๐", + "clamp": "๐๏ธ", + "clap": "๐", + "clapper": "๐ฌ", + "classical_building": "๐๏ธ", + "climbing": "๐ง", + "climbing_man": "๐งโโ๏ธ", + "climbing_woman": "๐งโโ๏ธ", + "clinking_glasses": "๐ฅ", + "clipboard": "๐", + "clipperton_island": "๐จ๐ต", + "clock1": "๐", + "clock10": "๐", + "clock1030": "๐ฅ", + "clock11": "๐", + "clock1130": "๐ฆ", + "clock12": "๐", + "clock1230": "๐ง", + "clock130": "๐", + "clock2": "๐", + "clock230": "๐", + "clock3": "๐", + "clock330": "๐", + "clock4": "๐", + "clock430": "๐", + "clock5": "๐", + "clock530": "๐ ", + "clock6": "๐", + "clock630": "๐ก", + "clock7": "๐", + "clock730": "๐ข", + "clock8": "๐", + "clock830": "๐ฃ", + "clock9": "๐", + "clock930": "๐ค", + "closed_book": "๐", + "closed_lock_with_key": "๐", + "closed_umbrella": "๐", + "cloud": "โ๏ธ", + "cloud_with_lightning": "๐ฉ๏ธ", + "cloud_with_lightning_and_rain": "โ๏ธ", + "cloud_with_rain": "๐ง๏ธ", + "cloud_with_snow": "๐จ๏ธ", + "clown_face": "๐คก", + "clubs": "โฃ๏ธ", + "cn": "๐จ๐ณ", + "coat": "๐งฅ", + "cockroach": "๐ชณ", + "cocktail": "๐ธ", + "coconut": "๐ฅฅ", + "cocos_islands": "๐จ๐จ", + "coffee": "โ", + "coffin": "โฐ๏ธ", + "coin": "๐ช", + "cold_face": "๐ฅถ", + "cold_sweat": "๐ฐ", + "collision": "๐ฅ", + "colombia": "๐จ๐ด", + "comet": "โ๏ธ", + "comoros": "๐ฐ๐ฒ", + "compass": "๐งญ", + "computer": "๐ป", + "computer_mouse": "๐ฑ๏ธ", + "confetti_ball": "๐", + "confounded": "๐", + "confused": "๐", + "congo_brazzaville": "๐จ๐ฌ", + "congo_kinshasa": "๐จ๐ฉ", + "congratulations": "ใ๏ธ", + "construction": "๐ง", + "construction_worker": "๐ท", + "construction_worker_man": "๐ทโโ๏ธ", + "construction_worker_woman": "๐ทโโ๏ธ", + "control_knobs": "๐๏ธ", + "convenience_store": "๐ช", + "cook": "๐งโ๐ณ", + "cook_islands": "๐จ๐ฐ", + "cookie": "๐ช", + "cool": "๐", + "cop": "๐ฎ", + "copyright": "ยฉ๏ธ", + "corn": "๐ฝ", + "costa_rica": "๐จ๐ท", + "cote_divoire": "๐จ๐ฎ", + "couch_and_lamp": "๐๏ธ", + "couple": "๐ซ", + "couple_with_heart": "๐", + "couple_with_heart_man_man": "๐จโโค๏ธโ๐จ", + "couple_with_heart_woman_man": "๐ฉโโค๏ธโ๐จ", + "couple_with_heart_woman_woman": "๐ฉโโค๏ธโ๐ฉ", + "couplekiss": "๐", + "couplekiss_man_man": "๐จโโค๏ธโ๐โ๐จ", + "couplekiss_man_woman": "๐ฉโโค๏ธโ๐โ๐จ", + "couplekiss_woman_woman": "๐ฉโโค๏ธโ๐โ๐ฉ", + "cow": "๐ฎ", + "cow2": "๐", + "cowboy_hat_face": "๐ค ", + "crab": "๐ฆ", + "crayon": "๐๏ธ", + "credit_card": "๐ณ", + "crescent_moon": "๐", + "cricket": "๐ฆ", + "cricket_game": "๐", + "croatia": "๐ญ๐ท", + "crocodile": "๐", + "croissant": "๐ฅ", + "crossed_fingers": "๐ค", + "crossed_flags": "๐", + "crossed_swords": "โ๏ธ", + "crown": "๐", + "cry": "๐ข", + "crying_cat_face": "๐ฟ", + "crystal_ball": "๐ฎ", + "cuba": "๐จ๐บ", + "cucumber": "๐ฅ", + "cup_with_straw": "๐ฅค", + "cupcake": "๐ง", + "cupid": "๐", + "curacao": "๐จ๐ผ", + "curling_stone": "๐ฅ", + "curly_haired_man": "๐จโ๐ฆฑ", + "curly_haired_woman": "๐ฉโ๐ฆฑ", + "curly_loop": "โฐ", + "currency_exchange": "๐ฑ", + "curry": "๐", + "cursing_face": "๐คฌ", + "custard": "๐ฎ", + "customs": "๐", + "cut_of_meat": "๐ฅฉ", + "cyclone": "๐", + "cyprus": "๐จ๐พ", + "czech_republic": "๐จ๐ฟ", + "dagger": "๐ก๏ธ", + "dancer": "๐", + "dancers": "๐ฏ", + "dancing_men": "๐ฏโโ๏ธ", + "dancing_women": "๐ฏโโ๏ธ", + "dango": "๐ก", + "dark_sunglasses": "๐ถ๏ธ", + "dart": "๐ฏ", + "dash": "๐จ", + "date": "๐ ", + "de": "๐ฉ๐ช", + "deaf_man": "๐งโโ๏ธ", + "deaf_person": "๐ง", + "deaf_woman": "๐งโโ๏ธ", + "deciduous_tree": "๐ณ", + "deer": "๐ฆ", + "denmark": "๐ฉ๐ฐ", + "department_store": "๐ฌ", + "derelict_house": "๐๏ธ", + "desert": "๐๏ธ", + "desert_island": "๐๏ธ", + "desktop_computer": "๐ฅ๏ธ", + "detective": "๐ต๏ธ", + "diamond_shape_with_a_dot_inside": "๐ ", + "diamonds": "โฆ๏ธ", + "diego_garcia": "๐ฉ๐ฌ", + "disappointed": "๐", + "disappointed_relieved": "๐ฅ", + "disguised_face": "๐ฅธ", + "diving_mask": "๐คฟ", + "diya_lamp": "๐ช", + "dizzy": "๐ซ", + "dizzy_face": "๐ต", + "djibouti": "๐ฉ๐ฏ", + "dna": "๐งฌ", + "do_not_litter": "๐ฏ", + "dodo": "๐ฆค", + "dog": "๐ถ", + "dog2": "๐", + "dollar": "๐ต", + "dolls": "๐", + "dolphin": "๐ฌ", + "dominica": "๐ฉ๐ฒ", + "dominican_republic": "๐ฉ๐ด", + "door": "๐ช", + "doughnut": "๐ฉ", + "dove": "๐๏ธ", + "dragon": "๐", + "dragon_face": "๐ฒ", + "dress": "๐", + "dromedary_camel": "๐ช", + "drooling_face": "๐คค", + "drop_of_blood": "๐ฉธ", + "droplet": "๐ง", + "drum": "๐ฅ", + "duck": "๐ฆ", + "dumpling": "๐ฅ", + "dvd": "๐", + "e-mail": "๐ง", + "eagle": "๐ฆ ", + "ear": "๐", + "ear_of_rice": "๐พ", + "ear_with_hearing_aid": "๐ฆป", + "earth_africa": "๐", + "earth_americas": "๐", + "earth_asia": "๐", + "ecuador": "๐ช๐จ", + "egg": "๐ฅ", + "eggplant": "๐", + "egypt": "๐ช๐ฌ", + "eight": "8๏ธโฃ", + "eight_pointed_black_star": "โด๏ธ", + "eight_spoked_asterisk": "โณ๏ธ", + "eject_button": "โ๏ธ", + "el_salvador": "๐ธ๐ป", + "electric_plug": "๐", + "elephant": "๐", + "elevator": "๐", + "elf": "๐ง", + "elf_man": "๐งโโ๏ธ", + "elf_woman": "๐งโโ๏ธ", + "email": "๐ง", + "end": "๐", + "england": "๐ด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ", + "envelope": "โ๏ธ", + "envelope_with_arrow": "๐ฉ", + "equatorial_guinea": "๐ฌ๐ถ", + "eritrea": "๐ช๐ท", + "es": "๐ช๐ธ", + "estonia": "๐ช๐ช", + "ethiopia": "๐ช๐น", + "eu": "๐ช๐บ", + "euro": "๐ถ", + "european_castle": "๐ฐ", + "european_post_office": "๐ค", + "european_union": "๐ช๐บ", + "evergreen_tree": "๐ฒ", + "exclamation": "โ", + "exploding_head": "๐คฏ", + "expressionless": "๐", + "eye": "๐๏ธ", + "eye_speech_bubble": "๐๏ธโ๐จ๏ธ", + "eyeglasses": "๐", + "eyes": "๐", + "face_exhaling": "๐ฎโ๐จ", + "face_in_clouds": "๐ถโ๐ซ๏ธ", + "face_with_head_bandage": "๐ค", + "face_with_spiral_eyes": "๐ตโ๐ซ", + "face_with_thermometer": "๐ค", + "facepalm": "๐คฆ", + "facepunch": "๐", + "factory": "๐ญ", + "factory_worker": "๐งโ๐ญ", + "fairy": "๐ง", + "fairy_man": "๐งโโ๏ธ", + "fairy_woman": "๐งโโ๏ธ", + "falafel": "๐ง", + "falkland_islands": "๐ซ๐ฐ", + "fallen_leaf": "๐", + "family": "๐ช", + "family_man_boy": "๐จโ๐ฆ", + "family_man_boy_boy": "๐จโ๐ฆโ๐ฆ", + "family_man_girl": "๐จโ๐ง", + "family_man_girl_boy": "๐จโ๐งโ๐ฆ", + "family_man_girl_girl": "๐จโ๐งโ๐ง", + "family_man_man_boy": "๐จโ๐จโ๐ฆ", + "family_man_man_boy_boy": "๐จโ๐จโ๐ฆโ๐ฆ", + "family_man_man_girl": "๐จโ๐จโ๐ง", + "family_man_man_girl_boy": "๐จโ๐จโ๐งโ๐ฆ", + "family_man_man_girl_girl": "๐จโ๐จโ๐งโ๐ง", + "family_man_woman_boy": "๐จโ๐ฉโ๐ฆ", + "family_man_woman_boy_boy": "๐จโ๐ฉโ๐ฆโ๐ฆ", + "family_man_woman_girl": "๐จโ๐ฉโ๐ง", + "family_man_woman_girl_boy": "๐จโ๐ฉโ๐งโ๐ฆ", + "family_man_woman_girl_girl": "๐จโ๐ฉโ๐งโ๐ง", + "family_woman_boy": "๐ฉโ๐ฆ", + "family_woman_boy_boy": "๐ฉโ๐ฆโ๐ฆ", + "family_woman_girl": "๐ฉโ๐ง", + "family_woman_girl_boy": "๐ฉโ๐งโ๐ฆ", + "family_woman_girl_girl": "๐ฉโ๐งโ๐ง", + "family_woman_woman_boy": "๐ฉโ๐ฉโ๐ฆ", + "family_woman_woman_boy_boy": "๐ฉโ๐ฉโ๐ฆโ๐ฆ", + "family_woman_woman_girl": "๐ฉโ๐ฉโ๐ง", + "family_woman_woman_girl_boy": "๐ฉโ๐ฉโ๐งโ๐ฆ", + "family_woman_woman_girl_girl": "๐ฉโ๐ฉโ๐งโ๐ง", + "farmer": "๐งโ๐พ", + "faroe_islands": "๐ซ๐ด", + "fast_forward": "โฉ", + "fax": "๐ ", + "fearful": "๐จ", + "feather": "๐ชถ", + "feet": "๐พ", + "female_detective": "๐ต๏ธโโ๏ธ", + "female_sign": "โ๏ธ", + "ferris_wheel": "๐ก", + "ferry": "โด๏ธ", + "field_hockey": "๐", + "fiji": "๐ซ๐ฏ", + "file_cabinet": "๐๏ธ", + "file_folder": "๐", + "film_projector": "๐ฝ๏ธ", + "film_strip": "๐๏ธ", + "finland": "๐ซ๐ฎ", + "fire": "๐ฅ", + "fire_engine": "๐", + "fire_extinguisher": "๐งฏ", + "firecracker": "๐งจ", + "firefighter": "๐งโ๐", + "fireworks": "๐", + "first_quarter_moon": "๐", + "first_quarter_moon_with_face": "๐", + "fish": "๐", + "fish_cake": "๐ฅ", + "fishing_pole_and_fish": "๐ฃ", + "fist": "โ", + "fist_left": "๐ค", + "fist_oncoming": "๐", + "fist_raised": "โ", + "fist_right": "๐ค", + "five": "5๏ธโฃ", + "flags": "๐", + "flamingo": "๐ฆฉ", + "flashlight": "๐ฆ", + "flat_shoe": "๐ฅฟ", + "flatbread": "๐ซ", + "fleur_de_lis": "โ๏ธ", + "flight_arrival": "๐ฌ", + "flight_departure": "๐ซ", + "flipper": "๐ฌ", + "floppy_disk": "๐พ", + "flower_playing_cards": "๐ด", + "flushed": "๐ณ", + "fly": "๐ชฐ", + "flying_disc": "๐ฅ", + "flying_saucer": "๐ธ", + "fog": "๐ซ๏ธ", + "foggy": "๐", + "fondue": "๐ซ", + "foot": "๐ฆถ", + "football": "๐", + "footprints": "๐ฃ", + "fork_and_knife": "๐ด", + "fortune_cookie": "๐ฅ ", + "fountain": "โฒ", + "fountain_pen": "๐๏ธ", + "four": "4๏ธโฃ", + "four_leaf_clover": "๐", + "fox_face": "๐ฆ", + "fr": "๐ซ๐ท", + "framed_picture": "๐ผ๏ธ", + "free": "๐", + "french_guiana": "๐ฌ๐ซ", + "french_polynesia": "๐ต๐ซ", + "french_southern_territories": "๐น๐ซ", + "fried_egg": "๐ณ", + "fried_shrimp": "๐ค", + "fries": "๐", + "frog": "๐ธ", + "frowning": "๐ฆ", + "frowning_face": "โน๏ธ", + "frowning_man": "๐โโ๏ธ", + "frowning_person": "๐", + "frowning_woman": "๐โโ๏ธ", + "fu": "๐", + "fuelpump": "โฝ", + "full_moon": "๐", + "full_moon_with_face": "๐", + "funeral_urn": "โฑ๏ธ", + "gabon": "๐ฌ๐ฆ", + "gambia": "๐ฌ๐ฒ", + "game_die": "๐ฒ", + "garlic": "๐ง", + "gb": "๐ฌ๐ง", + "gear": "โ๏ธ", + "gem": "๐", + "gemini": "โ", + "genie": "๐ง", + "genie_man": "๐งโโ๏ธ", + "genie_woman": "๐งโโ๏ธ", + "georgia": "๐ฌ๐ช", + "ghana": "๐ฌ๐ญ", + "ghost": "๐ป", + "gibraltar": "๐ฌ๐ฎ", + "gift": "๐", + "gift_heart": "๐", + "giraffe": "๐ฆ", + "girl": "๐ง", + "globe_with_meridians": "๐", + "gloves": "๐งค", + "goal_net": "๐ฅ ", + "goat": "๐", + "goggles": "๐ฅฝ", + "golf": "โณ", + "golfing": "๐๏ธ", + "golfing_man": "๐๏ธโโ๏ธ", + "golfing_woman": "๐๏ธโโ๏ธ", + "gorilla": "๐ฆ", + "grapes": "๐", + "greece": "๐ฌ๐ท", + "green_apple": "๐", + "green_book": "๐", + "green_circle": "๐ข", + "green_heart": "๐", + "green_salad": "๐ฅ", + "green_square": "๐ฉ", + "greenland": "๐ฌ๐ฑ", + "grenada": "๐ฌ๐ฉ", + "grey_exclamation": "โ", + "grey_question": "โ", + "grimacing": "๐ฌ", + "grin": "๐", + "grinning": "๐", + "guadeloupe": "๐ฌ๐ต", + "guam": "๐ฌ๐บ", + "guard": "๐", + "guardsman": "๐โโ๏ธ", + "guardswoman": "๐โโ๏ธ", + "guatemala": "๐ฌ๐น", + "guernsey": "๐ฌ๐ฌ", + "guide_dog": "๐ฆฎ", + "guinea": "๐ฌ๐ณ", + "guinea_bissau": "๐ฌ๐ผ", + "guitar": "๐ธ", + "gun": "๐ซ", + "guyana": "๐ฌ๐พ", + "haircut": "๐", + "haircut_man": "๐โโ๏ธ", + "haircut_woman": "๐โโ๏ธ", + "haiti": "๐ญ๐น", + "hamburger": "๐", + "hammer": "๐จ", + "hammer_and_pick": "โ๏ธ", + "hammer_and_wrench": "๐ ๏ธ", + "hamster": "๐น", + "hand": "โ", + "hand_over_mouth": "๐คญ", + "handbag": "๐", + "handball_person": "๐คพ", + "handshake": "๐ค", + "hankey": "๐ฉ", + "hash": "#๏ธโฃ", + "hatched_chick": "๐ฅ", + "hatching_chick": "๐ฃ", + "headphones": "๐ง", + "headstone": "๐ชฆ", + "health_worker": "๐งโโ๏ธ", + "hear_no_evil": "๐", + "heard_mcdonald_islands": "๐ญ๐ฒ", + "heart": "โค๏ธ", + "heart_decoration": "๐", + "heart_eyes": "๐", + "heart_eyes_cat": "๐ป", + "heart_on_fire": "โค๏ธโ๐ฅ", + "heartbeat": "๐", + "heartpulse": "๐", + "hearts": "โฅ๏ธ", + "heavy_check_mark": "โ๏ธ", + "heavy_division_sign": "โ", + "heavy_dollar_sign": "๐ฒ", + "heavy_exclamation_mark": "โ", + "heavy_heart_exclamation": "โฃ๏ธ", + "heavy_minus_sign": "โ", + "heavy_multiplication_x": "โ๏ธ", + "heavy_plus_sign": "โ", + "hedgehog": "๐ฆ", + "helicopter": "๐", + "herb": "๐ฟ", + "hibiscus": "๐บ", + "high_brightness": "๐", + "high_heel": "๐ ", + "hiking_boot": "๐ฅพ", + "hindu_temple": "๐", + "hippopotamus": "๐ฆ", + "hocho": "๐ช", + "hole": "๐ณ๏ธ", + "honduras": "๐ญ๐ณ", + "honey_pot": "๐ฏ", + "honeybee": "๐", + "hong_kong": "๐ญ๐ฐ", + "hook": "๐ช", + "horse": "๐ด", + "horse_racing": "๐", + "hospital": "๐ฅ", + "hot_face": "๐ฅต", + "hot_pepper": "๐ถ๏ธ", + "hotdog": "๐ญ", + "hotel": "๐จ", + "hotsprings": "โจ๏ธ", + "hourglass": "โ", + "hourglass_flowing_sand": "โณ", + "house": "๐ ", + "house_with_garden": "๐ก", + "houses": "๐๏ธ", + "hugs": "๐ค", + "hungary": "๐ญ๐บ", + "hushed": "๐ฏ", + "hut": "๐", + "ice_cream": "๐จ", + "ice_cube": "๐ง", + "ice_hockey": "๐", + "ice_skate": "โธ๏ธ", + "icecream": "๐ฆ", + "iceland": "๐ฎ๐ธ", + "id": "๐", + "ideograph_advantage": "๐", + "imp": "๐ฟ", + "inbox_tray": "๐ฅ", + "incoming_envelope": "๐จ", + "india": "๐ฎ๐ณ", + "indonesia": "๐ฎ๐ฉ", + "infinity": "โพ๏ธ", + "information_desk_person": "๐", + "information_source": "โน๏ธ", + "innocent": "๐", + "interrobang": "โ๏ธ", + "iphone": "๐ฑ", + "iran": "๐ฎ๐ท", + "iraq": "๐ฎ๐ถ", + "ireland": "๐ฎ๐ช", + "isle_of_man": "๐ฎ๐ฒ", + "israel": "๐ฎ๐ฑ", + "it": "๐ฎ๐น", + "izakaya_lantern": "๐ฎ", + "jack_o_lantern": "๐", + "jamaica": "๐ฏ๐ฒ", + "japan": "๐พ", + "japanese_castle": "๐ฏ", + "japanese_goblin": "๐บ", + "japanese_ogre": "๐น", + "jeans": "๐", + "jersey": "๐ฏ๐ช", + "jigsaw": "๐งฉ", + "jordan": "๐ฏ๐ด", + "joy": "๐", + "joy_cat": "๐น", + "joystick": "๐น๏ธ", + "jp": "๐ฏ๐ต", + "judge": "๐งโโ๏ธ", + "juggling_person": "๐คน", + "kaaba": "๐", + "kangaroo": "๐ฆ", + "kazakhstan": "๐ฐ๐ฟ", + "kenya": "๐ฐ๐ช", + "key": "๐", + "keyboard": "โจ๏ธ", + "keycap_ten": "๐", + "kick_scooter": "๐ด", + "kimono": "๐", + "kiribati": "๐ฐ๐ฎ", + "kiss": "๐", + "kissing": "๐", + "kissing_cat": "๐ฝ", + "kissing_closed_eyes": "๐", + "kissing_heart": "๐", + "kissing_smiling_eyes": "๐", + "kite": "๐ช", + "kiwi_fruit": "๐ฅ", + "kneeling_man": "๐งโโ๏ธ", + "kneeling_person": "๐ง", + "kneeling_woman": "๐งโโ๏ธ", + "knife": "๐ช", + "knot": "๐ชข", + "koala": "๐จ", + "koko": "๐", + "kosovo": "๐ฝ๐ฐ", + "kr": "๐ฐ๐ท", + "kuwait": "๐ฐ๐ผ", + "kyrgyzstan": "๐ฐ๐ฌ", + "lab_coat": "๐ฅผ", + "label": "๐ท๏ธ", + "lacrosse": "๐ฅ", + "ladder": "๐ช", + "lady_beetle": "๐", + "lantern": "๐ฎ", + "laos": "๐ฑ๐ฆ", + "large_blue_circle": "๐ต", + "large_blue_diamond": "๐ท", + "large_orange_diamond": "๐ถ", + "last_quarter_moon": "๐", + "last_quarter_moon_with_face": "๐", + "latin_cross": "โ๏ธ", + "latvia": "๐ฑ๐ป", + "laughing": "๐", + "leafy_green": "๐ฅฌ", + "leaves": "๐", + "lebanon": "๐ฑ๐ง", + "ledger": "๐", + "left_luggage": "๐ ", + "left_right_arrow": "โ๏ธ", + "left_speech_bubble": "๐จ๏ธ", + "leftwards_arrow_with_hook": "โฉ๏ธ", + "leg": "๐ฆต", + "lemon": "๐", + "leo": "โ", + "leopard": "๐", + "lesotho": "๐ฑ๐ธ", + "level_slider": "๐๏ธ", + "liberia": "๐ฑ๐ท", + "libra": "โ", + "libya": "๐ฑ๐พ", + "liechtenstein": "๐ฑ๐ฎ", + "light_rail": "๐", + "link": "๐", + "lion": "๐ฆ", + "lips": "๐", + "lipstick": "๐", + "lithuania": "๐ฑ๐น", + "lizard": "๐ฆ", + "llama": "๐ฆ", + "lobster": "๐ฆ", + "lock": "๐", + "lock_with_ink_pen": "๐", + "lollipop": "๐ญ", + "long_drum": "๐ช", + "loop": "โฟ", + "lotion_bottle": "๐งด", + "lotus_position": "๐ง", + "lotus_position_man": "๐งโโ๏ธ", + "lotus_position_woman": "๐งโโ๏ธ", + "loud_sound": "๐", + "loudspeaker": "๐ข", + "love_hotel": "๐ฉ", + "love_letter": "๐", + "love_you_gesture": "๐ค", + "low_brightness": "๐ ", + "luggage": "๐งณ", + "lungs": "๐ซ", + "luxembourg": "๐ฑ๐บ", + "lying_face": "๐คฅ", + "m": "โ๏ธ", + "macau": "๐ฒ๐ด", + "macedonia": "๐ฒ๐ฐ", + "madagascar": "๐ฒ๐ฌ", + "mag": "๐", + "mag_right": "๐", + "mage": "๐ง", + "mage_man": "๐งโโ๏ธ", + "mage_woman": "๐งโโ๏ธ", + "magic_wand": "๐ช", + "magnet": "๐งฒ", + "mahjong": "๐", + "mailbox": "๐ซ", + "mailbox_closed": "๐ช", + "mailbox_with_mail": "๐ฌ", + "mailbox_with_no_mail": "๐ญ", + "malawi": "๐ฒ๐ผ", + "malaysia": "๐ฒ๐พ", + "maldives": "๐ฒ๐ป", + "male_detective": "๐ต๏ธโโ๏ธ", + "male_sign": "โ๏ธ", + "mali": "๐ฒ๐ฑ", + "malta": "๐ฒ๐น", + "mammoth": "๐ฆฃ", + "man": "๐จ", + "man_artist": "๐จโ๐จ", + "man_astronaut": "๐จโ๐", + "man_beard": "๐งโโ๏ธ", + "man_cartwheeling": "๐คธโโ๏ธ", + "man_cook": "๐จโ๐ณ", + "man_dancing": "๐บ", + "man_facepalming": "๐คฆโโ๏ธ", + "man_factory_worker": "๐จโ๐ญ", + "man_farmer": "๐จโ๐พ", + "man_feeding_baby": "๐จโ๐ผ", + "man_firefighter": "๐จโ๐", + "man_health_worker": "๐จโโ๏ธ", + "man_in_manual_wheelchair": "๐จโ๐ฆฝ", + "man_in_motorized_wheelchair": "๐จโ๐ฆผ", + "man_in_tuxedo": "๐คตโโ๏ธ", + "man_judge": "๐จโโ๏ธ", + "man_juggling": "๐คนโโ๏ธ", + "man_mechanic": "๐จโ๐ง", + "man_office_worker": "๐จโ๐ผ", + "man_pilot": "๐จโโ๏ธ", + "man_playing_handball": "๐คพโโ๏ธ", + "man_playing_water_polo": "๐คฝโโ๏ธ", + "man_scientist": "๐จโ๐ฌ", + "man_shrugging": "๐คทโโ๏ธ", + "man_singer": "๐จโ๐ค", + "man_student": "๐จโ๐", + "man_teacher": "๐จโ๐ซ", + "man_technologist": "๐จโ๐ป", + "man_with_gua_pi_mao": "๐ฒ", + "man_with_probing_cane": "๐จโ๐ฆฏ", + "man_with_turban": "๐ณโโ๏ธ", + "man_with_veil": "๐ฐโโ๏ธ", + "mandarin": "๐", + "mango": "๐ฅญ", + "mans_shoe": "๐", + "mantelpiece_clock": "๐ฐ๏ธ", + "manual_wheelchair": "๐ฆฝ", + "maple_leaf": "๐", + "marshall_islands": "๐ฒ๐ญ", + "martial_arts_uniform": "๐ฅ", + "martinique": "๐ฒ๐ถ", + "mask": "๐ท", + "massage": "๐", + "massage_man": "๐โโ๏ธ", + "massage_woman": "๐โโ๏ธ", + "mate": "๐ง", + "mauritania": "๐ฒ๐ท", + "mauritius": "๐ฒ๐บ", + "mayotte": "๐พ๐น", + "meat_on_bone": "๐", + "mechanic": "๐งโ๐ง", + "mechanical_arm": "๐ฆพ", + "mechanical_leg": "๐ฆฟ", + "medal_military": "๐๏ธ", + "medal_sports": "๐ ", + "medical_symbol": "โ๏ธ", + "mega": "๐ฃ", + "melon": "๐", + "memo": "๐", + "men_wrestling": "๐คผโโ๏ธ", + "mending_heart": "โค๏ธโ๐ฉน", + "menorah": "๐", + "mens": "๐น", + "mermaid": "๐งโโ๏ธ", + "merman": "๐งโโ๏ธ", + "merperson": "๐ง", + "metal": "๐ค", + "metro": "๐", + "mexico": "๐ฒ๐ฝ", + "microbe": "๐ฆ ", + "micronesia": "๐ซ๐ฒ", + "microphone": "๐ค", + "microscope": "๐ฌ", + "middle_finger": "๐", + "military_helmet": "๐ช", + "milk_glass": "๐ฅ", + "milky_way": "๐", + "minibus": "๐", + "minidisc": "๐ฝ", + "mirror": "๐ช", + "mobile_phone_off": "๐ด", + "moldova": "๐ฒ๐ฉ", + "monaco": "๐ฒ๐จ", + "money_mouth_face": "๐ค", + "money_with_wings": "๐ธ", + "moneybag": "๐ฐ", + "mongolia": "๐ฒ๐ณ", + "monkey": "๐", + "monkey_face": "๐ต", + "monocle_face": "๐ง", + "monorail": "๐", + "montenegro": "๐ฒ๐ช", + "montserrat": "๐ฒ๐ธ", + "moon": "๐", + "moon_cake": "๐ฅฎ", + "morocco": "๐ฒ๐ฆ", + "mortar_board": "๐", + "mosque": "๐", + "mosquito": "๐ฆ", + "motor_boat": "๐ฅ๏ธ", + "motor_scooter": "๐ต", + "motorcycle": "๐๏ธ", + "motorized_wheelchair": "๐ฆผ", + "motorway": "๐ฃ๏ธ", + "mount_fuji": "๐ป", + "mountain": "โฐ๏ธ", + "mountain_bicyclist": "๐ต", + "mountain_biking_man": "๐ตโโ๏ธ", + "mountain_biking_woman": "๐ตโโ๏ธ", + "mountain_cableway": "๐ ", + "mountain_railway": "๐", + "mountain_snow": "๐๏ธ", + "mouse": "๐ญ", + "mouse2": "๐", + "mouse_trap": "๐ชค", + "movie_camera": "๐ฅ", + "moyai": "๐ฟ", + "mozambique": "๐ฒ๐ฟ", + "mrs_claus": "๐คถ", + "muscle": "๐ช", + "mushroom": "๐", + "musical_keyboard": "๐น", + "musical_note": "๐ต", + "musical_score": "๐ผ", + "mute": "๐", + "mx_claus": "๐งโ๐", + "myanmar": "๐ฒ๐ฒ", + "nail_care": "๐ ", + "name_badge": "๐", + "namibia": "๐ณ๐ฆ", + "national_park": "๐๏ธ", + "nauru": "๐ณ๐ท", + "nauseated_face": "๐คข", + "nazar_amulet": "๐งฟ", + "necktie": "๐", + "negative_squared_cross_mark": "โ", + "nepal": "๐ณ๐ต", + "nerd_face": "๐ค", + "nesting_dolls": "๐ช", + "netherlands": "๐ณ๐ฑ", + "neutral_face": "๐", + "new": "๐", + "new_caledonia": "๐ณ๐จ", + "new_moon": "๐", + "new_moon_with_face": "๐", + "new_zealand": "๐ณ๐ฟ", + "newspaper": "๐ฐ", + "newspaper_roll": "๐๏ธ", + "next_track_button": "โญ๏ธ", + "ng": "๐", + "ng_man": "๐ โโ๏ธ", + "ng_woman": "๐ โโ๏ธ", + "nicaragua": "๐ณ๐ฎ", + "niger": "๐ณ๐ช", + "nigeria": "๐ณ๐ฌ", + "night_with_stars": "๐", + "nine": "9๏ธโฃ", + "ninja": "๐ฅท", + "niue": "๐ณ๐บ", + "no_bell": "๐", + "no_bicycles": "๐ณ", + "no_entry": "โ", + "no_entry_sign": "๐ซ", + "no_good": "๐ ", + "no_good_man": "๐ โโ๏ธ", + "no_good_woman": "๐ โโ๏ธ", + "no_mobile_phones": "๐ต", + "no_mouth": "๐ถ", + "no_pedestrians": "๐ท", + "no_smoking": "๐ญ", + "non-potable_water": "๐ฑ", + "norfolk_island": "๐ณ๐ซ", + "north_korea": "๐ฐ๐ต", + "northern_mariana_islands": "๐ฒ๐ต", + "norway": "๐ณ๐ด", + "nose": "๐", + "notebook": "๐", + "notebook_with_decorative_cover": "๐", + "notes": "๐ถ", + "nut_and_bolt": "๐ฉ", + "o": "โญ", + "o2": "๐ พ๏ธ", + "ocean": "๐", + "octopus": "๐", + "oden": "๐ข", + "office": "๐ข", + "office_worker": "๐งโ๐ผ", + "oil_drum": "๐ข๏ธ", + "ok": "๐", + "ok_hand": "๐", + "ok_man": "๐โโ๏ธ", + "ok_person": "๐", + "ok_woman": "๐โโ๏ธ", + "old_key": "๐๏ธ", + "older_adult": "๐ง", + "older_man": "๐ด", + "older_woman": "๐ต", + "olive": "๐ซ", + "om": "๐๏ธ", + "oman": "๐ด๐ฒ", + "on": "๐", + "oncoming_automobile": "๐", + "oncoming_bus": "๐", + "oncoming_police_car": "๐", + "oncoming_taxi": "๐", + "one": "1๏ธโฃ", + "one_piece_swimsuit": "๐ฉฑ", + "onion": "๐ง ", + "open_book": "๐", + "open_file_folder": "๐", + "open_hands": "๐", + "open_mouth": "๐ฎ", + "open_umbrella": "โ๏ธ", + "ophiuchus": "โ", + "orange": "๐", + "orange_book": "๐", + "orange_circle": "๐ ", + "orange_heart": "๐งก", + "orange_square": "๐ง", + "orangutan": "๐ฆง", + "orthodox_cross": "โฆ๏ธ", + "otter": "๐ฆฆ", + "outbox_tray": "๐ค", + "owl": "๐ฆ", + "ox": "๐", + "oyster": "๐ฆช", + "package": "๐ฆ", + "page_facing_up": "๐", + "page_with_curl": "๐", + "pager": "๐", + "paintbrush": "๐๏ธ", + "pakistan": "๐ต๐ฐ", + "palau": "๐ต๐ผ", + "palestinian_territories": "๐ต๐ธ", + "palm_tree": "๐ด", + "palms_up_together": "๐คฒ", + "panama": "๐ต๐ฆ", + "pancakes": "๐ฅ", + "panda_face": "๐ผ", + "paperclip": "๐", + "paperclips": "๐๏ธ", + "papua_new_guinea": "๐ต๐ฌ", + "parachute": "๐ช", + "paraguay": "๐ต๐พ", + "parasol_on_ground": "โฑ๏ธ", + "parking": "๐ ฟ๏ธ", + "parrot": "๐ฆ", + "part_alternation_mark": "ใฝ๏ธ", + "partly_sunny": "โ ", + "partying_face": "๐ฅณ", + "passenger_ship": "๐ณ๏ธ", + "passport_control": "๐", + "pause_button": "โธ๏ธ", + "paw_prints": "๐พ", + "peace_symbol": "โฎ๏ธ", + "peach": "๐", + "peacock": "๐ฆ", + "peanuts": "๐ฅ", + "pear": "๐", + "pen": "๐๏ธ", + "pencil": "๐", + "pencil2": "โ๏ธ", + "penguin": "๐ง", + "pensive": "๐", + "people_holding_hands": "๐งโ๐คโ๐ง", + "people_hugging": "๐ซ", + "performing_arts": "๐ญ", + "persevere": "๐ฃ", + "person_bald": "๐งโ๐ฆฒ", + "person_curly_hair": "๐งโ๐ฆฑ", + "person_feeding_baby": "๐งโ๐ผ", + "person_fencing": "๐คบ", + "person_in_manual_wheelchair": "๐งโ๐ฆฝ", + "person_in_motorized_wheelchair": "๐งโ๐ฆผ", + "person_in_tuxedo": "๐คต", + "person_red_hair": "๐งโ๐ฆฐ", + "person_white_hair": "๐งโ๐ฆณ", + "person_with_probing_cane": "๐งโ๐ฆฏ", + "person_with_turban": "๐ณ", + "person_with_veil": "๐ฐ", + "peru": "๐ต๐ช", + "petri_dish": "๐งซ", + "philippines": "๐ต๐ญ", + "phone": "โ๏ธ", + "pick": "โ๏ธ", + "pickup_truck": "๐ป", + "pie": "๐ฅง", + "pig": "๐ท", + "pig2": "๐", + "pig_nose": "๐ฝ", + "pill": "๐", + "pilot": "๐งโโ๏ธ", + "pinata": "๐ช ", + "pinched_fingers": "๐ค", + "pinching_hand": "๐ค", + "pineapple": "๐", + "ping_pong": "๐", + "pirate_flag": "๐ดโโ ๏ธ", + "pisces": "โ", + "pitcairn_islands": "๐ต๐ณ", + "pizza": "๐", + "placard": "๐ชง", + "place_of_worship": "๐", + "plate_with_cutlery": "๐ฝ๏ธ", + "play_or_pause_button": "โฏ๏ธ", + "pleading_face": "๐ฅบ", + "plunger": "๐ช ", + "point_down": "๐", + "point_left": "๐", + "point_right": "๐", + "point_up": "โ๏ธ", + "point_up_2": "๐", + "poland": "๐ต๐ฑ", + "polar_bear": "๐ปโโ๏ธ", + "police_car": "๐", + "police_officer": "๐ฎ", + "policeman": "๐ฎโโ๏ธ", + "policewoman": "๐ฎโโ๏ธ", + "poodle": "๐ฉ", + "poop": "๐ฉ", + "popcorn": "๐ฟ", + "portugal": "๐ต๐น", + "post_office": "๐ฃ", + "postal_horn": "๐ฏ", + "postbox": "๐ฎ", + "potable_water": "๐ฐ", + "potato": "๐ฅ", + "potted_plant": "๐ชด", + "pouch": "๐", + "poultry_leg": "๐", + "pound": "๐ท", + "pout": "๐ก", + "pouting_cat": "๐พ", + "pouting_face": "๐", + "pouting_man": "๐โโ๏ธ", + "pouting_woman": "๐โโ๏ธ", + "pray": "๐", + "prayer_beads": "๐ฟ", + "pregnant_woman": "๐คฐ", + "pretzel": "๐ฅจ", + "previous_track_button": "โฎ๏ธ", + "prince": "๐คด", + "princess": "๐ธ", + "printer": "๐จ๏ธ", + "probing_cane": "๐ฆฏ", + "puerto_rico": "๐ต๐ท", + "punch": "๐", + "purple_circle": "๐ฃ", + "purple_heart": "๐", + "purple_square": "๐ช", + "purse": "๐", + "pushpin": "๐", + "put_litter_in_its_place": "๐ฎ", + "qatar": "๐ถ๐ฆ", + "question": "โ", + "rabbit": "๐ฐ", + "rabbit2": "๐", + "raccoon": "๐ฆ", + "racehorse": "๐", + "racing_car": "๐๏ธ", + "radio": "๐ป", + "radio_button": "๐", + "radioactive": "โข๏ธ", + "rage": "๐ก", + "railway_car": "๐", + "railway_track": "๐ค๏ธ", + "rainbow": "๐", + "rainbow_flag": "๐ณ๏ธโ๐", + "raised_back_of_hand": "๐ค", + "raised_eyebrow": "๐คจ", + "raised_hand": "โ", + "raised_hand_with_fingers_splayed": "๐๏ธ", + "raised_hands": "๐", + "raising_hand": "๐", + "raising_hand_man": "๐โโ๏ธ", + "raising_hand_woman": "๐โโ๏ธ", + "ram": "๐", + "ramen": "๐", + "rat": "๐", + "razor": "๐ช", + "receipt": "๐งพ", + "record_button": "โบ๏ธ", + "recycle": "โป๏ธ", + "red_car": "๐", + "red_circle": "๐ด", + "red_envelope": "๐งง", + "red_haired_man": "๐จโ๐ฆฐ", + "red_haired_woman": "๐ฉโ๐ฆฐ", + "red_square": "๐ฅ", + "registered": "ยฎ๏ธ", + "relaxed": "โบ๏ธ", + "relieved": "๐", + "reminder_ribbon": "๐๏ธ", + "repeat": "๐", + "repeat_one": "๐", + "rescue_worker_helmet": "โ๏ธ", + "restroom": "๐ป", + "reunion": "๐ท๐ช", + "revolving_hearts": "๐", + "rewind": "โช", + "rhinoceros": "๐ฆ", + "ribbon": "๐", + "rice": "๐", + "rice_ball": "๐", + "rice_cracker": "๐", + "rice_scene": "๐", + "right_anger_bubble": "๐ฏ๏ธ", + "ring": "๐", + "ringed_planet": "๐ช", + "robot": "๐ค", + "rock": "๐ชจ", + "rocket": "๐", + "rofl": "๐คฃ", + "roll_eyes": "๐", + "roll_of_paper": "๐งป", + "roller_coaster": "๐ข", + "roller_skate": "๐ผ", + "romania": "๐ท๐ด", + "rooster": "๐", + "rose": "๐น", + "rosette": "๐ต๏ธ", + "rotating_light": "๐จ", + "round_pushpin": "๐", + "rowboat": "๐ฃ", + "rowing_man": "๐ฃโโ๏ธ", + "rowing_woman": "๐ฃโโ๏ธ", + "ru": "๐ท๐บ", + "rugby_football": "๐", + "runner": "๐", + "running": "๐", + "running_man": "๐โโ๏ธ", + "running_shirt_with_sash": "๐ฝ", + "running_woman": "๐โโ๏ธ", + "rwanda": "๐ท๐ผ", + "sa": "๐๏ธ", + "safety_pin": "๐งท", + "safety_vest": "๐ฆบ", + "sagittarius": "โ", + "sailboat": "โต", + "sake": "๐ถ", + "salt": "๐ง", + "samoa": "๐ผ๐ธ", + "san_marino": "๐ธ๐ฒ", + "sandal": "๐ก", + "sandwich": "๐ฅช", + "santa": "๐ ", + "sao_tome_principe": "๐ธ๐น", + "sari": "๐ฅป", + "sassy_man": "๐โโ๏ธ", + "sassy_woman": "๐โโ๏ธ", + "satellite": "๐ก", + "satisfied": "๐", + "saudi_arabia": "๐ธ๐ฆ", + "sauna_man": "๐งโโ๏ธ", + "sauna_person": "๐ง", + "sauna_woman": "๐งโโ๏ธ", + "sauropod": "๐ฆ", + "saxophone": "๐ท", + "scarf": "๐งฃ", + "school": "๐ซ", + "school_satchel": "๐", + "scientist": "๐งโ๐ฌ", + "scissors": "โ๏ธ", + "scorpion": "๐ฆ", + "scorpius": "โ", + "scotland": "๐ด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ", + "scream": "๐ฑ", + "scream_cat": "๐", + "screwdriver": "๐ช", + "scroll": "๐", + "seal": "๐ฆญ", + "seat": "๐บ", + "secret": "ใ๏ธ", + "see_no_evil": "๐", + "seedling": "๐ฑ", + "selfie": "๐คณ", + "senegal": "๐ธ๐ณ", + "serbia": "๐ท๐ธ", + "service_dog": "๐โ๐ฆบ", + "seven": "7๏ธโฃ", + "sewing_needle": "๐ชก", + "seychelles": "๐ธ๐จ", + "shallow_pan_of_food": "๐ฅ", + "shamrock": "โ๏ธ", + "shark": "๐ฆ", + "shaved_ice": "๐ง", + "sheep": "๐", + "shell": "๐", + "shield": "๐ก๏ธ", + "shinto_shrine": "โฉ๏ธ", + "ship": "๐ข", + "shirt": "๐", + "shit": "๐ฉ", + "shoe": "๐", + "shopping": "๐๏ธ", + "shopping_cart": "๐", + "shorts": "๐ฉณ", + "shower": "๐ฟ", + "shrimp": "๐ฆ", + "shrug": "๐คท", + "shushing_face": "๐คซ", + "sierra_leone": "๐ธ๐ฑ", + "signal_strength": "๐ถ", + "singapore": "๐ธ๐ฌ", + "singer": "๐งโ๐ค", + "sint_maarten": "๐ธ๐ฝ", + "six": "6๏ธโฃ", + "six_pointed_star": "๐ฏ", + "skateboard": "๐น", + "ski": "๐ฟ", + "skier": "โท๏ธ", + "skull": "๐", + "skull_and_crossbones": "โ ๏ธ", + "skunk": "๐ฆจ", + "sled": "๐ท", + "sleeping": "๐ด", + "sleeping_bed": "๐", + "sleepy": "๐ช", + "slightly_frowning_face": "๐", + "slightly_smiling_face": "๐", + "slot_machine": "๐ฐ", + "sloth": "๐ฆฅ", + "slovakia": "๐ธ๐ฐ", + "slovenia": "๐ธ๐ฎ", + "small_airplane": "๐ฉ๏ธ", + "small_blue_diamond": "๐น", + "small_orange_diamond": "๐ธ", + "small_red_triangle": "๐บ", + "small_red_triangle_down": "๐ป", + "smile": "๐", + "smile_cat": "๐ธ", + "smiley": "๐", + "smiley_cat": "๐บ", + "smiling_face_with_tear": "๐ฅฒ", + "smiling_face_with_three_hearts": "๐ฅฐ", + "smiling_imp": "๐", + "smirk": "๐", + "smirk_cat": "๐ผ", + "smoking": "๐ฌ", + "snail": "๐", + "snake": "๐", + "sneezing_face": "๐คง", + "snowboarder": "๐", + "snowflake": "โ๏ธ", + "snowman": "โ", + "snowman_with_snow": "โ๏ธ", + "soap": "๐งผ", + "sob": "๐ญ", + "soccer": "โฝ", + "socks": "๐งฆ", + "softball": "๐ฅ", + "solomon_islands": "๐ธ๐ง", + "somalia": "๐ธ๐ด", + "soon": "๐", + "sos": "๐", + "sound": "๐", + "south_africa": "๐ฟ๐ฆ", + "south_georgia_south_sandwich_islands": "๐ฌ๐ธ", + "south_sudan": "๐ธ๐ธ", + "space_invader": "๐พ", + "spades": "โ ๏ธ", + "spaghetti": "๐", + "sparkle": "โ๏ธ", + "sparkler": "๐", + "sparkles": "โจ", + "sparkling_heart": "๐", + "speak_no_evil": "๐", + "speaker": "๐", + "speaking_head": "๐ฃ๏ธ", + "speech_balloon": "๐ฌ", + "speedboat": "๐ค", + "spider": "๐ท๏ธ", + "spider_web": "๐ธ๏ธ", + "spiral_calendar": "๐๏ธ", + "spiral_notepad": "๐๏ธ", + "sponge": "๐งฝ", + "spoon": "๐ฅ", + "squid": "๐ฆ", + "sri_lanka": "๐ฑ๐ฐ", + "st_barthelemy": "๐ง๐ฑ", + "st_helena": "๐ธ๐ญ", + "st_kitts_nevis": "๐ฐ๐ณ", + "st_lucia": "๐ฑ๐จ", + "st_martin": "๐ฒ๐ซ", + "st_pierre_miquelon": "๐ต๐ฒ", + "st_vincent_grenadines": "๐ป๐จ", + "stadium": "๐๏ธ", + "standing_man": "๐งโโ๏ธ", + "standing_person": "๐ง", + "standing_woman": "๐งโโ๏ธ", + "star": "โญ", + "star2": "๐", + "star_and_crescent": "โช๏ธ", + "star_of_david": "โก๏ธ", + "star_struck": "๐คฉ", + "stars": "๐ ", + "station": "๐", + "statue_of_liberty": "๐ฝ", + "steam_locomotive": "๐", + "stethoscope": "๐ฉบ", + "stew": "๐ฒ", + "stop_button": "โน๏ธ", + "stop_sign": "๐", + "stopwatch": "โฑ๏ธ", + "straight_ruler": "๐", + "strawberry": "๐", + "stuck_out_tongue": "๐", + "stuck_out_tongue_closed_eyes": "๐", + "stuck_out_tongue_winking_eye": "๐", + "student": "๐งโ๐", + "studio_microphone": "๐๏ธ", + "stuffed_flatbread": "๐ฅ", + "sudan": "๐ธ๐ฉ", + "sun_behind_large_cloud": "๐ฅ๏ธ", + "sun_behind_rain_cloud": "๐ฆ๏ธ", + "sun_behind_small_cloud": "๐ค๏ธ", + "sun_with_face": "๐", + "sunflower": "๐ป", + "sunglasses": "๐", + "sunny": "โ๏ธ", + "sunrise": "๐ ", + "sunrise_over_mountains": "๐", + "superhero": "๐ฆธ", + "superhero_man": "๐ฆธโโ๏ธ", + "superhero_woman": "๐ฆธโโ๏ธ", + "supervillain": "๐ฆน", + "supervillain_man": "๐ฆนโโ๏ธ", + "supervillain_woman": "๐ฆนโโ๏ธ", + "surfer": "๐", + "surfing_man": "๐โโ๏ธ", + "surfing_woman": "๐โโ๏ธ", + "suriname": "๐ธ๐ท", + "sushi": "๐ฃ", + "suspension_railway": "๐", + "svalbard_jan_mayen": "๐ธ๐ฏ", + "swan": "๐ฆข", + "swaziland": "๐ธ๐ฟ", + "sweat": "๐", + "sweat_drops": "๐ฆ", + "sweat_smile": "๐ ", + "sweden": "๐ธ๐ช", + "sweet_potato": "๐ ", + "swim_brief": "๐ฉฒ", + "swimmer": "๐", + "swimming_man": "๐โโ๏ธ", + "swimming_woman": "๐โโ๏ธ", + "switzerland": "๐จ๐ญ", + "symbols": "๐ฃ", + "synagogue": "๐", + "syria": "๐ธ๐พ", + "syringe": "๐", + "t-rex": "๐ฆ", + "taco": "๐ฎ", + "tada": "๐", + "taiwan": "๐น๐ผ", + "tajikistan": "๐น๐ฏ", + "takeout_box": "๐ฅก", + "tamale": "๐ซ", + "tanabata_tree": "๐", + "tangerine": "๐", + "tanzania": "๐น๐ฟ", + "taurus": "โ", + "taxi": "๐", + "tea": "๐ต", + "teacher": "๐งโ๐ซ", + "teapot": "๐ซ", + "technologist": "๐งโ๐ป", + "teddy_bear": "๐งธ", + "telephone": "โ๏ธ", + "telephone_receiver": "๐", + "telescope": "๐ญ", + "tennis": "๐พ", + "tent": "โบ", + "test_tube": "๐งช", + "thailand": "๐น๐ญ", + "thermometer": "๐ก๏ธ", + "thinking": "๐ค", + "thong_sandal": "๐ฉด", + "thought_balloon": "๐ญ", + "thread": "๐งต", + "three": "3๏ธโฃ", + "thumbsdown": "๐", + "thumbsup": "๐", + "ticket": "๐ซ", + "tickets": "๐๏ธ", + "tiger": "๐ฏ", + "tiger2": "๐ ", + "timer_clock": "โฒ๏ธ", + "timor_leste": "๐น๐ฑ", + "tipping_hand_man": "๐โโ๏ธ", + "tipping_hand_person": "๐", + "tipping_hand_woman": "๐โโ๏ธ", + "tired_face": "๐ซ", + "tm": "โข๏ธ", + "togo": "๐น๐ฌ", + "toilet": "๐ฝ", + "tokelau": "๐น๐ฐ", + "tokyo_tower": "๐ผ", + "tomato": "๐ ", + "tonga": "๐น๐ด", + "tongue": "๐ ", + "toolbox": "๐งฐ", + "tooth": "๐ฆท", + "toothbrush": "๐ชฅ", + "top": "๐", + "tophat": "๐ฉ", + "tornado": "๐ช๏ธ", + "tr": "๐น๐ท", + "trackball": "๐ฒ๏ธ", + "tractor": "๐", + "traffic_light": "๐ฅ", + "train": "๐", + "train2": "๐", + "tram": "๐", + "transgender_flag": "๐ณ๏ธโโง๏ธ", + "transgender_symbol": "โง๏ธ", + "triangular_flag_on_post": "๐ฉ", + "triangular_ruler": "๐", + "trident": "๐ฑ", + "trinidad_tobago": "๐น๐น", + "tristan_da_cunha": "๐น๐ฆ", + "triumph": "๐ค", + "trolleybus": "๐", + "trophy": "๐", + "tropical_drink": "๐น", + "tropical_fish": "๐ ", + "truck": "๐", + "trumpet": "๐บ", + "tshirt": "๐", + "tulip": "๐ท", + "tumbler_glass": "๐ฅ", + "tunisia": "๐น๐ณ", + "turkey": "๐ฆ", + "turkmenistan": "๐น๐ฒ", + "turks_caicos_islands": "๐น๐จ", + "turtle": "๐ข", + "tuvalu": "๐น๐ป", + "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": "๐ณ", + "uganda": "๐บ๐ฌ", + "uk": "๐ฌ๐ง", + "ukraine": "๐บ๐ฆ", + "umbrella": "โ", + "unamused": "๐", + "underage": "๐", + "unicorn": "๐ฆ", + "united_arab_emirates": "๐ฆ๐ช", + "united_nations": "๐บ๐ณ", + "unlock": "๐", + "up": "๐", + "upside_down_face": "๐", + "uruguay": "๐บ๐พ", + "us": "๐บ๐ธ", + "us_outlying_islands": "๐บ๐ฒ", + "us_virgin_islands": "๐ป๐ฎ", + "uzbekistan": "๐บ๐ฟ", + "v": "โ๏ธ", + "vampire": "๐ง", + "vampire_man": "๐งโโ๏ธ", + "vampire_woman": "๐งโโ๏ธ", + "vanuatu": "๐ป๐บ", + "vatican_city": "๐ป๐ฆ", + "venezuela": "๐ป๐ช", + "vertical_traffic_light": "๐ฆ", + "vhs": "๐ผ", + "vibration_mode": "๐ณ", + "video_camera": "๐น", + "video_game": "๐ฎ", + "vietnam": "๐ป๐ณ", + "violin": "๐ป", + "virgo": "โ", + "volcano": "๐", + "volleyball": "๐", + "vomiting_face": "๐คฎ", + "vs": "๐", + "vulcan_salute": "๐", + "waffle": "๐ง", + "wales": "๐ด๓ ง๓ ข๓ ท๓ ฌ๓ ณ๓ ฟ", + "walking": "๐ถ", + "walking_man": "๐ถโโ๏ธ", + "walking_woman": "๐ถโโ๏ธ", + "wallis_futuna": "๐ผ๐ซ", + "waning_crescent_moon": "๐", + "waning_gibbous_moon": "๐", + "warning": "โ ๏ธ", + "wastebasket": "๐๏ธ", + "watch": "โ", + "water_buffalo": "๐", + "water_polo": "๐คฝ", + "watermelon": "๐", + "wave": "๐", + "wavy_dash": "ใฐ๏ธ", + "waxing_crescent_moon": "๐", + "waxing_gibbous_moon": "๐", + "wc": "๐พ", + "weary": "๐ฉ", + "wedding": "๐", + "weight_lifting": "๐๏ธ", + "weight_lifting_man": "๐๏ธโโ๏ธ", + "weight_lifting_woman": "๐๏ธโโ๏ธ", + "western_sahara": "๐ช๐ญ", + "whale": "๐ณ", + "whale2": "๐", + "wheel_of_dharma": "โธ๏ธ", + "wheelchair": "โฟ", + "white_check_mark": "โ ", + "white_circle": "โช", + "white_flag": "๐ณ๏ธ", + "white_flower": "๐ฎ", + "white_haired_man": "๐จโ๐ฆณ", + "white_haired_woman": "๐ฉโ๐ฆณ", + "white_heart": "๐ค", + "white_large_square": "โฌ", + "white_medium_small_square": "โฝ", + "white_medium_square": "โป๏ธ", + "white_small_square": "โซ๏ธ", + "white_square_button": "๐ณ", + "wilted_flower": "๐ฅ", + "wind_chime": "๐", + "wind_face": "๐ฌ๏ธ", + "window": "๐ช", + "wine_glass": "๐ท", + "wink": "๐", + "wolf": "๐บ", + "woman": "๐ฉ", + "woman_artist": "๐ฉโ๐จ", + "woman_astronaut": "๐ฉโ๐", + "woman_beard": "๐งโโ๏ธ", + "woman_cartwheeling": "๐คธโโ๏ธ", + "woman_cook": "๐ฉโ๐ณ", + "woman_dancing": "๐", + "woman_facepalming": "๐คฆโโ๏ธ", + "woman_factory_worker": "๐ฉโ๐ญ", + "woman_farmer": "๐ฉโ๐พ", + "woman_feeding_baby": "๐ฉโ๐ผ", + "woman_firefighter": "๐ฉโ๐", + "woman_health_worker": "๐ฉโโ๏ธ", + "woman_in_manual_wheelchair": "๐ฉโ๐ฆฝ", + "woman_in_motorized_wheelchair": "๐ฉโ๐ฆผ", + "woman_in_tuxedo": "๐คตโโ๏ธ", + "woman_judge": "๐ฉโโ๏ธ", + "woman_juggling": "๐คนโโ๏ธ", + "woman_mechanic": "๐ฉโ๐ง", + "woman_office_worker": "๐ฉโ๐ผ", + "woman_pilot": "๐ฉโโ๏ธ", + "woman_playing_handball": "๐คพโโ๏ธ", + "woman_playing_water_polo": "๐คฝโโ๏ธ", + "woman_scientist": "๐ฉโ๐ฌ", + "woman_shrugging": "๐คทโโ๏ธ", + "woman_singer": "๐ฉโ๐ค", + "woman_student": "๐ฉโ๐", + "woman_teacher": "๐ฉโ๐ซ", + "woman_technologist": "๐ฉโ๐ป", + "woman_with_headscarf": "๐ง", + "woman_with_probing_cane": "๐ฉโ๐ฆฏ", + "woman_with_turban": "๐ณโโ๏ธ", + "woman_with_veil": "๐ฐโโ๏ธ", + "womans_clothes": "๐", + "womans_hat": "๐", + "women_wrestling": "๐คผโโ๏ธ", + "womens": "๐บ", + "wood": "๐ชต", + "woozy_face": "๐ฅด", + "world_map": "๐บ๏ธ", + "worm": "๐ชฑ", + "worried": "๐", + "wrench": "๐ง", + "wrestling": "๐คผ", + "writing_hand": "โ๏ธ", + "x": "โ", + "yarn": "๐งถ", + "yawning_face": "๐ฅฑ", + "yellow_circle": "๐ก", + "yellow_heart": "๐", + "yellow_square": "๐จ", + "yemen": "๐พ๐ช", + "yen": "๐ด", + "yin_yang": "โฏ๏ธ", + "yo_yo": "๐ช", + "yum": "๐", + "zambia": "๐ฟ๐ฒ", + "zany_face": "๐คช", + "zap": "โก", + "zebra": "๐ฆ", + "zero": "0๏ธโฃ", + "zimbabwe": "๐ฟ๐ผ", + "zipper_mouth_face": "๐ค", + "zombie": "๐ง", + "zombie_man": "๐งโโ๏ธ", + "zombie_woman": "๐งโโ๏ธ", + "zzz": "๐ค" +} \ No newline at end of file diff --git a/server/server.go b/server/server.go index 505de4b8..430fa5cb 100644 --- a/server/server.go +++ b/server/server.go @@ -82,6 +82,8 @@ var ( apiHealthPath = "/v1/health" apiStatsPath = "/v1/stats" apiTiersPath = "/v1/tiers" + apiUsersPath = "/v1/users" + apiUsersAccessPath = "/v1/users/access" apiAccountPath = "/v1/account" apiAccountTokenPath = "/v1/account/token" apiAccountPasswordPath = "/v1/account/password" @@ -413,6 +415,16 @@ func (s *Server) handleInternal(w http.ResponseWriter, r *http.Request, v *visit return s.handleHealth(w, r, v) } else if r.Method == http.MethodGet && r.URL.Path == webConfigPath { return s.ensureWebEnabled(s.handleWebConfig)(w, r, v) + } else if r.Method == http.MethodGet && r.URL.Path == apiUsersPath { + return s.ensureAdmin(s.handleUsersGet)(w, r, v) + } else if r.Method == http.MethodPut && r.URL.Path == apiUsersPath { + return s.ensureAdmin(s.handleUsersAdd)(w, r, v) + } else if r.Method == http.MethodDelete && r.URL.Path == apiUsersPath { + return s.ensureAdmin(s.handleUsersDelete)(w, r, v) + } else if (r.Method == http.MethodPut || r.Method == http.MethodPost) && r.URL.Path == apiUsersAccessPath { + return s.ensureAdmin(s.handleAccessAllow)(w, r, v) + } else if r.Method == http.MethodDelete && r.URL.Path == apiUsersAccessPath { + return s.ensureAdmin(s.handleAccessReset)(w, r, v) } else if r.Method == http.MethodPost && r.URL.Path == apiAccountPath { return s.ensureUserManager(s.handleAccountCreate)(w, r, v) } else if r.Method == http.MethodGet && r.URL.Path == apiAccountPath { @@ -651,6 +663,9 @@ func (s *Server) handleFile(w http.ResponseWriter, r *http.Request, v *visitor) return err } defer f.Close() + if m.Attachment.Name != "" { + w.Header().Set("Content-Disposition", "attachment; filename="+strconv.Quote(m.Attachment.Name)) + } _, err = io.Copy(util.NewContentTypeWriter(w, r.URL.Path), f) return err } @@ -1221,7 +1236,7 @@ func (s *Server) handleSubscribeWS(w http.ResponseWriter, r *http.Request, v *vi } defer conn.Close() - // Subscription connections can be canceled externally, see topic.CancelSubscribers + // Subscription connections can be canceled externally, see topic.CancelSubscribersExceptUser cancelCtx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -1463,6 +1478,7 @@ func (s *Server) handleOptions(w http.ResponseWriter, _ *http.Request, _ *visito return nil } +// topicFromPath returns the topic from a root path (e.g. /mytopic), creating it if it doesn't exist. func (s *Server) topicFromPath(path string) (*topic, error) { parts := strings.Split(path, "/") if len(parts) < 2 { @@ -1471,6 +1487,7 @@ func (s *Server) topicFromPath(path string) (*topic, error) { return s.topicFromID(parts[1]) } +// topicsFromPath returns the topic from a root path (e.g. /mytopic,mytopic2), creating it if it doesn't exist. func (s *Server) topicsFromPath(path string) ([]*topic, string, error) { parts := strings.Split(path, "/") if len(parts) < 2 { @@ -1484,6 +1501,7 @@ func (s *Server) topicsFromPath(path string) ([]*topic, string, error) { return topics, parts[1], nil } +// topicsFromIDs returns the topics with the given IDs, creating them if they don't exist. func (s *Server) topicsFromIDs(ids ...string) ([]*topic, error) { s.mu.Lock() defer s.mu.Unlock() @@ -1503,6 +1521,7 @@ func (s *Server) topicsFromIDs(ids ...string) ([]*topic, error) { return topics, nil } +// topicFromID returns the topic with the given ID, creating it if it doesn't exist. func (s *Server) topicFromID(id string) (*topic, error) { topics, err := s.topicsFromIDs(id) if err != nil { @@ -1511,6 +1530,23 @@ func (s *Server) topicFromID(id string) (*topic, error) { return topics[0], nil } +// topicsFromPattern returns a list of topics matching the given pattern, but it does not create them. +func (s *Server) topicsFromPattern(pattern string) ([]*topic, error) { + s.mu.RLock() + defer s.mu.RUnlock() + patternRegexp, err := regexp.Compile("^" + strings.ReplaceAll(pattern, "*", ".*") + "$") + if err != nil { + return nil, err + } + topics := make([]*topic, 0) + for _, t := range s.topics { + if patternRegexp.MatchString(t.ID) { + topics = append(topics, t) + } + } + return topics, nil +} + func (s *Server) runSMTPServer() error { s.smtpServerBackend = newMailBackend(s.config, s.handle) s.smtpServer = smtp.NewServer(s.smtpServerBackend) diff --git a/server/server_account.go b/server/server_account.go index c5517d66..eb1c768f 100644 --- a/server/server_account.go +++ b/server/server_account.go @@ -454,7 +454,7 @@ func (s *Server) handleAccountReservationAdd(w http.ResponseWriter, r *http.Requ if err != nil { return err } - t.CancelSubscribers(u.ID) + t.CancelSubscribersExceptUser(u.ID) return s.writeJSON(w, newSuccessResponse()) } diff --git a/server/server_admin.go b/server/server_admin.go new file mode 100644 index 00000000..9380a5ff --- /dev/null +++ b/server/server_admin.go @@ -0,0 +1,143 @@ +package server + +import ( + "heckel.io/ntfy/user" + "net/http" +) + +func (s *Server) handleUsersGet(w http.ResponseWriter, r *http.Request, v *visitor) error { + users, err := s.userManager.Users() + if err != nil { + return err + } + grants, err := s.userManager.AllGrants() + if err != nil { + return err + } + usersResponse := make([]*apiUserResponse, len(users)) + for i, u := range users { + tier := "" + if u.Tier != nil { + tier = u.Tier.Code + } + userGrants := make([]*apiUserGrantResponse, len(grants[u.ID])) + for i, g := range grants[u.ID] { + userGrants[i] = &apiUserGrantResponse{ + Topic: g.TopicPattern, + Permission: g.Allow.String(), + } + } + usersResponse[i] = &apiUserResponse{ + Username: u.Name, + Role: string(u.Role), + Tier: tier, + Grants: userGrants, + } + } + return s.writeJSON(w, usersResponse) +} + +func (s *Server) handleUsersAdd(w http.ResponseWriter, r *http.Request, v *visitor) error { + req, err := readJSONWithLimit[apiUserAddRequest](r.Body, jsonBodyBytesLimit, false) + if err != nil { + return err + } else if !user.AllowedUsername(req.Username) || req.Password == "" { + return errHTTPBadRequest.Wrap("username invalid, or password missing") + } + u, err := s.userManager.User(req.Username) + if err != nil && err != user.ErrUserNotFound { + return err + } else if u != nil { + return errHTTPConflictUserExists + } + var tier *user.Tier + if req.Tier != "" { + tier, err = s.userManager.Tier(req.Tier) + if err == user.ErrTierNotFound { + return errHTTPBadRequestTierInvalid + } else if err != nil { + return err + } + } + if err := s.userManager.AddUser(req.Username, req.Password, user.RoleUser); err != nil { + return err + } + if tier != nil { + if err := s.userManager.ChangeTier(req.Username, req.Tier); err != nil { + return err + } + } + return s.writeJSON(w, newSuccessResponse()) +} + +func (s *Server) handleUsersDelete(w http.ResponseWriter, r *http.Request, v *visitor) error { + req, err := readJSONWithLimit[apiUserDeleteRequest](r.Body, jsonBodyBytesLimit, false) + if err != nil { + return err + } + u, err := s.userManager.User(req.Username) + if err == user.ErrUserNotFound { + return errHTTPBadRequestUserNotFound + } else if err != nil { + return err + } else if !u.IsUser() { + return errHTTPUnauthorized.Wrap("can only remove regular users from API") + } + if err := s.userManager.RemoveUser(req.Username); err != nil { + return err + } + if err := s.killUserSubscriber(u, "*"); err != nil { // FIXME super inefficient + return err + } + return s.writeJSON(w, newSuccessResponse()) +} + +func (s *Server) handleAccessAllow(w http.ResponseWriter, r *http.Request, v *visitor) error { + req, err := readJSONWithLimit[apiAccessAllowRequest](r.Body, jsonBodyBytesLimit, false) + if err != nil { + return err + } + _, err = s.userManager.User(req.Username) + if err == user.ErrUserNotFound { + return errHTTPBadRequestUserNotFound + } else if err != nil { + return err + } + permission, err := user.ParsePermission(req.Permission) + if err != nil { + return errHTTPBadRequestPermissionInvalid + } + if err := s.userManager.AllowAccess(req.Username, req.Topic, permission); err != nil { + return err + } + return s.writeJSON(w, newSuccessResponse()) +} + +func (s *Server) handleAccessReset(w http.ResponseWriter, r *http.Request, v *visitor) error { + req, err := readJSONWithLimit[apiAccessResetRequest](r.Body, jsonBodyBytesLimit, false) + if err != nil { + return err + } + u, err := s.userManager.User(req.Username) + if err != nil { + return err + } + if err := s.userManager.ResetAccess(req.Username, req.Topic); err != nil { + return err + } + if err := s.killUserSubscriber(u, req.Topic); err != nil { // This may be a pattern + return err + } + return s.writeJSON(w, newSuccessResponse()) +} + +func (s *Server) killUserSubscriber(u *user.User, topicPattern string) error { + topics, err := s.topicsFromPattern(topicPattern) + if err != nil { + return err + } + for _, t := range topics { + t.CancelSubscriberUser(u.ID) + } + return nil +} diff --git a/server/server_admin_test.go b/server/server_admin_test.go new file mode 100644 index 00000000..1513ea40 --- /dev/null +++ b/server/server_admin_test.go @@ -0,0 +1,181 @@ +package server + +import ( + "github.com/stretchr/testify/require" + "heckel.io/ntfy/user" + "heckel.io/ntfy/util" + "sync/atomic" + "testing" + "time" +) + +func TestUser_AddRemove(t *testing.T) { + s := newTestServer(t, newTestConfigWithAuthFile(t)) + defer s.closeDatabases() + + // Create admin, tier + require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleAdmin)) + require.Nil(t, s.userManager.AddTier(&user.Tier{ + Code: "tier1", + })) + + // Create user via API + rr := request(t, s, "PUT", "/v1/users", `{"username": "ben", "password":"ben"}`, map[string]string{ + "Authorization": util.BasicAuth("phil", "phil"), + }) + require.Equal(t, 200, rr.Code) + + // Create user with tier via API + rr = request(t, s, "PUT", "/v1/users", `{"username": "emma", "password":"emma", "tier": "tier1"}`, map[string]string{ + "Authorization": util.BasicAuth("phil", "phil"), + }) + require.Equal(t, 200, rr.Code) + + // Check users + users, err := s.userManager.Users() + require.Nil(t, err) + require.Equal(t, 4, len(users)) + require.Equal(t, "phil", users[0].Name) + require.Equal(t, "ben", users[1].Name) + require.Equal(t, user.RoleUser, users[1].Role) + require.Nil(t, users[1].Tier) + require.Equal(t, "emma", users[2].Name) + require.Equal(t, user.RoleUser, users[2].Role) + require.Equal(t, "tier1", users[2].Tier.Code) + require.Equal(t, user.Everyone, users[3].Name) + + // Delete user via API + rr = request(t, s, "DELETE", "/v1/users", `{"username": "ben"}`, map[string]string{ + "Authorization": util.BasicAuth("phil", "phil"), + }) + require.Equal(t, 200, rr.Code) +} + +func TestUser_AddRemove_Failures(t *testing.T) { + s := newTestServer(t, newTestConfigWithAuthFile(t)) + defer s.closeDatabases() + + // Create admin + require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleAdmin)) + require.Nil(t, s.userManager.AddUser("ben", "ben", user.RoleUser)) + + // Cannot create user with invalid username + rr := request(t, s, "PUT", "/v1/users", `{"username": "not valid", "password":"ben"}`, map[string]string{ + "Authorization": util.BasicAuth("phil", "phil"), + }) + require.Equal(t, 400, rr.Code) + + // Cannot create user if user already exists + rr = request(t, s, "PUT", "/v1/users", `{"username": "phil", "password":"phil"}`, map[string]string{ + "Authorization": util.BasicAuth("phil", "phil"), + }) + require.Equal(t, 40901, toHTTPError(t, rr.Body.String()).Code) + + // Cannot create user with invalid tier + rr = request(t, s, "PUT", "/v1/users", `{"username": "emma", "password":"emma", "tier": "invalid"}`, map[string]string{ + "Authorization": util.BasicAuth("phil", "phil"), + }) + require.Equal(t, 40030, toHTTPError(t, rr.Body.String()).Code) + + // Cannot delete user as non-admin + rr = request(t, s, "DELETE", "/v1/users", `{"username": "ben"}`, map[string]string{ + "Authorization": util.BasicAuth("ben", "ben"), + }) + require.Equal(t, 401, rr.Code) + + // Delete user via API + rr = request(t, s, "DELETE", "/v1/users", `{"username": "ben"}`, map[string]string{ + "Authorization": util.BasicAuth("phil", "phil"), + }) + require.Equal(t, 200, rr.Code) +} + +func TestAccess_AllowReset(t *testing.T) { + c := newTestConfigWithAuthFile(t) + c.AuthDefault = user.PermissionDenyAll + s := newTestServer(t, c) + defer s.closeDatabases() + + // User and admin + require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleAdmin)) + require.Nil(t, s.userManager.AddUser("ben", "ben", user.RoleUser)) + + // Subscribing not allowed + rr := request(t, s, "GET", "/gold/json?poll=1", "", map[string]string{ + "Authorization": util.BasicAuth("ben", "ben"), + }) + require.Equal(t, 403, rr.Code) + + // Grant access + rr = request(t, s, "POST", "/v1/users/access", `{"username": "ben", "topic":"gold", "permission":"ro"}`, map[string]string{ + "Authorization": util.BasicAuth("phil", "phil"), + }) + require.Equal(t, 200, rr.Code) + + // Now subscribing is allowed + rr = request(t, s, "GET", "/gold/json?poll=1", "", map[string]string{ + "Authorization": util.BasicAuth("ben", "ben"), + }) + require.Equal(t, 200, rr.Code) + + // Reset access + rr = request(t, s, "DELETE", "/v1/users/access", `{"username": "ben", "topic":"gold"}`, map[string]string{ + "Authorization": util.BasicAuth("phil", "phil"), + }) + require.Equal(t, 200, rr.Code) + + // Subscribing not allowed (again) + rr = request(t, s, "GET", "/gold/json?poll=1", "", map[string]string{ + "Authorization": util.BasicAuth("ben", "ben"), + }) + require.Equal(t, 403, rr.Code) +} + +func TestAccess_AllowReset_NonAdminAttempt(t *testing.T) { + c := newTestConfigWithAuthFile(t) + c.AuthDefault = user.PermissionDenyAll + s := newTestServer(t, c) + defer s.closeDatabases() + + // User + require.Nil(t, s.userManager.AddUser("ben", "ben", user.RoleUser)) + + // Grant access fails, because non-admin + rr := request(t, s, "POST", "/v1/users/access", `{"username": "ben", "topic":"gold", "permission":"ro"}`, map[string]string{ + "Authorization": util.BasicAuth("ben", "ben"), + }) + require.Equal(t, 401, rr.Code) +} + +func TestAccess_AllowReset_KillConnection(t *testing.T) { + c := newTestConfigWithAuthFile(t) + c.AuthDefault = user.PermissionDenyAll + s := newTestServer(t, c) + defer s.closeDatabases() + + // User and admin, grant access to "gol*" topics + require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleAdmin)) + require.Nil(t, s.userManager.AddUser("ben", "ben", user.RoleUser)) + require.Nil(t, s.userManager.AllowAccess("ben", "gol*", user.PermissionRead)) // Wildcard! + + start, timeTaken := time.Now(), atomic.Int64{} + go func() { + rr := request(t, s, "GET", "/gold/json", "", map[string]string{ + "Authorization": util.BasicAuth("ben", "ben"), + }) + require.Equal(t, 200, rr.Code) + timeTaken.Store(time.Since(start).Milliseconds()) + }() + time.Sleep(500 * time.Millisecond) + + // Reset access + rr := request(t, s, "DELETE", "/v1/users/access", `{"username": "ben", "topic":"gol*"}`, map[string]string{ + "Authorization": util.BasicAuth("phil", "phil"), + }) + require.Equal(t, 200, rr.Code) + + // Wait for connection to be killed; this will fail if the connection is never killed + waitFor(t, func() bool { + return timeTaken.Load() >= 500 + }) +} diff --git a/server/server_middleware.go b/server/server_middleware.go index facd5698..e0435bb2 100644 --- a/server/server_middleware.go +++ b/server/server_middleware.go @@ -76,6 +76,15 @@ func (s *Server) ensureUser(next handleFunc) handleFunc { }) } +func (s *Server) ensureAdmin(next handleFunc) handleFunc { + return s.ensureUserManager(func(w http.ResponseWriter, r *http.Request, v *visitor) error { + if !v.User().IsAdmin() { + return errHTTPUnauthorized + } + return next(w, r, v) + }) +} + func (s *Server) ensurePaymentsEnabled(next handleFunc) handleFunc { return func(w http.ResponseWriter, r *http.Request, v *visitor) error { if s.config.StripeSecretKey == "" || s.stripe == nil { diff --git a/server/smtp_sender.go b/server/smtp_sender.go index 26a0e0e6..9093687e 100644 --- a/server/smtp_sender.go +++ b/server/smtp_sender.go @@ -4,14 +4,15 @@ import ( _ "embed" // required by go:embed "encoding/json" "fmt" - "heckel.io/ntfy/log" - "heckel.io/ntfy/util" "mime" "net" "net/smtp" "strings" "sync" "time" + + "heckel.io/ntfy/log" + "heckel.io/ntfy/util" ) type mailer interface { @@ -131,31 +132,23 @@ This message was sent by {ip} at {time} via {topicURL}` } var ( - //go:embed "mailer_emoji.json" + //go:embed "mailer_emoji_map.json" emojisJSON string ) -type emoji struct { - Emoji string `json:"emoji"` - Aliases []string `json:"aliases"` -} - func toEmojis(tags []string) (emojisOut []string, tagsOut []string, err error) { - var emojis []emoji - if err = json.Unmarshal([]byte(emojisJSON), &emojis); err != nil { + var emojiMap map[string]string + if err = json.Unmarshal([]byte(emojisJSON), &emojiMap); err != nil { return nil, nil, err } tagsOut = make([]string, 0) emojisOut = make([]string, 0) -nextTag: - for _, t := range tags { // TODO Super inefficient; we should just create a .json file with a map - for _, e := range emojis { - if util.Contains(e.Aliases, t) { - emojisOut = append(emojisOut, e.Emoji) - continue nextTag - } + for _, t := range tags { + if emoji, ok := emojiMap[t]; ok { + emojisOut = append(emojisOut, emoji) + } else { + tagsOut = append(tagsOut, t) } - tagsOut = append(tagsOut, t) } return } diff --git a/server/topic.go b/server/topic.go index 32b0d4b6..5dfafbe3 100644 --- a/server/topic.go +++ b/server/topic.go @@ -141,24 +141,40 @@ func (t *topic) Keepalive() { t.lastAccess = time.Now() } -// CancelSubscribers calls the cancel function for all subscribers, forcing -func (t *topic) CancelSubscribers(exceptUserID string) { +// CancelSubscribersExceptUser calls the cancel function for all subscribers, forcing +func (t *topic) CancelSubscribersExceptUser(exceptUserID string) { t.mu.Lock() defer t.mu.Unlock() for _, s := range t.subscribers { if s.userID != exceptUserID { - log. - Tag(tagSubscribe). - With(t). - Fields(log.Context{ - "user_id": s.userID, - }). - Debug("Canceling subscriber %s", s.userID) - s.cancel() + t.cancelUserSubscriber(s) } } } +// CancelSubscriberUser kills the subscriber with the given user ID +func (t *topic) CancelSubscriberUser(userID string) { + t.mu.RLock() + defer t.mu.RUnlock() + for _, s := range t.subscribers { + if s.userID == userID { + t.cancelUserSubscriber(s) + return + } + } +} + +func (t *topic) cancelUserSubscriber(s *topicSubscriber) { + log. + Tag(tagSubscribe). + With(t). + Fields(log.Context{ + "user_id": s.userID, + }). + Debug("Canceling subscriber with user ID %s", s.userID) + s.cancel() +} + func (t *topic) Context() log.Context { t.mu.RLock() defer t.mu.RUnlock() diff --git a/server/topic_test.go b/server/topic_test.go index 3fed46c2..41a29cfd 100644 --- a/server/topic_test.go +++ b/server/topic_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestTopic_CancelSubscribers(t *testing.T) { +func TestTopic_CancelSubscribersExceptUser(t *testing.T) { t.Parallel() subFn := func(v *visitor, msg *message) error { @@ -27,11 +27,34 @@ func TestTopic_CancelSubscribers(t *testing.T) { to.Subscribe(subFn, "", cancelFn1) to.Subscribe(subFn, "u_phil", cancelFn2) - to.CancelSubscribers("u_phil") + to.CancelSubscribersExceptUser("u_phil") require.True(t, canceled1.Load()) require.False(t, canceled2.Load()) } +func TestTopic_CancelSubscribersUser(t *testing.T) { + t.Parallel() + + subFn := func(v *visitor, msg *message) error { + return nil + } + canceled1 := atomic.Bool{} + cancelFn1 := func() { + canceled1.Store(true) + } + canceled2 := atomic.Bool{} + cancelFn2 := func() { + canceled2.Store(true) + } + to := newTopic("mytopic") + to.Subscribe(subFn, "u_another", cancelFn1) + to.Subscribe(subFn, "u_phil", cancelFn2) + + to.CancelSubscriberUser("u_phil") + require.False(t, canceled1.Load()) + require.True(t, canceled2.Load()) +} + func TestTopic_Keepalive(t *testing.T) { t.Parallel() diff --git a/server/types.go b/server/types.go index d660e717..cbf1df9a 100644 --- a/server/types.go +++ b/server/types.go @@ -244,6 +244,40 @@ type apiStatsResponse struct { MessagesRate float64 `json:"messages_rate"` // Average number of messages per second } +type apiUserAddRequest struct { + Username string `json:"username"` + Password string `json:"password"` + Tier string `json:"tier"` + // Do not add 'role' here. We don't want to add admins via the API. +} + +type apiUserResponse struct { + Username string `json:"username"` + Role string `json:"role"` + Tier string `json:"tier,omitempty"` + Grants []*apiUserGrantResponse `json:"grants,omitempty"` +} + +type apiUserGrantResponse struct { + Topic string `json:"topic"` // This may be a pattern + Permission string `json:"permission"` +} + +type apiUserDeleteRequest struct { + Username string `json:"username"` +} + +type apiAccessAllowRequest struct { + Username string `json:"username"` + Topic string `json:"topic"` // This may be a pattern + Permission string `json:"permission"` +} + +type apiAccessResetRequest struct { + Username string `json:"username"` + Topic string `json:"topic"` +} + type apiAccountCreateRequest struct { Username string `json:"username"` Password string `json:"password"` diff --git a/user/manager.go b/user/manager.go index 7a030951..8a9acf05 100644 --- a/user/manager.go +++ b/user/manager.go @@ -195,6 +195,11 @@ const ( ON CONFLICT (user_id, topic) DO UPDATE SET read=excluded.read, write=excluded.write, owner_user_id=excluded.owner_user_id ` + selectUserAllAccessQuery = ` + SELECT user_id, topic, read, write + FROM user_access + ORDER BY write DESC, read DESC, topic + ` selectUserAccessQuery = ` SELECT topic, read, write FROM user_access @@ -1050,6 +1055,33 @@ func (a *Manager) readUser(rows *sql.Rows) (*User, error) { return user, nil } +// AllGrants returns all user-specific access control entries, mapped to their respective user IDs +func (a *Manager) AllGrants() (map[string][]Grant, error) { + rows, err := a.db.Query(selectUserAllAccessQuery) + if err != nil { + return nil, err + } + defer rows.Close() + grants := make(map[string][]Grant, 0) + for rows.Next() { + var userID, topic string + var read, write bool + if err := rows.Scan(&userID, &topic, &read, &write); err != nil { + return nil, err + } else if err := rows.Err(); err != nil { + return nil, err + } + if _, ok := grants[userID]; !ok { + grants[userID] = make([]Grant, 0) + } + grants[userID] = append(grants[userID], Grant{ + TopicPattern: fromSQLWildcard(topic), + Allow: NewPermission(read, write), + }) + } + return grants, nil +} + // Grants returns all user-specific access control entries func (a *Manager) Grants(username string) ([]Grant, error) { rows, err := a.db.Query(selectUserAccessQuery, username) diff --git a/web/package-lock.json b/web/package-lock.json index 5e1d9b33..f1b4785f 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -3134,9 +3134,9 @@ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, "node_modules/@mui/base": { - "version": "5.0.0-alpha.128", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.128.tgz", - "integrity": "sha512-wub3wxNN+hUp8hzilMlXX3sZrPo75vsy1cXEQpqdTfIFlE9HprP1jlulFiPg5tfPst2OKmygXr2hhmgvAKRrzQ==", + "version": "5.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.0.tgz", + "integrity": "sha512-ap+juKvt8R8n3cBqd/pGtZydQ4v2I/hgJKnvJRGjpSh3RvsvnDHO4rXov8MHQlH6VqpOekwgilFLGxMZjNTucA==", "dependencies": { "@babel/runtime": "^7.21.0", "@emotion/is-prop-valid": "^1.2.0", @@ -3166,9 +3166,9 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.12.3", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.12.3.tgz", - "integrity": "sha512-yiJZ+knaknPHuRKhRk4L6XiwppwkAahVal3LuYpvBH7GkA2g+D9WLEXOEnNYtVFUggyKf6fWGLGnx0iqzkU5YA==", + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.13.0.tgz", + "integrity": "sha512-5nXz2k8Rv2ZjtQY6kXirJVyn2+ODaQuAJmXSJtLDUQDKWp3PFUj6j3bILqR0JGOs9R5ejgwz3crLKsl6GwjwkQ==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui" @@ -3200,17 +3200,17 @@ } }, "node_modules/@mui/material": { - "version": "5.12.3", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.12.3.tgz", - "integrity": "sha512-xNmKlrEN4HsTaKFNLZfc7ie7CXx2YqEeO//hsXZx2p3MGtDdeMr2sV3jC4hsFs57RhQlF79weY7uVvC8xSuVbg==", + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.13.0.tgz", + "integrity": "sha512-ckS+9tCpAzpdJdaTF+btF0b6mF9wbXg/EVKtnoAWYi0UKXoXBAVvEUMNpLGA5xdpCdf+A6fPbVUEHs9TsfU+Yw==", "dependencies": { "@babel/runtime": "^7.21.0", - "@mui/base": "5.0.0-alpha.128", - "@mui/core-downloads-tracker": "^5.12.3", + "@mui/base": "5.0.0-beta.0", + "@mui/core-downloads-tracker": "^5.13.0", "@mui/system": "^5.12.3", "@mui/types": "^7.2.4", "@mui/utils": "^5.12.3", - "@types/react-transition-group": "^4.4.5", + "@types/react-transition-group": "^4.4.6", "clsx": "^1.2.1", "csstype": "^3.1.2", "prop-types": "^15.8.1", @@ -3948,9 +3948,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.34", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.34.tgz", - "integrity": "sha512-fvr49XlCGoUj2Pp730AItckfjat4WNb0lb3kfrLWffd+RLeoGAMsq7UOy04PAPtoL01uKwcp6u8nhzpgpDYr3w==", + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -4016,9 +4016,9 @@ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, "node_modules/@types/node": { - "version": "20.1.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.0.tgz", - "integrity": "sha512-O+z53uwx64xY7D6roOi4+jApDGFg0qn6WHcxe5QeqjMaTezBO/mxdfFXIVAVVyNWKx84OmPB3L8kbVYOTeN34A==" + "version": "20.1.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.4.tgz", + "integrity": "sha512-At4pvmIOki8yuwLtd7BNHl3CiWNbtclUbNtScGx4OHfBd4/oWoJC8KRCIxXwkdndzhxOsPXihrsOoydxBjlE9Q==" }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -4105,9 +4105,9 @@ "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" }, "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==" + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==" }, "node_modules/@types/send": { "version": "0.17.1", @@ -4175,14 +4175,14 @@ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.2.tgz", - "integrity": "sha512-yVrXupeHjRxLDcPKL10sGQ/QlVrA8J5IYOEWVqk0lJaSZP7X5DfnP7Ns3cc74/blmbipQ1htFNVGsHX6wsYm0A==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.5.tgz", + "integrity": "sha512-feA9xbVRWJZor+AnLNAr7A8JRWeZqHUf4T9tlP+TN04b05pFVhO5eN7/O93Y/1OUlLMHKbnJisgDURs/qvtqdg==", "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/type-utils": "5.59.2", - "@typescript-eslint/utils": "5.59.2", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/type-utils": "5.59.5", + "@typescript-eslint/utils": "5.59.5", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -4208,11 +4208,11 @@ } }, "node_modules/@typescript-eslint/experimental-utils": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.59.2.tgz", - "integrity": "sha512-JLw2UImsjHDuVukpA8Nt+UK7JKE/LQAeV3tU5f7wJo2/NNYVwcakzkWjoYzu/2qzWY/Z9c7zojngNDfecNt92g==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.59.5.tgz", + "integrity": "sha512-ArcSSBifznsKNA/p4h2w3Olt/T8AZf3bNglxD8OnuTsSDJbRpjPPmI8qpr6ijyvk1J/T3GMJHwRIluS/Kuz9kA==", "dependencies": { - "@typescript-eslint/utils": "5.59.2" + "@typescript-eslint/utils": "5.59.5" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4226,13 +4226,13 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.2.tgz", - "integrity": "sha512-uq0sKyw6ao1iFOZZGk9F8Nro/8+gfB5ezl1cA06SrqbgJAt0SRoFhb9pXaHvkrxUpZaoLxt8KlovHNk8Gp6/HQ==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.5.tgz", + "integrity": "sha512-NJXQC4MRnF9N9yWqQE2/KLRSOLvrrlZb48NGVfBa+RuPMN6B7ZcK5jZOvhuygv4D64fRKnZI4L4p8+M+rfeQuw==", "dependencies": { - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/typescript-estree": "5.59.2", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.5", "debug": "^4.3.4" }, "engines": { @@ -4252,12 +4252,12 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.2.tgz", - "integrity": "sha512-dB1v7ROySwQWKqQ8rEWcdbTsFjh2G0vn8KUyvTXdPoyzSL6lLGkiXEV5CvpJsEe9xIdKV+8Zqb7wif2issoOFA==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.5.tgz", + "integrity": "sha512-jVecWwnkX6ZgutF+DovbBJirZcAxgxC0EOHYt/niMROf8p4PwxxG32Qdhj/iIQQIuOflLjNkxoXyArkcIP7C3A==", "dependencies": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2" + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/visitor-keys": "5.59.5" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4268,12 +4268,12 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.2.tgz", - "integrity": "sha512-b1LS2phBOsEy/T381bxkkywfQXkV1dWda/z0PhnIy3bC5+rQWQDS7fk9CSpcXBccPY27Z6vBEuaPBCKCgYezyQ==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.5.tgz", + "integrity": "sha512-4eyhS7oGym67/pSxA2mmNq7X164oqDYNnZCUayBwJZIRVvKpBCMBzFnFxjeoDeShjtO6RQBHBuwybuX3POnDqg==", "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.2", - "@typescript-eslint/utils": "5.59.2", + "@typescript-eslint/typescript-estree": "5.59.5", + "@typescript-eslint/utils": "5.59.5", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -4294,9 +4294,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz", - "integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.5.tgz", + "integrity": "sha512-xkfRPHbqSH4Ggx4eHRIO/eGL8XL4Ysb4woL8c87YuAo8Md7AUjyWKa9YMwTL519SyDPrfEgKdewjkxNCVeJW7w==", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -4306,12 +4306,12 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz", - "integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.5.tgz", + "integrity": "sha512-+XXdLN2CZLZcD/mO7mQtJMvCkzRfmODbeSKuMY/yXbGkzvA9rJyDY5qDYNoiz2kP/dmyAxXquL2BvLQLJFPQIg==", "dependencies": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/visitor-keys": "5.59.5", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -4332,16 +4332,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.2.tgz", - "integrity": "sha512-kSuF6/77TZzyGPhGO4uVp+f0SBoYxCDf+lW3GKhtKru/L8k/Hd7NFQxyWUeY7Z/KGB2C6Fe3yf2vVi4V9TsCSQ==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.5.tgz", + "integrity": "sha512-sCEHOiw+RbyTii9c3/qN74hYDPNORb8yWCoPLmB7BIflhplJ65u2PBpdRla12e3SSTJ2erRkPjz7ngLHhUegxA==", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/typescript-estree": "5.59.2", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.5", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -4377,11 +4377,11 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz", - "integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.5.tgz", + "integrity": "sha512-qL+Oz+dbeBRTeyJTIy0eniD3uvqU7x+y1QceBismZ41hd4aBSRh8UAw4pZP0+XzLuPZmx4raNMq/I+59W2lXKA==", "dependencies": { - "@typescript-eslint/types": "5.59.2", + "@typescript-eslint/types": "5.59.5", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -4393,133 +4393,133 @@ } }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.5.tgz", - "integrity": "sha512-LHY/GSAZZRpsNQH+/oHqhRQ5FT7eoULcBqgfyTB5nQHogFnK3/7QoN7dLnwSE/JkUAF0SrRuclT7ODqMFtWxxQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.5.tgz", - "integrity": "sha512-1j1zTIC5EZOtCplMBG/IEwLtUojtwFVwdyVMbL/hwWqbzlQoJsWCOavrdnLkemwNoC/EOwtUFch3fuo+cbcXYQ==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.5.tgz", - "integrity": "sha512-L65bDPmfpY0+yFrsgz8b6LhXmbbs38OnwDCf6NpnMUYqa+ENfE5Dq9E42ny0qz/PdR0LJyq/T5YijPnU8AXEpA==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.5.tgz", - "integrity": "sha512-fDKo1gstwFFSfacIeH5KfwzjykIE6ldh1iH9Y/8YkAZrhmu4TctqYjSh7t0K2VyDSXOZJ1MLhht/k9IvYGcIxg==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.5.tgz", - "integrity": "sha512-DhykHXM0ZABqfIGYNv93A5KKDw/+ywBFnuWybZZWcuzWHfbp21wUfRkbtz7dMGwGgT4iXjWuhRMA2Mzod6W4WA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.5", - "@webassemblyjs/helper-api-error": "1.11.5", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.5.tgz", - "integrity": "sha512-oC4Qa0bNcqnjAowFn7MPCETQgDYytpsfvz4ujZz63Zu/a/v71HeCAAmZsgZ3YVKec3zSPYytG3/PrRCqbtcAvA==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.5.tgz", - "integrity": "sha512-uEoThA1LN2NA+K3B9wDo3yKlBfVtC6rh0i4/6hvbz071E8gTNZD/pT0MsBf7MeD6KbApMSkaAK0XeKyOZC7CIA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", "dependencies": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-buffer": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/wasm-gen": "1.11.5" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.5.tgz", - "integrity": "sha512-37aGq6qVL8A8oPbPrSGMBcp38YZFXcHfiROflJn9jxSdSMMM5dS5P/9e2/TpaJuhE+wFrbukN2WI6Hw9MH5acg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.5.tgz", - "integrity": "sha512-ajqrRSXaTJoPW+xmkfYN6l8VIeNnR4vBOTQO9HzR7IygoCcKWkICbKFbVTNMjMgMREqXEr0+2M6zukzM47ZUfQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.5.tgz", - "integrity": "sha512-WiOhulHKTZU5UPlRl53gHR8OxdGsSOxqfpqWeA2FmcwBMaoEdz6b2x2si3IwC9/fSPLfe8pBMRTHVMk5nlwnFQ==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.5.tgz", - "integrity": "sha512-C0p9D2fAu3Twwqvygvf42iGCQ4av8MFBLiTb+08SZ4cEdwzWx9QeAHDo1E2k+9s/0w1DM40oflJOpkZ8jW4HCQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", "dependencies": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-buffer": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/helper-wasm-section": "1.11.5", - "@webassemblyjs/wasm-gen": "1.11.5", - "@webassemblyjs/wasm-opt": "1.11.5", - "@webassemblyjs/wasm-parser": "1.11.5", - "@webassemblyjs/wast-printer": "1.11.5" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.5.tgz", - "integrity": "sha512-14vteRlRjxLK9eSyYFvw1K8Vv+iPdZU0Aebk3j6oB8TQiQYuO6hj9s4d7qf6f2HJr2khzvNldAFG13CgdkAIfA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", "dependencies": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/ieee754": "1.11.5", - "@webassemblyjs/leb128": "1.11.5", - "@webassemblyjs/utf8": "1.11.5" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.5.tgz", - "integrity": "sha512-tcKwlIXstBQgbKy1MlbDMlXaxpucn42eb17H29rawYLxm5+MsEmgPzeCP8B1Cl69hCice8LeKgZpRUAPtqYPgw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", "dependencies": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-buffer": "1.11.5", - "@webassemblyjs/wasm-gen": "1.11.5", - "@webassemblyjs/wasm-parser": "1.11.5" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.5.tgz", - "integrity": "sha512-SVXUIwsLQlc8srSD7jejsfTU83g7pIGr2YYNb9oHdtldSxaOhvA5xwvIiWIfcX8PlSakgqMXsLpLfbbJ4cBYew==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", "dependencies": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-api-error": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/ieee754": "1.11.5", - "@webassemblyjs/leb128": "1.11.5", - "@webassemblyjs/utf8": "1.11.5" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.5.tgz", - "integrity": "sha512-f7Pq3wvg3GSPUPzR0F6bmI89Hdb+u9WXrSKc4v+N0aV0q6r42WoF92Jp2jEorBEBRoRNXgjp53nBniDXcqZYPA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", "dependencies": { - "@webassemblyjs/ast": "1.11.5", + "@webassemblyjs/ast": "1.11.6", "@xtuc/long": "4.2.2" } }, @@ -4582,9 +4582,9 @@ } }, "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "peerDependencies": { "acorn": "^8" } @@ -5511,9 +5511,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001486", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001486.tgz", - "integrity": "sha512-uv7/gXuHi10Whlj0pp5q/tsK/32J2QSqVRKQhs2j8VsDCjgyruAh/eEXHF822VqO9yT6iZKw3nRwZRSPBE9OQg==", + "version": "1.0.30001487", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001487.tgz", + "integrity": "sha512-83564Z3yWGqXsh2vaH/mhXfEM0wX+NlBCm1jYHOb97TrTWJEmPTccZgeLTPBUUb0PNVo+oomb7wkimZBIERClA==", "funding": [ { "type": "opencollective", @@ -6171,13 +6171,19 @@ } }, "node_modules/cssdb": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.5.4.tgz", - "integrity": "sha512-fGD+J6Jlq+aurfE1VDXlLS4Pt0VtNlu2+YgfGOdMxRyl/HQ9bDiHTwSck1Yz8A97Dt/82izSK6Bp/4nVqacOsg==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.6.0.tgz", + "integrity": "sha512-Nna7rph8V0jC6+JBY4Vk4ndErUmfJfV6NJCaZdurL0omggabiy+QB2HCQtu5c/ACLZ0I7REv7A4QyPIoYzZx0w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + } + ] }, "node_modules/cssesc": { "version": "3.0.0", @@ -6743,9 +6749,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.385", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.385.tgz", - "integrity": "sha512-L9zlje9bIw0h+CwPQumiuVlfMcV4boxRjFIWDcLfFqTZNbkwOExBzfmswytHawObQX4OUhtNv8gIiB21kOurIg==" + "version": "1.4.394", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.394.tgz", + "integrity": "sha512-0IbC2cfr8w5LxTz+nmn2cJTGafsK9iauV2r5A5scfzyovqLrxuLoxOHE5OBobP3oVIggJT+0JfKnw9sm87c8Hw==" }, "node_modules/emittery": { "version": "0.8.1", @@ -6780,9 +6786,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.13.0.tgz", - "integrity": "sha512-eyV8f0y1+bzyfh8xAwW/WTSZpLbjhqc4ne9eGSH4Zo2ejdyiNG9pU6mf9DG8a7+Auk6MFTlNOT4Y2y/9k8GKVg==", + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.0.tgz", + "integrity": "sha512-+DCows0XNwLDcUhbFJPdlQEVnT2zXlCv7hPxemTz86/O+B/hCQ+mb7ydkPKiflpVraqLPCAfu7lDy+hBXueojw==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -7361,9 +7367,9 @@ } }, "node_modules/eslint-plugin-testing-library": { - "version": "5.10.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.10.3.tgz", - "integrity": "sha512-0yhsKFsjHLud5PM+f2dWr9K3rqYzMy4cSHs3lcmFYMa1CdSzRvHGgXvsFarBjZ41gU8jhTdMIkg8jHLxGJqLqw==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.11.0.tgz", + "integrity": "sha512-ELY7Gefo+61OfXKlQeXNIDVVLPcvKTeiQOoMZG9TeuWa7Ln4dUNRv8JdRWBQI9Mbb427XGlVB1aa1QPZxBJM8Q==", "dependencies": { "@typescript-eslint/utils": "^5.58.0" }, @@ -8342,12 +8348,13 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3" }, "funding": { @@ -9551,14 +9558,14 @@ } }, "node_modules/jake": { - "version": "10.8.5", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", - "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "version": "10.8.6", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.6.tgz", + "integrity": "sha512-G43Ub9IYEFfu72sua6rzooi8V8Gz2lkfk48rW20vEWCGizeaEPlKB1Kh8JIA84yQbiAEfqlPmSpGgCKKxH3rDA==", "dependencies": { "async": "^3.2.3", "chalk": "^4.0.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" + "filelist": "^1.0.4", + "minimatch": "^3.1.2" }, "bin": { "jake": "bin/cli.js" @@ -15068,9 +15075,9 @@ } }, "node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -15969,9 +15976,9 @@ } }, "node_modules/terser": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.1.tgz", - "integrity": "sha512-hVl35zClmpisy6oaoKALOpS0rDYLxRFLHhRuDlEGTKey9qHjS1w9GMORjuwIMt70Wan4lwsLYyWDVnWgF+KUEw==", + "version": "5.17.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.3.tgz", + "integrity": "sha512-AudpAZKmZHkG9jueayypz4duuCFJMMNGRMwaPvQKWfxKedh8Z2x3OCoDqIIi1xx5+iwx1u6Au8XQcc9Lke65Yg==", "dependencies": { "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", @@ -16548,9 +16555,9 @@ } }, "node_modules/webpack": { - "version": "5.82.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.82.0.tgz", - "integrity": "sha512-iGNA2fHhnDcV1bONdUu554eZx+XeldsaeQ8T67H6KKHl2nUSwX8Zm7cmzOA46ox/X1ARxf7Bjv8wQ/HsB5fxBg==", + "version": "5.82.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.82.1.tgz", + "integrity": "sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==", "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", @@ -16561,7 +16568,7 @@ "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.13.0", + "enhanced-resolve": "^5.14.0", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", diff --git a/web/src/app/Api.js b/web/src/app/Api.js index 3d20d922..59bd78b8 100644 --- a/web/src/app/Api.js +++ b/web/src/app/Api.js @@ -21,8 +21,11 @@ class Api { const headers = maybeWithAuth({}, user); console.log(`[Api] Polling ${url}`); for await (let line of fetchLinesIterator(url, headers)) { - console.log(`[Api, ${shortUrl}] Received message ${line}`); - messages.push(JSON.parse(line)); + const message = JSON.parse(line); + if (message.id) { + console.log(`[Api, ${shortUrl}] Received message ${line}`); + messages.push(message); + } } return messages; } diff --git a/web/src/components/Account.js b/web/src/components/Account.js index 4c19a291..706ac02a 100644 --- a/web/src/components/Account.js +++ b/web/src/components/Account.js @@ -585,7 +585,7 @@ const Stats = () => { description={t("account_usage_attachment_storage_description", { filesize: formatBytes(account.limits.attachment_file_size), expiry: humanizeDuration(account.limits.attachment_expiry_duration * 1000, { - language: i18n.language, + language: i18n.resolvedLanguage, fallbacks: ["en"] }) })} diff --git a/web/src/components/Preferences.js b/web/src/components/Preferences.js index 0cccc6b4..fc8cb35b 100644 --- a/web/src/components/Preferences.js +++ b/web/src/components/Preferences.js @@ -436,7 +436,7 @@ const Appearance = () => { const Language = () => { const { t, i18n } = useTranslation(); const labelId = "prefLanguage"; - const lang = i18n.language ?? "en"; + const lang = i18n.resolvedLanguage ?? "en"; // Country flags are displayed using emoji. Emoji rendering is handled by platform fonts. // Windows in particular does not yet play nicely with flag emoji so for now, hide flags on Windows. @@ -541,8 +541,8 @@ const ReservationsTable = (props) => { const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const { subscriptions } = useOutletContext(); const localSubscriptions = (subscriptions?.length > 0) - ? Object.assign(...subscriptions.filter(s => s.baseUrl === config.base_url).map(s => ({[s.topic]: s}))) - : []; + ? Object.assign({}, ...subscriptions.filter(s => s.baseUrl === config.base_url).map(s => ({[s.topic]: s}))) + : {}; const handleEditClick = (reservation) => { setDialogKey(prev => prev+1); diff --git a/web/src/components/ReserveDialogs.js b/web/src/components/ReserveDialogs.js index 7a6a044f..e466269a 100644 --- a/web/src/components/ReserveDialogs.js +++ b/web/src/components/ReserveDialogs.js @@ -34,7 +34,7 @@ export const ReserveAddDialog = (props) => { const handleSubmit = async () => { try { await accountApi.upsertReservation(topic, everyone); - console.debug(`[ReserveAddDialog] Added reservation for topic ${t}: ${everyone}`); + console.debug(`[ReserveAddDialog] Added reservation for topic ${topic}: ${everyone}`); } catch (e) { console.log(`[ReserveAddDialog] Error adding topic reservation.`, e); if (e instanceof UnauthorizedError) {