Browse Source

Remove various unused files

pull/311/head
nielsandriesse 2 years ago
parent
commit
f6c1c84d90
  1. 5
      Gemfile
  2. 212
      Gemfile.lock
  3. 56
      Jenkinsfile
  4. 54
      Loki/LokiTestUtilities.swift
  5. 63
      Loki/MultiDeviceProtocolTests.swift
  6. 24
      Loki/OnionRequestAPITests.swift
  7. 9
      Loki/SessionManagementProtocolTests.swift
  8. 56
      Loki/SyncMessagesProtocolTests.swift
  9. 47
      Loki/XCTest+Utilities.swift
  10. 45
      Makefile
  11. 106
      Scripts/AuditStringH.py
  12. 3
      Scripts/ClearDerivedData.sh
  13. 4
      Scripts/HardResetGit.sh
  14. 206
      Scripts/bump_build_tag.py
  15. 73
      Scripts/debug_log_upload.py
  16. 679
      Scripts/emoji-data.txt
  17. 88
      Scripts/emoji_ranges.py
  18. 1
      Scripts/git_hooks/README.md
  19. 3
      Scripts/git_hooks/post-commit
  20. 3
      Scripts/git_hooks/pre-commit
  21. 475
      Scripts/precommit.py
  22. 98
      Scripts/reverse_integration_check.py
  23. 37
      Scripts/update_plist_info.sh
  24. 15
      Signal.xcodeproj/project.pbxproj
  25. 4
      fastlane/.gitignore
  26. 6
      fastlane/Appfile
  27. 27
      fastlane/Fastfile

5
Gemfile

@ -1,5 +0,0 @@
source 'https://rubygems.org'
gem 'cocoapods'
gem 'fastlane'

212
Gemfile.lock

@ -1,212 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.0)
activesupport (4.2.10)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
atomos (0.1.3)
babosa (1.0.2)
claide (1.0.2)
cocoapods (1.5.3)
activesupport (>= 4.0.2, < 5)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.5.3)
cocoapods-deintegrate (>= 1.0.2, < 2.0)
cocoapods-downloader (>= 1.2.0, < 2.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-stats (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.3.0, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored2 (~> 3.1)
escape (~> 0.0.4)
fourflusher (~> 2.0.1)
gh_inspector (~> 1.0)
molinillo (~> 0.6.5)
nap (~> 1.0)
ruby-macho (~> 1.1)
xcodeproj (>= 1.5.7, < 2.0)
cocoapods-core (1.5.3)
activesupport (>= 4.0.2, < 6)
fuzzy_match (~> 2.0.4)
nap (~> 1.0)
cocoapods-deintegrate (1.0.2)
cocoapods-downloader (1.2.2)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.0)
cocoapods-stats (1.0.0)
cocoapods-trunk (1.3.1)
nap (>= 0.8, < 2.0)
netrc (~> 0.11)
cocoapods-try (1.1.0)
colored (1.2)
colored2 (3.1.2)
commander-fastlane (4.4.6)
highline (~> 1.7.2)
concurrent-ruby (1.1.3)
declarative (0.0.10)
declarative-option (0.1.0)
digest-crc (0.4.1)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.5.0)
emoji_regex (0.1.1)
escape (0.0.4)
excon (0.62.0)
faraday (0.15.4)
multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6)
faraday (>= 0.7.4)
http-cookie (~> 1.0.0)
faraday_middleware (0.12.2)
faraday (>= 0.7.4, < 1.0)
fastimage (2.1.5)
fastlane (2.112.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0)
babosa (>= 1.0.2, < 2.0.0)
bundler (>= 1.12.0, < 2.0.0)
colored
commander-fastlane (>= 4.4.6, < 5.0.0)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (~> 0.1)
excon (>= 0.45.0, < 1.0.0)
faraday (~> 0.9)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 0.9)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-api-client (>= 0.21.2, < 0.24.0)
google-cloud-storage (>= 1.15.0, < 2.0.0)
highline (>= 1.7.2, < 2.0.0)
json (< 3.0.0)
mini_magick (~> 4.5.1)
multi_json
multi_xml (~> 0.5)
multipart-post (~> 2.0.0)
plist (>= 3.1.0, < 4.0.0)
public_suffix (~> 2.0.0)
rubyzip (>= 1.2.2, < 2.0.0)
security (= 0.1.3)
simctl (~> 1.6.3)
slack-notifier (>= 2.0.0, < 3.0.0)
terminal-notifier (>= 1.6.2, < 2.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.6.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
fourflusher (2.0.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
google-api-client (0.23.9)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.5, < 0.7.0)
httpclient (>= 2.8.1, < 3.0)
mime-types (~> 3.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
signet (~> 0.9)
google-cloud-core (1.2.7)
google-cloud-env (~> 1.0)
google-cloud-env (1.0.5)
faraday (~> 0.11)
google-cloud-storage (1.15.0)
digest-crc (~> 0.4)
google-api-client (~> 0.23)
google-cloud-core (~> 1.2)
googleauth (~> 0.6.2)
googleauth (0.6.7)
faraday (~> 0.12)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (~> 0.7)
highline (1.7.10)
http-cookie (1.0.3)
domain_name (~> 0.5)
httpclient (2.8.3)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
json (2.1.0)
jwt (2.1.0)
memoist (0.16.0)
mime-types (3.2.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
mini_magick (4.5.1)
minitest (5.11.3)
molinillo (0.6.6)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
nanaimo (0.2.6)
nap (1.1.0)
naturally (2.2.0)
netrc (0.11.0)
os (1.0.0)
plist (3.5.0)
public_suffix (2.0.5)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rouge (2.0.7)
ruby-macho (1.3.1)
rubyzip (1.2.2)
security (0.1.3)
signet (0.11.0)
addressable (~> 2.3)
faraday (~> 0.9)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.5)
CFPropertyList
naturally
slack-notifier (2.3.2)
terminal-notifier (1.8.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)
tty-cursor (0.6.0)
tty-screen (0.6.5)
tty-spinner (0.9.0)
tty-cursor (~> 0.6.0)
tzinfo (1.2.5)
thread_safe (~> 0.1)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.5)
unicode-display_width (1.4.1)
word_wrap (1.0.0)
xcodeproj (1.7.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.2.6)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.0)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
ruby
DEPENDENCIES
cocoapods
fastlane
BUNDLED WITH
1.17.2

