Merge remote-tracking branch 'origin/develop' into reactions
authorlain <lain@soykaf.club>
Fri, 13 Sep 2019 14:31:27 +0000 (16:31 +0200)
committerlain <lain@soykaf.club>
Fri, 13 Sep 2019 14:31:27 +0000 (16:31 +0200)
15 files changed:
docs/api/pleroma_api.md
lib/pleroma/emoji-data.txt [new file with mode: 0644]
lib/pleroma/emoji.ex
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/activity_pub/transmogrifier.ex
lib/pleroma/web/activity_pub/utils.ex
lib/pleroma/web/common_api/common_api.ex
lib/pleroma/web/pleroma_api/pleroma_api_controller.ex
lib/pleroma/web/router.ex
test/emoji_test.exs
test/fixtures/emoji-reaction.json [new file with mode: 0644]
test/web/activity_pub/activity_pub_test.exs
test/web/activity_pub/transmogrifier_test.exs
test/web/common_api/common_api_test.exs
test/web/pleroma_api/pleroma_api_controller_test.exs

index 30fac77dad7d20b1af3c70b7d83d1fe2cb6c82d4..3f12e38b9509e72b35c49fddf8d6a2a4cb4a285d 100644 (file)
@@ -365,3 +365,28 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa
 * Params:
     * `recipients`: A list of ids of users that should receive posts to this conversation. This will replace the current list of recipients, so submit the full list. The owner of owner of the conversation will always be part of the set of recipients, though.
 * Response: JSON, statuses (200 - healthy, 503 unhealthy)
