diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..24ee5b1 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/README.md b/README.md new file mode 100644 index 0000000..d67ab46 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Comming Soon diff --git a/config/assets/emoji.json b/config/assets/emoji.json new file mode 100644 index 0000000..fa174ff --- /dev/null +++ b/config/assets/emoji.json @@ -0,0 +1,15509 @@ +{ + "๐Ÿ˜€": { + "name": "grinning face", + "slug": "grinning_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ˜ƒ": { + "name": "grinning face with big eyes", + "slug": "grinning_face_with_big_eyes", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜„": { + "name": "grinning face with smiling eyes", + "slug": "grinning_face_with_smiling_eyes", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜": { + "name": "beaming face with smiling eyes", + "slug": "beaming_face_with_smiling_eyes", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜†": { + "name": "grinning squinting face", + "slug": "grinning_squinting_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜…": { + "name": "grinning face with sweat", + "slug": "grinning_face_with_sweat", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿคฃ": { + "name": "rolling on the floor laughing", + "slug": "rolling_on_the_floor_laughing", + "group": "Smileys & Emotion", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿ˜‚": { + "name": "face with tears of joy", + "slug": "face_with_tears_of_joy", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ™‚": { + "name": "slightly smiling face", + "slug": "slightly_smiling_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ™ƒ": { + "name": "upside-down face", + "slug": "upside_down_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿซ ": { + "name": "melting face", + "slug": "melting_face", + "group": "Smileys & Emotion", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿ˜‰": { + "name": "winking face", + "slug": "winking_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜Š": { + "name": "smiling face with smiling eyes", + "slug": "smiling_face_with_smiling_eyes", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜‡": { + "name": "smiling face with halo", + "slug": "smiling_face_with_halo", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿฅฐ": { + "name": "smiling face with hearts", + "slug": "smiling_face_with_hearts", + "group": "Smileys & Emotion", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿ˜": { + "name": "smiling face with heart-eyes", + "slug": "smiling_face_with_heart_eyes", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿคฉ": { + "name": "star-struck", + "slug": "star_struck", + "group": "Smileys & Emotion", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿ˜˜": { + "name": "face blowing a kiss", + "slug": "face_blowing_a_kiss", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜—": { + "name": "kissing face", + "slug": "kissing_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "โ˜บ๏ธ": { + "name": "smiling face", + "slug": "smiling_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜š": { + "name": "kissing face with closed eyes", + "slug": "kissing_face_with_closed_eyes", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜™": { + "name": "kissing face with smiling eyes", + "slug": "kissing_face_with_smiling_eyes", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿฅฒ": { + "name": "smiling face with tear", + "slug": "smiling_face_with_tear", + "group": "Smileys & Emotion", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿ˜‹": { + "name": "face savoring food", + "slug": "face_savoring_food", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜›": { + "name": "face with tongue", + "slug": "face_with_tongue", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ˜œ": { + "name": "winking face with tongue", + "slug": "winking_face_with_tongue", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿคช": { + "name": "zany face", + "slug": "zany_face", + "group": "Smileys & Emotion", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿ˜": { + "name": "squinting face with tongue", + "slug": "squinting_face_with_tongue", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿค‘": { + "name": "money-mouth face", + "slug": "money_mouth_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿค—": { + "name": "smiling face with open hands", + "slug": "smiling_face_with_open_hands", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿคญ": { + "name": "face with hand over mouth", + "slug": "face_with_hand_over_mouth", + "group": "Smileys & Emotion", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿซข": { + "name": "face with open eyes and hand over mouth", + "slug": "face_with_open_eyes_and_hand_over_mouth", + "group": "Smileys & Emotion", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿซฃ": { + "name": "face with peeking eye", + "slug": "face_with_peeking_eye", + "group": "Smileys & Emotion", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿคซ": { + "name": "shushing face", + "slug": "shushing_face", + "group": "Smileys & Emotion", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿค”": { + "name": "thinking face", + "slug": "thinking_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿซก": { + "name": "saluting face", + "slug": "saluting_face", + "group": "Smileys & Emotion", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿค": { + "name": "zipper-mouth face", + "slug": "zipper_mouth_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿคจ": { + "name": "face with raised eyebrow", + "slug": "face_with_raised_eyebrow", + "group": "Smileys & Emotion", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿ˜": { + "name": "neutral face", + "slug": "neutral_face", + "group": "Smileys & Emotion", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ˜‘": { + "name": "expressionless face", + "slug": "expressionless_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ˜ถ": { + "name": "face without mouth", + "slug": "face_without_mouth", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿซฅ": { + "name": "dotted line face", + "slug": "dotted_line_face", + "group": "Smileys & Emotion", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿ˜ถโ€๐ŸŒซ๏ธ": { + "name": "face in clouds", + "slug": "face_in_clouds", + "group": "Smileys & Emotion", + "emoji_version": "13.1", + "unicode_version": "13.1", + "skin_tone_support": false + }, + "๐Ÿ˜": { + "name": "smirking face", + "slug": "smirking_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜’": { + "name": "unamused face", + "slug": "unamused_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ™„": { + "name": "face with rolling eyes", + "slug": "face_with_rolling_eyes", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ˜ฌ": { + "name": "grimacing face", + "slug": "grimacing_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ˜ฎโ€๐Ÿ’จ": { + "name": "face exhaling", + "slug": "face_exhaling", + "group": "Smileys & Emotion", + "emoji_version": "13.1", + "unicode_version": "13.1", + "skin_tone_support": false + }, + "๐Ÿคฅ": { + "name": "lying face", + "slug": "lying_face", + "group": "Smileys & Emotion", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿซจ": { + "name": "shaking face", + "slug": "shaking_face", + "group": "Smileys & Emotion", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐Ÿ™‚โ€โ†”๏ธ": { + "name": "head shaking horizontally", + "slug": "head_shaking_horizontally", + "group": "Smileys & Emotion", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": false + }, + "๐Ÿ™‚โ€โ†•๏ธ": { + "name": "head shaking vertically", + "slug": "head_shaking_vertically", + "group": "Smileys & Emotion", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": false + }, + "๐Ÿ˜Œ": { + "name": "relieved face", + "slug": "relieved_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜”": { + "name": "pensive face", + "slug": "pensive_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ช": { + "name": "sleepy face", + "slug": "sleepy_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿคค": { + "name": "drooling face", + "slug": "drooling_face", + "group": "Smileys & Emotion", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿ˜ด": { + "name": "sleeping face", + "slug": "sleeping_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ˜ท": { + "name": "face with medical mask", + "slug": "face_with_medical_mask", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿค’": { + "name": "face with thermometer", + "slug": "face_with_thermometer", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿค•": { + "name": "face with head-bandage", + "slug": "face_with_head_bandage", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿคข": { + "name": "nauseated face", + "slug": "nauseated_face", + "group": "Smileys & Emotion", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿคฎ": { + "name": "face vomiting", + "slug": "face_vomiting", + "group": "Smileys & Emotion", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿคง": { + "name": "sneezing face", + "slug": "sneezing_face", + "group": "Smileys & Emotion", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฅต": { + "name": "hot face", + "slug": "hot_face", + "group": "Smileys & Emotion", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฅถ": { + "name": "cold face", + "slug": "cold_face", + "group": "Smileys & Emotion", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฅด": { + "name": "woozy face", + "slug": "woozy_face", + "group": "Smileys & Emotion", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿ˜ต": { + "name": "face with crossed-out eyes", + "slug": "face_with_crossed_out_eyes", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ตโ€๐Ÿ’ซ": { + "name": "face with spiral eyes", + "slug": "face_with_spiral_eyes", + "group": "Smileys & Emotion", + "emoji_version": "13.1", + "unicode_version": "13.1", + "skin_tone_support": false + }, + "๐Ÿคฏ": { + "name": "exploding head", + "slug": "exploding_head", + "group": "Smileys & Emotion", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿค ": { + "name": "cowboy hat face", + "slug": "cowboy_hat_face", + "group": "Smileys & Emotion", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฅณ": { + "name": "partying face", + "slug": "partying_face", + "group": "Smileys & Emotion", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฅธ": { + "name": "disguised face", + "slug": "disguised_face", + "group": "Smileys & Emotion", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿ˜Ž": { + "name": "smiling face with sunglasses", + "slug": "smiling_face_with_sunglasses", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿค“": { + "name": "nerd face", + "slug": "nerd_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿง": { + "name": "face with monocle", + "slug": "face_with_monocle", + "group": "Smileys & Emotion", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿ˜•": { + "name": "confused face", + "slug": "confused_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿซค": { + "name": "face with diagonal mouth", + "slug": "face_with_diagonal_mouth", + "group": "Smileys & Emotion", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿ˜Ÿ": { + "name": "worried face", + "slug": "worried_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ™": { + "name": "slightly frowning face", + "slug": "slightly_frowning_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "โ˜น๏ธ": { + "name": "frowning face", + "slug": "frowning_face", + "group": "Smileys & Emotion", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ˜ฎ": { + "name": "face with open mouth", + "slug": "face_with_open_mouth", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ˜ฏ": { + "name": "hushed face", + "slug": "hushed_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ˜ฒ": { + "name": "astonished face", + "slug": "astonished_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ณ": { + "name": "flushed face", + "slug": "flushed_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅบ": { + "name": "pleading face", + "slug": "pleading_face", + "group": "Smileys & Emotion", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฅน": { + "name": "face holding back tears", + "slug": "face_holding_back_tears", + "group": "Smileys & Emotion", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿ˜ฆ": { + "name": "frowning face with open mouth", + "slug": "frowning_face_with_open_mouth", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ˜ง": { + "name": "anguished face", + "slug": "anguished_face", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ˜จ": { + "name": "fearful face", + "slug": "fearful_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ฐ": { + "name": "anxious face with sweat", + "slug": "anxious_face_with_sweat", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ฅ": { + "name": "sad but relieved face", + "slug": "sad_but_relieved_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ข": { + "name": "crying face", + "slug": "crying_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ญ": { + "name": "loudly crying face", + "slug": "loudly_crying_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ฑ": { + "name": "face screaming in fear", + "slug": "face_screaming_in_fear", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜–": { + "name": "confounded face", + "slug": "confounded_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ฃ": { + "name": "persevering face", + "slug": "persevering_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ž": { + "name": "disappointed face", + "slug": "disappointed_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜“": { + "name": "downcast face with sweat", + "slug": "downcast_face_with_sweat", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ฉ": { + "name": "weary face", + "slug": "weary_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ซ": { + "name": "tired face", + "slug": "tired_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅฑ": { + "name": "yawning face", + "slug": "yawning_face", + "group": "Smileys & Emotion", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿ˜ค": { + "name": "face with steam from nose", + "slug": "face_with_steam_from_nose", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ก": { + "name": "enraged face", + "slug": "enraged_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ ": { + "name": "angry face", + "slug": "angry_face", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿคฌ": { + "name": "face with symbols on mouth", + "slug": "face_with_symbols_on_mouth", + "group": "Smileys & Emotion", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿ˜ˆ": { + "name": "smiling face with horns", + "slug": "smiling_face_with_horns", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ‘ฟ": { + "name": "angry face with horns", + "slug": "angry_face_with_horns", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’€": { + "name": "skull", + "slug": "skull", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ˜ ๏ธ": { + "name": "skull and crossbones", + "slug": "skull_and_crossbones", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ’ฉ": { + "name": "pile of poo", + "slug": "pile_of_poo", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿคก": { + "name": "clown face", + "slug": "clown_face", + "group": "Smileys & Emotion", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿ‘น": { + "name": "ogre", + "slug": "ogre", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘บ": { + "name": "goblin", + "slug": "goblin", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘ป": { + "name": "ghost", + "slug": "ghost", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘ฝ": { + "name": "alien", + "slug": "alien", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘พ": { + "name": "alien monster", + "slug": "alien_monster", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿค–": { + "name": "robot", + "slug": "robot", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ˜บ": { + "name": "grinning cat", + "slug": "grinning_cat", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ธ": { + "name": "grinning cat with smiling eyes", + "slug": "grinning_cat_with_smiling_eyes", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜น": { + "name": "cat with tears of joy", + "slug": "cat_with_tears_of_joy", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ป": { + "name": "smiling cat with heart-eyes", + "slug": "smiling_cat_with_heart_eyes", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ผ": { + "name": "cat with wry smile", + "slug": "cat_with_wry_smile", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ฝ": { + "name": "kissing cat", + "slug": "kissing_cat", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ™€": { + "name": "weary cat", + "slug": "weary_cat", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜ฟ": { + "name": "crying cat", + "slug": "crying_cat", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜พ": { + "name": "pouting cat", + "slug": "pouting_cat", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ™ˆ": { + "name": "see-no-evil monkey", + "slug": "see_no_evil_monkey", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ™‰": { + "name": "hear-no-evil monkey", + "slug": "hear_no_evil_monkey", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ™Š": { + "name": "speak-no-evil monkey", + "slug": "speak_no_evil_monkey", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’Œ": { + "name": "love letter", + "slug": "love_letter", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’˜": { + "name": "heart with arrow", + "slug": "heart_with_arrow", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’": { + "name": "heart with ribbon", + "slug": "heart_with_ribbon", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’–": { + "name": "sparkling heart", + "slug": "sparkling_heart", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’—": { + "name": "growing heart", + "slug": "growing_heart", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’“": { + "name": "beating heart", + "slug": "beating_heart", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ž": { + "name": "revolving hearts", + "slug": "revolving_hearts", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’•": { + "name": "two hearts", + "slug": "two_hearts", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’Ÿ": { + "name": "heart decoration", + "slug": "heart_decoration", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โฃ๏ธ": { + "name": "heart exclamation", + "slug": "heart_exclamation", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ’”": { + "name": "broken heart", + "slug": "broken_heart", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โค๏ธโ€๐Ÿ”ฅ": { + "name": "heart on fire", + "slug": "heart_on_fire", + "group": "Smileys & Emotion", + "emoji_version": "13.1", + "unicode_version": "13.1", + "skin_tone_support": false + }, + "โค๏ธโ€๐Ÿฉน": { + "name": "mending heart", + "slug": "mending_heart", + "group": "Smileys & Emotion", + "emoji_version": "13.1", + "unicode_version": "13.1", + "skin_tone_support": false + }, + "โค๏ธ": { + "name": "red heart", + "slug": "red_heart", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฉท": { + "name": "pink heart", + "slug": "pink_heart", + "group": "Smileys & Emotion", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐Ÿงก": { + "name": "orange heart", + "slug": "orange_heart", + "group": "Smileys & Emotion", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿ’›": { + "name": "yellow heart", + "slug": "yellow_heart", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’š": { + "name": "green heart", + "slug": "green_heart", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’™": { + "name": "blue heart", + "slug": "blue_heart", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฉต": { + "name": "light blue heart", + "slug": "light_blue_heart", + "group": "Smileys & Emotion", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐Ÿ’œ": { + "name": "purple heart", + "slug": "purple_heart", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸคŽ": { + "name": "brown heart", + "slug": "brown_heart", + "group": "Smileys & Emotion", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿ–ค": { + "name": "black heart", + "slug": "black_heart", + "group": "Smileys & Emotion", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฉถ": { + "name": "grey heart", + "slug": "grey_heart", + "group": "Smileys & Emotion", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐Ÿค": { + "name": "white heart", + "slug": "white_heart", + "group": "Smileys & Emotion", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿ’‹": { + "name": "kiss mark", + "slug": "kiss_mark", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ฏ": { + "name": "hundred points", + "slug": "hundred_points", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ข": { + "name": "anger symbol", + "slug": "anger_symbol", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ฅ": { + "name": "collision", + "slug": "collision", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ซ": { + "name": "dizzy", + "slug": "dizzy", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ฆ": { + "name": "sweat droplets", + "slug": "sweat_droplets", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’จ": { + "name": "dashing away", + "slug": "dashing_away", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•ณ๏ธ": { + "name": "hole", + "slug": "hole", + "group": "Smileys & Emotion", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ’ฌ": { + "name": "speech balloon", + "slug": "speech_balloon", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘๏ธโ€๐Ÿ—จ๏ธ": { + "name": "eye in speech bubble", + "slug": "eye_in_speech_bubble", + "group": "Smileys & Emotion", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ—จ๏ธ": { + "name": "left speech bubble", + "slug": "left_speech_bubble", + "group": "Smileys & Emotion", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ—ฏ๏ธ": { + "name": "right anger bubble", + "slug": "right_anger_bubble", + "group": "Smileys & Emotion", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ’ญ": { + "name": "thought balloon", + "slug": "thought_balloon", + "group": "Smileys & Emotion", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ’ค": { + "name": "ZZZ", + "slug": "zzz", + "group": "Smileys & Emotion", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘‹": { + "name": "waving hand", + "slug": "waving_hand", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿคš": { + "name": "raised back of hand", + "slug": "raised_back_of_hand", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿ–๏ธ": { + "name": "hand with fingers splayed", + "slug": "hand_with_fingers_splayed", + "group": "People & Body", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "โœ‹": { + "name": "raised hand", + "slug": "raised_hand", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ––": { + "name": "vulcan salute", + "slug": "vulcan_salute", + "group": "People & Body", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿซฑ": { + "name": "rightwards hand", + "slug": "rightwards_hand", + "group": "People & Body", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "14.0" + }, + "๐Ÿซฒ": { + "name": "leftwards hand", + "slug": "leftwards_hand", + "group": "People & Body", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "14.0" + }, + "๐Ÿซณ": { + "name": "palm down hand", + "slug": "palm_down_hand", + "group": "People & Body", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "14.0" + }, + "๐Ÿซด": { + "name": "palm up hand", + "slug": "palm_up_hand", + "group": "People & Body", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "14.0" + }, + "๐Ÿซท": { + "name": "leftwards pushing hand", + "slug": "leftwards_pushing_hand", + "group": "People & Body", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.0" + }, + "๐Ÿซธ": { + "name": "rightwards pushing hand", + "slug": "rightwards_pushing_hand", + "group": "People & Body", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.0" + }, + "๐Ÿ‘Œ": { + "name": "OK hand", + "slug": "ok_hand", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐ŸคŒ": { + "name": "pinched fingers", + "slug": "pinched_fingers", + "group": "People & Body", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.0" + }, + "๐Ÿค": { + "name": "pinching hand", + "slug": "pinching_hand", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "โœŒ๏ธ": { + "name": "victory hand", + "slug": "victory_hand", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿคž": { + "name": "crossed fingers", + "slug": "crossed_fingers", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿซฐ": { + "name": "hand with index finger and thumb crossed", + "slug": "hand_with_index_finger_and_thumb_crossed", + "group": "People & Body", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "14.0" + }, + "๐ŸคŸ": { + "name": "love-you gesture", + "slug": "love_you_gesture", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿค˜": { + "name": "sign of the horns", + "slug": "sign_of_the_horns", + "group": "People & Body", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿค™": { + "name": "call me hand", + "slug": "call_me_hand", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿ‘ˆ": { + "name": "backhand index pointing left", + "slug": "backhand_index_pointing_left", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ‘‰": { + "name": "backhand index pointing right", + "slug": "backhand_index_pointing_right", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ‘†": { + "name": "backhand index pointing up", + "slug": "backhand_index_pointing_up", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ–•": { + "name": "middle finger", + "slug": "middle_finger", + "group": "People & Body", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ‘‡": { + "name": "backhand index pointing down", + "slug": "backhand_index_pointing_down", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "โ˜๏ธ": { + "name": "index pointing up", + "slug": "index_pointing_up", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿซต": { + "name": "index pointing at the viewer", + "slug": "index_pointing_at_the_viewer", + "group": "People & Body", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "14.0" + }, + "๐Ÿ‘": { + "name": "thumbs up", + "slug": "thumbs_up", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ‘Ž": { + "name": "thumbs down", + "slug": "thumbs_down", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "โœŠ": { + "name": "raised fist", + "slug": "raised_fist", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ‘Š": { + "name": "oncoming fist", + "slug": "oncoming_fist", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿค›": { + "name": "left-facing fist", + "slug": "left_facing_fist", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿคœ": { + "name": "right-facing fist", + "slug": "right_facing_fist", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿ‘": { + "name": "clapping hands", + "slug": "clapping_hands", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ™Œ": { + "name": "raising hands", + "slug": "raising_hands", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿซถ": { + "name": "heart hands", + "slug": "heart_hands", + "group": "People & Body", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "14.0" + }, + "๐Ÿ‘": { + "name": "open hands", + "slug": "open_hands", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿคฒ": { + "name": "palms up together", + "slug": "palms_up_together", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿค": { + "name": "handshake", + "slug": "handshake", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "14.0" + }, + "๐Ÿ™": { + "name": "folded hands", + "slug": "folded_hands", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "โœ๏ธ": { + "name": "writing hand", + "slug": "writing_hand", + "group": "People & Body", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ’…": { + "name": "nail polish", + "slug": "nail_polish", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿคณ": { + "name": "selfie", + "slug": "selfie", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿ’ช": { + "name": "flexed biceps", + "slug": "flexed_biceps", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿฆพ": { + "name": "mechanical arm", + "slug": "mechanical_arm", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฆฟ": { + "name": "mechanical leg", + "slug": "mechanical_leg", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฆต": { + "name": "leg", + "slug": "leg", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿฆถ": { + "name": "foot", + "slug": "foot", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿ‘‚": { + "name": "ear", + "slug": "ear", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿฆป": { + "name": "ear with hearing aid", + "slug": "ear_with_hearing_aid", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿ‘ƒ": { + "name": "nose", + "slug": "nose", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿง ": { + "name": "brain", + "slug": "brain", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿซ€": { + "name": "anatomical heart", + "slug": "anatomical_heart", + "group": "People & Body", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿซ": { + "name": "lungs", + "slug": "lungs", + "group": "People & Body", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿฆท": { + "name": "tooth", + "slug": "tooth", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฆด": { + "name": "bone", + "slug": "bone", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿ‘€": { + "name": "eyes", + "slug": "eyes", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘๏ธ": { + "name": "eye", + "slug": "eye", + "group": "People & Body", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ‘…": { + "name": "tongue", + "slug": "tongue", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘„": { + "name": "mouth", + "slug": "mouth", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿซฆ": { + "name": "biting lip", + "slug": "biting_lip", + "group": "People & Body", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿ‘ถ": { + "name": "baby", + "slug": "baby", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿง’": { + "name": "child", + "slug": "child", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿ‘ฆ": { + "name": "boy", + "slug": "boy", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ‘ง": { + "name": "girl", + "slug": "girl", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿง‘": { + "name": "person", + "slug": "person", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿ‘ฑ": { + "name": "person blond hair", + "slug": "person_blond_hair", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ‘จ": { + "name": "man", + "slug": "man", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿง”": { + "name": "person beard", + "slug": "person_beard", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿง”โ€โ™‚๏ธ": { + "name": "man beard", + "slug": "man_beard", + "group": "People & Body", + "emoji_version": "13.1", + "unicode_version": "13.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.1" + }, + "๐Ÿง”โ€โ™€๏ธ": { + "name": "woman beard", + "slug": "woman_beard", + "group": "People & Body", + "emoji_version": "13.1", + "unicode_version": "13.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.1" + }, + "๐Ÿ‘จโ€๐Ÿฆฐ": { + "name": "man red hair", + "slug": "man_red_hair", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿ‘จโ€๐Ÿฆฑ": { + "name": "man curly hair", + "slug": "man_curly_hair", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿ‘จโ€๐Ÿฆณ": { + "name": "man white hair", + "slug": "man_white_hair", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿ‘จโ€๐Ÿฆฒ": { + "name": "man bald", + "slug": "man_bald", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿ‘ฉ": { + "name": "woman", + "slug": "woman", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ‘ฉโ€๐Ÿฆฐ": { + "name": "woman red hair", + "slug": "woman_red_hair", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿง‘โ€๐Ÿฆฐ": { + "name": "person red hair", + "slug": "person_red_hair", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘ฉโ€๐Ÿฆฑ": { + "name": "woman curly hair", + "slug": "woman_curly_hair", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿง‘โ€๐Ÿฆฑ": { + "name": "person curly hair", + "slug": "person_curly_hair", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘ฉโ€๐Ÿฆณ": { + "name": "woman white hair", + "slug": "woman_white_hair", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿง‘โ€๐Ÿฆณ": { + "name": "person white hair", + "slug": "person_white_hair", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘ฉโ€๐Ÿฆฒ": { + "name": "woman bald", + "slug": "woman_bald", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿง‘โ€๐Ÿฆฒ": { + "name": "person bald", + "slug": "person_bald", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘ฑโ€โ™€๏ธ": { + "name": "woman blond hair", + "slug": "woman_blond_hair", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฑโ€โ™‚๏ธ": { + "name": "man blond hair", + "slug": "man_blond_hair", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง“": { + "name": "older person", + "slug": "older_person", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿ‘ด": { + "name": "old man", + "slug": "old_man", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ‘ต": { + "name": "old woman", + "slug": "old_woman", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ™": { + "name": "person frowning", + "slug": "person_frowning", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ™โ€โ™‚๏ธ": { + "name": "man frowning", + "slug": "man_frowning", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ™โ€โ™€๏ธ": { + "name": "woman frowning", + "slug": "woman_frowning", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ™Ž": { + "name": "person pouting", + "slug": "person_pouting", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ™Žโ€โ™‚๏ธ": { + "name": "man pouting", + "slug": "man_pouting", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ™Žโ€โ™€๏ธ": { + "name": "woman pouting", + "slug": "woman_pouting", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ™…": { + "name": "person gesturing NO", + "slug": "person_gesturing_no", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ™…โ€โ™‚๏ธ": { + "name": "man gesturing NO", + "slug": "man_gesturing_no", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ™…โ€โ™€๏ธ": { + "name": "woman gesturing NO", + "slug": "woman_gesturing_no", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ™†": { + "name": "person gesturing OK", + "slug": "person_gesturing_ok", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ™†โ€โ™‚๏ธ": { + "name": "man gesturing OK", + "slug": "man_gesturing_ok", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ™†โ€โ™€๏ธ": { + "name": "woman gesturing OK", + "slug": "woman_gesturing_ok", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ’": { + "name": "person tipping hand", + "slug": "person_tipping_hand", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ’โ€โ™‚๏ธ": { + "name": "man tipping hand", + "slug": "man_tipping_hand", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ’โ€โ™€๏ธ": { + "name": "woman tipping hand", + "slug": "woman_tipping_hand", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ™‹": { + "name": "person raising hand", + "slug": "person_raising_hand", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ™‹โ€โ™‚๏ธ": { + "name": "man raising hand", + "slug": "man_raising_hand", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ™‹โ€โ™€๏ธ": { + "name": "woman raising hand", + "slug": "woman_raising_hand", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง": { + "name": "deaf person", + "slug": "deaf_person", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿงโ€โ™‚๏ธ": { + "name": "deaf man", + "slug": "deaf_man", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿงโ€โ™€๏ธ": { + "name": "deaf woman", + "slug": "deaf_woman", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿ™‡": { + "name": "person bowing", + "slug": "person_bowing", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ™‡โ€โ™‚๏ธ": { + "name": "man bowing", + "slug": "man_bowing", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ™‡โ€โ™€๏ธ": { + "name": "woman bowing", + "slug": "woman_bowing", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿคฆ": { + "name": "person facepalming", + "slug": "person_facepalming", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿคฆโ€โ™‚๏ธ": { + "name": "man facepalming", + "slug": "man_facepalming", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿคฆโ€โ™€๏ธ": { + "name": "woman facepalming", + "slug": "woman_facepalming", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿคท": { + "name": "person shrugging", + "slug": "person_shrugging", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿคทโ€โ™‚๏ธ": { + "name": "man shrugging", + "slug": "man_shrugging", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿคทโ€โ™€๏ธ": { + "name": "woman shrugging", + "slug": "woman_shrugging", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€โš•๏ธ": { + "name": "health worker", + "slug": "health_worker", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€โš•๏ธ": { + "name": "man health worker", + "slug": "man_health_worker", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€โš•๏ธ": { + "name": "woman health worker", + "slug": "woman_health_worker", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€๐ŸŽ“": { + "name": "student", + "slug": "student", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€๐ŸŽ“": { + "name": "man student", + "slug": "man_student", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€๐ŸŽ“": { + "name": "woman student", + "slug": "woman_student", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€๐Ÿซ": { + "name": "teacher", + "slug": "teacher", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€๐Ÿซ": { + "name": "man teacher", + "slug": "man_teacher", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€๐Ÿซ": { + "name": "woman teacher", + "slug": "woman_teacher", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€โš–๏ธ": { + "name": "judge", + "slug": "judge", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€โš–๏ธ": { + "name": "man judge", + "slug": "man_judge", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€โš–๏ธ": { + "name": "woman judge", + "slug": "woman_judge", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€๐ŸŒพ": { + "name": "farmer", + "slug": "farmer", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€๐ŸŒพ": { + "name": "man farmer", + "slug": "man_farmer", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€๐ŸŒพ": { + "name": "woman farmer", + "slug": "woman_farmer", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€๐Ÿณ": { + "name": "cook", + "slug": "cook", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€๐Ÿณ": { + "name": "man cook", + "slug": "man_cook", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€๐Ÿณ": { + "name": "woman cook", + "slug": "woman_cook", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€๐Ÿ”ง": { + "name": "mechanic", + "slug": "mechanic", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€๐Ÿ”ง": { + "name": "man mechanic", + "slug": "man_mechanic", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€๐Ÿ”ง": { + "name": "woman mechanic", + "slug": "woman_mechanic", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€๐Ÿญ": { + "name": "factory worker", + "slug": "factory_worker", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€๐Ÿญ": { + "name": "man factory worker", + "slug": "man_factory_worker", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€๐Ÿญ": { + "name": "woman factory worker", + "slug": "woman_factory_worker", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€๐Ÿ’ผ": { + "name": "office worker", + "slug": "office_worker", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€๐Ÿ’ผ": { + "name": "man office worker", + "slug": "man_office_worker", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€๐Ÿ’ผ": { + "name": "woman office worker", + "slug": "woman_office_worker", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€๐Ÿ”ฌ": { + "name": "scientist", + "slug": "scientist", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€๐Ÿ”ฌ": { + "name": "man scientist", + "slug": "man_scientist", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€๐Ÿ”ฌ": { + "name": "woman scientist", + "slug": "woman_scientist", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€๐Ÿ’ป": { + "name": "technologist", + "slug": "technologist", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€๐Ÿ’ป": { + "name": "man technologist", + "slug": "man_technologist", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€๐Ÿ’ป": { + "name": "woman technologist", + "slug": "woman_technologist", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€๐ŸŽค": { + "name": "singer", + "slug": "singer", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€๐ŸŽค": { + "name": "man singer", + "slug": "man_singer", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€๐ŸŽค": { + "name": "woman singer", + "slug": "woman_singer", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€๐ŸŽจ": { + "name": "artist", + "slug": "artist", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€๐ŸŽจ": { + "name": "man artist", + "slug": "man_artist", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€๐ŸŽจ": { + "name": "woman artist", + "slug": "woman_artist", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€โœˆ๏ธ": { + "name": "pilot", + "slug": "pilot", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€โœˆ๏ธ": { + "name": "man pilot", + "slug": "man_pilot", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€โœˆ๏ธ": { + "name": "woman pilot", + "slug": "woman_pilot", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€๐Ÿš€": { + "name": "astronaut", + "slug": "astronaut", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€๐Ÿš€": { + "name": "man astronaut", + "slug": "man_astronaut", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€๐Ÿš€": { + "name": "woman astronaut", + "slug": "woman_astronaut", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€๐Ÿš’": { + "name": "firefighter", + "slug": "firefighter", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿ‘จโ€๐Ÿš’": { + "name": "man firefighter", + "slug": "man_firefighter", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฉโ€๐Ÿš’": { + "name": "woman firefighter", + "slug": "woman_firefighter", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฎ": { + "name": "police officer", + "slug": "police_officer", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ‘ฎโ€โ™‚๏ธ": { + "name": "man police officer", + "slug": "man_police_officer", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฎโ€โ™€๏ธ": { + "name": "woman police officer", + "slug": "woman_police_officer", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ•ต๏ธ": { + "name": "detective", + "slug": "detective", + "group": "People & Body", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "2.0" + }, + "๐Ÿ•ต๏ธโ€โ™‚๏ธ": { + "name": "man detective", + "slug": "man_detective", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ•ต๏ธโ€โ™€๏ธ": { + "name": "woman detective", + "slug": "woman_detective", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ’‚": { + "name": "guard", + "slug": "guard", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ’‚โ€โ™‚๏ธ": { + "name": "man guard", + "slug": "man_guard", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ’‚โ€โ™€๏ธ": { + "name": "woman guard", + "slug": "woman_guard", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿฅท": { + "name": "ninja", + "slug": "ninja", + "group": "People & Body", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.0" + }, + "๐Ÿ‘ท": { + "name": "construction worker", + "slug": "construction_worker", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ‘ทโ€โ™‚๏ธ": { + "name": "man construction worker", + "slug": "man_construction_worker", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ทโ€โ™€๏ธ": { + "name": "woman construction worker", + "slug": "woman_construction_worker", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿซ…": { + "name": "person with crown", + "slug": "person_with_crown", + "group": "People & Body", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "14.0" + }, + "๐Ÿคด": { + "name": "prince", + "slug": "prince", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿ‘ธ": { + "name": "princess", + "slug": "princess", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ‘ณ": { + "name": "person wearing turban", + "slug": "person_wearing_turban", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ‘ณโ€โ™‚๏ธ": { + "name": "man wearing turban", + "slug": "man_wearing_turban", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ณโ€โ™€๏ธ": { + "name": "woman wearing turban", + "slug": "woman_wearing_turban", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฒ": { + "name": "person with skullcap", + "slug": "person_with_skullcap", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿง•": { + "name": "woman with headscarf", + "slug": "woman_with_headscarf", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿคต": { + "name": "person in tuxedo", + "slug": "person_in_tuxedo", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿคตโ€โ™‚๏ธ": { + "name": "man in tuxedo", + "slug": "man_in_tuxedo", + "group": "People & Body", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.0" + }, + "๐Ÿคตโ€โ™€๏ธ": { + "name": "woman in tuxedo", + "slug": "woman_in_tuxedo", + "group": "People & Body", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.0" + }, + "๐Ÿ‘ฐ": { + "name": "person with veil", + "slug": "person_with_veil", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ‘ฐโ€โ™‚๏ธ": { + "name": "man with veil", + "slug": "man_with_veil", + "group": "People & Body", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.0" + }, + "๐Ÿ‘ฐโ€โ™€๏ธ": { + "name": "woman with veil", + "slug": "woman_with_veil", + "group": "People & Body", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.0" + }, + "๐Ÿคฐ": { + "name": "pregnant woman", + "slug": "pregnant_woman", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿซƒ": { + "name": "pregnant man", + "slug": "pregnant_man", + "group": "People & Body", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "14.0" + }, + "๐Ÿซ„": { + "name": "pregnant person", + "slug": "pregnant_person", + "group": "People & Body", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "14.0" + }, + "๐Ÿคฑ": { + "name": "breast-feeding", + "slug": "breast_feeding", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿ‘ฉโ€๐Ÿผ": { + "name": "woman feeding baby", + "slug": "woman_feeding_baby", + "group": "People & Body", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.0" + }, + "๐Ÿ‘จโ€๐Ÿผ": { + "name": "man feeding baby", + "slug": "man_feeding_baby", + "group": "People & Body", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.0" + }, + "๐Ÿง‘โ€๐Ÿผ": { + "name": "person feeding baby", + "slug": "person_feeding_baby", + "group": "People & Body", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.0" + }, + "๐Ÿ‘ผ": { + "name": "baby angel", + "slug": "baby_angel", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐ŸŽ…": { + "name": "Santa Claus", + "slug": "santa_claus", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿคถ": { + "name": "Mrs. Claus", + "slug": "mrs_claus", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿง‘โ€๐ŸŽ„": { + "name": "mx claus", + "slug": "mx_claus", + "group": "People & Body", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.0" + }, + "๐Ÿฆธ": { + "name": "superhero", + "slug": "superhero", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿฆธโ€โ™‚๏ธ": { + "name": "man superhero", + "slug": "man_superhero", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿฆธโ€โ™€๏ธ": { + "name": "woman superhero", + "slug": "woman_superhero", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿฆน": { + "name": "supervillain", + "slug": "supervillain", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿฆนโ€โ™‚๏ธ": { + "name": "man supervillain", + "slug": "man_supervillain", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿฆนโ€โ™€๏ธ": { + "name": "woman supervillain", + "slug": "woman_supervillain", + "group": "People & Body", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "11.0" + }, + "๐Ÿง™": { + "name": "mage", + "slug": "mage", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿง™โ€โ™‚๏ธ": { + "name": "man mage", + "slug": "man_mage", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿง™โ€โ™€๏ธ": { + "name": "woman mage", + "slug": "woman_mage", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿงš": { + "name": "fairy", + "slug": "fairy", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿงšโ€โ™‚๏ธ": { + "name": "man fairy", + "slug": "man_fairy", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿงšโ€โ™€๏ธ": { + "name": "woman fairy", + "slug": "woman_fairy", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿง›": { + "name": "vampire", + "slug": "vampire", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿง›โ€โ™‚๏ธ": { + "name": "man vampire", + "slug": "man_vampire", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿง›โ€โ™€๏ธ": { + "name": "woman vampire", + "slug": "woman_vampire", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿงœ": { + "name": "merperson", + "slug": "merperson", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿงœโ€โ™‚๏ธ": { + "name": "merman", + "slug": "merman", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿงœโ€โ™€๏ธ": { + "name": "mermaid", + "slug": "mermaid", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿง": { + "name": "elf", + "slug": "elf", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿงโ€โ™‚๏ธ": { + "name": "man elf", + "slug": "man_elf", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿงโ€โ™€๏ธ": { + "name": "woman elf", + "slug": "woman_elf", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿงž": { + "name": "genie", + "slug": "genie", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿงžโ€โ™‚๏ธ": { + "name": "man genie", + "slug": "man_genie", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿงžโ€โ™€๏ธ": { + "name": "woman genie", + "slug": "woman_genie", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐ŸงŸ": { + "name": "zombie", + "slug": "zombie", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐ŸงŸโ€โ™‚๏ธ": { + "name": "man zombie", + "slug": "man_zombie", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐ŸงŸโ€โ™€๏ธ": { + "name": "woman zombie", + "slug": "woman_zombie", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐ŸงŒ": { + "name": "troll", + "slug": "troll", + "group": "People & Body", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿ’†": { + "name": "person getting massage", + "slug": "person_getting_massage", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ’†โ€โ™‚๏ธ": { + "name": "man getting massage", + "slug": "man_getting_massage", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ’†โ€โ™€๏ธ": { + "name": "woman getting massage", + "slug": "woman_getting_massage", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ’‡": { + "name": "person getting haircut", + "slug": "person_getting_haircut", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ’‡โ€โ™‚๏ธ": { + "name": "man getting haircut", + "slug": "man_getting_haircut", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ’‡โ€โ™€๏ธ": { + "name": "woman getting haircut", + "slug": "woman_getting_haircut", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿšถ": { + "name": "person walking", + "slug": "person_walking", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿšถโ€โ™‚๏ธ": { + "name": "man walking", + "slug": "man_walking", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿšถโ€โ™€๏ธ": { + "name": "woman walking", + "slug": "woman_walking", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿšถโ€โžก๏ธ": { + "name": "person walking facing right", + "slug": "person_walking_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿšถโ€โ™€๏ธโ€โžก๏ธ": { + "name": "woman walking facing right", + "slug": "woman_walking_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿšถโ€โ™‚๏ธโ€โžก๏ธ": { + "name": "man walking facing right", + "slug": "man_walking_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿง": { + "name": "person standing", + "slug": "person_standing", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿงโ€โ™‚๏ธ": { + "name": "man standing", + "slug": "man_standing", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿงโ€โ™€๏ธ": { + "name": "woman standing", + "slug": "woman_standing", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐ŸงŽ": { + "name": "person kneeling", + "slug": "person_kneeling", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐ŸงŽโ€โ™‚๏ธ": { + "name": "man kneeling", + "slug": "man_kneeling", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐ŸงŽโ€โ™€๏ธ": { + "name": "woman kneeling", + "slug": "woman_kneeling", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐ŸงŽโ€โžก๏ธ": { + "name": "person kneeling facing right", + "slug": "person_kneeling_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐ŸงŽโ€โ™€๏ธโ€โžก๏ธ": { + "name": "woman kneeling facing right", + "slug": "woman_kneeling_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐ŸงŽโ€โ™‚๏ธโ€โžก๏ธ": { + "name": "man kneeling facing right", + "slug": "man_kneeling_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿง‘โ€๐Ÿฆฏ": { + "name": "person with white cane", + "slug": "person_with_white_cane", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿง‘โ€๐Ÿฆฏโ€โžก๏ธ": { + "name": "person with white cane facing right", + "slug": "person_with_white_cane_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿ‘จโ€๐Ÿฆฏ": { + "name": "man with white cane", + "slug": "man_with_white_cane", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿ‘จโ€๐Ÿฆฏโ€โžก๏ธ": { + "name": "man with white cane facing right", + "slug": "man_with_white_cane_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿ‘ฉโ€๐Ÿฆฏ": { + "name": "woman with white cane", + "slug": "woman_with_white_cane", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿ‘ฉโ€๐Ÿฆฏโ€โžก๏ธ": { + "name": "woman with white cane facing right", + "slug": "woman_with_white_cane_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿง‘โ€๐Ÿฆผ": { + "name": "person in motorized wheelchair", + "slug": "person_in_motorized_wheelchair", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿง‘โ€๐Ÿฆผโ€โžก๏ธ": { + "name": "person in motorized wheelchair facing right", + "slug": "person_in_motorized_wheelchair_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿ‘จโ€๐Ÿฆผ": { + "name": "man in motorized wheelchair", + "slug": "man_in_motorized_wheelchair", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿ‘จโ€๐Ÿฆผโ€โžก๏ธ": { + "name": "man in motorized wheelchair facing right", + "slug": "man_in_motorized_wheelchair_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿ‘ฉโ€๐Ÿฆผ": { + "name": "woman in motorized wheelchair", + "slug": "woman_in_motorized_wheelchair", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿ‘ฉโ€๐Ÿฆผโ€โžก๏ธ": { + "name": "woman in motorized wheelchair facing right", + "slug": "woman_in_motorized_wheelchair_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿง‘โ€๐Ÿฆฝ": { + "name": "person in manual wheelchair", + "slug": "person_in_manual_wheelchair", + "group": "People & Body", + "emoji_version": "12.1", + "unicode_version": "12.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.1" + }, + "๐Ÿง‘โ€๐Ÿฆฝโ€โžก๏ธ": { + "name": "person in manual wheelchair facing right", + "slug": "person_in_manual_wheelchair_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿ‘จโ€๐Ÿฆฝ": { + "name": "man in manual wheelchair", + "slug": "man_in_manual_wheelchair", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿ‘จโ€๐Ÿฆฝโ€โžก๏ธ": { + "name": "man in manual wheelchair facing right", + "slug": "man_in_manual_wheelchair_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿ‘ฉโ€๐Ÿฆฝ": { + "name": "woman in manual wheelchair", + "slug": "woman_in_manual_wheelchair", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿ‘ฉโ€๐Ÿฆฝโ€โžก๏ธ": { + "name": "woman in manual wheelchair facing right", + "slug": "woman_in_manual_wheelchair_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿƒ": { + "name": "person running", + "slug": "person_running", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿƒโ€โ™‚๏ธ": { + "name": "man running", + "slug": "man_running", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿƒโ€โ™€๏ธ": { + "name": "woman running", + "slug": "woman_running", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿƒโ€โžก๏ธ": { + "name": "person running facing right", + "slug": "person_running_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿƒโ€โ™€๏ธโ€โžก๏ธ": { + "name": "woman running facing right", + "slug": "woman_running_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿƒโ€โ™‚๏ธโ€โžก๏ธ": { + "name": "man running facing right", + "slug": "man_running_facing_right", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "15.1" + }, + "๐Ÿ’ƒ": { + "name": "woman dancing", + "slug": "woman_dancing", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ•บ": { + "name": "man dancing", + "slug": "man_dancing", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿ•ด๏ธ": { + "name": "person in suit levitating", + "slug": "person_in_suit_levitating", + "group": "People & Body", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‘ฏ": { + "name": "people with bunny ears", + "slug": "people_with_bunny_ears", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘ฏโ€โ™‚๏ธ": { + "name": "men with bunny ears", + "slug": "men_with_bunny_ears", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿ‘ฏโ€โ™€๏ธ": { + "name": "women with bunny ears", + "slug": "women_with_bunny_ears", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿง–": { + "name": "person in steamy room", + "slug": "person_in_steamy_room", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿง–โ€โ™‚๏ธ": { + "name": "man in steamy room", + "slug": "man_in_steamy_room", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿง–โ€โ™€๏ธ": { + "name": "woman in steamy room", + "slug": "woman_in_steamy_room", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿง—": { + "name": "person climbing", + "slug": "person_climbing", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿง—โ€โ™‚๏ธ": { + "name": "man climbing", + "slug": "man_climbing", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿง—โ€โ™€๏ธ": { + "name": "woman climbing", + "slug": "woman_climbing", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿคบ": { + "name": "person fencing", + "slug": "person_fencing", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿ‡": { + "name": "horse racing", + "slug": "horse_racing", + "group": "People & Body", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "โ›ท๏ธ": { + "name": "skier", + "slug": "skier", + "group": "People & Body", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ‚": { + "name": "snowboarder", + "slug": "snowboarder", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐ŸŒ๏ธ": { + "name": "person golfing", + "slug": "person_golfing", + "group": "People & Body", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐ŸŒ๏ธโ€โ™‚๏ธ": { + "name": "man golfing", + "slug": "man_golfing", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐ŸŒ๏ธโ€โ™€๏ธ": { + "name": "woman golfing", + "slug": "woman_golfing", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ„": { + "name": "person surfing", + "slug": "person_surfing", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ„โ€โ™‚๏ธ": { + "name": "man surfing", + "slug": "man_surfing", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ„โ€โ™€๏ธ": { + "name": "woman surfing", + "slug": "woman_surfing", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿšฃ": { + "name": "person rowing boat", + "slug": "person_rowing_boat", + "group": "People & Body", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿšฃโ€โ™‚๏ธ": { + "name": "man rowing boat", + "slug": "man_rowing_boat", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿšฃโ€โ™€๏ธ": { + "name": "woman rowing boat", + "slug": "woman_rowing_boat", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐ŸŠ": { + "name": "person swimming", + "slug": "person_swimming", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐ŸŠโ€โ™‚๏ธ": { + "name": "man swimming", + "slug": "man_swimming", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐ŸŠโ€โ™€๏ธ": { + "name": "woman swimming", + "slug": "woman_swimming", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "โ›น๏ธ": { + "name": "person bouncing ball", + "slug": "person_bouncing_ball", + "group": "People & Body", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "2.0" + }, + "โ›น๏ธโ€โ™‚๏ธ": { + "name": "man bouncing ball", + "slug": "man_bouncing_ball", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "โ›น๏ธโ€โ™€๏ธ": { + "name": "woman bouncing ball", + "slug": "woman_bouncing_ball", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‹๏ธ": { + "name": "person lifting weights", + "slug": "person_lifting_weights", + "group": "People & Body", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "2.0" + }, + "๐Ÿ‹๏ธโ€โ™‚๏ธ": { + "name": "man lifting weights", + "slug": "man_lifting_weights", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿ‹๏ธโ€โ™€๏ธ": { + "name": "woman lifting weights", + "slug": "woman_lifting_weights", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿšด": { + "name": "person biking", + "slug": "person_biking", + "group": "People & Body", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿšดโ€โ™‚๏ธ": { + "name": "man biking", + "slug": "man_biking", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿšดโ€โ™€๏ธ": { + "name": "woman biking", + "slug": "woman_biking", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿšต": { + "name": "person mountain biking", + "slug": "person_mountain_biking", + "group": "People & Body", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿšตโ€โ™‚๏ธ": { + "name": "man mountain biking", + "slug": "man_mountain_biking", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿšตโ€โ™€๏ธ": { + "name": "woman mountain biking", + "slug": "woman_mountain_biking", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿคธ": { + "name": "person cartwheeling", + "slug": "person_cartwheeling", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿคธโ€โ™‚๏ธ": { + "name": "man cartwheeling", + "slug": "man_cartwheeling", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿคธโ€โ™€๏ธ": { + "name": "woman cartwheeling", + "slug": "woman_cartwheeling", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿคผ": { + "name": "people wrestling", + "slug": "people_wrestling", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿคผโ€โ™‚๏ธ": { + "name": "men wrestling", + "slug": "men_wrestling", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿคผโ€โ™€๏ธ": { + "name": "women wrestling", + "slug": "women_wrestling", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿคฝ": { + "name": "person playing water polo", + "slug": "person_playing_water_polo", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿคฝโ€โ™‚๏ธ": { + "name": "man playing water polo", + "slug": "man_playing_water_polo", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿคฝโ€โ™€๏ธ": { + "name": "woman playing water polo", + "slug": "woman_playing_water_polo", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿคพ": { + "name": "person playing handball", + "slug": "person_playing_handball", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿคพโ€โ™‚๏ธ": { + "name": "man playing handball", + "slug": "man_playing_handball", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿคพโ€โ™€๏ธ": { + "name": "woman playing handball", + "slug": "woman_playing_handball", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿคน": { + "name": "person juggling", + "slug": "person_juggling", + "group": "People & Body", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "3.0" + }, + "๐Ÿคนโ€โ™‚๏ธ": { + "name": "man juggling", + "slug": "man_juggling", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿคนโ€โ™€๏ธ": { + "name": "woman juggling", + "slug": "woman_juggling", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง˜": { + "name": "person in lotus position", + "slug": "person_in_lotus_position", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿง˜โ€โ™‚๏ธ": { + "name": "man in lotus position", + "slug": "man_in_lotus_position", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿง˜โ€โ™€๏ธ": { + "name": "woman in lotus position", + "slug": "woman_in_lotus_position", + "group": "People & Body", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "5.0" + }, + "๐Ÿ›€": { + "name": "person taking bath", + "slug": "person_taking_bath", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "1.0" + }, + "๐Ÿ›Œ": { + "name": "person in bed", + "slug": "person_in_bed", + "group": "People & Body", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "4.0" + }, + "๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘": { + "name": "people holding hands", + "slug": "people_holding_hands", + "group": "People & Body", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿ‘ญ": { + "name": "women holding hands", + "slug": "women_holding_hands", + "group": "People & Body", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿ‘ซ": { + "name": "woman and man holding hands", + "slug": "woman_and_man_holding_hands", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿ‘ฌ": { + "name": "men holding hands", + "slug": "men_holding_hands", + "group": "People & Body", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "12.0" + }, + "๐Ÿ’": { + "name": "kiss", + "slug": "kiss", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.1" + }, + "๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ": { + "name": "kiss woman, man", + "slug": "kiss_woman_man", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.1" + }, + "๐Ÿ‘จโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ": { + "name": "kiss man, man", + "slug": "kiss_man_man", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.1" + }, + "๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘ฉ": { + "name": "kiss woman, woman", + "slug": "kiss_woman_woman", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.1" + }, + "๐Ÿ’‘": { + "name": "couple with heart", + "slug": "couple_with_heart", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.1" + }, + "๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘จ": { + "name": "couple with heart woman, man", + "slug": "couple_with_heart_woman_man", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.1" + }, + "๐Ÿ‘จโ€โค๏ธโ€๐Ÿ‘จ": { + "name": "couple with heart man, man", + "slug": "couple_with_heart_man_man", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.1" + }, + "๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘ฉ": { + "name": "couple with heart woman, woman", + "slug": "couple_with_heart_woman_woman", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": true, + "skin_tone_support_unicode_version": "13.1" + }, + "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ": { + "name": "family man, woman, boy", + "slug": "family_man_woman_boy", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง": { + "name": "family man, woman, girl", + "slug": "family_man_woman_girl", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ": { + "name": "family man, woman, girl, boy", + "slug": "family_man_woman_girl_boy", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ": { + "name": "family man, woman, boy, boy", + "slug": "family_man_woman_boy_boy", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง": { + "name": "family man, woman, girl, girl", + "slug": "family_man_woman_girl_girl", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆ": { + "name": "family man, man, boy", + "slug": "family_man_man_boy", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ง": { + "name": "family man, man, girl", + "slug": "family_man_man_girl", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ": { + "name": "family man, man, girl, boy", + "slug": "family_man_man_girl_boy", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ": { + "name": "family man, man, boy, boy", + "slug": "family_man_man_boy_boy", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง": { + "name": "family man, man, girl, girl", + "slug": "family_man_man_girl_girl", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ": { + "name": "family woman, woman, boy", + "slug": "family_woman_woman_boy", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ง": { + "name": "family woman, woman, girl", + "slug": "family_woman_woman_girl", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ": { + "name": "family woman, woman, girl, boy", + "slug": "family_woman_woman_girl_boy", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ": { + "name": "family woman, woman, boy, boy", + "slug": "family_woman_woman_boy_boy", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง": { + "name": "family woman, woman, girl, girl", + "slug": "family_woman_woman_girl_girl", + "group": "People & Body", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‘จโ€๐Ÿ‘ฆ": { + "name": "family man, boy", + "slug": "family_man_boy", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ": { + "name": "family man, boy, boy", + "slug": "family_man_boy_boy", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿ‘จโ€๐Ÿ‘ง": { + "name": "family man, girl", + "slug": "family_man_girl", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ": { + "name": "family man, girl, boy", + "slug": "family_man_girl_boy", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง": { + "name": "family man, girl, girl", + "slug": "family_man_girl_girl", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿ‘ฉโ€๐Ÿ‘ฆ": { + "name": "family woman, boy", + "slug": "family_woman_boy", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ": { + "name": "family woman, boy, boy", + "slug": "family_woman_boy_boy", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿ‘ฉโ€๐Ÿ‘ง": { + "name": "family woman, girl", + "slug": "family_woman_girl", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ": { + "name": "family woman, girl, boy", + "slug": "family_woman_girl_boy", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง": { + "name": "family woman, girl, girl", + "slug": "family_woman_girl_girl", + "group": "People & Body", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿ—ฃ๏ธ": { + "name": "speaking head", + "slug": "speaking_head", + "group": "People & Body", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ‘ค": { + "name": "bust in silhouette", + "slug": "bust_in_silhouette", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘ฅ": { + "name": "busts in silhouette", + "slug": "busts_in_silhouette", + "group": "People & Body", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿซ‚": { + "name": "people hugging", + "slug": "people_hugging", + "group": "People & Body", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿ‘ช": { + "name": "family", + "slug": "family", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿง‘โ€๐Ÿง‘โ€๐Ÿง’": { + "name": "family adult, adult, child", + "slug": "family_adult_adult_child", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": false + }, + "๐Ÿง‘โ€๐Ÿง‘โ€๐Ÿง’โ€๐Ÿง’": { + "name": "family adult, adult, child, child", + "slug": "family_adult_adult_child_child", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": false + }, + "๐Ÿง‘โ€๐Ÿง’": { + "name": "family adult, child", + "slug": "family_adult_child", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": false + }, + "๐Ÿง‘โ€๐Ÿง’โ€๐Ÿง’": { + "name": "family adult, child, child", + "slug": "family_adult_child_child", + "group": "People & Body", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": false + }, + "๐Ÿ‘ฃ": { + "name": "footprints", + "slug": "footprints", + "group": "People & Body", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿต": { + "name": "monkey face", + "slug": "monkey_face", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’": { + "name": "monkey", + "slug": "monkey", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฆ": { + "name": "gorilla", + "slug": "gorilla", + "group": "Animals & Nature", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฆง": { + "name": "orangutan", + "slug": "orangutan", + "group": "Animals & Nature", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿถ": { + "name": "dog face", + "slug": "dog_face", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•": { + "name": "dog", + "slug": "dog", + "group": "Animals & Nature", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿฆฎ": { + "name": "guide dog", + "slug": "guide_dog", + "group": "Animals & Nature", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿ•โ€๐Ÿฆบ": { + "name": "service dog", + "slug": "service_dog", + "group": "Animals & Nature", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฉ": { + "name": "poodle", + "slug": "poodle", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿบ": { + "name": "wolf", + "slug": "wolf", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸฆŠ": { + "name": "fox", + "slug": "fox", + "group": "Animals & Nature", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฆ": { + "name": "raccoon", + "slug": "raccoon", + "group": "Animals & Nature", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฑ": { + "name": "cat face", + "slug": "cat_face", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿˆ": { + "name": "cat", + "slug": "cat", + "group": "Animals & Nature", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿˆโ€โฌ›": { + "name": "black cat", + "slug": "black_cat", + "group": "Animals & Nature", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿฆ": { + "name": "lion", + "slug": "lion", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿฏ": { + "name": "tiger face", + "slug": "tiger_face", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ…": { + "name": "tiger", + "slug": "tiger", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ†": { + "name": "leopard", + "slug": "leopard", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿด": { + "name": "horse face", + "slug": "horse_face", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸซŽ": { + "name": "moose", + "slug": "moose", + "group": "Animals & Nature", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐Ÿซ": { + "name": "donkey", + "slug": "donkey", + "group": "Animals & Nature", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐ŸŽ": { + "name": "horse", + "slug": "horse", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฆ„": { + "name": "unicorn", + "slug": "unicorn", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿฆ“": { + "name": "zebra", + "slug": "zebra", + "group": "Animals & Nature", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐ŸฆŒ": { + "name": "deer", + "slug": "deer", + "group": "Animals & Nature", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฆฌ": { + "name": "bison", + "slug": "bison", + "group": "Animals & Nature", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿฎ": { + "name": "cow face", + "slug": "cow_face", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‚": { + "name": "ox", + "slug": "ox", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿƒ": { + "name": "water buffalo", + "slug": "water_buffalo", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ„": { + "name": "cow", + "slug": "cow", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿท": { + "name": "pig face", + "slug": "pig_face", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ–": { + "name": "pig", + "slug": "pig", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ—": { + "name": "boar", + "slug": "boar", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฝ": { + "name": "pig nose", + "slug": "pig_nose", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ": { + "name": "ram", + "slug": "ram", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ‘": { + "name": "ewe", + "slug": "ewe", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ": { + "name": "goat", + "slug": "goat", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿช": { + "name": "camel", + "slug": "camel", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿซ": { + "name": "two-hump camel", + "slug": "two_hump_camel", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฆ™": { + "name": "llama", + "slug": "llama", + "group": "Animals & Nature", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฆ’": { + "name": "giraffe", + "slug": "giraffe", + "group": "Animals & Nature", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿ˜": { + "name": "elephant", + "slug": "elephant", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฆฃ": { + "name": "mammoth", + "slug": "mammoth", + "group": "Animals & Nature", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿฆ": { + "name": "rhinoceros", + "slug": "rhinoceros", + "group": "Animals & Nature", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฆ›": { + "name": "hippopotamus", + "slug": "hippopotamus", + "group": "Animals & Nature", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿญ": { + "name": "mouse face", + "slug": "mouse_face", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ": { + "name": "mouse", + "slug": "mouse", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ€": { + "name": "rat", + "slug": "rat", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿน": { + "name": "hamster", + "slug": "hamster", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฐ": { + "name": "rabbit face", + "slug": "rabbit_face", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‡": { + "name": "rabbit", + "slug": "rabbit", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿฟ๏ธ": { + "name": "chipmunk", + "slug": "chipmunk", + "group": "Animals & Nature", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿฆซ": { + "name": "beaver", + "slug": "beaver", + "group": "Animals & Nature", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿฆ”": { + "name": "hedgehog", + "slug": "hedgehog", + "group": "Animals & Nature", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿฆ‡": { + "name": "bat", + "slug": "bat", + "group": "Animals & Nature", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿป": { + "name": "bear", + "slug": "bear", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿปโ€โ„๏ธ": { + "name": "polar bear", + "slug": "polar_bear", + "group": "Animals & Nature", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿจ": { + "name": "koala", + "slug": "koala", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿผ": { + "name": "panda", + "slug": "panda", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฆฅ": { + "name": "sloth", + "slug": "sloth", + "group": "Animals & Nature", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฆฆ": { + "name": "otter", + "slug": "otter", + "group": "Animals & Nature", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฆจ": { + "name": "skunk", + "slug": "skunk", + "group": "Animals & Nature", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฆ˜": { + "name": "kangaroo", + "slug": "kangaroo", + "group": "Animals & Nature", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฆก": { + "name": "badger", + "slug": "badger", + "group": "Animals & Nature", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿพ": { + "name": "paw prints", + "slug": "paw_prints", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฆƒ": { + "name": "turkey", + "slug": "turkey", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ”": { + "name": "chicken", + "slug": "chicken", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“": { + "name": "rooster", + "slug": "rooster", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿฃ": { + "name": "hatching chick", + "slug": "hatching_chick", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿค": { + "name": "baby chick", + "slug": "baby_chick", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅ": { + "name": "front-facing baby chick", + "slug": "front_facing_baby_chick", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฆ": { + "name": "bird", + "slug": "bird", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿง": { + "name": "penguin", + "slug": "penguin", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•Š๏ธ": { + "name": "dove", + "slug": "dove", + "group": "Animals & Nature", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿฆ…": { + "name": "eagle", + "slug": "eagle", + "group": "Animals & Nature", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฆ†": { + "name": "duck", + "slug": "duck", + "group": "Animals & Nature", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฆข": { + "name": "swan", + "slug": "swan", + "group": "Animals & Nature", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฆ‰": { + "name": "owl", + "slug": "owl", + "group": "Animals & Nature", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฆค": { + "name": "dodo", + "slug": "dodo", + "group": "Animals & Nature", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿชถ": { + "name": "feather", + "slug": "feather", + "group": "Animals & Nature", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿฆฉ": { + "name": "flamingo", + "slug": "flamingo", + "group": "Animals & Nature", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฆš": { + "name": "peacock", + "slug": "peacock", + "group": "Animals & Nature", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฆœ": { + "name": "parrot", + "slug": "parrot", + "group": "Animals & Nature", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿชฝ": { + "name": "wing", + "slug": "wing", + "group": "Animals & Nature", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐Ÿฆโ€โฌ›": { + "name": "black bird", + "slug": "black_bird", + "group": "Animals & Nature", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐Ÿชฟ": { + "name": "goose", + "slug": "goose", + "group": "Animals & Nature", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐Ÿฆโ€๐Ÿ”ฅ": { + "name": "phoenix", + "slug": "phoenix", + "group": "Animals & Nature", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": false + }, + "๐Ÿธ": { + "name": "frog", + "slug": "frog", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŠ": { + "name": "crocodile", + "slug": "crocodile", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿข": { + "name": "turtle", + "slug": "turtle", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸฆŽ": { + "name": "lizard", + "slug": "lizard", + "group": "Animals & Nature", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿ": { + "name": "snake", + "slug": "snake", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฒ": { + "name": "dragon face", + "slug": "dragon_face", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‰": { + "name": "dragon", + "slug": "dragon", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿฆ•": { + "name": "sauropod", + "slug": "sauropod", + "group": "Animals & Nature", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿฆ–": { + "name": "T-Rex", + "slug": "t_rex", + "group": "Animals & Nature", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿณ": { + "name": "spouting whale", + "slug": "spouting_whale", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‹": { + "name": "whale", + "slug": "whale", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿฌ": { + "name": "dolphin", + "slug": "dolphin", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฆญ": { + "name": "seal", + "slug": "seal", + "group": "Animals & Nature", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐ŸŸ": { + "name": "fish", + "slug": "fish", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ ": { + "name": "tropical fish", + "slug": "tropical_fish", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿก": { + "name": "blowfish", + "slug": "blowfish", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฆˆ": { + "name": "shark", + "slug": "shark", + "group": "Animals & Nature", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿ™": { + "name": "octopus", + "slug": "octopus", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿš": { + "name": "spiral shell", + "slug": "spiral_shell", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿชธ": { + "name": "coral", + "slug": "coral", + "group": "Animals & Nature", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿชผ": { + "name": "jellyfish", + "slug": "jellyfish", + "group": "Animals & Nature", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐ŸŒ": { + "name": "snail", + "slug": "snail", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฆ‹": { + "name": "butterfly", + "slug": "butterfly", + "group": "Animals & Nature", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿ›": { + "name": "bug", + "slug": "bug", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿœ": { + "name": "ant", + "slug": "ant", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ": { + "name": "honeybee", + "slug": "honeybee", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿชฒ": { + "name": "beetle", + "slug": "beetle", + "group": "Animals & Nature", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿž": { + "name": "lady beetle", + "slug": "lady_beetle", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฆ—": { + "name": "cricket", + "slug": "cricket", + "group": "Animals & Nature", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿชณ": { + "name": "cockroach", + "slug": "cockroach", + "group": "Animals & Nature", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿ•ท๏ธ": { + "name": "spider", + "slug": "spider", + "group": "Animals & Nature", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ•ธ๏ธ": { + "name": "spider web", + "slug": "spider_web", + "group": "Animals & Nature", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿฆ‚": { + "name": "scorpion", + "slug": "scorpion", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸฆŸ": { + "name": "mosquito", + "slug": "mosquito", + "group": "Animals & Nature", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿชฐ": { + "name": "fly", + "slug": "fly", + "group": "Animals & Nature", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿชฑ": { + "name": "worm", + "slug": "worm", + "group": "Animals & Nature", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿฆ ": { + "name": "microbe", + "slug": "microbe", + "group": "Animals & Nature", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿ’": { + "name": "bouquet", + "slug": "bouquet", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒธ": { + "name": "cherry blossom", + "slug": "cherry_blossom", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ฎ": { + "name": "white flower", + "slug": "white_flower", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿชท": { + "name": "lotus", + "slug": "lotus", + "group": "Animals & Nature", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿต๏ธ": { + "name": "rosette", + "slug": "rosette", + "group": "Animals & Nature", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒน": { + "name": "rose", + "slug": "rose", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅ€": { + "name": "wilted flower", + "slug": "wilted_flower", + "group": "Animals & Nature", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐ŸŒบ": { + "name": "hibiscus", + "slug": "hibiscus", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒป": { + "name": "sunflower", + "slug": "sunflower", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒผ": { + "name": "blossom", + "slug": "blossom", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒท": { + "name": "tulip", + "slug": "tulip", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿชป": { + "name": "hyacinth", + "slug": "hyacinth", + "group": "Animals & Nature", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐ŸŒฑ": { + "name": "seedling", + "slug": "seedling", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿชด": { + "name": "potted plant", + "slug": "potted_plant", + "group": "Animals & Nature", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐ŸŒฒ": { + "name": "evergreen tree", + "slug": "evergreen_tree", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸŒณ": { + "name": "deciduous tree", + "slug": "deciduous_tree", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸŒด": { + "name": "palm tree", + "slug": "palm_tree", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒต": { + "name": "cactus", + "slug": "cactus", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒพ": { + "name": "sheaf of rice", + "slug": "sheaf_of_rice", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒฟ": { + "name": "herb", + "slug": "herb", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ˜˜๏ธ": { + "name": "shamrock", + "slug": "shamrock", + "group": "Animals & Nature", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ€": { + "name": "four leaf clover", + "slug": "four_leaf_clover", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ": { + "name": "maple leaf", + "slug": "maple_leaf", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‚": { + "name": "fallen leaf", + "slug": "fallen_leaf", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿƒ": { + "name": "leaf fluttering in wind", + "slug": "leaf_fluttering_in_wind", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿชน": { + "name": "empty nest", + "slug": "empty_nest", + "group": "Animals & Nature", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿชบ": { + "name": "nest with eggs", + "slug": "nest_with_eggs", + "group": "Animals & Nature", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿ„": { + "name": "mushroom", + "slug": "mushroom", + "group": "Animals & Nature", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‡": { + "name": "grapes", + "slug": "grapes", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿˆ": { + "name": "melon", + "slug": "melon", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‰": { + "name": "watermelon", + "slug": "watermelon", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŠ": { + "name": "tangerine", + "slug": "tangerine", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‹": { + "name": "lemon", + "slug": "lemon", + "group": "Food & Drink", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ‹โ€๐ŸŸฉ": { + "name": "lime", + "slug": "lime", + "group": "Food & Drink", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": false + }, + "๐ŸŒ": { + "name": "banana", + "slug": "banana", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ": { + "name": "pineapple", + "slug": "pineapple", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅญ": { + "name": "mango", + "slug": "mango", + "group": "Food & Drink", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐ŸŽ": { + "name": "red apple", + "slug": "red_apple", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ": { + "name": "green apple", + "slug": "green_apple", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ": { + "name": "pear", + "slug": "pear", + "group": "Food & Drink", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ‘": { + "name": "peach", + "slug": "peach", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’": { + "name": "cherries", + "slug": "cherries", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“": { + "name": "strawberry", + "slug": "strawberry", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿซ": { + "name": "blueberries", + "slug": "blueberries", + "group": "Food & Drink", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿฅ": { + "name": "kiwi fruit", + "slug": "kiwi_fruit", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿ…": { + "name": "tomato", + "slug": "tomato", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿซ’": { + "name": "olive", + "slug": "olive", + "group": "Food & Drink", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿฅฅ": { + "name": "coconut", + "slug": "coconut", + "group": "Food & Drink", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿฅ‘": { + "name": "avocado", + "slug": "avocado", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿ†": { + "name": "eggplant", + "slug": "eggplant", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅ”": { + "name": "potato", + "slug": "potato", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฅ•": { + "name": "carrot", + "slug": "carrot", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐ŸŒฝ": { + "name": "ear of corn", + "slug": "ear_of_corn", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒถ๏ธ": { + "name": "hot pepper", + "slug": "hot_pepper", + "group": "Food & Drink", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿซ‘": { + "name": "bell pepper", + "slug": "bell_pepper", + "group": "Food & Drink", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿฅ’": { + "name": "cucumber", + "slug": "cucumber", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฅฌ": { + "name": "leafy green", + "slug": "leafy_green", + "group": "Food & Drink", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฅฆ": { + "name": "broccoli", + "slug": "broccoli", + "group": "Food & Drink", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿง„": { + "name": "garlic", + "slug": "garlic", + "group": "Food & Drink", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿง…": { + "name": "onion", + "slug": "onion", + "group": "Food & Drink", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฅœ": { + "name": "peanuts", + "slug": "peanuts", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿซ˜": { + "name": "beans", + "slug": "beans", + "group": "Food & Drink", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐ŸŒฐ": { + "name": "chestnut", + "slug": "chestnut", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿซš": { + "name": "ginger root", + "slug": "ginger_root", + "group": "Food & Drink", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐Ÿซ›": { + "name": "pea pod", + "slug": "pea_pod", + "group": "Food & Drink", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐Ÿ„โ€๐ŸŸซ": { + "name": "brown mushroom", + "slug": "brown_mushroom", + "group": "Food & Drink", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": false + }, + "๐Ÿž": { + "name": "bread", + "slug": "bread", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅ": { + "name": "croissant", + "slug": "croissant", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฅ–": { + "name": "baguette bread", + "slug": "baguette_bread", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿซ“": { + "name": "flatbread", + "slug": "flatbread", + "group": "Food & Drink", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿฅจ": { + "name": "pretzel", + "slug": "pretzel", + "group": "Food & Drink", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿฅฏ": { + "name": "bagel", + "slug": "bagel", + "group": "Food & Drink", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฅž": { + "name": "pancakes", + "slug": "pancakes", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿง‡": { + "name": "waffle", + "slug": "waffle", + "group": "Food & Drink", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿง€": { + "name": "cheese wedge", + "slug": "cheese_wedge", + "group": "Food & Drink", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ–": { + "name": "meat on bone", + "slug": "meat_on_bone", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ—": { + "name": "poultry leg", + "slug": "poultry_leg", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅฉ": { + "name": "cut of meat", + "slug": "cut_of_meat", + "group": "Food & Drink", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿฅ“": { + "name": "bacon", + "slug": "bacon", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿ”": { + "name": "hamburger", + "slug": "hamburger", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŸ": { + "name": "french fries", + "slug": "french_fries", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•": { + "name": "pizza", + "slug": "pizza", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒญ": { + "name": "hot dog", + "slug": "hot_dog", + "group": "Food & Drink", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿฅช": { + "name": "sandwich", + "slug": "sandwich", + "group": "Food & Drink", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐ŸŒฎ": { + "name": "taco", + "slug": "taco", + "group": "Food & Drink", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸŒฏ": { + "name": "burrito", + "slug": "burrito", + "group": "Food & Drink", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿซ”": { + "name": "tamale", + "slug": "tamale", + "group": "Food & Drink", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿฅ™": { + "name": "stuffed flatbread", + "slug": "stuffed_flatbread", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿง†": { + "name": "falafel", + "slug": "falafel", + "group": "Food & Drink", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฅš": { + "name": "egg", + "slug": "egg", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿณ": { + "name": "cooking", + "slug": "cooking", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅ˜": { + "name": "shallow pan of food", + "slug": "shallow_pan_of_food", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฒ": { + "name": "pot of food", + "slug": "pot_of_food", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿซ•": { + "name": "fondue", + "slug": "fondue", + "group": "Food & Drink", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿฅฃ": { + "name": "bowl with spoon", + "slug": "bowl_with_spoon", + "group": "Food & Drink", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿฅ—": { + "name": "green salad", + "slug": "green_salad", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฟ": { + "name": "popcorn", + "slug": "popcorn", + "group": "Food & Drink", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿงˆ": { + "name": "butter", + "slug": "butter", + "group": "Food & Drink", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿง‚": { + "name": "salt", + "slug": "salt", + "group": "Food & Drink", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฅซ": { + "name": "canned food", + "slug": "canned_food", + "group": "Food & Drink", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿฑ": { + "name": "bento box", + "slug": "bento_box", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ˜": { + "name": "rice cracker", + "slug": "rice_cracker", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ™": { + "name": "rice ball", + "slug": "rice_ball", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿš": { + "name": "cooked rice", + "slug": "cooked_rice", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›": { + "name": "curry rice", + "slug": "curry_rice", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿœ": { + "name": "steaming bowl", + "slug": "steaming_bowl", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ": { + "name": "spaghetti", + "slug": "spaghetti", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ ": { + "name": "roasted sweet potato", + "slug": "roasted_sweet_potato", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿข": { + "name": "oden", + "slug": "oden", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฃ": { + "name": "sushi", + "slug": "sushi", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿค": { + "name": "fried shrimp", + "slug": "fried_shrimp", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅ": { + "name": "fish cake with swirl", + "slug": "fish_cake_with_swirl", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅฎ": { + "name": "moon cake", + "slug": "moon_cake", + "group": "Food & Drink", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿก": { + "name": "dango", + "slug": "dango", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸฅŸ": { + "name": "dumpling", + "slug": "dumpling", + "group": "Food & Drink", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿฅ ": { + "name": "fortune cookie", + "slug": "fortune_cookie", + "group": "Food & Drink", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿฅก": { + "name": "takeout box", + "slug": "takeout_box", + "group": "Food & Drink", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿฆ€": { + "name": "crab", + "slug": "crab", + "group": "Food & Drink", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿฆž": { + "name": "lobster", + "slug": "lobster", + "group": "Food & Drink", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฆ": { + "name": "shrimp", + "slug": "shrimp", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฆ‘": { + "name": "squid", + "slug": "squid", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฆช": { + "name": "oyster", + "slug": "oyster", + "group": "Food & Drink", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฆ": { + "name": "soft ice cream", + "slug": "soft_ice_cream", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿง": { + "name": "shaved ice", + "slug": "shaved_ice", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿจ": { + "name": "ice cream", + "slug": "ice_cream", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฉ": { + "name": "doughnut", + "slug": "doughnut", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿช": { + "name": "cookie", + "slug": "cookie", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ‚": { + "name": "birthday cake", + "slug": "birthday_cake", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฐ": { + "name": "shortcake", + "slug": "shortcake", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿง": { + "name": "cupcake", + "slug": "cupcake", + "group": "Food & Drink", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฅง": { + "name": "pie", + "slug": "pie", + "group": "Food & Drink", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿซ": { + "name": "chocolate bar", + "slug": "chocolate_bar", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฌ": { + "name": "candy", + "slug": "candy", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿญ": { + "name": "lollipop", + "slug": "lollipop", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฎ": { + "name": "custard", + "slug": "custard", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฏ": { + "name": "honey pot", + "slug": "honey_pot", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿผ": { + "name": "baby bottle", + "slug": "baby_bottle", + "group": "Food & Drink", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿฅ›": { + "name": "glass of milk", + "slug": "glass_of_milk", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "โ˜•": { + "name": "hot beverage", + "slug": "hot_beverage", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿซ–": { + "name": "teapot", + "slug": "teapot", + "group": "Food & Drink", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿต": { + "name": "teacup without handle", + "slug": "teacup_without_handle", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿถ": { + "name": "sake", + "slug": "sake", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿพ": { + "name": "bottle with popping cork", + "slug": "bottle_with_popping_cork", + "group": "Food & Drink", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿท": { + "name": "wine glass", + "slug": "wine_glass", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿธ": { + "name": "cocktail glass", + "slug": "cocktail_glass", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿน": { + "name": "tropical drink", + "slug": "tropical_drink", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿบ": { + "name": "beer mug", + "slug": "beer_mug", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿป": { + "name": "clinking beer mugs", + "slug": "clinking_beer_mugs", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅ‚": { + "name": "clinking glasses", + "slug": "clinking_glasses", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฅƒ": { + "name": "tumbler glass", + "slug": "tumbler_glass", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿซ—": { + "name": "pouring liquid", + "slug": "pouring_liquid", + "group": "Food & Drink", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿฅค": { + "name": "cup with straw", + "slug": "cup_with_straw", + "group": "Food & Drink", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿง‹": { + "name": "bubble tea", + "slug": "bubble_tea", + "group": "Food & Drink", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿงƒ": { + "name": "beverage box", + "slug": "beverage_box", + "group": "Food & Drink", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿง‰": { + "name": "mate", + "slug": "mate", + "group": "Food & Drink", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐ŸงŠ": { + "name": "ice", + "slug": "ice", + "group": "Food & Drink", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฅข": { + "name": "chopsticks", + "slug": "chopsticks", + "group": "Food & Drink", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿฝ๏ธ": { + "name": "fork and knife with plate", + "slug": "fork_and_knife_with_plate", + "group": "Food & Drink", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿด": { + "name": "fork and knife", + "slug": "fork_and_knife", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅ„": { + "name": "spoon", + "slug": "spoon", + "group": "Food & Drink", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿ”ช": { + "name": "kitchen knife", + "slug": "kitchen_knife", + "group": "Food & Drink", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿซ™": { + "name": "jar", + "slug": "jar", + "group": "Food & Drink", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿบ": { + "name": "amphora", + "slug": "amphora", + "group": "Food & Drink", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸŒ": { + "name": "globe showing Europe-Africa", + "slug": "globe_showing_europe_africa", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒŽ": { + "name": "globe showing Americas", + "slug": "globe_showing_americas", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒ": { + "name": "globe showing Asia-Australia", + "slug": "globe_showing_asia_australia", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒ": { + "name": "globe with meridians", + "slug": "globe_with_meridians", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ—บ๏ธ": { + "name": "world map", + "slug": "world_map", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ—พ": { + "name": "map of Japan", + "slug": "map_of_japan", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿงญ": { + "name": "compass", + "slug": "compass", + "group": "Travel & Places", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿ”๏ธ": { + "name": "snow-capped mountain", + "slug": "snow_capped_mountain", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โ›ฐ๏ธ": { + "name": "mountain", + "slug": "mountain", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒ‹": { + "name": "volcano", + "slug": "volcano", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ—ป": { + "name": "mount fuji", + "slug": "mount_fuji", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•๏ธ": { + "name": "camping", + "slug": "camping", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ–๏ธ": { + "name": "beach with umbrella", + "slug": "beach_with_umbrella", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿœ๏ธ": { + "name": "desert", + "slug": "desert", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ๏ธ": { + "name": "desert island", + "slug": "desert_island", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿž๏ธ": { + "name": "national park", + "slug": "national_park", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŸ๏ธ": { + "name": "stadium", + "slug": "stadium", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ›๏ธ": { + "name": "classical building", + "slug": "classical_building", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ—๏ธ": { + "name": "building construction", + "slug": "building_construction", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿงฑ": { + "name": "brick", + "slug": "brick", + "group": "Travel & Places", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿชจ": { + "name": "rock", + "slug": "rock", + "group": "Travel & Places", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿชต": { + "name": "wood", + "slug": "wood", + "group": "Travel & Places", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿ›–": { + "name": "hut", + "slug": "hut", + "group": "Travel & Places", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿ˜๏ธ": { + "name": "houses", + "slug": "houses", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿš๏ธ": { + "name": "derelict house", + "slug": "derelict_house", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ ": { + "name": "house", + "slug": "house", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿก": { + "name": "house with garden", + "slug": "house_with_garden", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿข": { + "name": "office building", + "slug": "office_building", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฃ": { + "name": "Japanese post office", + "slug": "japanese_post_office", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿค": { + "name": "post office", + "slug": "post_office", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿฅ": { + "name": "hospital", + "slug": "hospital", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฆ": { + "name": "bank", + "slug": "bank", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿจ": { + "name": "hotel", + "slug": "hotel", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฉ": { + "name": "love hotel", + "slug": "love_hotel", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿช": { + "name": "convenience store", + "slug": "convenience_store", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿซ": { + "name": "school", + "slug": "school", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฌ": { + "name": "department store", + "slug": "department_store", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿญ": { + "name": "factory", + "slug": "factory", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฏ": { + "name": "Japanese castle", + "slug": "japanese_castle", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฐ": { + "name": "castle", + "slug": "castle", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’’": { + "name": "wedding", + "slug": "wedding", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ—ผ": { + "name": "Tokyo tower", + "slug": "tokyo_tower", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ—ฝ": { + "name": "Statue of Liberty", + "slug": "statue_of_liberty", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ›ช": { + "name": "church", + "slug": "church", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•Œ": { + "name": "mosque", + "slug": "mosque", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ›•": { + "name": "hindu temple", + "slug": "hindu_temple", + "group": "Travel & Places", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿ•": { + "name": "synagogue", + "slug": "synagogue", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "โ›ฉ๏ธ": { + "name": "shinto shrine", + "slug": "shinto_shrine", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ•‹": { + "name": "kaaba", + "slug": "kaaba", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "โ›ฒ": { + "name": "fountain", + "slug": "fountain", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ›บ": { + "name": "tent", + "slug": "tent", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒ": { + "name": "foggy", + "slug": "foggy", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒƒ": { + "name": "night with stars", + "slug": "night_with_stars", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ™๏ธ": { + "name": "cityscape", + "slug": "cityscape", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒ„": { + "name": "sunrise over mountains", + "slug": "sunrise_over_mountains", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒ…": { + "name": "sunrise", + "slug": "sunrise", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒ†": { + "name": "cityscape at dusk", + "slug": "cityscape_at_dusk", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒ‡": { + "name": "sunset", + "slug": "sunset", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒ‰": { + "name": "bridge at night", + "slug": "bridge_at_night", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™จ๏ธ": { + "name": "hot springs", + "slug": "hot_springs", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ ": { + "name": "carousel horse", + "slug": "carousel_horse", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›": { + "name": "playground slide", + "slug": "playground_slide", + "group": "Travel & Places", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐ŸŽก": { + "name": "ferris wheel", + "slug": "ferris_wheel", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽข": { + "name": "roller coaster", + "slug": "roller_coaster", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ˆ": { + "name": "barber pole", + "slug": "barber_pole", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽช": { + "name": "circus tent", + "slug": "circus_tent", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿš‚": { + "name": "locomotive", + "slug": "locomotive", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿšƒ": { + "name": "railway car", + "slug": "railway_car", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿš„": { + "name": "high-speed train", + "slug": "high_speed_train", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿš…": { + "name": "bullet train", + "slug": "bullet_train", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿš†": { + "name": "train", + "slug": "train", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿš‡": { + "name": "metro", + "slug": "metro", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿšˆ": { + "name": "light rail", + "slug": "light_rail", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿš‰": { + "name": "station", + "slug": "station", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸšŠ": { + "name": "tram", + "slug": "tram", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿš": { + "name": "monorail", + "slug": "monorail", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿšž": { + "name": "mountain railway", + "slug": "mountain_railway", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿš‹": { + "name": "tram car", + "slug": "tram_car", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸšŒ": { + "name": "bus", + "slug": "bus", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿš": { + "name": "oncoming bus", + "slug": "oncoming_bus", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸšŽ": { + "name": "trolleybus", + "slug": "trolleybus", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿš": { + "name": "minibus", + "slug": "minibus", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿš‘": { + "name": "ambulance", + "slug": "ambulance", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿš’": { + "name": "fire engine", + "slug": "fire_engine", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿš“": { + "name": "police car", + "slug": "police_car", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿš”": { + "name": "oncoming police car", + "slug": "oncoming_police_car", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿš•": { + "name": "taxi", + "slug": "taxi", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿš–": { + "name": "oncoming taxi", + "slug": "oncoming_taxi", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿš—": { + "name": "automobile", + "slug": "automobile", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿš˜": { + "name": "oncoming automobile", + "slug": "oncoming_automobile", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿš™": { + "name": "sport utility vehicle", + "slug": "sport_utility_vehicle", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›ป": { + "name": "pickup truck", + "slug": "pickup_truck", + "group": "Travel & Places", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿšš": { + "name": "delivery truck", + "slug": "delivery_truck", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿš›": { + "name": "articulated lorry", + "slug": "articulated_lorry", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿšœ": { + "name": "tractor", + "slug": "tractor", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸŽ๏ธ": { + "name": "racing car", + "slug": "racing_car", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ๏ธ": { + "name": "motorcycle", + "slug": "motorcycle", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ›ต": { + "name": "motor scooter", + "slug": "motor_scooter", + "group": "Travel & Places", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฆฝ": { + "name": "manual wheelchair", + "slug": "manual_wheelchair", + "group": "Travel & Places", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฆผ": { + "name": "motorized wheelchair", + "slug": "motorized_wheelchair", + "group": "Travel & Places", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿ›บ": { + "name": "auto rickshaw", + "slug": "auto_rickshaw", + "group": "Travel & Places", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿšฒ": { + "name": "bicycle", + "slug": "bicycle", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›ด": { + "name": "kick scooter", + "slug": "kick_scooter", + "group": "Travel & Places", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿ›น": { + "name": "skateboard", + "slug": "skateboard", + "group": "Travel & Places", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿ›ผ": { + "name": "roller skate", + "slug": "roller_skate", + "group": "Travel & Places", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿš": { + "name": "bus stop", + "slug": "bus_stop", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›ฃ๏ธ": { + "name": "motorway", + "slug": "motorway", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ›ค๏ธ": { + "name": "railway track", + "slug": "railway_track", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ›ข๏ธ": { + "name": "oil drum", + "slug": "oil_drum", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โ›ฝ": { + "name": "fuel pump", + "slug": "fuel_pump", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›ž": { + "name": "wheel", + "slug": "wheel", + "group": "Travel & Places", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿšจ": { + "name": "police car light", + "slug": "police_car_light", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿšฅ": { + "name": "horizontal traffic light", + "slug": "horizontal_traffic_light", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿšฆ": { + "name": "vertical traffic light", + "slug": "vertical_traffic_light", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ›‘": { + "name": "stop sign", + "slug": "stop_sign", + "group": "Travel & Places", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿšง": { + "name": "construction", + "slug": "construction", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โš“": { + "name": "anchor", + "slug": "anchor", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›Ÿ": { + "name": "ring buoy", + "slug": "ring_buoy", + "group": "Travel & Places", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "โ›ต": { + "name": "sailboat", + "slug": "sailboat", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›ถ": { + "name": "canoe", + "slug": "canoe", + "group": "Travel & Places", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿšค": { + "name": "speedboat", + "slug": "speedboat", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›ณ๏ธ": { + "name": "passenger ship", + "slug": "passenger_ship", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โ›ด๏ธ": { + "name": "ferry", + "slug": "ferry", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ›ฅ๏ธ": { + "name": "motor boat", + "slug": "motor_boat", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿšข": { + "name": "ship", + "slug": "ship", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โœˆ๏ธ": { + "name": "airplane", + "slug": "airplane", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›ฉ๏ธ": { + "name": "small airplane", + "slug": "small_airplane", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ›ซ": { + "name": "airplane departure", + "slug": "airplane_departure", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ›ฌ": { + "name": "airplane arrival", + "slug": "airplane_arrival", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿช‚": { + "name": "parachute", + "slug": "parachute", + "group": "Travel & Places", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿ’บ": { + "name": "seat", + "slug": "seat", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿš": { + "name": "helicopter", + "slug": "helicopter", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸšŸ": { + "name": "suspension railway", + "slug": "suspension_railway", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿš ": { + "name": "mountain cableway", + "slug": "mountain_cableway", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿšก": { + "name": "aerial tramway", + "slug": "aerial_tramway", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ›ฐ๏ธ": { + "name": "satellite", + "slug": "satellite", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿš€": { + "name": "rocket", + "slug": "rocket", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›ธ": { + "name": "flying saucer", + "slug": "flying_saucer", + "group": "Travel & Places", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿ›Ž๏ธ": { + "name": "bellhop bell", + "slug": "bellhop_bell", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿงณ": { + "name": "luggage", + "slug": "luggage", + "group": "Travel & Places", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "โŒ›": { + "name": "hourglass done", + "slug": "hourglass_done", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โณ": { + "name": "hourglass not done", + "slug": "hourglass_not_done", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โŒš": { + "name": "watch", + "slug": "watch", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โฐ": { + "name": "alarm clock", + "slug": "alarm_clock", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โฑ๏ธ": { + "name": "stopwatch", + "slug": "stopwatch", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "โฒ๏ธ": { + "name": "timer clock", + "slug": "timer_clock", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ•ฐ๏ธ": { + "name": "mantelpiece clock", + "slug": "mantelpiece_clock", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ•›": { + "name": "twelve oโ€™clock", + "slug": "twelve_o_clock", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•ง": { + "name": "twelve-thirty", + "slug": "twelve_thirty", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ•": { + "name": "one oโ€™clock", + "slug": "one_o_clock", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•œ": { + "name": "one-thirty", + "slug": "one_thirty", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ•‘": { + "name": "two oโ€™clock", + "slug": "two_o_clock", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•": { + "name": "two-thirty", + "slug": "two_thirty", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ•’": { + "name": "three oโ€™clock", + "slug": "three_o_clock", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•ž": { + "name": "three-thirty", + "slug": "three_thirty", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ•“": { + "name": "four oโ€™clock", + "slug": "four_o_clock", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•Ÿ": { + "name": "four-thirty", + "slug": "four_thirty", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ•”": { + "name": "five oโ€™clock", + "slug": "five_o_clock", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ• ": { + "name": "five-thirty", + "slug": "five_thirty", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ••": { + "name": "six oโ€™clock", + "slug": "six_o_clock", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•ก": { + "name": "six-thirty", + "slug": "six_thirty", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ•–": { + "name": "seven oโ€™clock", + "slug": "seven_o_clock", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•ข": { + "name": "seven-thirty", + "slug": "seven_thirty", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ•—": { + "name": "eight oโ€™clock", + "slug": "eight_o_clock", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•ฃ": { + "name": "eight-thirty", + "slug": "eight_thirty", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ•˜": { + "name": "nine oโ€™clock", + "slug": "nine_o_clock", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•ค": { + "name": "nine-thirty", + "slug": "nine_thirty", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ•™": { + "name": "ten oโ€™clock", + "slug": "ten_o_clock", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•ฅ": { + "name": "ten-thirty", + "slug": "ten_thirty", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ•š": { + "name": "eleven oโ€™clock", + "slug": "eleven_o_clock", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•ฆ": { + "name": "eleven-thirty", + "slug": "eleven_thirty", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒ‘": { + "name": "new moon", + "slug": "new_moon", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒ’": { + "name": "waxing crescent moon", + "slug": "waxing_crescent_moon", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸŒ“": { + "name": "first quarter moon", + "slug": "first_quarter_moon", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒ”": { + "name": "waxing gibbous moon", + "slug": "waxing_gibbous_moon", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒ•": { + "name": "full moon", + "slug": "full_moon", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒ–": { + "name": "waning gibbous moon", + "slug": "waning_gibbous_moon", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸŒ—": { + "name": "last quarter moon", + "slug": "last_quarter_moon", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸŒ˜": { + "name": "waning crescent moon", + "slug": "waning_crescent_moon", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸŒ™": { + "name": "crescent moon", + "slug": "crescent_moon", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒš": { + "name": "new moon face", + "slug": "new_moon_face", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸŒ›": { + "name": "first quarter moon face", + "slug": "first_quarter_moon_face", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒœ": { + "name": "last quarter moon face", + "slug": "last_quarter_moon_face", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒก๏ธ": { + "name": "thermometer", + "slug": "thermometer", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โ˜€๏ธ": { + "name": "sun", + "slug": "sun", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒ": { + "name": "full moon face", + "slug": "full_moon_face", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸŒž": { + "name": "sun with face", + "slug": "sun_with_face", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿช": { + "name": "ringed planet", + "slug": "ringed_planet", + "group": "Travel & Places", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "โญ": { + "name": "star", + "slug": "star", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒŸ": { + "name": "glowing star", + "slug": "glowing_star", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒ ": { + "name": "shooting star", + "slug": "shooting_star", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒŒ": { + "name": "milky way", + "slug": "milky_way", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ˜๏ธ": { + "name": "cloud", + "slug": "cloud", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ›…": { + "name": "sun behind cloud", + "slug": "sun_behind_cloud", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ›ˆ๏ธ": { + "name": "cloud with lightning and rain", + "slug": "cloud_with_lightning_and_rain", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒค๏ธ": { + "name": "sun behind small cloud", + "slug": "sun_behind_small_cloud", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒฅ๏ธ": { + "name": "sun behind large cloud", + "slug": "sun_behind_large_cloud", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒฆ๏ธ": { + "name": "sun behind rain cloud", + "slug": "sun_behind_rain_cloud", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒง๏ธ": { + "name": "cloud with rain", + "slug": "cloud_with_rain", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒจ๏ธ": { + "name": "cloud with snow", + "slug": "cloud_with_snow", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒฉ๏ธ": { + "name": "cloud with lightning", + "slug": "cloud_with_lightning", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒช๏ธ": { + "name": "tornado", + "slug": "tornado", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒซ๏ธ": { + "name": "fog", + "slug": "fog", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒฌ๏ธ": { + "name": "wind face", + "slug": "wind_face", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŒ€": { + "name": "cyclone", + "slug": "cyclone", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒˆ": { + "name": "rainbow", + "slug": "rainbow", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒ‚": { + "name": "closed umbrella", + "slug": "closed_umbrella", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ˜‚๏ธ": { + "name": "umbrella", + "slug": "umbrella", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โ˜”": { + "name": "umbrella with rain drops", + "slug": "umbrella_with_rain_drops", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ›ฑ๏ธ": { + "name": "umbrella on ground", + "slug": "umbrella_on_ground", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โšก": { + "name": "high voltage", + "slug": "high_voltage", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ„๏ธ": { + "name": "snowflake", + "slug": "snowflake", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ˜ƒ๏ธ": { + "name": "snowman", + "slug": "snowman", + "group": "Travel & Places", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โ›„": { + "name": "snowman without snow", + "slug": "snowman_without_snow", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ˜„๏ธ": { + "name": "comet", + "slug": "comet", + "group": "Travel & Places", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ”ฅ": { + "name": "fire", + "slug": "fire", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ง": { + "name": "droplet", + "slug": "droplet", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŒŠ": { + "name": "water wave", + "slug": "water_wave", + "group": "Travel & Places", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽƒ": { + "name": "jack-o-lantern", + "slug": "jack_o_lantern", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ„": { + "name": "Christmas tree", + "slug": "christmas_tree", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ†": { + "name": "fireworks", + "slug": "fireworks", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ‡": { + "name": "sparkler", + "slug": "sparkler", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿงจ": { + "name": "firecracker", + "slug": "firecracker", + "group": "Activities", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "โœจ": { + "name": "sparkles", + "slug": "sparkles", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽˆ": { + "name": "balloon", + "slug": "balloon", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ‰": { + "name": "party popper", + "slug": "party_popper", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽŠ": { + "name": "confetti ball", + "slug": "confetti_ball", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ‹": { + "name": "tanabata tree", + "slug": "tanabata_tree", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ": { + "name": "pine decoration", + "slug": "pine_decoration", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽŽ": { + "name": "Japanese dolls", + "slug": "japanese_dolls", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ": { + "name": "carp streamer", + "slug": "carp_streamer", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ": { + "name": "wind chime", + "slug": "wind_chime", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ‘": { + "name": "moon viewing ceremony", + "slug": "moon_viewing_ceremony", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿงง": { + "name": "red envelope", + "slug": "red_envelope", + "group": "Activities", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐ŸŽ€": { + "name": "ribbon", + "slug": "ribbon", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ": { + "name": "wrapped gift", + "slug": "wrapped_gift", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ—๏ธ": { + "name": "reminder ribbon", + "slug": "reminder_ribbon", + "group": "Activities", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŽŸ๏ธ": { + "name": "admission tickets", + "slug": "admission_tickets", + "group": "Activities", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŽซ": { + "name": "ticket", + "slug": "ticket", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ–๏ธ": { + "name": "military medal", + "slug": "military_medal", + "group": "Activities", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ†": { + "name": "trophy", + "slug": "trophy", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ…": { + "name": "sports medal", + "slug": "sports_medal", + "group": "Activities", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿฅ‡": { + "name": "1st place medal", + "slug": "1st_place_medal", + "group": "Activities", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฅˆ": { + "name": "2nd place medal", + "slug": "2nd_place_medal", + "group": "Activities", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฅ‰": { + "name": "3rd place medal", + "slug": "3rd_place_medal", + "group": "Activities", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "โšฝ": { + "name": "soccer ball", + "slug": "soccer_ball", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โšพ": { + "name": "baseball", + "slug": "baseball", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸฅŽ": { + "name": "softball", + "slug": "softball", + "group": "Activities", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿ€": { + "name": "basketball", + "slug": "basketball", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ": { + "name": "volleyball", + "slug": "volleyball", + "group": "Activities", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿˆ": { + "name": "american football", + "slug": "american_football", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‰": { + "name": "rugby football", + "slug": "rugby_football", + "group": "Activities", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸŽพ": { + "name": "tennis", + "slug": "tennis", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅ": { + "name": "flying disc", + "slug": "flying_disc", + "group": "Activities", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐ŸŽณ": { + "name": "bowling", + "slug": "bowling", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ": { + "name": "cricket game", + "slug": "cricket_game", + "group": "Activities", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ‘": { + "name": "field hockey", + "slug": "field_hockey", + "group": "Activities", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ’": { + "name": "ice hockey", + "slug": "ice_hockey", + "group": "Activities", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿฅ": { + "name": "lacrosse", + "slug": "lacrosse", + "group": "Activities", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿ“": { + "name": "ping pong", + "slug": "ping_pong", + "group": "Activities", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿธ": { + "name": "badminton", + "slug": "badminton", + "group": "Activities", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸฅŠ": { + "name": "boxing glove", + "slug": "boxing_glove", + "group": "Activities", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฅ‹": { + "name": "martial arts uniform", + "slug": "martial_arts_uniform", + "group": "Activities", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿฅ…": { + "name": "goal net", + "slug": "goal_net", + "group": "Activities", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "โ›ณ": { + "name": "flag in hole", + "slug": "flag_in_hole", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ›ธ๏ธ": { + "name": "ice skate", + "slug": "ice_skate", + "group": "Activities", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŽฃ": { + "name": "fishing pole", + "slug": "fishing_pole", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿคฟ": { + "name": "diving mask", + "slug": "diving_mask", + "group": "Activities", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐ŸŽฝ": { + "name": "running shirt", + "slug": "running_shirt", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽฟ": { + "name": "skis", + "slug": "skis", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›ท": { + "name": "sled", + "slug": "sled", + "group": "Activities", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐ŸฅŒ": { + "name": "curling stone", + "slug": "curling_stone", + "group": "Activities", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐ŸŽฏ": { + "name": "bullseye", + "slug": "bullseye", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿช€": { + "name": "yo-yo", + "slug": "yo_yo", + "group": "Activities", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿช": { + "name": "kite", + "slug": "kite", + "group": "Activities", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿ”ซ": { + "name": "water pistol", + "slug": "water_pistol", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽฑ": { + "name": "pool 8 ball", + "slug": "pool_8_ball", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ฎ": { + "name": "crystal ball", + "slug": "crystal_ball", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿช„": { + "name": "magic wand", + "slug": "magic_wand", + "group": "Activities", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐ŸŽฎ": { + "name": "video game", + "slug": "video_game", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•น๏ธ": { + "name": "joystick", + "slug": "joystick", + "group": "Activities", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŽฐ": { + "name": "slot machine", + "slug": "slot_machine", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽฒ": { + "name": "game die", + "slug": "game_die", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿงฉ": { + "name": "puzzle piece", + "slug": "puzzle_piece", + "group": "Activities", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿงธ": { + "name": "teddy bear", + "slug": "teddy_bear", + "group": "Activities", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿช…": { + "name": "piรฑata", + "slug": "pinata", + "group": "Activities", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿชฉ": { + "name": "mirror ball", + "slug": "mirror_ball", + "group": "Activities", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿช†": { + "name": "nesting dolls", + "slug": "nesting_dolls", + "group": "Activities", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "โ™ ๏ธ": { + "name": "spade suit", + "slug": "spade_suit", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™ฅ๏ธ": { + "name": "heart suit", + "slug": "heart_suit", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™ฆ๏ธ": { + "name": "diamond suit", + "slug": "diamond_suit", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™ฃ๏ธ": { + "name": "club suit", + "slug": "club_suit", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™Ÿ๏ธ": { + "name": "chess pawn", + "slug": "chess_pawn", + "group": "Activities", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿƒ": { + "name": "joker", + "slug": "joker", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ€„": { + "name": "mahjong red dragon", + "slug": "mahjong_red_dragon", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽด": { + "name": "flower playing cards", + "slug": "flower_playing_cards", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽญ": { + "name": "performing arts", + "slug": "performing_arts", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ–ผ๏ธ": { + "name": "framed picture", + "slug": "framed_picture", + "group": "Activities", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŽจ": { + "name": "artist palette", + "slug": "artist_palette", + "group": "Activities", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿงต": { + "name": "thread", + "slug": "thread", + "group": "Activities", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿชก": { + "name": "sewing needle", + "slug": "sewing_needle", + "group": "Activities", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿงถ": { + "name": "yarn", + "slug": "yarn", + "group": "Activities", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿชข": { + "name": "knot", + "slug": "knot", + "group": "Activities", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿ‘“": { + "name": "glasses", + "slug": "glasses", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•ถ๏ธ": { + "name": "sunglasses", + "slug": "sunglasses", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿฅฝ": { + "name": "goggles", + "slug": "goggles", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฅผ": { + "name": "lab coat", + "slug": "lab_coat", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฆบ": { + "name": "safety vest", + "slug": "safety_vest", + "group": "Objects", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿ‘”": { + "name": "necktie", + "slug": "necktie", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘•": { + "name": "t-shirt", + "slug": "t_shirt", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘–": { + "name": "jeans", + "slug": "jeans", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿงฃ": { + "name": "scarf", + "slug": "scarf", + "group": "Objects", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿงค": { + "name": "gloves", + "slug": "gloves", + "group": "Objects", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿงฅ": { + "name": "coat", + "slug": "coat", + "group": "Objects", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿงฆ": { + "name": "socks", + "slug": "socks", + "group": "Objects", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿ‘—": { + "name": "dress", + "slug": "dress", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘˜": { + "name": "kimono", + "slug": "kimono", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅป": { + "name": "sari", + "slug": "sari", + "group": "Objects", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฉฑ": { + "name": "one-piece swimsuit", + "slug": "one_piece_swimsuit", + "group": "Objects", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฉฒ": { + "name": "briefs", + "slug": "briefs", + "group": "Objects", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฉณ": { + "name": "shorts", + "slug": "shorts", + "group": "Objects", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿ‘™": { + "name": "bikini", + "slug": "bikini", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘š": { + "name": "womanโ€™s clothes", + "slug": "woman_s_clothes", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿชญ": { + "name": "folding hand fan", + "slug": "folding_hand_fan", + "group": "Objects", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐Ÿ‘›": { + "name": "purse", + "slug": "purse", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘œ": { + "name": "handbag", + "slug": "handbag", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘": { + "name": "clutch bag", + "slug": "clutch_bag", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›๏ธ": { + "name": "shopping bags", + "slug": "shopping_bags", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŽ’": { + "name": "backpack", + "slug": "backpack", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฉด": { + "name": "thong sandal", + "slug": "thong_sandal", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿ‘ž": { + "name": "manโ€™s shoe", + "slug": "man_s_shoe", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘Ÿ": { + "name": "running shoe", + "slug": "running_shoe", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฅพ": { + "name": "hiking boot", + "slug": "hiking_boot", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿฅฟ": { + "name": "flat shoe", + "slug": "flat_shoe", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿ‘ ": { + "name": "high-heeled shoe", + "slug": "high_heeled_shoe", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘ก": { + "name": "womanโ€™s sandal", + "slug": "woman_s_sandal", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฉฐ": { + "name": "ballet shoes", + "slug": "ballet_shoes", + "group": "Objects", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿ‘ข": { + "name": "womanโ€™s boot", + "slug": "woman_s_boot", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿชฎ": { + "name": "hair pick", + "slug": "hair_pick", + "group": "Objects", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐Ÿ‘‘": { + "name": "crown", + "slug": "crown", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‘’": { + "name": "womanโ€™s hat", + "slug": "woman_s_hat", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽฉ": { + "name": "top hat", + "slug": "top_hat", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ“": { + "name": "graduation cap", + "slug": "graduation_cap", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿงข": { + "name": "billed cap", + "slug": "billed_cap", + "group": "Objects", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿช–": { + "name": "military helmet", + "slug": "military_helmet", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "โ›‘๏ธ": { + "name": "rescue workerโ€™s helmet", + "slug": "rescue_worker_s_helmet", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ“ฟ": { + "name": "prayer beads", + "slug": "prayer_beads", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ’„": { + "name": "lipstick", + "slug": "lipstick", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’": { + "name": "ring", + "slug": "ring", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’Ž": { + "name": "gem stone", + "slug": "gem_stone", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”‡": { + "name": "muted speaker", + "slug": "muted_speaker", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ”ˆ": { + "name": "speaker low volume", + "slug": "speaker_low_volume", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ”‰": { + "name": "speaker medium volume", + "slug": "speaker_medium_volume", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ”Š": { + "name": "speaker high volume", + "slug": "speaker_high_volume", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ข": { + "name": "loudspeaker", + "slug": "loudspeaker", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ฃ": { + "name": "megaphone", + "slug": "megaphone", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ฏ": { + "name": "postal horn", + "slug": "postal_horn", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ””": { + "name": "bell", + "slug": "bell", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”•": { + "name": "bell with slash", + "slug": "bell_with_slash", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸŽผ": { + "name": "musical score", + "slug": "musical_score", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽต": { + "name": "musical note", + "slug": "musical_note", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽถ": { + "name": "musical notes", + "slug": "musical_notes", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽ™๏ธ": { + "name": "studio microphone", + "slug": "studio_microphone", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŽš๏ธ": { + "name": "level slider", + "slug": "level_slider", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŽ›๏ธ": { + "name": "control knobs", + "slug": "control_knobs", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŽค": { + "name": "microphone", + "slug": "microphone", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽง": { + "name": "headphone", + "slug": "headphone", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ป": { + "name": "radio", + "slug": "radio", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽท": { + "name": "saxophone", + "slug": "saxophone", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿช—": { + "name": "accordion", + "slug": "accordion", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐ŸŽธ": { + "name": "guitar", + "slug": "guitar", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽน": { + "name": "musical keyboard", + "slug": "musical_keyboard", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽบ": { + "name": "trumpet", + "slug": "trumpet", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽป": { + "name": "violin", + "slug": "violin", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿช•": { + "name": "banjo", + "slug": "banjo", + "group": "Objects", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฅ": { + "name": "drum", + "slug": "drum", + "group": "Objects", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿช˜": { + "name": "long drum", + "slug": "long_drum", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿช‡": { + "name": "maracas", + "slug": "maracas", + "group": "Objects", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐Ÿชˆ": { + "name": "flute", + "slug": "flute", + "group": "Objects", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐Ÿ“ฑ": { + "name": "mobile phone", + "slug": "mobile_phone", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ฒ": { + "name": "mobile phone with arrow", + "slug": "mobile_phone_with_arrow", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ˜Ž๏ธ": { + "name": "telephone", + "slug": "telephone", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ž": { + "name": "telephone receiver", + "slug": "telephone_receiver", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“Ÿ": { + "name": "pager", + "slug": "pager", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ ": { + "name": "fax machine", + "slug": "fax_machine", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”‹": { + "name": "battery", + "slug": "battery", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿชซ": { + "name": "low battery", + "slug": "low_battery", + "group": "Objects", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿ”Œ": { + "name": "electric plug", + "slug": "electric_plug", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ป": { + "name": "laptop", + "slug": "laptop", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ–ฅ๏ธ": { + "name": "desktop computer", + "slug": "desktop_computer", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ–จ๏ธ": { + "name": "printer", + "slug": "printer", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โŒจ๏ธ": { + "name": "keyboard", + "slug": "keyboard", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ–ฑ๏ธ": { + "name": "computer mouse", + "slug": "computer_mouse", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ–ฒ๏ธ": { + "name": "trackball", + "slug": "trackball", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ’ฝ": { + "name": "computer disk", + "slug": "computer_disk", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’พ": { + "name": "floppy disk", + "slug": "floppy_disk", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ฟ": { + "name": "optical disk", + "slug": "optical_disk", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“€": { + "name": "dvd", + "slug": "dvd", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿงฎ": { + "name": "abacus", + "slug": "abacus", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐ŸŽฅ": { + "name": "movie camera", + "slug": "movie_camera", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽž๏ธ": { + "name": "film frames", + "slug": "film_frames", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ“ฝ๏ธ": { + "name": "film projector", + "slug": "film_projector", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐ŸŽฌ": { + "name": "clapper board", + "slug": "clapper_board", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“บ": { + "name": "television", + "slug": "television", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ท": { + "name": "camera", + "slug": "camera", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ธ": { + "name": "camera with flash", + "slug": "camera_with_flash", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ“น": { + "name": "video camera", + "slug": "video_camera", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ผ": { + "name": "videocassette", + "slug": "videocassette", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”": { + "name": "magnifying glass tilted left", + "slug": "magnifying_glass_tilted_left", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”Ž": { + "name": "magnifying glass tilted right", + "slug": "magnifying_glass_tilted_right", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ•ฏ๏ธ": { + "name": "candle", + "slug": "candle", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ’ก": { + "name": "light bulb", + "slug": "light_bulb", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ฆ": { + "name": "flashlight", + "slug": "flashlight", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฎ": { + "name": "red paper lantern", + "slug": "red_paper_lantern", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿช”": { + "name": "diya lamp", + "slug": "diya_lamp", + "group": "Objects", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿ“”": { + "name": "notebook with decorative cover", + "slug": "notebook_with_decorative_cover", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“•": { + "name": "closed book", + "slug": "closed_book", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“–": { + "name": "open book", + "slug": "open_book", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“—": { + "name": "green book", + "slug": "green_book", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“˜": { + "name": "blue book", + "slug": "blue_book", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“™": { + "name": "orange book", + "slug": "orange_book", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“š": { + "name": "books", + "slug": "books", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ““": { + "name": "notebook", + "slug": "notebook", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“’": { + "name": "ledger", + "slug": "ledger", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ƒ": { + "name": "page with curl", + "slug": "page_with_curl", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“œ": { + "name": "scroll", + "slug": "scroll", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“„": { + "name": "page facing up", + "slug": "page_facing_up", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ฐ": { + "name": "newspaper", + "slug": "newspaper", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ—ž๏ธ": { + "name": "rolled-up newspaper", + "slug": "rolled_up_newspaper", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ“‘": { + "name": "bookmark tabs", + "slug": "bookmark_tabs", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”–": { + "name": "bookmark", + "slug": "bookmark", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿท๏ธ": { + "name": "label", + "slug": "label", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ’ฐ": { + "name": "money bag", + "slug": "money_bag", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿช™": { + "name": "coin", + "slug": "coin", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿ’ด": { + "name": "yen banknote", + "slug": "yen_banknote", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ต": { + "name": "dollar banknote", + "slug": "dollar_banknote", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ถ": { + "name": "euro banknote", + "slug": "euro_banknote", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ’ท": { + "name": "pound banknote", + "slug": "pound_banknote", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ’ธ": { + "name": "money with wings", + "slug": "money_with_wings", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ณ": { + "name": "credit card", + "slug": "credit_card", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿงพ": { + "name": "receipt", + "slug": "receipt", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿ’น": { + "name": "chart increasing with yen", + "slug": "chart_increasing_with_yen", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โœ‰๏ธ": { + "name": "envelope", + "slug": "envelope", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ง": { + "name": "e-mail", + "slug": "e_mail", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“จ": { + "name": "incoming envelope", + "slug": "incoming_envelope", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ฉ": { + "name": "envelope with arrow", + "slug": "envelope_with_arrow", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ค": { + "name": "outbox tray", + "slug": "outbox_tray", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ฅ": { + "name": "inbox tray", + "slug": "inbox_tray", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ฆ": { + "name": "package", + "slug": "package", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ซ": { + "name": "closed mailbox with raised flag", + "slug": "closed_mailbox_with_raised_flag", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ช": { + "name": "closed mailbox with lowered flag", + "slug": "closed_mailbox_with_lowered_flag", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ฌ": { + "name": "open mailbox with raised flag", + "slug": "open_mailbox_with_raised_flag", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ“ญ": { + "name": "open mailbox with lowered flag", + "slug": "open_mailbox_with_lowered_flag", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ“ฎ": { + "name": "postbox", + "slug": "postbox", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ—ณ๏ธ": { + "name": "ballot box with ballot", + "slug": "ballot_box_with_ballot", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โœ๏ธ": { + "name": "pencil", + "slug": "pencil", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โœ’๏ธ": { + "name": "black nib", + "slug": "black_nib", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ–‹๏ธ": { + "name": "fountain pen", + "slug": "fountain_pen", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ–Š๏ธ": { + "name": "pen", + "slug": "pen", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ–Œ๏ธ": { + "name": "paintbrush", + "slug": "paintbrush", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ–๏ธ": { + "name": "crayon", + "slug": "crayon", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ“": { + "name": "memo", + "slug": "memo", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ผ": { + "name": "briefcase", + "slug": "briefcase", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“": { + "name": "file folder", + "slug": "file_folder", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“‚": { + "name": "open file folder", + "slug": "open_file_folder", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ—‚๏ธ": { + "name": "card index dividers", + "slug": "card_index_dividers", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ“…": { + "name": "calendar", + "slug": "calendar", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“†": { + "name": "tear-off calendar", + "slug": "tear_off_calendar", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ—’๏ธ": { + "name": "spiral notepad", + "slug": "spiral_notepad", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ—“๏ธ": { + "name": "spiral calendar", + "slug": "spiral_calendar", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ“‡": { + "name": "card index", + "slug": "card_index", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ˆ": { + "name": "chart increasing", + "slug": "chart_increasing", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“‰": { + "name": "chart decreasing", + "slug": "chart_decreasing", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“Š": { + "name": "bar chart", + "slug": "bar_chart", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“‹": { + "name": "clipboard", + "slug": "clipboard", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“Œ": { + "name": "pushpin", + "slug": "pushpin", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“": { + "name": "round pushpin", + "slug": "round_pushpin", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“Ž": { + "name": "paperclip", + "slug": "paperclip", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ–‡๏ธ": { + "name": "linked paperclips", + "slug": "linked_paperclips", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ“": { + "name": "straight ruler", + "slug": "straight_ruler", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“": { + "name": "triangular ruler", + "slug": "triangular_ruler", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โœ‚๏ธ": { + "name": "scissors", + "slug": "scissors", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ—ƒ๏ธ": { + "name": "card file box", + "slug": "card_file_box", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ—„๏ธ": { + "name": "file cabinet", + "slug": "file_cabinet", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ—‘๏ธ": { + "name": "wastebasket", + "slug": "wastebasket", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ”’": { + "name": "locked", + "slug": "locked", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”“": { + "name": "unlocked", + "slug": "unlocked", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”": { + "name": "locked with pen", + "slug": "locked_with_pen", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”": { + "name": "locked with key", + "slug": "locked_with_key", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”‘": { + "name": "key", + "slug": "key", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ—๏ธ": { + "name": "old key", + "slug": "old_key", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ”จ": { + "name": "hammer", + "slug": "hammer", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿช“": { + "name": "axe", + "slug": "axe", + "group": "Objects", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "โ›๏ธ": { + "name": "pick", + "slug": "pick", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โš’๏ธ": { + "name": "hammer and pick", + "slug": "hammer_and_pick", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ› ๏ธ": { + "name": "hammer and wrench", + "slug": "hammer_and_wrench", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ—ก๏ธ": { + "name": "dagger", + "slug": "dagger", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โš”๏ธ": { + "name": "crossed swords", + "slug": "crossed_swords", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ’ฃ": { + "name": "bomb", + "slug": "bomb", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿชƒ": { + "name": "boomerang", + "slug": "boomerang", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿน": { + "name": "bow and arrow", + "slug": "bow_and_arrow", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ›ก๏ธ": { + "name": "shield", + "slug": "shield", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿชš": { + "name": "carpentry saw", + "slug": "carpentry_saw", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿ”ง": { + "name": "wrench", + "slug": "wrench", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿช›": { + "name": "screwdriver", + "slug": "screwdriver", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿ”ฉ": { + "name": "nut and bolt", + "slug": "nut_and_bolt", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โš™๏ธ": { + "name": "gear", + "slug": "gear", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ—œ๏ธ": { + "name": "clamp", + "slug": "clamp", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โš–๏ธ": { + "name": "balance scale", + "slug": "balance_scale", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿฆฏ": { + "name": "white cane", + "slug": "white_cane", + "group": "Objects", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿ”—": { + "name": "link", + "slug": "link", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ›“๏ธโ€๐Ÿ’ฅ": { + "name": "broken chain", + "slug": "broken_chain", + "group": "Objects", + "emoji_version": "15.1", + "unicode_version": "15.1", + "skin_tone_support": false + }, + "โ›“๏ธ": { + "name": "chains", + "slug": "chains", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿช": { + "name": "hook", + "slug": "hook", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿงฐ": { + "name": "toolbox", + "slug": "toolbox", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿงฒ": { + "name": "magnet", + "slug": "magnet", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿชœ": { + "name": "ladder", + "slug": "ladder", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "โš—๏ธ": { + "name": "alembic", + "slug": "alembic", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿงช": { + "name": "test tube", + "slug": "test_tube", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿงซ": { + "name": "petri dish", + "slug": "petri_dish", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿงฌ": { + "name": "dna", + "slug": "dna", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿ”ฌ": { + "name": "microscope", + "slug": "microscope", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ”ญ": { + "name": "telescope", + "slug": "telescope", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ“ก": { + "name": "satellite antenna", + "slug": "satellite_antenna", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’‰": { + "name": "syringe", + "slug": "syringe", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฉธ": { + "name": "drop of blood", + "slug": "drop_of_blood", + "group": "Objects", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿ’Š": { + "name": "pill", + "slug": "pill", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿฉน": { + "name": "adhesive bandage", + "slug": "adhesive_bandage", + "group": "Objects", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฉผ": { + "name": "crutch", + "slug": "crutch", + "group": "Objects", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿฉบ": { + "name": "stethoscope", + "slug": "stethoscope", + "group": "Objects", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿฉป": { + "name": "x-ray", + "slug": "x_ray", + "group": "Objects", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿšช": { + "name": "door", + "slug": "door", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›—": { + "name": "elevator", + "slug": "elevator", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿชž": { + "name": "mirror", + "slug": "mirror", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐ŸชŸ": { + "name": "window", + "slug": "window", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿ›๏ธ": { + "name": "bed", + "slug": "bed", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ›‹๏ธ": { + "name": "couch and lamp", + "slug": "couch_and_lamp", + "group": "Objects", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿช‘": { + "name": "chair", + "slug": "chair", + "group": "Objects", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿšฝ": { + "name": "toilet", + "slug": "toilet", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿช ": { + "name": "plunger", + "slug": "plunger", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿšฟ": { + "name": "shower", + "slug": "shower", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ›": { + "name": "bathtub", + "slug": "bathtub", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿชค": { + "name": "mouse trap", + "slug": "mouse_trap", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿช’": { + "name": "razor", + "slug": "razor", + "group": "Objects", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿงด": { + "name": "lotion bottle", + "slug": "lotion_bottle", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿงท": { + "name": "safety pin", + "slug": "safety_pin", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿงน": { + "name": "broom", + "slug": "broom", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿงบ": { + "name": "basket", + "slug": "basket", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿงป": { + "name": "roll of paper", + "slug": "roll_of_paper", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿชฃ": { + "name": "bucket", + "slug": "bucket", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿงผ": { + "name": "soap", + "slug": "soap", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿซง": { + "name": "bubbles", + "slug": "bubbles", + "group": "Objects", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿชฅ": { + "name": "toothbrush", + "slug": "toothbrush", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿงฝ": { + "name": "sponge", + "slug": "sponge", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿงฏ": { + "name": "fire extinguisher", + "slug": "fire_extinguisher", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿ›’": { + "name": "shopping cart", + "slug": "shopping_cart", + "group": "Objects", + "emoji_version": "3.0", + "unicode_version": "3.0", + "skin_tone_support": false + }, + "๐Ÿšฌ": { + "name": "cigarette", + "slug": "cigarette", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โšฐ๏ธ": { + "name": "coffin", + "slug": "coffin", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿชฆ": { + "name": "headstone", + "slug": "headstone", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "โšฑ๏ธ": { + "name": "funeral urn", + "slug": "funeral_urn", + "group": "Objects", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿงฟ": { + "name": "nazar amulet", + "slug": "nazar_amulet", + "group": "Objects", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿชฌ": { + "name": "hamsa", + "slug": "hamsa", + "group": "Objects", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿ—ฟ": { + "name": "moai", + "slug": "moai", + "group": "Objects", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿชง": { + "name": "placard", + "slug": "placard", + "group": "Objects", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿชช": { + "name": "identification card", + "slug": "identification_card", + "group": "Objects", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "๐Ÿง": { + "name": "ATM sign", + "slug": "atm_sign", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿšฎ": { + "name": "litter in bin sign", + "slug": "litter_in_bin_sign", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿšฐ": { + "name": "potable water", + "slug": "potable_water", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "โ™ฟ": { + "name": "wheelchair symbol", + "slug": "wheelchair_symbol", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿšน": { + "name": "menโ€™s room", + "slug": "men_s_room", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿšบ": { + "name": "womenโ€™s room", + "slug": "women_s_room", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿšป": { + "name": "restroom", + "slug": "restroom", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿšผ": { + "name": "baby symbol", + "slug": "baby_symbol", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿšพ": { + "name": "water closet", + "slug": "water_closet", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›‚": { + "name": "passport control", + "slug": "passport_control", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ›ƒ": { + "name": "customs", + "slug": "customs", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ›„": { + "name": "baggage claim", + "slug": "baggage_claim", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ›…": { + "name": "left luggage", + "slug": "left_luggage", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "โš ๏ธ": { + "name": "warning", + "slug": "warning", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿšธ": { + "name": "children crossing", + "slug": "children_crossing", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "โ›”": { + "name": "no entry", + "slug": "no_entry", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿšซ": { + "name": "prohibited", + "slug": "prohibited", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿšณ": { + "name": "no bicycles", + "slug": "no_bicycles", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿšญ": { + "name": "no smoking", + "slug": "no_smoking", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿšฏ": { + "name": "no littering", + "slug": "no_littering", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿšฑ": { + "name": "non-potable water", + "slug": "non_potable_water", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿšท": { + "name": "no pedestrians", + "slug": "no_pedestrians", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ“ต": { + "name": "no mobile phones", + "slug": "no_mobile_phones", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ”ž": { + "name": "no one under eighteen", + "slug": "no_one_under_eighteen", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ˜ข๏ธ": { + "name": "radioactive", + "slug": "radioactive", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "โ˜ฃ๏ธ": { + "name": "biohazard", + "slug": "biohazard", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "โฌ†๏ธ": { + "name": "up arrow", + "slug": "up_arrow", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ†—๏ธ": { + "name": "up-right arrow", + "slug": "up_right_arrow", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โžก๏ธ": { + "name": "right arrow", + "slug": "right_arrow", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ†˜๏ธ": { + "name": "down-right arrow", + "slug": "down_right_arrow", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โฌ‡๏ธ": { + "name": "down arrow", + "slug": "down_arrow", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ†™๏ธ": { + "name": "down-left arrow", + "slug": "down_left_arrow", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โฌ…๏ธ": { + "name": "left arrow", + "slug": "left_arrow", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ†–๏ธ": { + "name": "up-left arrow", + "slug": "up_left_arrow", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ†•๏ธ": { + "name": "up-down arrow", + "slug": "up_down_arrow", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ†”๏ธ": { + "name": "left-right arrow", + "slug": "left_right_arrow", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ†ฉ๏ธ": { + "name": "right arrow curving left", + "slug": "right_arrow_curving_left", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ†ช๏ธ": { + "name": "left arrow curving right", + "slug": "left_arrow_curving_right", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โคด๏ธ": { + "name": "right arrow curving up", + "slug": "right_arrow_curving_up", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โคต๏ธ": { + "name": "right arrow curving down", + "slug": "right_arrow_curving_down", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ƒ": { + "name": "clockwise vertical arrows", + "slug": "clockwise_vertical_arrows", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”„": { + "name": "counterclockwise arrows button", + "slug": "counterclockwise_arrows_button", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ”™": { + "name": "BACK arrow", + "slug": "back_arrow", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”š": { + "name": "END arrow", + "slug": "end_arrow", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”›": { + "name": "ON! arrow", + "slug": "on_arrow", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”œ": { + "name": "SOON arrow", + "slug": "soon_arrow", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”": { + "name": "TOP arrow", + "slug": "top_arrow", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›": { + "name": "place of worship", + "slug": "place_of_worship", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "โš›๏ธ": { + "name": "atom symbol", + "slug": "atom_symbol", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ•‰๏ธ": { + "name": "om", + "slug": "om", + "group": "Symbols", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โœก๏ธ": { + "name": "star of David", + "slug": "star_of_david", + "group": "Symbols", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โ˜ธ๏ธ": { + "name": "wheel of dharma", + "slug": "wheel_of_dharma", + "group": "Symbols", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โ˜ฏ๏ธ": { + "name": "yin yang", + "slug": "yin_yang", + "group": "Symbols", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โœ๏ธ": { + "name": "latin cross", + "slug": "latin_cross", + "group": "Symbols", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โ˜ฆ๏ธ": { + "name": "orthodox cross", + "slug": "orthodox_cross", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "โ˜ช๏ธ": { + "name": "star and crescent", + "slug": "star_and_crescent", + "group": "Symbols", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โ˜ฎ๏ธ": { + "name": "peace symbol", + "slug": "peace_symbol", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ•Ž": { + "name": "menorah", + "slug": "menorah", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ”ฏ": { + "name": "dotted six-pointed star", + "slug": "dotted_six_pointed_star", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿชฏ": { + "name": "khanda", + "slug": "khanda", + "group": "Symbols", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "โ™ˆ": { + "name": "Aries", + "slug": "aries", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™‰": { + "name": "Taurus", + "slug": "taurus", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™Š": { + "name": "Gemini", + "slug": "gemini", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™‹": { + "name": "Cancer", + "slug": "cancer", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™Œ": { + "name": "Leo", + "slug": "leo", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™": { + "name": "Virgo", + "slug": "virgo", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™Ž": { + "name": "Libra", + "slug": "libra", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™": { + "name": "Scorpio", + "slug": "scorpio", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™": { + "name": "Sagittarius", + "slug": "sagittarius", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™‘": { + "name": "Capricorn", + "slug": "capricorn", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™’": { + "name": "Aquarius", + "slug": "aquarius", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™“": { + "name": "Pisces", + "slug": "pisces", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ›Ž": { + "name": "Ophiuchus", + "slug": "ophiuchus", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”€": { + "name": "shuffle tracks button", + "slug": "shuffle_tracks_button", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ”": { + "name": "repeat button", + "slug": "repeat_button", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ”‚": { + "name": "repeat single button", + "slug": "repeat_single_button", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "โ–ถ๏ธ": { + "name": "play button", + "slug": "play_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โฉ": { + "name": "fast-forward button", + "slug": "fast_forward_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โญ๏ธ": { + "name": "next track button", + "slug": "next_track_button", + "group": "Symbols", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โฏ๏ธ": { + "name": "play or pause button", + "slug": "play_or_pause_button", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "โ—€๏ธ": { + "name": "reverse button", + "slug": "reverse_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โช": { + "name": "fast reverse button", + "slug": "fast_reverse_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โฎ๏ธ": { + "name": "last track button", + "slug": "last_track_button", + "group": "Symbols", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿ”ผ": { + "name": "upwards button", + "slug": "upwards_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โซ": { + "name": "fast up button", + "slug": "fast_up_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ฝ": { + "name": "downwards button", + "slug": "downwards_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โฌ": { + "name": "fast down button", + "slug": "fast_down_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โธ๏ธ": { + "name": "pause button", + "slug": "pause_button", + "group": "Symbols", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โน๏ธ": { + "name": "stop button", + "slug": "stop_button", + "group": "Symbols", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โบ๏ธ": { + "name": "record button", + "slug": "record_button", + "group": "Symbols", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "โ๏ธ": { + "name": "eject button", + "slug": "eject_button", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐ŸŽฆ": { + "name": "cinema", + "slug": "cinema", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”…": { + "name": "dim button", + "slug": "dim_button", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ”†": { + "name": "bright button", + "slug": "bright_button", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ“ถ": { + "name": "antenna bars", + "slug": "antenna_bars", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ›œ": { + "name": "wireless", + "slug": "wireless", + "group": "Symbols", + "emoji_version": "15.0", + "unicode_version": "15.0", + "skin_tone_support": false + }, + "๐Ÿ“ณ": { + "name": "vibration mode", + "slug": "vibration_mode", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“ด": { + "name": "mobile phone off", + "slug": "mobile_phone_off", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ™€๏ธ": { + "name": "female sign", + "slug": "female_sign", + "group": "Symbols", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "โ™‚๏ธ": { + "name": "male sign", + "slug": "male_sign", + "group": "Symbols", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "โšง๏ธ": { + "name": "transgender symbol", + "slug": "transgender_symbol", + "group": "Symbols", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "โœ–๏ธ": { + "name": "multiply", + "slug": "multiply", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โž•": { + "name": "plus", + "slug": "plus", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โž–": { + "name": "minus", + "slug": "minus", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โž—": { + "name": "divide", + "slug": "divide", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŸฐ": { + "name": "heavy equals sign", + "slug": "heavy_equals_sign", + "group": "Symbols", + "emoji_version": "14.0", + "unicode_version": "14.0", + "skin_tone_support": false + }, + "โ™พ๏ธ": { + "name": "infinity", + "slug": "infinity", + "group": "Symbols", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "โ€ผ๏ธ": { + "name": "double exclamation mark", + "slug": "double_exclamation_mark", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ‰๏ธ": { + "name": "exclamation question mark", + "slug": "exclamation_question_mark", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ“": { + "name": "red question mark", + "slug": "red_question_mark", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ”": { + "name": "white question mark", + "slug": "white_question_mark", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ•": { + "name": "white exclamation mark", + "slug": "white_exclamation_mark", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ—": { + "name": "red exclamation mark", + "slug": "red_exclamation_mark", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "ใ€ฐ๏ธ": { + "name": "wavy dash", + "slug": "wavy_dash", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ฑ": { + "name": "currency exchange", + "slug": "currency_exchange", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ฒ": { + "name": "heavy dollar sign", + "slug": "heavy_dollar_sign", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โš•๏ธ": { + "name": "medical symbol", + "slug": "medical_symbol", + "group": "Symbols", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "โ™ป๏ธ": { + "name": "recycling symbol", + "slug": "recycling_symbol", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โšœ๏ธ": { + "name": "fleur-de-lis", + "slug": "fleur_de_lis", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿ”ฑ": { + "name": "trident emblem", + "slug": "trident_emblem", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ“›": { + "name": "name badge", + "slug": "name_badge", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ฐ": { + "name": "Japanese symbol for beginner", + "slug": "japanese_symbol_for_beginner", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โญ•": { + "name": "hollow red circle", + "slug": "hollow_red_circle", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โœ…": { + "name": "check mark button", + "slug": "check_mark_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ˜‘๏ธ": { + "name": "check box with check", + "slug": "check_box_with_check", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โœ”๏ธ": { + "name": "check mark", + "slug": "check_mark", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โŒ": { + "name": "cross mark", + "slug": "cross_mark", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โŽ": { + "name": "cross mark button", + "slug": "cross_mark_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โžฐ": { + "name": "curly loop", + "slug": "curly_loop", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โžฟ": { + "name": "double curly loop", + "slug": "double_curly_loop", + "group": "Symbols", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "ใ€ฝ๏ธ": { + "name": "part alternation mark", + "slug": "part_alternation_mark", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โœณ๏ธ": { + "name": "eight-spoked asterisk", + "slug": "eight_spoked_asterisk", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โœด๏ธ": { + "name": "eight-pointed star", + "slug": "eight_pointed_star", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ‡๏ธ": { + "name": "sparkle", + "slug": "sparkle", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "ยฉ๏ธ": { + "name": "copyright", + "slug": "copyright", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "ยฎ๏ธ": { + "name": "registered", + "slug": "registered", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ„ข๏ธ": { + "name": "trade mark", + "slug": "trade_mark", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "#๏ธโƒฃ": { + "name": "keycap #", + "slug": "keycap_number_sign", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "*๏ธโƒฃ": { + "name": "keycap *", + "slug": "keycap_asterisk", + "group": "Symbols", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "0๏ธโƒฃ": { + "name": "keycap 0", + "slug": "keycap_0", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "1๏ธโƒฃ": { + "name": "keycap 1", + "slug": "keycap_1", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "2๏ธโƒฃ": { + "name": "keycap 2", + "slug": "keycap_2", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "3๏ธโƒฃ": { + "name": "keycap 3", + "slug": "keycap_3", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "4๏ธโƒฃ": { + "name": "keycap 4", + "slug": "keycap_4", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "5๏ธโƒฃ": { + "name": "keycap 5", + "slug": "keycap_5", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "6๏ธโƒฃ": { + "name": "keycap 6", + "slug": "keycap_6", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "7๏ธโƒฃ": { + "name": "keycap 7", + "slug": "keycap_7", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "8๏ธโƒฃ": { + "name": "keycap 8", + "slug": "keycap_8", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "9๏ธโƒฃ": { + "name": "keycap 9", + "slug": "keycap_9", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”Ÿ": { + "name": "keycap 10", + "slug": "keycap_10", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ” ": { + "name": "input latin uppercase", + "slug": "input_latin_uppercase", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ก": { + "name": "input latin lowercase", + "slug": "input_latin_lowercase", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ข": { + "name": "input numbers", + "slug": "input_numbers", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ฃ": { + "name": "input symbols", + "slug": "input_symbols", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ค": { + "name": "input latin letters", + "slug": "input_latin_letters", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ…ฐ๏ธ": { + "name": "A button (blood type)", + "slug": "a_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ†Ž": { + "name": "AB button (blood type)", + "slug": "ab_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ…ฑ๏ธ": { + "name": "B button (blood type)", + "slug": "b_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ†‘": { + "name": "CL button", + "slug": "cl_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ†’": { + "name": "COOL button", + "slug": "cool_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ†“": { + "name": "FREE button", + "slug": "free_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ„น๏ธ": { + "name": "information", + "slug": "information", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ†”": { + "name": "ID button", + "slug": "id_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ“‚๏ธ": { + "name": "circled M", + "slug": "circled_m", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ†•": { + "name": "NEW button", + "slug": "new_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ†–": { + "name": "NG button", + "slug": "ng_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ…พ๏ธ": { + "name": "O button (blood type)", + "slug": "o_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ†—": { + "name": "OK button", + "slug": "ok_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ…ฟ๏ธ": { + "name": "P button", + "slug": "p_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ†˜": { + "name": "SOS button", + "slug": "sos_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ†™": { + "name": "UP! button", + "slug": "up_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ†š": { + "name": "VS button", + "slug": "vs_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿˆ": { + "name": "Japanese โ€œhereโ€ button", + "slug": "japanese_here_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿˆ‚๏ธ": { + "name": "Japanese โ€œservice chargeโ€ button", + "slug": "japanese_service_charge_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿˆท๏ธ": { + "name": "Japanese โ€œmonthly amountโ€ button", + "slug": "japanese_monthly_amount_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿˆถ": { + "name": "Japanese โ€œnot free of chargeโ€ button", + "slug": "japanese_not_free_of_charge_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿˆฏ": { + "name": "Japanese โ€œreservedโ€ button", + "slug": "japanese_reserved_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‰": { + "name": "Japanese โ€œbargainโ€ button", + "slug": "japanese_bargain_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿˆน": { + "name": "Japanese โ€œdiscountโ€ button", + "slug": "japanese_discount_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿˆš": { + "name": "Japanese โ€œfree of chargeโ€ button", + "slug": "japanese_free_of_charge_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿˆฒ": { + "name": "Japanese โ€œprohibitedโ€ button", + "slug": "japanese_prohibited_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‰‘": { + "name": "Japanese โ€œacceptableโ€ button", + "slug": "japanese_acceptable_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿˆธ": { + "name": "Japanese โ€œapplicationโ€ button", + "slug": "japanese_application_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿˆด": { + "name": "Japanese โ€œpassing gradeโ€ button", + "slug": "japanese_passing_grade_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿˆณ": { + "name": "Japanese โ€œvacancyโ€ button", + "slug": "japanese_vacancy_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "ใŠ—๏ธ": { + "name": "Japanese โ€œcongratulationsโ€ button", + "slug": "japanese_congratulations_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "ใŠ™๏ธ": { + "name": "Japanese โ€œsecretโ€ button", + "slug": "japanese_secret_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿˆบ": { + "name": "Japanese โ€œopen for businessโ€ button", + "slug": "japanese_open_for_business_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿˆต": { + "name": "Japanese โ€œno vacancyโ€ button", + "slug": "japanese_no_vacancy_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ด": { + "name": "red circle", + "slug": "red_circle", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŸ ": { + "name": "orange circle", + "slug": "orange_circle", + "group": "Symbols", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐ŸŸก": { + "name": "yellow circle", + "slug": "yellow_circle", + "group": "Symbols", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐ŸŸข": { + "name": "green circle", + "slug": "green_circle", + "group": "Symbols", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐Ÿ”ต": { + "name": "blue circle", + "slug": "blue_circle", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŸฃ": { + "name": "purple circle", + "slug": "purple_circle", + "group": "Symbols", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐ŸŸค": { + "name": "brown circle", + "slug": "brown_circle", + "group": "Symbols", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "โšซ": { + "name": "black circle", + "slug": "black_circle", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โšช": { + "name": "white circle", + "slug": "white_circle", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŸฅ": { + "name": "red square", + "slug": "red_square", + "group": "Symbols", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐ŸŸง": { + "name": "orange square", + "slug": "orange_square", + "group": "Symbols", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐ŸŸจ": { + "name": "yellow square", + "slug": "yellow_square", + "group": "Symbols", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐ŸŸฉ": { + "name": "green square", + "slug": "green_square", + "group": "Symbols", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐ŸŸฆ": { + "name": "blue square", + "slug": "blue_square", + "group": "Symbols", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐ŸŸช": { + "name": "purple square", + "slug": "purple_square", + "group": "Symbols", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "๐ŸŸซ": { + "name": "brown square", + "slug": "brown_square", + "group": "Symbols", + "emoji_version": "12.0", + "unicode_version": "12.0", + "skin_tone_support": false + }, + "โฌ›": { + "name": "black large square", + "slug": "black_large_square", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โฌœ": { + "name": "white large square", + "slug": "white_large_square", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ—ผ๏ธ": { + "name": "black medium square", + "slug": "black_medium_square", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ—ป๏ธ": { + "name": "white medium square", + "slug": "white_medium_square", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ—พ": { + "name": "black medium-small square", + "slug": "black_medium_small_square", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ—ฝ": { + "name": "white medium-small square", + "slug": "white_medium_small_square", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ–ช๏ธ": { + "name": "black small square", + "slug": "black_small_square", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "โ–ซ๏ธ": { + "name": "white small square", + "slug": "white_small_square", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ถ": { + "name": "large orange diamond", + "slug": "large_orange_diamond", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ท": { + "name": "large blue diamond", + "slug": "large_blue_diamond", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ธ": { + "name": "small orange diamond", + "slug": "small_orange_diamond", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”น": { + "name": "small blue diamond", + "slug": "small_blue_diamond", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”บ": { + "name": "red triangle pointed up", + "slug": "red_triangle_pointed_up", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ป": { + "name": "red triangle pointed down", + "slug": "red_triangle_pointed_down", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ’ ": { + "name": "diamond with a dot", + "slug": "diamond_with_a_dot", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”˜": { + "name": "radio button", + "slug": "radio_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ณ": { + "name": "white square button", + "slug": "white_square_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ”ฒ": { + "name": "black square button", + "slug": "black_square_button", + "group": "Symbols", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ": { + "name": "chequered flag", + "slug": "chequered_flag", + "group": "Flags", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿšฉ": { + "name": "triangular flag", + "slug": "triangular_flag", + "group": "Flags", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐ŸŽŒ": { + "name": "crossed flags", + "slug": "crossed_flags", + "group": "Flags", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿด": { + "name": "black flag", + "slug": "black_flag", + "group": "Flags", + "emoji_version": "1.0", + "unicode_version": "1.0", + "skin_tone_support": false + }, + "๐Ÿณ๏ธ": { + "name": "white flag", + "slug": "white_flag", + "group": "Flags", + "emoji_version": "0.7", + "unicode_version": "0.7", + "skin_tone_support": false + }, + "๐Ÿณ๏ธโ€๐ŸŒˆ": { + "name": "rainbow flag", + "slug": "rainbow_flag", + "group": "Flags", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿณ๏ธโ€โšง๏ธ": { + "name": "transgender flag", + "slug": "transgender_flag", + "group": "Flags", + "emoji_version": "13.0", + "unicode_version": "13.0", + "skin_tone_support": false + }, + "๐Ÿดโ€โ˜ ๏ธ": { + "name": "pirate flag", + "slug": "pirate_flag", + "group": "Flags", + "emoji_version": "11.0", + "unicode_version": "11.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡จ": { + "name": "flag Ascension Island", + "slug": "flag_ascension_island", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡ฉ": { + "name": "flag Andorra", + "slug": "flag_andorra", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡ช": { + "name": "flag United Arab Emirates", + "slug": "flag_united_arab_emirates", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡ซ": { + "name": "flag Afghanistan", + "slug": "flag_afghanistan", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡ฌ": { + "name": "flag Antigua & Barbuda", + "slug": "flag_antigua_barbuda", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡ฎ": { + "name": "flag Anguilla", + "slug": "flag_anguilla", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡ฑ": { + "name": "flag Albania", + "slug": "flag_albania", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡ฒ": { + "name": "flag Armenia", + "slug": "flag_armenia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡ด": { + "name": "flag Angola", + "slug": "flag_angola", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡ถ": { + "name": "flag Antarctica", + "slug": "flag_antarctica", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡ท": { + "name": "flag Argentina", + "slug": "flag_argentina", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡ธ": { + "name": "flag American Samoa", + "slug": "flag_american_samoa", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡น": { + "name": "flag Austria", + "slug": "flag_austria", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡บ": { + "name": "flag Australia", + "slug": "flag_australia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡ผ": { + "name": "flag Aruba", + "slug": "flag_aruba", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡ฝ": { + "name": "flag ร…land Islands", + "slug": "flag_aland_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฆ๐Ÿ‡ฟ": { + "name": "flag Azerbaijan", + "slug": "flag_azerbaijan", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ฆ": { + "name": "flag Bosnia & Herzegovina", + "slug": "flag_bosnia_herzegovina", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ง": { + "name": "flag Barbados", + "slug": "flag_barbados", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ฉ": { + "name": "flag Bangladesh", + "slug": "flag_bangladesh", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ช": { + "name": "flag Belgium", + "slug": "flag_belgium", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ซ": { + "name": "flag Burkina Faso", + "slug": "flag_burkina_faso", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ฌ": { + "name": "flag Bulgaria", + "slug": "flag_bulgaria", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ญ": { + "name": "flag Bahrain", + "slug": "flag_bahrain", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ฎ": { + "name": "flag Burundi", + "slug": "flag_burundi", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ฏ": { + "name": "flag Benin", + "slug": "flag_benin", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ฑ": { + "name": "flag St. Barthรฉlemy", + "slug": "flag_st_barthelemy", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ฒ": { + "name": "flag Bermuda", + "slug": "flag_bermuda", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ณ": { + "name": "flag Brunei", + "slug": "flag_brunei", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ด": { + "name": "flag Bolivia", + "slug": "flag_bolivia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ถ": { + "name": "flag Caribbean Netherlands", + "slug": "flag_caribbean_netherlands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ท": { + "name": "flag Brazil", + "slug": "flag_brazil", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ธ": { + "name": "flag Bahamas", + "slug": "flag_bahamas", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡น": { + "name": "flag Bhutan", + "slug": "flag_bhutan", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ป": { + "name": "flag Bouvet Island", + "slug": "flag_bouvet_island", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ผ": { + "name": "flag Botswana", + "slug": "flag_botswana", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡พ": { + "name": "flag Belarus", + "slug": "flag_belarus", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ง๐Ÿ‡ฟ": { + "name": "flag Belize", + "slug": "flag_belize", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ฆ": { + "name": "flag Canada", + "slug": "flag_canada", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡จ": { + "name": "flag Cocos (Keeling) Islands", + "slug": "flag_cocos_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ฉ": { + "name": "flag Congo - Kinshasa", + "slug": "flag_congo_kinshasa", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ซ": { + "name": "flag Central African Republic", + "slug": "flag_central_african_republic", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ฌ": { + "name": "flag Congo - Brazzaville", + "slug": "flag_congo_brazzaville", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ญ": { + "name": "flag Switzerland", + "slug": "flag_switzerland", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ฎ": { + "name": "flag Cรดte dโ€™Ivoire", + "slug": "flag_cote_d_ivoire", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ฐ": { + "name": "flag Cook Islands", + "slug": "flag_cook_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ฑ": { + "name": "flag Chile", + "slug": "flag_chile", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ฒ": { + "name": "flag Cameroon", + "slug": "flag_cameroon", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ณ": { + "name": "flag China", + "slug": "flag_china", + "group": "Flags", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ด": { + "name": "flag Colombia", + "slug": "flag_colombia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ต": { + "name": "flag Clipperton Island", + "slug": "flag_clipperton_island", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ท": { + "name": "flag Costa Rica", + "slug": "flag_costa_rica", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡บ": { + "name": "flag Cuba", + "slug": "flag_cuba", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ป": { + "name": "flag Cape Verde", + "slug": "flag_cape_verde", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ผ": { + "name": "flag Curaรงao", + "slug": "flag_curacao", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ฝ": { + "name": "flag Christmas Island", + "slug": "flag_christmas_island", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡พ": { + "name": "flag Cyprus", + "slug": "flag_cyprus", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡จ๐Ÿ‡ฟ": { + "name": "flag Czechia", + "slug": "flag_czechia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฉ๐Ÿ‡ช": { + "name": "flag Germany", + "slug": "flag_germany", + "group": "Flags", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‡ฉ๐Ÿ‡ฌ": { + "name": "flag Diego Garcia", + "slug": "flag_diego_garcia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฉ๐Ÿ‡ฏ": { + "name": "flag Djibouti", + "slug": "flag_djibouti", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฉ๐Ÿ‡ฐ": { + "name": "flag Denmark", + "slug": "flag_denmark", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฉ๐Ÿ‡ฒ": { + "name": "flag Dominica", + "slug": "flag_dominica", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฉ๐Ÿ‡ด": { + "name": "flag Dominican Republic", + "slug": "flag_dominican_republic", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฉ๐Ÿ‡ฟ": { + "name": "flag Algeria", + "slug": "flag_algeria", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ช๐Ÿ‡ฆ": { + "name": "flag Ceuta & Melilla", + "slug": "flag_ceuta_melilla", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ช๐Ÿ‡จ": { + "name": "flag Ecuador", + "slug": "flag_ecuador", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ช๐Ÿ‡ช": { + "name": "flag Estonia", + "slug": "flag_estonia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ช๐Ÿ‡ฌ": { + "name": "flag Egypt", + "slug": "flag_egypt", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ช๐Ÿ‡ญ": { + "name": "flag Western Sahara", + "slug": "flag_western_sahara", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ช๐Ÿ‡ท": { + "name": "flag Eritrea", + "slug": "flag_eritrea", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ช๐Ÿ‡ธ": { + "name": "flag Spain", + "slug": "flag_spain", + "group": "Flags", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‡ช๐Ÿ‡น": { + "name": "flag Ethiopia", + "slug": "flag_ethiopia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ช๐Ÿ‡บ": { + "name": "flag European Union", + "slug": "flag_european_union", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ซ๐Ÿ‡ฎ": { + "name": "flag Finland", + "slug": "flag_finland", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ซ๐Ÿ‡ฏ": { + "name": "flag Fiji", + "slug": "flag_fiji", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ซ๐Ÿ‡ฐ": { + "name": "flag Falkland Islands", + "slug": "flag_falkland_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ซ๐Ÿ‡ฒ": { + "name": "flag Micronesia", + "slug": "flag_micronesia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ซ๐Ÿ‡ด": { + "name": "flag Faroe Islands", + "slug": "flag_faroe_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ซ๐Ÿ‡ท": { + "name": "flag France", + "slug": "flag_france", + "group": "Flags", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ฆ": { + "name": "flag Gabon", + "slug": "flag_gabon", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ง": { + "name": "flag United Kingdom", + "slug": "flag_united_kingdom", + "group": "Flags", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ฉ": { + "name": "flag Grenada", + "slug": "flag_grenada", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ช": { + "name": "flag Georgia", + "slug": "flag_georgia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ซ": { + "name": "flag French Guiana", + "slug": "flag_french_guiana", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ฌ": { + "name": "flag Guernsey", + "slug": "flag_guernsey", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ญ": { + "name": "flag Ghana", + "slug": "flag_ghana", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ฎ": { + "name": "flag Gibraltar", + "slug": "flag_gibraltar", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ฑ": { + "name": "flag Greenland", + "slug": "flag_greenland", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ฒ": { + "name": "flag Gambia", + "slug": "flag_gambia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ณ": { + "name": "flag Guinea", + "slug": "flag_guinea", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ต": { + "name": "flag Guadeloupe", + "slug": "flag_guadeloupe", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ถ": { + "name": "flag Equatorial Guinea", + "slug": "flag_equatorial_guinea", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ท": { + "name": "flag Greece", + "slug": "flag_greece", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ธ": { + "name": "flag South Georgia & South Sandwich Islands", + "slug": "flag_south_georgia_south_sandwich_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡น": { + "name": "flag Guatemala", + "slug": "flag_guatemala", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡บ": { + "name": "flag Guam", + "slug": "flag_guam", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡ผ": { + "name": "flag Guinea-Bissau", + "slug": "flag_guinea_bissau", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฌ๐Ÿ‡พ": { + "name": "flag Guyana", + "slug": "flag_guyana", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ญ๐Ÿ‡ฐ": { + "name": "flag Hong Kong SAR China", + "slug": "flag_hong_kong_sar_china", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ญ๐Ÿ‡ฒ": { + "name": "flag Heard & McDonald Islands", + "slug": "flag_heard_mcdonald_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ญ๐Ÿ‡ณ": { + "name": "flag Honduras", + "slug": "flag_honduras", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ญ๐Ÿ‡ท": { + "name": "flag Croatia", + "slug": "flag_croatia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ญ๐Ÿ‡น": { + "name": "flag Haiti", + "slug": "flag_haiti", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ญ๐Ÿ‡บ": { + "name": "flag Hungary", + "slug": "flag_hungary", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฎ๐Ÿ‡จ": { + "name": "flag Canary Islands", + "slug": "flag_canary_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฎ๐Ÿ‡ฉ": { + "name": "flag Indonesia", + "slug": "flag_indonesia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฎ๐Ÿ‡ช": { + "name": "flag Ireland", + "slug": "flag_ireland", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฎ๐Ÿ‡ฑ": { + "name": "flag Israel", + "slug": "flag_israel", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฎ๐Ÿ‡ฒ": { + "name": "flag Isle of Man", + "slug": "flag_isle_of_man", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฎ๐Ÿ‡ณ": { + "name": "flag India", + "slug": "flag_india", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฎ๐Ÿ‡ด": { + "name": "flag British Indian Ocean Territory", + "slug": "flag_british_indian_ocean_territory", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฎ๐Ÿ‡ถ": { + "name": "flag Iraq", + "slug": "flag_iraq", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฎ๐Ÿ‡ท": { + "name": "flag Iran", + "slug": "flag_iran", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฎ๐Ÿ‡ธ": { + "name": "flag Iceland", + "slug": "flag_iceland", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฎ๐Ÿ‡น": { + "name": "flag Italy", + "slug": "flag_italy", + "group": "Flags", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‡ฏ๐Ÿ‡ช": { + "name": "flag Jersey", + "slug": "flag_jersey", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฏ๐Ÿ‡ฒ": { + "name": "flag Jamaica", + "slug": "flag_jamaica", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฏ๐Ÿ‡ด": { + "name": "flag Jordan", + "slug": "flag_jordan", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฏ๐Ÿ‡ต": { + "name": "flag Japan", + "slug": "flag_japan", + "group": "Flags", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‡ฐ๐Ÿ‡ช": { + "name": "flag Kenya", + "slug": "flag_kenya", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฐ๐Ÿ‡ฌ": { + "name": "flag Kyrgyzstan", + "slug": "flag_kyrgyzstan", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฐ๐Ÿ‡ญ": { + "name": "flag Cambodia", + "slug": "flag_cambodia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฐ๐Ÿ‡ฎ": { + "name": "flag Kiribati", + "slug": "flag_kiribati", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฐ๐Ÿ‡ฒ": { + "name": "flag Comoros", + "slug": "flag_comoros", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฐ๐Ÿ‡ณ": { + "name": "flag St. Kitts & Nevis", + "slug": "flag_st_kitts_nevis", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฐ๐Ÿ‡ต": { + "name": "flag North Korea", + "slug": "flag_north_korea", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฐ๐Ÿ‡ท": { + "name": "flag South Korea", + "slug": "flag_south_korea", + "group": "Flags", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‡ฐ๐Ÿ‡ผ": { + "name": "flag Kuwait", + "slug": "flag_kuwait", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฐ๐Ÿ‡พ": { + "name": "flag Cayman Islands", + "slug": "flag_cayman_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฐ๐Ÿ‡ฟ": { + "name": "flag Kazakhstan", + "slug": "flag_kazakhstan", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฑ๐Ÿ‡ฆ": { + "name": "flag Laos", + "slug": "flag_laos", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฑ๐Ÿ‡ง": { + "name": "flag Lebanon", + "slug": "flag_lebanon", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฑ๐Ÿ‡จ": { + "name": "flag St. Lucia", + "slug": "flag_st_lucia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฑ๐Ÿ‡ฎ": { + "name": "flag Liechtenstein", + "slug": "flag_liechtenstein", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฑ๐Ÿ‡ฐ": { + "name": "flag Sri Lanka", + "slug": "flag_sri_lanka", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฑ๐Ÿ‡ท": { + "name": "flag Liberia", + "slug": "flag_liberia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฑ๐Ÿ‡ธ": { + "name": "flag Lesotho", + "slug": "flag_lesotho", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฑ๐Ÿ‡น": { + "name": "flag Lithuania", + "slug": "flag_lithuania", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฑ๐Ÿ‡บ": { + "name": "flag Luxembourg", + "slug": "flag_luxembourg", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฑ๐Ÿ‡ป": { + "name": "flag Latvia", + "slug": "flag_latvia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฑ๐Ÿ‡พ": { + "name": "flag Libya", + "slug": "flag_libya", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ฆ": { + "name": "flag Morocco", + "slug": "flag_morocco", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡จ": { + "name": "flag Monaco", + "slug": "flag_monaco", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ฉ": { + "name": "flag Moldova", + "slug": "flag_moldova", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ช": { + "name": "flag Montenegro", + "slug": "flag_montenegro", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ซ": { + "name": "flag St. Martin", + "slug": "flag_st_martin", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ฌ": { + "name": "flag Madagascar", + "slug": "flag_madagascar", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ญ": { + "name": "flag Marshall Islands", + "slug": "flag_marshall_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ฐ": { + "name": "flag North Macedonia", + "slug": "flag_north_macedonia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ฑ": { + "name": "flag Mali", + "slug": "flag_mali", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ฒ": { + "name": "flag Myanmar (Burma)", + "slug": "flag_myanmar", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ณ": { + "name": "flag Mongolia", + "slug": "flag_mongolia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ด": { + "name": "flag Macao SAR China", + "slug": "flag_macao_sar_china", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ต": { + "name": "flag Northern Mariana Islands", + "slug": "flag_northern_mariana_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ถ": { + "name": "flag Martinique", + "slug": "flag_martinique", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ท": { + "name": "flag Mauritania", + "slug": "flag_mauritania", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ธ": { + "name": "flag Montserrat", + "slug": "flag_montserrat", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡น": { + "name": "flag Malta", + "slug": "flag_malta", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡บ": { + "name": "flag Mauritius", + "slug": "flag_mauritius", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ป": { + "name": "flag Maldives", + "slug": "flag_maldives", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ผ": { + "name": "flag Malawi", + "slug": "flag_malawi", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ฝ": { + "name": "flag Mexico", + "slug": "flag_mexico", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡พ": { + "name": "flag Malaysia", + "slug": "flag_malaysia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฒ๐Ÿ‡ฟ": { + "name": "flag Mozambique", + "slug": "flag_mozambique", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ณ๐Ÿ‡ฆ": { + "name": "flag Namibia", + "slug": "flag_namibia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ณ๐Ÿ‡จ": { + "name": "flag New Caledonia", + "slug": "flag_new_caledonia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ณ๐Ÿ‡ช": { + "name": "flag Niger", + "slug": "flag_niger", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ณ๐Ÿ‡ซ": { + "name": "flag Norfolk Island", + "slug": "flag_norfolk_island", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ณ๐Ÿ‡ฌ": { + "name": "flag Nigeria", + "slug": "flag_nigeria", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ณ๐Ÿ‡ฎ": { + "name": "flag Nicaragua", + "slug": "flag_nicaragua", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ณ๐Ÿ‡ฑ": { + "name": "flag Netherlands", + "slug": "flag_netherlands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ณ๐Ÿ‡ด": { + "name": "flag Norway", + "slug": "flag_norway", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ณ๐Ÿ‡ต": { + "name": "flag Nepal", + "slug": "flag_nepal", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ณ๐Ÿ‡ท": { + "name": "flag Nauru", + "slug": "flag_nauru", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ณ๐Ÿ‡บ": { + "name": "flag Niue", + "slug": "flag_niue", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ณ๐Ÿ‡ฟ": { + "name": "flag New Zealand", + "slug": "flag_new_zealand", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ด๐Ÿ‡ฒ": { + "name": "flag Oman", + "slug": "flag_oman", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ต๐Ÿ‡ฆ": { + "name": "flag Panama", + "slug": "flag_panama", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ต๐Ÿ‡ช": { + "name": "flag Peru", + "slug": "flag_peru", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ต๐Ÿ‡ซ": { + "name": "flag French Polynesia", + "slug": "flag_french_polynesia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ต๐Ÿ‡ฌ": { + "name": "flag Papua New Guinea", + "slug": "flag_papua_new_guinea", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ต๐Ÿ‡ญ": { + "name": "flag Philippines", + "slug": "flag_philippines", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ต๐Ÿ‡ฐ": { + "name": "flag Pakistan", + "slug": "flag_pakistan", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ต๐Ÿ‡ฑ": { + "name": "flag Poland", + "slug": "flag_poland", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ต๐Ÿ‡ฒ": { + "name": "flag St. Pierre & Miquelon", + "slug": "flag_st_pierre_miquelon", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ต๐Ÿ‡ณ": { + "name": "flag Pitcairn Islands", + "slug": "flag_pitcairn_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ต๐Ÿ‡ท": { + "name": "flag Puerto Rico", + "slug": "flag_puerto_rico", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ต๐Ÿ‡ธ": { + "name": "flag Palestinian Territories", + "slug": "flag_palestinian_territories", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ต๐Ÿ‡น": { + "name": "flag Portugal", + "slug": "flag_portugal", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ต๐Ÿ‡ผ": { + "name": "flag Palau", + "slug": "flag_palau", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ต๐Ÿ‡พ": { + "name": "flag Paraguay", + "slug": "flag_paraguay", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ถ๐Ÿ‡ฆ": { + "name": "flag Qatar", + "slug": "flag_qatar", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ท๐Ÿ‡ช": { + "name": "flag Rรฉunion", + "slug": "flag_reunion", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ท๐Ÿ‡ด": { + "name": "flag Romania", + "slug": "flag_romania", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ท๐Ÿ‡ธ": { + "name": "flag Serbia", + "slug": "flag_serbia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ท๐Ÿ‡บ": { + "name": "flag Russia", + "slug": "flag_russia", + "group": "Flags", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‡ท๐Ÿ‡ผ": { + "name": "flag Rwanda", + "slug": "flag_rwanda", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ฆ": { + "name": "flag Saudi Arabia", + "slug": "flag_saudi_arabia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ง": { + "name": "flag Solomon Islands", + "slug": "flag_solomon_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡จ": { + "name": "flag Seychelles", + "slug": "flag_seychelles", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ฉ": { + "name": "flag Sudan", + "slug": "flag_sudan", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ช": { + "name": "flag Sweden", + "slug": "flag_sweden", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ฌ": { + "name": "flag Singapore", + "slug": "flag_singapore", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ญ": { + "name": "flag St. Helena", + "slug": "flag_st_helena", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ฎ": { + "name": "flag Slovenia", + "slug": "flag_slovenia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ฏ": { + "name": "flag Svalbard & Jan Mayen", + "slug": "flag_svalbard_jan_mayen", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ฐ": { + "name": "flag Slovakia", + "slug": "flag_slovakia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ฑ": { + "name": "flag Sierra Leone", + "slug": "flag_sierra_leone", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ฒ": { + "name": "flag San Marino", + "slug": "flag_san_marino", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ณ": { + "name": "flag Senegal", + "slug": "flag_senegal", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ด": { + "name": "flag Somalia", + "slug": "flag_somalia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ท": { + "name": "flag Suriname", + "slug": "flag_suriname", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ธ": { + "name": "flag South Sudan", + "slug": "flag_south_sudan", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡น": { + "name": "flag Sรฃo Tomรฉ & Prรญncipe", + "slug": "flag_sao_tome_principe", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ป": { + "name": "flag El Salvador", + "slug": "flag_el_salvador", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ฝ": { + "name": "flag Sint Maarten", + "slug": "flag_sint_maarten", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡พ": { + "name": "flag Syria", + "slug": "flag_syria", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ธ๐Ÿ‡ฟ": { + "name": "flag Eswatini", + "slug": "flag_eswatini", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡ฆ": { + "name": "flag Tristan da Cunha", + "slug": "flag_tristan_da_cunha", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡จ": { + "name": "flag Turks & Caicos Islands", + "slug": "flag_turks_caicos_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡ฉ": { + "name": "flag Chad", + "slug": "flag_chad", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡ซ": { + "name": "flag French Southern Territories", + "slug": "flag_french_southern_territories", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡ฌ": { + "name": "flag Togo", + "slug": "flag_togo", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡ญ": { + "name": "flag Thailand", + "slug": "flag_thailand", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡ฏ": { + "name": "flag Tajikistan", + "slug": "flag_tajikistan", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡ฐ": { + "name": "flag Tokelau", + "slug": "flag_tokelau", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡ฑ": { + "name": "flag Timor-Leste", + "slug": "flag_timor_leste", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡ฒ": { + "name": "flag Turkmenistan", + "slug": "flag_turkmenistan", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡ณ": { + "name": "flag Tunisia", + "slug": "flag_tunisia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡ด": { + "name": "flag Tonga", + "slug": "flag_tonga", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡ท": { + "name": "flag Tรผrkiye", + "slug": "flag_turkiye", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡น": { + "name": "flag Trinidad & Tobago", + "slug": "flag_trinidad_tobago", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡ป": { + "name": "flag Tuvalu", + "slug": "flag_tuvalu", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡ผ": { + "name": "flag Taiwan", + "slug": "flag_taiwan", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡น๐Ÿ‡ฟ": { + "name": "flag Tanzania", + "slug": "flag_tanzania", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡บ๐Ÿ‡ฆ": { + "name": "flag Ukraine", + "slug": "flag_ukraine", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡บ๐Ÿ‡ฌ": { + "name": "flag Uganda", + "slug": "flag_uganda", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡บ๐Ÿ‡ฒ": { + "name": "flag U.S. Outlying Islands", + "slug": "flag_u_s_outlying_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡บ๐Ÿ‡ณ": { + "name": "flag United Nations", + "slug": "flag_united_nations", + "group": "Flags", + "emoji_version": "4.0", + "unicode_version": "4.0", + "skin_tone_support": false + }, + "๐Ÿ‡บ๐Ÿ‡ธ": { + "name": "flag United States", + "slug": "flag_united_states", + "group": "Flags", + "emoji_version": "0.6", + "unicode_version": "0.6", + "skin_tone_support": false + }, + "๐Ÿ‡บ๐Ÿ‡พ": { + "name": "flag Uruguay", + "slug": "flag_uruguay", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡บ๐Ÿ‡ฟ": { + "name": "flag Uzbekistan", + "slug": "flag_uzbekistan", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ป๐Ÿ‡ฆ": { + "name": "flag Vatican City", + "slug": "flag_vatican_city", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ป๐Ÿ‡จ": { + "name": "flag St. Vincent & Grenadines", + "slug": "flag_st_vincent_grenadines", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ป๐Ÿ‡ช": { + "name": "flag Venezuela", + "slug": "flag_venezuela", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ป๐Ÿ‡ฌ": { + "name": "flag British Virgin Islands", + "slug": "flag_british_virgin_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ป๐Ÿ‡ฎ": { + "name": "flag U.S. Virgin Islands", + "slug": "flag_u_s_virgin_islands", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ป๐Ÿ‡ณ": { + "name": "flag Vietnam", + "slug": "flag_vietnam", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ป๐Ÿ‡บ": { + "name": "flag Vanuatu", + "slug": "flag_vanuatu", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ผ๐Ÿ‡ซ": { + "name": "flag Wallis & Futuna", + "slug": "flag_wallis_futuna", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ผ๐Ÿ‡ธ": { + "name": "flag Samoa", + "slug": "flag_samoa", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฝ๐Ÿ‡ฐ": { + "name": "flag Kosovo", + "slug": "flag_kosovo", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡พ๐Ÿ‡ช": { + "name": "flag Yemen", + "slug": "flag_yemen", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡พ๐Ÿ‡น": { + "name": "flag Mayotte", + "slug": "flag_mayotte", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฟ๐Ÿ‡ฆ": { + "name": "flag South Africa", + "slug": "flag_south_africa", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฟ๐Ÿ‡ฒ": { + "name": "flag Zambia", + "slug": "flag_zambia", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿ‡ฟ๐Ÿ‡ผ": { + "name": "flag Zimbabwe", + "slug": "flag_zimbabwe", + "group": "Flags", + "emoji_version": "2.0", + "unicode_version": "2.0", + "skin_tone_support": false + }, + "๐Ÿด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ": { + "name": "flag England", + "slug": "flag_england", + "group": "Flags", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ": { + "name": "flag Scotland", + "slug": "flag_scotland", + "group": "Flags", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + }, + "๐Ÿด๓ ง๓ ข๓ ท๓ ฌ๓ ณ๓ ฟ": { + "name": "flag Wales", + "slug": "flag_wales", + "group": "Flags", + "emoji_version": "5.0", + "unicode_version": "5.0", + "skin_tone_support": false + } +} diff --git a/config/assets/modus.json b/config/assets/modus.json new file mode 100644 index 0000000..530c99d --- /dev/null +++ b/config/assets/modus.json @@ -0,0 +1,17 @@ +{ + "commands": { + "/wp": "launcher.open(\"wallpapers\")", + "/em": "launcher.open(\"emoji\")", + "/ch": "launcher.open(\"cliphist\")", + "/kb": "launcher.open(\"kanban\")", + "/bt": "launcher.open(\"bluetooth\")", + "/sh": "launcher.open(\"sh\")", + "/pw": "launcher.open(\"power\")", + "/nw": "launcher.open(\"wifi\")", + "/cl": "launcher.open(\"calendar\")", + "/tl": "launcher.open(\"tools\")", + "/tx": "launcher.open(\"tmux\")", + "/ws": "launcher.open(\"window-switcher\")" + }, + "pinned_apps": [] +} \ No newline at end of file diff --git a/config/config.py b/config/config.py new file mode 100644 index 0000000..a10894e --- /dev/null +++ b/config/config.py @@ -0,0 +1,1294 @@ +import os +import shutil +import json +import sys +from pathlib import Path +import random +import subprocess +import toml +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk + +# Fabric imports +from fabric import Application +from fabric.widgets.window import Window +from fabric.widgets.box import Box +from fabric.widgets.label import Label +from fabric.widgets.button import Button +from fabric.widgets.entry import Entry +from fabric.widgets.scrolledwindow import ScrolledWindow +from fabric.widgets.image import Image +from fabric.widgets.stack import Stack +from fabric.widgets.scale import Scale +from fabric.utils import exec_shell_command, exec_shell_command_async + +# Assuming data.py exists in the same directory or is accessible via sys.path +# If data.py is in ./config/data.py relative to this script's original location: +try: + # Adjust path relative to the *original* location if needed + sys.path.insert(0, str(Path(__file__).resolve().parent / "../config")) + from data import ( + APP_NAME, + APP_NAME_CAP, + WALLPAPERS_DIR_DEFAULT, + ) +except ImportError as e: + print(f"Error importing data constants: {e}") + # Provide fallback defaults if import fails + APP_NAME = "modusv2" + APP_NAME_CAP = "Modusv2" + CONFIG_DIR = "~/Modusv2" + HOME_DIR = "~" + WALLPAPERS_DIR_DEFAULT = "~/Pictures/wallpapers" + +SOURCE_STRING = f""" +# {APP_NAME_CAP} +source = ~/{APP_NAME_CAP}/config/hypr/{APP_NAME}.conf +""" + +DEFAULTS = { + "prefix_restart": "SHIFT ALT", + "suffix_restart": "T", + "prefix_bluetooth": "SHIFT ALT", + "suffix_bluetooth": "B", + "prefix_emoji": "SUPER", + "suffix_emoji": "E", + "prefix_cliphist": "SUPER", + "suffix_cliphist": "V", + "prefix_kanban": "SUPER", + "suffix_kanban": "T", + "prefix_toolbox": "SUPER", + "suffix_toolbox": "S", + "prefix_walls": "SUPER", + "suffix_walls": "W", + "prefix_launcher": "SUPER", + "suffix_launcher": "D", + "prefix_power": "SUPER", + "suffix_power": "X", + "prefix_tmux": "SUPER", + "suffix_tmux": "Z", + "prefix_notifications": "SUPER", + "suffix_notifications": "N", + "prefix_window_switcher": "ALT", + "suffix_window_switcher": "W", + "prefix_restart_inspector": "SUPER SHIFT", + "suffix_restart_inspector": "T", + "vertical": False, + "vertical_right_align": True, + "bottom_bar": False, + "centered_bar": False, + "terminal_command": "kitty -e", + "wallpapers_dir": WALLPAPERS_DIR_DEFAULT, + "dock_enabled": True, + "dock_always_occluded": False, # Added default + "dock_icon_size": 28, + "osd_enabled": True, # Added default + # Defaults for bar components (assuming True initially) + "bar_button_app_visible": True, + "bar_tray_visible": True, + "bar_workspaces_visible": True, + "bar_metrics_visible": True, + "bar_language_visible": True, + "bar_date_time_visible": True, + "bar_updates_visible": True, + "bar_indicators_visible": True, + "corners_visible": True, # Added default for corners visibility + "bar_metrics_disks": ["/"], + # Add metric visibility defaults + "metrics_visible": { + "cpu": True, + "ram": True, + "disk": True, + "swap": True, + "gpu": False, + }, +} + +bind_vars = DEFAULTS.copy() + + +def deep_update(target: dict, update: dict) -> dict: + """ + Recursively update a nested dictionary with values from another dictionary. + """ + for key, value in update.items(): + if isinstance(value, dict): + target[key] = deep_update(target.get(key, {}), value) + else: + target[key] = value + return target + + +def ensure_matugen_config(): + """ + Ensure that the matugen configuration file exists and is updated + with the expected settings. + """ + expected_config = { + "config": { + "reload_apps": True, + "wallpaper": { + "command": "swww", + "arguments": [ + "img", + "-t", + "outer", + "--transition-duration", + "1.5", + "--transition-step", + "255", + "--transition-fps", + "60", + "-f", + "Nearest", + ], + "set": True, + }, + "custom_colors": { + "red": {"color": "#FF0000", "blend": True}, + "green": {"color": "#00FF00", "blend": True}, + "yellow": {"color": "#FFFF00", "blend": True}, + "blue": {"color": "#0000FF", "blend": True}, + "magenta": {"color": "#FF00FF", "blend": True}, + "cyan": {"color": "#00FFFF", "blend": True}, + "white": {"color": "#FFFFFF", "blend": True}, + }, + }, + "templates": { + "hyprland": { + "input_path": f"~/{APP_NAME_CAP}/config/matugen/templates/hyprland-colors.conf", + "output_path": f"~/{APP_NAME_CAP}/config/hypr/colors.conf", + }, + f"{APP_NAME}": { + "input_path": f"~/{APP_NAME_CAP}/config/matugen/templates/{APP_NAME}.css", + "output_path": f"~/{APP_NAME_CAP}/styles/colors.css", + "post_hook": f"fabric-cli exec {APP_NAME} 'app.set_css()' &", + }, + }, + } + + config_path = os.path.expanduser("~/.config/matugen/config.toml") + os.makedirs(os.path.dirname(config_path), exist_ok=True) + + # Load any existing configuration + existing_config = {} + if os.path.exists(config_path): + with open(config_path, "r") as f: + existing_config = toml.load(f) + # Backup existing configuration + shutil.copyfile(config_path, config_path + ".bak") + + # Merge configurations + merged_config = deep_update(existing_config, expected_config) + with open(config_path, "w") as f: + toml.dump(merged_config, f) + + # Check if colors.css exists in styles directory + colors_css_path = os.path.expanduser(f"~/{APP_NAME_CAP}/styles/colors.css") + if not os.path.exists(colors_css_path): + # Get the wallpapers directory from bind_vars or use default + wallpapers_dir = bind_vars.get("wallpapers_dir", WALLPAPERS_DIR_DEFAULT) + wallpapers_dir = os.path.expanduser(wallpapers_dir) + + # Get list of image files in the directory + image_extensions = (".png", ".jpg", ".jpeg", ".gif", ".bmp") + image_files = [ + f + for f in os.listdir(wallpapers_dir) + if f.lower().endswith(image_extensions) + ] + + if image_files: + # Select a random image + random_image = random.choice(image_files) + image_path = os.path.join(wallpapers_dir, random_image) + # Apply the random wallpaper using matugen + os.system(f"matugen image {image_path}") + else: + # If no images found in user's directory, try the default directory + default_dir = os.path.expanduser(f"~/{APP_NAME_CAP}/assets/wallpaper/") + default_images = [ + f + for f in os.listdir(default_dir) + if f.lower().endswith(image_extensions) + ] + + random_image = random.choice(default_images) + image_path = os.path.join(default_dir, random_image) + os.system(f"matugen image {image_path}") + + +def load_bind_vars(): + """ + Load saved key binding variables from JSON, if available. + """ + config_json = os.path.expanduser(f"~/{APP_NAME_CAP}/config/assets/config.json") + if os.path.exists(config_json): + try: + with open(config_json, "r") as f: + saved_vars = json.load(f) + # Update defaults with saved values, ensuring all keys exist + for key in DEFAULTS: + if key in saved_vars: + bind_vars[key] = saved_vars[key] + else: + bind_vars[key] = DEFAULTS[ + key + ] # Use default if missing in saved + # Add any new keys from DEFAULTS not present in saved_vars + for key in saved_vars: + if key not in bind_vars: + bind_vars[key] = saved_vars[ + key + ] # Keep saved if it's not in new defaults (less likely) + for vis_key in ["metrics_visible"]: + if vis_key in DEFAULTS: + if vis_key not in bind_vars or not isinstance( + bind_vars[vis_key], dict + ): + bind_vars[vis_key] = DEFAULTS[vis_key].copy() + else: + for m in DEFAULTS[vis_key]: + if m not in bind_vars[vis_key]: + bind_vars[vis_key][m] = DEFAULTS[vis_key][m] + except json.JSONDecodeError: + print(f"Warning: Could not decode JSON from {config_json}. Using defaults.") + bind_vars.update(DEFAULTS) # Ensure defaults on error + except Exception as e: + print(f"Error loading config from {config_json}: {e}. Using defaults.") + bind_vars.update(DEFAULTS) # Ensure defaults on error + else: + # Ensure defaults are set if file doesn't exist + bind_vars.update(DEFAULTS) + + +def generate_hyprconf() -> str: + """ + Generate the Hypr configuration string using the current bind_vars. + """ + home = os.path.expanduser("~") + return f"""# Generated by {APP_NAME_CAP} - DO NOT EDIT MANUALLY +exec-once = python {home}/{APP_NAME_CAP}/main.py +exec = pgrep -x "hypridle" > /dev/null || hypridle +exec = swww-daemon +exec-once = wl-paste --type text --watch cliphist store +exec-once = wl-paste --type image --watch cliphist store + +$fabricSend = fabric-cli exec {APP_NAME} +$scriptsDir = {home}/{APP_NAME_CAP}/config/scripts/ + +# Key Bindings +bind = {bind_vars["prefix_restart"]}, {bind_vars["suffix_restart"]}, exec, killall {APP_NAME}; python {home}/{APP_NAME_CAP}/main.py # Reload {APP_NAME_CAP} +bind = {bind_vars["prefix_bluetooth"]}, {bind_vars["suffix_bluetooth"]}, exec, $fabricSend 'launcher.open("bluetooth")' # Bluetooth +bind = {bind_vars["prefix_notifications"]}, {bind_vars["suffix_notifications"]}, exec, $fabricSend 'launcher.open("notification-center")' # Notifications +bind = {bind_vars["prefix_emoji"]}, {bind_vars["suffix_emoji"]}, exec, $fabricSend 'launcher.open("emoji")' # Emoji +bind = {bind_vars["prefix_cliphist"]}, {bind_vars["suffix_cliphist"]}, exec, $fabricSend 'launcher.open("cliphist")' # Clipboard History +bind = {bind_vars["prefix_kanban"]}, {bind_vars["suffix_kanban"]}, exec, $fabricSend 'launcher.open("kanban")' # Kanban +bind = {bind_vars["prefix_tmux"]}, {bind_vars["suffix_tmux"]}, exec, $fabricSend 'launcher.open("tmux")' # Tmux Manager +bind = {bind_vars["prefix_toolbox"]}, {bind_vars["suffix_toolbox"]}, exec, $fabricSend 'launcher.open("tools")' # Toolbox +bind = {bind_vars["prefix_walls"]}, {bind_vars["suffix_walls"]}, exec, $fabricSend 'launcher.open("wallpapers")' # Wallpaper Selector +bind = {bind_vars["prefix_launcher"]}, {bind_vars["suffix_launcher"]}, exec, $fabricSend 'launcher.open("launcher")' # App Launcher +bind = {bind_vars["prefix_window_switcher"]}, {bind_vars["suffix_window_switcher"]}, exec, $fabricSend 'launcher.open("window-switcher")' # Window Switcher +bind = {bind_vars["prefix_power"]}, {bind_vars["suffix_power"]}, exec, $fabricSend 'launcher.open("power")' # Power Menu +bind = {bind_vars["prefix_restart_inspector"]}, {bind_vars["suffix_restart_inspector"]}, exec, killall {APP_NAME}; GTK_DEBUG=interactive python {home}/{APP_NAME_CAP}/main.py # Restart with inspector + +# Wallpapers directory: {bind_vars["wallpapers_dir"]} + +# Source color scheme +source = {home}/{APP_NAME_CAP}/config/hypr/colors.conf + +general {{ + col.active_border = 0xff$primary + col.inactive_border = 0xff$surface + gaps_in = 2 + gaps_out = 4 + border_size = 2 + layout = dwindle +}} + +decoration {{ + blur {{ + enabled = yes + size = 5 + passes = 3 + new_optimizations = yes + contrast = 1 + brightness = 1 + }} + rounding = 14 + shadow {{ + enabled = true + range = 10 + render_power = 2 + color = rgba(0, 0, 0, 0.25) + }} +}} + +animations {{ + enabled = true + # Animation curves + bezier = linear, 0, 0, 1, 1 + bezier = md3_standard, 0.2, 0, 0, 1 + bezier = md3_decel, 0.05, 0.7, 0.1, 1 + bezier = md3_accel, 0.3, 0, 0.8, 0.15 + bezier = overshot, 0.05, 0.9, 0.1, 1.1 + bezier = crazyshot, 0.1, 1.5, 0.76, 0.92 + bezier = hyprnostretch, 0.05, 0.9, 0.1, 1.0 + bezier = menu_decel, 0.1, 1, 0, 1 + bezier = menu_accel, 0.38, 0.04, 1, 0.07 + bezier = easeInOutCirc, 0.85, 0, 0.15, 1 + bezier = easeOutCirc, 0, 0.55, 0.45, 1 + bezier = easeOutExpo, 0.16, 1, 0.3, 1 + bezier = softAcDecel, 0.26, 0.26, 0.15, 1 + bezier = md2, 0.4, 0, 0.2, 1 + + animation = windows, 1, 3, md3_decel, popin 60% + animation = windowsIn, 1, 3, md3_decel, popin 60% + animation = windowsOut, 1, 3, md3_accel, popin 60% + animation = border, 1, 10, default + animation = fade, 1, 3, md3_decel + animation = layers, 1, 2, md3_decel, slide + animation = layersIn, 1, 3, menu_decel, slide + animation = layersOut, 1, 1.6, menu_accel, slide + animation = fadeLayersIn, 1, 2, menu_decel + animation = fadeLayersOut, 1, 4.5, menu_accel + animation = workspaces, 1, 7, menu_decel, slide + animation = specialWorkspace, 1, 3, md3_decel, slidevert +}} +""" + + +def backup_and_replace(src: str, dest: str, config_name: str): + """ + Backup the existing configuration file and replace it with a new one. + """ + if os.path.exists(dest): + backup_path = dest + ".bak" + shutil.copy(dest, backup_path) + print(f"{config_name} config backed up to {backup_path}") + shutil.copy(src, dest) + print(f"{config_name} config replaced from {src}") + + +class HyprConfGUI(Window): + def __init__(self, show_lock_checkbox: bool, show_idle_checkbox: bool, **kwargs): + super().__init__( + title="Modus Settings", + name="modus-settings-widnow", + size=(650, 550), + **kwargs, + ) + self.set_resizable(False) + + self.show_lock_checkbox = show_lock_checkbox + self.show_idle_checkbox = show_idle_checkbox + + # Overall vertical box to hold the main content and bottom buttons + root_box = Box(orientation="v", spacing=10, style="margin: 10px;") + self.add(root_box) + + # Main horizontal box for switcher and stack + main_content_box = Box(orientation="h", spacing=6, v_expand=True, h_expand=True) + root_box.add(main_content_box) + + # --- Tab Control --- + self.tab_stack = Stack( + transition_type="slide-up-down", # Change transition for vertical feel + transition_duration=250, + v_expand=True, + h_expand=True, + ) + + # Create tabs and add to stack + self.key_bindings_tab_content = self.create_key_bindings_tab() + self.appearance_tab_content = self.create_appearance_tab() + self.system_tab_content = self.create_system_tab() + self.about_tab_content = self.create_about_tab() + + self.tab_stack.add_titled( + self.key_bindings_tab_content, "key_bindings", "Key Bindings" + ) + self.tab_stack.add_titled( + self.appearance_tab_content, "appearance", "Appearance" + ) + self.tab_stack.add_titled(self.system_tab_content, "system", "System") + self.tab_stack.add_titled( + self.about_tab_content, "about", "About" + ) # Add About tab to stack + + # Use Gtk.StackSwitcher vertically on the left + tab_switcher = Gtk.StackSwitcher() + tab_switcher.set_stack(self.tab_stack) + tab_switcher.set_orientation( + Gtk.Orientation.VERTICAL + ) # Set vertical orientation + # Optional: Adjust alignment if needed + # tab_switcher.set_valign(Gtk.Align.START) + + # Add switcher to the left of the main content box + main_content_box.add(tab_switcher) + + # Add stack to the right of the main content box + main_content_box.add(self.tab_stack) + + # --- Bottom Buttons --- + button_box = Box(orientation="h", spacing=10, h_align="end") + + reset_btn = Button(label="Reset to Defaults", on_clicked=self.on_reset) + button_box.add(reset_btn) + + # Add Close button back + close_btn = Button(label="Close", on_clicked=self.on_close) + button_box.add(close_btn) + + accept_btn = Button(label="Apply & Reload", on_clicked=self.on_accept) + button_box.add(accept_btn) + + # Add button box to the bottom of the root box + root_box.add(button_box) + + def create_key_bindings_tab(self): + """Create tab for key bindings configuration using Fabric widgets and Gtk.Grid.""" + scrolled_window = ScrolledWindow( + h_scrollbar_policy="never", + v_scrollbar_policy="automatic", + h_expand=True, + v_expand=True, + ) + # Remove fixed height constraints to allow stack to fill space + scrolled_window.set_min_content_height(300) + scrolled_window.set_max_content_height(300) + + # Main container with padding + main_vbox = Box(orientation="v", spacing=10, style="margin: 15px;") + scrolled_window.add(main_vbox) + + # Create a grid for key bindings + keybind_grid = Gtk.Grid() + keybind_grid.set_column_spacing(10) + keybind_grid.set_row_spacing(8) + keybind_grid.set_margin_start(5) + keybind_grid.set_margin_end(5) + keybind_grid.set_margin_top(5) + keybind_grid.set_margin_bottom(5) + + # Header Row + action_label = Label( + markup="Action", h_align="start", style="margin-bottom: 5px;" + ) + modifier_label = Label( + markup="Modifier", h_align="start", style="margin-bottom: 5px;" + ) + separator_label = Label( + label="+", h_align="center", style="margin-bottom: 5px;" + ) + key_label = Label( + markup="Key", h_align="start", style="margin-bottom: 5px;" + ) + + keybind_grid.attach(action_label, 0, 0, 1, 1) + keybind_grid.attach(modifier_label, 1, 0, 1, 1) + keybind_grid.attach(separator_label, 2, 0, 1, 1) + keybind_grid.attach(key_label, 3, 0, 1, 1) + + self.entries = [] + bindings = [ + (f"Reload {APP_NAME_CAP}", "prefix_restart", "suffix_restart"), + ("Bluetooth", "prefix_bluetooth", "suffix_bluetooth"), + ("Notifications", "prefix_notifications", "suffix_notifications"), + ("Kanban", "prefix_kanban", "suffix_kanban"), + ("App Launcher", "prefix_launcher", "suffix_launcher"), + ("Tmux", "prefix_tmux", "suffix_tmux"), + ("Toolbox", "prefix_toolbox", "suffix_toolbox"), + ("Wallpapers", "prefix_walls", "suffix_walls"), + ("Emoji Picker", "prefix_emoji", "suffix_emoji"), + ("Clipboard History", "prefix_cliphist", "suffix_cliphist"), + ("Window Switcher", "prefix_window_switcher", "suffix_window_switcher"), + ("Power Menu", "prefix_power", "suffix_power"), + ( + "Restart with inspector", + "prefix_restart_inspector", + "suffix_restart_inspector", + ), + ] + + # Populate the grid with entries + for i, (label_text, prefix_key, suffix_key) in enumerate(bindings): + row = i + 1 # Start at row 1 after headers + + # Action label + binding_label = Label(label=label_text, h_align="start") + keybind_grid.attach(binding_label, 0, row, 1, 1) + + # Prefix entry + prefix_entry = Entry(text=bind_vars[prefix_key]) + keybind_grid.attach(prefix_entry, 1, row, 1, 1) + + # Plus separator + plus_label = Label(label="+", h_align="center") + keybind_grid.attach(plus_label, 2, row, 1, 1) + + # Suffix entry + suffix_entry = Entry(text=bind_vars[suffix_key]) + keybind_grid.attach(suffix_entry, 3, row, 1, 1) + + self.entries.append((prefix_key, suffix_key, prefix_entry, suffix_entry)) + + main_vbox.add(keybind_grid) + return scrolled_window + + def create_appearance_tab(self): + """Create tab for appearance settings using Fabric widgets and Gtk.Grid.""" + scrolled_window = ScrolledWindow( + h_scrollbar_policy="never", + v_scrollbar_policy="automatic", + h_expand=True, + v_expand=True, + ) + scrolled_window.set_min_content_height(300) + scrolled_window.set_max_content_height(300) + + # Main container with padding + vbox = Box(orientation="v", spacing=15, style="margin: 15px;") + scrolled_window.add(vbox) + + # === WALLPAPERS SECTION === + wall_header = Label(markup="Wallpapers", h_align="start") + vbox.add(wall_header) + + wall_box = Box(orientation="h", spacing=10, style="margin-left: 10px;") + vbox.add(wall_box) + + wall_label = Label(label="Directory:", h_align="start", v_align="center") + wall_box.add(wall_label) + + self.wall_dir_chooser = Gtk.FileChooserButton( + title="Select a folder", action=Gtk.FileChooserAction.SELECT_FOLDER + ) + self.wall_dir_chooser.set_tooltip_text( + "Select the directory containing your wallpaper images" + ) + self.wall_dir_chooser.set_filename(bind_vars["wallpapers_dir"]) + self.wall_dir_chooser.set_size_request(180, -1) + wall_box.add(self.wall_dir_chooser) + + # === LAYOUT OPTIONS SECTION === + layout_header = Label(markup="Layout Options", h_align="start") + vbox.add(layout_header) + + # Create a grid for layout options + layout_grid = Gtk.Grid() + layout_grid.set_column_spacing(20) + layout_grid.set_row_spacing(15) + layout_grid.set_margin_start(10) + layout_grid.set_margin_top(5) + layout_grid.set_margin_bottom(10) + vbox.add(layout_grid) + + # Column 1 (Left) + # Vertical Layout + vertical_label = Label( + label="Vertical Layout", h_align="start", v_align="center" + ) + layout_grid.attach(vertical_label, 0, 0, 1, 1) + + vertical_switch_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) + vertical_switch_container.set_halign(Gtk.Align.START) + vertical_switch_container.set_valign(Gtk.Align.CENTER) + + self.vertical_switch = Gtk.Switch() + self.vertical_switch.set_active(bind_vars.get("vertical", False)) + self.vertical_switch.connect("notify::active", self.on_vertical_changed) + vertical_switch_container.add(self.vertical_switch) + + layout_grid.attach(vertical_switch_container, 1, 0, 1, 1) + + # Vertical Right Align (new) + vertical_right_label = Label( + label="Right Side (Vertical)", h_align="start", v_align="center" + ) + layout_grid.attach(vertical_right_label, 0, 1, 1, 1) + + vertical_right_switch_container = Gtk.Box( + orientation=Gtk.Orientation.HORIZONTAL + ) + vertical_right_switch_container.set_halign(Gtk.Align.START) + vertical_right_switch_container.set_valign(Gtk.Align.CENTER) + + self.vertical_right_switch = Gtk.Switch() + self.vertical_right_switch.set_active( + bind_vars.get("vertical_right_align", True) + ) + self.vertical_right_switch.set_sensitive(self.vertical_switch.get_active()) + vertical_right_switch_container.add(self.vertical_right_switch) + layout_grid.attach(vertical_right_switch_container, 1, 1, 1, 1) + + # Bottom Layout + bottom_bar_label = Label( + label="Bottom Layout", h_align="start", v_align="center" + ) + layout_grid.attach(bottom_bar_label, 0, 2, 1, 1) + + bottom_bar_switch_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) + bottom_bar_switch_container.set_halign(Gtk.Align.START) + bottom_bar_switch_container.set_valign(Gtk.Align.CENTER) + + self.bottom_bar_switch = Gtk.Switch() + self.bottom_bar_switch.set_active(bind_vars.get("bottom_bar", False)) + self.bottom_bar_switch.connect("notify::active", self.on_bottom_bar_changed) + bottom_bar_switch_container.add(self.bottom_bar_switch) + layout_grid.attach(bottom_bar_switch_container, 1, 2, 1, 1) + + # Dock Options + dock_label = Label(label="Show Dock", h_align="start", v_align="center") + layout_grid.attach(dock_label, 0, 3, 1, 1) + + dock_switch_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) + dock_switch_container.set_halign(Gtk.Align.START) + dock_switch_container.set_valign(Gtk.Align.CENTER) + + self.dock_switch = Gtk.Switch() + self.dock_switch.set_active(bind_vars.get("dock_enabled", True)) + self.dock_switch.connect("notify::active", self.on_dock_enabled_changed) + dock_switch_container.add(self.dock_switch) + layout_grid.attach(dock_switch_container, 1, 3, 1, 1) + + # Column 2 (Right) + # Centered Bar + centered_label = Label( + label="Centered Bar (Vertical Only)", h_align="start", v_align="center" + ) + layout_grid.attach(centered_label, 2, 0, 1, 1) + + centered_switch_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) + centered_switch_container.set_halign(Gtk.Align.START) + centered_switch_container.set_valign(Gtk.Align.CENTER) + + self.centered_switch = Gtk.Switch() + self.centered_switch.set_active(bind_vars.get("centered_bar", False)) + self.centered_switch.set_sensitive(self.vertical_switch.get_active()) + centered_switch_container.add(self.centered_switch) + layout_grid.attach(centered_switch_container, 3, 0, 1, 1) + + # Dock Hover + dock_hover_label = Label( + label="Show Dock Only on Hover", h_align="start", v_align="center" + ) + layout_grid.attach(dock_hover_label, 2, 1, 1, 1) + + dock_hover_switch_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) + dock_hover_switch_container.set_halign(Gtk.Align.START) + dock_hover_switch_container.set_valign(Gtk.Align.CENTER) + + self.dock_hover_switch = Gtk.Switch() + self.dock_hover_switch.set_active(bind_vars.get("dock_always_occluded", False)) + self.dock_hover_switch.set_sensitive(self.dock_switch.get_active()) + dock_hover_switch_container.add(self.dock_hover_switch) + layout_grid.attach(dock_hover_switch_container, 3, 1, 1, 1) + + # Show OSD + osd_label = Label(label="Show OSD", h_align="start", v_align="center") + layout_grid.attach(osd_label, 2, 2, 1, 1) + + osd_hover_switch_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) + osd_hover_switch_container.set_halign(Gtk.Align.START) + osd_hover_switch_container.set_valign(Gtk.Align.CENTER) + + self.osd_switch = Gtk.Switch() + self.osd_switch.set_active(bind_vars.get("osd_enabled", True)) + osd_hover_switch_container.add(self.osd_switch) + layout_grid.attach(osd_hover_switch_container, 3, 2, 1, 1) + + # Dock Icon Size (Full width) + dock_size_label = Label( + label="Dock Icon Size", h_align="start", v_align="center" + ) + layout_grid.attach(dock_size_label, 0, 4, 1, 1) + + self.dock_size_scale = Scale( + min_value=16, + max_value=48, + value=bind_vars.get("dock_icon_size", 28), + increments=(2, 4), + draw_value=True, + value_position="right", + digits=0, + h_expand=True, + ) + layout_grid.attach(self.dock_size_scale, 1, 4, 3, 1) + + # === BAR COMPONENTS SECTION === + components_header = Label(markup="Bar Components", h_align="start") + vbox.add(components_header) + + # Create a grid for bar components + components_grid = Gtk.Grid() + components_grid.set_column_spacing(15) + components_grid.set_row_spacing(8) + components_grid.set_margin_start(10) + components_grid.set_margin_top(5) + vbox.add(components_grid) + + self.component_switches = {} + component_display_names = { + "button_app": "App Launcher Button", + "tray": "System Tray", + "workspaces": "Workspaces", + "metrics": "System Metrics", + "language": "Language Indicator", + "date_time": "Date & Time", + "updates": "Update Indicator", + "indicators": "System Indicators", + } + + # Add corners visibility switch + self.corners_switch = Gtk.Switch() + self.corners_switch.set_active(bind_vars.get("corners_visible", True)) + + # Calculate number of rows needed (we'll use 2 columns) + num_components = len(component_display_names) + 1 # +1 for corners + rows_per_column = (num_components + 1) // 2 # Ceiling division + + # First add corners to the top of first column + corners_label = Label( + label="Rounded Corners", h_align="start", v_align="center" + ) + components_grid.attach(corners_label, 0, 0, 1, 1) + + switch_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) + switch_container.set_halign(Gtk.Align.START) + switch_container.set_valign(Gtk.Align.CENTER) + switch_container.add(self.corners_switch) + components_grid.attach(switch_container, 1, 0, 1, 1) + + # Add components to grid in two columns + for i, (component_name, display_name) in enumerate( + component_display_names.items() + ): + # Determine position: first half in column 0, second half in column 2 + # Start at row 1 to account for corners at row 0 + row = (i + 1) % rows_per_column # +1 to start after corners + col = 0 if i < (rows_per_column - 1) else 2 # Adjust column calculation + + component_label = Label( + label=display_name, h_align="start", v_align="center" + ) + components_grid.attach(component_label, col, row, 1, 1) + + # Container for switch to prevent stretching + switch_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) + switch_container.set_halign(Gtk.Align.START) + switch_container.set_valign(Gtk.Align.CENTER) + + component_switch = Gtk.Switch() + config_key = f"bar_{component_name}_visible" + component_switch.set_active(bind_vars.get(config_key, True)) + switch_container.add(component_switch) + + components_grid.attach(switch_container, col + 1, row, 1, 1) + + self.component_switches[component_name] = component_switch + + return scrolled_window + + def create_system_tab(self): + """Create tab for system configurations using Fabric widgets and Gtk.Grid.""" + scrolled_window = ScrolledWindow( + h_scrollbar_policy="never", + v_scrollbar_policy="automatic", + h_expand=True, + v_expand=True, + ) + # Remove fixed height constraints + scrolled_window.set_min_content_height(300) + scrolled_window.set_max_content_height(300) + + # Main container with padding + vbox = Box(orientation="v", spacing=15, style="margin: 15px;") + scrolled_window.add(vbox) + + # Create a grid for system settings + system_grid = Gtk.Grid() + system_grid.set_column_spacing(20) + system_grid.set_row_spacing(10) + system_grid.set_margin_bottom(15) + vbox.add(system_grid) + + # === TERMINAL SETTINGS === + terminal_header = Label(markup="Terminal Settings", h_align="start") + system_grid.attach(terminal_header, 0, 0, 2, 1) + + terminal_label = Label(label="Command:", h_align="start", v_align="center") + system_grid.attach(terminal_label, 0, 1, 1, 1) + + self.terminal_entry = Entry( + text=bind_vars["terminal_command"], + tooltip_text="Command used to launch terminal apps (e.g., 'kitty -e')", + h_expand=True, + ) + system_grid.attach(self.terminal_entry, 1, 1, 1, 1) + + hint_label = Label( + markup="Examples: 'kitty -e', 'alacritty -e', 'foot -e'", + h_align="start", + ) + system_grid.attach(hint_label, 0, 2, 2, 1) + + # === HYPRLAND INTEGRATION === + hypr_header = Label(markup="Hyprland Integration", h_align="start") + system_grid.attach(hypr_header, 2, 0, 2, 1) + + row = 1 + + # Hyprland locks and idle settings + self.lock_switch = None + if self.show_lock_checkbox: + lock_label = Label( + label="Replace Hyprlock config", h_align="start", v_align="center" + ) + system_grid.attach(lock_label, 2, row, 1, 1) + + # Container for switch to prevent stretching + lock_switch_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) + lock_switch_container.set_halign(Gtk.Align.START) + lock_switch_container.set_valign(Gtk.Align.CENTER) + + self.lock_switch = Gtk.Switch() + self.lock_switch.set_tooltip_text( + "Replace Hyprlock configuration with Ax-Shell's custom config" + ) + lock_switch_container.add(self.lock_switch) + + system_grid.attach(lock_switch_container, 3, row, 1, 1) + row += 1 + + self.idle_switch = None + if self.show_idle_checkbox: + idle_label = Label( + label="Replace Hypridle config", h_align="start", v_align="center" + ) + system_grid.attach(idle_label, 2, row, 1, 1) + + # Container for switch to prevent stretching + idle_switch_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) + idle_switch_container.set_halign(Gtk.Align.START) + idle_switch_container.set_valign(Gtk.Align.CENTER) + + self.idle_switch = Gtk.Switch() + self.idle_switch.set_tooltip_text( + "Replace Hypridle configuration with Ax-Shell's custom config" + ) + idle_switch_container.add(self.idle_switch) + + system_grid.attach(idle_switch_container, 3, row, 1, 1) + row += 1 + + if self.show_lock_checkbox or self.show_idle_checkbox: + note_label = Label( + markup="Existing configs will be backed up", + h_align="start", + ) + system_grid.attach(note_label, 2, row, 2, 1) + + # --- System Metrics Options (moved from appearance tab) --- + metrics_header = Label(markup="System Metrics Options", h_align="start") + vbox.add(metrics_header) + + # Metrics visibility toggles + metrics_grid = Gtk.Grid() + metrics_grid.set_column_spacing(15) + metrics_grid.set_row_spacing(8) + metrics_grid.set_margin_start(10) + metrics_grid.set_margin_top(5) + vbox.add(metrics_grid) + + self.metrics_switches = {} + + metric_names = { + "cpu": "CPU", + "ram": "RAM", + "disk": "Disk", + "swap": "Swap", + "gpu": "GPU", + } + + # metrics toggles + metrics_grid.attach(Label(label="Show in Metrics", h_align="start"), 2, 0, 1, 1) + for i, (key, label) in enumerate(metric_names.items()): + switch = Gtk.Switch() + switch.set_active(bind_vars.get("metrics_visible", {}).get(key, True)) + self.metrics_switches[key] = switch + metrics_grid.attach(Label(label=label, h_align="start"), 2, i + 1, 1, 1) + metrics_grid.attach(switch, 4, i + 1, 1, 1) + + # Enforce minimum 4 enabled metrics + def enforce_minimum_metrics(switch_dict): + enabled = [k for k, s in switch_dict.items() if s.get_active()] + for k, s in switch_dict.items(): + if len(enabled) <= 4 and s.get_active(): + s.set_sensitive(False) + else: + s.set_sensitive(True) + + def on_metric_toggle(switch, gparam, which): + enforce_minimum_metrics(self.metrics_switches) + + for k, s in self.metrics_switches.items(): + s.connect("notify::active", on_metric_toggle, k) + enforce_minimum_metrics(self.metrics_switches) + + # Disk directories + disks_label = Label(label="Disk directories", h_align="start", v_align="center") + vbox.add(disks_label) + + self.disk_entries = Box(orientation="v", spacing=8, h_align="start") + + def create_disk_edit(path): + bar = Box(orientation="h", spacing=10, h_align="start") + entry = Entry(text=path, h_expand=True) + bar.add(entry) + x = Button(label="X", on_clicked=lambda _: self.disk_entries.remove(bar)) + bar.add(x) + self.disk_entries.add(bar) + + vbox.add(self.disk_entries) + for path in bind_vars.get("bar_metrics_disks"): + create_disk_edit(path) + add_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) + add_container.set_halign(Gtk.Align.START) + add_container.set_valign(Gtk.Align.CENTER) + add = Button(label="Add new disk", on_clicked=lambda _: create_disk_edit("/")) + add_container.add(add) + vbox.add(add_container) + + return scrolled_window + + def create_about_tab(self): + """Create an About tab with project info, repo link, and Ko-Fi button.""" + vbox = Box(orientation="v", spacing=18, style="margin: 30px;") + # Project title + vbox.add( + Label( + markup=f"{APP_NAME_CAP}", + h_align="start", + style="font-size: 1.5em; margin-bottom: 8px;", + ) + ) + # Description + vbox.add( + Label( + label="A hackable shell for Hyprland, powered by Fabric.", + h_align="start", + style="margin-bottom: 12px;", + ) + ) + # Repo link + repo_box = Box(orientation="h", spacing=6, h_align="start") + repo_label = Label(label="GitHub:", h_align="start") + repo_link = Label() + repo_link.set_markup( + f'https://github.com/S4NKALP/Modus' + ) + repo_box.add(repo_label) + repo_box.add(repo_link) + vbox.add(repo_box) + + # Ko-Fi button + def on_kofi_clicked(_): + import webbrowser + + webbrowser.open("https://ko-fi.com/S4NKALP") + + kofi_btn = Button( + label="Support on Ko-Fi โค๏ธ", + on_clicked=on_kofi_clicked, + tooltip_text="Support S4NKALP on Ko-Fi", + ) + kofi_btn.set_style("margin-top: 18px; min-width: 160px;") + vbox.add(kofi_btn) + # Spacer + vbox.add(Box(v_expand=True)) + return vbox + + def on_vertical_changed(self, switch, gparam): + """Callback for vertical switch.""" + is_active = switch.get_active() + self.centered_switch.set_sensitive(is_active) + self.vertical_right_switch.set_sensitive(is_active) + + if is_active: + # Disable bottom bar when vertical layout is enabled + bind_vars["bottom_bar"] = False + self.bottom_bar_switch.set_active(False) + + def on_dock_enabled_changed(self, switch, gparam): + """Callback for dock enabled switch.""" + is_active = switch.get_active() + self.dock_hover_switch.set_sensitive(is_active) + if not is_active: + self.dock_hover_switch.set_active(False) + + def on_bottom_bar_changed(self, switch, gparam): + """Handle bottom bar switch changes""" + bind_vars["bottom_bar"] = switch.get_active() + if switch.get_active(): + # Disable vertical layout + bind_vars["vertical"] = False + self.vertical_switch.set_active(False) + + # Only disable centered bar without turning it off + self.centered_switch.set_sensitive(False) + + # Disable right side option and reset it to False + self.vertical_right_switch.set_sensitive(False) + self.vertical_right_switch.set_active(False) + bind_vars["vertical_right_align"] = False + + def on_accept(self, widget): + """ + Save the configuration and update the necessary files without closing the window. + """ + for prefix_key, suffix_key, prefix_entry, suffix_entry in self.entries: + bind_vars[prefix_key] = prefix_entry.get_text() + bind_vars[suffix_key] = suffix_entry.get_text() + + bind_vars["wallpapers_dir"] = self.wall_dir_chooser.get_filename() + bind_vars["vertical"] = self.vertical_switch.get_active() + bind_vars["vertical_right_align"] = self.vertical_right_switch.get_active() + bind_vars["bottom_bar"] = self.bottom_bar_switch.get_active() + bind_vars["enabled_osd"] = self.osd_switch.get_active() + bind_vars["centered_bar"] = self.centered_switch.get_active() + bind_vars["dock_enabled"] = self.dock_switch.get_active() + bind_vars["dock_always_occluded"] = self.dock_hover_switch.get_active() + bind_vars["dock_icon_size"] = int(self.dock_size_scale.get_value()) + bind_vars["terminal_command"] = self.terminal_entry.get_text() + bind_vars["corners_visible"] = self.corners_switch.get_active() + + for component_name, switch in self.component_switches.items(): + config_key = f"bar_{component_name}_visible" + bind_vars[config_key] = switch.get_active() + + # Save metrics visibility + bind_vars["metrics_visible"] = { + k: s.get_active() for k, s in self.metrics_switches.items() + } + + bind_vars["bar_metrics_disks"] = [] + for entry in self.disk_entries.children: + bind_vars["bar_metrics_disks"].append(entry.children[0].get_text()) + + config_json = os.path.expanduser(f"~/{APP_NAME_CAP}/config/assets/config.json") + os.makedirs(os.path.dirname(config_json), exist_ok=True) + try: + with open(config_json, "w") as f: + json.dump(bind_vars, f, indent=4) + except Exception as e: + print(f"Error saving config.json: {e}") + + if self.lock_switch and self.lock_switch.get_active(): + src_lock = os.path.expanduser(f"~/{APP_NAME_CAP}/config/hypr/hyprlock.conf") + dest_lock = os.path.expanduser("~/.config/hypr/hyprlock.conf") + if os.path.exists(src_lock): + backup_and_replace(src_lock, dest_lock, "Hyprlock") + else: + print(f"Warning: Source hyprlock config not found at {src_lock}") + + if self.idle_switch and self.idle_switch.get_active(): + src_idle = os.path.expanduser(f"~/{APP_NAME_CAP}/config/hypr/hypridle.conf") + dest_idle = os.path.expanduser("~/.config/hypr/hypridle.conf") + if os.path.exists(src_idle): + backup_and_replace(src_idle, dest_idle, "Hypridle") + else: + print(f"Warning: Source hypridle config not found at {src_idle}") + + hyprland_config_path = os.path.expanduser("~/.config/hypr/hyprland.conf") + try: + needs_append = True + if os.path.exists(hyprland_config_path): + with open(hyprland_config_path, "r") as f: + content = f.read() + if SOURCE_STRING.strip() in content: + needs_append = False + else: + os.makedirs(os.path.dirname(hyprland_config_path), exist_ok=True) + + if needs_append: + with open(hyprland_config_path, "a") as f: + f.write("\n" + SOURCE_STRING) + print(f"Appended source string to {hyprland_config_path}") + + except Exception as e: + print(f"Error updating {hyprland_config_path}: {e}") + + start_config() + + # Restart Modus using fabric's async command executor + main_script_path = os.path.expanduser(f"~/{APP_NAME_CAP}/main.py") + kill_cmd = f"killall {APP_NAME}" + start_cmd = f"python {main_script_path}" + + try: + # Use fabric's helper to run the command asynchronously + exec_shell_command(kill_cmd) + exec_shell_command_async(start_cmd) + print(f"{APP_NAME_CAP} restart initiated.") + except Exception as e: + print(f"Error restarting {APP_NAME_CAP}: {e}") + + def on_reset(self, widget): + """ + Reset all settings to default values. Uses Gtk.MessageDialog. + """ + dialog = Gtk.MessageDialog( + transient_for=self.get_toplevel(), + flags=0, + message_type=Gtk.MessageType.QUESTION, + buttons=Gtk.ButtonsType.YES_NO, + text="Reset all settings to defaults?", + ) + dialog.format_secondary_text( + "This will reset all keybindings and appearance settings to their default values." + ) + response = dialog.run() + dialog.destroy() + + if response == Gtk.ResponseType.YES: + global bind_vars + bind_vars = DEFAULTS.copy() + + for prefix_key, suffix_key, prefix_entry, suffix_entry in self.entries: + prefix_entry.set_text(bind_vars[prefix_key]) + suffix_entry.set_text(bind_vars[suffix_key]) + + self.wall_dir_chooser.set_filename(bind_vars["wallpapers_dir"]) + self.vertical_switch.set_active(bind_vars.get("vertical", False)) + self.vertical_right_switch.set_active( + bind_vars.get("vertical_right_align", True) + ) + self.centered_switch.set_active(bind_vars.get("centered_bar", False)) + self.centered_switch.set_sensitive(self.vertical_switch.get_active()) + self.vertical_right_switch.set_sensitive(self.vertical_switch.get_active()) + self.dock_switch.set_active(bind_vars.get("dock_enabled", True)) + self.dock_hover_switch.set_active( + bind_vars.get("dock_always_occluded", False) + ) + self.dock_hover_switch.set_sensitive(self.dock_switch.get_active()) + self.dock_size_scale.value = bind_vars.get("dock_icon_size", 28) + self.terminal_entry.set_text(bind_vars["terminal_command"]) + self.osd_switch.set_active(bind_vars.get("osd_enabled", True)) + self.bottom_bar_switch.set_active(bind_vars.get("bottom_bar", False)) + + for component_name, switch in self.component_switches.items(): + config_key = f"bar_{component_name}_visible" + switch.set_active(bind_vars.get(config_key, True)) + + self.corners_switch.set_active(bind_vars.get("corners_visible", True)) + + # Reset metrics visibility + for k, s in self.metrics_switches.items(): + s.set_active(DEFAULTS["metrics_visible"][k]) + + # Reset disk entries + if True: + for i in self.disk_entries.children: + self.disk_entries.remove(i) + bar = Box(orientation="h", spacing=10, h_align="start") + entry = Entry(text="/", h_expand=True) + bar.add(entry) + x = Button( + label="X", on_clicked=lambda _: self.disk_entries.remove(bar) + ) + bar.add(x) + self.disk_entries.add(bar) + + if self.lock_switch: + self.lock_switch.set_active(False) + if self.idle_switch: + self.idle_switch.set_active(False) + + print("Settings reset to defaults.") + + def on_close(self, widget): + """Close the settings window.""" + if self.application: + self.application.quit() + else: + self.destroy() + + +def start_config(): + """ + Run final configuration steps: ensure necessary configs, write the hyprconf, and reload. + """ + ensure_matugen_config() + + hypr_config_dir = os.path.expanduser(f"~/{APP_NAME_CAP}/config/hypr/") + os.makedirs(hypr_config_dir, exist_ok=True) + hypr_conf_path = os.path.join(hypr_config_dir, f"{APP_NAME}.conf") + try: + with open(hypr_conf_path, "w") as f: + f.write(generate_hyprconf()) + print(f"Generated Hyprland config at {hypr_conf_path}") + except Exception as e: + print(f"Error writing Hyprland config: {e}") + + try: + subprocess.run(["hyprctl", "reload"], check=True, capture_output=True) + print("Hyprland configuration reloaded.") + except subprocess.CalledProcessError as e: + print(f"Error reloading Hyprland: {e}\nstderr: {e.stderr.decode()}") + except FileNotFoundError: + print("Error: hyprctl command not found. Cannot reload Hyprland.") + except Exception as e: + print(f"An unexpected error occurred during hyprctl reload: {e}") + + +def open_config(): + """ + Entry point for opening the configuration GUI using Fabric Application. + """ + load_bind_vars() + + dest_lock = os.path.expanduser("~/.config/hypr/hyprlock.conf") + src_lock = os.path.expanduser(f"~/{APP_NAME_CAP}/config/hypr/hyprlock.conf") + show_lock_checkbox = True + if not os.path.exists(dest_lock) and os.path.exists(src_lock): + try: + os.makedirs(os.path.dirname(dest_lock), exist_ok=True) + shutil.copy(src_lock, dest_lock) + show_lock_checkbox = False + print(f"Copied default hyprlock config to {dest_lock}") + except Exception as e: + print(f"Error copying default hyprlock config: {e}") + show_lock_checkbox = os.path.exists(src_lock) + + dest_idle = os.path.expanduser("~/.config/hypr/hypridle.conf") + src_idle = os.path.expanduser(f"~/{APP_NAME_CAP}/config/hypr/hypridle.conf") + show_idle_checkbox = True + if not os.path.exists(dest_idle) and os.path.exists(src_idle): + try: + os.makedirs(os.path.dirname(dest_idle), exist_ok=True) + shutil.copy(src_idle, dest_idle) + show_idle_checkbox = False + print(f"Copied default hypridle config to {dest_idle}") + except Exception as e: + print(f"Error copying default hypridle config: {e}") + show_idle_checkbox = os.path.exists(src_idle) + + app = Application(f"{APP_NAME}-settings") + window = HyprConfGUI( + show_lock_checkbox=show_lock_checkbox, + show_idle_checkbox=show_idle_checkbox, + application=app, + on_destroy=lambda *_: app.quit(), + ) + app.add_window(window) + + window.show_all() + app.run() + + +if __name__ == "__main__": + open_config() diff --git a/config/data.py b/config/data.py new file mode 100644 index 0000000..681e9d1 --- /dev/null +++ b/config/data.py @@ -0,0 +1,129 @@ +from fabric.utils import get_relative_path +from gi.repository import Gdk, GLib +import os +import json +import gi + +gi.require_version("Gtk", "3.0") + + +APP_NAME = "modusv2" +APP_NAME_CAP = "Modusv2" + +CACHE_DIR = str(GLib.get_user_cache_dir()) + f"/{APP_NAME}" +STATE_DIR = str(GLib.get_user_state_dir() + f"/{APP_NAME}") + + +USERNAME = os.getlogin() +HOSTNAME = os.uname().nodename +HOME_DIR = os.path.expanduser("~") + +CONFIG_DIR = os.path.expanduser(f"~/{APP_NAME}") +MATUGEN_STATE_FILE = os.path.join(CONFIG_DIR, "matugen") + +screen = Gdk.Screen.get_default() +CURRENT_WIDTH = screen.get_width() +CURRENT_HEIGHT = screen.get_height() + +WALLPAPERS_DIR_DEFAULT = get_relative_path("../assets/wallpaper") +CONFIG_FILE = get_relative_path("../config/assets/config.json") + +if os.path.exists(CONFIG_FILE): + with open(CONFIG_FILE, "r") as f: + config = json.load(f) + WALLPAPERS_DIR = config.get("wallpapers_dir", WALLPAPERS_DIR_DEFAULT) + # Use saved value or False as default + VERTICAL = config.get("vertical", False) + VERTICAL_RIGHT_ALIGN = config.get( + "vertical_right_align", False + ) # Right side by default + # Use saved value or False as default + BOTTOM_BAR = config.get("bottom_bar", False) + # Load centered bar setting + CENTERED_BAR = config.get("centered_bar", False) + TERMINAL_COMMAND = config.get( + "terminal_command", "kitty -e" + ) # Load terminal command + # Load dock visibility setting + DOCK_ENABLED = config.get("dock_enabled", True) + DOCK_ALWAYS_OCCLUDED = config.get( + "dock_always_occluded", False + ) # Load dock hover-only setting + # Load dock icon size setting + DOCK_ICON_SIZE = config.get("dock_icon_size", 28) + # Load OSD visibility setting + OSD_ENABLED = config.get("osd_enabled", True) + + # Load bar component visibility settings + BAR_COMPONENTS_VISIBILITY = { + "button_app": config.get("bar_button_app_visible", True), + "tray": config.get("bar_tray_visible", True), + # "button_tools": config.get("bar_button_tools_visible", True), + "workspaces": config.get("bar_workspaes_visible", True), + "metrics": config.get("bar_metrics_visible", True), + "language": config.get("bar_language_visible", True), + "date_time": config.get("bar_date_time_visible", True), + "updates": config.get("bar_updates_visible", True), + "indicators": config.get("bar_indicators", True), + } + + BAR_METRICS_DISKS = config.get("bar_metrics_disks", ["/"]) + METRICS_VISIBLE = config.get( + "metrics_visible", + {"cpu": True, "ram": True, "disk": True, "swap": True, "gpu": False}, + ) +else: + WALLPAPERS_DIR = WALLPAPERS_DIR_DEFAULT + VERTICAL = False # Default value when no config exists + VERTICAL_RIGHT_ALIGN = False # Default to right alignment + BOTTOM_BAR = False # Default value for bottom bar + CENTERED_BAR = False # Default value for centered bar + DOCK_ENABLED = True # Default value for dock visibility + DOCK_ALWAYS_OCCLUDED = False # Default value for dock hover-only mode + OSD_ENABLED = True # Default value for OSD visibility + TERMINAL_COMMAND = "kitty -e" # Default terminal command when no config + DOCK_ICON_SIZE = 28 # Default dock icon size when no config + + # Default values for component visibility (all visible) + BAR_COMPONENTS_VISIBILITY = { + "button_aps": True, + "tray": True, + # "button_tools": True, + "workspaces": True, + "metrics": True, + "language": True, + "date_time": True, + "indicators": True, + "updates": True, + } + + BAR_METRICS_DISKS = ["/"] + METRICS_VISIBLE = { + "cpu": True, + "ram": True, + "disk": True, + "swap": True, + "gpu": False, + } + + +def read_config(): + config_path = get_relative_path("./assets/modus.json") + + with open(config_path, "r") as file: + # Load JSON data into a Python dictionary + data = json.load(file) + return data + + +def load_config(): + """Load the configuration from config.json""" + config_path = get_relative_path("./assets/config.json") + config = {} + if os.path.exists(config_path): + try: + with open(config_path, "r") as f: + config = json.load(f) + except Exception as e: + print(f"Error loading config: {e}") + return config diff --git a/config/hypr/colors.conf b/config/hypr/colors.conf new file mode 100644 index 0000000..1377374 --- /dev/null +++ b/config/hypr/colors.conf @@ -0,0 +1,11 @@ +$wallpaper = /home/sankalp/Pictures/wallpapers/1.png +$background = 111318 +$foreground = e1e2e9 + +$primary = a5c8ff +$secondary = bcc7dc +$tertiary = dabde2 +$surface = 111318 +$surface_bright = 37393e +$outline = 8d9199 +$error = ff5945 diff --git a/config/hypr/hypridle.conf b/config/hypr/hypridle.conf new file mode 100644 index 0000000..48bd7d7 --- /dev/null +++ b/config/hypr/hypridle.conf @@ -0,0 +1,41 @@ + +listener { + timeout = 500 # in seconds. + on-timeout = notify-send "You are idle!" # command to run when timeout has passed. + on-resume = notify-send "Welcome back!" # command to run when activity is detected after timeout has fired. +} + +general { + lock_cmd = pidof hyprlock || hyprlock # avoid starting multiple hyprlock instances. + before_sleep_cmd = loginctl lock-session # lock before suspend. + after_sleep_cmd = hyprctl dispatch dpms on # to avoid having to press a key twice to turn on the display. +} + +listener { + timeout = 150 # 2.5min. + on-timeout = brightnessctl -s set 10 # set monitor backlight to minimum, avoid 0 on OLED monitor. + on-resume = brightnessctl -r # monitor backlight restore. +} + +# turn off keyboard backlight, comment out this section if you dont have a keyboard backlight. +listener { + timeout = 150 # 2.5min. + on-timeout = brightnessctl -sd rgb:kbd_backlight set 0 # turn off keyboard backlight. + on-resume = brightnessctl -rd rgb:kbd_backlight # turn on keyboard backlight. +} + +listener { + timeout = 300 # 5min + on-timeout = loginctl lock-session # lock screen when timeout has passed +} + +listener { + timeout = 330 # 5.5min + on-timeout = hyprctl dispatch dpms off # screen off when timeout has passed + on-resume = hyprctl dispatch dpms on # screen on when activity is detected after timeout has fired. +} + +listener { + timeout = 1800 # 30min + on-timeout = systemctl suspend # suspend pc +} diff --git a/config/hypr/hyprlock.conf b/config/hypr/hyprlock.conf new file mode 100644 index 0000000..80977af --- /dev/null +++ b/config/hypr/hyprlock.conf @@ -0,0 +1,150 @@ + + +source = ~/Modus/config/hypr/colors.conf + +# Configuration + # (general settings) + general { + grace = 2 + hide_cursor = true + ignore_empty_input = true + text_trim = true + } + # (background config) + background { + monitor = + path = $wallpaper # only png supported for now + # color = rgba(26,17,16, 1.0) + blur_passes = 3 # 0 disables blurring + blur_size = 1 + noise = 0.01 + contrast = 0.8916 + brightness = 0.7 + vibrancy = 0.1696 + vibrancy_darkness = 0.0 + } + + +# Password input + input-field { + monitor = + size = 256, 48 + outline_thickness = -1 + dots_size = 0.33 + dots_spacing = 0.45 + dots_center = true + dots_rounding = -1 + outer_color = rgba(0,0,0,0) + inner_color = rgba(0,0,0,0) + font_color = 0xff$foreground + fade_on_empty = true + fade_timeout = 1000 + font_family = Product Sans + placeholder_text = + hide_input = false + rounding = 4 + check_color = 0xff$tertiary + fail_color = 0xff$error + capslock_color = 0xff$secondary + fail_text = $FAIL ($ATTEMPTS) + fail_transition = 200 + capslock_color = -1 + numlock_color = -1 + bothlock_color = -1 + invert_numlock = false + swap_font_color = false + position = 0, 150 + halign = center + valign = bottom + } +# + + +# Time + # (hours) + label { + monitor = + text = cmd[update:1000] echo -e "$(date +"%H")" + color = 0xff$foreground + shadow_pass = 2 + shadow_size = 3 + shadow_color = rgb(0,0,0) + shadow_boost = 1.2 + font_size = 150 + font_family = Product Sans Light + position = 0, 90 + halign = center + valign = center + } + # (minutes) + label { + monitor = + text = cmd[update:1000] echo -e "$(date +"%M")" + color = 0xff$foreground + font_size = 150 + font_family = Product Sans Light + position = 0, -90 + halign = center + valign = center + } +# + +# Date + # (label) + label { + monitor = + text = cmd[update:1000] echo -e "$(date +"%A, %B %d")" + color = 0xff$foreground + font_size = 15 + font_family = Product Sans Medium + position = 100, -75 + shadow_passes = 5 + shadow_size = 10 + halign = left + valign = top + } + # (icon) + label { + monitor = + text = calendar_today + color = 0xff$foreground + font_size = 15 + font_family = Material Symbols Outlined + position = 75, -75 + shadow_passes = 5 + shadow_size = 10 + halign = left + valign = top + } +# + +# Input layout + # (label) + label { + monitor = + text = $LAYOUT + color = 0xff$foreground + font_size = 15 + font_family = Product Sans Medium + position = 100, -110 + shadow_passes = 5 + shadow_size = 10 + halign = left + valign = top + } + # (icon) + label { + monitor = + text = keyboard + color = 0xff$foreground + font_size = 15 + font_family = Material Symbols Outlined + position = 75, -112 + shadow_passes = 5 + shadow_size = 10 + halign = left + valign = top + } +# + + diff --git a/config/matugen/templates/hyprland-colors.conf b/config/matugen/templates/hyprland-colors.conf new file mode 100644 index 0000000..a375c24 --- /dev/null +++ b/config/matugen/templates/hyprland-colors.conf @@ -0,0 +1,11 @@ +$wallpaper = {{image}} +$background = {{colors.background.default.hex_stripped}} +$foreground = {{colors.on_background.default.hex_stripped}} + +$primary = {{colors.primary.default.hex_stripped}} +$secondary = {{colors.secondary.default.hex_stripped}} +$tertiary = {{colors.tertiary.default.hex_stripped}} +$surface = {{colors.surface.default.hex_stripped}} +$surface_bright = {{colors.surface_bright.default.hex_stripped}} +$outline = {{colors.outline.default.hex_stripped}} +$error = {{colors.error.default.hex_stripped | set_lightness: -20.0}} diff --git a/config/matugen/templates/modus.css b/config/matugen/templates/modus.css new file mode 100644 index 0000000..db192d7 --- /dev/null +++ b/config/matugen/templates/modus.css @@ -0,0 +1,44 @@ +:vars { + --foreground: {{colors.on_background.default.hex}}; + --background: {{colors.background.default.hex}}; + --cursor: {{colors.on_background.default.hex}}; + --primary: {{colors.primary.default.hex}}; + --primary-container: {{colors.primary_container.default.hex}}; + --on-primary: {{colors.on_primary.default.hex}}; + --on-primary-container: {{colors.on_primary_container.default.hex}}; + --secondary: {{colors.secondary.default.hex}}; + --on-secondary: {{colors.on_secondary.default.hex}}; + --secondary-container: {{colors.secondary_container.default.hex}}; + --tertiary: {{colors.tertiary.default.hex}}; + --tertiary-container: {{colors.tertiary_container.default.hex}}; + --on-tertiary: {{colors.on_tertiary.default.hex}}; + --on-tertiary-container: {{colors.on_tertiary_container.default.hex}}; + --surface: {{colors.surface.default.hex}}; + --surface-container: {{colors.surface_container.default.hex}}; + --surface-bright: {{colors.surface_bright.default.hex}}; + --surface-variant: {{colors.surface_variant.default.hex}}; + --surface-container-low: {{colors.surface_container_low.default.hex}}; + --on-surface: {{colors.on_surface.default.hex}}; + --error: {{colors.error.default.hex}}; + --error-dim: {{colors.error.default.hex | set_lightness: -10.0}}; + --on-error: {{colors.on_error.default.hex}}; + --error-container: {{colors.error_container.default.hex}}; + --on-error-container: {{colors.on_error_container.default.hex}}; + --outline: {{colors.outline.default.hex}}; + --outline-variant: {{colors.outline_variant.default.hex}}; + --shadow: {{colors.shadow.default.hex}}; + --red: {{colors.red.default.hex}}; + --red-dim: {{colors.red.default.hex | set_lightness: -10.0}}; + --green: {{colors.green.default.hex}}; + --green-dim: {{colors.green.default.hex | set_lightness: -10.0}}; + --yellow: {{colors.yellow.default.hex}}; + --yellow-dim: {{colors.yellow.default.hex | set_lightness: -10.0}}; + --blue: {{colors.blue.default.hex}}; + --blue-dim: {{colors.blue.default.hex | set_lightness: -10.0}}; + --magenta: {{colors.magenta.default.hex}}; + --magenta-dim: {{colors.magenta.default.hex | set_lightness: -10.0}}; + --cyan: {{colors.cyan.default.hex}}; + --cyan-dim: {{colors.cyan.default.hex | set_lightness: -10.0}}; + --white: {{colors.white.default.hex}}; + +} diff --git a/config/matugen/templates/modus.scss b/config/matugen/templates/modus.scss new file mode 100644 index 0000000..aba4239 --- /dev/null +++ b/config/matugen/templates/modus.scss @@ -0,0 +1,29 @@ +@use "sass:color"; +<* for name, value in colors *> +${{name}}: {{value.default.hex}}; +<* endfor *> + +// Custom Color +$red: {{colors.red.default.hex}}; +$red-dim: {{colors.red.default.hex | set_lightness: -10.0}}; +$green: {{colors.green.default.hex}}; +$green-dim: {{colors.green.default.hex | set_lightness: -10.0}}; +$yellow: {{colors.yellow.default.hex}}; +$yellow-dim: {{colors.yellow.default.hex | set_lightness: -10.0}}; +$blue: {{colors.blue.default.hex}}; +$blue-dim: {{colors.blue.default.hex | set_lightness: -10.0}}; +$magenta: {{colors.magenta.default.hex}}; +$magenta-dim: {{colors.magenta.default.hex | set_lightness: -10.0}}; +$cyan: {{colors.cyan.default.hex}}; +$cyan-dim: {{colors.cyan.default.hex | set_lightness: -10.0}}; +$white: {{colors.white.default.hex}}; + +$theme: 'dark'; +$surface_transparent: color.scale($surface, $alpha: -20%); +$inverse_surface_transparent: color.scale($inverse_surface, $alpha: -92%); +$inverse_surface_transparent_variant: color.scale( + $inverse_surface, + $alpha: -82% +); +$inverse_surface_transparent_overlay: linear-gradient(0deg, $inverse_surface_transparent, $inverse_surface_transparent); +$inverse_surface_transparent_variant_overlay: linear-gradient(0deg, $inverse_surface_transparent_variant, $inverse_surface_transparent_variant); diff --git a/config/scripts/capture.sh b/config/scripts/capture.sh new file mode 100755 index 0000000..465e038 --- /dev/null +++ b/config/scripts/capture.sh @@ -0,0 +1,201 @@ + +#!/bin/bash + +# Print usage information +print_usage() { + cat <<"EOF" +Usage: screen-tools.sh [mode] [option] +Modes: + screenshot [option] Take a screenshot + Options: + p Print all screens + s Snip current screen + sf Snip current screen (frozen) + m Print focused monitor + [mockup] Optional: Add mockup effect to screenshot + + record Start/Stop screen recording + + ocr Perform OCR on selected area +EOF +} + +# OCR functionality using hyprshot +do_ocr() { + sleep 0.25 + + # Temporary file to store the snipped image + temp_ocr_image="$(mktemp --suffix=.png)" + hyprshot -s -z -m region -o "$(dirname "$temp_ocr_image")" -f "$(basename "$temp_ocr_image")" + + if [ ! -f "$temp_ocr_image" ]; then + notify-send -a "Modus" "OCR Failed" "No image captured" + exit 1 + fi + + # Perform OCR with tesseract + ocr_text=$(tesseract "$temp_ocr_image" - -l eng 2>/dev/null) + + rm -f "$temp_ocr_image" # Clean up temp file + + # Check if OCR was successful + if [[ -n "$ocr_text" ]]; then + echo -n "$ocr_text" | wl-copy + notify-send -a "Modus" "OCR Success" "Text copied to clipboard" + else + notify-send -a "Modus" "OCR Failed" "No text recognized or operation failed" + fi +} + +# Screen recording functionality +do_screenrecord() { + if [ -z "$XDG_VIDEOS_DIR" ]; then + XDG_VIDEOS_DIR="$HOME/Videos" + fi + local save_dir="${XDG_VIDEOS_DIR:-$HOME/Videos}/Recordings" + mkdir -p "$save_dir" + + if pgrep -f "gpu-screen-recorder" >/dev/null; then + pkill -SIGINT -f "gpu-screen-recorder" + sleep 1 + + local last_video=$(ls -t "$save_dir"/*.mp4 2>/dev/null | head -n 1) + local action=$(notify-send -a "Modus" "โฌœ Recording stopped" -A "view=View" -A "open=Open folder") + + if [ "$action" = "view" ] && [ -n "$last_video" ]; then + xdg-open "$last_video" + elif [ "$action" = "open" ]; then + xdg-open "$save_dir" + fi + exit 0 + fi + + local output_file="$save_dir/$(date +%Y-%m-%d-%H-%M-%S).mp4" + notify-send -a "Modus" "๐Ÿ”ด Recording started" + gpu-screen-recorder -w screen -q ultra -a default_output -ac opus -cr full -f 60 -o "$output_file" +} + +# Screenshot functionality +do_screenshot() { + sleep 0.25 + + if [ -z "$XDG_PICTURES_DIR" ]; then + XDG_PICTURES_DIR="$HOME/Pictures" + fi + + local save_dir="${3:-$XDG_PICTURES_DIR/Screenshots}" + local save_file=$(date +'%y%m%d_%Hh%Mm%Ss_screenshot.png') + local full_path="$save_dir/$save_file" + mkdir -p "$save_dir" + + local mockup_mode="$2" + + case $1 in + p) hyprshot -s -m output -o "$save_dir" -f "$save_file" ;; + s) hyprshot -s -m region -o "$save_dir" -f "$save_file" ;; + sf) hyprshot -s -z -m region -o "$save_dir" -f "$save_file" ;; + m) hyprshot -s -m output -m active -o "$save_dir" -f "$save_file" ;; + *) + echo "Invalid screenshot mode" + print_usage + exit 1 + ;; + esac + + if [ -f "$full_path" ]; then + if [ "$mockup_mode" != "mockup" ]; then + if command -v wl-copy >/dev/null 2>&1; then + wl-copy <"$full_path" + elif command -v xclip >/dev/null 2>&1; then + xclip -selection clipboard -t image/png <"$full_path" + fi + fi + + # Process as mockup if requested + if [ "$mockup_mode" = "mockup" ]; then + temp_file="${full_path%.png}_temp.png" + cropped_file="${full_path%.png}_cropped.png" + mockup_file="${full_path%.png}_mockup.png" + mockup_success=true + + # Crop top pixel + convert "$full_path" -crop +0+1 +repage "$cropped_file" || mockup_success=false + + # Rounded corners and transparency + if [ "$mockup_success" = true ]; then + convert "$cropped_file" \ + \( +clone -alpha extract -draw 'fill black polygon 0,0 0,20 20,0 fill white circle 20,20 20,0' \ + \( +clone -flip \) -compose Multiply -composite \ + \( +clone -flop \) -compose Multiply -composite \ + \) -alpha off -compose CopyOpacity -composite "$temp_file" || mockup_success=false + fi + + # Add shadow + if [ "$mockup_success" = true ]; then + convert "$temp_file" \ + \( +clone -background black -shadow 60x20+0+10 -alpha set -channel A -evaluate multiply 1 +channel \) \ + +swap -background none -layers merge +repage "$mockup_file" || mockup_success=false + fi + + # Finalize + if [ "$mockup_success" = true ] && [ -f "$mockup_file" ]; then + rm "$temp_file" "$cropped_file" + mv "$mockup_file" "$full_path" + if command -v wl-copy >/dev/null 2>&1; then + wl-copy <"$full_path" + elif command -v xclip >/dev/null 2>&1; then + xclip -selection clipboard -t image/png <"$full_path" + fi + else + echo "Warning: Mockup processing failed for $full_path." >&2 + rm -f "$temp_file" "$cropped_file" "$mockup_file" + if [ "$mockup_mode" = "mockup" ]; then + if command -v wl-copy >/dev/null 2>&1; then + wl-copy <"$full_path" + elif command -v xclip >/dev/null 2>&1; then + xclip -selection clipboard -t image/png <"$full_path" + fi + fi + fi + fi + + local action=$(notify-send -a "Modus" -i "$full_path" "Screenshot saved" "in $full_path" \ + -A "view=View" -A "edit=Edit" -A "open=Open Folder") + + case "$action" in + view) xdg-open "$full_path" ;; + edit) swappy -f "$full_path" ;; + open) xdg-open "$save_dir" ;; + esac + else + notify-send -a "Modus" "Screenshot Aborted" + fi +} + +# Handle command line arguments +if [ $# -eq 0 ]; then + print_usage + exit 1 +fi + +case "$1" in +screenshot) + if [ $# -lt 2 ]; then + echo "Error: Screenshot mode requires an option" + print_usage + exit 1 + fi + do_screenshot "$2" "$3" + ;; +record) + do_screenrecord + ;; +ocr) + do_ocr + ;; +*) + echo "Error: Invalid mode '$1'" + print_usage + exit 1 + ;; +esac diff --git a/config/scripts/gamemode.sh b/config/scripts/gamemode.sh new file mode 100755 index 0000000..3652ccd --- /dev/null +++ b/config/scripts/gamemode.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env sh + +# Check if animations are disabled (game mode is active) +check_gamemode() { + HYPRGAMEMODE=$(hyprctl getoption animations:enabled | awk 'NR==1{print $2}') + if [ "$HYPRGAMEMODE" = 0 ]; then + echo "t" + return 0 + else + echo "f" + return 1 + fi +} + +# Toggle game mode state +toggle_gamemode() { + HYPRGAMEMODE=$(hyprctl getoption animations:enabled | awk 'NR==1{print $2}') + if [ "$HYPRGAMEMODE" = 1 ]; then + hyprctl --batch "\ + keyword animations:enabled 0;\ + keyword decoration:shadow:enabled 0;\ + keyword decoration:blur:enabled 0;\ + keyword general:gaps_in 0;\ + keyword general:gaps_out 0;\ + keyword general:border_size 1;\ + keyword decoration:rounding 0" + exit + fi + hyprctl reload +} + +# Main script logic +case "$1" in +check) + check_gamemode + ;; +*) + toggle_gamemode + ;; +esac diff --git a/config/scripts/hyprpicker.sh b/config/scripts/hyprpicker.sh new file mode 100755 index 0000000..703c7df --- /dev/null +++ b/config/scripts/hyprpicker.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +pick_rgb() { + + # Execute hyprpicker with RGB format and save the output to a variable + hyprpicker -a -n -f rgb && sleep 0.1 + + # Create a temporal 64x64 PNG file with the color in /tmp using convert + magick -size 64x64 xc:"rgb($(wl-paste))" /tmp/color.png + + # Send a notification using the file as an icon + notify-send "RGB color picked" "rgb($(wl-paste))" -i /tmp/color.png -a "Hyprpicker" + + # Remove the temporal file + rm /tmp/color.png + + # Exit + exit 0 + +} + +pick_hex() { + + # Execute hyprpicker and save the output to a variable + hyprpicker -a -n -f hex && sleep 0.1 + + # Create a temporal 64x64 PNG file with the color in /tmp using convert + magick -size 64x64 xc:"$(wl-paste)" /tmp/color.png + + # Send a notification using the file as an icon + notify-send "HEX color picked" "$(wl-paste)" -i /tmp/color.png -a "Hyprpicker" + + # Remove the temporal file + rm /tmp/color.png + + # Exit + exit 0 + +} + +pick_hsv() { + + # Copy the color to the clipboard + echo -n "$(hyprpicker -n -f hsv)" | wl-copy -n + + # Create a temporal 64x64 PNG file with the color in /tmp using convert + magick -size 64x64 xc:"hsv($(wl-paste))" /tmp/color.png + + # Send a notification using the file as an icon + notify-send "HSV color picked" "hsv($(wl-paste))" -i /tmp/color.png -a "Hyprpicker" + + # Remove the temporal file + rm /tmp/color.png + + # Exit + exit 0 + +} + +case "$1" in +-rgb) + pick_rgb + ;; +-hsv) + pick_hsv + ;; +-hex) + pick_hex + ;; + +*) + echo "Usage: $0 [-rgb|-hex|-hsv]" + exit 1 + ;; +esac diff --git a/config/scripts/systemupdates.sh b/config/scripts/systemupdates.sh new file mode 100755 index 0000000..a2677ff --- /dev/null +++ b/config/scripts/systemupdates.sh @@ -0,0 +1,182 @@ +#!/bin/bash + +# Word of caution: Changing this may break the update module, be careful! + +# Function to check updates for Arch-based distros +check_arch_updates() { + official_updates=0 + aur_updates=0 + flatpak_updates=0 + tooltip="" + + # Get the number of official updates + official_updates=$(checkupdates 2>/dev/null | wc -l) + + # Determine the AUR helper + if command -v paru &>/dev/null; then + aur_helper="paru" + else + aur_helper="yay" + fi + + # Get the number of AUR updates + aur_updates=$($aur_helper -Qum 2>/dev/null | wc -l) + + # Check for Flatpak updates + if command -v flatpak &>/dev/null; then + flatpak_updates=$(flatpak remote-ls --updates | wc -l) + fi + + # Calculate total updates + total_updates=$((official_updates + aur_updates + flatpak_updates)) + + # Build the tooltip + tooltip="๓ฐฃ‡ Official: $official_updates\n๓ฐฎฏ AUR: $aur_updates\n๏’‡ Flatpak: $flatpak_updates" + + # Output JSON + echo "{\"total\":\"$total_updates\", \"tooltip\":\"$tooltip\"}" +} + +# Function to check updates for Ubuntu-based distros +check_ubuntu_updates() { + official_updates=0 + flatpak_updates=0 + tooltip="" + + # Get the number of official updates + official_updates=$(apt-get -s -o Debug::NoLocking=true upgrade | grep -c ^Inst) + + # Check for Flatpak updates + if command -v flatpak &>/dev/null; then + flatpak_updates=$(flatpak remote-ls --updates | wc -l) + fi + + # Calculate total updates + total_updates=$((official_updates + flatpak_updates)) + + # Build the tooltip + tooltip="๓ฐ•ˆ Official: $official_updates\n๏’‡ Flatpak: $flatpak_updates" + + # Output JSON + echo "{\"total\":\"$total_updates\", \"tooltip\":\"$tooltip\"}" +} + +# Function to check updates for Fedora-based distros +check_fedora_updates() { + official_updates=0 + flatpak_updates=0 + tooltip="" + + # Get the number of official updates + official_updates=$(dnf list updates -q | tail -n +2 | wc -l) + + # Check for Flatpak updates + if command -v flatpak &>/dev/null; then + flatpak_updates=$(flatpak remote-ls --updates | wc -l) + fi + + # Calculate total updates + total_updates=$((official_updates + flatpak_updates)) + + # Build the tooltip + tooltip="๓ฐฃ› Official: $official_updates\n๏’‡ Flatpak: $flatpak_updates" + + # Output JSON + echo "{\"total\":\"$total_updates\", \"tooltip\":\"$tooltip\"}" +} + +# Function to check updates for openSUSE-based distros +check_opensuse_updates() { + official_updates=0 + flatpak_updates=0 + tooltip="" + + # Get the number of official updates (skip header lines) + official_updates=$(zypper lu | tail -n +3 | wc -l) + + # Check for Flatpak updates + if command -v flatpak &>/dev/null; then + flatpak_updates=$(flatpak remote-ls --updates | wc -l) + fi + + # Calculate total updates + total_updates=$((official_updates + flatpak_updates)) + + # Build the tooltip + tooltip="๎ฝญ Official: $official_updates\n๏’‡ Flatpak: $flatpak_updates" + + # Output JSON + echo "{\"total\":\"$total_updates\", \"tooltip\":\"$tooltip\"}" +} + +# Function to update Arch-based distros +update_arch() { + kitty --title "System Update" sh -c " + fastfetch + yay -Syu + read -n 1 -p 'Press any key to continue...' + " +} + +# Function to update Ubuntu-based distros +update_ubuntu() { + kitty --title "System Update" sh -c " + neofetch + sudo apt update && sudo apt upgrade -y + read -n 1 -p 'Press any key to continue...' + " +} + +# Function to update Fedora-based distros +update_fedora() { + kitty --title "System Update" sh -c " + neofetch + sudo dnf upgrade -y + read -n 1 -p 'Press any key to continue...' + " +} + +# Function to update openSUSE-based distros +update_opensuse() { + kitty --title "System Update" sh -c " + neofetch + sudo zypper up -y + read -n 1 -p 'Press any key to continue...' + " +} + +# Main case handling for different distributions +case "$1" in +-arch) + if [ -z "$2" ]; then + check_arch_updates + else + update_arch + fi + ;; +-ubuntu) + if [ -z "$2" ]; then + check_ubuntu_updates + else + update_ubuntu + fi + ;; +-fedora) + if [ -z "$2" ]; then + check_fedora_updates + else + update_fedora + fi + ;; +-suse) + if [ -z "$2" ]; then + check_opensuse_updates + else + update_opensuse + fi + ;; +*) + echo "Usage: $0 [-arch|-ubuntu|-fedora|-suse] [up (optional)]" + exit 1 + ;; +esac diff --git a/main.py b/main.py new file mode 100644 index 0000000..136fe16 --- /dev/null +++ b/main.py @@ -0,0 +1,54 @@ +from loguru import logger +import setproctitle +from fabric import Application +from fabric.utils import get_relative_path, exec_shell_command_async, monitor_file + +from config.data import APP_NAME, CACHE_DIR, CONFIG_FILE, DOCK_ICON_SIZE, APP_NAME_CAP +from modules.bar.bar import Bar +from modules.dock import Dock +from modules.corners import Corners + + +# Disable unnecessary logging immediately +for log in [ + "fabric.hyprland.widgets", + "fabric.audio.service", + "fabric.bluetooth.service", + "fabric.widgets.wayland", + "fabric.utils.helpers", +]: + logger.disable(log) + +if __name__ == "__main__": + setproctitle.setproctitle(APP_NAME) + + # Load configuration + from config.data import load_config + config = load_config() + + bar = Bar() + dock = Dock() + corners = Corners() + + app = Application(f"{APP_NAME}", bar, dock) + + css_file = monitor_file(get_relative_path("styles")) + _ = css_file.connect("changed", lambda *_: set_css()) + + color_css_file = monitor_file(get_relative_path("./styles/colors.css")) + _ = color_css_file.connect("changed", lambda *_: set_css()) + + + def set_css(): + app.set_stylesheet_from_file( + get_relative_path("styles/main.css"), + exposed_functions={ + "dock_nmargin": lambda: f"margin-bottom: -{32 + DOCK_ICON_SIZE}px;", + "dock_sep": lambda: f"margin: 8px 0;", + }, + ) + app.set_css = set_css + + app.set_css() + + app.run() \ No newline at end of file diff --git a/modules/bar/bar.py b/modules/bar/bar.py new file mode 100644 index 0000000..c44ec6b --- /dev/null +++ b/modules/bar/bar.py @@ -0,0 +1,128 @@ +from fabric.widgets.box import Box +from fabric.widgets.eventbox import EventBox +from fabric.widgets.datetime import DateTime +from fabric.widgets.button import Button +from fabric.widgets.centerbox import CenterBox +from fabric.system_tray.widgets import SystemTray +from fabric.widgets.wayland import WaylandWindow as Window +from fabric.hyprland.widgets import ActiveWindow +from fabric.utils import truncate, FormattedString + +from modules.bar.components.workspaces import workspace +from modules.bar.components.language import LanguageWidget +from modules.bar.components.auto_hide import AutoHideBarController +from modules.corners import MyCorner +from modules.bar.components.power_menu import Power +from modules.bar.components.system_indicators import SystemIndicators +from modules.bar.components.metrics import Metrics + + +class Bar(Window): + """Main bar widget for the desktop environment.""" + + def __init__(self): + super().__init__( + layer="top", + anchor="top", + visible=True, + ) + + self.active_window = ActiveWindow( + name="active-window", + h_expand=True, + h_align="fill", + formatter=FormattedString( + f"{{'Desktop' if not win_class or win_class == 'unknown' else win_class}}", + truncate=truncate, + ), + ) + self.workspaces = Button( + name="workspaces", + child=workspace, + ) + + self.language = LanguageWidget() + self.date_time = DateTime(name="date-time", formatters=["%-I:%M:%p ๓ฐงž %a %d %b"]) + self.tray = SystemTray(name="tray", spacing=4, icon_size=16) + self.power_menu = Power() + self.system_indicators = SystemIndicators() + self.metrics = Metrics() + + # Main bar content + + self.bar = CenterBox( + name="bar", + start_children=Box(spacing=4, orientation="h", children=self.workspaces), + center_children=Box( + spacing=4, orientation="h", children=self.active_window + ), + end_children=Box( + spacing=4, + orientation="h", + children=[ + self.date_time, + self.metrics, + self.system_indicators, + self.tray, + self.power_menu, + ], + ), + ) + + # Event handling and corners + self.eventbox = EventBox() + self.eventbox.add(self.bar) + + self.corner_left = Box( + name="bar-corner-left", + orientation="v", + h_align="start", + children=[ + MyCorner("top-right"), + Box(), + ], + ) + self.corner_left.set_margin_start(56) + + self.corner_right = Box( + name="bar-corner-right", + orientation="v", + h_align="end", + children=[ + MyCorner("top-left"), + Box(), + ], + ) + self.corner_right.set_margin_end(56) + self.main_box = Box( + name="bar-container", + orientation="h", + h_expand=True, + children=[ + self.corner_left, + self.eventbox, + self.corner_right, + ], + ) + + # Add hover activator + self.hover_activator = EventBox(name="hover-activator", v_align="start") + self.hover_activator.set_size_request(-1, 1) + + # Root container + self.root_box = Box( + orientation="v", children=[self.main_box, self.hover_activator] + ) + self.add(self.root_box) + + # Setup auto-hide controller + self.auto_hide = AutoHideBarController(self) + + # Connect event handlers for hover + self.eventbox.connect("enter-notify-event", self.auto_hide.on_bar_enter) + self.eventbox.connect("leave-notify-event", self.auto_hide.on_bar_leave) + self.hover_activator.connect( + "enter-notify-event", self.auto_hide.on_hover_enter + ) + + self.show_all() diff --git a/modules/bar/components/__init__.py b/modules/bar/components/__init__.py new file mode 100644 index 0000000..cfde6ca --- /dev/null +++ b/modules/bar/components/__init__.py @@ -0,0 +1 @@ +# Bar components package \ No newline at end of file diff --git a/modules/bar/components/auto_hide.py b/modules/bar/components/auto_hide.py new file mode 100644 index 0000000..22a5ad5 --- /dev/null +++ b/modules/bar/components/auto_hide.py @@ -0,0 +1,202 @@ +import json +from gi.repository import GLib, Gdk +from fabric.hyprland.widgets import get_hyprland_connection +from utils.occlusion import check_occlusion + + +class AutoHideBarController: + """Controller for bar auto-hide behavior.""" + + # Constants for configuration + OCCLUSION_CHECK_INTERVAL = 250 # ms + HIDE_DELAY = 300 # ms + + def __init__(self, bar): + self.bar = bar + self.is_hidden = False + self.hide_id = None + self.is_hovered = False + self.conn = get_hyprland_connection() + self.last_occlusion_state = False + + self._setup_event_handlers() + self._start_occlusion_checking() + + def _setup_event_handlers(self): + """Initialize event handlers for window management""" + # Initial state check + if self.conn.ready: + self.check_hide() + else: + self.conn.connect("event::ready", lambda *_: self.check_hide()) + + # Monitor window events + window_events = ("activewindow", "openwindow", "closewindow", "changefloatingmode") + for event in window_events: + self.conn.connect(f"event::{event}", lambda *_: self.check_hide()) + self.conn.connect("event::workspace", lambda *_: GLib.timeout_add(50, self.check_hide)) + + def _start_occlusion_checking(self): + """Start periodic occlusion check""" + GLib.timeout_add(self.OCCLUSION_CHECK_INTERVAL, self.check_occlusion_state) + + def _get_bar_height(self): + """Get the height of the bar with fallback""" + try: + height = self.bar.get_allocated_height() + return height if height > 0 else 30 + except Exception: + return 30 # Default fallback + + def _get_occlusion_region(self): + """Get the region to check for occlusion""" + return ("top", self._get_bar_height()) + + def check_occlusion_state(self): + """Periodic occlusion check""" + # Skip occlusion check if hovered + if self.is_hovered: + self.bar.main_box.remove_style_class("occluded") + return True + + # Check occlusion using the top region + is_occluded = check_occlusion(self._get_occlusion_region()) + + # Only apply changes if state has changed to avoid unnecessary CSS operations + if is_occluded != self.last_occlusion_state: + self.last_occlusion_state = is_occluded + if is_occluded: + self.bar.main_box.add_style_class("occluded") + else: + self.bar.main_box.remove_style_class("occluded") + if not self.is_hovered and self.is_hidden: + # Debounce showing the bar to prevent flickering + GLib.timeout_add(100, lambda: self.toggle_bar(not self._should_stay_hidden())) + + return True + + def _should_stay_hidden(self): + """Determine if the bar should stay hidden based on window state""" + clients = self.get_clients() + current_ws = self.get_workspace() + ws_clients = [w for w in clients if w["workspace"]["id"] == current_ws] + + # If we have normal windows and are not being hovered, stay hidden + return self._has_normal_windows(ws_clients) and not self.is_hovered + + def on_bar_enter(self, widget, event): + """Handle hover over bar content.""" + self.is_hovered = True + self.bar.main_box.remove_style_class("occluded") + + # Cancel any pending hide operations + self._cancel_hide_timer() + self.toggle_bar(show=True) + return True # Stop event propagation + + def on_bar_leave(self, widget, event): + """Handle leave from bar content.""" + # Only trigger if mouse actually left the entire bar area + if event.detail == Gdk.NotifyType.INFERIOR: + return False # Ignore child-to-child mouse movements + + self.is_hovered = False + + # Schedule hide if needed + if self._should_stay_hidden() or check_occlusion(self._get_occlusion_region()): + self.delay_hide() + + # Update occlusion state + if check_occlusion(self._get_occlusion_region()): + self.last_occlusion_state = True + self.bar.main_box.add_style_class("occluded") + + return True # Stop event propagation + + def on_hover_enter(self, *args): + """Handle hover over top activation area.""" + self.bar.main_box.remove_style_class("occluded") + self.toggle_bar(show=True) + return False + + def _cancel_hide_timer(self): + """Cancel any pending hide timer""" + if self.hide_id: + GLib.source_remove(self.hide_id) + self.hide_id = None + + def toggle_bar(self, show): + """Show or hide the bar immediately.""" + if show: + if self.is_hidden: + self.is_hidden = False + self.bar.main_box.remove_style_class("hide-bar") + self.bar.main_box.add_style_class("show-bar") + self._cancel_hide_timer() + else: + if not self.is_hidden: + self.is_hidden = True + self.bar.main_box.remove_style_class("show-bar") + self.bar.main_box.add_style_class("hide-bar") + + def delay_hide(self): + """Schedule hiding after short delay.""" + self._cancel_hide_timer() + self.hide_id = GLib.timeout_add(self.HIDE_DELAY, self.hide_bar) + + def hide_bar(self): + """Finalize hiding procedure.""" + if not self.is_hovered: + self.toggle_bar(show=False) + self.hide_id = None + return False + + def get_clients(self): + """Get current client list.""" + try: + return json.loads(self.conn.send_command("j/clients").reply.decode()) + except (json.JSONDecodeError, AttributeError): + return [] + + def get_workspace(self): + """Get current workspace ID.""" + try: + return json.loads( + self.conn.send_command("j/activeworkspace").reply.decode() + ).get("id", 0) + except (json.JSONDecodeError, AttributeError): + return 0 + + def _has_normal_windows(self, clients): + """Check if any non-floating, non-fullscreen windows exist""" + return any(not w.get("floating") and not w.get("fullscreen") for w in clients) + + def check_hide(self, *args): + """Determine if bar should auto-hide based on window state.""" + # Get window data + clients = self.get_clients() + current_ws = self.get_workspace() + ws_clients = [w for w in clients if w["workspace"]["id"] == current_ws] + + # Check for occlusion + is_occluded = check_occlusion(self._get_occlusion_region()) + self.last_occlusion_state = is_occluded + + # Determine visibility state + if not ws_clients: + # No windows in current workspace, show the bar + self.bar.main_box.remove_style_class("occluded") + self.toggle_bar(show=True) + elif self._has_normal_windows(ws_clients): + # Normal windows exist, handle occlusion and hide if not hovered + if is_occluded: + self.bar.main_box.add_style_class("occluded") + + if not self.is_hovered: + self.toggle_bar(show=False) + else: + # Only floating/fullscreen windows, show the bar + self.bar.main_box.remove_style_class("occluded") + self.toggle_bar(show=True) + + return False \ No newline at end of file diff --git a/modules/bar/components/language.py b/modules/bar/components/language.py new file mode 100644 index 0000000..858c0e2 --- /dev/null +++ b/modules/bar/components/language.py @@ -0,0 +1,24 @@ +from fabric.widgets.button import Button +from fabric.widgets.label import Label +from fabric.hyprland.widgets import Language, HyprlandEvent, get_hyprland_connection + + +class LanguageWidget(Button): + """Widget that displays the current keyboard layout.""" + + def __init__(self, **kwargs): + self.lang_label = Label(name="lang-label") + super().__init__( + name="language", h_align="center", v_align="center", + child=self.lang_label, **kwargs + ) + + self.conn = get_hyprland_connection() + self.update_language() + self.conn.connect("event::activelayout", self.update_language) + + def update_language(self, _=None, event: HyprlandEvent = None): + """Update the language indicator based on Hyprland events.""" + lang = event.data[1] if event else Language().get_label() + self.set_tooltip_text(lang) + self.lang_label.set_label(lang[:2].lower()) \ No newline at end of file diff --git a/modules/bar/components/metrics.py b/modules/bar/components/metrics.py new file mode 100644 index 0000000..b8150d6 --- /dev/null +++ b/modules/bar/components/metrics.py @@ -0,0 +1,327 @@ +import subprocess +import json +import psutil +from gi.repository import GLib, Gdk + +from fabric.widgets.label import Label +from fabric.widgets.box import Box +from fabric.widgets.circularprogressbar import CircularProgressBar +from fabric.widgets.revealer import Revealer +from fabric.core.fabricator import Fabricator +from fabric.widgets.button import Button +import utils.icons as icons +import config.data as data + + +class MetricsProvider: + def __init__(self): + self.cpu = 0.0 + self.mem = 0.0 + self.swap = 0.0 + self.bat_percent = 0.0 + self.bat_charging = None + + GLib.timeout_add_seconds(1, self._update) + + def _update(self): + # Get non-blocking usage percentages (interval=0) + # The first call may return 0, but subsequent calls will provide consistent values. + self.cpu = psutil.cpu_percent(interval=0) + mem = psutil.virtual_memory() + self.mem = mem.percent + swap = psutil.swap_memory() + self.swap = swap.percent + + battery = psutil.sensors_battery() + if battery is None: + self.bat_percent = 0.0 + self.bat_charging = None + else: + self.bat_percent = battery.percent + self.bat_charging = battery.power_plugged + return True + + def get_metrics(self): + return (self.cpu, self.mem, self.swap) + + def get_battery(self): + return (self.bat_percent, self.bat_charging) + + + +shared_provider = MetricsProvider() + + +class SingularMetric: + def __init__(self, id, name, icon): + self.is_vertical_layout = data.VERTICAL + self.name_markup = name + self.icon_markup = icon + + self.icon = Label(name="metrics-icon", markup=icon) + self.circle = CircularProgressBar( + name="metrics-circle", + value=0, + size=26, + line_width=2, + start_angle=150, + end_angle=390, + style_classes=id, + child=self.icon, + ) + + self.circle_button = Button( + name=f"metrics-{id}-button", + child=self.circle, + style="padding: 0; margin: 0; background: none;", + ) + + self.circle_button.add_events( + Gdk.EventMask.ENTER_NOTIFY_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK + ) + self.circle_button.connect("enter-notify-event", self.on_button_enter) + self.circle_button.connect("leave-notify-event", self.on_button_leave) + + self.circle_button.connect("clicked", self.on_circle_clicked) + + self.level = Label( + name="metrics-level", + style_classes=id, + label="0%", + style="margin: 4px 0px;" if self.is_vertical_layout else "margin: 0 4px;", + ) + self.revealer = Revealer( + name=f"metrics-{id}-revealer", + transition_duration=250, + transition_type="slide-up" if self.is_vertical_layout else "slide-left", + child=self.level, + child_revealed=False, + ) + + self.box = Box( + name=f"metrics-{id}-box", + orientation="v" if self.is_vertical_layout else "h", + spacing=0, + children=[self.circle_button, self.revealer], + ) + + # Connect events for cursor changes to the box as well + self.box.connect("enter-notify-event", self.on_button_enter) + self.box.connect("leave-notify-event", self.on_button_leave) + + # Set initial tooltip - moved after box is created + self.update_tooltip("0%") + + def update_tooltip(self, value_text): + tooltip = f"{self.icon_markup} {self.name_markup}: {value_text}" + # self.box.set_tooltip_markup(tooltip) + self.circle_button.set_tooltip_markup(tooltip) + self.circle.set_tooltip_markup(tooltip) + self.icon.set_tooltip_markup(tooltip) + + def markup(self): + """Get formatted text for tooltip display""" + return f"{self.icon_markup} {self.name_markup}: {self.level.get_label()}" + + def on_button_enter(self, widget, event): + window = widget.get_window() + if window: + window.set_cursor(Gdk.Cursor(Gdk.CursorType.HAND2)) + + def on_button_leave(self, widget, event): + window = widget.get_window() + if window: + window.set_cursor(None) + + def on_circle_clicked(self, button): + # Toggle the revealed state of the label + current_state = self.revealer.get_child_revealed() + self.revealer.set_reveal_child(not current_state) + + +class Metrics(Box): + def __init__(self, **kwargs): + # Determine if we should use vertical layout for components + self.is_vertical_layout = data.VERTICAL + + super().__init__( + name="metrics", + spacing=0, + orientation="h" if not self.is_vertical_layout else "v", + visible=True, + all_visible=True, + style="padding:4px 0px" if self.is_vertical_layout else "padding: 0px 4px;", + **kwargs, + ) + + self.batt_fabricator = Fabricator( + poll_from=lambda v: shared_provider.get_battery(), + on_changed=lambda f, v: self.update_battery, + interval=1000, + stream=False, + default_value=0, + ) + self.batt_fabricator.changed.connect(self.update_battery) + GLib.idle_add(self.update_battery, None, shared_provider.get_battery()) + + + self.cpu = ( + SingularMetric("cpu", "CPU", icons.cpu) + ) + self.ram = ( + SingularMetric("ram", "RAM", icons.memory) + ) + self.swap = ( + SingularMetric("swap", "SWAP", icons.swap) + ) + self.bat = ( + SingularMetric("bat", "BATTERY", icons.battery) + ) + + + # Add only enabled metrics + if self.ram: + self.add(self.ram.box) + self.add(Box(name="metrics-sep")) + if self.cpu: + self.add(self.cpu.box) + if self.swap: + self.add(Box(name="metrics-sep")) + self.add(self.swap.box) + if self.bat: + self.add(Box(name="metrics-sep")) + self.add(self.bat.box) + + # Connect events directly to the button + self.connect("enter-notify-event", self.on_mouse_enter) + self.connect("leave-notify-event", self.on_mouse_leave) + + GLib.timeout_add_seconds(1, self.update_metrics) + + self.hide_timer = None + self.hover_counter = 0 + + def _format_percentage(self, value: int) -> str: + return f"{value}%" + + def on_mouse_enter(self, widget, event): + window = widget.get_window() + if window: + window.set_cursor(Gdk.Cursor(Gdk.CursorType.HAND2)) + + if not data.VERTICAL: + self.hover_counter += 1 + if self.hide_timer is not None: + GLib.source_remove(self.hide_timer) + self.hide_timer = None + if self.cpu: + self.cpu.revealer.set_reveal_child(True) + if self.ram: + self.ram.revealer.set_reveal_child(True) + if self.swap: + self.swap.revealer.set_reveal_child(True) + if self.bat: + self.bat.revealer.set_reveal_child(True) + return False + + def on_mouse_leave(self, widget, event): + window = widget.get_window() + if window: + window.set_cursor(None) + + if not data.VERTICAL: + if self.hover_counter > 0: + self.hover_counter -= 1 + if self.hover_counter == 0: + if self.hide_timer is not None: + GLib.source_remove(self.hide_timer) + self.hide_timer = GLib.timeout_add(500, self.hide_revealer) + return False + + def hide_revealer(self): + if not data.VERTICAL: + if self.cpu: + self.cpu.revealer.set_reveal_child(False) + if self.ram: + self.ram.revealer.set_reveal_child(False) + self.hide_timer = None + return False + + def update_metrics(self): + cpu, mem, swap = shared_provider.get_metrics() + if self.cpu: + self.cpu.circle.set_value(cpu / 100.0) + value_text = self._format_percentage(int(cpu)) + self.cpu.level.set_label(value_text) + self.cpu.update_tooltip(value_text) + if self.ram: + self.ram.circle.set_value(mem / 100.0) + value_text = self._format_percentage(int(mem)) + self.ram.level.set_label(value_text) + self.ram.update_tooltip(value_text) + if self.swap: + self.swap.circle.set_value(swap / 100.0) + value_text = self._format_percentage(int(swap)) + self.swap.level.set_label(value_text) + self.swap.update_tooltip(value_text) + if self.bat: + bat_percent, _ = shared_provider.get_battery() + self.bat.circle.set_value(bat_percent / 100.0) + value_text = self._format_percentage(int(bat_percent)) + self.bat.level.set_label(value_text) + self.bat.update_tooltip(value_text) + + # Tooltip: only show enabled metrics + tooltip_metrics = [] + if self.swap: tooltip_metrics.append(self.swap) + if self.bat: tooltip_metrics.append(self.bat) + if self.ram: tooltip_metrics.append(self.ram) + if self.cpu: tooltip_metrics.append(self.cpu) + + return True + + def update_battery(self, sender, battery_data): + if self.bat is None: + return + + value, charging = battery_data + if value == 0: + if self.bat: + self.bat.box.set_visible(False) + else: + if self.bat: + self.bat.box.set_visible(True) + self.bat.circle.set_value(value / 100) + percentage = int(value) + self.bat.level.set_label(self._format_percentage(percentage)) + + # Apply alert styling if battery is low AND not charging + if percentage <= 15 and charging == False: + self.bat.icon.add_style_class("alert") + self.bat.circle.add_style_class("alert") + else: + self.bat.icon.remove_style_class("alert") + self.bat.circle.remove_style_class("alert") + + # Choose the icon based on charging state first, then battery level + if percentage == 100: + self.bat.icon.set_markup(icons.battery) + charging_status = f"{icons.bat_full} Fully Charged" + elif charging == True: + self.bat.icon.set_markup(icons.charging) + charging_status = f"{icons.bat_charging} Charging" + elif percentage <= 15 and charging == False: + self.bat.icon.set_markup(icons.alert) + charging_status = f"{icons.bat_low} Low Battery" + elif charging == False: + self.bat.icon.set_markup(icons.discharging) + charging_status = f"{icons.bat_discharging} Discharging" + else: + self.bat.icon.set_markup(icons.battery) + charging_status = "Battery" + + # Update individual tooltip for battery + self.bat.update_tooltip(f"{charging_status}: {self._format_percentage(percentage)}") + + # Update the combined tooltip + self.update_metrics() diff --git a/modules/bar/components/power_menu.py b/modules/bar/components/power_menu.py new file mode 100644 index 0000000..cb230a9 --- /dev/null +++ b/modules/bar/components/power_menu.py @@ -0,0 +1,180 @@ +from fabric.widgets.button import Button +from fabric.widgets.box import Box +from fabric.widgets.label import Label +from fabric.widgets.stack import Stack +from fabric.widgets.revealer import Revealer +from fabric.utils import exec_shell_command_async +from gi.repository import GLib, Gdk, Gtk +import utils.icons as icons + + +class Power(Button): + TRANSITION_TYPE = "slide-up-down" + TRANSITION_DURATION = 300 # milliseconds + LABEL_TRANSITION_TYPE = "slide-left" + LONG_PRESS_DURATION = 500 # milliseconds + SCROLL_COOLDOWN = 100 # milliseconds + + def __init__(self): + self.current_action = "shutdown" + self.is_locked = True + self.long_press_timeout = None + self.scroll_timeout = None + self.just_unlocked = False + + # Initialize stacks for icons and labels + for name in ["icon_stack", "label_stack"]: + setattr( + self, + name, + Stack( + transition_type=self.TRANSITION_TYPE, + transition_duration=self.TRANSITION_DURATION, + ), + ) + + # Define power actions + self.power_actions = { + "shutdown": { + "icon": icons.shutdown, + "label": "Shutdown", + "command": "systemctl poweroff" + }, + "reboot": { + "icon": icons.reboot, + "label": "Reboot", + "command": "systemctl reboot" + }, + "suspend": { + "icon": icons.suspend, + "label": "Suspend", + "command": "systemctl suspend" + }, + "logout": { + "icon": icons.logout, + "label": "Logout", + "command": "hyprctl dispatch exit" + }, + "lock": { + "icon": icons.lock, + "label": "Lock", + "command": "hyprlock --immediate" + } + } + + # Add all actions to stacks + for action, data in self.power_actions.items(): + self.icon_stack.add_named( + Label( + markup=data["icon"], + style_classes=["power-icon"], + ), + name=action, + ) + self.label_stack.add_named( + Label( + label=data["label"], + style_classes=["power-label"] + ), + name=action, + ) + + self.revealer = Revealer( + transition_type=self.LABEL_TRANSITION_TYPE, + transition_duration=self.TRANSITION_DURATION, + child=self.label_stack, + ) + + super().__init__( + name="power-menu", + on_enter_notify_event=lambda *args: self.revealer.set_reveal_child(True), + on_leave_notify_event=self.on_leave, + on_pressed=self.on_pressed, + on_released=self.on_released, + on_scroll_event=self.on_scroll, + child=Box( + children=[ + self.icon_stack, + self.revealer, + ] + ), + ) + + self.add_events( + Gdk.EventMask.SCROLL_MASK | + Gdk.EventMask.BUTTON_PRESS_MASK | + Gdk.EventMask.SMOOTH_SCROLL_MASK + ) + self.add_style_class("locked") + + # Add cursor change on hover + self.connect( + "state-flags-changed", + lambda btn, *_: ( + btn.set_cursor("pointer") + if btn.get_state_flags() & Gtk.StateFlags.PRELIGHT # type: ignore + else btn.set_cursor("default"), + ), + ) + + def on_pressed(self, widget, event=None): + if self.is_locked: + self.long_press_timeout = GLib.timeout_add( + self.LONG_PRESS_DURATION, + self.on_long_press + ) + + def on_released(self, widget, event=None): + timeout = self.long_press_timeout + self.long_press_timeout = None + if timeout: + GLib.source_remove(timeout) + + if not self.is_locked and not self.just_unlocked: + exec_shell_command_async(self.power_actions[self.current_action]["command"]) + self.is_locked = True + self.add_style_class("locked") + + self.just_unlocked = False + + def on_long_press(self): + if self.is_locked: + self.is_locked = False + self.just_unlocked = True + self.remove_style_class("locked") + self.long_press_timeout = None + return False + + def _change_action(self, direction): + if self.is_locked: + return + + actions = list(self.power_actions.keys()) + current_index = actions.index(self.current_action) + new_index = (current_index + direction) % len(actions) + + self.current_action = actions[new_index] + self.icon_stack.set_visible_child_name(self.current_action) + self.label_stack.set_visible_child_name(self.current_action) + + def on_scroll(self, widget, event): + if self.is_locked: + return True + + if event.direction == Gdk.ScrollDirection.SMOOTH: + if event.delta_y < -0.1: + self._change_action(-1) + elif event.delta_y > 0.1: + self._change_action(1) + elif event.direction == Gdk.ScrollDirection.UP: + self._change_action(-1) + elif event.direction == Gdk.ScrollDirection.DOWN: + self._change_action(1) + + self.scroll_timeout = GLib.timeout_add(self.SCROLL_COOLDOWN, lambda: None) + return True + def on_leave(self, widget, event=None): + self.revealer.set_reveal_child(False) + if not self.is_locked: + self.is_locked = True + self.add_style_class("locked") diff --git a/modules/bar/components/system_indicators.py b/modules/bar/components/system_indicators.py new file mode 100644 index 0000000..b9a357e --- /dev/null +++ b/modules/bar/components/system_indicators.py @@ -0,0 +1,214 @@ +import subprocess +from fabric import Fabricator +from fabric.widgets.label import Label +from fabric.widgets.box import Box +from fabric.bluetooth import BluetoothClient +from services import network_client, audio +import utils.icons as icons +from fabric.hyprland.widgets import Language, HyprlandEvent, get_hyprland_connection + + +class SystemIndicators(Box): + def __init__(self, **kwargs): + super().__init__( + orientation="h", spacing=2, name="system-indicator", **kwargs + ) + + self.bluetooth_icon = Label(name="system-indicator-icon") + self.wifi_icon = Label(name="system-indicator-icon") + self.volume_icon_button = Label(name="system-indicator-icon") + self.language_icon = Label(name="lang-label") + self.idle_label = Label(name="system-indicator-icon") + self.night_label = Label(name="system-indicator-icon") + self.power_label = Label(name="system-indicator-icon") + + + for widget in [ + self.language_icon, + self.bluetooth_icon, + self.wifi_icon, + self.volume_icon_button, + self.idle_label, + self.night_label, + self.power_label, + ]: + self.add(widget) + + self.audio_service = audio + self.bluetooth_client = BluetoothClient() + self.network_client = network_client + self.hyprland = get_hyprland_connection() + + # Connect signals + self.bluetooth_client.connect("changed", self.update_bluetooth_status) + self.audio_service.connect("changed", self.update_volume_status) + self.network_client.connect("device_ready", self.update_network_status) + self.hyprland.connect("event::activelayout", self.update_language) + + + if self.network_client.wifi_device: + self.network_client.wifi_device.connect( + "changed", self.update_network_status + ) + + if self.network_client.ethernet_device: + self.network_client.ethernet_device.connect( + "changed", self.update_network_status + ) + + Fabricator(interval=1000, poll_from=self.update_all_statuses) + + # Initial updates + self.update_bluetooth_status() + self.update_language() + self.update_idle_night_status() + + def update_all_statuses(self, *_args): + self.update_idle_night_status() + self.update_power_profile() + self.update_network_status() + + def update_language(self, _=None, event: HyprlandEvent = None): + """Update the language indicator based on Hyprland events.""" + lang = event.data[1] if event else Language().get_label() + self.language_icon.set_tooltip_text(lang) + self.language_icon.set_label(lang[:2].lower()) + + def update_idle_night_status(self, *_): + # Update idle status + has_idle = ( + subprocess.run(["pgrep", "-x", "wlinhibit"], capture_output=True).returncode + == 0 + ) + self.idle_label.set_visible(has_idle) + self.idle_label.set_markup(icons.coffee if has_idle else "") + + # Update night mode status + has_night = ( + subprocess.run( + ["pgrep", "-x", "hyprsunset"], capture_output=True + ).returncode + == 0 + ) + self.night_label.set_visible(has_night) + self.night_label.set_markup(icons.night if has_night else "") + + def update_volume_status(self, *_): + stream = self.audio_service.speaker + if not stream: + self.volume_icon_button.set_visible(False) + return + + self.volume_icon_button.set_visible(True) + # Normalize volume to integer percentage (0-100) + volume_level = stream.volume + if volume_level > 1: + volume_level = min(int(volume_level), 100) + else: + volume_level = int(volume_level * 100) + + is_muted = stream.muted + + if is_muted: + icon = icons.vol_off + elif volume_level > 74: + icon = icons.vol_high + elif volume_level > 0: + icon = icons.vol_medium + else: + icon = icons.vol_mute + + self.volume_icon_button.set_markup(icon) + + tooltip_text = "Muted" if is_muted else f"Volume: {volume_level}%" + self.volume_icon_button.set_tooltip_text(tooltip_text) + + + def update_bluetooth_status(self, *_): + if self.bluetooth_client.enabled: + self.bluetooth_icon.set_visible(True) + # Get a list of connected devices + connected_devices = [ + device.name + for device in self.bluetooth_client.devices + if device.connected + ] + + if connected_devices: + self.bluetooth_icon.set_markup(icons.bluetooth_connected) + self.bluetooth_icon.set_tooltip_text(f"{', '.join(connected_devices)}") + else: + self.bluetooth_icon.set_markup(icons.bluetooth) + self.bluetooth_icon.set_tooltip_text( + "Bluetooth is enabled, no devices connected" + ) + else: + self.bluetooth_icon.set_visible(True) # Keep it visible + self.bluetooth_icon.set_markup(icons.bluetooth_off) + self.bluetooth_icon.set_tooltip_text("Bluetooth is disabled") + + def update_network_status(self, *_): + primary_device = self.network_client.primary_device + self.wifi_icon.set_visible(True) + + if primary_device == "wifi" and self.network_client.wifi_device: + wifi_device = self.network_client.wifi_device + + self.wifi_icon.set_tooltip_text( + wifi_device.ssid if wifi_device.ssid else "No WiFi Connection" + ) + + if wifi_device.enabled: + strength = wifi_device.strength + + if strength > 0: + if strength < 25: + icon_label = icons.wifi_0 + elif strength < 50: + icon_label = icons.wifi_1 + elif strength < 75: + icon_label = icons.wifi_2 + else: + icon_label = icons.wifi_3 + else: + icon_label = icons.wifi_off + else: + icon_label = icons.wifi_off + + elif primary_device == "wired": + icon_label = icons.lan + self.wifi_icon.set_tooltip_text("Wired Connection") + + else: + icon_label = icons.wifi_off # No network + + self.wifi_icon.set_markup(icon_label) + + def update_power_profile(self, *_): + try: + result = subprocess.run( + ["powerprofilesctl", "get"], capture_output=True, text=True + ) + current_profile = result.stdout.strip() + + profile_icons = { + "performance": icons.power_performance, + "balanced": "", + "power-saver": icons.power_saving, + } + + icon = profile_icons.get(current_profile) + tooltip = ( + f"Power Profile: {current_profile.capitalize()}" + if current_profile + else "Unknown Profile" + ) + + self.power_label.set_visible(bool(icon)) # Only show if there's an icon + self.power_label.set_markup(icon) + self.power_label.set_tooltip_text(tooltip) + + except Exception as e: + self.power_label.set_visible(False) + self.power_label.set_tooltip_text(f"Error fetching power profile: {e}") + diff --git a/modules/bar/components/workspaces.py b/modules/bar/components/workspaces.py new file mode 100644 index 0000000..a0d8df2 --- /dev/null +++ b/modules/bar/components/workspaces.py @@ -0,0 +1,19 @@ +import json + +from fabric.hyprland.service import Hyprland +from fabric.widgets.label import Label + +connection = Hyprland() + +workspaceData = connection.send_command("j/activeworkspace").reply +activeWorkspace = json.loads(workspaceData.decode("utf-8"))["name"] +workspace = Label(label=f"{activeWorkspace}") + + +def on_workspace(obj, signal): + global activeWorkspace + activeWorkspace = json.loads(signal.data[0]) + workspace.set_label(f"{activeWorkspace}") + + +connection.connect("event::workspace", on_workspace) diff --git a/modules/corners.py b/modules/corners.py new file mode 100644 index 0000000..0df401d --- /dev/null +++ b/modules/corners.py @@ -0,0 +1,62 @@ +from fabric.widgets.box import Box +from fabric.widgets.wayland import WaylandWindow as Window +from fabric.widgets.shapes import Corner + +class MyCorner(Box): + def __init__(self, corner): + super().__init__( + name="corner-container", + children=Corner( + name="corner", + orientation=corner, + size=20, + ), + ) + +class Corners(Window): + def __init__(self): + super().__init__( + name="corners", + layer="top", + anchor="top bottom left right", + exclusivity="normal", + pass_through=True, + visible=False, + all_visible=False, + ) + + self.all_corners = Box( + name="all-corners", + orientation="v", + h_expand=True, + v_expand=True, + h_align="fill", + v_align="fill", + children=[ + Box( + name="top-corners", + orientation="h", + h_align="fill", + children=[ + MyCorner("top-left"), + Box(h_expand=True), + MyCorner("top-right"), + ], + ), + Box(v_expand=True), + Box( + name="bottom-corners", + orientation="h", + h_align="fill", + children=[ + MyCorner("bottom-left"), + Box(h_expand=True), + MyCorner("bottom-right"), + ], + ), + ], + ) + + self.add(self.all_corners) + + self.show_all() \ No newline at end of file diff --git a/modules/dock.py b/modules/dock.py new file mode 100644 index 0000000..c638174 --- /dev/null +++ b/modules/dock.py @@ -0,0 +1,948 @@ +import json +from gi.repository import GLib, Gtk, Gdk +import cairo +from utils.icon_resolver import IconResolver +from utils.occlusion import check_occlusion +from fabric.widgets.box import Box +from fabric.widgets.button import Button +from fabric.widgets.image import Image +from fabric.widgets.eventbox import EventBox +from fabric.widgets.wayland import WaylandWindow as Window +from fabric.hyprland.widgets import get_hyprland_connection +from fabric.utils import exec_shell_command, exec_shell_command_async, idle_add, remove_handler, get_relative_path +from fabric.utils.helpers import get_desktop_applications +from modules.corners import MyCorner # Add this import for corners + +import config.data as data +import logging + +OCCLUSION = 36 + data.DOCK_ICON_SIZE + +def read_config(): + """Read and return the full configuration from the JSON file, handling missing file.""" + config_path = get_relative_path("../config/dock.json") + try: + with open(config_path, "r") as file: + data = json.load(file) + + # Migration: Convert old format (simple string array) to new format (array of objects with full app data) + if "pinned_apps" in data and data["pinned_apps"] and isinstance(data["pinned_apps"][0], str): + # Get all desktop apps for lookup during migration + all_apps = get_desktop_applications() + app_map = {app.name: app for app in all_apps if app.name} + + # This is the old format - convert it with full app data + old_pinned = data["pinned_apps"] + data["pinned_apps"] = [] + + for app_id in old_pinned: + # Try to find the app by name + app = app_map.get(app_id) + if app: + # Create comprehensive app data + app_data = { + "name": app.name, + "display_name": app.display_name, + "window_class": app.window_class, + "executable": app.executable, + "command_line": app.command_line + } + data["pinned_apps"].append(app_data) + else: + # Fallback to just the name if app not found + data["pinned_apps"].append({"name": app_id}) + + except (FileNotFoundError, json.JSONDecodeError): + data = {"pinned_apps": []} # Default to empty pinned apps + return data + +# Credit to Aylur for the createSurfaceFromWidget code +def createSurfaceFromWidget(widget: Gtk.Widget) -> cairo.ImageSurface: + alloc = widget.get_allocation() + surface = cairo.ImageSurface( + cairo.Format.ARGB32, + alloc.width, + alloc.height, + ) + cr = cairo.Context(surface) + cr.set_source_rgba(255, 255, 255, 0) + cr.rectangle(0, 0, alloc.width, alloc.height) + cr.fill() + widget.draw(cr) + return surface + +class Dock(Window): + # Static registry to track all active dock instances + _instances = [] + + def __init__(self, **kwargs): + super().__init__( + name="dock-window", + layer="top", + anchor="bottom center", + margin="-8px 0 -8px 0", + exclusivity="none", + **kwargs, + ) + # Add this instance to the registry + Dock._instances.append(self) + + # Initialize configuration + self.config = read_config() + self.conn = get_hyprland_connection() + self.icon = IconResolver() + self.pinned = self.config.get("pinned_apps", []) + self.config_path = get_relative_path("../config/dock.json") + self.app_map = {} # Initialize the app map + self._all_apps = get_desktop_applications() # Get all apps for lookup + # Create app identifiers mapping + self.app_identifiers = self._build_app_identifiers_map() + self.is_hidden = False + self.hide_id = None + self._arranger_handler = None + self._drag_in_progress = False # Drag lock flag + self.is_hovered = False + self.always_occluded = data.DOCK_ALWAYS_OCCLUDED # Track the always occluded setting + + # Set up UI containers + self.view = Box(name="viewport", orientation="h", spacing=4) + self.wrapper = Box(name="dock", orientation="v", children=[self.view]) + + # Main dock container with hover handling + self.dock_eventbox = EventBox() + self.dock_eventbox.add(self.wrapper) + self.dock_eventbox.connect("enter-notify-event", self._on_dock_enter) + self.dock_eventbox.connect("leave-notify-event", self._on_dock_leave) + + # Create corners in the orientation-appropriate direction + + self.corner_left = Box( + name="dock-corner-left", + orientation="v", + h_align="start", + children=[ + Box(v_expand=True, v_align="fill"), + MyCorner("bottom-right"), + ] + ) + self.corner_right = Box( + name="dock-corner-right", + orientation="v", + h_align="end", + children=[ + Box(v_expand=True, v_align="fill"), + MyCorner("bottom-left"), + ] + ) + # Create a horizontal box that contains the corners and the dock + self.dock_full = Box( + name="dock-full", + orientation="h", + h_expand=True, + h_align="fill", + children=[ + self.corner_left, + self.dock_eventbox, + self.corner_right, + ] + ) + + + # Bottom/side hover activation area + self.hover_activator = EventBox() + self.hover_activator.set_size_request(-1, 1) + self.hover_activator.connect("enter-notify-event", self._on_hover_enter) + self.hover_activator.connect("leave-notify-event", self._on_hover_leave) + + # Update main_box to include the dock_full and activator + self.main_box = Box(orientation="v", + children=[self.dock_full, self.hover_activator]) + self.add(self.main_box) + + # Drag-and-drop setup for the viewport + self.view.drag_source_set( + Gdk.ModifierType.BUTTON1_MASK, + [Gtk.TargetEntry.new("text/plain", Gtk.TargetFlags.SAME_APP, 0)], + Gdk.DragAction.MOVE + ) + self.view.drag_dest_set( + Gtk.DestDefaults.ALL, + [Gtk.TargetEntry.new("text/plain", Gtk.TargetFlags.SAME_APP, 0)], + Gdk.DragAction.MOVE + ) + self.view.connect("drag-data-get", self.on_drag_data_get) + self.view.connect("drag-data-received", self.on_drag_data_received) + self.view.connect("drag-begin", self.on_drag_begin) + self.view.connect("drag-end", self.on_drag_end) + + # Initialization + if self.conn.ready: + self.update_dock() + GLib.timeout_add(500, self.check_hide) + else: + self.conn.connect("event::ready", self.update_dock) + self.conn.connect("event::ready", self.check_hide) + + for ev in ("activewindow", "openwindow", "closewindow", "changefloatingmode"): + self.conn.connect(f"event::{ev}", self.update_dock) + self.conn.connect("event::workspace", self.check_hide) + + + GLib.timeout_add(250, self.check_occlusion_state) + # Monitor dock.json for changes + GLib.timeout_add_seconds(1, self.check_config_change) + + # Check if dock should be visible based on configuration + if not data.DOCK_ENABLED: + self.set_visible(False) + + # Apply always occluded state if enabled in settings + if self.always_occluded: + self.dock_full.add_style_class("occluded") + + def _build_app_identifiers_map(self): + """Build a mapping of app identifiers (class names, executables, names) to DesktopApp objects""" + identifiers = {} + for app in self._all_apps: + # Map by name (lowercase) + if app.name: + identifiers[app.name.lower()] = app + + # Map by display name + if app.display_name: + identifiers[app.display_name.lower()] = app + + # Map by window class if available + if app.window_class: + identifiers[app.window_class.lower()] = app + + # Map by executable name if available + if app.executable: + exe_basename = app.executable.split('/')[-1].lower() + identifiers[exe_basename] = app + + # Map by command line if available (without parameters) + if app.command_line: + cmd_base = app.command_line.split()[0].split('/')[-1].lower() + identifiers[cmd_base] = app + + return identifiers + + def _normalize_window_class(self, class_name): + """Normalize window class by removing common suffixes and lowercase.""" + if not class_name: + return "" + + normalized = class_name.lower() + + # Remove common suffixes + suffixes = [".bin", ".exe", ".so", "-bin", "-gtk"] + for suffix in suffixes: + if normalized.endswith(suffix): + normalized = normalized[:-len(suffix)] + + return normalized + + def _classes_match(self, class1, class2): + """Check if two window class names match with stricter comparison.""" + if not class1 or not class2: + return False + + # Normalize both classes + norm1 = self._normalize_window_class(class1) + norm2 = self._normalize_window_class(class2) + + # Direct match after normalization + if norm1 == norm2: + return True + + # Don't do substring matching as it's too error-prone + # This avoids incorrectly matching flatpak apps and others + return False + + def on_drag_begin(self, widget, drag_context): + """Handle drag begin event by setting the drag lock flag.""" + self._drag_in_progress = True + # Set custom drag icon using the widget surface + Gtk.drag_set_icon_surface(drag_context, createSurfaceFromWidget(widget)) + + def _on_hover_enter(self, *args): + """Handle hover over bottom activation area""" + self.toggle_dock(show=True) + + def _on_hover_leave(self, *args): + """Handle leave from bottom activation area""" + self.delay_hide() + + def _on_dock_enter(self, widget, event): + """Handle hover over dock content""" + self.is_hovered = True + self.dock_full.remove_style_class("occluded") + # Cancel any pending hide operations + if self.hide_id: + GLib.source_remove(self.hide_id) + self.hide_id = None + self.toggle_dock(show=True) + return True # Important: Stop event propagation + + def _on_dock_leave(self, widget, event): + """Handle leave from dock content""" + # Only trigger if mouse actually left the entire dock area + if event.detail == Gdk.NotifyType.INFERIOR: + return False # Ignore child-to-child mouse movements + + self.is_hovered = False + self.delay_hide() + # Immediate occlusion check on true leave using simplified format + occlusion_region = ("bottom", OCCLUSION) + # Add occlusion style if not dragging an icon or if always_occluded is enabled + if (self.always_occluded or (not self._drag_in_progress and (check_occlusion(occlusion_region) or not self.view.get_children()))): + self.dock_full.add_style_class("occluded") + return True + + # Enhanced app lookup methods + def find_app(self, app_identifier): + """Return the DesktopApp object by matching any app identifier. + + If app_identifier is a dict, it will use all available keys for matching. + """ + if not app_identifier: + return None + + # If we got a dict object with app data (new format) + if isinstance(app_identifier, dict): + # Try to find by all available identifiers in priority order + for key in ["window_class", "executable", "command_line", "name", "display_name"]: + if key in app_identifier and app_identifier[key]: + app = self.find_app_by_key(app_identifier[key]) + if app: + return app + return None + + # Simple string identifier (backward compatibility) + return self.find_app_by_key(app_identifier) + + def find_app_by_key(self, key_value): + """Find app by a single identifier value""" + if not key_value: + return None + + # Try direct lookup in our identifiers map + normalized_id = str(key_value).lower() + if normalized_id in self.app_identifiers: + return self.app_identifiers[normalized_id] + + # Try fuzzy matching - find apps where the identifier is part of their names + for app in self._all_apps: + if app.name and normalized_id in app.name.lower(): + return app + if app.display_name and normalized_id in app.display_name.lower(): + return app + if app.window_class and normalized_id in app.window_class.lower(): + return app + if app.executable and normalized_id in app.executable.lower(): + return app + if app.command_line and normalized_id in app.command_line.lower(): + return app + + return None + + # Update the dock's app map using DesktopApp objects from the system. + def update_app_map(self): + """Updates the mapping of commands to DesktopApp objects.""" + self._all_apps = get_desktop_applications() # Refresh all apps + self.app_map = {app.name: app for app in self._all_apps if app.name} # Map app names to DesktopApp objects + self.app_identifiers = self._build_app_identifiers_map() # Rebuild identifiers map + + def create_button(self, app_identifier, instances): + """Create dock application button""" + desktop_app = self.find_app(app_identifier) # Find app by identifier + icon_img = None + display_name = None + + if desktop_app: + icon_img = desktop_app.get_icon_pixbuf(size=data.DOCK_ICON_SIZE) + display_name = desktop_app.display_name or desktop_app.name + + # Extract identifier for fallback + id_value = app_identifier["name"] if isinstance(app_identifier, dict) else app_identifier + + if not icon_img: + # Fallback to IconResolver with the app command + icon_img = self.icon.get_icon_pixbuf(id_value, data.DOCK_ICON_SIZE) # Use identifier for fallback + + if not icon_img: # Double check after exec path try + # Fallback icon if no DesktopApp is found + icon_img = self.icon.get_icon_pixbuf("application-x-executable-symbolic", data.DOCK_ICON_SIZE) + # Final fallback + if not icon_img: + icon_img = self.icon.get_icon_pixbuf("image-missing", data.DOCK_ICON_SIZE) + + items = [Image(pixbuf=icon_img)] + + tooltip = display_name or (id_value if isinstance(id_value, str) else "Unknown") + if not display_name and instances and instances[0].get("title"): + tooltip = instances[0]["title"] + + button = Button( + child= Box( + name="dock-icon", + orientation="v", + h_align="center", + children=items, + ), + on_clicked=lambda *a: self.handle_app(app_identifier, instances, desktop_app), # Pass desktop_app as well + tooltip_text=tooltip, + name="dock-app-button", + ) + + # Store app data with the button for future reference + button.app_identifier = app_identifier + button.desktop_app = desktop_app + button.instances = instances + + if instances: + button.add_style_class("instance") # Style running apps + + # Enable DnD for ALL apps + button.drag_source_set( + Gdk.ModifierType.BUTTON1_MASK, + [Gtk.TargetEntry.new("text/plain", Gtk.TargetFlags.SAME_APP, 0)], + Gdk.DragAction.MOVE + ) + button.connect("drag-begin", self.on_drag_begin) + button.connect("drag-end", self.on_drag_end) # Connect drag-end to ALL buttons + + # Make all buttons drop targets for better reordering + button.drag_dest_set( + Gtk.DestDefaults.ALL, + [Gtk.TargetEntry.new("text/plain", Gtk.TargetFlags.SAME_APP, 0)], + Gdk.DragAction.MOVE + ) + button.connect("drag-data-get", self.on_drag_data_get) + button.connect("drag-data-received", self.on_drag_data_received) + + button.connect("enter-notify-event", self._on_child_enter) + return button + + # Enhanced app launching with multiple fallbacks + def handle_app(self, app_identifier, instances, desktop_app=None): + """Handle application button clicks with improved fallbacks""" + if not instances: + # Try to launch the app with multiple fallback methods + if not desktop_app: + desktop_app = self.find_app(app_identifier) + + if desktop_app: + # Try the standard launch method first + launch_success = desktop_app.launch() + + # If that fails, try command line or executable + if not launch_success: + if desktop_app.command_line: + exec_shell_command_async(f"nohup {desktop_app.command_line}") + elif desktop_app.executable: + exec_shell_command_async(f"nohup {desktop_app.executable}") + else: + # No desktop entry found, try direct execution + if isinstance(app_identifier, dict): + # Try command_line first, then executable, then name as last resort + if "command_line" in app_identifier and app_identifier["command_line"]: + exec_shell_command_async(f"nohup {app_identifier['command_line']}") + elif "executable" in app_identifier and app_identifier["executable"]: + exec_shell_command_async(f"nohup {app_identifier['executable']}") + elif "name" in app_identifier and app_identifier["name"]: + exec_shell_command_async(f"nohup {app_identifier['name']}") + elif isinstance(app_identifier, str): + # Try direct execution with the identifier as fallback + exec_shell_command_async(f"nohup {app_identifier}") + else: + # Handle window switching for running instances + focused = self.get_focused() + idx = next( + (i for i, inst in enumerate(instances) if inst["address"] == focused), + -1, + ) + next_inst = instances[(idx + 1) % len(instances)] + exec_shell_command( + f"hyprctl dispatch focuswindow address:{next_inst['address']}" + ) + + def _on_child_enter(self, widget, event): + """Maintain hover state when entering child widgets""" + self.is_hovered = True + if self.hide_id: + GLib.source_remove(self.hide_id) + self.hide_id = None + return False # Continue event propagation + + def toggle_dock(self, show): + """Show or hide the dock immediately""" + if show: + if self.is_hidden: + self.is_hidden = False + self.dock_full.add_style_class("show-dock") + self.dock_full.remove_style_class("hide-dock") + if self.hide_id: + GLib.source_remove(self.hide_id) + self.hide_id = None + else: + if not self.is_hidden: + self.is_hidden = True + self.dock_full.add_style_class("hide-dock") + self.dock_full.remove_style_class("show-dock") + + def delay_hide(self): + """Schedule hiding after short delay""" + if self.hide_id: + GLib.source_remove(self.hide_id) + self.hide_id = GLib.timeout_add(1000, self.hide_dock) + + def hide_dock(self): + """Finalize hiding procedure""" + self.toggle_dock(show=False) + self.hide_id = None + return False + + def check_hide(self, *args): + """Determine if dock should auto-hide""" + clients = self.get_clients() + current_ws = self.get_workspace() + ws_clients = [w for w in clients if w["workspace"]["id"] == current_ws] + + if not ws_clients: + self.toggle_dock(show=True) + elif any(not w.get("floating") and not w.get("fullscreen") for w in ws_clients): + self.delay_hide() + else: + self.toggle_dock(show=True) + + def update_dock(self, *args): + """Refresh dock contents and clear drag lock.""" + self.update_app_map() # Update app map before creating buttons + arranger_handler = getattr(self, "_arranger_handler", None) + if arranger_handler: + remove_handler(arranger_handler) + clients = self.get_clients() + + # Create a mapping of window class to instances + running_windows = {} + for c in clients: + # Try multiple identification methods in order of reliability + window_id = None + + # Try initialClass first (most reliable) + if class_name := c.get("initialClass", "").lower(): + window_id = class_name + + # Try class second (fallback) + elif class_name := c.get("class", "").lower(): + window_id = class_name + + # Use title as last resort if both class identifiers are missing + elif title := c.get("title", "").lower(): + # Extract app name from title (common format: "App Name - Document") + possible_name = title.split(" - ")[0].strip() + if possible_name and len(potential_name) > 1: # Avoid single letter app names + window_id = possible_name + else: + window_id = title # Use full title if we can't extract a good name + + # Use generic identifier as absolute fallback + if not window_id: + window_id = "unknown-app" + + # Log window for debugging purposes + logging.debug(f"Window detected: {window_id} (from {c.get('initialClass', '')}/{c.get('class', '')}/{c.get('title', '')})") + + # Add to running windows - store with both original and normalized keys + running_windows.setdefault(window_id, []).append(c) + + # Also store with normalized key for more flexible matching + normalized_id = self._normalize_window_class(window_id) + if normalized_id != window_id: + running_windows.setdefault(normalized_id, []).extend(running_windows[window_id]) + + # Map pinned apps to their running instances + pinned_buttons = [] + used_window_classes = set() # Track which window classes we've already assigned + + for app_data in self.pinned: + app = self.find_app(app_data) + + # Try to find running instances for this pinned app + instances = [] + matched_class = None + + # Extract all possible identifiers from app_data for matching + possible_identifiers = [] + + if isinstance(app_data, dict): + for key in ["window_class", "executable", "command_line", "name", "display_name"]: + if key in app_data and app_data[key]: + possible_identifiers.append(app_data[key].lower()) + elif isinstance(app_data, str): + possible_identifiers.append(app_data.lower()) + + # Add identifiers from DesktopApp if available + if app: + if app.window_class: + possible_identifiers.append(app.window_class.lower()) + if app.executable: + possible_identifiers.append(app.executable.split('/')[-1].lower()) + if app.command_line: + cmd_parts = app.command_line.split() + if cmd_parts: + possible_identifiers.append(cmd_parts[0].split('/')[-1].lower()) + if app.name: + possible_identifiers.append(app.name.lower()) + if app.display_name: + possible_identifiers.append(app.display_name.lower()) + + # Remove duplicates + possible_identifiers = list(set(possible_identifiers)) + + # Try each identifier for matching + for identifier in possible_identifiers: + # Try direct match + if identifier in running_windows: + instances = running_windows[identifier] + matched_class = identifier + break + + # Try normalized version + normalized = self._normalize_window_class(identifier) + if normalized in running_windows: + instances = running_windows[normalized] + matched_class = normalized + break + + # Try substring matching for window classes (less reliable but helpful) + for window_class in running_windows: + # For substring matching, ensure the identifier is at least 3 chars + # to avoid too broad matches + if len(identifier) >= 3 and identifier in window_class: + instances = running_windows[window_class] + matched_class = window_class + logging.debug(f"Substring match: {identifier} in {window_class}") + break + + if matched_class: + break + + # Mark the matched class as used + if matched_class: + used_window_classes.add(matched_class) + # Also mark the normalized version as used + used_window_classes.add(self._normalize_window_class(matched_class)) + logging.debug(f"Matched pinned app {app_data} to running instances via {matched_class}") + + # Create button for this pinned app with any found instances + pinned_buttons.append(self.create_button(app_data, instances)) + + # For any remaining window classes that aren't assigned to pinned apps + open_buttons = [] + for class_name, instances in running_windows.items(): + if class_name not in used_window_classes: + # Enhanced app identification for running windows + app = None + + # Try multiple methods to find the correct app + # 1. Direct lookup by class name + app = self.app_identifiers.get(class_name) + + # 2. Try with normalized class name + if not app: + norm_class = self._normalize_window_class(class_name) + app = self.app_identifiers.get(norm_class) + + # 3. Try with our more robust find_app method + if not app: + app = self.find_app_by_key(class_name) + + # 4. Try using window title which often contains app name + if not app and instances and instances[0].get("title"): + title = instances[0].get("title", "") + # Extract potential app name from title (common format: "App Name - Document") + potential_name = title.split(" - ")[0].strip() + if len(potential_name) > 2: # Avoid very short names + app = self.find_app_by_key(potential_name) + + # Create comprehensive app data if app was found + if app: + app_data = { + "name": app.name, + "display_name": app.display_name, + "window_class": app.window_class, + "executable": app.executable, + "command_line": app.command_line + } + identifier = app_data + else: + # Fallback to just class name + identifier = class_name + + open_buttons.append(self.create_button(identifier, instances)) + + # Assemble dock layout + children = pinned_buttons + # Only add separator if both pinned and open buttons exist + if pinned_buttons and open_buttons: + children += [Box(orientation="v", v_expand=True, name="dock-separator")] + children += open_buttons + + self.view.children = children + idle_add(self._update_size) + self._drag_in_progress = False # Clear the drag lock + + def _update_size(self): + """Update window size based on content""" + width, _ = self.view.get_preferred_width() + self.set_size_request(width, -1) + return False + + def get_clients(self): + """Get current client list""" + try: + return json.loads(self.conn.send_command("j/clients").reply.decode()) + except json.JSONDecodeError: + return [] + + def get_focused(self): + """Get focused window address""" + try: + return json.loads( + self.conn.send_command("j/activewindow").reply.decode() + ).get("address", "") + except json.JSONDecodeError: + return "" + + def get_workspace(self): + """Get current workspace ID""" + try: + return json.loads( + self.conn.send_command("j/activeworkspace").reply.decode() + ).get("id", 0) + except json.JSONDecodeError: + return 0 + + def check_occlusion_state(self): + """Periodic occlusion check""" + # Skip occlusion check if hovered or dragging an icon + if self.is_hovered or self._drag_in_progress: + self.dock_full.remove_style_class("occluded") + return True + + # If always_occluded is enabled, keep the dock occluded + if self.always_occluded: + self.dock_full.add_style_class("occluded") + return True + + occlusion_region = ("bottom", OCCLUSION) + if check_occlusion(occlusion_region) or not self.view.get_children(): + self.dock_full.add_style_class("occluded") + else: + self.dock_full.remove_style_class("occluded") + return True + + def _find_drag_target(self, widget): + """Find valid drag target in viewport""" + children = self.view.get_children() + while widget is not None and widget not in children: + widget = widget.get_parent() if hasattr(widget, "get_parent") else None + return widget + + def on_drag_data_get(self, widget, drag_context, data, info, time): + """Handle drag start""" + target = self._find_drag_target(widget.get_parent() if isinstance(widget, Box) else widget) + if target is not None: + index = self.view.get_children().index(target) + data.set_text(str(index), -1) + + def on_drag_data_received(self, widget, drag_context, x, y, data, info, time): + """Handle drop event""" + target = self._find_drag_target(widget.get_parent() if isinstance(widget, Box) else widget) + if target is None: + return + try: + source_index = int(data.get_text()) + except (TypeError, ValueError): + return + + children = self.view.get_children() + try: + target_index = children.index(target) + except ValueError: + return + + if source_index != target_index: + # Check for separator to detect cross-section drag + separator_index = -1 + for i, child in enumerate(children): + if child.get_name() == "dock-separator": + separator_index = i + break + + # Detect if we're dragging across the separator (between pinned/unpinned) + cross_section_drag = (separator_index != -1 and + ((source_index < separator_index and target_index > separator_index) or + (source_index > separator_index and target_index < separator_index))) + + # Move the item in the children list + child = children.pop(source_index) + children.insert(target_index, child) + self.view.children = children # Update view immediately + + # Update pinned apps configuration + self.update_pinned_apps(skip_update=not cross_section_drag) + + # Force immediate update if we dragged across sections to update separator visibility + if cross_section_drag: + GLib.idle_add(self.update_dock) + + def on_drag_end(self, widget, drag_context): + """Handles drag end, for unpinning and closing apps.""" + # If a drag is already in progress, ignore duplicate calls. + if not self._drag_in_progress: + return + + def process_drag_end(): + """Inner function to handle drag end, safe to call with idle_add.""" + if self.get_mapped(): # Check if the window is mapped + # Get window geometry *before* any modifications + display = Gdk.Display.get_default() + _, x, y, _ = display.get_pointer() # Get pointer relative to the screen + window = self.get_window() + if window: # Check if we got a window + win_x, win_y, width, height = window.get_geometry() + if not (win_x <= x <= win_x + width and win_y <= y <= win_y + height): + # Drag ended outside the dock - get app data from the button + app_id = widget.app_identifier + instances = widget.instances + + # Find this app in pinned list + app_index = -1 + for i, pinned_app in enumerate(self.pinned): + # Match by identifier + if pinned_app == app_id: + app_index = i + break + # For dict format, match by name + elif isinstance(pinned_app, dict) and isinstance(app_id, dict): + if pinned_app.get("name") == app_id.get("name"): + app_index = i + break + + # If it's a pinned app, remove from pinned + if app_index >= 0: + self.pinned.pop(app_index) + self.config["pinned_apps"] = self.pinned + self.update_pinned_apps_file() + self.update_dock() # Update dock after file save + elif instances: # Close if running and unpinned + # Close running app (if not pinned) + address = instances[0].get("address") + if address: + exec_shell_command(f"hyprctl dispatch closewindow address:{address}") + self.update_dock() # Update dock after closing window + self._drag_in_progress = False # Clear the drag lock + + GLib.idle_add(process_drag_end) # Deferred execution with idle_add + + def check_config_change(self): + """Check if the config file has been modified.""" + new_config = read_config() + if new_config.get("pinned_apps", []) != self.config.get("pinned_apps", []): + self.config = new_config + self.pinned = self.config.get("pinned_apps", []) + self.update_app_map() # Update app_map when config changes + self.update_dock() + return True # Continue the timeout + + def update_pinned_apps_file(self): + """Writes the updated pinned apps list to dock.json""" + config_path = get_relative_path("../config/dock.json") + try: + with open(config_path, "w") as file: + json.dump(self.config, file, indent=4) + return True + except Exception as e: + logging.error(f"Failed to write dock config: {e}") + return False + + def update_pinned_apps(self, skip_update=False): + """Update pinned apps configuration by collecting all items before the separator""" + pinned_children = [] + for child in self.view.get_children(): + if child.get_name() == "dock-separator": + break # Stop at separator + + # Use stored app identifier from the button + if hasattr(child, "app_identifier"): + # If the button has a desktop_app, use it to create comprehensive data + if hasattr(child, "desktop_app") and child.desktop_app: + app = child.desktop_app + app_data = { + "name": app.name, + "display_name": app.display_name, + "window_class": app.window_class, + "executable": app.executable, + "command_line": app.command_line + } + pinned_children.append(app_data) + else: + # Keep existing app_identifier (might be dict or string) + pinned_children.append(child.app_identifier) + + # Directly update both config and local pinned list + self.config["pinned_apps"] = pinned_children + self.pinned = pinned_children # Update local state immediately + + # Write to file first to ensure persistence + file_updated = self.update_pinned_apps_file() + + # Only update the dock if needed and file was successfully written + if file_updated and not skip_update: + self.update_dock() # Refresh dock only after file is saved + + # Static method to update all dock instances + @staticmethod + def notify_config_change(): + """Notify all dock instances to reload their configuration immediately.""" + for dock in Dock._instances: + # Use idle_add to avoid potential issues with direct calls + GLib.idle_add(dock.check_config_change_immediate) + + def check_config_change_immediate(self): + """Immediately check for configuration changes and update if needed.""" + new_config = read_config() + + # Check if always_occluded setting has changed + previous_always_occluded = self.always_occluded + self.always_occluded = data.DOCK_ALWAYS_OCCLUDED + + # If always_occluded changed, update the dock appearance + if previous_always_occluded != self.always_occluded: + if self.always_occluded and not self.is_hovered: + self.dock_full.add_style_class("occluded") + elif not self.always_occluded and not self.is_hovered: + # Perform a normal occlusion check + occlusion_region = ("bottom", OCCLUSION) + if check_occlusion(occlusion_region) or not self.view.get_children(): + self.dock_full.add_style_class("occluded") + else: + self.dock_full.remove_style_class("occluded") + + if new_config.get("pinned_apps", []) != self.config.get("pinned_apps", []): + self.config = new_config + self.pinned = self.config.get("pinned_apps", []) + self.update_app_map() + self.update_dock() + return False # Don't repeat + + # Add a static method to handle dock visibility changes + @staticmethod + def update_visibility(visible): + """Update visibility for all dock instances.""" + for dock in Dock._instances: + dock.set_visible(visible) \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..ca1847f --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,16 @@ +[project] +name = "modusv2" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.13" +dependencies = [ + "fabric", + "loguru>=0.7.3", + "psutil>=7.0.0", + "pydbus>=0.6.0", + "setproctitle>=1.3.6", +] + +[tool.uv.sources] +fabric = { git = "https://github.com/Fabric-Development/fabric.git" } diff --git a/services/__init__.py b/services/__init__.py new file mode 100644 index 0000000..fdf19b4 --- /dev/null +++ b/services/__init__.py @@ -0,0 +1,9 @@ +from fabric.audio import Audio +from .brightness import Brightness +from .network import NetworkClient +from .battery import * + +network_client = NetworkClient() +brightness = Brightness() +audio = Audio() + diff --git a/services/battery.py b/services/battery.py new file mode 100644 index 0000000..1648f64 --- /dev/null +++ b/services/battery.py @@ -0,0 +1,112 @@ +from fabric.core import Service, Property, Signal +from pydbus import SystemBus +from loguru import logger + +DeviceState = { + 0: "UNKNOWN", + 1: "CHARGING", + 2: "DISCHARGING", + 3: "EMPTY", + 4: "FULLY_CHARGED", + 5: "PENDING_CHARGE", + 6: "PENDING_DISCHARGE", +} + + +class Battery(Service): + @staticmethod + def seconds_to_hours_minutes(seconds): + hours = seconds // 3600 + minutes = (seconds % 3600) // 60 + return f"{hours}h {minutes}m" if hours else f"{minutes}m" + + @Signal + def changed(self) -> None: ... + + @Signal + def profile_changed(self, value: str) -> None: ... + + @Property(int, "readable") + def percentage(self): + return int(self._battery.Percentage) + + @Property(str, "readable") + def temperature(self): + return f"{self._battery.Temperature}ยฐC" if hasattr(self._battery, "Temperature") else "N/A" + + @Property(str, "readable") + def time_to_empty(self): + return self.seconds_to_hours_minutes(getattr(self._battery, "TimeToEmpty", 0)) + + @Property(str, "readable") + def time_to_full(self): + return self.seconds_to_hours_minutes(getattr(self._battery, "TimeToFull", 0)) + + @Property(str, "readable") + def icon_name(self): + return self._battery.IconName + + @Property(str, "readable") + def state(self): + return DeviceState.get(self._battery.State, "UNKNOWN") + + @Property(str, "readable") + def capacity(self): + return f"{self._battery.Capacity}%" + + @Property(bool, "readable", default_value=False) + def is_present(self): + return self._battery.IsPresent + + @Property(str, "readable") + def power_profile(self): + return self._profile_proxy.ActiveProfile + + def set_power_profile(self, profile: str) -> bool: + if profile not in [p.Profile for p in self._profile_proxy.Profiles]: + logger.warning(f"[Battery] Invalid profile: {profile}") + return False + try: + self._profile_proxy.ActiveProfile = profile + logger.info(f"[Battery] Power profile set to {profile}") + self.profile_changed.emit(profile) + self.changed.emit() + return True + except Exception as e: + logger.error(f"[Battery] Failed to set profile: {e}") + return False + + def __init__(self): + super().__init__() + self._bus = SystemBus() + + # Battery device + try: + self._battery = self._bus.get("org.freedesktop.UPower", "/org/freedesktop/UPower/devices/battery_BAT0") + self._battery.onPropertiesChanged = self.handle_battery_change + logger.info("[Battery] UPower device connected.") + except Exception as e: + logger.error(f"[Battery] Failed to connect to UPower battery: {e}") + return + + # PowerProfiles + try: + self._profile_proxy = self._bus.get("net.hadess.PowerProfiles", "/net/hadess/PowerProfiles") + self._profile_proxy.onPropertiesChanged = self.handle_profile_change + logger.info("[Battery] PowerProfiles daemon connected.") + except Exception as e: + logger.error(f"[Battery] Failed to connect to PowerProfiles daemon: {e}") + self._profile_proxy = None + + self.changed.emit() + + def handle_battery_change(self, iface, changed, invalidated): + logger.debug(f"[Battery] UPower properties changed: {changed}") + self.changed.emit() + + def handle_profile_change(self, iface, changed, invalidated): + if "ActiveProfile" in changed: + new_profile = changed["ActiveProfile"] + logger.info(f"[Battery] Power profile changed: {new_profile}") + self.profile_changed.emit(new_profile) + self.changed.emit() diff --git a/services/brightness.py b/services/brightness.py new file mode 100644 index 0000000..2c07276 --- /dev/null +++ b/services/brightness.py @@ -0,0 +1,81 @@ +import os +from loguru import logger +from fabric.core import Service, Property, Signal +from fabric.utils import exec_shell_command_async, monitor_file + + +class Brightness(Service): + @Signal + def changed(self) -> None: ... + + @Property(int, "readable") + def max_brightness(self): + if self._cached_max_brightness is not None: + return self._cached_max_brightness + try: + with open(self._max_brightness_path) as f: + self._cached_max_brightness = int(f.read().strip()) + return self._cached_max_brightness + except Exception as e: + logger.error(f"[Brightness] Failed to read max brightness: {e}") + return -1 + + @Property(int, "read-write") + def brightness(self): + try: + with open(self._brightness_path) as f: + return int(f.read().strip()) + except Exception as e: + logger.error(f"[Brightness] Failed to read current brightness: {e}") + return -1 + + @brightness.setter + def brightness(self, value: int): + max_brightness = self.max_brightness + if max_brightness <= 0: + logger.error("[Brightness] Invalid max brightness; cannot set brightness.") + return + + value = max(0, min(value, max_brightness)) + try: + exec_shell_command_async( + f"brightnessctl --device '{self._device}' set {value}" + ) + logger.info(f"[Brightness] Set screen brightness to {value}") + except Exception as e: + logger.exception(f"[Brightness] Failed to set brightness: {e}") + + @Property(int, "readable") + def brightness_percentage(self): + max_brightness = self.max_brightness + current_brightness = self.brightness + + if max_brightness <= 0: + return 0 + return int((current_brightness / max_brightness) * 100) + + def __init__(self): + super().__init__() + self._device = None + self._cached_max_brightness = None + + self._backlight_path = "/sys/class/backlight" + + try: + devices = os.listdir(self._backlight_path) + if devices: + self._device = devices[0] + else: + raise FileNotFoundError + except FileNotFoundError: + logger.error("[Brightness] No backlight device found; brightness control disabled.") + return + + self._brightness_path = f"{self._backlight_path}/{self._device}/brightness" + self._max_brightness_path = f"{self._backlight_path}/{self._device}/max_brightness" + + try: + self._screen_monitor = monitor_file(self._brightness_path) + self._screen_monitor.connect("changed", lambda *args: self.changed.emit()) + except Exception as e: + logger.error(f"[Brightness] Failed to monitor brightness file: {e}") diff --git a/services/network.py b/services/network.py new file mode 100644 index 0000000..04ebcae --- /dev/null +++ b/services/network.py @@ -0,0 +1,334 @@ +from typing import Any, List, Literal + +import gi +from fabric.core.service import Property, Service, Signal +from fabric.utils import bulk_connect, exec_shell_command_async +from gi.repository import Gio +from loguru import logger + +try: + gi.require_version("NM", "1.0") + from gi.repository import NM +except ValueError: + logger.error("Failed to start network manager") + + +class Wifi(Service): + """A service to manage wifi devices""" + + @Signal + def changed(self) -> None: ... + + @Signal + def enabled(self) -> bool: ... + + @Signal + def scanning(self, is_scanning: bool) -> None: ... + + def __init__(self, client: NM.Client, device: NM.DeviceWifi, **kwargs): + self._client: NM.Client = client + self._device: NM.DeviceWifi = device + self._ap: NM.AccessPoint | None = None + self._ap_signal: int | None = None + super().__init__(**kwargs) + + self._client.connect( + "notify::wireless-enabled", + lambda *args: self.notifier("enabled", args), + ) + if self._device: + bulk_connect( + self._device, + { + "notify::active-access-point": lambda *args: self._activate_ap(), + "access-point-added": lambda *args: self.emit("changed"), + "access-point-removed": lambda *args: self.emit("changed"), + "state-changed": lambda *args: self.ap_update(), + }, + ) + self._activate_ap() + + def ap_update(self): + self.emit("changed") + for sn in [ + "enabled", + "internet", + "strength", + "frequency", + "access-points", + "ssid", + "state", + "icon-name", + ]: + self.notify(sn) + + def _activate_ap(self): + if self._ap: + self._ap.disconnect(self._ap_signal) + self._ap = self._device.get_active_access_point() + if not self._ap: + return + + self._ap_signal = self._ap.connect( + "notify::strength", lambda *args: self.ap_update() + ) # type: ignore + + def toggle_wifi(self): + self._client.wireless_set_enabled(not self._client.wireless_get_enabled()) + + # def set_active_ap(self, ap): + # self._device.access + + def scan(self): + """Start scanning for WiFi networks and emit scanning signal""" + if self._device: + self.emit("scanning", True) # Emit signal that scanning has started + self._device.request_scan_async( + None, + lambda device, result: [ + device.request_scan_finish(result), + self.emit( + "scanning", False + ), # Emit signal that scanning has stopped + ], + ) + + def notifier(self, name: str, *args): + self.notify(name) + self.emit("changed") + return + + @Property(bool, "read-write", default_value=False) + def enabled(self) -> bool: # type: ignore + return bool(self._client.wireless_get_enabled()) + + @enabled.setter + def enabled(self, value: bool): + self._client.wireless_set_enabled(value) + + @Property(int, "readable") + def strength(self): + return self._ap.get_strength() if self._ap else -1 + + @Property(str, "readable") + def icon_name(self): + if not self._ap: + return "network-wireless-disabled-symbolic" + + if self.internet == "activated": + return { + 80: "network-wireless-signal-excellent-symbolic", + 60: "network-wireless-signal-good-symbolic", + 40: "network-wireless-signal-ok-symbolic", + 20: "network-wireless-signal-weak-symbolic", + 00: "network-wireless-signal-none-symbolic", + }.get( + min(80, 20 * round(self._ap.get_strength() / 20)), + "network-wireless-no-route-symbolic", + ) + if self.internet == "activating": + return "network-wireless-acquiring-symbolic" + + return "network-wireless-offline-symbolic" + + @Property(int, "readable") + def frequency(self): + return self._ap.get_frequency() if self._ap else -1 + + @Property(int, "readable") + def internet(self): + return { + NM.ActiveConnectionState.ACTIVATED: "activated", + NM.ActiveConnectionState.ACTIVATING: "activating", + NM.ActiveConnectionState.DEACTIVATING: "deactivating", + NM.ActiveConnectionState.DEACTIVATED: "deactivated", + }.get( + self._device.get_active_connection().get_state(), + "unknown", + ) + + @Property(object, "readable") + def access_points(self) -> List[object]: + points: list[NM.AccessPoint] = self._device.get_access_points() + + def make_ap_dict(ap: NM.AccessPoint): + return { + "bssid": ap.get_bssid(), + # "address": ap.get_ + "last_seen": ap.get_last_seen(), + "ssid": NM.utils_ssid_to_utf8(ap.get_ssid().get_data()) + if ap.get_ssid() + else "Unknown", + "active-ap": self._ap, + "strength": ap.get_strength(), + "frequency": ap.get_frequency(), + "icon-name": { + 80: "network-wireless-signal-excellent-symbolic", + 60: "network-wireless-signal-good-symbolic", + 40: "network-wireless-signal-ok-symbolic", + 20: "network-wireless-signal-weak-symbolic", + 00: "network-wireless-signal-none-symbolic", + }.get( + min(80, 20 * round(ap.get_strength() / 20)), + "network-wireless-no-route-symbolic", + ), + } + + return list(map(make_ap_dict, points)) + + @Property(str, "readable") + def ssid(self): + if not self._ap: + return "Disconnected" + ssid = self._ap.get_ssid().get_data() + return NM.utils_ssid_to_utf8(ssid) if ssid else "Unknown" + + @Property(int, "readable") + def state(self): + return { + NM.DeviceState.UNMANAGED: "unmanaged", + NM.DeviceState.UNAVAILABLE: "unavailable", + NM.DeviceState.DISCONNECTED: "disconnected", + NM.DeviceState.PREPARE: "prepare", + NM.DeviceState.CONFIG: "config", + NM.DeviceState.NEED_AUTH: "need_auth", + NM.DeviceState.IP_CONFIG: "ip_config", + NM.DeviceState.IP_CHECK: "ip_check", + NM.DeviceState.SECONDARIES: "secondaries", + NM.DeviceState.ACTIVATED: "activated", + NM.DeviceState.DEACTIVATING: "deactivating", + NM.DeviceState.FAILED: "failed", + }.get(self._device.get_state(), "unknown") + + +class Ethernet(Service): + """A service to manage ethernet devices""" + + @Signal + def changed(self) -> None: ... + + @Signal + def enabled(self) -> bool: ... + + @Property(int, "readable") + def speed(self) -> int: + return self._device.get_speed() + + @Property(str, "readable") + def internet(self) -> str: + return { + NM.ActiveConnectionState.ACTIVATED: "activated", + NM.ActiveConnectionState.ACTIVATING: "activating", + NM.ActiveConnectionState.DEACTIVATING: "deactivating", + NM.ActiveConnectionState.DEACTIVATED: "deactivated", + }.get( + self._device.get_active_connection().get_state(), + "disconnected", + ) + + @Property(str, "readable") + def icon_name(self) -> str: + network = self.internet + if network == "activated": + return "network-wired-symbolic" + + elif network == "activating": + return "network-wired-acquiring-symbolic" + + elif self._device.get_connectivity != NM.ConnectivityState.FULL: + return "network-wired-no-route-symbolic" + + return "network-wired-disconnected-symbolic" + + def __init__(self, client: NM.Client, device: NM.DeviceEthernet, **kwargs) -> None: + super().__init__(**kwargs) + self._client: NM.Client = client + self._device: NM.DeviceEthernet = device + + for names in ( + "active-connection", + "icon-name", + "internet", + "speed", + "state", + ): + self._device.connect(f"notify::{names}", lambda *_: self.notifier(names)) + + self._device.connect("notify::speed", lambda *_: print(_)) + + def notifier(self, names): + self.notify(names) + self.emit("changed") + + +class NetworkClient(Service): + """A service to manage network devices""" + + @Signal + def device_ready(self) -> None: ... + + def __init__(self, **kwargs): + self._client: NM.Client | None = None + self.wifi_device: Wifi | None = None + self.ethernet_device: Ethernet | None = None + super().__init__(**kwargs) + NM.Client.new_async( + cancellable=None, + callback=self._init_network_client, + **kwargs, + ) + + def _init_network_client(self, client: NM.Client, task: Gio.Task, **kwargs): + self._client = client + wifi_device: NM.DeviceWifi | None = self._get_device(NM.DeviceType.WIFI) # type: ignore + ethernet_device: NM.DeviceEthernet | None = self._get_device( + NM.DeviceType.ETHERNET + ) + + if wifi_device: + self.wifi_device = Wifi(self._client, wifi_device) + self.emit("device-ready") + + if ethernet_device: + self.ethernet_device = Ethernet(client=self._client, device=ethernet_device) + self.emit("device-ready") + + self.notify("primary-device") + + def _get_device(self, device_type) -> Any: + devices: List[NM.Device] = self._client.get_devices() # type: ignore + return next( + ( + x + for x in devices + if x.get_device_type() == device_type + and x.get_active_connection() is not None + ), + None, + ) + + def _get_primary_device(self) -> Literal["wifi", "wired"] | None: + if not self._client: + return None + + if self._client.get_primary_connection() is None: + return "wifi" + return ( + "wifi" + if "wireless" + in str(self._client.get_primary_connection().get_connection_type()) + else "wired" + if "ethernet" + in str(self._client.get_primary_connection().get_connection_type()) + else None + ) + + def connect_wifi_bssid(self, bssid): + # We are using nmcli here, idk im lazy + exec_shell_command_async( + f"nmcli device wifi connect {bssid}", lambda *args: print(args) + ) + + @Property(str, "readable") + def primary_device(self) -> Literal["wifi", "wired"] | None: + return self._get_primary_device() diff --git a/styles/bar.css b/styles/bar.css new file mode 100644 index 0000000..fbf935a --- /dev/null +++ b/styles/bar.css @@ -0,0 +1,162 @@ +#bar { + padding: 4px; + background-color: var(--surface); + border-radius: 0 0 12px 12px; +} + + +#bar-container { + transition: all 0.25s cubic-bezier(0.5, 0.25, 0, 1); + opacity: 1; + } + + #bar-container.hide-bar { + margin-top: -32px; + } + + #bar-container.show-bar { + margin-top: 0; + } + + #bar-container.occluded { + margin-top: -32px; + } + + + #bar-corner-left { + margin-left: -16px; + } + + #bar-corner-right { + margin-right: -16px; + } + + #active-window { + padding: 0px 8px; + margin: 0 200px 0 0; + } + + + #workspaces { + padding: 4px; + min-width: 20px; + border-radius: 8px; + background-color: var(--surface-container); + } + + #date-time { + padding: 4px; + margin: 0 200px 0 0; + } + + #tray { + padding: 4px; + } + + #tray > button { + margin: 0px; + padding: 0px; + } + + menu { + border: solid 1px var(--outline-variant); + border-radius: 16px; + background-color: var(--surface); + padding: 6px; + } + + menu > menuitem { + border-radius: 10px; + padding: 6px 10px; + } + + menu > menuitem:hover { + background-color: var(--surface-bright); + } + + menu > menuitem:hover > label { + color: var(--on-surface); + } + + +#metrics{ + padding: 4px; + background-color: var(--surface-container); + border-radius: 8px; +} + +#metrics-circle { + color: var(--surface-bright); + border: 3px solid var(--primary); +} + +#metrics-circle.bat { + border: 3px solid var(--green); +} + +#metrics-circle.alert { + border: 3px solid var(--red-dim); +} + +#metrics-icon { + font-size: 15px; +} + +#metrics-icon.alert { + color: var(--red-dim); +} + +#metrics-level { + font-weight: bold; + padding: 2px; +} + +#metrics-sep { + min-width: 6px; +} + +#system-indicator { + padding: 4px; + background-color: var(--surface-container); + border-radius: 8px; +} + +#system-indicator-icon { + font-size: 20px; +} + + +#power-menu { + padding: 4px; + border-radius: 8px; + background-color: var(--surface-container); + transition: all 0.2s ease; +} + +#power-menu .power-icon{ + font-size: 20px; +} + +#power-menu.locked { + opacity: 0.5; + background-color: var(--surface-container-low); +} + +#power-menu.locked:hover { + opacity: 0.7; + background-color: var(--surface-container); +} + +#power-menu .power-label { + transition: all 0.2s ease; +} + +#power-menu.locked .power-label { + color: var(--on-surface-variant); +} + +#power-menu:not(.locked) .power-label { + color: var(--on-surface); +} + + \ No newline at end of file diff --git a/styles/colors.css b/styles/colors.css new file mode 100644 index 0000000..b7c1da5 --- /dev/null +++ b/styles/colors.css @@ -0,0 +1,44 @@ +:vars { + --foreground: #e1e4da; + --background: #11140f; + --cursor: #e1e4da; + --primary: #a5d396; + --primary-container: #285021; + --on-primary: #11380c; + --on-primary-container: #c0efb0; + --secondary: #bbcbb2; + --on-secondary: #263422; + --secondary-container: #3c4b37; + --tertiary: #a0cfd2; + --tertiary-container: #1e4d51; + --on-tertiary: #00373a; + --on-tertiary-container: #bcebee; + --surface: #11140f; + --surface-container: #1d211b; + --surface-bright: #363a34; + --surface-variant: #43483f; + --surface-container-low: #191d17; + --on-surface: #e1e4da; + --error: #ffb4ab; + --error-dim: #ff8678; + --on-error: #690005; + --error-container: #93000a; + --on-error-container: #ffdad6; + --outline: #8d9387; + --outline-variant: #43483f; + --shadow: #000000; + --red: #ffb595; + --red-dim: #ff9162; + --green: #a5d396; + --green-dim: #86c472; + --yellow: #b8cf84; + --yellow-dim: #a3c15f; + --blue: #afc6ff; + --blue-dim: #7ca2ff; + --magenta: #fcb0d5; + --magenta-dim: #fa7fbb; + --cyan: #84d5c4; + --cyan-dim: #5ec8b2; + --white: #82d3e0; + +} diff --git a/styles/dock.css b/styles/dock.css new file mode 100644 index 0000000..1d1de04 --- /dev/null +++ b/styles/dock.css @@ -0,0 +1,64 @@ +#dock { + background-color: var(--surface); + padding: 8px; + margin: 8px 8px 7px 8px; + border-radius: 20px 20px 0 0; + transition: all 0.25s cubic-bezier(0.5, 0.25, 0, 1); +} + +#dock-full { + transition: all 0.25s cubic-bezier(0.5, 0.25, 0, 1); + opacity: 1; +} + +#dock-full.occluded { + @apply dock_nmargin(); + /* opacity: 0; */ +} + +#dock-separator { + padding: 1px; + @apply dock_sep(); + border-radius: 16px; + background-color: var(--surface-bright); +} + +#dock-app-button { + padding: 4px; + border-radius: 12px; +} + +#dock-app-button:hover, +#dock-app-button:hover.instance { + background-color: var(--surface-bright); + border-top: 1px solid var(--primary); + padding-top: 3px; +} + +#dock-app-button:active, +#dock-app-button:active.instance { + background-color: var(--primary); +} + +#dock-app-button.instance { + background: linear-gradient(to top, transparent, var(--surface-bright)); + border-bottom: 1px solid var(--surface); + border-top: 1px solid var(--outline); + padding: 3px 4px; +} + +#dock-corner-left { + margin: 0 -8px 7px 0; +} + +#dock-corner-right { + margin: 0 0 7px -8px; +} + +#dock-corner-top { + margin: 0 79px -8px 0; +} + +#dock-corner-bottom { + margin: -8px 79px 0 0; +} diff --git a/styles/main.css b/styles/main.css new file mode 100644 index 0000000..3482759 --- /dev/null +++ b/styles/main.css @@ -0,0 +1,50 @@ +@import url("./colors.css"); +@import url("./bar.css"); +@import url("./dock.css"); + +* { + all: unset; + color: var(--foreground); + font-size: 15px; + font-family: "Zed Sans","Jost*", sans-serif; +} + +#corner { + background-color: var(--surface); + border-radius: 0; +} + +#corner-container { + min-width: 20px; + min-height: 20px; +} + +/* + * โ”€โ”€ tooltip โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +*/ +tooltip { + border-radius: 16px; + background-color: var(--surface); + animation: tooltipShow 0.25s cubic-bezier(0.5, 0.25, 0, 1); +} + +@keyframes tooltipShow { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +tooltip > * { + padding: 6px 10px; + border-radius: 10px; +} + + + + + + diff --git a/utils/__init__.py b/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/utils/icon_resolver.py b/utils/icon_resolver.py new file mode 100644 index 0000000..a80c8f6 --- /dev/null +++ b/utils/icon_resolver.py @@ -0,0 +1,102 @@ +import json +import os +import re + +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import GLib, Gtk +from loguru import logger + +import config.data as data + +ICON_CACHE_FILE = data.CACHE_DIR + "/icons.json" +if not os.path.exists(data.CACHE_DIR): + os.makedirs(data.CACHE_DIR) + + +class IconResolver: + def __init__(self, default_applicaiton_icon: str = "application-x-executable-symbolic"): + if os.path.exists(ICON_CACHE_FILE): + with open(ICON_CACHE_FILE) as f: + try: + self._icon_dict = json.load(f) + except json.JSONDecodeError: + logger.info("[ICONS] Cache file does not exist or is corrupted") + self._icon_dict = {} + else: + self._icon_dict = {} + + self.default_applicaiton_icon = default_applicaiton_icon + + def get_icon_name(self, app_id: str): + if app_id in self._icon_dict: + return self._icon_dict[app_id] + new_icon = self._compositor_find_icon(app_id) + logger.info( + f"[ICONS] found new icon: '{new_icon}' for app id: '{app_id}', storing..." + ) + self._store_new_icon(app_id, new_icon) + return new_icon + + def get_icon_pixbuf(self, app_id: str, size: int = 16): + icon_theme = Gtk.IconTheme.get_default() + icon_name = self.get_icon_name(app_id) + try: + # Try to load the resolved icon. + return icon_theme.load_icon(icon_name, size, Gtk.IconLookupFlags.FORCE_SIZE) + except GLib.Error as primary_error: + logger.warning( + f"Warning: Icon '{icon_name}' not found in theme. Error: {primary_error}" + ) + try: + # Fallback to the default application icon. + return icon_theme.load_icon( + self.default_applicaiton_icon, size, Gtk.IconLookupFlags.FORCE_SIZE + ) + except GLib.Error as fallback_error: + logger.error( + f"Error: Fallback icon '{self.default_applicaiton_icon}' also not found. Error: {fallback_error}" + ) + return None + + def _store_new_icon(self, app_id: str, icon: str): + self._icon_dict[app_id] = icon + with open(ICON_CACHE_FILE, "w") as f: + json.dump(self._icon_dict, f) + + def _get_icon_from_desktop_file(self, desktop_file_path: str): + # Retrieve the icon specified in the [Desktop Entry] section. + with open(desktop_file_path) as f: + for line in f.readlines(): + if "Icon=" in line: + return "".join(line[5:].split()) + return self.default_applicaiton_icon + + def _get_desktop_file(self, app_id: str) -> str | None: + data_dirs = GLib.get_system_data_dirs() + for data_dir in data_dirs: + data_dir = os.path.join(data_dir, "applications") + if os.path.exists(data_dir): + files = os.listdir(data_dir) + matching = [s for s in files if "".join(app_id.lower().split()) in s.lower()] + if matching: + return os.path.join(data_dir, matching[0]) + for word in list(filter(None, re.split(r"-|\.|_|\s", app_id))): + matching = [s for s in files if word.lower() in s.lower()] + if matching: + return os.path.join(data_dir, matching[0]) + return None + + def _compositor_find_icon(self, app_id: str): + icon_theme = Gtk.IconTheme.get_default() + if icon_theme.has_icon(app_id): + return app_id + if icon_theme.has_icon(app_id + "-desktop"): + return app_id + "-desktop" + desktop_file = self._get_desktop_file(app_id) + return ( + self._get_icon_from_desktop_file(desktop_file) + if desktop_file + else self.default_applicaiton_icon + ) diff --git a/utils/icons.py b/utils/icons.py new file mode 100644 index 0000000..ed61594 --- /dev/null +++ b/utils/icons.py @@ -0,0 +1,185 @@ +# Parameters +font_family: str = "tabler-icons" +font_weight: str = "normal" + +span: str = f"" + +# Panels +apps: str = "" +dashboard: str = "" +chat: str = "" +wallpapers: str = "" +windows: str = "" + +# Bar +colorpicker: str = "" +media: str = "" + +# Circles +temp: str = "" +disk: str = "" +battery: str = "" +memory: str = "流" +cpu: str = "" +swap: str = "" + +# Toolbox +toolbox: str = "" +ssfull: str = "" +ssregion: str = "" +screenshots: str = "" +screenrecord: str = "" +recordings: str = "" +ocr: str = "ﳃ" +gamemode: str = "" +gamemode_off: str = "" +close: str = "" +bell: str = "" +bell_off: str = "" +notifications_on: str = "" +notifications_off: str = "" +notifications_clear: str = "" +notifications: str = "" + +# Wallpapers +add: str = "" +sort: str = "" +circle: str = "" +check_box: str = "" +box: str = "" +scan: str = "" +scan_stop: str = "" +record: str = "" +update: str = "見" +updated: str = "" + +# Chevrons +chevron_up: str = "" +chevron_down: str = "" +chevron_left: str = "" +chevron_right: str = "" + +# Power +lock: str = "" +suspend: str = "" +logout: str = "" +reboot: str = "" +shutdown: str = "" + +# Power Manager +power_saving: str = "" +power_balanced: str = "勺" +power_performance: str = "" +charging: str = "" +discharging: str = "" +alert: str = "" +bat_charging: str = "" +bat_discharging: str = "" +bat_low: str = "=" +bat_full: str = "" + + +moderate_signal: str = "" +good_signal: str = "" +no_signal: str = "" +weak_signal: str = "" +# Applets +lan: str = "" +wifi_0: str = "" +wifi_1: str = "" +wifi_2: str = "" +wifi_3: str = "" +wifi: str = "" +world: str = "" +world_off: str = "" +bluetooth: str = "" +night: str = "" +coffee: str = "" +dnd: str = "" +darkmode: str = "﹖" + + +wifi_off: str = "" +bluetooth_off: str = "" +night_off: str = "" +dnd_off: str = "" + + +# Bluetooth +bluetooth_connected: str = "" +bluetooth_disconnected: str = "" + + +# Player +pause: str = "" +play: str = "" +stop: str = "" +skip_back: str = "" +skip_forward: str = "" +prev: str = "" +next: str = "" +shuffle: str = "" +repeat: str = "" +music: str = "" +rewind_backward_5: str = "謹" +rewind_forward_5: str = "難" + +# Volume +vol_off: str = "" +vol_mute: str = "" +vol_medium: str = "" +vol_high: str = "" + + +mic: str = "" +mic_muted: str = "" + + +# Overview +circle_plus: str = "" + +# Pins +copy_plus: str = "ﶮ" + +# Clipboard Manager +clipboard: str = "" +clip_text: str = "" + +# Confirm +accept: str = "" +cancel: str = "" +trash: str = "" +clear: str = "" + +# Config +config: str = "" + +# Icons +firefox: str = "" +chromium: str = "" +spotify: str = "ﺆ" +disc: str = "𐀾" +disc_off: str = "" + +# Misc +dot: str = "" +palette: str = "" +cloud_off: str = "" +loader: str = "" +radar: str = "" +emoji: str = "" +keyboard: str = "" +terminal: str = "" + + +exceptions: list[str] = ["font_family", "font_weight", "span"] + + +def apply_span() -> None: + global_dict = globals() + for key in global_dict: + if key not in exceptions and not key.startswith("__"): + global_dict[key] = f"{span}{global_dict[key]}" + + +apply_span() diff --git a/utils/occlusion.py b/utils/occlusion.py new file mode 100644 index 0000000..bf06350 --- /dev/null +++ b/utils/occlusion.py @@ -0,0 +1,141 @@ +import subprocess +import json + +import config.data as data + + +def get_current_workspace(): + """ + Get the current workspace ID using hyprctl. + """ + try: + result = subprocess.run( + ["hyprctl", "activeworkspace"], capture_output=True, text=True + ) + # Assume the output similar to: "ID " + # Extracting the number from the output + parts = result.stdout.split() + for i, part in enumerate(parts): + if part == "ID" and i + 1 < len(parts): + return int(parts[i + 1]) + except Exception as e: + print(f"Error getting current workspace: {e}") + return -1 + + +def get_screen_dimensions(): + """ + Get screen dimensions from hyprctl. + + Returns: + tuple: (width, height) of the monitor containing the current workspace + """ + try: + # Get current workspace + workspace_id = get_current_workspace() + + # Get monitor information + result = subprocess.run( + ["hyprctl", "-j", "monitors"], capture_output=True, text=True + ) + monitors = json.loads(result.stdout) + + # Find the monitor containing our workspace + for monitor in monitors: + if monitor.get("activeWorkspace", {}).get("id") == workspace_id: + return monitor.get("width", data.CURRENT_WIDTH), monitor.get( + "height", data.CURRENT_HEIGHT + ) + + # Fallback to first monitor + if monitors: + return monitors[0].get("width", data.CURRENT_WIDTH), monitors[0].get( + "height", data.CURRENT_HEIGHT + ) + except Exception as e: + print(f"Error getting screen dimensions: {e}") + + # Default fallback values + return data.CURRENT_WIDTH, data.CURRENT_HEIGHT + + +def check_occlusion(occlusion_region, workspace=None): + """ + Check if a region is occupied by any window on a given workspace. + + Parameters: + occlusion_region: Can be one of: + - tuple (side, size): where side is "top", "bottom", "left", or "right" + and size is the pixel width of the region + - tuple (x, y, width, height): The full region coordinates (legacy format) + workspace (int, optional): The workspace ID to check. If None, the current workspace is used. + + Returns: + bool: True if any window overlaps with the occlusion region, False otherwise. + """ + if workspace is None: + workspace = get_current_workspace() + + # Handle simplified side-based format + if isinstance(occlusion_region, tuple) and len(occlusion_region) == 2: + side, size = occlusion_region + if isinstance(side, str): + # Convert side-based format to coordinates + screen_width, screen_height = get_screen_dimensions() + + if side.lower() == "bottom": + occlusion_region = (0, screen_height - size, screen_width, size) + elif side.lower() == "top": + occlusion_region = (0, 0, screen_width, size) + elif side.lower() == "left": + occlusion_region = (0, 0, size, screen_height) + elif side.lower() == "right": + occlusion_region = (screen_width - size, 0, size, screen_height) + + # Ensure occlusion_region is in the correct format (x, y, width, height) + if not isinstance(occlusion_region, tuple) or len(occlusion_region) != 4: + print(f"Invalid occlusion region format: {occlusion_region}") + return False + + try: + result = subprocess.run( + ["hyprctl", "-j", "clients"], capture_output=True, text=True + ) + clients = json.loads(result.stdout) + except Exception as e: + print(f"Error retrieving client windows: {e}") + return False + + occ_x, occ_y, occ_width, occ_height = occlusion_region + occ_x2 = occ_x + occ_width + occ_y2 = occ_y + occ_height + + for client in clients: + # Check if client is mapped + if not client.get("mapped", False): + continue + + # Ensure client has proper workspace information and matches the workspace + client_workspace = client.get("workspace", {}) + if client_workspace.get("id") != workspace: + continue + + # Ensure client has position and size info + position = client.get("at") + size = client.get("size") + if not position or not size: + continue + + x, y = position + width, height = size + win_x1, win_y1 = x, y + win_x2, win_y2 = x + width, y + height + + # Check for intersection between the window and occlusion region + if not ( + win_x2 <= occ_x or win_x1 >= occ_x2 or win_y2 <= occ_y or win_y1 >= occ_y2 + ): + return True # Occlusion region is occupied + + return False # No window overlaps the occlusion region + diff --git a/utils/popup.py b/utils/popup.py new file mode 100644 index 0000000..f1c9942 --- /dev/null +++ b/utils/popup.py @@ -0,0 +1,279 @@ +from typing import ClassVar + +import gi +from fabric.hyprland.service import HyprlandEvent +from fabric.hyprland.widgets import get_hyprland_connection +from fabric.widgets.box import Box +from fabric.widgets.wayland import WaylandWindow +from fabric.widgets.widget import Widget +from gi.repository import Gdk, GLib, GObject, GtkLayerShell +from loguru import logger + +gi.require_versions( + {"Gtk": "3.0", "Gdk": "3.0", "GtkLayerShell": "0.1", "GObject": "2.0"} +) + + +class PopoverManager: + """Singleton manager to handle shared resources for popovers.""" + + _instance = None + + @classmethod + def get_instance(cls): + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def __init__(self): + # Shared overlay window for all popovers + self.overlay = WaylandWindow( + name="popover-overlay", + style_classes="popover-overlay", + title="fabric-shell-popover-overlay", + anchor="left top right bottom", + margin="-50px 0px 0px 0px", + exclusivity="auto", + layer="overlay", + type="top-level", + visible=False, + all_visible=False, + style="background-color: rgba(0,0,0,0.0);", + ) + + # Add empty box so GTK doesn't complain + self.overlay.add(Box()) + + # Keep track of active popovers + self.active_popover = None + self.available_windows = [] + + # Close popover when clicking overlay + self.overlay.connect("button-press-event", self._on_overlay_clicked) + self._hyprland_connection = get_hyprland_connection() + self._hyprland_connection.connect( + "event::focusedmonv2", self._on_monitor_change + ) + + def _on_monitor_change(self, _, event: HyprlandEvent): + if self.active_popover: + self.active_popover.hide_popover() + return True + + def _on_overlay_clicked(self, widget, event): + if self.active_popover: + self.active_popover.hide_popover() + return True + + def get_popover_window(self): + """Get an available popover window or create a new one.""" + if self.available_windows: + return self.available_windows.pop() + + window = WaylandWindow( + type="popup", + layer="overlay", + name="popover-window", + anchor="left top", + visible=False, + all_visible=False, + ) + GtkLayerShell.set_keyboard_interactivity(window, True) + window.set_keep_above(True) + return window + + def return_popover_window(self, window): + """Return a popover window to the pool.""" + # Remove any children + for child in window.get_children(): + window.remove(child) + + window.hide() + # Only keep a reasonable number of windows in the pool + if len(self.available_windows) < 5: + self.available_windows.append(window) + else: + # Let the window be garbage collected + window.destroy() + + def activate_popover(self, popover): + """Set the active popover and show overlay.""" + if self.active_popover and self.active_popover != popover: + self.active_popover.hide_popover() + + self.active_popover = popover + self.overlay.show() + + +@GObject.Signal( + flags=GObject.SignalFlags.RUN_LAST, return_type=GObject.TYPE_NONE, arg_types=() +) +def popover_opened(widget: Widget): ... + + +@GObject.Signal( + flags=GObject.SignalFlags.RUN_LAST, return_type=GObject.TYPE_NONE, arg_types=() +) +def popover_closed(widget: Widget): ... + + +@GObject.type_register +class Popover(Widget): + """Memory-efficient popover implementation.""" + + __gsignals__: ClassVar = { + "popover-opened": (GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()), + "popover-closed": (GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()), + } + + def __init__( + self, + point_to, + content_factory=None, + content=None, + ): + super().__init__() + """ + Initialize a popover. + + Args: + content_factory: Function that returns content widget when called + point_to: Widget to position the popover next to + """ + self._content_factory = content_factory + self._point_to = point_to + self._content_window = None + self._content = content + self._visible = False + self._destroy_timeout = None + # Use weak reference to avoid circular reference issues + self._manager = PopoverManager.get_instance() + + def set_content_factory(self, content_factory): + """Set the content factory for the popover.""" + self._content_factory = content_factory + + def set_content(self, content): + """Set the content for the popover.""" + self._content = content + + def _on_key_press(self, widget, event): + if event.keyval == Gdk.KEY_Escape and self._manager.active_popover: + self._manager.active_popover.hide_popover() + + def open(self): + if self._destroy_timeout is not None: + GLib.source_remove(self._destroy_timeout) + self._destroy_timeout = None + + if not self._content_window: + try: + self._create_popover() + except Exception as e: + logger.error(f"Could not create popover! Error: {e}") + else: + self._manager.activate_popover(self) + self._content_window.show() + self._content_window.steal_input() + self._visible = True + + self.emit("popover-opened") + + def _calculate_margins(self): + widget_allocation = self._point_to.get_allocation() + popover_size = self._content_window.get_size() + + display = Gdk.Display.get_default() + screen = display.get_default() + monitor_at_window = screen.get_monitor_at_window(self._point_to.get_window()) + monitor_geometry = monitor_at_window.get_geometry() + + x = ( + widget_allocation.x + + (widget_allocation.width / 2) + - (popover_size.width / 2) + ) + # Position below the button instead of above + y = widget_allocation.y + widget_allocation.height + 5 # 5px gap below button + + # Ensure popover stays within monitor bounds + if x <= 0: + x = widget_allocation.x + elif x + popover_size.width >= monitor_geometry.width: + x = widget_allocation.x - popover_size.width + widget_allocation.width + + # If popover would go below monitor, position it above the button + if y + popover_size.height > monitor_geometry.y + monitor_geometry.height: + y = widget_allocation.y - popover_size.height - 5 # 5px gap above button + + return [y, 0, 0, x] + + def set_position(self, position: tuple[int, int, int, int] | None = None): + if position is None: + self._content_window.set_margin(self._calculate_margins()) + return False + + self._content_window.set_margin(position) + return False + + def _on_content_ready(self, widget, event): + self.set_position() + + def _create_popover(self): + if self._content is None and self._content_factory is not None: + self._content = self._content_factory() + + # Get a window from the pool + self._content_window = self._manager.get_popover_window() + + # This is a hack to fix wrong positioning for widgets that are not rendered + # immediately (e.g., Gtk.Calendar()) + self._content.connect("draw", self._on_content_ready) + + # Add content to window + self._content_window.add( + Box(style_classes="popover-content", children=self._content) + ) + + self._content_window.connect("focus-out-event", self._on_popover_focus_out) + + self._content_window.connect("key-press-event", self._on_key_press) + self._manager.activate_popover(self) + self._content_window.show() + self._content_window.steal_input() + self._visible = True + + def _on_popover_focus_out(self, widget, event): + # This helps with keyboard focus issues + GLib.timeout_add(100, self.hide_popover) + return False + + def hide_popover(self): + if not self._visible or not self._content_window: + return False + + self._content_window.hide() + self._manager.overlay.hide() + self._visible = False + + if not self._destroy_timeout: + self._destroy_timeout = GLib.timeout_add(1000 * 5, self._destroy_popover) + + self.emit("popover-closed") + + return False + + def _destroy_popover(self): + """Return resources to the pool and clear references.""" + self._destroy_timeout = None + self._visible = False + + if self._content_window: + # Return window to the pool + self._manager.return_popover_window(self._content_window) + self._content_window = None + + # Allow content to be garbage collected if no longer needed + self._content = None + + return False \ No newline at end of file diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..d3dd3fc --- /dev/null +++ b/uv.lock @@ -0,0 +1,154 @@ +version = 1 +revision = 2 +requires-python = ">=3.13" + +[[package]] +name = "click" +version = "8.1.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593, upload-time = "2024-12-21T18:38:44.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188, upload-time = "2024-12-21T18:38:41.666Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "fabric" +version = "0.0.2" +source = { git = "https://github.com/Fabric-Development/fabric.git#1831ced4d9bb9f4be3893be55a8d502b47bff29e" } +dependencies = [ + { name = "click" }, + { name = "loguru" }, + { name = "pycairo" }, + { name = "pygobject" }, +] + +[[package]] +name = "loguru" +version = "0.7.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "win32-setctime", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3a/05/a1dae3dffd1116099471c643b8924f5aa6524411dc6c63fdae648c4f1aca/loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6", size = 63559, upload-time = "2024-12-06T11:20:56.608Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/29/0348de65b8cc732daa3e33e67806420b2ae89bdce2b04af740289c5c6c8c/loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c", size = 61595, upload-time = "2024-12-06T11:20:54.538Z" }, +] + +[[package]] +name = "modusv2" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "fabric" }, + { name = "loguru" }, + { name = "psutil" }, + { name = "pydbus" }, + { name = "setproctitle" }, +] + +[package.metadata] +requires-dist = [ + { name = "fabric", git = "https://github.com/Fabric-Development/fabric.git" }, + { name = "loguru", specifier = ">=0.7.3" }, + { name = "psutil", specifier = ">=7.0.0" }, + { name = "pydbus", specifier = ">=0.6.0" }, + { name = "setproctitle", specifier = ">=1.3.6" }, +] + +[[package]] +name = "psutil" +version = "7.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2a/80/336820c1ad9286a4ded7e845b2eccfcb27851ab8ac6abece774a6ff4d3de/psutil-7.0.0.tar.gz", hash = "sha256:7be9c3eba38beccb6495ea33afd982a44074b78f28c434a1f51cc07fd315c456", size = 497003, upload-time = "2025-02-13T21:54:07.946Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/e6/2d26234410f8b8abdbf891c9da62bee396583f713fb9f3325a4760875d22/psutil-7.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:101d71dc322e3cffd7cea0650b09b3d08b8e7c4109dd6809fe452dfd00e58b25", size = 238051, upload-time = "2025-02-13T21:54:12.36Z" }, + { url = "https://files.pythonhosted.org/packages/04/8b/30f930733afe425e3cbfc0e1468a30a18942350c1a8816acfade80c005c4/psutil-7.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:39db632f6bb862eeccf56660871433e111b6ea58f2caea825571951d4b6aa3da", size = 239535, upload-time = "2025-02-13T21:54:16.07Z" }, + { url = "https://files.pythonhosted.org/packages/2a/ed/d362e84620dd22876b55389248e522338ed1bf134a5edd3b8231d7207f6d/psutil-7.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fcee592b4c6f146991ca55919ea3d1f8926497a713ed7faaf8225e174581e91", size = 275004, upload-time = "2025-02-13T21:54:18.662Z" }, + { url = "https://files.pythonhosted.org/packages/bf/b9/b0eb3f3cbcb734d930fdf839431606844a825b23eaf9a6ab371edac8162c/psutil-7.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b1388a4f6875d7e2aff5c4ca1cc16c545ed41dd8bb596cefea80111db353a34", size = 277986, upload-time = "2025-02-13T21:54:21.811Z" }, + { url = "https://files.pythonhosted.org/packages/eb/a2/709e0fe2f093556c17fbafda93ac032257242cabcc7ff3369e2cb76a97aa/psutil-7.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f098451abc2828f7dc6b58d44b532b22f2088f4999a937557b603ce72b1993", size = 279544, upload-time = "2025-02-13T21:54:24.68Z" }, + { url = "https://files.pythonhosted.org/packages/50/e6/eecf58810b9d12e6427369784efe814a1eec0f492084ce8eb8f4d89d6d61/psutil-7.0.0-cp37-abi3-win32.whl", hash = "sha256:ba3fcef7523064a6c9da440fc4d6bd07da93ac726b5733c29027d7dc95b39d99", size = 241053, upload-time = "2025-02-13T21:54:34.31Z" }, + { url = "https://files.pythonhosted.org/packages/50/1b/6921afe68c74868b4c9fa424dad3be35b095e16687989ebbb50ce4fceb7c/psutil-7.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:4cf3d4eb1aa9b348dec30105c55cd9b7d4629285735a102beb4441e38db90553", size = 244885, upload-time = "2025-02-13T21:54:37.486Z" }, +] + +[[package]] +name = "pycairo" +version = "1.28.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/40/d9/412da520de9052b7e80bfc810ec10f5cb3dbfa4aa3e23c2820dc61cdb3d0/pycairo-1.28.0.tar.gz", hash = "sha256:26ec5c6126781eb167089a123919f87baa2740da2cca9098be8b3a6b91cc5fbc", size = 662477, upload-time = "2025-04-14T20:11:08.218Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/a7/c3e5ed55781dfe1b31eb4a2482aeae707671f3d36b0ea53a1722f4a3dfe9/pycairo-1.28.0-cp313-cp313-win32.whl", hash = "sha256:d13352429d8a08a1cb3607767d23d2fb32e4c4f9faa642155383980ec1478c24", size = 750594, upload-time = "2025-04-14T20:10:59.284Z" }, + { url = "https://files.pythonhosted.org/packages/8b/1c/ebadd290748aff3b6bc35431114d41e7a42f40a4b988c2aaf2dfed5d8156/pycairo-1.28.0-cp313-cp313-win_amd64.whl", hash = "sha256:082aef6b3a9dcc328fa648d38ed6b0a31c863e903ead57dd184b2e5f86790140", size = 841774, upload-time = "2025-04-14T20:11:01.79Z" }, + { url = "https://files.pythonhosted.org/packages/3e/ce/a3f5f1946613cd8a4654322b878c59f273c6e9b01dfadadd3f609070e0b9/pycairo-1.28.0-cp313-cp313-win_arm64.whl", hash = "sha256:026afd53b75291917a7412d9fe46dcfbaa0c028febd46ff1132d44a53ac2c8b6", size = 691675, upload-time = "2025-04-16T19:30:26.565Z" }, +] + +[[package]] +name = "pydbus" +version = "0.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/56/3e84f2c1f2e39b9ea132460183f123af41e3b9c8befe222a35636baa6a5a/pydbus-0.6.0.tar.gz", hash = "sha256:4207162eff54223822c185da06c1ba8a34137a9602f3da5a528eedf3f78d0f2c", size = 22079, upload-time = "2016-12-18T16:44:31.904Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/56/27148014c2f85ce70332f18612f921f682395c7d4e91ec103783be4fce00/pydbus-0.6.0-py2.py3-none-any.whl", hash = "sha256:66b80106352a718d80d6c681dc2a82588048e30b75aab933e4020eb0660bf85e", size = 19580, upload-time = "2016-12-18T16:44:19.565Z" }, +] + +[[package]] +name = "pygobject" +version = "3.50.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycairo" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2b/58/d34e67a79631177e3c08e7d02b5165147f590171f2cae6769502af5f7f7e/pygobject-3.50.0.tar.gz", hash = "sha256:4500ad3dbf331773d8dedf7212544c999a76fc96b63a91b3dcac1e5925a1d103", size = 1080367, upload-time = "2024-09-12T12:05:22.579Z" } + +[[package]] +name = "setproctitle" +version = "1.3.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9e/af/56efe21c53ac81ac87e000b15e60b3d8104224b4313b6eacac3597bd183d/setproctitle-1.3.6.tar.gz", hash = "sha256:c9f32b96c700bb384f33f7cf07954bb609d35dd82752cef57fb2ee0968409169", size = 26889, upload-time = "2025-04-29T13:35:00.184Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/76/f1a2fdbf9b9602945a7489ba5c52e9863de37381ef1a85a2b9ed0ff8bc79/setproctitle-1.3.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e2a9e62647dc040a76d55563580bf3bb8fe1f5b6ead08447c2ed0d7786e5e794", size = 17392, upload-time = "2025-04-29T13:33:30.925Z" }, + { url = "https://files.pythonhosted.org/packages/5c/5b/4e0db8b10b4543afcb3dbc0827793d46e43ec1de6b377e313af3703d08e0/setproctitle-1.3.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:751ba352ed922e0af60458e961167fa7b732ac31c0ddd1476a2dfd30ab5958c5", size = 11951, upload-time = "2025-04-29T13:33:32.296Z" }, + { url = "https://files.pythonhosted.org/packages/dc/fe/d5d00aaa700fe1f6160b6e95c225b29c01f4d9292176d48fd968815163ea/setproctitle-1.3.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7890e291bf4708e3b61db9069ea39b3ab0651e42923a5e1f4d78a7b9e4b18301", size = 32087, upload-time = "2025-04-29T13:33:33.469Z" }, + { url = "https://files.pythonhosted.org/packages/9f/b3/894b827b93ef813c082479bebf88185860f01ac243df737823dd705e7fff/setproctitle-1.3.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2b17855ed7f994f3f259cf2dfbfad78814538536fa1a91b50253d84d87fd88d", size = 33502, upload-time = "2025-04-29T13:33:34.831Z" }, + { url = "https://files.pythonhosted.org/packages/b2/cd/5330734cca1a4cfcb721432c22cb7899ff15a4101ba868b2ef452ffafea1/setproctitle-1.3.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e51ec673513465663008ce402171192a053564865c2fc6dc840620871a9bd7c", size = 30713, upload-time = "2025-04-29T13:33:36.739Z" }, + { url = "https://files.pythonhosted.org/packages/fa/d3/c2590c5daa2e9a008d3f2b16c0f4a351826193be55f147cb32af49c6d814/setproctitle-1.3.6-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63cc10352dc6cf35a33951656aa660d99f25f574eb78132ce41a85001a638aa7", size = 31792, upload-time = "2025-04-29T13:33:37.974Z" }, + { url = "https://files.pythonhosted.org/packages/e6/b1/c553ed5af8cfcecd5ae7737e63af58a17a03d26f3d61868c7eb20bf7e3cf/setproctitle-1.3.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0dba8faee2e4a96e934797c9f0f2d093f8239bf210406a99060b3eabe549628e", size = 31927, upload-time = "2025-04-29T13:33:39.203Z" }, + { url = "https://files.pythonhosted.org/packages/70/78/2d5385206540127a3dca0ff83225b1ac66873f5cc89d4a6d3806c92f5ae2/setproctitle-1.3.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e3e44d08b61de0dd6f205528498f834a51a5c06689f8fb182fe26f3a3ce7dca9", size = 30981, upload-time = "2025-04-29T13:33:40.431Z" }, + { url = "https://files.pythonhosted.org/packages/31/62/e3e4a4e006d0e549748e53cded4ff3b667be0602860fc61b7de8b412b667/setproctitle-1.3.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:de004939fc3fd0c1200d26ea9264350bfe501ffbf46c8cf5dc7f345f2d87a7f1", size = 33244, upload-time = "2025-04-29T13:33:41.817Z" }, + { url = "https://files.pythonhosted.org/packages/aa/05/4b223fd4ef94e105dc7aff27fa502fb7200cf52be2bb0c064bd2406b5611/setproctitle-1.3.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3f8194b4d631b003a1176a75d1acd545e04b1f54b821638e098a93e6e62830ef", size = 31630, upload-time = "2025-04-29T13:33:43.093Z" }, + { url = "https://files.pythonhosted.org/packages/1b/ba/5f68eb969f7336f54b54a599fd3ffbd7662f9733b080bc8598705971b3dd/setproctitle-1.3.6-cp313-cp313-win32.whl", hash = "sha256:d714e002dd3638170fe7376dc1b686dbac9cb712cde3f7224440af722cc9866a", size = 11480, upload-time = "2025-04-29T13:34:01.257Z" }, + { url = "https://files.pythonhosted.org/packages/ba/f5/7f47f0ca35c9c357f16187cee9229f3eda0237bc6fdd3061441336f361c0/setproctitle-1.3.6-cp313-cp313-win_amd64.whl", hash = "sha256:b70c07409d465f3a8b34d52f863871fb8a00755370791d2bd1d4f82b3cdaf3d5", size = 12198, upload-time = "2025-04-29T13:34:02.293Z" }, + { url = "https://files.pythonhosted.org/packages/39/ad/c3941b8fc6b32a976c9e2d9615a90ae793b69cd010ca8c3575dbc822104f/setproctitle-1.3.6-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:23a57d3b8f1549515c2dbe4a2880ebc1f27780dc126c5e064167563e015817f5", size = 17401, upload-time = "2025-04-29T13:33:44.186Z" }, + { url = "https://files.pythonhosted.org/packages/04/38/a184f857b988d3a9c401e470a4e38182a5c99ee77bf90432d7665e9d35a3/setproctitle-1.3.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:81c443310831e29fabbd07b75ebbfa29d0740b56f5907c6af218482d51260431", size = 11959, upload-time = "2025-04-29T13:33:45.71Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b9/4878ef9d8483adfd1edf6bf95151362aaec0d05aac306a97ff0383f491b5/setproctitle-1.3.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d88c63bd395c787b0aa81d8bbc22c1809f311032ce3e823a6517b711129818e4", size = 33463, upload-time = "2025-04-29T13:33:46.913Z" }, + { url = "https://files.pythonhosted.org/packages/cc/60/3ef49d1931aff2a36a7324a49cca10d77ef03e0278452fd468c33a52d7e3/setproctitle-1.3.6-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d73f14b86d0e2858ece6bf5807c9889670e392c001d414b4293d0d9b291942c3", size = 34959, upload-time = "2025-04-29T13:33:48.216Z" }, + { url = "https://files.pythonhosted.org/packages/81/c6/dee0a973acecefb0db6c9c2e0ea7f18b7e4db773a72e534741ebdee8bbb8/setproctitle-1.3.6-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3393859eb8f19f5804049a685bf286cb08d447e28ba5c6d8543c7bf5500d5970", size = 32055, upload-time = "2025-04-29T13:33:49.443Z" }, + { url = "https://files.pythonhosted.org/packages/ea/a5/5dd5c4192cf18d16349a32a07f728a9a48a2a05178e16966cabd6645903e/setproctitle-1.3.6-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:785cd210c0311d9be28a70e281a914486d62bfd44ac926fcd70cf0b4d65dff1c", size = 32986, upload-time = "2025-04-29T13:33:51.519Z" }, + { url = "https://files.pythonhosted.org/packages/df/a6/1508d37eb8008670d33f13fcdb91cbd8ef54697276469abbfdd3d4428c59/setproctitle-1.3.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c051f46ed1e13ba8214b334cbf21902102807582fbfaf0fef341b9e52f0fafbf", size = 32736, upload-time = "2025-04-29T13:33:52.852Z" }, + { url = "https://files.pythonhosted.org/packages/1a/73/c84ec8880d543766a12fcd6b65dbd013770974a40577889f357409b0441e/setproctitle-1.3.6-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:49498ebf68ca3e75321ffe634fcea5cc720502bfaa79bd6b03ded92ce0dc3c24", size = 31945, upload-time = "2025-04-29T13:33:54.665Z" }, + { url = "https://files.pythonhosted.org/packages/95/0a/126b9ff7a406a69a62825fe5bd6d1ba8671919a7018c4f9e2c63f49bfcb6/setproctitle-1.3.6-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:4431629c178193f23c538cb1de3da285a99ccc86b20ee91d81eb5f1a80e0d2ba", size = 34333, upload-time = "2025-04-29T13:33:56.101Z" }, + { url = "https://files.pythonhosted.org/packages/9a/fd/5474b04f1c013ff460129d2bc774557dd6e186da4667865efef9a83bf378/setproctitle-1.3.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d136fbf8ad4321716e44d6d6b3d8dffb4872626010884e07a1db54b7450836cf", size = 32508, upload-time = "2025-04-29T13:33:57.43Z" }, + { url = "https://files.pythonhosted.org/packages/32/21/2503e38520cb076a7ecaef6a35d6a6fa89cf02af3541c84c811fd7500d20/setproctitle-1.3.6-cp313-cp313t-win32.whl", hash = "sha256:d483cc23cc56ab32911ea0baa0d2d9ea7aa065987f47de847a0a93a58bf57905", size = 11482, upload-time = "2025-04-29T13:33:58.602Z" }, + { url = "https://files.pythonhosted.org/packages/65/23/7833d75a27fba25ddc5cd3b54cd03c4bf8e18b8e2dbec622eb6326278ce8/setproctitle-1.3.6-cp313-cp313t-win_amd64.whl", hash = "sha256:74973aebea3543ad033b9103db30579ec2b950a466e09f9c2180089e8346e0ec", size = 12209, upload-time = "2025-04-29T13:33:59.727Z" }, +] + +[[package]] +name = "win32-setctime" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b3/8f/705086c9d734d3b663af0e9bb3d4de6578d08f46b1b101c2442fd9aecaa2/win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0", size = 4867, upload-time = "2024-12-07T15:28:28.314Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/07/c6fe3ad3e685340704d314d765b7912993bcb8dc198f0e7a89382d37974b/win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390", size = 4083, upload-time = "2024-12-07T15:28:26.465Z" }, +]