56
Jenkinsfile vendored

@ -1,56 +0,0 @@
pipeline {
agent any
environment {
LANG = "en_US.UTF-8"
LANGUAGE = "en_US.UTF-8"
LC_ALL = "en_US.UTF-8"
PATH = "PATH=$HOME/.rbenv/bin:$HOME/.rbenv/shims:/usr/local/bin/:$PATH"
}
stages {
stage('env setup') {
steps {
script {
// CHANGE_ID is set only for pull requests, so it is safe to access the pullRequest global variable
if (env.CHANGE_ID) {
currentBuild.displayName = "PR #${pullRequest.number}: ${pullRequest.title}"
}
}
sh 'make setup'
}
}
stage('build dependencies') {
steps {
sh 'make dependencies'
}
}
stage('test') {
steps {
ansiColor('xterm') {
sh 'make test'
}
}
}
}
post {
success {
script {
// CHANGE_ID is set only for pull requests, so it is safe to access the pullRequest global variable
if (env.CHANGE_ID) {
def comment = pullRequest.comment("๐Ÿ‘ Build PASSED commit: ${pullRequest.head}\nbuild: ${currentBuild.absoluteUrl}")
}
}
}
failure {
script {
// CHANGE_ID is set only for pull requests, so it is safe to access the pullRequest global variable
if (env.CHANGE_ID) {
def comment = pullRequest.comment("๐Ÿ’ฅ Build FAILED commit: ${pullRequest.head}\nbuild: ${currentBuild.absoluteUrl}")
}
}
}
}
}

54
Loki/LokiTestUtilities.swift