+
+# Emoji Reactions
+
+Emoji reactions work a lot like favourites do. They make it possible to react to a post with a single emoji character.
+
+## `POST /api/v1/pleroma/statuses/:id/react_with_emoji`
+### React to a post with a unicode emoji
+* Method: `POST`
+* Authentication: required
+* Params: `emoji`: A single character unicode emoji
+* Response: JSON, the status.
+
+## `GET /api/v1/pleroma/statuses/:id/emoji_reactions_by`
+### Get an object of emoji to account mappings with accounts that reacted to the post
+* Method: `GET`
+* Authentication: optional
+* Params: None
+* Response: JSON, a map of emoji to account list mappings.
+* Example Response:
+```json
+{
+  "😀" => [{"id" => "xyz.."...}, {"id" => "zyx..."}],
+  "🗡" => [{"id" => "abc..."}] 
+}
+```
diff --git a/lib/pleroma/emoji-data.txt b/lib/pleroma/emoji-data.txt
new file mode 100644 (file)
index 0000000..2fb5c3f
--- /dev/null
@@ -0,0 +1,769 @@
+# emoji-data.txt
+# Date: 2019-01-15, 12:10:05 GMT
+# © 2019 Unicode®, Inc.
+# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Emoji Data for UTS #51
+# Version: 12.0
+#
+# For documentation and usage, see http://www.unicode.org/reports/tr51
+#
+# Format: 
+# <codepoint(s)> ; <property> # <comments> 
+# Note: there is no guarantee as to the structure of whitespace or comments
+#
+# Characters and sequences are listed in code point order. Users should be shown a more natural order.
+# See the CLDR collation order for Emoji.
+
+
+# ================================================
+
+# All omitted code points have Emoji=No 
+# @missing: 0000..10FFFF  ; Emoji ; No
+
+0023          ; Emoji                #  1.1  [1] (#️)       number sign
+002A          ; Emoji                #  1.1  [1] (*️)       asterisk
+0030..0039    ; Emoji                #  1.1 [10] (0️..9️)    digit zero..digit nine
+00A9          ; Emoji                #  1.1  [1] (©️)       copyright
+00AE          ; Emoji                #  1.1  [1] (®️)       registered
+203C          ; Emoji                #  1.1  [1] (‼️)       double exclamation mark
+2049          ; Emoji                #  3.0  [1] (⁉️)       exclamation question mark
+2122          ; Emoji                #  1.1  [1] (™️)       trade mark
+2139          ; Emoji                #  3.0  [1] (ℹ️)       information
+2194..2199    ; Emoji                #  1.1  [6] (↔️..↙️)    left-right arrow..down-left arrow
+21A9..21AA    ; Emoji                #  1.1  [2] (↩️..↪️)    right arrow curving left..left arrow curving right
+231A..231B    ; Emoji                #  1.1  [2] (⌚..⌛)    watch..hourglass done
+2328          ; Emoji                #  1.1  [1] (⌨️)       keyboard
+23CF          ; Emoji                #  4.0  [1] (⏏️)       eject button
+23E9..23F3    ; Emoji                #  6.0 [11] (⏩..⏳)    fast-forward button..hourglass not done
+23F8..23FA    ; Emoji                #  7.0  [3] (⏸️..⏺️)    pause button..record button
+24C2          ; Emoji                #  1.1  [1] (Ⓜ️)       circled M
+25AA..25AB    ; Emoji                #  1.1  [2] (▪️..▫️)    black small square..white small square
+25B6          ; Emoji                #  1.1  [1] (▶️)       play button
+25C0          ; Emoji                #  1.1  [1] (◀️)       reverse button
+25FB..25FE    ; Emoji                #  3.2  [4] (◻️..◾)    white medium square..black medium-small square
+2600..2604    ; Emoji                #  1.1  [5] (☀️..☄️)    sun..comet
+260E          ; Emoji                #  1.1  [1] (☎️)       telephone
+2611          ; Emoji                #  1.1  [1] (☑️)       check box with check
+2614..2615    ; Emoji                #  4.0  [2] (☔..☕)    umbrella with rain drops..hot beverage
+2618          ; Emoji                #  4.1  [1] (☘️)       shamrock
+261D          ; Emoji                #  1.1  [1] (☝️)       index pointing up
+2620          ; Emoji                #  1.1  [1] (☠️)       skull and crossbones
+2622..2623    ; Emoji                #  1.1  [2] (☢️..☣️)    radioactive..biohazard
+2626          ; Emoji                #  1.1  [1] (☦️)       orthodox cross
+262A          ; Emoji                #  1.1  [1] (☪️)       star and crescent
+262E..262F    ; Emoji                #  1.1  [2] (☮️..☯️)    peace symbol..yin yang
+2638..263A    ; Emoji                #  1.1  [3] (☸️..☺️)    wheel of dharma..smiling face
+2640          ; Emoji                #  1.1  [1] (♀️)       female sign
+2642          ; Emoji                #  1.1  [1] (♂️)       male sign
+2648..2653    ; Emoji                #  1.1 [12] (♈..♓)    Aries..Pisces
+265F..2660    ; Emoji                #  1.1  [2] (♟️..♠️)    chess pawn..spade suit
+2663          ; Emoji                #  1.1  [1] (♣️)       club suit
+2665..2666    ; Emoji                #  1.1  [2] (♥️..♦️)    heart suit..diamond suit
+2668          ; Emoji                #  1.1  [1] (♨️)       hot springs
+267B          ; Emoji                #  3.2  [1] (♻️)       recycling symbol
+267E..267F    ; Emoji                #  4.1  [2] (♾️..♿)    infinity..wheelchair symbol
+2692..2697    ; Emoji                #  4.1  [6] (⚒️..⚗️)    hammer and pick..alembic
+2699          ; Emoji                #  4.1  [1] (⚙️)       gear
+269B..269C    ; Emoji                #  4.1  [2] (⚛️..⚜️)    atom symbol..fleur-de-lis
+26A0..26A1    ; Emoji                #  4.0  [2] (⚠️..⚡)    warning..high voltage
+26AA..26AB    ; Emoji                #  4.1  [2] (⚪..⚫)    white circle..black circle
+26B0..26B1    ; Emoji                #  4.1  [2] (⚰️..⚱️)    coffin..funeral urn
+26BD..26BE    ; Emoji                #  5.2  [2] (⚽..⚾)    soccer ball..baseball
+26C4..26C5    ; Emoji                #  5.2  [2] (⛄..⛅)    snowman without snow..sun behind cloud
+26C8          ; Emoji                #  5.2  [1] (⛈️)       cloud with lightning and rain
+26CE          ; Emoji                #  6.0  [1] (⛎)       Ophiuchus
+26CF          ; Emoji                #  5.2  [1] (⛏️)       pick
+26D1          ; Emoji                #  5.2  [1] (⛑️)       rescue worker’s helmet
+26D3..26D4    ; Emoji                #  5.2  [2] (⛓️..⛔)    chains..no entry
+26E9..26EA    ; Emoji                #  5.2  [2] (⛩️..⛪)    shinto shrine..church
+26F0..26F5    ; Emoji                #  5.2  [6] (⛰️..⛵)    mountain..sailboat
+26F7..26FA    ; Emoji                #  5.2  [4] (⛷️..⛺)    skier..tent
+26FD          ; Emoji                #  5.2  [1] (⛽)       fuel pump
+2702          ; Emoji                #  1.1  [1] (✂️)       scissors
+2705          ; Emoji                #  6.0  [1] (✅)       check mark button
+2708..2709    ; Emoji                #  1.1  [2] (✈️..✉️)    airplane..envelope
+270A..270B    ; Emoji                #  6.0  [2] (✊..✋)    raised fist..raised hand
+270C..270D    ; Emoji                #  1.1  [2] (✌️..✍️)    victory hand..writing hand
+270F          ; Emoji                #  1.1  [1] (✏️)       pencil
+2712          ; Emoji                #  1.1  [1] (✒️)       black nib
+2714          ; Emoji                #  1.1  [1] (✔️)       check mark
+2716          ; Emoji                #  1.1  [1] (✖️)       multiplication sign
+271D          ; Emoji                #  1.1  [1] (✝️)       latin cross
+2721          ; Emoji                #  1.1  [1] (✡️)       star of David
+2728          ; Emoji                #  6.0  [1] (✨)       sparkles
+2733..2734    ; Emoji                #  1.1  [2] (✳️..✴️)    eight-spoked asterisk..eight-pointed star
+2744          ; Emoji                #  1.1  [1] (❄️)       snowflake
+2747          ; Emoji                #  1.1  [1] (❇️)       sparkle
+274C          ; Emoji                #  6.0  [1] (❌)       cross mark
+274E          ; Emoji                #  6.0  [1] (❎)       cross mark button
+2753..2755    ; Emoji                #  6.0  [3] (❓..❕)    question mark..white exclamation mark
+2757          ; Emoji                #  5.2  [1] (❗)       exclamation mark
+2763..2764    ; Emoji                #  1.1  [2] (❣️..❤️)    heart exclamation..red heart
+2795..2797    ; Emoji                #  6.0  [3] (➕..➗)    plus sign..division sign
+27A1          ; Emoji                #  1.1  [1] (➡️)       right arrow
+27B0          ; Emoji                #  6.0  [1] (➰)       curly loop
+27BF          ; Emoji                #  6.0  [1] (➿)       double curly loop
+2934..2935    ; Emoji                #  3.2  [2] (⤴️..⤵️)    right arrow curving up..right arrow curving down
+2B05..2B07    ; Emoji                #  4.0  [3] (⬅️..⬇️)    left arrow..down arrow
+2B1B..2B1C    ; Emoji                #  5.1  [2] (⬛..⬜)    black large square..white large square
+2B50          ; Emoji                #  5.1  [1] (⭐)       star
+2B55          ; Emoji                #  5.2  [1] (⭕)       hollow red circle
+3030          ; Emoji                #  1.1  [1] (〰️)       wavy dash
+303D          ; Emoji                #  3.2  [1] (〽️)       part alternation mark
+3297          ; Emoji                #  1.1  [1] (㊗️)       Japanese “congratulations” button
+3299          ; Emoji                #  1.1  [1] (㊙️)       Japanese “secret” button
+1F004         ; Emoji                #  5.1  [1] (🀄)       mahjong red dragon
+1F0CF         ; Emoji                #  6.0  [1] (🃏)       joker
+1F170..1F171  ; Emoji                #  6.0  [2] (🅰️..🅱️)    A button (blood type)..B button (blood type)
+1F17E         ; Emoji                #  6.0  [1] (🅾️)       O button (blood type)
+1F17F         ; Emoji                #  5.2  [1] (🅿️)       P button
+1F18E         ; Emoji                #  6.0  [1] (🆎)       AB button (blood type)
+1F191..1F19A  ; Emoji                #  6.0 [10] (🆑..🆚)    CL button..VS button
+1F1E6..1F1FF  ; Emoji                #  6.0 [26] (🇦..🇿)    regional indicator symbol letter a..regional indicator symbol letter z
+1F201..1F202  ; Emoji                #  6.0  [2] (🈁..🈂️)    Japanese “here” button..Japanese “service charge” button
+1F21A         ; Emoji                #  5.2  [1] (🈚)       Japanese “free of charge” button
+1F22F         ; Emoji                #  5.2  [1] (🈯)       Japanese “reserved” button
+1F232..1F23A  ; Emoji                #  6.0  [9] (🈲..🈺)    Japanese “prohibited” button..Japanese “open for business” button
+1F250..1F251  ; Emoji                #  6.0  [2] (🉐..🉑)    Japanese “bargain” button..Japanese “acceptable” button
+1F300..1F320  ; Emoji                #  6.0 [33] (🌀..🌠)    cyclone..shooting star
+1F321         ; Emoji                #  7.0  [1] (🌡️)       thermometer
+1F324..1F32C  ; Emoji                #  7.0  [9] (🌤️..🌬️)    sun behind small cloud..wind face
+1F32D..1F32F  ; Emoji                #  8.0  [3] (🌭..🌯)    hot dog..burrito
+1F330..1F335  ; Emoji                #  6.0  [6] (🌰..🌵)    chestnut..cactus
+1F336         ; Emoji                #  7.0  [1] (🌶️)       hot pepper
+1F337..1F37C  ; Emoji                #  6.0 [70] (🌷..🍼)    tulip..baby bottle
+1F37D         ; Emoji                #  7.0  [1] (🍽️)       fork and knife with plate
+1F37E..1F37F  ; Emoji                #  8.0  [2] (🍾..🍿)    bottle with popping cork..popcorn
+1F380..1F393  ; Emoji                #  6.0 [20] (🎀..🎓)    ribbon..graduation cap
+1F396..1F397  ; Emoji                #  7.0  [2] (🎖️..🎗️)    military medal..reminder ribbon
+1F399..1F39B  ; Emoji                #  7.0  [3] (🎙️..🎛️)    studio microphone..control knobs
+1F39E..1F39F  ; Emoji                #  7.0  [2] (🎞️..🎟️)    film frames..admission tickets
+1F3A0..1F3C4  ; Emoji                #  6.0 [37] (🎠..🏄)    carousel horse..person surfing
+1F3C5         ; Emoji                #  7.0  [1] (🏅)       sports medal
+1F3C6..1F3CA  ; Emoji                #  6.0  [5] (🏆..🏊)    trophy..person swimming
+1F3CB..1F3CE  ; Emoji                #  7.0  [4] (🏋️..🏎️)    person lifting weights..racing car
+1F3CF..1F3D3  ; Emoji                #  8.0  [5] (🏏..🏓)    cricket game..ping pong
+1F3D4..1F3DF  ; Emoji                #  7.0 [12] (🏔️..🏟️)    snow-capped mountain..stadium
+1F3E0..1F3F0  ; Emoji                #  6.0 [17] (🏠..🏰)    house..castle
+1F3F3..1F3F5  ; Emoji                #  7.0  [3] (🏳️..🏵️)    white flag..rosette
+1F3F7         ; Emoji                #  7.0  [1] (🏷️)       label
+1F3F8..1F3FF  ; Emoji                #  8.0  [8] (🏸..🏿)    badminton..dark skin tone
+1F400..1F43E  ; Emoji                #  6.0 [63] (🐀..🐾)    rat..paw prints
+1F43F         ; Emoji                #  7.0  [1] (🐿️)       chipmunk
+1F440         ; Emoji                #  6.0  [1] (👀)       eyes
+1F441         ; Emoji                #  7.0  [1] (👁️)       eye
+1F442..1F4F7  ; Emoji                #  6.0[182] (👂..📷)    ear..camera
+1F4F8         ; Emoji                #  7.0  [1] (📸)       camera with flash
+1F4F9..1F4FC  ; Emoji                #  6.0  [4] (📹..📼)    video camera..videocassette
+1F4FD         ; Emoji                #  7.0  [1] (📽️)       film projector
+1F4FF         ; Emoji                #  8.0  [1] (📿)       prayer beads
+1F500..1F53D  ; Emoji                #  6.0 [62] (🔀..🔽)    shuffle tracks button..downwards button
+1F549..1F54A  ; Emoji                #  7.0  [2] (🕉️..🕊️)    om..dove
+1F54B..1F54E  ; Emoji                #  8.0  [4] (🕋..🕎)    kaaba..menorah
+1F550..1F567  ; Emoji                #  6.0 [24] (🕐..🕧)    one o’clock..twelve-thirty
+1F56F..1F570  ; Emoji                #  7.0  [2] (🕯️..🕰️)    candle..mantelpiece clock
+1F573..1F579  ; Emoji                #  7.0  [7] (🕳️..🕹️)    hole..joystick
+1F57A         ; Emoji                #  9.0  [1] (🕺)       man dancing
+1F587         ; Emoji                #  7.0  [1] (🖇️)       linked paperclips
+1F58A..1F58D  ; Emoji                #  7.0  [4] (🖊️..🖍️)    pen..crayon
+1F590         ; Emoji                #  7.0  [1] (🖐️)       hand with fingers splayed
+1F595..1F596  ; Emoji                #  7.0  [2] (🖕..🖖)    middle finger..vulcan salute
+1F5A4         ; Emoji                #  9.0  [1] (🖤)       black heart
+1F5A5         ; Emoji                #  7.0  [1] (🖥️)       desktop computer
+1F5A8         ; Emoji                #  7.0  [1] (🖨️)       printer
+1F5B1..1F5B2  ; Emoji                #  7.0  [2] (🖱️..🖲️)    computer mouse..trackball
+1F5BC         ; Emoji                #  7.0  [1] (🖼️)       framed picture
+1F5C2..1F5C4  ; Emoji                #  7.0  [3] (🗂️..🗄️)    card index dividers..file cabinet
+1F5D1..1F5D3  ; Emoji                #  7.0  [3] (🗑️..🗓️)    wastebasket..spiral calendar
+1F5DC..1F5DE  ; Emoji                #  7.0  [3] (🗜️..🗞️)    clamp..rolled-up newspaper
+1F5E1         ; Emoji                #  7.0  [1] (🗡️)       dagger
+1F5E3         ; Emoji                #  7.0  [1] (🗣️)       speaking head
+1F5E8         ; Emoji                #  7.0  [1] (🗨️)       left speech bubble
+1F5EF         ; Emoji                #  7.0  [1] (🗯️)       right anger bubble
+1F5F3         ; Emoji                #  7.0  [1] (🗳️)       ballot box with ballot
+1F5FA         ; Emoji                #  7.0  [1] (🗺️)       world map
+1F5FB..1F5FF  ; Emoji                #  6.0  [5] (🗻..🗿)    mount fuji..moai
+1F600         ; Emoji                #  6.1  [1] (😀)       grinning face
+1F601..1F610  ; Emoji                #  6.0 [16] (😁..😐)    beaming face with smiling eyes..neutral face
+1F611         ; Emoji                #  6.1  [1] (😑)       expressionless face
+1F612..1F614  ; Emoji                #  6.0  [3] (😒..😔)    unamused face..pensive face
+1F615         ; Emoji                #  6.1  [1] (😕)       confused face
+1F616         ; Emoji                #  6.0  [1] (😖)       confounded face
+1F617         ; Emoji                #  6.1  [1] (😗)       kissing face
+1F618         ; Emoji                #  6.0  [1] (😘)       face blowing a kiss
+1F619         ; Emoji                #  6.1  [1] (😙)       kissing face with smiling eyes
+1F61A         ; Emoji                #  6.0  [1] (😚)       kissing face with closed eyes
+1F61B         ; Emoji                #  6.1  [1] (😛)       face with tongue
+1F61C..1F61E  ; Emoji                #  6.0  [3] (😜..😞)    winking face with tongue..disappointed face
+1F61F         ; Emoji                #  6.1  [1] (😟)       worried face
+1F620..1F625  ; Emoji                #  6.0  [6] (😠..😥)    angry face..sad but relieved face
+1F626..1F627  ; Emoji                #  6.1  [2] (😦..😧)    frowning face with open mouth..anguished face
+1F628..1F62B  ; Emoji                #  6.0  [4] (😨..😫)    fearful face..tired face
+1F62C         ; Emoji                #  6.1  [1] (😬)       grimacing face
+1F62D         ; Emoji                #  6.0  [1] (😭)       loudly crying face
+1F62E..1F62F  ; Emoji                #  6.1  [2] (😮..😯)    face with open mouth..hushed face
+1F630..1F633  ; Emoji                #  6.0  [4] (😰..😳)    anxious face with sweat..flushed face
+1F634         ; Emoji                #  6.1  [1] (😴)       sleeping face
+1F635..1F640  ; Emoji                #  6.0 [12] (😵..🙀)    dizzy face..weary cat
+1F641..1F642  ; Emoji                #  7.0  [2] (🙁..🙂)    slightly frowning face..slightly smiling face
+1F643..1F644  ; Emoji                #  8.0  [2] (🙃..🙄)    upside-down face..face with rolling eyes
+1F645..1F64F  ; Emoji                #  6.0 [11] (🙅..🙏)    person gesturing NO..folded hands
+1F680..1F6C5  ; Emoji                #  6.0 [70] (🚀..🛅)    rocket..left luggage
+1F6CB..1F6CF  ; Emoji                #  7.0  [5] (🛋️..🛏️)    couch and lamp..bed
+1F6D0         ; Emoji                #  8.0  [1] (🛐)       place of worship
+1F6D1..1F6D2  ; Emoji                #  9.0  [2] (🛑..🛒)    stop sign..shopping cart
+1F6D5         ; Emoji                # 12.0  [1] (🛕)       hindu temple
+1F6E0..1F6E5  ; Emoji                #  7.0  [6] (🛠️..🛥️)    hammer and wrench..motor boat
+1F6E9         ; Emoji                #  7.0  [1] (🛩️)       small airplane
+1F6EB..1F6EC  ; Emoji                #  7.0  [2] (🛫..🛬)    airplane departure..airplane arrival
+1F6F0         ; Emoji                #  7.0  [1] (🛰️)       satellite
+1F6F3         ; Emoji                #  7.0  [1] (🛳️)       passenger ship
+1F6F4..1F6F6  ; Emoji                #  9.0  [3] (🛴..🛶)    kick scooter..canoe
+1F6F7..1F6F8  ; Emoji                # 10.0  [2] (🛷..🛸)    sled..flying saucer
+1F6F9         ; Emoji                # 11.0  [1] (🛹)       skateboard
+1F6FA         ; Emoji                # 12.0  [1] (🛺)       auto rickshaw
+1F7E0..1F7EB  ; Emoji                # 12.0 [12] (🟠..🟫)    orange circle..brown square
+1F90D..1F90F  ; Emoji                # 12.0  [3] (🤍..🤏)    white heart..pinching hand
+1F910..1F918  ; Emoji                #  8.0  [9] (🤐..🤘)    zipper-mouth face..sign of the horns
+1F919..1F91E  ; Emoji                #  9.0  [6] (🤙..🤞)    call me hand..crossed fingers
+1F91F         ; Emoji                # 10.0  [1] (🤟)       love-you gesture
+1F920..1F927  ; Emoji                #  9.0  [8] (🤠..🤧)    cowboy hat face..sneezing face
+1F928..1F92F  ; Emoji                # 10.0  [8] (🤨..🤯)    face with raised eyebrow..exploding head
+1F930         ; Emoji                #  9.0  [1] (🤰)       pregnant woman
+1F931..1F932  ; Emoji                # 10.0  [2] (🤱..🤲)    breast-feeding..palms up together
+1F933..1F93A  ; Emoji                #  9.0  [8] (🤳..🤺)    selfie..person fencing
+1F93C..1F93E  ; Emoji                #  9.0  [3] (🤼..🤾)    people wrestling..person playing handball
+1F93F         ; Emoji                # 12.0  [1] (🤿)       diving mask
+1F940..1F945  ; Emoji                #  9.0  [6] (🥀..🥅)    wilted flower..goal net
+1F947..1F94B  ; Emoji                #  9.0  [5] (🥇..🥋)    1st place medal..martial arts uniform
+1F94C         ; Emoji                # 10.0  [1] (🥌)       curling stone
+1F94D..1F94F  ; Emoji                # 11.0  [3] (🥍..🥏)    lacrosse..flying disc
+1F950..1F95E  ; Emoji                #  9.0 [15] (🥐..🥞)    croissant..pancakes
+1F95F..1F96B  ; Emoji                # 10.0 [13] (🥟..🥫)    dumpling..canned food
+1F96C..1F970  ; Emoji                # 11.0  [5] (🥬..🥰)    leafy green..smiling face with hearts
+1F971         ; Emoji                # 12.0  [1] (🥱)       yawning face
+1F973..1F976  ; Emoji                # 11.0  [4] (🥳..🥶)    partying face..cold face
+1F97A         ; Emoji                # 11.0  [1] (🥺)       pleading face
+1F97B         ; Emoji                # 12.0  [1] (🥻)       sari
+1F97C..1F97F  ; Emoji                # 11.0  [4] (🥼..🥿)    lab coat..flat shoe
+1F980..1F984  ; Emoji                #  8.0  [5] (🦀..🦄)    crab..unicorn
+1F985..1F991  ; Emoji                #  9.0 [13] (🦅..🦑)    eagle..squid
+1F992..1F997  ; Emoji                # 10.0  [6] (🦒..🦗)    giraffe..cricket
+1F998..1F9A2  ; Emoji                # 11.0 [11] (🦘..🦢)    kangaroo..swan
+1F9A5..1F9AA  ; Emoji                # 12.0  [6] (🦥..🦪)    sloth..oyster
+1F9AE..1F9AF  ; Emoji                # 12.0  [2] (🦮..🦯)    guide dog..probing cane
+1F9B0..1F9B9  ; Emoji                # 11.0 [10] (🦰..🦹)    red hair..supervillain
+1F9BA..1F9BF  ; Emoji                # 12.0  [6] (🦺..🦿)    safety vest..mechanical leg
+1F9C0         ; Emoji                #  8.0  [1] (🧀)       cheese wedge
+1F9C1..1F9C2  ; Emoji                # 11.0  [2] (🧁..🧂)    cupcake..salt
+1F9C3..1F9CA  ; Emoji                # 12.0  [8] (🧃..🧊)    beverage box..ice cube
+1F9CD..1F9CF  ; Emoji                # 12.0  [3] (🧍..🧏)    person standing..deaf person
+1F9D0..1F9E6  ; Emoji                # 10.0 [23] (🧐..🧦)    face with monocle..socks
+1F9E7..1F9FF  ; Emoji                # 11.0 [25] (🧧..🧿)    red envelope..nazar amulet
+1FA70..1FA73  ; Emoji                # 12.0  [4] (🩰..🩳)    ballet shoes..shorts
+1FA78..1FA7A  ; Emoji                # 12.0  [3] (🩸..🩺)    drop of blood..stethoscope
+1FA80..1FA82  ; Emoji                # 12.0  [3] (🪀..🪂)    yo-yo..parachute
+1FA90..1FA95  ; Emoji                # 12.0  [6] (🪐..🪕)    ringed planet..banjo
+
+# Total elements: 1311
+
+# ================================================
+
+# All omitted code points have Emoji_Presentation=No 
+# @missing: 0000..10FFFF  ; Emoji_Presentation ; No
+
+231A..231B    ; Emoji_Presentation   #  1.1  [2] (⌚..⌛)    watch..hourglass done
+23E9..23EC    ; Emoji_Presentation   #  6.0  [4] (⏩..⏬)    fast-forward button..fast down button
+23F0          ; Emoji_Presentation   #  6.0  [1] (⏰)       alarm clock
+23F3          ; Emoji_Presentation   #  6.0  [1] (⏳)       hourglass not done
+25FD..25FE    ; Emoji_Presentation   #  3.2  [2] (◽..◾)    white medium-small square..black medium-small square
+2614..2615    ; Emoji_Presentation   #  4.0  [2] (☔..☕)    umbrella with rain drops..hot beverage
+2648..2653    ; Emoji_Presentation   #  1.1 [12] (♈..♓)    Aries..Pisces
+267F          ; Emoji_Presentation   #  4.1  [1] (♿)       wheelchair symbol
+2693          ; Emoji_Presentation   #  4.1  [1] (⚓)       anchor
+26A1          ; Emoji_Presentation   #  4.0  [1] (⚡)       high voltage
+26AA..26AB    ; Emoji_Presentation   #  4.1  [2] (⚪..⚫)    white circle..black circle
+26BD..26BE    ; Emoji_Presentation   #  5.2  [2] (⚽..⚾)    soccer ball..baseball
+26C4..26C5    ; Emoji_Presentation   #  5.2  [2] (⛄..⛅)    snowman without snow..sun behind cloud
+26CE          ; Emoji_Presentation   #  6.0  [1] (⛎)       Ophiuchus
+26D4          ; Emoji_Presentation   #  5.2  [1] (⛔)       no entry
+26EA          ; Emoji_Presentation   #  5.2  [1] (⛪)       church
+26F2..26F3    ; Emoji_Presentation   #  5.2  [2] (⛲..⛳)    fountain..flag in hole
+26F5          ; Emoji_Presentation   #  5.2  [1] (⛵)       sailboat
+26FA          ; Emoji_Presentation   #  5.2  [1] (⛺)       tent
+26FD          ; Emoji_Presentation   #  5.2  [1] (⛽)       fuel pump
+2705          ; Emoji_Presentation   #  6.0  [1] (✅)       check mark button
+270A..270B    ; Emoji_Presentation   #  6.0  [2] (✊..✋)    raised fist..raised hand
+2728          ; Emoji_Presentation   #  6.0  [1] (✨)       sparkles
+274C          ; Emoji_Presentation   #  6.0  [1] (❌)       cross mark
+274E          ; Emoji_Presentation   #  6.0  [1] (❎)       cross mark button
+2753..2755    ; Emoji_Presentation   #  6.0  [3] (❓..❕)    question mark..white exclamation mark
+2757          ; Emoji_Presentation   #  5.2  [1] (❗)       exclamation mark
+2795..2797    ; Emoji_Presentation   #  6.0  [3] (➕..➗)    plus sign..division sign
+27B0          ; Emoji_Presentation   #  6.0  [1] (➰)       curly loop
+27BF          ; Emoji_Presentation   #  6.0  [1] (➿)       double curly loop
+2B1B..2B1C    ; Emoji_Presentation   #  5.1  [2] (⬛..⬜)    black large square..white large square
+2B50          ; Emoji_Presentation   #  5.1  [1] (⭐)       star
+2B55          ; Emoji_Presentation   #  5.2  [1] (⭕)       hollow red circle
+1F004         ; Emoji_Presentation   #  5.1  [1] (🀄)       mahjong red dragon
+1F0CF         ; Emoji_Presentation   #  6.0  [1] (🃏)       joker
+1F18E         ; Emoji_Presentation   #  6.0  [1] (🆎)       AB button (blood type)
+1F191..1F19A  ; Emoji_Presentation   #  6.0 [10] (🆑..🆚)    CL button..VS button
+1F1E6..1F1FF  ; Emoji_Presentation   #  6.0 [26] (🇦..🇿)    regional indicator symbol letter a..regional indicator symbol letter z
+1F201         ; Emoji_Presentation   #  6.0  [1] (🈁)       Japanese “here” button
+1F21A         ; Emoji_Presentation   #  5.2  [1] (🈚)       Japanese “free of charge” button
+1F22F         ; Emoji_Presentation   #  5.2  [1] (🈯)       Japanese “reserved” button
+1F232..1F236  ; Emoji_Presentation   #  6.0  [5] (🈲..🈶)    Japanese “prohibited” button..Japanese “not free of charge” button
+1F238..1F23A  ; Emoji_Presentation   #  6.0  [3] (🈸..🈺)    Japanese “application” button..Japanese “open for business” button
+1F250..1F251  ; Emoji_Presentation   #  6.0  [2] (🉐..🉑)    Japanese “bargain” button..Japanese “acceptable” button
+1F300..1F320  ; Emoji_Presentation   #  6.0 [33] (🌀..🌠)    cyclone..shooting star
+1F32D..1F32F  ; Emoji_Presentation   #  8.0  [3] (🌭..🌯)    hot dog..burrito
+1F330..1F335  ; Emoji_Presentation   #  6.0  [6] (🌰..🌵)    chestnut..cactus
+1F337..1F37C  ; Emoji_Presentation   #  6.0 [70] (🌷..🍼)    tulip..baby bottle
+1F37E..1F37F  ; Emoji_Presentation   #  8.0  [2] (🍾..🍿)    bottle with popping cork..popcorn
+1F380..1F393  ; Emoji_Presentation   #  6.0 [20] (🎀..🎓)    ribbon..graduation cap
+1F3A0..1F3C4  ; Emoji_Presentation   #  6.0 [37] (🎠..🏄)    carousel horse..person surfing
+1F3C5         ; Emoji_Presentation   #  7.0  [1] (🏅)       sports medal
+1F3C6..1F3CA  ; Emoji_Presentation   #  6.0  [5] (🏆..🏊)    trophy..person swimming
+1F3CF..1F3D3  ; Emoji_Presentation   #  8.0  [5] (🏏..🏓)    cricket game..ping pong
+1F3E0..1F3F0  ; Emoji_Presentation   #  6.0 [17] (🏠..🏰)    house..castle
+1F3F4         ; Emoji_Presentation   #  7.0  [1] (🏴)       black flag
+1F3F8..1F3FF  ; Emoji_Presentation   #  8.0  [8] (🏸..🏿)    badminton..dark skin tone
+1F400..1F43E  ; Emoji_Presentation   #  6.0 [63] (🐀..🐾)    rat..paw prints
+1F440         ; Emoji_Presentation   #  6.0  [1] (👀)       eyes
+1F442..1F4F7  ; Emoji_Presentation   #  6.0[182] (👂..📷)    ear..camera
+1F4F8         ; Emoji_Presentation   #  7.0  [1] (📸)       camera with flash
+1F4F9..1F4FC  ; Emoji_Presentation   #  6.0  [4] (📹..📼)    video camera..videocassette
+1F4FF         ; Emoji_Presentation   #  8.0  [1] (📿)       prayer beads
+1F500..1F53D  ; Emoji_Presentation   #  6.0 [62] (🔀..🔽)    shuffle tracks button..downwards button
+1F54B..1F54E  ; Emoji_Presentation   #  8.0  [4] (🕋..🕎)    kaaba..menorah
+1F550..1F567  ; Emoji_Presentation   #  6.0 [24] (🕐..🕧)    one o’clock..twelve-thirty
+1F57A         ; Emoji_Presentation   #  9.0  [1] (🕺)       man dancing
+1F595..1F596  ; Emoji_Presentation   #  7.0  [2] (🖕..🖖)    middle finger..vulcan salute
+1F5A4         ; Emoji_Presentation   #  9.0  [1] (🖤)       black heart
+1F5FB..1F5FF  ; Emoji_Presentation   #  6.0  [5] (🗻..🗿)    mount fuji..moai
+1F600         ; Emoji_Presentation   #  6.1  [1] (😀)       grinning face
+1F601..1F610  ; Emoji_Presentation   #  6.0 [16] (😁..😐)    beaming face with smiling eyes..neutral face
+1F611         ; Emoji_Presentation   #  6.1  [1] (😑)       expressionless face
+1F612..1F614  ; Emoji_Presentation   #  6.0  [3] (😒..😔)    unamused face..pensive face
+1F615         ; Emoji_Presentation   #  6.1  [1] (😕)       confused face
+1F616         ; Emoji_Presentation   #  6.0  [1] (😖)       confounded face
+1F617         ; Emoji_Presentation   #  6.1  [1] (😗)       kissing face
+1F618         ; Emoji_Presentation   #  6.0  [1] (😘)       face blowing a kiss
+1F619         ; Emoji_Presentation   #  6.1  [1] (😙)       kissing face with smiling eyes
+1F61A         ; Emoji_Presentation   #  6.0  [1] (😚)       kissing face with closed eyes
+1F61B         ; Emoji_Presentation   #  6.1  [1] (😛)       face with tongue
+1F61C..1F61E  ; Emoji_Presentation   #  6.0  [3] (😜..😞)    winking face with tongue..disappointed face
+1F61F         ; Emoji_Presentation   #  6.1  [1] (😟)       worried face
+1F620..1F625  ; Emoji_Presentation   #  6.0  [6] (😠..😥)    angry face..sad but relieved face
+1F626..1F627  ; Emoji_Presentation   #  6.1  [2] (😦..😧)    frowning face with open mouth..anguished face
+1F628..1F62B  ; Emoji_Presentation   #  6.0  [4] (😨..😫)    fearful face..tired face
+1F62C         ; Emoji_Presentation   #  6.1  [1] (😬)       grimacing face
+1F62D         ; Emoji_Presentation   #  6.0  [1] (😭)       loudly crying face
+1F62E..1F62F  ; Emoji_Presentation   #  6.1  [2] (😮..😯)    face with open mouth..hushed face
+1F630..1F633  ; Emoji_Presentation   #  6.0  [4] (😰..😳)    anxious face with sweat..flushed face
+1F634         ; Emoji_Presentation   #  6.1  [1] (😴)       sleeping face
+1F635..1F640  ; Emoji_Presentation   #  6.0 [12] (😵..🙀)    dizzy face..weary cat
+1F641..1F642  ; Emoji_Presentation   #  7.0  [2] (🙁..🙂)    slightly frowning face..slightly smiling face
+1F643..1F644  ; Emoji_Presentation   #  8.0  [2] (🙃..🙄)    upside-down face..face with rolling eyes
+1F645..1F64F  ; Emoji_Presentation   #  6.0 [11] (🙅..🙏)    person gesturing NO..folded hands
+1F680..1F6C5  ; Emoji_Presentation   #  6.0 [70] (🚀..🛅)    rocket..left luggage
+1F6CC         ; Emoji_Presentation   #  7.0  [1] (🛌)       person in bed
+1F6D0         ; Emoji_Presentation   #  8.0  [1] (🛐)       place of worship
+1F6D1..1F6D2  ; Emoji_Presentation   #  9.0  [2] (🛑..🛒)    stop sign..shopping cart
+1F6D5         ; Emoji_Presentation   # 12.0  [1] (🛕)       hindu temple
+1F6EB..1F6EC  ; Emoji_Presentation   #  7.0  [2] (🛫..🛬)    airplane departure..airplane arrival
+1F6F4..1F6F6  ; Emoji_Presentation   #  9.0  [3] (🛴..🛶)    kick scooter..canoe
+1F6F7..1F6F8  ; Emoji_Presentation   # 10.0  [2] (🛷..🛸)    sled..flying saucer
+1F6F9         ; Emoji_Presentation   # 11.0  [1] (🛹)       skateboard
+1F6FA         ; Emoji_Presentation   # 12.0  [1] (🛺)       auto rickshaw
+1F7E0..1F7EB  ; Emoji_Presentation   # 12.0 [12] (🟠..🟫)    orange circle..brown square
+1F90D..1F90F  ; Emoji_Presentation   # 12.0  [3] (🤍..🤏)    white heart..pinching hand
+1F910..1F918  ; Emoji_Presentation   #  8.0  [9] (🤐..🤘)    zipper-mouth face..sign of the horns
+1F919..1F91E  ; Emoji_Presentation   #  9.0  [6] (🤙..🤞)    call me hand..crossed fingers
+1F91F         ; Emoji_Presentation   # 10.0  [1] (🤟)       love-you gesture
+1F920..1F927  ; Emoji_Presentation   #  9.0  [8] (🤠..🤧)    cowboy hat face..sneezing face
+1F928..1F92F  ; Emoji_Presentation   # 10.0  [8] (🤨..🤯)    face with raised eyebrow..exploding head
+1F930         ; Emoji_Presentation   #  9.0  [1] (🤰)       pregnant woman
+1F931..1F932  ; Emoji_Presentation   # 10.0  [2] (🤱..🤲)    breast-feeding..palms up together
+1F933..1F93A  ; Emoji_Presentation   #  9.0  [8] (🤳..🤺)    selfie..person fencing
+1F93C..1F93E  ; Emoji_Presentation   #  9.0  [3] (🤼..🤾)    people wrestling..person playing handball
+1F93F         ; Emoji_Presentation   # 12.0  [1] (🤿)       diving mask
+1F940..1F945  ; Emoji_Presentation   #  9.0  [6] (🥀..🥅)    wilted flower..goal net
+1F947..1F94B  ; Emoji_Presentation   #  9.0  [5] (🥇..🥋)    1st place medal..martial arts uniform
+1F94C         ; Emoji_Presentation   # 10.0  [1] (🥌)       curling stone
+1F94D..1F94F  ; Emoji_Presentation   # 11.0  [3] (🥍..🥏)    lacrosse..flying disc
+1F950..1F95E  ; Emoji_Presentation   #  9.0 [15] (🥐..🥞)    croissant..pancakes
+1F95F..1F96B  ; Emoji_Presentation   # 10.0 [13] (🥟..🥫)    dumpling..canned food
+1F96C..1F970  ; Emoji_Presentation   # 11.0  [5] (🥬..🥰)    leafy green..smiling face with hearts
+1F971         ; Emoji_Presentation   # 12.0  [1] (🥱)       yawning face
+1F973..1F976  ; Emoji_Presentation   # 11.0  [4] (🥳..🥶)    partying face..cold face
+1F97A         ; Emoji_Presentation   # 11.0  [1] (🥺)       pleading face
+1F97B         ; Emoji_Presentation   # 12.0  [1] (🥻)       sari
+1F97C..1F97F  ; Emoji_Presentation   # 11.0  [4] (🥼..🥿)    lab coat..flat shoe
+1F980..1F984  ; Emoji_Presentation   #  8.0  [5] (🦀..🦄)    crab..unicorn
+1F985..1F991  ; Emoji_Presentation   #  9.0 [13] (🦅..🦑)    eagle..squid
+1F992..1F997  ; Emoji_Presentation   # 10.0  [6] (🦒..🦗)    giraffe..cricket
+1F998..1F9A2  ; Emoji_Presentation   # 11.0 [11] (🦘..🦢)    kangaroo..swan
+1F9A5..1F9AA  ; Emoji_Presentation   # 12.0  [6] (🦥..🦪)    sloth..oyster
+1F9AE..1F9AF  ; Emoji_Presentation   # 12.0  [2] (🦮..🦯)    guide dog..probing cane
+1F9B0..1F9B9  ; Emoji_Presentation   # 11.0 [10] (🦰..🦹)    red hair..supervillain
+1F9BA..1F9BF  ; Emoji_Presentation   # 12.0  [6] (🦺..🦿)    safety vest..mechanical leg
+1F9C0         ; Emoji_Presentation   #  8.0  [1] (🧀)       cheese wedge
+1F9C1..1F9C2  ; Emoji_Presentation   # 11.0  [2] (🧁..🧂)    cupcake..salt
+1F9C3..1F9CA  ; Emoji_Presentation   # 12.0  [8] (🧃..🧊)    beverage box..ice cube
+1F9CD..1F9CF  ; Emoji_Presentation   # 12.0  [3] (🧍..🧏)    person standing..deaf person
+1F9D0..1F9E6  ; Emoji_Presentation   # 10.0 [23] (🧐..🧦)    face with monocle..socks
+1F9E7..1F9FF  ; Emoji_Presentation   # 11.0 [25] (🧧..🧿)    red envelope..nazar amulet
+1FA70..1FA73  ; Emoji_Presentation   # 12.0  [4] (🩰..🩳)    ballet shoes..shorts
+1FA78..1FA7A  ; Emoji_Presentation   # 12.0  [3] (🩸..🩺)    drop of blood..stethoscope
+1FA80..1FA82  ; Emoji_Presentation   # 12.0  [3] (🪀..🪂)    yo-yo..parachute
+1FA90..1FA95  ; Emoji_Presentation   # 12.0  [6] (🪐..🪕)    ringed planet..banjo
+
+# Total elements: 1093
+
+# ================================================
+
+# All omitted code points have Emoji_Modifier=No 
+# @missing: 0000..10FFFF  ; Emoji_Modifier ; No
+
+1F3FB..1F3FF  ; Emoji_Modifier       #  8.0  [5] (🏻..🏿)    light skin tone..dark skin tone
+
+# Total elements: 5
+
+# ================================================
+
+# All omitted code points have Emoji_Modifier_Base=No 
+# @missing: 0000..10FFFF  ; Emoji_Modifier_Base ; No
+
+261D          ; Emoji_Modifier_Base  #  1.1  [1] (☝️)       index pointing up
+26F9          ; Emoji_Modifier_Base  #  5.2  [1] (⛹️)       person bouncing ball
+270A..270B    ; Emoji_Modifier_Base  #  6.0  [2] (✊..✋)    raised fist..raised hand
+270C..270D    ; Emoji_Modifier_Base  #  1.1  [2] (✌️..✍️)    victory hand..writing hand
+1F385         ; Emoji_Modifier_Base  #  6.0  [1] (🎅)       Santa Claus
+1F3C2..1F3C4  ; Emoji_Modifier_Base  #  6.0  [3] (🏂..🏄)    snowboarder..person surfing
+1F3C7         ; Emoji_Modifier_Base  #  6.0  [1] (🏇)       horse racing
+1F3CA         ; Emoji_Modifier_Base  #  6.0  [1] (🏊)       person swimming
+1F3CB..1F3CC  ; Emoji_Modifier_Base  #  7.0  [2] (🏋️..🏌️)    person lifting weights..person golfing
+1F442..1F443  ; Emoji_Modifier_Base  #  6.0  [2] (👂..👃)    ear..nose
+1F446..1F450  ; Emoji_Modifier_Base  #  6.0 [11] (👆..👐)    backhand index pointing up..open hands
+1F466..1F478  ; Emoji_Modifier_Base  #  6.0 [19] (👦..👸)    boy..princess
+1F47C         ; Emoji_Modifier_Base  #  6.0  [1] (👼)       baby angel
+1F481..1F483  ; Emoji_Modifier_Base  #  6.0  [3] (💁..💃)    person tipping hand..woman dancing
+1F485..1F487  ; Emoji_Modifier_Base  #  6.0  [3] (💅..💇)    nail polish..person getting haircut
+1F48F         ; Emoji_Modifier_Base  #  6.0  [1] (💏)       kiss
+1F491         ; Emoji_Modifier_Base  #  6.0  [1] (💑)       couple with heart
+1F4AA         ; Emoji_Modifier_Base  #  6.0  [1] (💪)       flexed biceps
+1F574..1F575  ; Emoji_Modifier_Base  #  7.0  [2] (🕴️..🕵️)    man in suit levitating..detective
+1F57A         ; Emoji_Modifier_Base  #  9.0  [1] (🕺)       man dancing
+1F590         ; Emoji_Modifier_Base  #  7.0  [1] (🖐️)       hand with fingers splayed
+1F595..1F596  ; Emoji_Modifier_Base  #  7.0  [2] (🖕..🖖)    middle finger..vulcan salute
+1F645..1F647  ; Emoji_Modifier_Base  #  6.0  [3] (🙅..🙇)    person gesturing NO..person bowing
+1F64B..1F64F  ; Emoji_Modifier_Base  #  6.0  [5] (🙋..🙏)    person raising hand..folded hands
+1F6A3         ; Emoji_Modifier_Base  #  6.0  [1] (🚣)       person rowing boat
+1F6B4..1F6B6  ; Emoji_Modifier_Base  #  6.0  [3] (🚴..🚶)    person biking..person walking
+1F6C0         ; Emoji_Modifier_Base  #  6.0  [1] (🛀)       person taking bath
+1F6CC         ; Emoji_Modifier_Base  #  7.0  [1] (🛌)       person in bed
+1F90F         ; Emoji_Modifier_Base  # 12.0  [1] (🤏)       pinching hand
+1F918         ; Emoji_Modifier_Base  #  8.0  [1] (🤘)       sign of the horns
+1F919..1F91E  ; Emoji_Modifier_Base  #  9.0  [6] (🤙..🤞)    call me hand..crossed fingers
+1F91F         ; Emoji_Modifier_Base  # 10.0  [1] (🤟)       love-you gesture
+1F926         ; Emoji_Modifier_Base  #  9.0  [1] (🤦)       person facepalming
+1F930         ; Emoji_Modifier_Base  #  9.0  [1] (🤰)       pregnant woman
+1F931..1F932  ; Emoji_Modifier_Base  # 10.0  [2] (🤱..🤲)    breast-feeding..palms up together
+1F933..1F939  ; Emoji_Modifier_Base  #  9.0  [7] (🤳..🤹)    selfie..person juggling
+1F93C..1F93E  ; Emoji_Modifier_Base  #  9.0  [3] (🤼..🤾)    people wrestling..person playing handball
+1F9B5..1F9B6  ; Emoji_Modifier_Base  # 11.0  [2] (🦵..🦶)    leg..foot
+1F9B8..1F9B9  ; Emoji_Modifier_Base  # 11.0  [2] (🦸..🦹)    superhero..supervillain
+1F9BB         ; Emoji_Modifier_Base  # 12.0  [1] (🦻)       ear with hearing aid
+1F9CD..1F9CF  ; Emoji_Modifier_Base  # 12.0  [3] (🧍..🧏)    person standing..deaf person
+1F9D1..1F9DD  ; Emoji_Modifier_Base  # 10.0 [13] (🧑..🧝)    person..elf
+
+# Total elements: 120
+
+# ================================================
+
+# All omitted code points have Emoji_Component=No 
+# @missing: 0000..10FFFF  ; Emoji_Component ; No
+
+0023          ; Emoji_Component      #  1.1  [1] (#️)       number sign
+002A          ; Emoji_Component      #  1.1  [1] (*️)       asterisk
+0030..0039    ; Emoji_Component      #  1.1 [10] (0️..9️)    digit zero..digit nine
+200D          ; Emoji_Component      #  1.1  [1] (‍)        zero width joiner
+20E3          ; Emoji_Component      #  3.0  [1] (⃣)       combining enclosing keycap
+FE0F          ; Emoji_Component      #  3.2  [1] ()        VARIATION SELECTOR-16
+1F1E6..1F1FF  ; Emoji_Component      #  6.0 [26] (🇦..🇿)    regional indicator symbol letter a..regional indicator symbol letter z
+1F3FB..1F3FF  ; Emoji_Component      #  8.0  [5] (🏻..🏿)    light skin tone..dark skin tone
+1F9B0..1F9B3  ; Emoji_Component      # 11.0  [4] (🦰..🦳)    red hair..white hair
+E0020..E007F  ; Emoji_Component      #  3.1 [96] (󠀠..󠁿)      tag space..cancel tag
+
+# Total elements: 146
+
+# ================================================
+
+# All omitted code points have Extended_Pictographic=No 
+# @missing: 0000..10FFFF  ; Extended_Pictographic ; No
+
+00A9          ; Extended_Pictographic#  1.1  [1] (©️)       copyright
+00AE          ; Extended_Pictographic#  1.1  [1] (®️)       registered
+203C          ; Extended_Pictographic#  1.1  [1] (‼️)       double exclamation mark
+2049          ; Extended_Pictographic#  3.0  [1] (⁉️)       exclamation question mark
+2122          ; Extended_Pictographic#  1.1  [1] (™️)       trade mark
+2139          ; Extended_Pictographic#  3.0  [1] (ℹ️)       information
+2194..2199    ; Extended_Pictographic#  1.1  [6] (↔️..↙️)    left-right arrow..down-left arrow
+21A9..21AA    ; Extended_Pictographic#  1.1  [2] (↩️..↪️)    right arrow curving left..left arrow curving right
+231A..231B    ; Extended_Pictographic#  1.1  [2] (⌚..⌛)    watch..hourglass done
+2328          ; Extended_Pictographic#  1.1  [1] (⌨️)       keyboard
+2388          ; Extended_Pictographic#  3.0  [1] (⎈)       HELM SYMBOL
+23CF          ; Extended_Pictographic#  4.0  [1] (⏏️)       eject button
+23E9..23F3    ; Extended_Pictographic#  6.0 [11] (⏩..⏳)    fast-forward button..hourglass not done
+23F8..23FA    ; Extended_Pictographic#  7.0  [3] (⏸️..⏺️)    pause button..record button
+24C2          ; Extended_Pictographic#  1.1  [1] (Ⓜ️)       circled M
+25AA..25AB    ; Extended_Pictographic#  1.1  [2] (▪️..▫️)    black small square..white small square
+25B6          ; Extended_Pictographic#  1.1  [1] (▶️)       play button
+25C0          ; Extended_Pictographic#  1.1  [1] (◀️)       reverse button
+25FB..25FE    ; Extended_Pictographic#  3.2  [4] (◻️..◾)    white medium square..black medium-small square
+2600..2605    ; Extended_Pictographic#  1.1  [6] (☀️..★)    sun..BLACK STAR
+2607..2612    ; Extended_Pictographic#  1.1 [12] (☇..☒)    LIGHTNING..BALLOT BOX WITH X
+2614..2615    ; Extended_Pictographic#  4.0  [2] (☔..☕)    umbrella with rain drops..hot beverage
+2616..2617    ; Extended_Pictographic#  3.2  [2] (☖..☗)    WHITE SHOGI PIECE..BLACK SHOGI PIECE
+2618          ; Extended_Pictographic#  4.1  [1] (☘️)       shamrock
+2619          ; Extended_Pictographic#  3.0  [1] (☙)       REVERSED ROTATED FLORAL HEART BULLET
+261A..266F    ; Extended_Pictographic#  1.1 [86] (☚..♯)    BLACK LEFT POINTING INDEX..MUSIC SHARP SIGN
+2670..2671    ; Extended_Pictographic#  3.0  [2] (♰..♱)    WEST SYRIAC CROSS..EAST SYRIAC CROSS
+2672..267D    ; Extended_Pictographic#  3.2 [12] (♲..♽)    UNIVERSAL RECYCLING SYMBOL..PARTIALLY-RECYCLED PAPER SYMBOL
+267E..267F    ; Extended_Pictographic#  4.1  [2] (♾️..♿)    infinity..wheelchair symbol
+2680..2685    ; Extended_Pictographic#  3.2  [6] (⚀..⚅)    DIE FACE-1..DIE FACE-6
+2690..2691    ; Extended_Pictographic#  4.0  [2] (⚐..⚑)    WHITE FLAG..BLACK FLAG
+2692..269C    ; Extended_Pictographic#  4.1 [11] (⚒️..⚜️)    hammer and pick..fleur-de-lis
+269D          ; Extended_Pictographic#  5.1  [1] (⚝)       OUTLINED WHITE STAR
+269E..269F    ; Extended_Pictographic#  5.2  [2] (⚞..⚟)    THREE LINES CONVERGING RIGHT..THREE LINES CONVERGING LEFT
+26A0..26A1    ; Extended_Pictographic#  4.0  [2] (⚠️..⚡)    warning..high voltage
+26A2..26B1    ; Extended_Pictographic#  4.1 [16] (⚢..⚱️)    DOUBLED FEMALE SIGN..funeral urn
+26B2          ; Extended_Pictographic#  5.0  [1] (⚲)       NEUTER
+26B3..26BC    ; Extended_Pictographic#  5.1 [10] (⚳..⚼)    CERES..SESQUIQUADRATE
+26BD..26BF    ; Extended_Pictographic#  5.2  [3] (⚽..⚿)    soccer ball..SQUARED KEY
+26C0..26C3    ; Extended_Pictographic#  5.1  [4] (⛀..⛃)    WHITE DRAUGHTS MAN..BLACK DRAUGHTS KING
+26C4..26CD    ; Extended_Pictographic#  5.2 [10] (⛄..⛍)    snowman without snow..DISABLED CAR
+26CE          ; Extended_Pictographic#  6.0  [1] (⛎)       Ophiuchus
+26CF..26E1    ; Extended_Pictographic#  5.2 [19] (⛏️..⛡)    pick..RESTRICTED LEFT ENTRY-2
+26E2          ; Extended_Pictographic#  6.0  [1] (⛢)       ASTRONOMICAL SYMBOL FOR URANUS
+26E3          ; Extended_Pictographic#  5.2  [1] (⛣)       HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE
+26E4..26E7    ; Extended_Pictographic#  6.0  [4] (⛤..⛧)    PENTAGRAM..INVERTED PENTAGRAM
+26E8..26FF    ; Extended_Pictographic#  5.2 [24] (⛨..⛿)    BLACK CROSS ON SHIELD..WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE
+2700          ; Extended_Pictographic#  7.0  [1] (✀)       BLACK SAFETY SCISSORS
+2701..2704    ; Extended_Pictographic#  1.1  [4] (✁..✄)    UPPER BLADE SCISSORS..WHITE SCISSORS
+2705          ; Extended_Pictographic#  6.0  [1] (✅)       check mark button
+2708..2709    ; Extended_Pictographic#  1.1  [2] (✈️..✉️)    airplane..envelope
+270A..270B    ; Extended_Pictographic#  6.0  [2] (✊..✋)    raised fist..raised hand
+270C..2712    ; Extended_Pictographic#  1.1  [7] (✌️..✒️)    victory hand..black nib
+2714          ; Extended_Pictographic#  1.1  [1] (✔️)       check mark
+2716          ; Extended_Pictographic#  1.1  [1] (✖️)       multiplication sign
+271D          ; Extended_Pictographic#  1.1  [1] (✝️)       latin cross
+2721          ; Extended_Pictographic#  1.1  [1] (✡️)       star of David
+2728          ; Extended_Pictographic#  6.0  [1] (✨)       sparkles
+2733..2734    ; Extended_Pictographic#  1.1  [2] (✳️..✴️)    eight-spoked asterisk..eight-pointed star
+2744          ; Extended_Pictographic#  1.1  [1] (❄️)       snowflake
+2747          ; Extended_Pictographic#  1.1  [1] (❇️)       sparkle
+274C          ; Extended_Pictographic#  6.0  [1] (❌)       cross mark
+274E          ; Extended_Pictographic#  6.0  [1] (❎)       cross mark button
+2753..2755    ; Extended_Pictographic#  6.0  [3] (❓..❕)    question mark..white exclamation mark
+2757          ; Extended_Pictographic#  5.2  [1] (❗)       exclamation mark
+2763..2767    ; Extended_Pictographic#  1.1  [5] (❣️..❧)    heart exclamation..ROTATED FLORAL HEART BULLET
+2795..2797    ; Extended_Pictographic#  6.0  [3] (➕..➗)    plus sign..division sign
+27A1          ; Extended_Pictographic#  1.1  [1] (➡️)       right arrow
+27B0          ; Extended_Pictographic#  6.0  [1] (➰)       curly loop
+27BF          ; Extended_Pictographic#  6.0  [1] (➿)       double curly loop
+2934..2935    ; Extended_Pictographic#  3.2  [2] (⤴️..⤵️)    right arrow curving up..right arrow curving down
+2B05..2B07    ; Extended_Pictographic#  4.0  [3] (⬅️..⬇️)    left arrow..down arrow
+2B1B..2B1C    ; Extended_Pictographic#  5.1  [2] (⬛..⬜)    black large square..white large square
+2B50          ; Extended_Pictographic#  5.1  [1] (⭐)       star
+2B55          ; Extended_Pictographic#  5.2  [1] (⭕)       hollow red circle
+3030          ; Extended_Pictographic#  1.1  [1] (〰️)       wavy dash
+303D          ; Extended_Pictographic#  3.2  [1] (〽️)       part alternation mark
+3297          ; Extended_Pictographic#  1.1  [1] (㊗️)       Japanese “congratulations” button
+3299          ; Extended_Pictographic#  1.1  [1] (㊙️)       Japanese “secret” button
+1F000..1F02B  ; Extended_Pictographic#  5.1 [44] (🀀..🀫)    MAHJONG TILE EAST WIND..MAHJONG TILE BACK
+1F02C..1F02F  ; Extended_Pictographic#   NA  [4] (🀬..🀯)    <reserved-1F02C>..<reserved-1F02F>
+1F030..1F093  ; Extended_Pictographic#  5.1[100] (🀰..🂓)    DOMINO TILE HORIZONTAL BACK..DOMINO TILE VERTICAL-06-06
+1F094..1F09F  ; Extended_Pictographic#   NA [12] (🂔..🂟)    <reserved-1F094>..<reserved-1F09F>
+1F0A0..1F0AE  ; Extended_Pictographic#  6.0 [15] (🂠..🂮)    PLAYING CARD BACK..PLAYING CARD KING OF SPADES
+1F0AF..1F0B0  ; Extended_Pictographic#   NA  [2] (🂯..🂰)    <reserved-1F0AF>..<reserved-1F0B0>
+1F0B1..1F0BE  ; Extended_Pictographic#  6.0 [14] (🂱..🂾)    PLAYING CARD ACE OF HEARTS..PLAYING CARD KING OF HEARTS
+1F0BF         ; Extended_Pictographic#  7.0  [1] (🂿)       PLAYING CARD RED JOKER
+1F0C0         ; Extended_Pictographic#   NA  [1] (🃀)       <reserved-1F0C0>
+1F0C1..1F0CF  ; Extended_Pictographic#  6.0 [15] (🃁..🃏)    PLAYING CARD ACE OF DIAMONDS..joker
+1F0D0         ; Extended_Pictographic#   NA  [1] (🃐)       <reserved-1F0D0>
+1F0D1..1F0DF  ; Extended_Pictographic#  6.0 [15] (🃑..🃟)    PLAYING CARD ACE OF CLUBS..PLAYING CARD WHITE JOKER
+1F0E0..1F0F5  ; Extended_Pictographic#  7.0 [22] (🃠..🃵)    PLAYING CARD FOOL..PLAYING CARD TRUMP-21
+1F0F6..1F0FF  ; Extended_Pictographic#   NA [10] (🃶..🃿)    <reserved-1F0F6>..<reserved-1F0FF>
+1F10D..1F10F  ; Extended_Pictographic#   NA  [3] (🄍..🄏)    <reserved-1F10D>..<reserved-1F10F>
+1F12F         ; Extended_Pictographic# 11.0  [1] (🄯)       COPYLEFT SYMBOL
+1F16C         ; Extended_Pictographic# 12.0  [1] (🅬)       RAISED MR SIGN
+1F16D..1F16F  ; Extended_Pictographic#   NA  [3] (🅭..🅯)    <reserved-1F16D>..<reserved-1F16F>
+1F170..1F171  ; Extended_Pictographic#  6.0  [2] (🅰️..🅱️)    A button (blood type)..B button (blood type)
+1F17E         ; Extended_Pictographic#  6.0  [1] (🅾️)       O button (blood type)
+1F17F         ; Extended_Pictographic#  5.2  [1] (🅿️)       P button
+1F18E         ; Extended_Pictographic#  6.0  [1] (🆎)       AB button (blood type)
+1F191..1F19A  ; Extended_Pictographic#  6.0 [10] (🆑..🆚)    CL button..VS button
+1F1AD..1F1E5  ; Extended_Pictographic#   NA [57] (🆭..🇥)    <reserved-1F1AD>..<reserved-1F1E5>
+1F201..1F202  ; Extended_Pictographic#  6.0  [2] (🈁..🈂️)    Japanese “here” button..Japanese “service charge” button
+1F203..1F20F  ; Extended_Pictographic#   NA [13] (🈃..🈏)    <reserved-1F203>..<reserved-1F20F>
+1F21A         ; Extended_Pictographic#  5.2  [1] (🈚)       Japanese “free of charge” button
+1F22F         ; Extended_Pictographic#  5.2  [1] (🈯)       Japanese “reserved” button
+1F232..1F23A  ; Extended_Pictographic#  6.0  [9] (🈲..🈺)    Japanese “prohibited” button..Japanese “open for business” button
+1F23C..1F23F  ; Extended_Pictographic#   NA  [4] (🈼..🈿)    <reserved-1F23C>..<reserved-1F23F>
+1F249..1F24F  ; Extended_Pictographic#   NA  [7] (🉉..🉏)    <reserved-1F249>..<reserved-1F24F>
+1F250..1F251  ; Extended_Pictographic#  6.0  [2] (🉐..🉑)    Japanese “bargain” button..Japanese “acceptable” button
+1F252..1F25F  ; Extended_Pictographic#   NA [14] (🉒..🉟)    <reserved-1F252>..<reserved-1F25F>
+1F260..1F265  ; Extended_Pictographic# 10.0  [6] (🉠..🉥)    ROUNDED SYMBOL FOR FU..ROUNDED SYMBOL FOR CAI
+1F266..1F2FF  ; Extended_Pictographic#   NA[154] (🉦..🋿)    <reserved-1F266>..<reserved-1F2FF>
+1F300..1F320  ; Extended_Pictographic#  6.0 [33] (🌀..🌠)    cyclone..shooting star
+1F321..1F32C  ; Extended_Pictographic#  7.0 [12] (🌡️..🌬️)    thermometer..wind face
+1F32D..1F32F  ; Extended_Pictographic#  8.0  [3] (🌭..🌯)    hot dog..burrito
+1F330..1F335  ; Extended_Pictographic#  6.0  [6] (🌰..🌵)    chestnut..cactus
+1F336         ; Extended_Pictographic#  7.0  [1] (🌶️)       hot pepper
+1F337..1F37C  ; Extended_Pictographic#  6.0 [70] (🌷..🍼)    tulip..baby bottle
+1F37D         ; Extended_Pictographic#  7.0  [1] (🍽️)       fork and knife with plate
+1F37E..1F37F  ; Extended_Pictographic#  8.0  [2] (🍾..🍿)    bottle with popping cork..popcorn
+1F380..1F393  ; Extended_Pictographic#  6.0 [20] (🎀..🎓)    ribbon..graduation cap
+1F394..1F39F  ; Extended_Pictographic#  7.0 [12] (🎔..🎟️)    HEART WITH TIP ON THE LEFT..admission tickets
+1F3A0..1F3C4  ; Extended_Pictographic#  6.0 [37] (🎠..🏄)    carousel horse..person surfing
+1F3C5         ; Extended_Pictographic#  7.0  [1] (🏅)       sports medal
+1F3C6..1F3CA  ; Extended_Pictographic#  6.0  [5] (🏆..🏊)    trophy..person swimming
+1F3CB..1F3CE  ; Extended_Pictographic#  7.0  [4] (🏋️..🏎️)    person lifting weights..racing car
+1F3CF..1F3D3  ; Extended_Pictographic#  8.0  [5] (🏏..🏓)    cricket game..ping pong
+1F3D4..1F3DF  ; Extended_Pictographic#  7.0 [12] (🏔️..🏟️)    snow-capped mountain..stadium
+1F3E0..1F3F0  ; Extended_Pictographic#  6.0 [17] (🏠..🏰)    house..castle
+1F3F1..1F3F7  ; Extended_Pictographic#  7.0  [7] (🏱..🏷️)    WHITE PENNANT..label
+1F3F8..1F3FA  ; Extended_Pictographic#  8.0  [3] (🏸..🏺)    badminton..amphora
+1F400..1F43E  ; Extended_Pictographic#  6.0 [63] (🐀..🐾)    rat..paw prints
+1F43F         ; Extended_Pictographic#  7.0  [1] (🐿️)       chipmunk
+1F440         ; Extended_Pictographic#  6.0  [1] (👀)       eyes
+1F441         ; Extended_Pictographic#  7.0  [1] (👁️)       eye
+1F442..1F4F7  ; Extended_Pictographic#  6.0[182] (👂..📷)    ear..camera
+1F4F8         ; Extended_Pictographic#  7.0  [1] (📸)       camera with flash
+1F4F9..1F4FC  ; Extended_Pictographic#  6.0  [4] (📹..📼)    video camera..videocassette
+1F4FD..1F4FE  ; Extended_Pictographic#  7.0  [2] (📽️..📾)    film projector..PORTABLE STEREO
+1F4FF         ; Extended_Pictographic#  8.0  [1] (📿)       prayer beads
+1F500..1F53D  ; Extended_Pictographic#  6.0 [62] (🔀..🔽)    shuffle tracks button..downwards button
+1F546..1F54A  ; Extended_Pictographic#  7.0  [5] (🕆..🕊️)    WHITE LATIN CROSS..dove
+1F54B..1F54F  ; Extended_Pictographic#  8.0  [5] (🕋..🕏)    kaaba..BOWL OF HYGIEIA
+1F550..1F567  ; Extended_Pictographic#  6.0 [24] (🕐..🕧)    one o’clock..twelve-thirty
+1F568..1F579  ; Extended_Pictographic#  7.0 [18] (🕨..🕹️)    RIGHT SPEAKER..joystick
+1F57A         ; Extended_Pictographic#  9.0  [1] (🕺)       man dancing
+1F57B..1F5A3  ; Extended_Pictographic#  7.0 [41] (🕻..🖣)    LEFT HAND TELEPHONE RECEIVER..BLACK DOWN POINTING BACKHAND INDEX
+1F5A4         ; Extended_Pictographic#  9.0  [1] (🖤)       black heart
+1F5A5..1F5FA  ; Extended_Pictographic#  7.0 [86] (🖥️..🗺️)    desktop computer..world map
+1F5FB..1F5FF  ; Extended_Pictographic#  6.0  [5] (🗻..🗿)    mount fuji..moai
+1F600         ; Extended_Pictographic#  6.1  [1] (😀)       grinning face
+1F601..1F610  ; Extended_Pictographic#  6.0 [16] (😁..😐)    beaming face with smiling eyes..neutral face
+1F611         ; Extended_Pictographic#  6.1  [1] (😑)       expressionless face
+1F612..1F614  ; Extended_Pictographic#  6.0  [3] (😒..😔)    unamused face..pensive face
+1F615         ; Extended_Pictographic#  6.1  [1] (😕)       confused face
+1F616         ; Extended_Pictographic#  6.0  [1] (😖)       confounded face
+1F617         ; Extended_Pictographic#  6.1  [1] (😗)       kissing face
+1F618         ; Extended_Pictographic#  6.0  [1] (😘)       face blowing a kiss
+1F619         ; Extended_Pictographic#  6.1  [1] (😙)       kissing face with smiling eyes
+1F61A         ; Extended_Pictographic#  6.0  [1] (😚)       kissing face with closed eyes
+1F61B         ; Extended_Pictographic#  6.1  [1] (😛)       face with tongue
+1F61C..1F61E  ; Extended_Pictographic#  6.0  [3] (😜..😞)    winking face with tongue..disappointed face
+1F61F         ; Extended_Pictographic#  6.1  [1] (😟)       worried face
+1F620..1F625  ; Extended_Pictographic#  6.0  [6] (😠..😥)    angry face..sad but relieved face
+1F626..1F627  ; Extended_Pictographic#  6.1  [2] (😦..😧)    frowning face with open mouth..anguished face
+1F628..1F62B  ; Extended_Pictographic#  6.0  [4] (😨..😫)    fearful face..tired face
+1F62C         ; Extended_Pictographic#  6.1  [1] (😬)       grimacing face
+1F62D         ; Extended_Pictographic#  6.0  [1] (😭)       loudly crying face
+1F62E..1F62F  ; Extended_Pictographic#  6.1  [2] (😮..😯)    face with open mouth..hushed face
+1F630..1F633  ; Extended_Pictographic#  6.0  [4] (😰..😳)    anxious face with sweat..flushed face
+1F634         ; Extended_Pictographic#  6.1  [1] (😴)       sleeping face
+1F635..1F640  ; Extended_Pictographic#  6.0 [12] (😵..🙀)    dizzy face..weary cat
+1F641..1F642  ; Extended_Pictographic#  7.0  [2] (🙁..🙂)    slightly frowning face..slightly smiling face
+1F643..1F644  ; Extended_Pictographic#  8.0  [2] (🙃..🙄)    upside-down face..face with rolling eyes
+1F645..1F64F  ; Extended_Pictographic#  6.0 [11] (🙅..🙏)    person gesturing NO..folded hands
+1F680..1F6C5  ; Extended_Pictographic#  6.0 [70] (🚀..🛅)    rocket..left luggage
+1F6C6..1F6CF  ; Extended_Pictographic#  7.0 [10] (🛆..🛏️)    TRIANGLE WITH ROUNDED CORNERS..bed
+1F6D0         ; Extended_Pictographic#  8.0  [1] (🛐)       place of worship
+1F6D1..1F6D2  ; Extended_Pictographic#  9.0  [2] (🛑..🛒)    stop sign..shopping cart
+1F6D3..1F6D4  ; Extended_Pictographic# 10.0  [2] (🛓..🛔)    STUPA..PAGODA
+1F6D5         ; Extended_Pictographic# 12.0  [1] (🛕)       hindu temple
+1F6D6..1F6DF  ; Extended_Pictographic#   NA [10] (🛖..🛟)    <reserved-1F6D6>..<reserved-1F6DF>
+1F6E0..1F6EC  ; Extended_Pictographic#  7.0 [13] (🛠️..🛬)    hammer and wrench..airplane arrival
+1F6ED..1F6EF  ; Extended_Pictographic#   NA  [3] (🛭..🛯)    <reserved-1F6ED>..<reserved-1F6EF>
+1F6F0..1F6F3  ; Extended_Pictographic#  7.0  [4] (🛰️..🛳️)    satellite..passenger ship
+1F6F4..1F6F6  ; Extended_Pictographic#  9.0  [3] (🛴..🛶)    kick scooter..canoe
+1F6F7..1F6F8  ; Extended_Pictographic# 10.0  [2] (🛷..🛸)    sled..flying saucer
+1F6F9         ; Extended_Pictographic# 11.0  [1] (🛹)       skateboard
+1F6FA         ; Extended_Pictographic# 12.0  [1] (🛺)       auto rickshaw
+1F6FB..1F6FF  ; Extended_Pictographic#   NA  [5] (🛻..🛿)    <reserved-1F6FB>..<reserved-1F6FF>
+1F774..1F77F  ; Extended_Pictographic#   NA [12] (🝴..🝿)    <reserved-1F774>..<reserved-1F77F>
+1F7D5..1F7D8  ; Extended_Pictographic# 11.0  [4] (🟕..🟘)    CIRCLED TRIANGLE..NEGATIVE CIRCLED SQUARE
+1F7D9..1F7DF  ; Extended_Pictographic#   NA  [7] (🟙..🟟)    <reserved-1F7D9>..<reserved-1F7DF>
+1F7E0..1F7EB  ; Extended_Pictographic# 12.0 [12] (🟠..🟫)    orange circle..brown square
+1F7EC..1F7FF  ; Extended_Pictographic#   NA [20] (🟬..🟿)    <reserved-1F7EC>..<reserved-1F7FF>
+1F80C..1F80F  ; Extended_Pictographic#   NA  [4] (🠌..🠏)    <reserved-1F80C>..<reserved-1F80F>
+1F848..1F84F  ; Extended_Pictographic#   NA  [8] (🡈..🡏)    <reserved-1F848>..<reserved-1F84F>
+1F85A..1F85F  ; Extended_Pictographic#   NA  [6] (🡚..🡟)    <reserved-1F85A>..<reserved-1F85F>
+1F888..1F88F  ; Extended_Pictographic#   NA  [8] (🢈..🢏)    <reserved-1F888>..<reserved-1F88F>
+1F8AE..1F8FF  ; Extended_Pictographic#   NA [82] (🢮..🣿)    <reserved-1F8AE>..<reserved-1F8FF>
+1F90C         ; Extended_Pictographic#   NA  [1] (🤌)       <reserved-1F90C>
+1F90D..1F90F  ; Extended_Pictographic# 12.0  [3] (🤍..🤏)    white heart..pinching hand
+1F910..1F918  ; Extended_Pictographic#  8.0  [9] (🤐..🤘)    zipper-mouth face..sign of the horns
+1F919..1F91E  ; Extended_Pictographic#  9.0  [6] (🤙..🤞)    call me hand..crossed fingers
+1F91F         ; Extended_Pictographic# 10.0  [1] (🤟)       love-you gesture
+1F920..1F927  ; Extended_Pictographic#  9.0  [8] (🤠..🤧)    cowboy hat face..sneezing face
+1F928..1F92F  ; Extended_Pictographic# 10.0  [8] (🤨..🤯)    face with raised eyebrow..exploding head
+1F930         ; Extended_Pictographic#  9.0  [1] (🤰)       pregnant woman
+1F931..1F932  ; Extended_Pictographic# 10.0  [2] (🤱..🤲)    breast-feeding..palms up together
+1F933..1F93A  ; Extended_Pictographic#  9.0  [8] (🤳..🤺)    selfie..person fencing
+1F93C..1F93E  ; Extended_Pictographic#  9.0  [3] (🤼..🤾)    people wrestling..person playing handball
+1F93F         ; Extended_Pictographic# 12.0  [1] (🤿)       diving mask
+1F940..1F945  ; Extended_Pictographic#  9.0  [6] (🥀..🥅)    wilted flower..goal net
+1F947..1F94B  ; Extended_Pictographic#  9.0  [5] (🥇..🥋)    1st place medal..martial arts uniform
+1F94C         ; Extended_Pictographic# 10.0  [1] (🥌)       curling stone
+1F94D..1F94F  ; Extended_Pictographic# 11.0  [3] (🥍..🥏)    lacrosse..flying disc
+1F950..1F95E  ; Extended_Pictographic#  9.0 [15] (🥐..🥞)    croissant..pancakes
+1F95F..1F96B  ; Extended_Pictographic# 10.0 [13] (🥟..🥫)    dumpling..canned food
+1F96C..1F970  ; Extended_Pictographic# 11.0  [5] (🥬..🥰)    leafy green..smiling face with hearts
+1F971         ; Extended_Pictographic# 12.0  [1] (🥱)       yawning face
+1F972         ; Extended_Pictographic#   NA  [1] (🥲)       <reserved-1F972>
+1F973..1F976  ; Extended_Pictographic# 11.0  [4] (🥳..🥶)    partying face..cold face
+1F977..1F979  ; Extended_Pictographic#   NA  [3] (🥷..🥹)    <reserved-1F977>..<reserved-1F979>
+1F97A         ; Extended_Pictographic# 11.0  [1] (🥺)       pleading face
+1F97B         ; Extended_Pictographic# 12.0  [1] (🥻)       sari
+1F97C..1F97F  ; Extended_Pictographic# 11.0  [4] (🥼..🥿)    lab coat..flat shoe
+1F980..1F984  ; Extended_Pictographic#  8.0  [5] (🦀..🦄)    crab..unicorn
+1F985..1F991  ; Extended_Pictographic#  9.0 [13] (🦅..🦑)    eagle..squid
+1F992..1F997  ; Extended_Pictographic# 10.0  [6] (🦒..🦗)    giraffe..cricket
+1F998..1F9A2  ; Extended_Pictographic# 11.0 [11] (🦘..🦢)    kangaroo..swan
+1F9A3..1F9A4  ; Extended_Pictographic#   NA  [2] (🦣..🦤)    <reserved-1F9A3>..<reserved-1F9A4>
+1F9A5..1F9AA  ; Extended_Pictographic# 12.0  [6] (🦥..🦪)    sloth..oyster
+1F9AB..1F9AD  ; Extended_Pictographic#   NA  [3] (🦫..🦭)    <reserved-1F9AB>..<reserved-1F9AD>
+1F9AE..1F9AF  ; Extended_Pictographic# 12.0  [2] (🦮..🦯)    guide dog..probing cane
+1F9B0..1F9B9  ; Extended_Pictographic# 11.0 [10] (🦰..🦹)    red hair..supervillain
+1F9BA..1F9BF  ; Extended_Pictographic# 12.0  [6] (🦺..🦿)    safety vest..mechanical leg
+1F9C0         ; Extended_Pictographic#  8.0  [1] (🧀)       cheese wedge
+1F9C1..1F9C2  ; Extended_Pictographic# 11.0  [2] (🧁..🧂)    cupcake..salt
+1F9C3..1F9CA  ; Extended_Pictographic# 12.0  [8] (🧃..🧊)    beverage box..ice cube
+1F9CB..1F9CC  ; Extended_Pictographic#   NA  [2] (🧋..🧌)    <reserved-1F9CB>..<reserved-1F9CC>
+1F9CD..1F9CF  ; Extended_Pictographic# 12.0  [3] (🧍..🧏)    person standing..deaf person
+1F9D0..1F9E6  ; Extended_Pictographic# 10.0 [23] (🧐..🧦)    face with monocle..socks
+1F9E7..1F9FF  ; Extended_Pictographic# 11.0 [25] (🧧..🧿)    red envelope..nazar amulet
+1FA00..1FA53  ; Extended_Pictographic# 12.0 [84] (🨀..🩓)    NEUTRAL CHESS KING..BLACK CHESS KNIGHT-BISHOP
+1FA54..1FA5F  ; Extended_Pictographic#   NA [12] (🩔..🩟)    <reserved-1FA54>..<reserved-1FA5F>
+1FA60..1FA6D  ; Extended_Pictographic# 11.0 [14] (🩠..🩭)    XIANGQI RED GENERAL..XIANGQI BLACK SOLDIER
+1FA6E..1FA6F  ; Extended_Pictographic#   NA  [2] (🩮..🩯)    <reserved-1FA6E>..<reserved-1FA6F>
+1FA70..1FA73  ; Extended_Pictographic# 12.0  [4] (🩰..🩳)    ballet shoes..shorts
+1FA74..1FA77  ; Extended_Pictographic#   NA  [4] (🩴..🩷)    <reserved-1FA74>..<reserved-1FA77>
+1FA78..1FA7A  ; Extended_Pictographic# 12.0  [3] (🩸..🩺)    drop of blood..stethoscope
+1FA7B..1FA7F  ; Extended_Pictographic#   NA  [5] (🩻..🩿)    <reserved-1FA7B>..<reserved-1FA7F>
+1FA80..1FA82  ; Extended_Pictographic# 12.0  [3] (🪀..🪂)    yo-yo..parachute
+1FA83..1FA8F  ; Extended_Pictographic#   NA [13] (🪃..🪏)    <reserved-1FA83>..<reserved-1FA8F>
+1FA90..1FA95  ; Extended_Pictographic# 12.0  [6] (🪐..🪕)    ringed planet..banjo
+1FA96..1FFFD  ; Extended_Pictographic#   NA[1384] (🪖..🿽)   <reserved-1FA96>..<reserved-1FFFD>
+
+# Total elements: 3793
+
+#EOF
index 66e20f0e411e6c54e8a1634d1c6bb706e18cbeb6..3f516900764d0ba3131f30ae10a3ad318ecab6ab 100644 (file)
@@ -260,4 +260,29 @@ defmodule Pleroma.Emoji do
       Enum.any?(patterns, matcher) && group
     end)
   end
