From 49bd6129fff092951a317cc46ac923f3fc8aaef1 Mon Sep 17 00:00:00 2001 From: Michael Manganiello Date: Sat, 13 May 2023 11:33:04 -0300 Subject: [PATCH 01/12] Convert mailer_emoji JSON file to map This fixes a pending TODO comment regarding inefficient tags to emojis mapping, by requiring a full scan over emoji aliases to determine matches. Instead, now the JSON file is a map, with aliases as keys, and emojis as values. The script to convert the file with Python was: ```python import json with open("./mailer_emoji.json", "r", encoding="utf-8") as f: content = json.load(f) emoji_map = {} for emoji in content: for alias in emoji["aliases"]: if alias in emoji_map: print("WARNING: Duplicate alias:", alias) continue emoji_map[alias] = str(emoji["emoji"]) sorted_emoji_map = {k: emoji_map[k] for k in sorted(emoji_map)} with open("./mailer_emoji_map.json", "w", encoding="utf-8") as f: json.dump(sorted_emoji_map, f, indent=4, ensure_ascii=False) ``` --- server/mailer_emoji.json | 1 - server/mailer_emoji_map.json | 1857 ++++++++++++++++++++++++++++++++++ server/smtp_sender.go | 29 +- 3 files changed, 1868 insertions(+), 19 deletions(-) delete mode 100644 server/mailer_emoji.json create mode 100644 server/mailer_emoji_map.json 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/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 } From 625b13280f4c313fb848a7b2aebf2c5dc8715460 Mon Sep 17 00:00:00 2001 From: binwiederhier Date: Sat, 13 May 2023 14:39:31 -0400 Subject: [PATCH 02/12] WIP: Access API --- go.mod | 1 - go.sum | 31 ----------- server/server.go | 29 +++++++++- server/server_access.go | 50 ++++++++++++++++++ server/server_access_test.go | 100 +++++++++++++++++++++++++++++++++++ server/server_account.go | 2 +- server/server_middleware.go | 9 ++++ server/topic.go | 36 +++++++++---- server/topic_test.go | 27 +++++++++- server/types.go | 11 ++++ 10 files changed, 250 insertions(+), 46 deletions(-) create mode 100644 server/server_access.go create mode 100644 server/server_access_test.go diff --git a/go.mod b/go.mod index ca02fff2..e15e9b03 100644 --- a/go.mod +++ b/go.mod @@ -57,7 +57,6 @@ 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 diff --git a/go.sum b/go.sum index 965c4378..9ec101b9 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ 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/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= @@ -71,7 +69,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 +91,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 +116,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 +139,8 @@ 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/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= @@ -190,7 +172,6 @@ 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= @@ -203,10 +184,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ 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 +195,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,8 +225,6 @@ 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/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -276,8 +247,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/server.go b/server/server.go index c0ebc6eb..74a879bf 100644 --- a/server/server.go +++ b/server/server.go @@ -82,6 +82,8 @@ var ( apiHealthPath = "/v1/health" apiStatsPath = "/v1/stats" apiTiersPath = "/v1/tiers" + apiUserPath = "/v1/user" + apiAccessPath = "/v1/access" apiAccountPath = "/v1/account" apiAccountTokenPath = "/v1/account/token" apiAccountPasswordPath = "/v1/account/password" @@ -411,6 +413,10 @@ 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.MethodPost && r.URL.Path == apiAccessPath { + return s.ensureAdmin(s.handleAccessAllow)(w, r, v) + } else if r.Method == http.MethodDelete && r.URL.Path == apiAccessPath { + 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 { @@ -1192,7 +1198,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() @@ -1434,6 +1440,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 { @@ -1442,6 +1449,7 @@ func (s *Server) topicFromPath(path string) (*topic, error) { return s.topicFromID(parts[1]) } +// topicFromID 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 { @@ -1455,6 +1463,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() @@ -1474,6 +1483,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 { @@ -1482,6 +1492,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_access.go b/server/server_access.go new file mode 100644 index 00000000..a747b67d --- /dev/null +++ b/server/server_access.go @@ -0,0 +1,50 @@ +package server + +import ( + "heckel.io/ntfy/user" + "net/http" +) + +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 + } + 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_access_test.go b/server/server_access_test.go new file mode 100644 index 00000000..25ebf5e8 --- /dev/null +++ b/server/server_access_test.go @@ -0,0 +1,100 @@ +package server + +import ( + "github.com/stretchr/testify/require" + "heckel.io/ntfy/user" + "heckel.io/ntfy/util" + "sync/atomic" + "testing" + "time" +) + +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/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/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/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/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_account.go b/server/server_account.go index 1b2c0ce4..73f0792b 100644 --- a/server/server_account.go +++ b/server/server_account.go @@ -444,7 +444,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_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/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 563cafbb..2a2e736e 100644 --- a/server/types.go +++ b/server/types.go @@ -244,6 +244,17 @@ type apiStatsResponse struct { MessagesRate float64 `json:"messages_rate"` // Average number of messages per second } +type apiAccessAllowRequest struct { + Username string `json:"username"` + Topic string `json:"topic"` + 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"` From 97fc287b78521cc0ac0d805eb84c29c54f8b7959 Mon Sep 17 00:00:00 2001 From: binwiederhier Date: Sat, 13 May 2023 22:07:54 -0400 Subject: [PATCH 03/12] User endpoint --- server/errors.go | 2 + server/server.go | 6 +- server/server_access.go | 50 --------- server/server_admin.go | 105 ++++++++++++++++++ ...er_access_test.go => server_admin_test.go} | 0 server/types.go | 11 ++ 6 files changed, 123 insertions(+), 51 deletions(-) delete mode 100644 server/server_access.go create mode 100644 server/server_admin.go rename server/{server_access_test.go => server_admin_test.go} (100%) diff --git a/server/errors.go b/server/errors.go index 8e565197..7812989b 100644 --- a/server/errors.go +++ b/server/errors.go @@ -106,6 +106,8 @@ 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} + errHTTPBadRequestTierInvalid = &errHTTP{40030, http.StatusBadRequest, "invalid request: tier does not exist", "", nil} + errHTTPBadRequestUserNotFound = &errHTTP{40031, http.StatusBadRequest, "invalid request: user does not exist", "", 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/server.go b/server/server.go index 74a879bf..1c2f10c3 100644 --- a/server/server.go +++ b/server/server.go @@ -413,7 +413,11 @@ 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.MethodPost && r.URL.Path == apiAccessPath { + } else if r.Method == http.MethodPut && r.URL.Path == apiUserPath { + return s.ensureAdmin(s.handleUserAdd)(w, r, v) + } else if r.Method == http.MethodDelete && r.URL.Path == apiUserPath { + return s.ensureAdmin(s.handleUserDelete)(w, r, v) + } else if (r.Method == http.MethodPut || r.Method == http.MethodPost) && r.URL.Path == apiAccessPath { return s.ensureAdmin(s.handleAccessAllow)(w, r, v) } else if r.Method == http.MethodDelete && r.URL.Path == apiAccessPath { return s.ensureAdmin(s.handleAccessReset)(w, r, v) diff --git a/server/server_access.go b/server/server_access.go deleted file mode 100644 index a747b67d..00000000 --- a/server/server_access.go +++ /dev/null @@ -1,50 +0,0 @@ -package server - -import ( - "heckel.io/ntfy/user" - "net/http" -) - -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 - } - 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.go b/server/server_admin.go new file mode 100644 index 00000000..ca362785 --- /dev/null +++ b/server/server_admin.go @@ -0,0 +1,105 @@ +package server + +import ( + "heckel.io/ntfy/user" + "net/http" +) + +func (s *Server) handleUserAdd(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) handleUserDelete(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 + } + 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_access_test.go b/server/server_admin_test.go similarity index 100% rename from server/server_access_test.go rename to server/server_admin_test.go diff --git a/server/types.go b/server/types.go index 2a2e736e..8eec8b02 100644 --- a/server/types.go +++ b/server/types.go @@ -244,6 +244,17 @@ 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 apiUserDeleteRequest struct { + Username string `json:"username"` +} + type apiAccessAllowRequest struct { Username string `json:"username"` Topic string `json:"topic"` From 4fa06554382b32365a10dd1bb07f7cfa3d83ba6c Mon Sep 17 00:00:00 2001 From: Hunter Kehoe Date: Sun, 14 May 2023 11:19:49 -0600 Subject: [PATCH 04/12] set attachment filename when download through browser --- server/server.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/server.go b/server/server.go index c0ebc6eb..05b77d57 100644 --- a/server/server.go +++ b/server/server.go @@ -642,6 +642,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 } From 028f3aad14209c0a6bba1ad5ac002978333ae5d9 Mon Sep 17 00:00:00 2001 From: Hunter Kehoe Date: Sun, 14 May 2023 11:23:58 -0600 Subject: [PATCH 05/12] release notes --- docs/releases.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/releases.md b/docs/releases.md index 266882a7..602d2619 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -1185,6 +1185,7 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release * Removed old ntfy website from ntfy entirely (no ticket) * 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) ### ntfy Android app v1.16.1 (UNRELEASED) From 7c69b96fc725d788298bb0b72e1a2122c94930ae Mon Sep 17 00:00:00 2001 From: binwiederhier Date: Sun, 14 May 2023 13:39:31 -0400 Subject: [PATCH 06/12] Release notes --- docs/releases.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/releases.md b/docs/releases.md index 266882a7..8f2fb9a1 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -1183,6 +1183,7 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release **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)) From 4fdbd42f508717907ef0eb6cf93b96f8f0c867a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20W=C3=BChr?= Date: Mon, 15 May 2023 12:14:23 +0200 Subject: [PATCH 07/12] Add woodpecker-ntfy plugin to integrations.md --- docs/integrations.md | 1 + 1 file changed, 1 insertion(+) 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) From f14f0aaa26c8de54abb0062a871bcf364ccf7bee Mon Sep 17 00:00:00 2001 From: binwiederhier Date: Mon, 15 May 2023 10:42:24 -0400 Subject: [PATCH 08/12] Add tests for users, slightly change API a bit --- server/server.go | 20 +++++---- server/server_admin.go | 42 ++++++++++++++++- server/server_admin_test.go | 89 +++++++++++++++++++++++++++++++++++-- server/types.go | 14 +++++- user/manager.go | 32 +++++++++++++ 5 files changed, 181 insertions(+), 16 deletions(-) diff --git a/server/server.go b/server/server.go index b78f4cd1..2e8d20fd 100644 --- a/server/server.go +++ b/server/server.go @@ -82,8 +82,8 @@ var ( apiHealthPath = "/v1/health" apiStatsPath = "/v1/stats" apiTiersPath = "/v1/tiers" - apiUserPath = "/v1/user" - apiAccessPath = "/v1/access" + apiUsersPath = "/v1/users" + apiUsersAccessPath = "/v1/users/access" apiAccountPath = "/v1/account" apiAccountTokenPath = "/v1/account/token" apiAccountPasswordPath = "/v1/account/password" @@ -413,13 +413,15 @@ 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.MethodPut && r.URL.Path == apiUserPath { - return s.ensureAdmin(s.handleUserAdd)(w, r, v) - } else if r.Method == http.MethodDelete && r.URL.Path == apiUserPath { - return s.ensureAdmin(s.handleUserDelete)(w, r, v) - } else if (r.Method == http.MethodPut || r.Method == http.MethodPost) && r.URL.Path == apiAccessPath { + } 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 == apiAccessPath { + } 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) @@ -1456,7 +1458,7 @@ func (s *Server) topicFromPath(path string) (*topic, error) { return s.topicFromID(parts[1]) } -// topicFromID returns the topic from a root path (e.g. /mytopic,mytopic2), creating it if it doesn't exist. +// 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 { diff --git a/server/server_admin.go b/server/server_admin.go index ca362785..9380a5ff 100644 --- a/server/server_admin.go +++ b/server/server_admin.go @@ -5,7 +5,39 @@ import ( "net/http" ) -func (s *Server) handleUserAdd(w http.ResponseWriter, r *http.Request, v *visitor) error { +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 @@ -38,7 +70,7 @@ func (s *Server) handleUserAdd(w http.ResponseWriter, r *http.Request, v *visito return s.writeJSON(w, newSuccessResponse()) } -func (s *Server) handleUserDelete(w http.ResponseWriter, r *http.Request, v *visitor) error { +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 @@ -65,6 +97,12 @@ func (s *Server) handleAccessAllow(w http.ResponseWriter, r *http.Request, v *vi 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 diff --git a/server/server_admin_test.go b/server/server_admin_test.go index 25ebf5e8..1513ea40 100644 --- a/server/server_admin_test.go +++ b/server/server_admin_test.go @@ -9,6 +9,87 @@ import ( "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 @@ -26,7 +107,7 @@ func TestAccess_AllowReset(t *testing.T) { require.Equal(t, 403, rr.Code) // Grant access - rr = request(t, s, "POST", "/v1/access", `{"username": "ben", "topic":"gold", "permission":"ro"}`, map[string]string{ + 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) @@ -38,7 +119,7 @@ func TestAccess_AllowReset(t *testing.T) { require.Equal(t, 200, rr.Code) // Reset access - rr = request(t, s, "DELETE", "/v1/access", `{"username": "ben", "topic":"gold"}`, map[string]string{ + 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) @@ -60,7 +141,7 @@ func TestAccess_AllowReset_NonAdminAttempt(t *testing.T) { require.Nil(t, s.userManager.AddUser("ben", "ben", user.RoleUser)) // Grant access fails, because non-admin - rr := request(t, s, "POST", "/v1/access", `{"username": "ben", "topic":"gold", "permission":"ro"}`, map[string]string{ + 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) @@ -88,7 +169,7 @@ func TestAccess_AllowReset_KillConnection(t *testing.T) { time.Sleep(500 * time.Millisecond) // Reset access - rr := request(t, s, "DELETE", "/v1/access", `{"username": "ben", "topic":"gol*"}`, map[string]string{ + 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) diff --git a/server/types.go b/server/types.go index 8eec8b02..962f7dba 100644 --- a/server/types.go +++ b/server/types.go @@ -251,13 +251,25 @@ type apiUserAddRequest struct { // 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"` + Topic string `json:"topic"` // This may be a pattern Permission string `json:"permission"` } diff --git a/user/manager.go b/user/manager.go index b2898ae8..08c36db1 100644 --- a/user/manager.go +++ b/user/manager.go @@ -185,6 +185,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 @@ -966,6 +971,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) From e17cf676f4e6fcae1702811579960cf000cc1dc9 Mon Sep 17 00:00:00 2001 From: binwiederhier Date: Mon, 15 May 2023 10:58:37 -0400 Subject: [PATCH 09/12] Release notes --- docs/releases.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/releases.md b/docs/releases.md index e6f39494..38f7cf25 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -1180,6 +1180,10 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release ### ntfy server v2.5.0 (UNRELEASED) +**Features:** + +* 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) From 6e21bb742f2ba5b20bfe4f11cb7bb507e24a722d Mon Sep 17 00:00:00 2001 From: binwiederhier Date: Mon, 15 May 2023 11:03:19 -0400 Subject: [PATCH 10/12] Bump deps --- go.mod | 18 +- go.sum | 18 ++ web/package-lock.json | 371 +++++++++++++++++++++--------------------- 3 files changed, 216 insertions(+), 191 deletions(-) diff --git a/go.mod b/go.mod index e15e9b03..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 @@ -61,7 +61,7 @@ require ( 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 9ec101b9..ccb1ae4d 100644 --- a/go.sum +++ b/go.sum @@ -2,16 +2,24 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 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= @@ -141,6 +149,8 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 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/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= @@ -155,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= @@ -176,10 +188,14 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx 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= @@ -227,6 +243,8 @@ golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3j golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= 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= 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", From ed0c1abd2f4cc1c3b0cce2475dff20855301d99e Mon Sep 17 00:00:00 2001 From: binwiederhier Date: Mon, 15 May 2023 13:37:30 -0400 Subject: [PATCH 11/12] Tiny web app fixes --- web/src/app/Api.js | 7 +++++-- web/src/components/Preferences.js | 4 ++-- web/src/components/ReserveDialogs.js | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) 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/Preferences.js b/web/src/components/Preferences.js index 0cccc6b4..ec1c79da 100644 --- a/web/src/components/Preferences.js +++ b/web/src/components/Preferences.js @@ -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) { From f998d4d2adc4f582035eb37cf0537eb2d0b1e272 Mon Sep 17 00:00:00 2001 From: binwiederhier Date: Mon, 15 May 2023 19:49:34 -0400 Subject: [PATCH 12/12] Fix web app i18n issue in account preferences --- docs/releases.md | 3 ++- web/src/components/Account.js | 2 +- web/src/components/Preferences.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/releases.md b/docs/releases.md index 38f7cf25..440b950a 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -1190,7 +1190,8 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release * 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) +* 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/web/src/components/Account.js b/web/src/components/Account.js index e5b60077..0e37aa3e 100644 --- a/web/src/components/Account.js +++ b/web/src/components/Account.js @@ -390,7 +390,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 ec1c79da..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.