@ -1,54 +0,0 @@
import Foundation
import SignalServiceKit
import Curve25519Kit
enum LokiTestUtilities {
public static func setUpMockEnvironment() {
// Activate the mock Signal environment
ClearCurrentAppContextForTests()
SetCurrentAppContext(TestAppContext())
MockSSKEnvironment.activate()
// Register a mock user
let identityManager = OWSIdentityManager.shared()
let seed = Randomness.generateRandomBytes(16)!
let keyPair = Curve25519.generateKeyPair(fromSeed: seed + seed)
let databaseConnection = identityManager.value(forKey: "dbConnection") as! YapDatabaseConnection
databaseConnection.setObject(keyPair, forKey: OWSPrimaryStorageIdentityKeyStoreIdentityKey, inCollection: OWSPrimaryStorageIdentityKeyStoreCollection)
TSAccountManager.sharedInstance().phoneNumberAwaitingVerification = keyPair.hexEncodedPublicKey
TSAccountManager.sharedInstance().didRegister()
}
public static func generateKeyPair() -> ECKeyPair {
return Curve25519.generateKeyPair()
}
public static func getCurrentUserHexEncodedPublicKey() -> String {
return OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey
}
public static func generateHexEncodedPublicKey() -> String {
return generateKeyPair().hexEncodedPublicKey
}
public static func getDevice(for hexEncodedPublicKey: String) -> DeviceLink.Device? {
guard let signature = Data.getSecureRandomData(ofSize: 64) else { return nil }
return DeviceLink.Device(hexEncodedPublicKey: hexEncodedPublicKey, signature: signature)
}
public static func createContactThread(for hexEncodedPublicKey: String) -> TSContactThread {
return TSContactThread.getOrCreateThread(contactId: hexEncodedPublicKey)
}
public static func createGroupThread(groupType: GroupType) -> TSGroupThread? {
let hexEncodedGroupID = Randomness.generateRandomBytes(kGroupIdLength)!.toHexString()
let groupID: Data
switch groupType {
case .closedGroup: groupID = LKGroupUtilities.getEncodedClosedGroupIDAsData(hexEncodedGroupID)
case .openGroup: groupID = LKGroupUtilities.getEncodedOpenGroupIDAsData(hexEncodedGroupID)
case .rssFeed: groupID = LKGroupUtilities.getEncodedRSSFeedIDAsData(hexEncodedGroupID)
default: return nil
}
return TSGroupThread.getOrCreateThread(withGroupId: groupID, groupType: groupType)
}
}

63
Loki/MultiDeviceProtocolTests.swift

@ -1,63 +0,0 @@
/*
import PromiseKit
@testable import SignalServiceKit
import XCTest
class MultiDeviceProtocolTests : XCTestCase {
private var storage: OWSPrimaryStorage { OWSPrimaryStorage.shared() }
override func setUp() {
super.setUp()
LokiTestUtilities.setUpMockEnvironment()
}
// MARK: - isSlaveThread
func test_isSlaveThreadShouldReturnFalseOnGroupThreads() {
let allGroupTypes: [GroupType] = [ .closedGroup, .openGroup, .rssFeed ]
for groupType in allGroupTypes {
guard let groupThread = LokiTestUtilities.createGroupThread(groupType: groupType) else { return XCTFail() }
XCTAssertFalse(MultiDeviceProtocol.isSlaveThread(groupThread))
}
}
func test_isSlaveThreadShouldReturnTheCorrectValues() {
let master = LokiTestUtilities.generateHexEncodedPublicKey()
let slave = LokiTestUtilities.generateHexEncodedPublicKey()
let other = LokiTestUtilities.generateHexEncodedPublicKey()
guard let masterDevice = LokiTestUtilities.getDevice(for: master) else { return XCTFail() }
guard let slaveDevice = LokiTestUtilities.getDevice(for: slave) else { return XCTFail() }
let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
storage.dbReadWriteConnection.readWrite { transaction in
self.storage.addDeviceLink(deviceLink, in: transaction)
}
let masterThread = LokiTestUtilities.createContactThread(for: master)
let slaveThread = LokiTestUtilities.createContactThread(for: slave)
let otherThread = LokiTestUtilities.createContactThread(for: other)
storage.dbReadConnection.read { transaction in
XCTAssertNotNil(self.storage.getMasterHexEncodedPublicKey(for: slaveThread.contactIdentifier(), in: transaction))
}
XCTAssertFalse(MultiDeviceProtocol.isSlaveThread(masterThread))
XCTAssertTrue(MultiDeviceProtocol.isSlaveThread(slaveThread))
XCTAssertFalse(MultiDeviceProtocol.isSlaveThread(otherThread))
}
func test_isSlaveThreadShouldWorkInsideATransaction() {
let bob = LokiTestUtilities.generateHexEncodedPublicKey()
let thread = LokiTestUtilities.createContactThread(for: bob)
storage.dbReadWriteConnection.read { transaction in
XCTAssertNoThrow(MultiDeviceProtocol.isSlaveThread(thread))
}
storage.dbReadWriteConnection.readWrite { transaction in
XCTAssertNoThrow(MultiDeviceProtocol.isSlaveThread(thread))
}
}
}
*/

24
Loki/OnionRequestAPITests.swift