+
+  {:ok, file} = File.read("lib/pleroma/emoji-data.txt")
+
+  @unicode_emoji file
+                 |> String.split("\n")
+                 |> Enum.filter(fn line -> String.starts_with?(line, ["1", "2", "3", "4"]) end)
+                 |> Enum.map(fn line -> String.split(line) |> List.first() end)
+                 |> Enum.map(fn line ->
+                   case String.split(line, "..") do
+                     [number] ->
+                       String.to_integer(number, 16)
+
+                     [first, last] ->
+                       Range.new(String.to_integer(first, 16), String.to_integer(last, 16))
+                       |> Enum.to_list()
+                   end
+                 end)
+                 |> List.flatten()
+                 |> Enum.filter(&is_integer/1)
+                 |> Enum.uniq()
+                 |> Enum.map(fn n -> :unicode.characters_to_binary([n], :utf32) end)
+
+  def is_unicode_emoji?(str) do
+    str in @unicode_emoji
+  end
 end
index d23ec66ac4c6afd403099286a48409ac9c125fca..74663ac9769a21374ffa48a40458979562f78d68 100644 (file)
@@ -312,6 +312,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     end
   end
 
+  def react_with_emoji(user, object, emoji, options \\ []) do
+    with local <- Keyword.get(options, :local, true),
+         activity_id <- Keyword.get(options, :activity_id, nil),
+         Pleroma.Emoji.is_unicode_emoji?(emoji),
+         reaction_data <- make_emoji_reaction_data(user, object, emoji, activity_id),
+         {:ok, activity} <- insert(reaction_data, local),
+         {:ok, object} <- add_emoji_reaction_to_object(activity, object) do
+      {:ok, activity, object}
+    end
+  end
+
   # TODO: This is weird, maybe we shouldn't check here if we can make the activity.
   def like(
         %User{ap_id: ap_id} = user,
index 350b83abb3d245f5a08be850af46db9ca55188fd..cb5755ccc31a85d8c249165f35434f2842f1d7cb 100644 (file)
@@ -574,6 +574,27 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     end
   end
 
+  def handle_incoming(
+        %{
+          "type" => "EmojiReaction",
+          "object" => object_id,
+          "actor" => _actor,
+          "id" => id,
+          "content" => emoji
+        } = data,
+        _options
+      ) do
+    with actor <- Containment.get_actor(data),
+         {:ok, %User{} = actor} <- User.get_or_fetch_by_ap_id(actor),
+         {:ok, object} <- get_obj_helper(object_id),
+         {:ok, activity, _object} <-
+           ActivityPub.react_with_emoji(actor, object, emoji, activity_id: id, local: false) do
+      {:ok, activity}
+    else
+      _e -> :error
+    end
+  end
+
   def handle_incoming(
         %{"type" => "Announce", "object" => object_id, "actor" => _actor, "id" => id} = data,
         _options
@@ -976,9 +997,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     |> Map.put("attachment", attachments)
   end
 
-  defp strip_internal_fields(object) do
+  def strip_internal_fields(object) do
     object
     |> Map.drop([
+      "reactions",
+      "reaction_count",
       "likes",
       "like_count",
       "announcements",
index c9c0c376335f5bc43b627f8a35b4589faac7d428..95e040c6c6a32a1a7d0f61cee30c28a4319b5a8f 100644 (file)
@@ -277,6 +277,12 @@ defmodule Pleroma.Web.ActivityPub.Utils do
     |> Repo.all()
   end
 
+  def make_emoji_reaction_data(user, object, emoji, activity_id) do
+    make_like_data(user, object, activity_id)
+    |> Map.put("type", "EmojiReaction")
+    |> Map.put("content", emoji)
+  end
+
   @spec make_like_data(User.t(), map(), String.t()) :: map()
   def make_like_data(
         %User{ap_id: ap_id} = actor,
@@ -311,10 +317,21 @@ defmodule Pleroma.Web.ActivityPub.Utils do
   @spec update_element_in_object(String.t(), list(any), Object.t()) ::
           {:ok, Object.t()} | {:error, Ecto.Changeset.t()}
   def update_element_in_object(property, element, object) do
+    length =
+      if is_map(element) do
+        element
+        |> Map.values()
+        |> List.flatten()
+        |> length()
+      else
+        element
+        |> length()
+      end
+
     data =
       Map.merge(
         object.data,
-        %{"#{property}_count" => length(element), "#{property}s" => element}
+        %{"#{property}_count" => length, "#{property}s" => element}
       )
 
     object
@@ -322,6 +339,20 @@ defmodule Pleroma.Web.ActivityPub.Utils do
     |> Object.update_and_set_cache()
   end
 
+  @spec add_emoji_reaction_to_object(Activity.t(), Object.t()) ::
+          {:ok, Object.t()} | {:error, Ecto.Changeset.t()}
+
+  def add_emoji_reaction_to_object(
+        %Activity{data: %{"content" => emoji, "actor" => actor}},
+        object
+      ) do
+    reactions = object.data["reactions"] || %{}
+    emoji_actors = reactions[emoji] || []
+    new_emoji_actors = [actor | emoji_actors] |> Enum.uniq()
+    new_reactions = Map.put(reactions, emoji, new_emoji_actors)
+    update_element_in_object("reaction", new_reactions, object)
+  end
+
   @spec add_like_to_object(Activity.t(), Object.t()) ::
           {:ok, Object.t()} | {:error, Ecto.Changeset.t()}
   def add_like_to_object(%Activity{data: %{"actor" => actor}}, object) do
index 5faddc9f4e37f2e714104a193301b96a33a0dbef..3e1aa481897cacebef0270a75a0f97ca647e43eb 100644 (file)
@@ -123,6 +123,16 @@ defmodule Pleroma.Web.CommonAPI do
     end
   end
 
+  def react_with_emoji(id, user, emoji) do
+    with %Activity{} = activity <- Activity.get_by_id(id),
+         object <- Object.normalize(activity) do
+      ActivityPub.react_with_emoji(user, object, emoji)
+    else
+      _ ->
+        {:error, dgettext("errors", "Could not add reaction emoji")}
+    end
+  end
+
   def vote(user, object, choices) do
     with "Question" <- object.data["type"],
          {:author, false} <- {:author, object.data["actor"] == user.ap_id},
index f4df3b024e1004ddd77026b42539f505a46c7ef5..110240115478108a10d5d98171cf772cf97935f6 100644 (file)
@@ -7,13 +7,52 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
 
   import Pleroma.Web.ControllerHelper, only: [add_link_headers: 7]
 
+  alias Pleroma.Activity
+  alias Pleroma.Object
+  alias Pleroma.User
   alias Pleroma.Conversation.Participation
   alias Pleroma.Notification
   alias Pleroma.Web.ActivityPub.ActivityPub
+  alias Pleroma.Web.CommonAPI
+  alias Pleroma.Web.MastodonAPI.AccountView
   alias Pleroma.Web.MastodonAPI.ConversationView
   alias Pleroma.Web.MastodonAPI.NotificationView
   alias Pleroma.Web.MastodonAPI.StatusView
 
+  def emoji_reactions_by(%{assigns: %{user: user}} = conn, %{"id" => activity_id}) do
+    with %Activity{} = activity <- Activity.get_by_id_with_object(activity_id),
+         %Object{data: %{"reactions" => emoji_reactions}} <- Object.normalize(activity) do
+      reactions =
+        Enum.reduce(emoji_reactions, %{}, fn {emoji, users}, res ->
+          users =
+            users
+            |> Enum.map(&User.get_cached_by_ap_id/1)
+
+          res
+          |> Map.put(
+            emoji,
+            AccountView.render("accounts.json", %{users: users, for: user, as: :user})
+          )
+        end)
+
+      conn
+      |> json(reactions)
+    else
+      _e ->
+        conn
+        |> json(%{})
+    end
+  end
+
+  def react_with_emoji(%{assigns: %{user: user}} = conn, %{"id" => activity_id, "emoji" => emoji}) do
+    with {:ok, _activity, _object} <- CommonAPI.react_with_emoji(activity_id, user, emoji),
+         activity = Activity.get_by_id(activity_id) do
+      conn
+      |> put_view(StatusView)
+      |> render("status.json", %{activity: activity, for: user, as: :activity})
+    end
+  end
+
   def conversation(%{assigns: %{user: user}} = conn, %{"id" => participation_id}) do
     with %Participation{} = participation <- Participation.get(participation_id),
          true <- user.id == participation.user_id do
index b0464037e83ab03dadd11ab3839a96b0b4cb12db..6354510cf634c49825fd3f8c2c415c282c307a43 100644 (file)
@@ -260,6 +260,12 @@ defmodule Pleroma.Web.Router do
     end
   end
 
+  scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
+    pipe_through(:api)
+
+    get("/statuses/:id/emoji_reactions_by", PleromaAPIController, :emoji_reactions_by)
+  end
+
   scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
     pipe_through(:authenticated_api)
 
@@ -272,6 +278,7 @@ defmodule Pleroma.Web.Router do
     scope [] do
       pipe_through(:oauth_write)
       patch("/conversations/:id", PleromaAPIController, :update_conversation)
+      post("/statuses/:id/react_with_emoji", PleromaAPIController, :react_with_emoji)
       post("/notifications/read", PleromaAPIController, :read_notification)
     end
   end
index 07ac6ff1daada3d8da311f2c512fa59c967c736e..467357291afcaf744f11a028b1d4c97e93907e3b 100644 (file)
@@ -6,6 +6,14 @@ defmodule Pleroma.EmojiTest do
   use ExUnit.Case, async: true
   alias Pleroma.Emoji
 
+  describe "is_unicode_emoji?/1" do
+    test "tells if a string is an unicode emoji" do
+      refute Emoji.is_unicode_emoji?("X")
+      assert Emoji.is_unicode_emoji?("☂")
+      assert Emoji.is_unicode_emoji?("🥺")
+    end
+  end
+
   describe "get_all/0" do
     setup do
       emoji_list = Emoji.get_all()
diff --git a/test/fixtures/emoji-reaction.json b/test/fixtures/emoji-reaction.json
new file mode 100644 (file)
index 0000000..3812e43
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "type": "EmojiReaction",
+  "signature": {
+    "type": "RsaSignature2017",
+    "signatureValue": "fdxMfQSMwbC6wP6sh6neS/vM5879K67yQkHTbiT5Npr5wAac0y6+o3Ij+41tN3rL6wfuGTosSBTHOtta6R4GCOOhCaCSLMZKypnp1VltCzLDoyrZELnYQIC8gpUXVmIycZbREk22qWUe/w7DAFaKK4UscBlHDzeDVcA0K3Se5Sluqi9/Zh+ldAnEzj/rSEPDjrtvf5wGNf3fHxbKSRKFt90JvKK6hS+vxKUhlRFDf6/SMETw+EhwJSNW4d10yMUakqUWsFv4Acq5LW7l+HpYMvlYY1FZhNde1+uonnCyuQDyvzkff8zwtEJmAXC4RivO/VVLa17SmqheJZfI8oluVg==",
+    "creator": "http://mastodon.example.org/users/admin#main-key",
+    "created": "2018-02-17T18:57:49Z"
+  },
+  "object": "http://localtesting.pleroma.lol/objects/eb92579d-3417-42a8-8652-2492c2d4f454",
+  "content": "👌",
+  "nickname": "lain",
+  "id": "http://mastodon.example.org/users/admin#reactions/2",
+  "actor": "http://mastodon.example.org/users/admin",
+  "@context": [
+    "https://www.w3.org/ns/activitystreams",
+    "https://w3id.org/security/v1",
+    {
+      "toot": "http://joinmastodon.org/ns#",
+      "sensitive": "as:sensitive",
+      "ostatus": "http://ostatus.org#",
+      "movedTo": "as:movedTo",
+      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+      "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
+      "conversation": "ostatus:conversation",
+      "atomUri": "ostatus:atomUri",
+      "Hashtag": "as:Hashtag",
+      "Emoji": "toot:Emoji"
+    }
+  ]
+}
index f72b44aed4c0f531b6ebda36e778da5fc4e7c825..67dfb9394b93e6aa4e5df28c80a60c32fb099bc5 100644 (file)
@@ -677,6 +677,28 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
     end
   end
 
+  describe "react to an object" do
+    test "adds an emoji reaction activity to the db" do
+      user = insert(:user)
+      reactor = insert(:user)
+      {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
+      assert object = Object.normalize(activity)
+
+      {:ok, reaction_activity, object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
+
+      assert reaction_activity
+
+      assert reaction_activity.data["actor"] == reactor.ap_id
+      assert reaction_activity.data["type"] == "EmojiReaction"
+      assert reaction_activity.data["content"] == "🔥"
+      assert reaction_activity.data["object"] == object.data["id"]
+      assert reaction_activity.data["to"] == [User.ap_followers(reactor), activity.data["actor"]]
+      assert reaction_activity.data["context"] == object.data["context"]
+      assert object.data["reaction_count"] == 1
+      assert object.data["reactions"]["🔥"] == [reactor.ap_id]
+    end
+  end
+
   describe "like an object" do
     test_with_mock "sends an activity to federation", Pleroma.Web.Federator, [:passthrough], [] do
       Pleroma.Config.put([:instance, :federating], true)
index bebecce8db941d5f0cf355e17f3ed93d36557031..136c8034c8b5ad4c6d483c2465ffb22f10133c3b 100644 (file)
@@ -311,6 +311,24 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       assert data["object"] == activity.data["object"]
     end
 
+    test "it works for incoming emoji reactions" do
+      user = insert(:user)
+      {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
+
+      data =
+        File.read!("test/fixtures/emoji-reaction.json")
+        |> Poison.decode!()
+        |> Map.put("object", activity.data["object"])
+
+      {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+      assert data["actor"] == "http://mastodon.example.org/users/admin"
+      assert data["type"] == "EmojiReaction"
+      assert data["id"] == "http://mastodon.example.org/users/admin#reactions/2"
+      assert data["object"] == activity.data["object"]
+      assert data["content"] == "👌"
+    end
+
     test "it returns an error for incoming unlikes wihout a like activity" do
       user = insert(:user)
       {:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"})
@@ -473,6 +491,20 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       refute Map.has_key?(object.data, "likes")
     end
 
+    test "it strips internal reactions" do
+      user = insert(:user)
+      {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
+      {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, user, "📢")
+
+      %{object: object} = Activity.get_by_id_with_object(activity.id)
+      assert Map.has_key?(object.data, "reactions")
+      assert Map.has_key?(object.data, "reaction_count")
+
+      object_data = Transmogrifier.strip_internal_fields(object.data)
+      refute Map.has_key?(object_data, "reactions")
+      refute Map.has_key?(object_data, "reaction_count")
+    end
+
     test "it works for incoming update activities" do
       data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
 
index f28a6609070c99063bf1ca3189a9f084dbb361a0..7cb1202fc8d906cfe3be005c33ec3e4ff94a0775 100644 (file)
@@ -222,6 +222,20 @@ defmodule Pleroma.Web.CommonAPITest do
   end
 
   describe "reactions" do
+    test "reacting to a status with an emoji" do
+      user = insert(:user)
+      other_user = insert(:user)
+
+      {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
+
+      {:ok, reaction, _} = CommonAPI.react_with_emoji(activity.id, user, "👍")
+
+      assert reaction.data["actor"] == user.ap_id
+      assert reaction.data["content"] == "👍"
+
+      # TODO: test error case.
+    end
+
     test "repeating a status" do
       user = insert(:user)
       other_user = insert(:user)
index 7eaeda4a025a48d5b1e1d8ce1c4f2af27709bd8e..3c2a087ca458debf21e772dd23dfc69124136541 100644 (file)
@@ -12,6 +12,45 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do
 
   import Pleroma.Factory
 
+  test "POST /api/v1/pleroma/statuses/:id/react_with_emoji", %{conn: conn} do
+    user = insert(:user)
+    other_user = insert(:user)
+
+    {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
+
+    result =
+      conn
+      |> assign(:user, other_user)
+      |> post("/api/v1/pleroma/statuses/#{activity.id}/react_with_emoji", %{"emoji" => "☕"})
+
+    assert %{"id" => id} = json_response(result, 200)
+    assert to_string(activity.id) == id
+  end
+
+  test "GET /api/v1/pleroma/statuses/:id/emoji_reactions_by", %{conn: conn} do
+    user = insert(:user)
+    other_user = insert(:user)
+
+    {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
+
+    result =
+      conn
+      |> get("/api/v1/pleroma/statuses/#{activity.id}/emoji_reactions_by")
+      |> json_response(200)
+
+    assert result == %{}
+
+    {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
+
+    result =
+      conn
+      |> get("/api/v1/pleroma/statuses/#{activity.id}/emoji_reactions_by")
+      |> json_response(200)
+
+    [represented_user] = result["🎅"]
+    assert represented_user["id"] == other_user.id
+  end
+
   test "/api/v1/pleroma/conversations/:id", %{conn: conn} do
     user = insert(:user)
     other_user = insert(:user)