@ -1,24 +0,0 @@
import CryptoSwift
import PromiseKit
@testable import SignalServiceKit
import XCTest
class OnionRequestAPITests : XCTestCase {
private let maxRetryCount: UInt = 2 // Be a bit more stringent when testing
private let testPublicKey = "0501da4723331eb54aaa9a6753a0a59f762103de63f1dc40879cb65a5b5f508814"
func testOnionRequestSending() {
let semaphore = DispatchSemaphore(value: 0)
var error: Error? = nil
LokiAPI.useOnionRequests = true
let _ = attempt(maxRetryCount: maxRetryCount, recoveringOn: LokiAPI.workQueue) { [testPublicKey = self.testPublicKey] in
LokiAPI.getSwarm(for: testPublicKey)
}.done(on: LokiAPI.workQueue) { _ in
semaphore.signal()
}.catch(on: LokiAPI.workQueue) {
error = $0; semaphore.signal()
}
semaphore.wait()
XCTAssert(error == nil)
}
}

9
Loki/SessionManagementProtocolTests.swift

@ -1,9 +0,0 @@
import PromiseKit
@testable import SignalServiceKit
import XCTest
class SessionManagementProtocolTests : XCTestCase {
// TODO: Add tests
}

56
Loki/SyncMessagesProtocolTests.swift

@ -1,56 +0,0 @@
/*
import PromiseKit
@testable import SignalServiceKit
import XCTest
class SyncMessagesProtocolTests : XCTestCase {
private var storage: OWSPrimaryStorage { OWSPrimaryStorage.shared() }
private var messageSender: OWSFakeMessageSender { MockSSKEnvironment.shared.messageSender as! OWSFakeMessageSender }
override func setUp() {
super.setUp()
LokiTestUtilities.setUpMockEnvironment()
}
func testContactSyncMessageHandling() {
// Let's say Alice and Bob have an ongoing conversation. Alice now links a device. Let's call Alice's master device A1
// and her slave device A2, and let's call Bob's device B. When Alice links A2 to A1, A2 needs to somehow establish a
// session with B (it already established a session with A1 when the devices were linked). How does it do this?
//
// As part of the linking process, A2 should've received a contact sync from A1. Upon receiving this contact sync,
// A2 should send out AFRs to the subset of the contacts it received from A1 for which it doesn't yet have a session (in
// theory this should be all of them).
let base64EncodedContactData = "AAAA7QpCMDU0ZmI2M2IxYTU4YjU1YTcwNjMxODkyOWRjNmQxMWM4ZWY3OTAxMTZhNzRjOWFmNTVmYTZhMzZlNjhmMTYzYTMyEhBZMyAoLi4uOGYxNjNhMzIpIgZvcmFuZ2UqaQpCMDU0ZmI2M2IxYTU4YjU1YTcwNjMxODkyOWRjNmQxMWM4ZWY3OTAxMTZhNzRjOWFmNTVmYTZhMzZlNjhmMTYzYTMyEiEFT7Y7Gli1WnBjGJKdxtEcjveQEWp0ya9V+mo25o8WOjIYADIgXAgtAlrJr81tnuWyk8TgJhdsKzz+yIui5mXnbcMyPk1AAAAAAOwKQjA1Nzg4MmQzM2E4OTI1NDdiOTI2NjIyYjk0ZDZjMWNmYjI1ZmY2YTczZmQ4OTZlMWIxNmY1ODI0NzRjZjQ3MDE2YhIQWTQgKC4uLmNmNDcwMTZiKSIFYnJvd24qaQpCMDU3ODgyZDMzYTg5MjU0N2I5MjY2MjJiOTRkNmMxY2ZiMjVmZjZhNzNmZDg5NmUxYjE2ZjU4MjQ3NGNmNDcwMTZiEiEFeILTOoklR7kmYiuU1sHPsl/2pz/YluGxb1gkdM9HAWsYADIgD1QA1ofVIccRhbx8AnbygQYo5iOiyGUMG/sGNP1ENRJAAAAAAPAKQjA1OTUyYTRiNTFjNDJkZWE2OWEwYWNhNWU2OTgxYTQ2MDk0NGI2Yjc0NjdkOWQ5OTliOWU3NjExNzdkYWI1NzIxMxIQWTEgKC4uLmRhYjU3MjEzKSIJYmx1ZV9ncmV5KmkKQjA1OTUyYTRiNTFjNDJkZWE2OWEwYWNhNWU2OTgxYTQ2MDk0NGI2Yjc0NjdkOWQ5OTliOWU3NjExNzdkYWI1NzIxMxIhBZUqS1HELeppoKyl5pgaRglEtrdGfZ2Zm552EXfatXITGAAyIBkyX0S08IAuov6faUvaxYsfJtdpww1G4LF6bG5vG7L+QAA="
let contactData = Data(base64Encoded: base64EncodedContactData)!
let parser = ContactParser(data: contactData)
let hexEncodedPublicKeys = parser.parseHexEncodedPublicKeys()
let expectation = self.expectation(description: "Send friend request messages")
var messageCount = 0
let messageSender = self.messageSender
messageSender.sendMessageWasCalledBlock = { sentMessage in
messageCount += 1
guard sentMessage is FriendRequestMessage else {
return XCTFail("Expected a friend request to be sent, but found: \(sentMessage).")
}
guard messageCount == hexEncodedPublicKeys.count else { return }
expectation.fulfill()
messageSender.sendMessageWasCalledBlock = nil
}
storage.dbReadWriteConnection.readWrite { transaction in
SyncMessagesProtocol.handleContactSyncMessageData(contactData, using: transaction)
}
wait(for: [ expectation ], timeout: 1)
/* TODO: Re-enable when we've split friend request logic from OWSMessageSender
hexEncodedPublicKeys.forEach { hexEncodedPublicKey in
var friendRequestStatus: LKFriendRequestStatus!
storage.dbReadWriteConnection.readWrite { transaction in
friendRequestStatus = self.storage.getFriendRequestStatus(for: hexEncodedPublicKey, transaction: transaction)
}
XCTAssert(friendRequestStatus == .requestSent)
}
*/
// TODO: Test the case where Bob has multiple devices
}
}
*/

47
Loki/XCTest+Utilities.swift

@ -1,47 +0,0 @@
import XCTest
extension XCTestCase {
/// A helper for asynchronous testing.
///
/// Usage example:
///
/// ```
/// func testSomething() {
/// doAsyncThings()
/// eventually {
/// /* XCTAssert goes here... */
/// }
/// }
/// ```
///
/// The provided closure won't execute until `timeout` seconds have passed. Pass
/// in a timeout long enough for your asynchronous process to finish if it's
/// expected to take more than the default 0.1 second.
///
/// - Parameters:
/// - timeout: number of seconds to wait before executing `closure`.
/// - closure: a closure to execute when `timeout` seconds have passed.
///
/// - Note: `timeout` must be less than 60 seconds.
func eventually(timeout: TimeInterval = 0.1, closure: @escaping () -> Void) {
assert(timeout < 60)
let expectation = self.expectation(description: "")
expectation.fulfillAfter(timeout)
self.waitForExpectations(timeout: 60) { _ in
closure()
}
}
}
extension XCTestExpectation {
/// Call `fulfill()` after some time.
///
/// - Parameter time: number of seconds after which `fulfill()` will be called.
func fulfillAfter(_ time: TimeInterval) {
DispatchQueue.main.asyncAfter(deadline: .now() + time) {
self.fulfill()
}
}
}

45
Makefile

@ -1,45 +0,0 @@
# Make sure we're failing even though we pipe to xcpretty
SHELL=/bin/bash -o pipefail -o errexit
WORKING_DIR = ./
THIRD_PARTY_DIR = $(WORKING_DIR)/ThirdParty
SCHEME = Signal
XCODE_BUILD = xcrun xcodebuild -workspace $(SCHEME).xcworkspace -scheme $(SCHEME) -sdk iphonesimulator
.PHONY: build test retest clean dependencies
default: test
update_dependencies:
bundle exec pod update
carthage update --platform iOS
setup:
rbenv install -s
gem install bundler
bundle install
dependencies:
cd $(WORKING_DIR) && \
git submodule update --init
cd $(THIRD_PARTY_DIR) && \
carthage build --platform iOS
build: dependencies
cd $(WORKING_DIR) && \
$(XCODE_BUILD) build | xcpretty
test:
bundle exec fastlane test
clean: clean_carthage
cd $(WORKING_DIR) && \
$(XCODE_BUILD) clean | xcpretty
clean_carthage:
cd $(THIRD_PARTY_DIR) && \
rm -fr Carthage/Build
# Migrating across swift versions requires me to run this sometimes
clean_carthage_cache:
rm -fr ~/Library/Caches/org.carthage.CarthageKit/

106
Scripts/AuditStringH.py

@ -1,106 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
import subprocess
import datetime
import argparse
import commands
import re
git_repo_path = os.path.abspath(subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).strip())
string_h_functions = [
"memchr",
"memcmp",
"memcpy",
"memmove",
"memset",
"strcat",
"strchr",
"strcmp",
"strcoll",
"strcpy",
"strcspn",
"strerror",
"strlen",
"strncat",
"strncmp",
"strncpy",
"strpbrk",
"strrchr",
"strspn",
"strstr",
"strtok",
"strxfrm",
"strtok_r",
"strerror_r",
"strdup",
"memccpy",
"stpcpy",
"stpncpy",
"strndup",
"strnlen",
"strsignal",
"memset_s",
"memmem",
"memset_pattern4",
"memset_pattern8",
"memset_pattern16",
"strcasestr",
"strnstr",
"strlcat",
"strlcpy",
"strmode",
"strsep",
"swab",
"timingsafe_bcmp",
]
def process_if_appropriate(file_path):
file_ext = os.path.splitext(file_path)[1]
if file_ext.lower() not in ('.c', '.cpp', '.m', '.mm', '.h', '.swift'):
return
# print 'file_path', file_path, 'file_ext', file_ext
with open(file_path, 'rt') as f:
text = f.read()
has_match = False
for string_h_function in string_h_functions:
regex = re.compile(string_h_function + r'\s*\(')
assert(regex)
matches = []
for match in regex.finditer(text):
matches.append(match)
# matches = regex.findall(text)
if not matches:
continue
if not has_match:
has_match = True
print 'file_path', file_path, 'file_ext', file_ext
for match in matches:
# print 'match', match, type(match)
print '\t', 'match:', match.group(0)
if has_match:
print
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Precommit script.')
parser.add_argument('--path', help='used to specify a path to process.')
args = parser.parse_args()
if args.path:
dir_path = args.path
else:
dir_path = git_repo_path
for rootdir, dirnames, filenames in os.walk(dir_path):
for filename in filenames:
file_path = os.path.abspath(os.path.join(rootdir, filename))
process_if_appropriate(file_path)

3
Scripts/ClearDerivedData.sh

@ -1,3 +0,0 @@
#!/bin/bash
rm -rf ~/Library/Developer/Xcode/DerivedData

4
Scripts/HardResetGit.sh

@ -1,4 +0,0 @@
#!/bin/bash
git reset --hard HEAD
git clean -xdff

206
Scripts/bump_build_tag.py

@ -1,206 +0,0 @@
#!/usr/bin/env python
import sys
import os
import re
import commands
import subprocess
import argparse
import inspect
def fail(message):
file_name = __file__
current_line_no = inspect.stack()[1][2]
current_function_name = inspect.stack()[1][3]
print 'Failure in:', file_name, current_line_no, current_function_name
print message
sys.exit(1)
def execute_command(command):
try:
print ' '.join(command)
output = subprocess.check_output(command)
if output:
print output
except subprocess.CalledProcessError as e:
print e.output
sys.exit(1)
def find_project_root():
path = os.path.abspath(os.curdir)
while True:
# print 'path', path
if not os.path.exists(path):
break
git_path = os.path.join(path, '.git')
if os.path.exists(git_path):
return path
new_path = os.path.abspath(os.path.dirname(path))
if not new_path or new_path == path:
break
path = new_path
fail('Could not find project root path')
def is_valid_release_version(value):
regex = re.compile(r'^(\d+)\.(\d+)\.(\d+)$')
match = regex.search(value)
return match is not None
def is_valid_build_version(value):
regex = re.compile(r'^(\d+)\.(\d+)\.(\d+)\.(\d+)$')
match = regex.search(value)
return match is not None
def set_versions(plist_file_path, release_version, build_version):
if not is_valid_release_version(release_version):
fail('Invalid release version: %s' % release_version)
if not is_valid_build_version(build_version):
fail('Invalid build version: %s' % build_version)
with open(plist_file_path, 'rt') as f:
text = f.read()
# print 'text', text
# The "short" version is the release number.
#
# <key>CFBundleShortVersionString</key>
# <string>2.20.0</string>
file_regex = re.compile(r'<key>CFBundleShortVersionString</key>\s*<string>([\d\.]+)</string>', re.MULTILINE)
file_match = file_regex.search(text)
# print 'match', match
if not file_match:
fail('Could not parse .plist')
text = text[:file_match.start(1)] + release_version + text[file_match.end(1):]
# The "long" version is the build number.
#
# <key>CFBundleVersion</key>
# <string>2.20.0.3</string>
file_regex = re.compile(r'<key>CFBundleVersion</key>\s*<string>([\d\.]+)</string>', re.MULTILINE)
file_match = file_regex.search(text)
# print 'match', match
if not file_match:
fail('Could not parse .plist')
text = text[:file_match.start(1)] + build_version + text[file_match.end(1):]
with open(plist_file_path, 'wt') as f:
f.write(text)
def get_versions(plist_file_path):
with open(plist_file_path, 'rt') as f:
text = f.read()
# print 'text', text
# <key>CFBundleVersion</key>
# <string>2.13.0.13</string>
file_regex = re.compile(r'<key>CFBundleVersion</key>\s*<string>([\d\.]+)</string>', re.MULTILINE)
file_match = file_regex.search(text)
# print 'match', match
if not file_match:
fail('Could not parse .plist')
# e.g. "2.13.0.13"
old_build_version = file_match.group(1)
print 'old_build_version:', old_build_version
if not is_valid_build_version(old_build_version):
fail('Invalid build version: %s' % old_build_version)
build_number_regex = re.compile(r'\.(\d+)$')
build_number_match = build_number_regex.search(old_build_version)
if not build_number_match:
fail('Could not parse .plist version')
# e.g. "13"
old_build_number = build_number_match.group(1)
print 'old_build_number:', old_build_number
release_number_regex = re.compile(r'^(.+)\.\d+$')
release_number_match = release_number_regex.search(old_build_version)
if not release_number_match:
fail('Could not parse .plist')
# e.g. "2.13.0"
old_release_version = release_number_match.group(1)
print 'old_release_version:', old_release_version
# Given "2.13.0.13", this should return "2.13.0" and "13" as strings.
return old_release_version, old_build_number
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Precommit cleanup script.')
parser.add_argument('--version', help='used for starting a new version.')
args = parser.parse_args()
project_root_path = find_project_root()
# print 'project_root_path', project_root_path
# plist_path
main_plist_path = os.path.join(project_root_path, 'Signal', 'Signal-Info.plist')
if not os.path.exists(main_plist_path):
fail('Could not find main app info .plist')
share_ext_plist_path = os.path.join(project_root_path, 'SignalShareExtension', 'Info.plist')
if not os.path.exists(share_ext_plist_path):
fail('Could not find share extension info .plist')
output = subprocess.check_output(['git', 'status', '--porcelain'])
if len(output.strip()) > 0:
print output
fail('Git repository has untracked files.')
output = subprocess.check_output(['git', 'diff', '--shortstat'])
if len(output.strip()) > 0:
print output
fail('Git repository has untracked files.')
# Ensure .plist is in xml format, not binary.
output = subprocess.check_output(['plutil', '-convert', 'xml1', main_plist_path])
output = subprocess.check_output(['plutil', '-convert', 'xml1', share_ext_plist_path])
# print 'output', output
# ---------------
# Main App
# ---------------
old_release_version, old_build_number = get_versions(main_plist_path)
if args.version:
# e.g. --version 1.2.3 -> "1.2.3", "1.2.3.0"
new_release_version = args.version.strip()
new_build_version = new_release_version + ".0"
else:
new_build_number = str(1 + int(old_build_number))
print 'new_build_number:', new_build_number
new_release_version = old_release_version
new_build_version = old_release_version + "." + new_build_number
print 'new_release_version:', new_release_version
print 'new_build_version:', new_build_version
set_versions(main_plist_path, new_release_version, new_build_version)
# ---------------
# Share Extension
# ---------------
set_versions(share_ext_plist_path, new_release_version, new_build_version)
# ---------------
# Git
# ---------------
command = ['git', 'add', '.']
execute_command(command)
command = ['git', 'commit', '-m', '"Bump build to %s."' % new_build_version]
execute_command(command)
command = ['git', 'tag', new_build_version]
execute_command(command)

73
Scripts/debug_log_upload.py

@ -1,73 +0,0 @@
#!/usr/bin/env python
import sys
import os
import re
import commands
import subprocess
import argparse
import inspect
import urllib2
import json
def fail(message):
file_name = __file__
current_line_no = inspect.stack()[1][2]
current_function_name = inspect.stack()[1][3]
print 'Failure in:', file_name, current_line_no, current_function_name
print message
sys.exit(1)
def execute_command(command):
try:
print ' '.join(command)
output = subprocess.check_output(command)
if output:
print output
except subprocess.CalledProcessError as e:
print e.output
sys.exit(1)
def add_field(curl_command, form_key, form_value):
curl_command.append('-F')
curl_command.append("%s=%s" % (form_key, form_value))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Precommit cleanup script.')
parser.add_argument('--file', required=True, help='used for starting a new version.')
args = parser.parse_args()
params_response = urllib2.urlopen("https://debuglogs.org/").read()
params = json.loads(params_response)
upload_url = params['url']
upload_fields = params['fields']
upload_key = upload_fields.pop('key')
upload_key = upload_key + os.path.splitext(args.file)[1]
download_url = 'https://debuglogs.org/' + upload_key
print 'download_url:', download_url
curl_command = ['curl', '-v', '-i', '-X', 'POST']
# key must appear before other fields
add_field(curl_command, 'key', upload_key)
for field_name in upload_fields:
add_field(curl_command, field_name, upload_fields[field_name])
add_field(curl_command, "content-type", "application/octet-stream")
curl_command.append('-F')
curl_command.append("file=@%s" % (args.file,))
curl_command.append(upload_url)
print ' '.join(curl_command)
print 'Running...'
execute_command(curl_command)
print 'download_url:', download_url

679
Scripts/emoji-data.txt

@ -1,679 +0,0 @@
# emoji-data.txt
# Date: 2017-08-10, 11:51:32 GMT
# ยฉ 2017 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 UTR #51
# Version: 6.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] (โ˜‘๏ธ) ballot 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
2660 ; Emoji # 1.1 [1] (โ™ ๏ธ) 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
267F ; Emoji # 4.1 [1] (โ™ฟ) 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] (โœ…) white heavy check mark
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] (โœ”๏ธ) heavy check mark
2716 ; Emoji # 1.1 [1] (โœ–๏ธ) heavy multiplication x
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] (โฃ๏ธ..โค๏ธ) heavy heart exclamation..red heart
2795..2797 ; Emoji # 6.0 [3] (โž•..โž—) heavy plus sign..heavy 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] (โญ) white medium star
2B55 ; Emoji # 5.2 [1] (โญ•) heavy large 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..down 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 face
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
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
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
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
1F950..1F95E ; Emoji # 9.0 [15] (๐Ÿฅ..๐Ÿฅž) croissant..pancakes
1F95F..1F96B ; Emoji # 10.0 [13] (๐ŸฅŸ..๐Ÿฅซ) dumpling..canned food
1F980..1F984 ; Emoji # 8.0 [5] (๐Ÿฆ€..๐Ÿฆ„) crab..unicorn face
1F985..1F991 ; Emoji # 9.0 [13] (๐Ÿฆ…..๐Ÿฆ‘) eagle..squid
1F992..1F997 ; Emoji # 10.0 [6] (๐Ÿฆ’..๐Ÿฆ—) giraffe..cricket
1F9C0 ; Emoji # 8.0 [1] (๐Ÿง€) cheese wedge
1F9D0..1F9E6 ; Emoji # 10.0 [23] (๐Ÿง..๐Ÿงฆ) face with monocle..socks
# Total elements: 1182
# ================================================
# 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] (โœ…) white heavy check mark
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] (โž•..โž—) heavy plus sign..heavy 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] (โญ) white medium star
2B55 ; Emoji_Presentation # 5.2 [1] (โญ•) heavy large 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..down 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 face
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
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
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
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
1F950..1F95E ; Emoji_Presentation # 9.0 [15] (๐Ÿฅ..๐Ÿฅž) croissant..pancakes
1F95F..1F96B ; Emoji_Presentation # 10.0 [13] (๐ŸฅŸ..๐Ÿฅซ) dumpling..canned food
1F980..1F984 ; Emoji_Presentation # 8.0 [5] (๐Ÿฆ€..๐Ÿฆ„) crab..unicorn face
1F985..1F991 ; Emoji_Presentation # 9.0 [13] (๐Ÿฆ…..๐Ÿฆ‘) eagle..squid
1F992..1F997 ; Emoji_Presentation # 10.0 [6] (๐Ÿฆ’..๐Ÿฆ—) giraffe..cricket
1F9C0 ; Emoji_Presentation # 8.0 [1] (๐Ÿง€) cheese wedge
1F9D0..1F9E6 ; Emoji_Presentation # 10.0 [23] (๐Ÿง..๐Ÿงฆ) face with monocle..socks
# Total elements: 966
# ================================================
# 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