@@ -99,20 +28,20 @@ Welcome to Pyrogram
.. code-block:: python
- from pyrogram import Client, Filters
+ from pyrogram import Client, filters
app = Client("my_account")
- @app.on_message(Filters.private)
- def hello(client, message):
- message.reply_text(f"Hello {message.from_user.first_name}")
+ @app.on_message(filters.private)
+ async def hello(client, message):
+ await message.reply_text(f"Hello {message.from_user.mention}")
app.run()
-**Pyrogram** is an elegant, easy-to-use Telegram_ client library and framework written from the ground up in Python and
-C. It enables you to easily create custom apps for both user and bot identities (bot API alternative) via the
+**Pyrogram** is a modern, elegant and easy-to-use Telegram_ framework written from the ground up in Python and C.
+It enables you to easily create custom apps for both user and bot identities (bot API alternative) via the
:doc:`MTProto API
`.
.. _Telegram: https://telegram.org
@@ -120,9 +49,9 @@ C. It enables you to easily create custom apps for both user and bot identities
How the Documentation is Organized
----------------------------------
-Contents are organized into self-contained topics and can be all accessed from the sidebar, or by following them in
-order using the :guilabel:`Next` button at the end of each page. Here below you can, instead, find a list of the most
-relevant pages for a quick access.
+Contents are organized into sections composed of self-contained topics which can be all accessed from the sidebar, or by
+following them in order using the :guilabel:`Next` button at the end of each page. Here below you can, instead, find a
+list of the most relevant pages for a quick access.
First Steps
^^^^^^^^^^^
@@ -159,4 +88,77 @@ Meta
- :doc:`About the License `: Information about the Project license.
- :doc:`Release Notes `: Release notes for Pyrogram releases.
-Last updated on |today|
\ No newline at end of file
+Last updated on |today|
+
+.. toctree::
+ :hidden:
+ :caption: Introduction
+
+ intro/quickstart
+ intro/install
+ intro/setup
+
+.. toctree::
+ :hidden:
+ :caption: Getting Started
+
+ start/auth
+ start/invoking
+ start/updates
+ start/errors
+ start/examples/index
+
+.. toctree::
+ :hidden:
+ :caption: API Reference
+
+ api/client
+ api/methods/index
+ api/types/index
+ api/bound-methods/index
+ api/handlers
+ api/decorators
+ api/errors/index
+ api/filters
+
+.. toctree::
+ :hidden:
+ :caption: Topic Guides
+
+ topics/use-filters
+ topics/create-filters
+ topics/more-on-updates
+ topics/config-file
+ topics/smart-plugins
+ topics/session-settings
+ topics/tgcrypto
+ topics/storage-engines
+ topics/text-formatting
+ topics/serializing
+ topics/proxy
+ topics/scheduling
+ topics/bots-interaction
+ topics/mtproto-vs-botapi
+ topics/debugging
+ topics/test-servers
+ topics/advanced-usage
+ topics/voice-calls
+
+.. toctree::
+ :hidden:
+ :caption: Meta
+
+ faq
+ glossary
+ powered-by
+ support-pyrogram
+ license
+ releases/index
+
+.. toctree::
+ :hidden:
+ :caption: Telegram API
+
+ telegram/functions/index
+ telegram/types/index
+ telegram/base/index
\ No newline at end of file
diff --git a/docs/source/intro/install.rst b/docs/source/intro/install.rst
index 5312e44a84..9056d1f50f 100644
--- a/docs/source/intro/install.rst
+++ b/docs/source/intro/install.rst
@@ -1,18 +1,19 @@
Install Guide
=============
-Being a Python library, **Pyrogram** requires Python to be installed in your system.
+Being a modern Python library, **Pyrogram** requires Python 3.6+ to be installed in your system.
We recommend using the latest versions of both Python 3 and pip.
-- Get **Python 3** from https://www.python.org/downloads/ (or with your package manager)
+- Get **Python 3** from https://www.python.org/downloads/ (or with your package manager).
- Get **pip** by following the instructions at https://pip.pypa.io/en/latest/installing/.
.. important::
- Pyrogram supports **Python 3** only, starting from version 3.5.3. **PyPy** is supported too.
+ Pyrogram supports **Python 3** only, starting from version 3.6. **PyPy** is supported too.
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
@@ -46,43 +47,6 @@ the link):
$ pip3 install -U https://github.com/pyrogram/pyrogram/archive/develop.zip
-Asynchronous
-------------
-
-Pyrogram heavily depends on IO-bound network code (it's a cloud-based messaging framework after all), and here's
-where asyncio shines the most by providing extra performance and efficiency while running on a single OS-level thread
-only.
-
-**A fully asynchronous variant of Pyrogram is therefore available** (Python 3.5.3 or higher is required).
-Use this command to install (note "asyncio.zip" in the link):
-
-.. code-block:: text
-
- $ pip3 install -U https://github.com/pyrogram/pyrogram/archive/asyncio.zip
-
-
-Pyrogram's API remains the same and features are kept up to date from the non-async, default develop branch, but you
-are obviously required Python asyncio knowledge in order to take full advantage of it.
-
-
-.. tip::
-
- The idea to turn Pyrogram fully asynchronous is still under consideration, but is wise to expect that in future this
- would be the one and only way to work with Pyrogram.
-
- You can start using Pyrogram Async variant right now as an excuse to learn more about asynchronous programming and
- do experiments with it!
-
-.. raw:: html
-
-
-
-.. centered:: Subscribe to `@Pyrogram `_ for news and announcements
-
Verifying
---------
diff --git a/docs/source/intro/quickstart.rst b/docs/source/intro/quickstart.rst
index 13f646d1cb..593403b99c 100644
--- a/docs/source/intro/quickstart.rst
+++ b/docs/source/intro/quickstart.rst
@@ -1,8 +1,8 @@
Quick Start
===========
-The next few steps serve as a quick start for all new Pyrogrammers that want to get something done as fast as possible.
-Let's go!
+The next few steps serve as a quick start for all new Pyrogrammers that want to see Pyrogram in action as fast as
+possible. Let's go!
Get Pyrogram Real Fast
----------------------
diff --git a/docs/source/intro/setup.rst b/docs/source/intro/setup.rst
index f5bf607b3a..e4c6e64065 100644
--- a/docs/source/intro/setup.rst
+++ b/docs/source/intro/setup.rst
@@ -6,6 +6,7 @@ project with the library. Let's see how it's done.
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
diff --git a/docs/source/powered-by.rst b/docs/source/powered-by.rst
index 77e593e7ca..6fee50b25c 100644
--- a/docs/source/powered-by.rst
+++ b/docs/source/powered-by.rst
@@ -11,6 +11,7 @@ This is a collection of remarkable projects made with Pyrogram.
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
diff --git a/docs/source/start/auth.rst b/docs/source/start/auth.rst
index 0bbd4c5e4c..23ff9fe276 100644
--- a/docs/source/start/auth.rst
+++ b/docs/source/start/auth.rst
@@ -6,6 +6,7 @@ API calls. This section provides all the information you need in order to author
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
@@ -41,7 +42,7 @@ keep the session alive, Pyrogram won't ask you again to enter your phone number.
.. important::
- Your ``*.session`` files are personal and must be kept secret.
+ Your ``*.session`` file is personal and must be kept secret.
.. note::
diff --git a/docs/source/start/errors.rst b/docs/source/start/errors.rst
index a9707d0895..ff9ccf5b59 100644
--- a/docs/source/start/errors.rst
+++ b/docs/source/start/errors.rst
@@ -10,6 +10,7 @@ to control the behaviour of your application. Pyrogram errors all live inside th
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
@@ -17,9 +18,8 @@ to control the behaviour of your application. Pyrogram errors all live inside th
RPCError
--------
-The father of all errors is named ``RPCError``. This error exists in form of a Python exception which is directly
-subclass-ed from Python's main ``Exception`` and is able to catch all Telegram API related errors. This error is raised
-every time a method call against Telegram's API was unsuccessful.
+The father of all errors is named ``RPCError`` and is able to catch all Telegram API related errors.
+This error is raised every time a method call against Telegram's API was unsuccessful.
.. code-block:: python
@@ -34,19 +34,19 @@ Error Categories
----------------
The ``RPCError`` packs together all the possible errors Telegram could raise, but to make things tidier, Pyrogram
-provides categories of errors, which are named after the common HTTP errors and are subclass-ed from the RPCError:
+provides categories of errors, which are named after the common HTTP errors and are subclass-ed from the ``RPCError``:
.. code-block:: python
from pyrogram.errors import BadRequest, Forbidden, ...
-- `303 - SeeOther <../api/errors#seeother>`_
-- `400 - BadRequest <../api/errors#badrequest>`_
-- `401 - Unauthorized <../api/errors#unauthorized>`_
-- `403 - Forbidden <../api/errors#forbidden>`_
-- `406 - NotAcceptable <../api/errors#notacceptable>`_
-- `420 - Flood <../api/errors#flood>`_
-- `500 - InternalServerError <../api/errors#internalservererror>`_
+- :doc:`303 - SeeOther <../api/errors/see-other>`
+- :doc:`400 - BadRequest <../api/errors/bad-request>`
+- :doc:`401 - Unauthorized <../api/errors/unauthorized>`
+- :doc:`403 - Forbidden <../api/errors/forbidden>`
+- :doc:`406 - NotAcceptable <../api/errors/not-acceptable>`
+- :doc:`420 - Flood <../api/errors/flood>`
+- :doc:`500 - InternalServerError <../api/errors/internal-server-error>`
Single Errors
-------------
@@ -59,7 +59,7 @@ issue. For example:
from pyrogram.errors import FloodWait
These errors subclass directly from the category of errors they belong to, which in turn subclass from the father
-RPCError, thus building a class of error hierarchy such as this:
+``RPCError``, thus building a class of error hierarchy such as this:
- RPCError
- BadRequest
diff --git a/docs/source/start/examples/bot_keyboards.rst b/docs/source/start/examples/bot_keyboards.rst
new file mode 100644
index 0000000000..343e22c927
--- /dev/null
+++ b/docs/source/start/examples/bot_keyboards.rst
@@ -0,0 +1,61 @@
+bot_keyboards
+=============
+
+This example will show you how to send normal and inline keyboards (as bot).
+
+You must log-in as a regular bot in order to send keyboards (use the token from @BotFather).
+Any attempt in sending keyboards with a user account will be simply ignored by the server.
+
+send_message() is used as example, but a keyboard can be sent with any other send_* methods,
+like send_audio(), send_document(), send_location(), etc...
+
+.. code-block:: python
+
+ from pyrogram import Client, ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton
+
+ # Create a client using your bot token
+ app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
+
+ with app:
+ app.send_message(
+ "haskell", # Edit this
+ "This is a ReplyKeyboardMarkup example",
+ reply_markup=ReplyKeyboardMarkup(
+ [
+ ["A", "B", "C", "D"], # First row
+ ["E", "F", "G"], # Second row
+ ["H", "I"], # Third row
+ ["J"] # Fourth row
+ ],
+ resize_keyboard=True # Make the keyboard smaller
+ )
+ )
+
+ app.send_message(
+ "haskell", # Edit this
+ "This is a InlineKeyboardMarkup example",
+ reply_markup=InlineKeyboardMarkup(
+ [
+ [ # First row
+ InlineKeyboardButton( # Generates a callback query when pressed
+ "Button",
+ callback_data="data"
+ ),
+ InlineKeyboardButton( # Opens a web URL
+ "URL",
+ url="https://docs.pyrogram.org"
+ ),
+ ],
+ [ # Second row
+ InlineKeyboardButton( # Opens the inline interface
+ "Choose chat",
+ switch_inline_query="pyrogram"
+ ),
+ InlineKeyboardButton( # Opens the inline interface in the current chat
+ "Inline here",
+ switch_inline_query_current_chat="pyrogram"
+ )
+ ]
+ ]
+ )
+ )
diff --git a/docs/source/start/examples/callback_queries.rst b/docs/source/start/examples/callback_queries.rst
new file mode 100644
index 0000000000..73273058a1
--- /dev/null
+++ b/docs/source/start/examples/callback_queries.rst
@@ -0,0 +1,19 @@
+callback_queries
+================
+
+This example shows how to handle callback queries, i.e.: queries coming from inline button presses.
+It uses the @on_callback_query decorator to register a CallbackQueryHandler.
+
+.. code-block:: python
+
+ from pyrogram import Client
+
+ app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
+
+
+ @app.on_callback_query()
+ def answer(client, callback_query):
+ callback_query.answer(f"Button contains: '{callback_query.data}'", show_alert=True)
+
+
+ app.run() # Automatically start() and idle()
\ No newline at end of file
diff --git a/docs/source/start/examples/echobot.rst b/docs/source/start/examples/echobot.rst
new file mode 100644
index 0000000000..a751a2cddd
--- /dev/null
+++ b/docs/source/start/examples/echobot.rst
@@ -0,0 +1,21 @@
+echobot
+=======
+
+This simple echo bot replies to every private text message.
+
+It uses the @on_message decorator to register a MessageHandler and applies two filters on it:
+Filters.text and Filters.private to make sure it will reply to private text messages only.
+
+.. code-block:: python
+
+ from pyrogram import Client, Filters
+
+ app = Client("my_account")
+
+
+ @app.on_message(Filters.text & Filters.private)
+ def echo(client, message):
+ message.reply(message.text)
+
+
+ app.run() # Automatically start() and idle()
\ No newline at end of file
diff --git a/docs/source/start/examples/get_chat_members.rst b/docs/source/start/examples/get_chat_members.rst
new file mode 100644
index 0000000000..8d47797604
--- /dev/null
+++ b/docs/source/start/examples/get_chat_members.rst
@@ -0,0 +1,15 @@
+get_chat_members
+================
+
+This example shows how to get all the members of a chat.
+
+.. code-block:: python
+
+ from pyrogram import Client
+
+ app = Client("my_account")
+ target = "pyrogramchat" # Target channel/supergroup
+
+ with app:
+ for member in app.iter_chat_members(target):
+ print(member.user.first_name)
\ No newline at end of file
diff --git a/docs/source/start/examples/get_dialogs.rst b/docs/source/start/examples/get_dialogs.rst
new file mode 100644
index 0000000000..b1a4806427
--- /dev/null
+++ b/docs/source/start/examples/get_dialogs.rst
@@ -0,0 +1,14 @@
+get_dialogs
+===========
+
+This example shows how to get the full dialogs list (as user).
+
+.. code-block:: python
+
+ from pyrogram import Client
+
+ app = Client("my_account")
+
+ with app:
+ for dialog in app.iter_dialogs():
+ print(dialog.chat.title or dialog.chat.first_name)
\ No newline at end of file
diff --git a/docs/source/start/examples/get_history.rst b/docs/source/start/examples/get_history.rst
new file mode 100644
index 0000000000..01433d91fe
--- /dev/null
+++ b/docs/source/start/examples/get_history.rst
@@ -0,0 +1,15 @@
+get_history
+===========
+
+This example shows how to get the full message history of a chat, starting from the latest message.
+
+.. code-block:: python
+
+ from pyrogram import Client
+
+ app = Client("my_account")
+ target = "me" # "me" refers to your own chat (Saved Messages)
+
+ with app:
+ for message in app.iter_history(target):
+ print(message.text)
\ No newline at end of file
diff --git a/docs/source/start/examples/hello_world.rst b/docs/source/start/examples/hello_world.rst
new file mode 100644
index 0000000000..e68847798a
--- /dev/null
+++ b/docs/source/start/examples/hello_world.rst
@@ -0,0 +1,21 @@
+hello_world
+===========
+
+This example demonstrates a basic API usage
+
+.. code-block:: python
+
+ from pyrogram import Client
+
+ # Create a new Client instance
+ app = Client("my_account")
+
+ with app:
+ # Send a message, Markdown is enabled by default
+ app.send_message("me", "Hi there! I'm using **Pyrogram**")
+
+ # Send a location
+ app.send_location("me", 51.500729, -0.124583)
+
+ # Send a sticker
+ app.send_sticker("me", "CAADBAADzg4AAvLQYAEz_x2EOgdRwBYE")
\ No newline at end of file
diff --git a/docs/source/start/examples/index.rst b/docs/source/start/examples/index.rst
new file mode 100644
index 0000000000..7d8a69a41d
--- /dev/null
+++ b/docs/source/start/examples/index.rst
@@ -0,0 +1,46 @@
+Examples
+========
+
+This page contains example scripts to show you how Pyrogram looks like.
+
+Every script is working right away (provided you correctly set up your credentials), meaning you can simply copy-paste
+and run. The only things you have to change are session names and target chats, where applicable.
+
+The examples listed below can be treated as building blocks for your own applications and are meant to be simple enough
+to give you a basic idea.
+
+-----
+
+.. csv-table::
+ :header: Example, Description
+ :widths: auto
+ :align: center
+
+ :doc:`hello_world`, "Demonstration of basic API usage"
+ :doc:`echobot`, "Echo every private text message"
+ :doc:`welcomebot`, "The Welcome Bot in @PyrogramChat"
+ :doc:`get_history`, "Get the full message history of a chat"
+ :doc:`get_chat_members`, "Get all the members of a chat"
+ :doc:`get_dialogs`, "Get all of your dialog chats"
+ :doc:`callback_queries`, "Handle callback queries (as bot) coming from inline button presses"
+ :doc:`inline_queries`, "Handle inline queries (as bot) and answer with results"
+ :doc:`use_inline_bots`, "Query an inline bot (as user) and send a result to a chat"
+ :doc:`bot_keyboards`, "Send normal and inline keyboards using regular bots"
+ :doc:`raw_updates`, "Handle raw updates (old, should be avoided)"
+
+For more advanced examples, see https://snippets.pyrogram.org.
+
+.. toctree::
+ :hidden:
+
+ hello_world
+ echobot
+ welcomebot
+ get_history
+ get_chat_members
+ get_dialogs
+ callback_queries
+ inline_queries
+ use_inline_bots
+ bot_keyboards
+ raw_updates
diff --git a/docs/source/start/examples/inline_queries.rst b/docs/source/start/examples/inline_queries.rst
new file mode 100644
index 0000000000..158394e8d1
--- /dev/null
+++ b/docs/source/start/examples/inline_queries.rst
@@ -0,0 +1,61 @@
+inline_queries
+==============
+
+This example shows how to handle inline queries.
+
+Two results are generated when users invoke the bot inline mode, e.g.: @pyrogrambot hi.
+It uses the @on_inline_query decorator to register an InlineQueryHandler.
+
+.. code-block:: python
+
+ from pyrogram import (
+ Client, InlineQueryResultArticle, InputTextMessageContent, InlineKeyboardMarkup, InlineKeyboardButton
+ )
+
+ app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
+
+
+ @app.on_inline_query()
+ def answer(client, inline_query):
+ inline_query.answer(
+ results=[
+ InlineQueryResultArticle(
+ title="Installation",
+ input_message_content=InputTextMessageContent(
+ "Here's how to install **Pyrogram**"
+ ),
+ url="https://docs.pyrogram.org/intro/install",
+ description="How to install Pyrogram",
+ thumb_url="https://i.imgur.com/JyxrStE.png",
+ reply_markup=InlineKeyboardMarkup(
+ [
+ [InlineKeyboardButton(
+ "Open website",
+ url="https://docs.pyrogram.org/intro/install"
+ )]
+ ]
+ )
+ ),
+ InlineQueryResultArticle(
+ title="Usage",
+ input_message_content=InputTextMessageContent(
+ "Here's how to use **Pyrogram**"
+ ),
+ url="https://docs.pyrogram.org/start/invoking",
+ description="How to use Pyrogram",
+ thumb_url="https://i.imgur.com/JyxrStE.png",
+ reply_markup=InlineKeyboardMarkup(
+ [
+ [InlineKeyboardButton(
+ "Open website",
+ url="https://docs.pyrogram.org/start/invoking"
+ )]
+ ]
+ )
+ )
+ ],
+ cache_time=1
+ )
+
+
+ app.run() # Automatically start() and idle()
\ No newline at end of file
diff --git a/docs/source/start/examples/raw_updates.rst b/docs/source/start/examples/raw_updates.rst
new file mode 100644
index 0000000000..6086a9686c
--- /dev/null
+++ b/docs/source/start/examples/raw_updates.rst
@@ -0,0 +1,18 @@
+raw_updates
+===========
+
+This example shows how to handle raw updates.
+
+.. code-block:: python
+
+ from pyrogram import Client
+
+ app = Client("my_account")
+
+
+ @app.on_raw_update()
+ def raw(client, update, users, chats):
+ print(update)
+
+
+ app.run() # Automatically start() and idle()
diff --git a/docs/source/start/examples/use_inline_bots.rst b/docs/source/start/examples/use_inline_bots.rst
new file mode 100644
index 0000000000..284432d8a0
--- /dev/null
+++ b/docs/source/start/examples/use_inline_bots.rst
@@ -0,0 +1,18 @@
+use_inline_bots
+===============
+
+This example shows how to query an inline bot (as user).
+
+.. code-block:: python
+
+ from pyrogram import Client
+
+ # Create a new Client
+ app = Client("my_account")
+
+ with app:
+ # Get bot results for "Fuzz Universe" from the inline bot @vid
+ bot_results = app.get_inline_bot_results("vid", "Fuzz Universe")
+
+ # Send the first result (bot_results.results[0]) to your own chat (Saved Messages)
+ app.send_inline_bot_result("me", bot_results.query_id, bot_results.results[0].id)
\ No newline at end of file
diff --git a/docs/source/start/examples/welcomebot.rst b/docs/source/start/examples/welcomebot.rst
new file mode 100644
index 0000000000..a3bb32998a
--- /dev/null
+++ b/docs/source/start/examples/welcomebot.rst
@@ -0,0 +1,33 @@
+welcomebot
+==========
+
+This is the Welcome Bot in @PyrogramChat.
+
+It uses the Emoji module to easily add emojis in your text messages and Filters
+to make it only work for specific messages in a specific chat.
+
+.. code-block:: python
+
+ from pyrogram import Client, Emoji, Filters
+
+ TARGET = "PyrogramChat" # Target chat. Can also be a list of multiple chat ids/usernames
+ MENTION = "[{}](tg://user?id={})" # User mention markup
+ MESSAGE = "{} Welcome to [Pyrogram](https://docs.pyrogram.org/)'s group chat {}!" # Welcome message
+
+ app = Client("my_account")
+
+
+ # Filter in only new_chat_members updates generated in TARGET chat
+ @app.on_message(Filters.chat(TARGET) & Filters.new_chat_members)
+ def welcome(client, message):
+ # Build the new members list (with mentions) by using their first_name
+ new_members = [MENTION.format(i.first_name, i.id) for i in message.new_chat_members]
+
+ # Build the welcome message by using an emoji and the list we built above
+ text = MESSAGE.format(Emoji.SPARKLES, ", ".join(new_members))
+
+ # Send the welcome message, without the web page preview
+ message.reply(text, disable_web_page_preview=True)
+
+
+ app.run() # Automatically start() and idle()
\ No newline at end of file
diff --git a/docs/source/start/invoking.rst b/docs/source/start/invoking.rst
index 74b313e42b..0abea089e9 100644
--- a/docs/source/start/invoking.rst
+++ b/docs/source/start/invoking.rst
@@ -6,6 +6,7 @@ account; we are now aiming towards the core of the library. It's time to start p
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
@@ -13,7 +14,8 @@ account; we are now aiming towards the core of the library. It's time to start p
Basic Usage
-----------
-Making API method calls with Pyrogram is very simple. Here's an example we are going to examine:
+Making API method calls with Pyrogram is very simple. Here's a basic example we are going to examine step by step and
+then expand to explain what happens underneath:
.. code-block:: python
@@ -21,16 +23,13 @@ Making API method calls with Pyrogram is very simple. Here's an example we are g
app = Client("my_account")
- app.start()
+ with app:
+ app.send_message("me", "Hi!")
- print(app.get_me())
- app.send_message("me", "Hi, it's me!")
- app.send_location("me", 51.500729, -0.124583)
- app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")
+Basic step-by-step
+^^^^^^^^^^^^^^^^^^
- app.stop()
-
-#. Let's begin by importing the Client class from the Pyrogram package:
+#. Let's begin by importing the Client class:
.. code-block:: python
@@ -42,35 +41,42 @@ Making API method calls with Pyrogram is very simple. Here's an example we are g
app = Client("my_account")
-#. To actually make use of any method, the client has to be started first:
+#. The ``with`` context manager is a shortcut for starting, executing and stopping the Client:
.. code-block:: python
- app.start()
+ with app:
#. Now, you can call any method you like:
.. code-block:: python
- print(app.get_me()) # Print information about yourself
+ app.send_message("me", "Hi!")
- # Send messages to yourself:
- app.send_message("me", "Hi!") # Text message
- app.send_location("me", 51.500729, -0.124583) # Location
- app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI") # Sticker
+Context Manager
+---------------
-#. Finally, when done, simply stop the client:
+The ``with`` statement starts a context manager, which is used as a shortcut to automatically call
+:meth:`~pyrogram.Client.start` and :meth:`~pyrogram.Client.stop`, which are methods required for Pyrogram to work
+properly. The context manager does also gracefully stop the client, even in case of unhandled exceptions in your code.
- .. code-block:: python
+This is how Pyrogram looks without the context manager:
- app.stop()
+.. code-block:: python
-Context Manager
----------------
+ from pyrogram import Client
+
+ app = Client("my_account")
+
+ app.start()
+ app.send_message("me", "Hi!")
+ app.stop()
+
+Asynchronous Calls
+------------------
-You can also use Pyrogram's Client in a context manager with the ``with`` statement. The client will automatically
-:meth:`~pyrogram.Client.start` and :meth:`~pyrogram.Client.stop` gracefully, even in case of unhandled exceptions in
-your code. The example above can be therefore rewritten in a much nicer way:
+In case you want Pyrogram to run asynchronously (e.g.: if you are using third party libraries that require you to call
+them with ``await``), use the asynchronous context manager:
.. code-block:: python
@@ -78,10 +84,37 @@ your code. The example above can be therefore rewritten in a much nicer way:
app = Client("my_account")
- with app:
- print(app.get_me())
- app.send_message("me", "Hi there! I'm using **Pyrogram**")
- app.send_location("me", 51.500729, -0.124583)
- app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")
+ async def main():
+ async with app:
+ await app.send_message("me", "Hi!")
+
+ app.run(main())
+
+Asynchronous step-by-step
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+#. Import the Client class and create an instance:
+
+ .. code-block:: python
+
+ from pyrogram import Client
+
+ app = Client("my_account")
+
+#. Async methods can't normally be executed at the top level, because they must be inside an async-defined function;
+ here we define one and put our code inside; the context manager is also being used differently in asyncio and
+ method calls require the await keyword:
+
+ .. code-block:: python
+
+ async def main():
+ async with app:
+ await app.send_message("me", "Hi!")
+
+#. Finally, we tell Python to schedule our ``main()`` async function, which in turn will execute Pyrogram's code. Using
+ :meth:`~pyrogram.Client.run` this way is a friendly alternative for the much more verbose
+ ``asyncio.get_event_loop().run_until_complete(main())``:
+
+ .. code-block:: python
-More examples can be found on `GitHub `_.
+ app.run(main())
diff --git a/docs/source/start/updates.rst b/docs/source/start/updates.rst
index 4f010e27e8..ef569bf903 100644
--- a/docs/source/start/updates.rst
+++ b/docs/source/start/updates.rst
@@ -6,6 +6,7 @@ This page deals with updates and how to handle such events in Pyrogram. Let's ha
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
@@ -24,83 +25,76 @@ function will be called back by the framework and its body executed.
Registering a Handler
---------------------
-To explain how handlers work let's have a look at the most used one, the :class:`~pyrogram.MessageHandler`, which will
-be in charge for handling :class:`~pyrogram.Message` updates coming from all around your chats. Every other handler shares
-the same setup logic; you should not have troubles settings them up once you learn from this section.
+To explain how handlers work let's examine the one which will be in charge for handling :class:`~pyrogram.types.Message`
+updates coming from all around your chats. Every other handler shares the same setup logic; you should not have
+troubles settings them up once you learn from this section.
-Using add_handler()
--------------------
+Using Decorators
+^^^^^^^^^^^^^^^^
-The :meth:`~pyrogram.Client.add_handler` method takes any handler instance that wraps around your defined callback
-function and registers it in your Client. Here's a full example that prints out the content of a message as soon as it
-arrives:
+The most elegant way to register a message handler is by using the :meth:`~pyrogram.Client.on_message` decorator:
.. code-block:: python
- from pyrogram import Client, MessageHandler
-
-
- def my_function(client, message):
- print(message)
-
+ from pyrogram import Client
app = Client("my_account")
- my_handler = MessageHandler(my_function)
- app.add_handler(my_handler)
-
- app.run()
-Let's examine these four new pieces.
+ @app.on_message()
+ def my_handler(client, message):
+ message.forward("me")
-#. A callback function we defined which accepts two arguments -
- *(client, message)*. This will be the function that gets executed every time a new message arrives and Pyrogram will
- call that function by passing the client instance and the new message instance as argument.
- .. code-block:: python
+ app.run()
- def my_function(client, message):
- print(message)
+The defined function ``my_handler``, which accepts the two arguments *(client, message)*, will be the function that gets
+executed every time a new message arrives.
-#. The :class:`~pyrogram.MessageHandler`. This object tells Pyrogram the function we defined above must only handle
- updates that are in form of a :class:`~pyrogram.Message`:
+Asynchronous handlers
+^^^^^^^^^^^^^^^^^^^^^
- .. code-block:: python
+You can also have asynchronous handlers; you only need to define the callback function using ``async def`` and call API
+methods by placing ``await`` in front of them:
- my_handler = MessageHandler(my_function)
+.. code-block:: python
-#. The method :meth:`~pyrogram.Client.add_handler`. This method is used to actually register the handler and let
- Pyrogram know it needs to be taken into consideration when new updates arrive and the internal dispatching phase
- begins.
+ @app.on_message()
+ async def my_handler(client, message):
+ await message.forward("me")
- .. code-block:: python
+.. note::
- app.add_handler(my_handler)
+ You can mix ``def`` and ``async def`` handlers as much as you need, Pyrogram will still work concurrently and
+ efficiently regardless of what you choose.
-#. The :meth:`~pyrogram.Client.run` method. What this does is simply call :meth:`~pyrogram.Client.start` and
- a special method :meth:`~pyrogram.Client.idle` that keeps your main scripts alive until you press ``CTRL+C``; the
- client will be automatically stopped after that.
+Using add_handler()
+^^^^^^^^^^^^^^^^^^^
- .. code-block:: python
+The :meth:`~pyrogram.Client.add_handler` method takes any handler instance that wraps around your defined callback
+function and registers it in your Client. It us useful in case you want to programmatically add handlers (or in case,
+for some reason, you don't like to use decorators).
- app.run()
+.. code-block:: python
-Using Decorators
-----------------
+ from pyrogram import Client
+ from pyrogram.handlers import MessageHandler
-All of the above will become quite verbose, especially in case you have lots of handlers to register. A much nicer way
-to do so is by decorating your callback function with the :meth:`~pyrogram.Client.on_message` decorator.
-.. code-block:: python
+ def my_function(client, message):
+ message.forward("me")
- from pyrogram import Client
app = Client("my_account")
+ my_handler = MessageHandler(my_function)
+ app.add_handler(my_handler)
- @app.on_message()
- def my_handler(client, message):
- print(message)
+ app.run()
+The same about asynchronous handlers applies for :meth:`~pyrogram.Client.add_handler`:
- app.run()
+.. code-block:: python
+
+ async def my_function(client, message):
+ await message.forward("me")
diff --git a/docs/source/topics/advanced-usage.rst b/docs/source/topics/advanced-usage.rst
index a56e0da1dc..9df028ad31 100644
--- a/docs/source/topics/advanced-usage.rst
+++ b/docs/source/topics/advanced-usage.rst
@@ -10,6 +10,7 @@ Telegram API with its functions and types.
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
@@ -18,7 +19,7 @@ Telegram Raw API
----------------
If you can't find a high-level method for your needs or if you want complete, low-level access to the whole
-Telegram API, you have to use the raw :mod:`~pyrogram.api.functions` and :mod:`~pyrogram.api.types`.
+Telegram API, you have to use the raw :mod:`~pyrogram.raw.functions` and :mod:`~pyrogram.raw.types`.
As already hinted, raw functions and types can be really confusing, mainly because people don't realize soon enough they
accept *only* the right types and that all required parameters must be filled in. This section will therefore explain
@@ -41,7 +42,7 @@ Unlike the :doc:`methods <../api/methods/index>` found in Pyrogram's API, which
functions to be invoked from the raw Telegram API have a different way of usage and are more complex.
First of all, both :doc:`raw functions <../telegram/functions/index>` and :doc:`raw types <../telegram/types/index>`
-live in their respective packages (and sub-packages): ``pyrogram.api.functions``, ``pyrogram.api.types``. They all exist
+live in their respective packages (and sub-packages): ``pyrogram.raw.functions``, ``pyrogram.raw.types``. They all exist
as Python classes, meaning you need to create an instance of each every time you need them and fill them in with the
correct values using named arguments.
@@ -55,7 +56,7 @@ Here's some examples:
.. code-block:: python
from pyrogram import Client
- from pyrogram.api import functions
+ from pyrogram.raw import functions
with Client("my_account") as app:
app.send(
@@ -70,7 +71,7 @@ Here's some examples:
.. code-block:: python
from pyrogram import Client
- from pyrogram.api import functions, types
+ from pyrogram.raw import functions, types
with Client("my_account") as app:
app.send(
@@ -85,7 +86,7 @@ Here's some examples:
.. code-block:: python
from pyrogram import Client
- from pyrogram.api import functions, types
+ from pyrogram.raw import functions, types
with Client("my_account") as app:
app.send(
@@ -109,9 +110,9 @@ sending messages with IDs only thanks to cached access hashes.
There are three different InputPeer types, one for each kind of Telegram entity.
Whenever an InputPeer is needed you must pass one of these:
-- :class:`~pyrogram.api.types.InputPeerUser` - Users
-- :class:`~pyrogram.api.types.InputPeerChat` - Basic Chats
-- :class:`~pyrogram.api.types.InputPeerChannel` - Either Channels or Supergroups
+- :class:`~pyrogram.raw.types.InputPeerUser` - Users
+- :class:`~pyrogram.raw.types.InputPeerChat` - Basic Chats
+- :class:`~pyrogram.raw.types.InputPeerChannel` - Either Channels or Supergroups
But you don't necessarily have to manually instantiate each object because, luckily for you, Pyrogram already provides
:meth:`~pyrogram.Client.resolve_peer` as a convenience utility method that returns the correct InputPeer
diff --git a/docs/source/topics/bots-interaction.rst b/docs/source/topics/bots-interaction.rst
index 97a72e05c0..1fad206988 100644
--- a/docs/source/topics/bots-interaction.rst
+++ b/docs/source/topics/bots-interaction.rst
@@ -5,6 +5,7 @@ Users can interact with other bots via plain text messages as well as inline que
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
diff --git a/docs/source/topics/config-file.rst b/docs/source/topics/config-file.rst
index b6faee058d..38bb9e3375 100644
--- a/docs/source/topics/config-file.rst
+++ b/docs/source/topics/config-file.rst
@@ -6,6 +6,7 @@ This page explains how this file is structured, how to use it and why.
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
diff --git a/docs/source/topics/create-filters.rst b/docs/source/topics/create-filters.rst
index 060357def3..3e87a3deed 100644
--- a/docs/source/topics/create-filters.rst
+++ b/docs/source/topics/create-filters.rst
@@ -1,16 +1,12 @@
Creating Filters
================
-Pyrogram already provides lots of built-in :class:`~pyrogram.Filters` to work with, but in case you can't find
-a specific one for your needs or want to build a custom filter by yourself (to be used in a different kind of handler,
-for example) you can use :meth:`~pyrogram.Filters.create`.
-
-.. note::
-
- At the moment, the built-in filters are intended to be used with the :class:`~pyrogram.MessageHandler` only.
+Pyrogram already provides lots of built-in :class:`~pyrogram.filters` to work with, but in case you can't find a
+specific one for your needs or want to build a custom filter by yourself you can use :meth:`~pyrogram.filters.create`.
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
@@ -19,14 +15,14 @@ Custom Filters
--------------
An example to demonstrate how custom filters work is to show how to create and use one for the
-:class:`~pyrogram.CallbackQueryHandler`. Note that callback queries updates are only received by bots as result of a
-user pressing an inline button attached to the bot's message; create and :doc:`authorize your bot <../start/auth>`,
+:class:`~pyrogram.handlers.CallbackQueryHandler`. Note that callback queries updates are only received by bots as result
+of a user pressing an inline button attached to the bot's message; create and :doc:`authorize your bot <../start/auth>`,
then send a message with an inline keyboard to yourself. This allows you to test your filter by pressing the inline
button:
.. code-block:: python
- from pyrogram import InlineKeyboardMarkup, InlineKeyboardButton
+ from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
app.send_message(
"username", # Change this to your username or id
@@ -39,7 +35,7 @@ button:
Basic Filters
-------------
-For this basic filter we will be using only the first parameter of :meth:`~pyrogram.Filters.create`.
+For this basic filter we will be using only the first parameter of :meth:`~pyrogram.filters.create`.
The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries
containing "pyrogram" as data, that is, the function *func* you pass returns True in case the callback query data
@@ -47,17 +43,21 @@ equals to ``"pyrogram"``.
.. code-block:: python
- static_data_filter = Filters.create(lambda _, query: query.data == "pyrogram")
+ from pyrogram import filters
+
+ static_data_filter = filters.create(lambda _, query: query.data == "pyrogram")
The ``lambda`` operator in python is used to create small anonymous functions and is perfect for this example, the same
-could be achieved with a normal function, but we don't really need it as it makes sense only inside the filter scope:
+could be achieved with a normal function, but we don't really need it as it makes sense only inside the filter's scope:
.. code-block:: python
+ from pyrogram import filters
+
def func(_, query):
return query.data == "pyrogram"
- static_data_filter = Filters.create(func)
+ static_data_filter = filters.create(func)
The filter usage remains the same:
@@ -71,14 +71,16 @@ Filters with Arguments
----------------------
A much cooler filter would be one that accepts "pyrogram" or any other data as argument at usage time.
-A dynamic filter like this will make use of named arguments for the :meth:`~pyrogram.Filters.create` method.
+A dynamic filter like this will make use of named arguments for the :meth:`~pyrogram.filters.create` method.
This is how a dynamic custom filter looks like:
.. code-block:: python
+ from pyrogram import filters
+
def dynamic_data_filter(data):
- return Filters.create(
+ return filters.create(
lambda flt, query: flt.data == query.data,
data=data # "data" kwarg is accessed with "flt.data" above
)
diff --git a/docs/source/topics/debugging.rst b/docs/source/topics/debugging.rst
index 7284884af2..995ce9e5bb 100644
--- a/docs/source/topics/debugging.rst
+++ b/docs/source/topics/debugging.rst
@@ -6,6 +6,7 @@ to actually worry about -- that's normal -- and luckily for you, Pyrogram provid
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
diff --git a/docs/source/topics/more-on-updates.rst b/docs/source/topics/more-on-updates.rst
index 1bffaeef2b..a636008ace 100644
--- a/docs/source/topics/more-on-updates.rst
+++ b/docs/source/topics/more-on-updates.rst
@@ -6,6 +6,7 @@ Here we'll show some advanced usages when working with :doc:`update handlers <..
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
@@ -25,21 +26,21 @@ For example, take these two handlers:
.. code-block:: python
:emphasize-lines: 1, 6
- @app.on_message(Filters.text | Filters.sticker)
+ @app.on_message(filters.text | filters.sticker)
def text_or_sticker(client, message):
print("Text or Sticker")
- @app.on_message(Filters.text)
+ @app.on_message(filters.text)
def just_text(client, message):
print("Just Text")
Here, ``just_text`` is never executed because ``text_or_sticker``, which has been registered first, already handles
-texts (``Filters.text`` is shared and conflicting). To enable it, register the handler using a different group:
+texts (``filters.text`` is shared and conflicting). To enable it, register the handler using a different group:
.. code-block:: python
- @app.on_message(Filters.text, group=1)
+ @app.on_message(filters.text, group=1)
def just_text(client, message):
print("Just Text")
@@ -47,7 +48,7 @@ Or, if you want ``just_text`` to be executed *before* ``text_or_sticker`` (note
.. code-block:: python
- @app.on_message(Filters.text, group=-1)
+ @app.on_message(filters.text, group=-1)
def just_text(client, message):
print("Just Text")
@@ -55,7 +56,7 @@ With :meth:`~pyrogram.Client.add_handler` (without decorators) the same can be a
.. code-block:: python
- app.add_handler(MessageHandler(just_text, Filters.text), -1)
+ app.add_handler(MessageHandler(just_text, filters.text), -1)
Update propagation
------------------
@@ -67,17 +68,17 @@ continue to propagate the same update to the next groups until all the handlers
.. code-block:: python
- @app.on_message(Filters.private)
+ @app.on_message(filters.private)
def _(client, message):
print(0)
- @app.on_message(Filters.private, group=1)
+ @app.on_message(filters.private, group=1)
def _(client, message):
raise Exception("Unhandled exception!") # Simulate an unhandled exception
- @app.on_message(Filters.private, group=2)
+ @app.on_message(filters.private, group=2)
def _(client, message):
print(2)
@@ -109,18 +110,18 @@ Example with ``stop_propagation()``:
.. code-block:: python
- @app.on_message(Filters.private)
+ @app.on_message(filters.private)
def _(client, message):
print(0)
- @app.on_message(Filters.private, group=1)
+ @app.on_message(filters.private, group=1)
def _(client, message):
print(1)
message.stop_propagation()
- @app.on_message(Filters.private, group=2)
+ @app.on_message(filters.private, group=2)
def _(client, message):
print(2)
@@ -130,18 +131,18 @@ Example with ``raise StopPropagation``:
from pyrogram import StopPropagation
- @app.on_message(Filters.private)
+ @app.on_message(filters.private)
def _(client, message):
print(0)
- @app.on_message(Filters.private, group=1)
+ @app.on_message(filters.private, group=1)
def _(client, message):
print(1)
raise StopPropagation
- @app.on_message(Filters.private, group=2)
+ @app.on_message(filters.private, group=2)
def _(client, message):
print(2)
@@ -177,19 +178,19 @@ Example with ``continue_propagation()``:
.. code-block:: python
- @app.on_message(Filters.private)
+ @app.on_message(filters.private)
def _(client, message):
print(0)
message.continue_propagation()
- @app.on_message(Filters.private)
+ @app.on_message(filters.private)
def _(client, message):
print(1)
message.continue_propagation()
- @app.on_message(Filters.private)
+ @app.on_message(filters.private)
def _(client, message):
print(2)
@@ -199,19 +200,19 @@ Example with ``raise ContinuePropagation``:
from pyrogram import ContinuePropagation
- @app.on_message(Filters.private)
+ @app.on_message(filters.private)
def _(client, message):
print(0)
raise ContinuePropagation
- @app.on_message(Filters.private)
+ @app.on_message(filters.private)
def _(client, message):
print(1)
raise ContinuePropagation
- @app.on_message(Filters.private)
+ @app.on_message(filters.private)
def _(client, message):
print(2)
diff --git a/docs/source/topics/mtproto-vs-botapi.rst b/docs/source/topics/mtproto-vs-botapi.rst
index aab3525e44..c73d669219 100644
--- a/docs/source/topics/mtproto-vs-botapi.rst
+++ b/docs/source/topics/mtproto-vs-botapi.rst
@@ -8,6 +8,7 @@ actually is the MTProto and the Bot API.
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
diff --git a/docs/source/topics/proxy.rst b/docs/source/topics/proxy.rst
index cde55cc7da..7d7e2c88db 100644
--- a/docs/source/topics/proxy.rst
+++ b/docs/source/topics/proxy.rst
@@ -6,6 +6,7 @@ through an intermediate SOCKS5 proxy server.
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
diff --git a/docs/source/topics/scheduling.rst b/docs/source/topics/scheduling.rst
index c5f410bb46..0776d601ed 100644
--- a/docs/source/topics/scheduling.rst
+++ b/docs/source/topics/scheduling.rst
@@ -10,6 +10,7 @@ visit and learn from each library documentation.
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
@@ -69,8 +70,7 @@ Using ``apscheduler``
scheduler.start()
app.run()
-``apscheduler`` does also support async code, here's an example with
-`Pyrogram Asyncio `_:
+``apscheduler`` does also support async code, here's an example:
.. code-block:: python
diff --git a/docs/source/topics/serializing.rst b/docs/source/topics/serializing.rst
index 8e6f29de7b..7e01357330 100644
--- a/docs/source/topics/serializing.rst
+++ b/docs/source/topics/serializing.rst
@@ -7,6 +7,7 @@ humans and another more compact for machines that is able to recover the origina
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
diff --git a/docs/source/topics/session-settings.rst b/docs/source/topics/session-settings.rst
index a97dbc063f..847427cf25 100644
--- a/docs/source/topics/session-settings.rst
+++ b/docs/source/topics/session-settings.rst
@@ -22,6 +22,7 @@ That's how a session looks like on the Android app, showing the three main piece
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
diff --git a/docs/source/topics/smart-plugins.rst b/docs/source/topics/smart-plugins.rst
index 7ffe1cb2ee..fece636622 100644
--- a/docs/source/topics/smart-plugins.rst
+++ b/docs/source/topics/smart-plugins.rst
@@ -11,6 +11,7 @@ different Pyrogram applications with **minimal boilerplate code**.
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
@@ -51,7 +52,8 @@ after importing your modules, like this:
.. code-block:: python
- from pyrogram import Client, MessageHandler, Filters
+ from pyrogram import Client, filters
+ from pyrogram.handlers import MessageHandler
from handlers import echo, echo_reversed
@@ -60,19 +62,19 @@ after importing your modules, like this:
app.add_handler(
MessageHandler(
echo,
- Filters.text & Filters.private))
+ filters.text & filters.private))
app.add_handler(
MessageHandler(
echo_reversed,
- Filters.text & Filters.private),
+ filters.text & filters.private),
group=1)
app.run()
This is already nice and doesn't add *too much* boilerplate code, but things can get boring still; you have to
manually ``import``, manually :meth:`~pyrogram.Client.add_handler` and manually instantiate each
-:class:`~pyrogram.MessageHandler` object because **you can't use those cool decorators** for your
+:class:`~pyrogram.handlers.MessageHandler` object because **you can't use those cool decorators** for your
functions. So, what if you could? Smart Plugins solve this issue by taking care of handlers registration automatically.
Using Smart Plugins
@@ -102,15 +104,15 @@ Setting up your Pyrogram project to accommodate Smart Plugins is pretty straight
.. code-block:: python
:emphasize-lines: 4, 9
- from pyrogram import Client, Filters
+ from pyrogram import Client, filters
- @Client.on_message(Filters.text & Filters.private)
+ @Client.on_message(filters.text & filters.private)
def echo(client, message):
message.reply(message.text)
- @Client.on_message(Filters.text & Filters.private, group=1)
+ @Client.on_message(filters.text & filters.private, group=1)
def echo_reversed(client, message):
message.reply(message.text[::-1])
@@ -306,7 +308,7 @@ updates) will be modified in such a way that a special ``handler`` attribute poi
.. code-block:: python
:emphasize-lines: 5, 6
- @Client.on_message(Filters.text & Filters.private)
+ @Client.on_message(filters.text & filters.private)
def echo(client, message):
message.reply(message.text)
diff --git a/docs/source/topics/storage-engines.rst b/docs/source/topics/storage-engines.rst
index e7494e2bd0..1a86cad8b5 100644
--- a/docs/source/topics/storage-engines.rst
+++ b/docs/source/topics/storage-engines.rst
@@ -7,6 +7,7 @@ decide to manually terminate it) and is used to authorize a client to execute AP
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
diff --git a/docs/source/topics/test-servers.rst b/docs/source/topics/test-servers.rst
index 1906c2f159..3ed996eea9 100644
--- a/docs/source/topics/test-servers.rst
+++ b/docs/source/topics/test-servers.rst
@@ -20,6 +20,7 @@ Telegram's test servers without hassle. All you need to do is start a new sessio
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
diff --git a/docs/source/topics/text-formatting.rst b/docs/source/topics/text-formatting.rst
index f4ac23e1ef..5d9a9376c2 100644
--- a/docs/source/topics/text-formatting.rst
+++ b/docs/source/topics/text-formatting.rst
@@ -19,6 +19,7 @@ variety of decorations that can also be nested in order to combine multiple styl
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
diff --git a/docs/source/topics/use-filters.rst b/docs/source/topics/use-filters.rst
index 8806052e94..7e5219e14f 100644
--- a/docs/source/topics/use-filters.rst
+++ b/docs/source/topics/use-filters.rst
@@ -1,14 +1,15 @@
Using Filters
=============
-So far we've seen :doc:`how to register a callback function <../start/updates>` that executes every time a specific update
-comes from the server, but there's much more than that to come.
+So far we've seen :doc:`how to register a callback function <../start/updates>` that executes every time an update comes
+from the server, but there's much more than that to come.
-Here we'll discuss about :class:`~pyrogram.Filters`. Filters enable a fine-grain control over what kind of
+Here we'll discuss about :obj:`~pyrogram.filters`. Filters enable a fine-grain control over what kind of
updates are allowed or not to be passed in your callback functions, based on their inner details.
.. contents:: Contents
:backlinks: none
+ :depth: 1
:local:
-----
@@ -24,10 +25,10 @@ Let's start right away with a simple example:
.. code-block:: python
:emphasize-lines: 4
- from pyrogram import Filters
+ from pyrogram import filters
- @app.on_message(Filters.audio)
+ @app.on_message(filters.audio)
def my_handler(client, message):
print(message)
@@ -35,16 +36,17 @@ Let's start right away with a simple example:
callback function itself:
.. code-block:: python
- :emphasize-lines: 8
+ :emphasize-lines: 9
- from pyrogram import Filters, MessageHandler
+ from pyrogram import filters
+ from pyrogram.handlers import MessageHandler
def my_handler(client, message):
print(message)
- app.add_handler(MessageHandler(my_handler, Filters.audio))
+ app.add_handler(MessageHandler(my_handler, filters.audio))
Combining Filters
-----------------
@@ -61,7 +63,7 @@ Here are some examples:
.. code-block:: python
- @app.on_message(Filters.text & ~Filters.edited)
+ @app.on_message(filters.text & ~filters.edited)
def my_handler(client, message):
print(message)
@@ -69,21 +71,21 @@ Here are some examples:
.. code-block:: python
- @app.on_message(Filters.sticker & (Filters.channel | Filters.private))
+ @app.on_message(filters.sticker & (filters.channel | filters.private))
def my_handler(client, message):
print(message)
Advanced Filters
----------------
-Some filters, like :meth:`~pyrogram.Filters.command` or :meth:`~pyrogram.Filters.regex`
+Some filters, like :meth:`~pyrogram.filters.command` or :meth:`~pyrogram.filters.regex`
can also accept arguments:
- Message is either a */start* or */help* **command**.
.. code-block:: python
- @app.on_message(Filters.command(["start", "help"]))
+ @app.on_message(filters.command(["start", "help"]))
def my_handler(client, message):
print(message)
@@ -91,7 +93,7 @@ can also accept arguments:
.. code-block:: python
- @app.on_message(Filters.regex("pyrogram"))
+ @app.on_message(filters.regex("pyrogram"))
def my_handler(client, message):
print(message)
@@ -99,16 +101,16 @@ More handlers using different filters can also live together.
.. code-block:: python
- @app.on_message(Filters.command("start"))
+ @app.on_message(filters.command("start"))
def start_command(client, message):
print("This is the /start command")
- @app.on_message(Filters.command("help"))
+ @app.on_message(filters.command("help"))
def help_command(client, message):
print("This is the /help command")
- @app.on_message(Filters.chat("PyrogramChat"))
+ @app.on_message(filters.chat("PyrogramChat"))
def from_pyrogramchat(client, message):
print("New message in @PyrogramChat")
diff --git a/examples/LICENSE b/examples/LICENSE
deleted file mode 100644
index 1625c17936..0000000000
--- a/examples/LICENSE
+++ /dev/null
@@ -1,121 +0,0 @@
-Creative Commons Legal Code
-
-CC0 1.0 Universal
-
- CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
- LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
- ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
- INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
- REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
- PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
- THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
- HEREUNDER.
-
-Statement of Purpose
-
-The laws of most jurisdictions throughout the world automatically confer
-exclusive Copyright and Related Rights (defined below) upon the creator
-and subsequent owner(s) (each and all, an "owner") of an original work of
-authorship and/or a database (each, a "Work").
-
-Certain owners wish to permanently relinquish those rights to a Work for
-the purpose of contributing to a commons of creative, cultural and
-scientific works ("Commons") that the public can reliably and without fear
-of later claims of infringement build upon, modify, incorporate in other
-works, reuse and redistribute as freely as possible in any form whatsoever
-and for any purposes, including without limitation commercial purposes.
-These owners may contribute to the Commons to promote the ideal of a free
-culture and the further production of creative, cultural and scientific
-works, or to gain reputation or greater distribution for their Work in
-part through the use and efforts of others.
-
-For these and/or other purposes and motivations, and without any
-expectation of additional consideration or compensation, the person
-associating CC0 with a Work (the "Affirmer"), to the extent that he or she
-is an owner of Copyright and Related Rights in the Work, voluntarily
-elects to apply CC0 to the Work and publicly distribute the Work under its
-terms, with knowledge of his or her Copyright and Related Rights in the
-Work and the meaning and intended legal effect of CC0 on those rights.
-
-1. Copyright and Related Rights. A Work made available under CC0 may be
-protected by copyright and related or neighboring rights ("Copyright and
-Related Rights"). Copyright and Related Rights include, but are not
-limited to, the following:
-
- i. the right to reproduce, adapt, distribute, perform, display,
- communicate, and translate a Work;
- ii. moral rights retained by the original author(s) and/or performer(s);
-iii. publicity and privacy rights pertaining to a person's image or
- likeness depicted in a Work;
- iv. rights protecting against unfair competition in regards to a Work,
- subject to the limitations in paragraph 4(a), below;
- v. rights protecting the extraction, dissemination, use and reuse of data
- in a Work;
- vi. database rights (such as those arising under Directive 96/9/EC of the
- European Parliament and of the Council of 11 March 1996 on the legal
- protection of databases, and under any national implementation
- thereof, including any amended or successor version of such
- directive); and
-vii. other similar, equivalent or corresponding rights throughout the
- world based on applicable law or treaty, and any national
- implementations thereof.
-
-2. Waiver. To the greatest extent permitted by, but not in contravention
-of, applicable law, Affirmer hereby overtly, fully, permanently,
-irrevocably and unconditionally waives, abandons, and surrenders all of
-Affirmer's Copyright and Related Rights and associated claims and causes
-of action, whether now known or unknown (including existing as well as
-future claims and causes of action), in the Work (i) in all territories
-worldwide, (ii) for the maximum duration provided by applicable law or
-treaty (including future time extensions), (iii) in any current or future
-medium and for any number of copies, and (iv) for any purpose whatsoever,
-including without limitation commercial, advertising or promotional
-purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
-member of the public at large and to the detriment of Affirmer's heirs and
-successors, fully intending that such Waiver shall not be subject to
-revocation, rescission, cancellation, termination, or any other legal or
-equitable action to disrupt the quiet enjoyment of the Work by the public
-as contemplated by Affirmer's express Statement of Purpose.
-
-3. Public License Fallback. Should any part of the Waiver for any reason
-be judged legally invalid or ineffective under applicable law, then the
-Waiver shall be preserved to the maximum extent permitted taking into
-account Affirmer's express Statement of Purpose. In addition, to the
-extent the Waiver is so judged Affirmer hereby grants to each affected
-person a royalty-free, non transferable, non sublicensable, non exclusive,
-irrevocable and unconditional license to exercise Affirmer's Copyright and
-Related Rights in the Work (i) in all territories worldwide, (ii) for the
-maximum duration provided by applicable law or treaty (including future
-time extensions), (iii) in any current or future medium and for any number
-of copies, and (iv) for any purpose whatsoever, including without
-limitation commercial, advertising or promotional purposes (the
-"License"). The License shall be deemed effective as of the date CC0 was
-applied by Affirmer to the Work. Should any part of the License for any
-reason be judged legally invalid or ineffective under applicable law, such
-partial invalidity or ineffectiveness shall not invalidate the remainder
-of the License, and in such case Affirmer hereby affirms that he or she
-will not (i) exercise any of his or her remaining Copyright and Related
-Rights in the Work or (ii) assert any associated claims and causes of
-action with respect to the Work, in either case contrary to Affirmer's
-express Statement of Purpose.
-
-4. Limitations and Disclaimers.
-
- a. No trademark or patent rights held by Affirmer are waived, abandoned,
- surrendered, licensed or otherwise affected by this document.
- b. Affirmer offers the Work as-is and makes no representations or
- warranties of any kind concerning the Work, express, implied,
- statutory or otherwise, including without limitation warranties of
- title, merchantability, fitness for a particular purpose, non
- infringement, or the absence of latent or other defects, accuracy, or
- the present or absence of errors, whether or not discoverable, all to
- the greatest extent permissible under applicable law.
- c. Affirmer disclaims responsibility for clearing rights of other persons
- that may apply to the Work or any use thereof, including without
- limitation any person's Copyright and Related Rights in the Work.
- Further, Affirmer disclaims responsibility for obtaining any necessary
- consents, permissions or other rights required for any use of the
- Work.
- d. Affirmer understands and acknowledges that Creative Commons is not a
- party to this document and has no duty or obligation with respect to
- this CC0 or use of the Work.
\ No newline at end of file
diff --git a/examples/README.md b/examples/README.md
deleted file mode 100644
index b8898a718a..0000000000
--- a/examples/README.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Examples
-
-This folder contains example scripts to show you how **Pyrogram** looks like.
-
-Every script is working right away (provided you correctly set up your credentials), meaning you can simply copy-paste
-and run. The only things you have to change are session names and target chats.
-
-All the examples listed in this directory are licensed under the terms of the [CC0 1.0 Universal](LICENSE) license and
-can be freely used as basic building blocks for your own applications without worrying about copyrights.
-
-Example | Description
----: | :---
-[**hello_world**](hello_world.py) | Demonstration of basic API usage
-[**echobot**](echobot.py) | Echo every private text message
-[**welcomebot**](welcomebot.py) | The Welcome Bot in [@PyrogramChat](https://t.me/pyrogramchat)
-[**get_history**](get_history.py) | Get the full message history of a chat
-[**get_chat_members**](get_chat_members.py) | Get all the members of a chat
-[**get_dialogs**](get_dialogs.py) | Get all of your dialog chats
-[**callback_queries**](callback_queries.py) | Handle callback queries (as bot) coming from inline button presses
-[**inline_queries**](inline_queries.py) | Handle inline queries (as bot) and answer with results
-[**use_inline_bots**](use_inline_bots.py) | Query an inline bot (as user) and send a result to a chat
-[**bot_keyboards**](bot_keyboards.py) | Send normal and inline keyboards using regular bots
-[**raw_updates**](raw_updates.py) | Handle raw updates (old, should be avoided)
diff --git a/examples/bot_keyboards.py b/examples/bot_keyboards.py
deleted file mode 100644
index e1ff1e7e3f..0000000000
--- a/examples/bot_keyboards.py
+++ /dev/null
@@ -1,57 +0,0 @@
-"""This example will show you how to send normal and inline keyboards (as bot).
-
-You must log-in as a regular bot in order to send keyboards (use the token from @BotFather).
-Any attempt in sending keyboards with a user account will be simply ignored by the server.
-
-send_message() is used as example, but a keyboard can be sent with any other send_* methods,
-like send_audio(), send_document(), send_location(), etc...
-"""
-
-from pyrogram import Client, ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton
-
-# Create a client using your bot token
-app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
-
-with app:
- app.send_message(
- "haskell", # Edit this
- "This is a ReplyKeyboardMarkup example",
- reply_markup=ReplyKeyboardMarkup(
- [
- ["A", "B", "C", "D"], # First row
- ["E", "F", "G"], # Second row
- ["H", "I"], # Third row
- ["J"] # Fourth row
- ],
- resize_keyboard=True # Make the keyboard smaller
- )
- )
-
- app.send_message(
- "haskell", # Edit this
- "This is a InlineKeyboardMarkup example",
- reply_markup=InlineKeyboardMarkup(
- [
- [ # First row
- InlineKeyboardButton( # Generates a callback query when pressed
- "Button",
- callback_data=b"data" # Note how callback_data must be bytes
- ),
- InlineKeyboardButton( # Opens a web URL
- "URL",
- url="https://docs.pyrogram.org"
- ),
- ],
- [ # Second row
- InlineKeyboardButton( # Opens the inline interface
- "Choose chat",
- switch_inline_query="pyrogram"
- ),
- InlineKeyboardButton( # Opens the inline interface in the current chat
- "Inline here",
- switch_inline_query_current_chat="pyrogram"
- )
- ]
- ]
- )
- )
diff --git a/examples/callback_queries.py b/examples/callback_queries.py
deleted file mode 100644
index f4a87b0041..0000000000
--- a/examples/callback_queries.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""This example shows how to handle callback queries, i.e.: queries coming from inline button presses.
-
-It uses the @on_callback_query decorator to register a CallbackQueryHandler.
-"""
-
-from pyrogram import Client
-
-app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
-
-
-@app.on_callback_query()
-def answer(client, callback_query):
- callback_query.answer("Button contains: '{}'".format(callback_query.data), show_alert=True)
-
-
-app.run() # Automatically start() and idle()
diff --git a/examples/echobot.py b/examples/echobot.py
deleted file mode 100644
index c60ae2917b..0000000000
--- a/examples/echobot.py
+++ /dev/null
@@ -1,17 +0,0 @@
-"""This simple echo bot replies to every private text message.
-
-It uses the @on_message decorator to register a MessageHandler and applies two filters on it:
-Filters.text and Filters.private to make sure it will reply to private text messages only.
-"""
-
-from pyrogram import Client, Filters
-
-app = Client("my_account")
-
-
-@app.on_message(Filters.text & Filters.private)
-def echo(client, message):
- message.reply(message.text)
-
-
-app.run() # Automatically start() and idle()
diff --git a/examples/get_chat_members.py b/examples/get_chat_members.py
deleted file mode 100644
index 468ac7dec5..0000000000
--- a/examples/get_chat_members.py
+++ /dev/null
@@ -1,10 +0,0 @@
-"""This example shows how to get all the members of a chat."""
-
-from pyrogram import Client
-
-app = Client("my_account")
-target = "pyrogramchat" # Target channel/supergroup
-
-with app:
- for member in app.iter_chat_members(target):
- print(member.user.first_name)
diff --git a/examples/get_dialogs.py b/examples/get_dialogs.py
deleted file mode 100644
index 92da8834c9..0000000000
--- a/examples/get_dialogs.py
+++ /dev/null
@@ -1,9 +0,0 @@
-"""This example shows how to get the full dialogs list (as user)."""
-
-from pyrogram import Client
-
-app = Client("my_account")
-
-with app:
- for dialog in app.iter_dialogs():
- print(dialog.chat.title or dialog.chat.first_name)
diff --git a/examples/get_history.py b/examples/get_history.py
deleted file mode 100644
index e8bb14e31d..0000000000
--- a/examples/get_history.py
+++ /dev/null
@@ -1,10 +0,0 @@
-"""This example shows how to get the full message history of a chat, starting from the latest message"""
-
-from pyrogram import Client
-
-app = Client("my_account")
-target = "me" # "me" refers to your own chat (Saved Messages)
-
-with app:
- for message in app.iter_history(target):
- print(message.text)
diff --git a/examples/hello_world.py b/examples/hello_world.py
deleted file mode 100644
index 5764e97972..0000000000
--- a/examples/hello_world.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""This example demonstrates a basic API usage"""
-
-from pyrogram import Client
-
-# Create a new Client instance
-app = Client("my_account")
-
-with app:
- # Send a message, Markdown is enabled by default
- app.send_message("me", "Hi there! I'm using **Pyrogram**")
-
- # Send a location
- app.send_location("me", 51.500729, -0.124583)
-
- # Send a sticker
- app.send_sticker("me", "CAADBAADzg4AAvLQYAEz_x2EOgdRwBYE")
diff --git a/examples/inline_queries.py b/examples/inline_queries.py
deleted file mode 100644
index d86d90d5c7..0000000000
--- a/examples/inline_queries.py
+++ /dev/null
@@ -1,54 +0,0 @@
-"""This example shows how to handle inline queries.
-Two results are generated when users invoke the bot inline mode, e.g.: @pyrogrambot hi.
-It uses the @on_inline_query decorator to register an InlineQueryHandler.
-"""
-
-from uuid import uuid4
-
-from pyrogram import (
- Client, InlineQueryResultArticle, InputTextMessageContent, InlineKeyboardMarkup, InlineKeyboardButton
-)
-
-app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
-
-
-@app.on_inline_query()
-def answer(client, inline_query):
- inline_query.answer(
- results=[
- InlineQueryResultArticle(
- id=uuid4(),
- title="Installation",
- input_message_content=InputTextMessageContent(
- "Here's how to install **Pyrogram**"
- ),
- url="https://docs.pyrogram.org/intro/install",
- description="How to install Pyrogram",
- thumb_url="https://i.imgur.com/JyxrStE.png",
- reply_markup=InlineKeyboardMarkup(
- [
- [InlineKeyboardButton("Open website", url="https://docs.pyrogram.org/intro/install")]
- ]
- )
- ),
- InlineQueryResultArticle(
- id=uuid4(),
- title="Usage",
- input_message_content=InputTextMessageContent(
- "Here's how to use **Pyrogram**"
- ),
- url="https://docs.pyrogram.org/start/invoking",
- description="How to use Pyrogram",
- thumb_url="https://i.imgur.com/JyxrStE.png",
- reply_markup=InlineKeyboardMarkup(
- [
- [InlineKeyboardButton("Open website", url="https://docs.pyrogram.org/start/invoking")]
- ]
- )
- )
- ],
- cache_time=1
- )
-
-
-app.run() # Automatically start() and idle()
diff --git a/examples/raw_updates.py b/examples/raw_updates.py
deleted file mode 100644
index 27d87eb37b..0000000000
--- a/examples/raw_updates.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""This example shows how to handle raw updates"""
-
-from pyrogram import Client
-
-app = Client("my_account")
-
-
-@app.on_raw_update()
-def raw(client, update, users, chats):
- print(update)
-
-
-app.run() # Automatically start() and idle()
diff --git a/examples/use_inline_bots.py b/examples/use_inline_bots.py
deleted file mode 100644
index 5681df8778..0000000000
--- a/examples/use_inline_bots.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""This example shows how to query an inline bot (as user)"""
-
-from pyrogram import Client
-
-# Create a new Client
-app = Client("my_account")
-
-with app:
- # Get bot results for "Fuzz Universe" from the inline bot @vid
- bot_results = app.get_inline_bot_results("vid", "Fuzz Universe")
-
- # Send the first result (bot_results.results[0]) to your own chat (Saved Messages)
- app.send_inline_bot_result("me", bot_results.query_id, bot_results.results[0].id)
diff --git a/examples/welcomebot.py b/examples/welcomebot.py
deleted file mode 100644
index 35f72afff8..0000000000
--- a/examples/welcomebot.py
+++ /dev/null
@@ -1,29 +0,0 @@
-"""This is the Welcome Bot in @PyrogramChat.
-
-It uses the Emoji module to easily add emojis in your text messages and Filters
-to make it only work for specific messages in a specific chat.
-"""
-
-from pyrogram import Client, Emoji, Filters
-
-TARGET = "PyrogramChat" # Target chat. Can also be a list of multiple chat ids/usernames
-MENTION = "[{}](tg://user?id={})" # User mention markup
-MESSAGE = "{} Welcome to [Pyrogram](https://docs.pyrogram.org/)'s group chat {}!" # Welcome message
-
-app = Client("my_account")
-
-
-# Filter in only new_chat_members updates generated in TARGET chat
-@app.on_message(Filters.chat(TARGET) & Filters.new_chat_members)
-def welcome(client, message):
- # Build the new members list (with mentions) by using their first_name
- new_members = [MENTION.format(i.first_name, i.id) for i in message.new_chat_members]
-
- # Build the welcome message by using an emoji and the list we built above
- text = MESSAGE.format(Emoji.SPARKLES, ", ".join(new_members))
-
- # Send the welcome message, without the web page preview
- message.reply(text, disable_web_page_preview=True)
-
-
-app.run() # Automatically start() and idle()
diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py
index 053d33981a..65ac3d7175 100644
--- a/pyrogram/__init__.py
+++ b/pyrogram/__init__.py
@@ -16,10 +16,23 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-__version__ = "0.18.0-async"
+__version__ = "1.0.0b1"
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__copyright__ = "Copyright (C) 2017-2020 Dan "
-from .client import *
-from .client.handlers import *
-from .client.types import *
+
+class StopTransmission(StopAsyncIteration):
+ pass
+
+
+class StopPropagation(StopAsyncIteration):
+ pass
+
+
+class ContinuePropagation(StopAsyncIteration):
+ pass
+
+
+from . import types, filters, handlers, emoji
+from .client import Client
+from .sync import idle
diff --git a/pyrogram/client.py b/pyrogram/client.py
new file mode 100644
index 0000000000..a293efd544
--- /dev/null
+++ b/pyrogram/client.py
@@ -0,0 +1,1069 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import asyncio
+import functools
+import logging
+import os
+import re
+import shutil
+import tempfile
+from concurrent.futures.thread import ThreadPoolExecutor
+from configparser import ConfigParser
+from hashlib import sha256
+from importlib import import_module
+from pathlib import Path
+from typing import Union, List
+
+import pyrogram
+from pyrogram import raw
+from pyrogram import utils
+from pyrogram.crypto import aes
+from pyrogram.errors import (
+ SessionPasswordNeeded,
+ VolumeLocNotFound, ChannelPrivate,
+ AuthBytesInvalid, BadRequest
+)
+from pyrogram.handlers.handler import Handler
+from pyrogram.methods import Methods
+from pyrogram.session import Auth, Session
+from pyrogram.storage import Storage, FileStorage, MemoryStorage
+from pyrogram.types import User, TermsOfService
+from pyrogram.utils import ainput
+from .dispatcher import Dispatcher
+from .scaffold import Scaffold
+
+log = logging.getLogger(__name__)
+
+
+class Client(Methods, Scaffold):
+ """Pyrogram Client, the main means for interacting with Telegram.
+
+ Parameters:
+ session_name (``str``):
+ Pass a string of your choice to give a name to the client session, e.g.: "*my_account*". This name will be
+ used to save a file on disk that stores details needed to reconnect without asking again for credentials.
+ Alternatively, if you don't want a file to be saved on disk, pass the special name "**:memory:**" to start
+ an in-memory session that will be discarded as soon as you stop the Client. In order to reconnect again
+ using a memory storage without having to login again, you can use
+ :meth:`~pyrogram.Client.export_session_string` before stopping the client to get a session string you can
+ pass here as argument.
+
+ api_id (``int`` | ``str``, *optional*):
+ The *api_id* part of your Telegram API Key, as integer. E.g.: "12345".
+ This is an alternative way to pass it if you don't want to use the *config.ini* file.
+
+ api_hash (``str``, *optional*):
+ The *api_hash* part of your Telegram API Key, as string. E.g.: "0123456789abcdef0123456789abcdef".
+ This is an alternative way to set it if you don't want to use the *config.ini* file.
+
+ app_version (``str``, *optional*):
+ Application version. Defaults to "Pyrogram |version|".
+ This is an alternative way to set it if you don't want to use the *config.ini* file.
+
+ device_model (``str``, *optional*):
+ Device model. Defaults to *platform.python_implementation() + " " + platform.python_version()*.
+ This is an alternative way to set it if you don't want to use the *config.ini* file.
+
+ system_version (``str``, *optional*):
+ Operating System version. Defaults to *platform.system() + " " + platform.release()*.
+ This is an alternative way to set it if you don't want to use the *config.ini* file.
+
+ lang_code (``str``, *optional*):
+ Code of the language used on the client, in ISO 639-1 standard. Defaults to "en".
+ This is an alternative way to set it if you don't want to use the *config.ini* file.
+
+ ipv6 (``bool``, *optional*):
+ Pass True to connect to Telegram using IPv6.
+ Defaults to False (IPv4).
+
+ proxy (``dict``, *optional*):
+ Your SOCKS5 Proxy settings as dict,
+ e.g.: *dict(hostname="11.22.33.44", port=1080, username="user", password="pass")*.
+ The *username* and *password* can be omitted if your proxy doesn't require authorization.
+ This is an alternative way to setup a proxy if you don't want to use the *config.ini* file.
+
+ test_mode (``bool``, *optional*):
+ Enable or disable login to the test servers.
+ Only applicable for new sessions and will be ignored in case previously created sessions are loaded.
+ Defaults to False.
+
+ bot_token (``str``, *optional*):
+ Pass your Bot API token to create a bot session, e.g.: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
+ Only applicable for new sessions.
+ This is an alternative way to set it if you don't want to use the *config.ini* file.
+
+ phone_number (``str``, *optional*):
+ Pass your phone number as string (with your Country Code prefix included) to avoid entering it manually.
+ Only applicable for new sessions.
+
+ phone_code (``str``, *optional*):
+ Pass the phone code as string (for test numbers only) to avoid entering it manually.
+ Only applicable for new sessions.
+
+ password (``str``, *optional*):
+ Pass your Two-Step Verification password as string (if you have one) to avoid entering it manually.
+ Only applicable for new sessions.
+
+ force_sms (``bool``, *optional*):
+ Pass True to force Telegram sending the authorization code via SMS.
+ Only applicable for new sessions.
+ Defaults to False.
+
+ workers (``int``, *optional*):
+ Number of maximum concurrent workers for handling incoming updates.
+ Defaults to ``min(32, os.cpu_count() + 4)``.
+
+ workdir (``str``, *optional*):
+ Define a custom working directory. The working directory is the location in your filesystem where Pyrogram
+ will store your session files.
+ Defaults to the parent directory of the main script.
+
+ config_file (``str``, *optional*):
+ Path of the configuration file.
+ Defaults to ./config.ini
+
+ plugins (``dict``, *optional*):
+ Your Smart Plugins settings as dict, e.g.: *dict(root="plugins")*.
+ This is an alternative way to setup plugins if you don't want to use the *config.ini* file.
+
+ parse_mode (``str``, *optional*):
+ The parse mode, can be any of: *"combined"*, for the default combined mode. *"markdown"* or *"md"*
+ to force Markdown-only styles. *"html"* to force HTML-only styles. *None* to disable the parser
+ completely.
+
+ no_updates (``bool``, *optional*):
+ Pass True to completely disable incoming updates for the current session.
+ When updates are disabled your client can't receive any new message.
+ Useful for batch programs that don't need to deal with updates.
+ Defaults to False (updates enabled and always received).
+
+ takeout (``bool``, *optional*):
+ Pass True to let the client use a takeout session instead of a normal one, implies *no_updates=True*.
+ Useful for exporting your Telegram data. Methods invoked inside a takeout session (such as get_history,
+ download_media, ...) are less prone to throw FloodWait exceptions.
+ Only available for users, bots will ignore this parameter.
+ Defaults to False (normal session).
+
+ sleep_threshold (``int``, *optional*):
+ Set a sleep threshold for flood wait exceptions happening globally in this client instance, below which any
+ request that raises a flood wait will be automatically invoked again after sleeping for the required amount
+ of time. Flood wait exceptions requiring higher waiting times will be raised.
+ Defaults to 60 (seconds).
+ """
+
+ def __init__(
+ self,
+ session_name: Union[str, Storage],
+ api_id: Union[int, str] = None,
+ api_hash: str = None,
+ app_version: str = None,
+ device_model: str = None,
+ system_version: str = None,
+ lang_code: str = None,
+ ipv6: bool = False,
+ proxy: dict = None,
+ test_mode: bool = False,
+ bot_token: str = None,
+ phone_number: str = None,
+ phone_code: str = None,
+ password: str = None,
+ force_sms: bool = False,
+ workers: int = Scaffold.WORKERS,
+ workdir: str = Scaffold.WORKDIR,
+ config_file: str = Scaffold.CONFIG_FILE,
+ plugins: dict = None,
+ parse_mode: str = Scaffold.PARSE_MODES[0],
+ no_updates: bool = None,
+ takeout: bool = None,
+ sleep_threshold: int = Session.SLEEP_THRESHOLD
+ ):
+ super().__init__()
+
+ self.session_name = session_name
+ self.api_id = int(api_id) if api_id else None
+ self.api_hash = api_hash
+ self.app_version = app_version
+ self.device_model = device_model
+ self.system_version = system_version
+ self.lang_code = lang_code
+ self.ipv6 = ipv6
+ # TODO: Make code consistent, use underscore for private/protected fields
+ self._proxy = proxy
+ self.test_mode = test_mode
+ self.bot_token = bot_token
+ self.phone_number = phone_number
+ self.phone_code = phone_code
+ self.password = password
+ self.force_sms = force_sms
+ self.workers = workers
+ self.workdir = Path(workdir)
+ self.config_file = Path(config_file)
+ self.plugins = plugins
+ self.parse_mode = parse_mode
+ self.no_updates = no_updates
+ self.takeout = takeout
+ self.sleep_threshold = sleep_threshold
+
+ self.executor = ThreadPoolExecutor(self.workers, thread_name_prefix="Handler")
+
+ if isinstance(session_name, str):
+ if session_name == ":memory:" or len(session_name) >= MemoryStorage.SESSION_STRING_SIZE:
+ session_name = re.sub(r"[\n\s]+", "", session_name)
+ self.storage = MemoryStorage(session_name)
+ else:
+ self.storage = FileStorage(session_name, self.workdir)
+ elif isinstance(session_name, Storage):
+ self.storage = session_name
+ else:
+ raise ValueError("Unknown storage engine")
+
+ self.dispatcher = Dispatcher(self)
+ self.loop = asyncio.get_event_loop()
+
+ def __enter__(self):
+ return self.start()
+
+ def __exit__(self, *args):
+ try:
+ self.stop()
+ except ConnectionError:
+ pass
+
+ async def __aenter__(self):
+ return await self.start()
+
+ async def __aexit__(self, *args):
+ await self.stop()
+
+ @property
+ def proxy(self):
+ return self._proxy
+
+ @proxy.setter
+ def proxy(self, value):
+ if value is None:
+ self._proxy = None
+ return
+
+ if self._proxy is None:
+ self._proxy = {}
+
+ self._proxy["enabled"] = bool(value.get("enabled", True))
+ self._proxy.update(value)
+
+ async def authorize(self) -> User:
+ if self.bot_token:
+ return await self.sign_in_bot(self.bot_token)
+
+ while True:
+ try:
+ if not self.phone_number:
+ while True:
+ value = await ainput("Enter phone number or bot token: ")
+
+ if not value:
+ continue
+
+ confirm = (await ainput(f'Is "{value}" correct? (y/N): ')).lower()
+
+ if confirm == "y":
+ break
+
+ if ":" in value:
+ self.bot_token = value
+ return await self.sign_in_bot(value)
+ else:
+ self.phone_number = value
+
+ sent_code = await self.send_code(self.phone_number)
+ except BadRequest as e:
+ print(e.MESSAGE)
+ self.phone_number = None
+ self.bot_token = None
+ else:
+ break
+
+ if self.force_sms:
+ sent_code = await self.resend_code(self.phone_number, sent_code.phone_code_hash)
+
+ print("The confirmation code has been sent via {}".format(
+ {
+ "app": "Telegram app",
+ "sms": "SMS",
+ "call": "phone call",
+ "flash_call": "phone flash call"
+ }[sent_code.type]
+ ))
+
+ while True:
+ if not self.phone_code:
+ self.phone_code = await ainput("Enter confirmation code: ")
+
+ try:
+ signed_in = await self.sign_in(self.phone_number, sent_code.phone_code_hash, self.phone_code)
+ except BadRequest as e:
+ print(e.MESSAGE)
+ self.phone_code = None
+ except SessionPasswordNeeded as e:
+ print(e.MESSAGE)
+
+ while True:
+ print("Password hint: {}".format(await self.get_password_hint()))
+
+ if not self.password:
+ self.password = await ainput("Enter password (empty to recover): ", hide=True)
+
+ try:
+ if not self.password:
+ confirm = await ainput("Confirm password recovery (y/n): ")
+
+ if confirm == "y":
+ email_pattern = await self.send_recovery_code()
+ print(f"The recovery code has been sent to {email_pattern}")
+
+ while True:
+ recovery_code = await ainput("Enter recovery code: ")
+
+ try:
+ return await self.recover_password(recovery_code)
+ except BadRequest as e:
+ print(e.MESSAGE)
+ except Exception as e:
+ log.error(e, exc_info=True)
+ raise
+ else:
+ self.password = None
+ else:
+ return await self.check_password(self.password)
+ except BadRequest as e:
+ print(e.MESSAGE)
+ self.password = None
+ else:
+ break
+
+ if isinstance(signed_in, User):
+ return signed_in
+
+ while True:
+ first_name = await ainput("Enter first name: ")
+ last_name = await ainput("Enter last name (empty to skip): ")
+
+ try:
+ signed_up = await self.sign_up(
+ self.phone_number,
+ sent_code.phone_code_hash,
+ first_name,
+ last_name
+ )
+ except BadRequest as e:
+ print(e.MESSAGE)
+ else:
+ break
+
+ if isinstance(signed_in, TermsOfService):
+ print("\n" + signed_in.text + "\n")
+ await self.accept_terms_of_service(signed_in.id)
+
+ return signed_up
+
+ @property
+ def parse_mode(self):
+ return self._parse_mode
+
+ @parse_mode.setter
+ def parse_mode(self, parse_mode: Union[str, None] = "combined"):
+ if parse_mode not in self.PARSE_MODES:
+ raise ValueError('parse_mode must be one of {} or None. Not "{}"'.format(
+ ", ".join(f'"{m}"' for m in self.PARSE_MODES[:-1]),
+ parse_mode
+ ))
+
+ self._parse_mode = parse_mode
+
+ # TODO: redundant, remove in next major version
+ def set_parse_mode(self, parse_mode: Union[str, None] = "combined"):
+ """Set the parse mode to be used globally by the client.
+
+ When setting the parse mode with this method, all other methods having a *parse_mode* parameter will follow the
+ global value by default. The default value *"combined"* enables both Markdown and HTML styles to be used and
+ combined together.
+
+ Parameters:
+ parse_mode (``str``):
+ The new parse mode, can be any of: *"combined"*, for the default combined mode. *"markdown"* or *"md"*
+ to force Markdown-only styles. *"html"* to force HTML-only styles. *None* to disable the parser
+ completely.
+
+ Raises:
+ ValueError: In case the provided *parse_mode* is not a valid parse mode.
+
+ Example:
+ .. code-block:: python
+ :emphasize-lines: 10,14,18,22
+
+ from pyrogram import Client
+
+ app = Client("my_account")
+
+ with app:
+ # Default combined mode: Markdown + HTML
+ app.send_message("haskell", "1. **markdown** and html")
+
+ # Force Markdown-only, HTML is disabled
+ app.set_parse_mode("markdown")
+ app.send_message("haskell", "2. **markdown** and html")
+
+ # Force HTML-only, Markdown is disabled
+ app.set_parse_mode("html")
+ app.send_message("haskell", "3. **markdown** and html")
+
+ # Disable the parser completely
+ app.set_parse_mode(None)
+ app.send_message("haskell", "4. **markdown** and html")
+
+ # Bring back the default combined mode
+ app.set_parse_mode()
+ app.send_message("haskell", "5. **markdown** and html")
+ """
+
+ self.parse_mode = parse_mode
+
+ async def fetch_peers(self, peers: List[Union[raw.types.User, raw.types.Chat, raw.types.Channel]]) -> bool:
+ is_min = False
+ parsed_peers = []
+
+ for peer in peers:
+ if getattr(peer, "min", False):
+ is_min = True
+ continue
+
+ username = None
+ phone_number = None
+
+ if isinstance(peer, raw.types.User):
+ peer_id = peer.id
+ access_hash = peer.access_hash
+ username = (peer.username or "").lower() or None
+ phone_number = peer.phone
+ peer_type = "bot" if peer.bot else "user"
+ elif isinstance(peer, (raw.types.Chat, raw.types.ChatForbidden)):
+ peer_id = -peer.id
+ access_hash = 0
+ peer_type = "group"
+ elif isinstance(peer, (raw.types.Channel, raw.types.ChannelForbidden)):
+ peer_id = utils.get_channel_id(peer.id)
+ access_hash = peer.access_hash
+ username = (getattr(peer, "username", None) or "").lower() or None
+ peer_type = "channel" if peer.broadcast else "supergroup"
+ else:
+ continue
+
+ parsed_peers.append((peer_id, access_hash, peer_type, username, phone_number))
+
+ await self.storage.update_peers(parsed_peers)
+
+ return is_min
+
+ async def handle_download(self, packet):
+ temp_file_path = ""
+ final_file_path = ""
+
+ try:
+ data, directory, file_name, progress, progress_args = packet
+
+ temp_file_path = await self.get_file(
+ media_type=data.media_type,
+ dc_id=data.dc_id,
+ document_id=data.document_id,
+ access_hash=data.access_hash,
+ thumb_size=data.thumb_size,
+ peer_id=data.peer_id,
+ peer_type=data.peer_type,
+ peer_access_hash=data.peer_access_hash,
+ volume_id=data.volume_id,
+ local_id=data.local_id,
+ file_ref=data.file_ref,
+ file_size=data.file_size,
+ is_big=data.is_big,
+ progress=progress,
+ progress_args=progress_args
+ )
+
+ if temp_file_path:
+ final_file_path = os.path.abspath(re.sub("\\\\", "/", os.path.join(directory, file_name)))
+ os.makedirs(directory, exist_ok=True)
+ shutil.move(temp_file_path, final_file_path)
+ except Exception as e:
+ log.error(e, exc_info=True)
+
+ try:
+ os.remove(temp_file_path)
+ except OSError:
+ pass
+ else:
+ return final_file_path or None
+
+ async def handle_updates(self, updates):
+ if isinstance(updates, (raw.types.Updates, raw.types.UpdatesCombined)):
+ is_min = (await self.fetch_peers(updates.users)) or (await self.fetch_peers(updates.chats))
+
+ users = {u.id: u for u in updates.users}
+ chats = {c.id: c for c in updates.chats}
+
+ for update in updates.updates:
+ channel_id = getattr(
+ getattr(
+ getattr(
+ update, "message", None
+ ), "to_id", None
+ ), "channel_id", None
+ ) or getattr(update, "channel_id", None)
+
+ pts = getattr(update, "pts", None)
+ pts_count = getattr(update, "pts_count", None)
+
+ if isinstance(update, raw.types.UpdateChannelTooLong):
+ log.warning(update)
+
+ if isinstance(update, raw.types.UpdateNewChannelMessage) and is_min:
+ message = update.message
+
+ if not isinstance(message, raw.types.MessageEmpty):
+ try:
+ diff = await self.send(
+ raw.functions.updates.GetChannelDifference(
+ channel=await self.resolve_peer(utils.get_channel_id(channel_id)),
+ filter=raw.types.ChannelMessagesFilter(
+ ranges=[raw.types.MessageRange(
+ min_id=update.message.id,
+ max_id=update.message.id
+ )]
+ ),
+ pts=pts - pts_count,
+ limit=pts
+ )
+ )
+ except ChannelPrivate:
+ pass
+ else:
+ if not isinstance(diff, raw.types.updates.ChannelDifferenceEmpty):
+ users.update({u.id: u for u in diff.users})
+ chats.update({c.id: c for c in diff.chats})
+
+ self.dispatcher.updates_queue.put_nowait((update, users, chats))
+ elif isinstance(updates, (raw.types.UpdateShortMessage, raw.types.UpdateShortChatMessage)):
+ diff = await self.send(
+ raw.functions.updates.GetDifference(
+ pts=updates.pts - updates.pts_count,
+ date=updates.date,
+ qts=-1
+ )
+ )
+
+ if diff.new_messages:
+ self.dispatcher.updates_queue.put_nowait((
+ raw.types.UpdateNewMessage(
+ message=diff.new_messages[0],
+ pts=updates.pts,
+ pts_count=updates.pts_count
+ ),
+ {u.id: u for u in diff.users},
+ {c.id: c for c in diff.chats}
+ ))
+ else:
+ self.dispatcher.updates_queue.put_nowait((diff.other_updates[0], {}, {}))
+ elif isinstance(updates, raw.types.UpdateShort):
+ self.dispatcher.updates_queue.put_nowait((updates.update, {}, {}))
+ elif isinstance(updates, raw.types.UpdatesTooLong):
+ log.info(updates)
+
+ def load_config(self):
+ parser = ConfigParser()
+ parser.read(str(self.config_file))
+
+ if self.bot_token:
+ pass
+ else:
+ self.bot_token = parser.get("pyrogram", "bot_token", fallback=None)
+
+ if self.api_id and self.api_hash:
+ pass
+ else:
+ if parser.has_section("pyrogram"):
+ self.api_id = parser.getint("pyrogram", "api_id")
+ self.api_hash = parser.get("pyrogram", "api_hash")
+ else:
+ raise AttributeError("No API Key found. More info: https://docs.pyrogram.org/intro/setup")
+
+ for option in ["app_version", "device_model", "system_version", "lang_code"]:
+ if getattr(self, option):
+ pass
+ else:
+ if parser.has_section("pyrogram"):
+ setattr(self, option, parser.get(
+ "pyrogram",
+ option,
+ fallback=getattr(Client, option.upper())
+ ))
+ else:
+ setattr(self, option, getattr(Client, option.upper()))
+
+ if self._proxy:
+ self._proxy["enabled"] = bool(self._proxy.get("enabled", True))
+ else:
+ self._proxy = {}
+
+ if parser.has_section("proxy"):
+ self._proxy["enabled"] = parser.getboolean("proxy", "enabled", fallback=True)
+ self._proxy["hostname"] = parser.get("proxy", "hostname")
+ self._proxy["port"] = parser.getint("proxy", "port")
+ self._proxy["username"] = parser.get("proxy", "username", fallback=None) or None
+ self._proxy["password"] = parser.get("proxy", "password", fallback=None) or None
+
+ if self.plugins:
+ self.plugins = {
+ "enabled": bool(self.plugins.get("enabled", True)),
+ "root": self.plugins.get("root", None),
+ "include": self.plugins.get("include", []),
+ "exclude": self.plugins.get("exclude", [])
+ }
+ else:
+ try:
+ section = parser["plugins"]
+
+ self.plugins = {
+ "enabled": section.getboolean("enabled", True),
+ "root": section.get("root", None),
+ "include": section.get("include", []),
+ "exclude": section.get("exclude", [])
+ }
+
+ include = self.plugins["include"]
+ exclude = self.plugins["exclude"]
+
+ if include:
+ self.plugins["include"] = include.strip().split("\n")
+
+ if exclude:
+ self.plugins["exclude"] = exclude.strip().split("\n")
+
+ except KeyError:
+ self.plugins = None
+
+ async def load_session(self):
+ await self.storage.open()
+
+ session_empty = any([
+ await self.storage.test_mode() is None,
+ await self.storage.auth_key() is None,
+ await self.storage.user_id() is None,
+ await self.storage.is_bot() is None
+ ])
+
+ if session_empty:
+ await self.storage.dc_id(2)
+ await self.storage.date(0)
+
+ await self.storage.test_mode(self.test_mode)
+ await self.storage.auth_key(
+ await Auth(
+ self, await self.storage.dc_id(),
+ await self.storage.test_mode()
+ ).create()
+ )
+ await self.storage.user_id(None)
+ await self.storage.is_bot(None)
+
+ def load_plugins(self):
+ if self.plugins:
+ plugins = self.plugins.copy()
+
+ for option in ["include", "exclude"]:
+ if plugins[option]:
+ plugins[option] = [
+ (i.split()[0], i.split()[1:] or None)
+ for i in self.plugins[option]
+ ]
+ else:
+ return
+
+ if plugins.get("enabled", False):
+ root = plugins["root"]
+ include = plugins["include"]
+ exclude = plugins["exclude"]
+
+ count = 0
+
+ if not include:
+ for path in sorted(Path(root.replace(".", "/")).rglob("*.py")):
+ module_path = '.'.join(path.parent.parts + (path.stem,))
+ module = import_module(module_path)
+
+ for name in vars(module).keys():
+ # noinspection PyBroadException
+ try:
+ handler, group = getattr(module, name).handler
+
+ if isinstance(handler, Handler) and isinstance(group, int):
+ self.add_handler(handler, group)
+
+ log.info('[{}] [LOAD] {}("{}") in group {} from "{}"'.format(
+ self.session_name, type(handler).__name__, name, group, module_path))
+
+ count += 1
+ except Exception:
+ pass
+ else:
+ for path, handlers in include:
+ module_path = root + "." + path
+ warn_non_existent_functions = True
+
+ try:
+ module = import_module(module_path)
+ except ImportError:
+ log.warning(f'[{self.session_name}] [LOAD] Ignoring non-existent module "{module_path}"')
+ continue
+
+ if "__path__" in dir(module):
+ log.warning(f'[{self.session_name}] [LOAD] Ignoring namespace "{module_path}"')
+ continue
+
+ if handlers is None:
+ handlers = vars(module).keys()
+ warn_non_existent_functions = False
+
+ for name in handlers:
+ # noinspection PyBroadException
+ try:
+ handler, group = getattr(module, name).handler
+
+ if isinstance(handler, Handler) and isinstance(group, int):
+ self.add_handler(handler, group)
+
+ log.info('[{}] [LOAD] {}("{}") in group {} from "{}"'.format(
+ self.session_name, type(handler).__name__, name, group, module_path))
+
+ count += 1
+ except Exception:
+ if warn_non_existent_functions:
+ log.warning('[{}] [LOAD] Ignoring non-existent function "{}" from "{}"'.format(
+ self.session_name, name, module_path))
+
+ if exclude:
+ for path, handlers in exclude:
+ module_path = root + "." + path
+ warn_non_existent_functions = True
+
+ try:
+ module = import_module(module_path)
+ except ImportError:
+ log.warning(f'[{self.session_name}] [UNLOAD] Ignoring non-existent module "{module_path}"')
+ continue
+
+ if "__path__" in dir(module):
+ log.warning(f'[{self.session_name}] [UNLOAD] Ignoring namespace "{module_path}"')
+ continue
+
+ if handlers is None:
+ handlers = vars(module).keys()
+ warn_non_existent_functions = False
+
+ for name in handlers:
+ # noinspection PyBroadException
+ try:
+ handler, group = getattr(module, name).handler
+
+ if isinstance(handler, Handler) and isinstance(group, int):
+ self.remove_handler(handler, group)
+
+ log.info('[{}] [UNLOAD] {}("{}") from group {} in "{}"'.format(
+ self.session_name, type(handler).__name__, name, group, module_path))
+
+ count -= 1
+ except Exception:
+ if warn_non_existent_functions:
+ log.warning('[{}] [UNLOAD] Ignoring non-existent function "{}" from "{}"'.format(
+ self.session_name, name, module_path))
+
+ if count > 0:
+ log.info('[{}] Successfully loaded {} plugin{} from "{}"'.format(
+ self.session_name, count, "s" if count > 1 else "", root))
+ else:
+ log.warning(f'[{self.session_name}] No plugin loaded from "{root}"')
+
+ async def get_file(
+ self,
+ media_type: int,
+ dc_id: int,
+ document_id: int,
+ access_hash: int,
+ thumb_size: str,
+ peer_id: int,
+ peer_type: str,
+ peer_access_hash: int,
+ volume_id: int,
+ local_id: int,
+ file_ref: str,
+ file_size: int,
+ is_big: bool,
+ progress: callable,
+ progress_args: tuple = ()
+ ) -> str:
+ async with self.media_sessions_lock:
+ session = self.media_sessions.get(dc_id, None)
+
+ if session is None:
+ if dc_id != await self.storage.dc_id():
+ session = Session(
+ self, dc_id, await Auth(self, dc_id, await self.storage.test_mode()).create(),
+ await self.storage.test_mode(), is_media=True
+ )
+ await session.start()
+
+ for _ in range(3):
+ exported_auth = await self.send(
+ raw.functions.auth.ExportAuthorization(
+ dc_id=dc_id
+ )
+ )
+
+ try:
+ await session.send(
+ raw.functions.auth.ImportAuthorization(
+ id=exported_auth.id,
+ bytes=exported_auth.bytes
+ )
+ )
+ except AuthBytesInvalid:
+ continue
+ else:
+ break
+ else:
+ await session.stop()
+ raise AuthBytesInvalid
+ else:
+ session = Session(
+ self, dc_id, await self.storage.auth_key(),
+ await self.storage.test_mode(), is_media=True
+ )
+ await session.start()
+
+ self.media_sessions[dc_id] = session
+
+ file_ref = utils.decode_file_ref(file_ref)
+
+ if media_type == 1:
+ if peer_type == "user":
+ peer = raw.types.InputPeerUser(
+ user_id=peer_id,
+ access_hash=peer_access_hash
+ )
+ elif peer_type == "chat":
+ peer = raw.types.InputPeerChat(
+ chat_id=peer_id
+ )
+ else:
+ peer = raw.types.InputPeerChannel(
+ channel_id=peer_id,
+ access_hash=peer_access_hash
+ )
+
+ location = raw.types.InputPeerPhotoFileLocation(
+ peer=peer,
+ volume_id=volume_id,
+ local_id=local_id,
+ big=is_big or None
+ )
+ elif media_type in (0, 2):
+ location = raw.types.InputPhotoFileLocation(
+ id=document_id,
+ access_hash=access_hash,
+ file_reference=file_ref,
+ thumb_size=thumb_size
+ )
+ elif media_type == 14:
+ location = raw.types.InputDocumentFileLocation(
+ id=document_id,
+ access_hash=access_hash,
+ file_reference=file_ref,
+ thumb_size=thumb_size
+ )
+ else:
+ location = raw.types.InputDocumentFileLocation(
+ id=document_id,
+ access_hash=access_hash,
+ file_reference=file_ref,
+ thumb_size=""
+ )
+
+ limit = 1024 * 1024
+ offset = 0
+ file_name = ""
+
+ try:
+ r = await session.send(
+ raw.functions.upload.GetFile(
+ location=location,
+ offset=offset,
+ limit=limit
+ )
+ )
+
+ if isinstance(r, raw.types.upload.File):
+ with tempfile.NamedTemporaryFile("wb", delete=False) as f:
+ file_name = f.name
+
+ while True:
+ chunk = r.bytes
+
+ if not chunk:
+ break
+
+ f.write(chunk)
+
+ offset += limit
+
+ if progress:
+ await progress(
+ min(offset, file_size)
+ if file_size != 0
+ else offset,
+ file_size,
+ *progress_args
+ )
+
+ r = await session.send(
+ raw.functions.upload.GetFile(
+ location=location,
+ offset=offset,
+ limit=limit
+ )
+ )
+
+ elif isinstance(r, raw.types.upload.FileCdnRedirect):
+ async with self.media_sessions_lock:
+ cdn_session = self.media_sessions.get(r.dc_id, None)
+
+ if cdn_session is None:
+ cdn_session = Session(
+ self, r.dc_id, await Auth(self, r.dc_id, await self.storage.test_mode()).create(),
+ await self.storage.test_mode(), is_media=True, is_cdn=True
+ )
+
+ await cdn_session.start()
+
+ self.media_sessions[r.dc_id] = cdn_session
+
+ try:
+ with tempfile.NamedTemporaryFile("wb", delete=False) as f:
+ file_name = f.name
+
+ while True:
+ r2 = await cdn_session.send(
+ raw.functions.upload.GetCdnFile(
+ file_token=r.file_token,
+ offset=offset,
+ limit=limit
+ )
+ )
+
+ if isinstance(r2, raw.types.upload.CdnFileReuploadNeeded):
+ try:
+ await session.send(
+ raw.functions.upload.ReuploadCdnFile(
+ file_token=r.file_token,
+ request_token=r2.request_token
+ )
+ )
+ except VolumeLocNotFound:
+ break
+ else:
+ continue
+
+ chunk = r2.bytes
+
+ # https://core.telegram.org/cdn#decrypting-files
+ decrypted_chunk = aes.ctr256_decrypt(
+ chunk,
+ r.encryption_key,
+ bytearray(
+ r.encryption_iv[:-4]
+ + (offset // 16).to_bytes(4, "big")
+ )
+ )
+
+ hashes = await session.send(
+ raw.functions.upload.GetCdnFileHashes(
+ file_token=r.file_token,
+ offset=offset
+ )
+ )
+
+ # https://core.telegram.org/cdn#verifying-files
+ for i, h in enumerate(hashes):
+ cdn_chunk = decrypted_chunk[h.limit * i: h.limit * (i + 1)]
+ assert h.hash == sha256(cdn_chunk).digest(), f"Invalid CDN hash part {i}"
+
+ f.write(decrypted_chunk)
+
+ offset += limit
+
+ if progress:
+ if asyncio.iscoroutinefunction(progress):
+ await progress(
+ min(offset, file_size) if file_size != 0 else offset,
+ file_size,
+ *progress_args
+ )
+ else:
+ func = functools.partial(
+ progress,
+ min(offset, file_size) if file_size != 0 else offset,
+ file_size,
+ *progress_args
+ )
+
+ await self.loop.run_in_executor(self.executor, func)
+
+ if len(chunk) < limit:
+ break
+ except Exception as e:
+ raise e
+ except Exception as e:
+ if not isinstance(e, pyrogram.StopTransmission):
+ log.error(e, exc_info=True)
+
+ try:
+ os.remove(file_name)
+ except OSError:
+ pass
+
+ return ""
+ else:
+ return file_name
+
+ def guess_mime_type(self, filename: str):
+ extension = os.path.splitext(filename)[1]
+ return self.extensions_to_mime_types.get(extension)
+
+ def guess_extension(self, mime_type: str):
+ extensions = self.mime_types_to_extensions.get(mime_type)
+
+ if extensions:
+ return extensions.split(" ")[0]
diff --git a/pyrogram/client/__init__.py b/pyrogram/client/__init__.py
deleted file mode 100644
index d0b82f9184..0000000000
--- a/pyrogram/client/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Pyrogram - Telegram MTProto API Client Library for Python
-# Copyright (C) 2017-2020 Dan
-#
-# This file is part of Pyrogram.
-#
-# Pyrogram is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Pyrogram is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with Pyrogram. If not, see .
-
-from .client import Client
-from .ext import BaseClient, Emoji
-from .filters import Filters
-
-__all__ = [
- "Client", "BaseClient", "Emoji", "Filters",
-]
diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py
deleted file mode 100644
index 624c98c616..0000000000
--- a/pyrogram/client/client.py
+++ /dev/null
@@ -1,2151 +0,0 @@
-# Pyrogram - Telegram MTProto API Client Library for Python
-# Copyright (C) 2017-2020 Dan
-#
-# This file is part of Pyrogram.
-#
-# Pyrogram is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Pyrogram is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with Pyrogram. If not, see .
-
-import asyncio
-import io
-import logging
-import math
-import os
-import re
-import shutil
-import tempfile
-from configparser import ConfigParser
-from hashlib import sha256, md5
-from importlib import import_module
-from pathlib import Path, Pureapath
-from signal import signal, SIGINT, SIGTERM, SIGABRT
-from typing import Union, List, BinaryIO
-
-from pyrogram.api import functions, types
-from pyrogram.api.core import TLObject
-from pyrogram.client.handlers import DisconnectHandler
-from pyrogram.client.handlers.handler import Handler
-from pyrogram.client.methods.password.utils import compute_check
-from pyrogram.crypto import AES
-from pyrogram.errors import (
- PhoneMigrate, NetworkMigrate, SessionPasswordNeeded,
- PeerIdInvalid, VolumeLocNotFound, UserMigrate, ChannelPrivate,
- AuthBytesInvalid, BadRequest
-)
-from pyrogram.session import Auth, Session
-from .ext import utils, Syncer, BaseClient, Dispatcher
-from .ext.utils import ainput
-from .methods import Methods
-from .storage import Storage, FileStorage, MemoryStorage
-from .types import User, SentCode, TermsOfService
-
-log = logging.getLogger(__name__)
-
-
-class Client(Methods, BaseClient):
- """Pyrogram Client, the main means for interacting with Telegram.
-
- Parameters:
- session_name (``str``):
- Pass a string of your choice to give a name to the client session, e.g.: "*my_account*". This name will be
- used to save a file on disk that stores details needed to reconnect without asking again for credentials.
- Alternatively, if you don't want a file to be saved on disk, pass the special name "**:memory:**" to start
- an in-memory session that will be discarded as soon as you stop the Client. In order to reconnect again
- using a memory storage without having to login again, you can use
- :meth:`~pyrogram.Client.export_session_string` before stopping the client to get a session string you can
- pass here as argument.
-
- api_id (``int`` | ``str``, *optional*):
- The *api_id* part of your Telegram API Key, as integer. E.g.: "12345".
- This is an alternative way to pass it if you don't want to use the *config.ini* file.
-
- api_hash (``str``, *optional*):
- The *api_hash* part of your Telegram API Key, as string. E.g.: "0123456789abcdef0123456789abcdef".
- This is an alternative way to set it if you don't want to use the *config.ini* file.
-
- app_version (``str``, *optional*):
- Application version. Defaults to "Pyrogram |version|".
- This is an alternative way to set it if you don't want to use the *config.ini* file.
-
- device_model (``str``, *optional*):
- Device model. Defaults to *platform.python_implementation() + " " + platform.python_version()*.
- This is an alternative way to set it if you don't want to use the *config.ini* file.
-
- system_version (``str``, *optional*):
- Operating System version. Defaults to *platform.system() + " " + platform.release()*.
- This is an alternative way to set it if you don't want to use the *config.ini* file.
-
- lang_code (``str``, *optional*):
- Code of the language used on the client, in ISO 639-1 standard. Defaults to "en".
- This is an alternative way to set it if you don't want to use the *config.ini* file.
-
- ipv6 (``bool``, *optional*):
- Pass True to connect to Telegram using IPv6.
- Defaults to False (IPv4).
-
- proxy (``dict``, *optional*):
- Your SOCKS5 Proxy settings as dict,
- e.g.: *dict(hostname="11.22.33.44", port=1080, username="user", password="pass")*.
- The *username* and *password* can be omitted if your proxy doesn't require authorization.
- This is an alternative way to setup a proxy if you don't want to use the *config.ini* file.
-
- test_mode (``bool``, *optional*):
- Enable or disable login to the test servers.
- Only applicable for new sessions and will be ignored in case previously created sessions are loaded.
- Defaults to False.
-
- bot_token (``str``, *optional*):
- Pass your Bot API token to create a bot session, e.g.: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
- Only applicable for new sessions.
- This is an alternative way to set it if you don't want to use the *config.ini* file.
-
- phone_number (``str``, *optional*):
- Pass your phone number as string (with your Country Code prefix included) to avoid entering it manually.
- Only applicable for new sessions.
-
- phone_code (``str``, *optional*):
- Pass the phone code as string (for test numbers only) to avoid entering it manually.
- Only applicable for new sessions.
-
- password (``str``, *optional*):
- Pass your Two-Step Verification password as string (if you have one) to avoid entering it manually.
- Only applicable for new sessions.
-
- force_sms (``bool``, *optional*):
- Pass True to force Telegram sending the authorization code via SMS.
- Only applicable for new sessions.
- Defaults to False.
-
- workers (``int``, *optional*):
- Number of maximum concurrent workers for handling incoming updates.
- Defaults to 4.
-
- workdir (``str``, *optional*):
- Define a custom working directory. The working directory is the location in your filesystem where Pyrogram
- will store your session files.
- Defaults to the parent directory of the main script.
-
- config_file (``str``, *optional*):
- Path of the configuration file.
- Defaults to ./config.ini
-
- plugins (``dict``, *optional*):
- Your Smart Plugins settings as dict, e.g.: *dict(root="plugins")*.
- This is an alternative way to setup plugins if you don't want to use the *config.ini* file.
-
- parse_mode (``str``, *optional*):
- The parse mode, can be any of: *"combined"*, for the default combined mode. *"markdown"* or *"md"*
- to force Markdown-only styles. *"html"* to force HTML-only styles. *None* to disable the parser
- completely.
-
- no_updates (``bool``, *optional*):
- Pass True to completely disable incoming updates for the current session.
- When updates are disabled your client can't receive any new message.
- Useful for batch programs that don't need to deal with updates.
- Defaults to False (updates enabled and always received).
-
- takeout (``bool``, *optional*):
- Pass True to let the client use a takeout session instead of a normal one, implies *no_updates=True*.
- Useful for exporting your Telegram data. Methods invoked inside a takeout session (such as get_history,
- download_media, ...) are less prone to throw FloodWait exceptions.
- Only available for users, bots will ignore this parameter.
- Defaults to False (normal session).
-
- sleep_threshold (``int``, *optional*):
- Set a sleep threshold for flood wait exceptions happening globally in this client instance, below which any
- request that raises a flood wait will be automatically invoked again after sleeping for the required amount
- of time. Flood wait exceptions requiring higher waiting times will be raised.
- Defaults to 60 (seconds).
- """
-
- def __init__(
- self,
- session_name: Union[str, Storage],
- api_id: Union[int, str] = None,
- api_hash: str = None,
- app_version: str = None,
- device_model: str = None,
- system_version: str = None,
- lang_code: str = None,
- ipv6: bool = False,
- proxy: dict = None,
- test_mode: bool = False,
- bot_token: str = None,
- phone_number: str = None,
- phone_code: str = None,
- password: str = None,
- force_sms: bool = False,
- workers: int = BaseClient.WORKERS,
- workdir: str = BaseClient.WORKDIR,
- config_file: str = BaseClient.CONFIG_FILE,
- plugins: dict = None,
- parse_mode: str = BaseClient.PARSE_MODES[0],
- no_updates: bool = None,
- takeout: bool = None,
- sleep_threshold: int = Session.SLEEP_THRESHOLD
- ):
- super().__init__()
-
- self.session_name = session_name
- self.api_id = int(api_id) if api_id else None
- self.api_hash = api_hash
- self.app_version = app_version
- self.device_model = device_model
- self.system_version = system_version
- self.lang_code = lang_code
- self.ipv6 = ipv6
- # TODO: Make code consistent, use underscore for private/protected fields
- self._proxy = proxy
- self.test_mode = test_mode
- self.bot_token = bot_token
- self.phone_number = phone_number
- self.phone_code = phone_code
- self.password = password
- self.force_sms = force_sms
- self.workers = workers
- self.workdir = Path(workdir)
- self.config_file = Path(config_file)
- self.plugins = plugins
- self.parse_mode = parse_mode
- self.no_updates = no_updates
- self.takeout = takeout
- self.sleep_threshold = sleep_threshold
-
- if isinstance(session_name, str):
- if session_name == ":memory:" or len(session_name) >= MemoryStorage.SESSION_STRING_SIZE:
- session_name = re.sub(r"[\n\s]+", "", session_name)
- self.storage = MemoryStorage(session_name)
- else:
- self.storage = FileStorage(session_name, self.workdir)
- elif isinstance(session_name, Storage):
- self.storage = session_name
- else:
- raise ValueError("Unknown storage engine")
-
- self.dispatcher = Dispatcher(self, 0 if no_updates else workers)
-
- def __enter__(self):
- return self.start()
-
- def __exit__(self, *args):
- try:
- self.stop()
- except ConnectionError:
- pass
-
- async def __aenter__(self):
- return await self.start()
-
- async def __aexit__(self, *args):
- await self.stop()
-
- @property
- def proxy(self):
- return self._proxy
-
- @proxy.setter
- def proxy(self, value):
- if value is None:
- self._proxy = None
- return
-
- if self._proxy is None:
- self._proxy = {}
-
- self._proxy["enabled"] = bool(value.get("enabled", True))
- self._proxy.update(value)
-
- async def connect(self) -> bool:
- """
- Connect the client to Telegram servers.
-
- Returns:
- ``bool``: On success, in case the passed-in session is authorized, True is returned. Otherwise, in case
- the session needs to be authorized, False is returned.
-
- Raises:
- ConnectionError: In case you try to connect an already connected client.
- """
- if self.is_connected:
- raise ConnectionError("Client is already connected")
-
- self.load_config()
- await self.load_session()
-
- self.session = Session(self, self.storage.dc_id(), self.storage.auth_key())
-
- await self.session.start()
-
- self.is_connected = True
-
- return bool(self.storage.user_id())
-
- async def disconnect(self):
- """Disconnect the client from Telegram servers.
-
- Raises:
- ConnectionError: In case you try to disconnect an already disconnected client or in case you try to
- disconnect a client that needs to be terminated first.
- """
- if not self.is_connected:
- raise ConnectionError("Client is already disconnected")
-
- if self.is_initialized:
- raise ConnectionError("Can't disconnect an initialized client")
-
- await self.session.stop()
- self.storage.close()
- self.is_connected = False
-
- async def initialize(self):
- """Initialize the client by starting up workers.
-
- This method will start updates and download workers.
- It will also load plugins and start the internal dispatcher.
-
- Raises:
- ConnectionError: In case you try to initialize a disconnected client or in case you try to initialize an
- already initialized client.
- """
- if not self.is_connected:
- raise ConnectionError("Can't initialize a disconnected client")
-
- if self.is_initialized:
- raise ConnectionError("Client is already initialized")
-
- self.load_plugins()
-
- if not self.no_updates:
- for _ in range(Client.UPDATES_WORKERS):
- self.updates_worker_tasks.append(
- asyncio.ensure_future(self.updates_worker())
- )
-
- logging.info("Started {} UpdatesWorkerTasks".format(Client.UPDATES_WORKERS))
-
- for _ in range(Client.DOWNLOAD_WORKERS):
- self.download_worker_tasks.append(
- asyncio.ensure_future(self.download_worker())
- )
-
- logging.info("Started {} DownloadWorkerTasks".format(Client.DOWNLOAD_WORKERS))
-
- await self.dispatcher.start()
- await Syncer.add(self)
-
- self.is_initialized = True
-
- async def terminate(self):
- """Terminate the client by shutting down workers.
-
- This method does the opposite of :meth:`~Client.initialize`.
- It will stop the dispatcher and shut down updates and download workers.
-
- Raises:
- ConnectionError: In case you try to terminate a client that is already terminated.
- """
- if not self.is_initialized:
- raise ConnectionError("Client is already terminated")
-
- if self.takeout_id:
- await self.send(functions.account.FinishTakeoutSession())
- log.warning("Takeout session {} finished".format(self.takeout_id))
-
- await Syncer.remove(self)
- await self.dispatcher.stop()
-
- for _ in range(Client.DOWNLOAD_WORKERS):
- self.download_queue.put_nowait(None)
-
- for task in self.download_worker_tasks:
- await task
-
- self.download_worker_tasks.clear()
-
- logging.info("Stopped {} DownloadWorkerTasks".format(Client.DOWNLOAD_WORKERS))
-
- if not self.no_updates:
- for _ in range(Client.UPDATES_WORKERS):
- self.updates_queue.put_nowait(None)
-
- for task in self.updates_worker_tasks:
- await task
-
- self.updates_worker_tasks.clear()
-
- logging.info("Stopped {} UpdatesWorkerTasks".format(Client.UPDATES_WORKERS))
-
- for media_session in self.media_sessions.values():
- await media_session.stop()
-
- self.media_sessions.clear()
-
- self.is_initialized = False
-
- async def send_code(self, phone_number: str) -> SentCode:
- """Send the confirmation code to the given phone number.
-
- Parameters:
- phone_number (``str``):
- Phone number in international format (includes the country prefix).
-
- Returns:
- :obj:`SentCode`: On success, an object containing information on the sent confirmation code is returned.
-
- Raises:
- BadRequest: In case the phone number is invalid.
- """
- phone_number = phone_number.strip(" +")
-
- while True:
- try:
- r = await self.send(
- functions.auth.SendCode(
- phone_number=phone_number,
- api_id=self.api_id,
- api_hash=self.api_hash,
- settings=types.CodeSettings()
- )
- )
- except (PhoneMigrate, NetworkMigrate) as e:
- await self.session.stop()
-
- self.storage.dc_id(e.x)
- self.storage.auth_key(await Auth(self, self.storage.dc_id()).create())
- self.session = Session(self, self.storage.dc_id(), self.storage.auth_key())
-
- await self.session.start()
- else:
- return SentCode._parse(r)
-
- async def resend_code(self, phone_number: str, phone_code_hash: str) -> SentCode:
- """Re-send the confirmation code using a different type.
-
- The type of the code to be re-sent is specified in the *next_type* attribute of the :obj:`SentCode` object
- returned by :meth:`send_code`.
-
- Parameters:
- phone_number (``str``):
- Phone number in international format (includes the country prefix).
-
- phone_code_hash (``str``):
- Confirmation code identifier.
-
- Returns:
- :obj:`SentCode`: On success, an object containing information on the re-sent confirmation code is returned.
-
- Raises:
- BadRequest: In case the arguments are invalid.
- """
- phone_number = phone_number.strip(" +")
-
- r = await self.send(
- functions.auth.ResendCode(
- phone_number=phone_number,
- phone_code_hash=phone_code_hash
- )
- )
-
- return SentCode._parse(r)
-
- async def sign_in(self, phone_number: str, phone_code_hash: str, phone_code: str) -> Union[
- User, TermsOfService, bool]:
- """Authorize a user in Telegram with a valid confirmation code.
-
- Parameters:
- phone_number (``str``):
- Phone number in international format (includes the country prefix).
-
- phone_code_hash (``str``):
- Code identifier taken from the result of :meth:`~Client.send_code`.
-
- phone_code (``str``):
- The valid confirmation code you received (either as Telegram message or as SMS in your phone number).
-
- Returns:
- :obj:`User` | :obj:`TermsOfService` | bool: On success, in case the authorization completed, the user is
- returned. In case the phone number needs to be registered first AND the terms of services accepted (with
- :meth:`~Client.accept_terms_of_service`), an object containing them is returned. In case the phone number
- needs to be registered, but the terms of services don't need to be accepted, False is returned instead.
-
- Raises:
- BadRequest: In case the arguments are invalid.
- SessionPasswordNeeded: In case a password is needed to sign in.
- """
- phone_number = phone_number.strip(" +")
-
- r = await self.send(
- functions.auth.SignIn(
- phone_number=phone_number,
- phone_code_hash=phone_code_hash,
- phone_code=phone_code
- )
- )
-
- if isinstance(r, types.auth.AuthorizationSignUpRequired):
- if r.terms_of_service:
- return TermsOfService._parse(terms_of_service=r.terms_of_service)
-
- return False
- else:
- self.storage.user_id(r.user.id)
- self.storage.is_bot(False)
-
- return User._parse(self, r.user)
-
- async def sign_up(self, phone_number: str, phone_code_hash: str, first_name: str, last_name: str = "") -> User:
- """Register a new user in Telegram.
-
- Parameters:
- phone_number (``str``):
- Phone number in international format (includes the country prefix).
-
- phone_code_hash (``str``):
- Code identifier taken from the result of :meth:`~Client.send_code`.
-
- first_name (``str``):
- New user first name.
-
- last_name (``str``, *optional*):
- New user last name. Defaults to "" (empty string, no last name).
-
- Returns:
- :obj:`User`: On success, the new registered user is returned.
-
- Raises:
- BadRequest: In case the arguments are invalid.
- """
- phone_number = phone_number.strip(" +")
-
- r = await self.send(
- functions.auth.SignUp(
- phone_number=phone_number,
- first_name=first_name,
- last_name=last_name,
- phone_code_hash=phone_code_hash
- )
- )
-
- self.storage.user_id(r.user.id)
- self.storage.is_bot(False)
-
- return User._parse(self, r.user)
-
- async def sign_in_bot(self, bot_token: str) -> User:
- """Authorize a bot using its bot token generated by BotFather.
-
- Parameters:
- bot_token (``str``):
- The bot token generated by BotFather
-
- Returns:
- :obj:`User`: On success, the bot identity is return in form of a user object.
-
- Raises:
- BadRequest: In case the bot token is invalid.
- """
- while True:
- try:
- r = await self.send(
- functions.auth.ImportBotAuthorization(
- flags=0,
- api_id=self.api_id,
- api_hash=self.api_hash,
- bot_auth_token=bot_token
- )
- )
- except UserMigrate as e:
- await self.session.stop()
-
- self.storage.dc_id(e.x)
- self.storage.auth_key(await Auth(self, self.storage.dc_id()).create())
- self.session = Session(self, self.storage.dc_id(), self.storage.auth_key())
-
- await self.session.start()
- else:
- self.storage.user_id(r.user.id)
- self.storage.is_bot(True)
-
- return User._parse(self, r.user)
-
- async def get_password_hint(self) -> str:
- """Get your Two-Step Verification password hint.
-
- Returns:
- ``str``: On success, the password hint as string is returned.
- """
- return (await self.send(functions.account.GetPassword())).hint
-
- async def check_password(self, password: str) -> User:
- """Check your Two-Step Verification password and log in.
-
- Parameters:
- password (``str``):
- Your Two-Step Verification password.
-
- Returns:
- :obj:`User`: On success, the authorized user is returned.
-
- Raises:
- BadRequest: In case the password is invalid.
- """
- r = await self.send(
- functions.auth.CheckPassword(
- password=compute_check(
- await self.send(functions.account.GetPassword()),
- password
- )
- )
- )
-
- self.storage.user_id(r.user.id)
- self.storage.is_bot(False)
-
- return User._parse(self, r.user)
-
- async def send_recovery_code(self) -> str:
- """Send a code to your email to recover your password.
-
- Returns:
- ``str``: On success, the hidden email pattern is returned and a recovery code is sent to that email.
-
- Raises:
- BadRequest: In case no recovery email was set up.
- """
- return (await self.send(
- functions.auth.RequestPasswordRecovery()
- )).email_pattern
-
- async def recover_password(self, recovery_code: str) -> User:
- """Recover your password with a recovery code and log in.
-
- Parameters:
- recovery_code (``str``):
- The recovery code sent via email.
-
- Returns:
- :obj:`User`: On success, the authorized user is returned and the Two-Step Verification password reset.
-
- Raises:
- BadRequest: In case the recovery code is invalid.
- """
- r = await self.send(
- functions.auth.RecoverPassword(
- code=recovery_code
- )
- )
-
- self.storage.user_id(r.user.id)
- self.storage.is_bot(False)
-
- return User._parse(self, r.user)
-
- async def accept_terms_of_service(self, terms_of_service_id: str) -> bool:
- """Accept the given terms of service.
-
- Parameters:
- terms_of_service_id (``str``):
- The terms of service identifier.
- """
- r = await self.send(
- functions.help.AcceptTermsOfService(
- id=types.DataJSON(
- data=terms_of_service_id
- )
- )
- )
-
- assert r
-
- return True
-
- async def authorize(self) -> User:
- if self.bot_token:
- return await self.sign_in_bot(self.bot_token)
-
- while True:
- try:
- if not self.phone_number:
- while True:
- value = await ainput("Enter phone number or bot token: ")
-
- if not value:
- continue
-
- confirm = input("Is \"{}\" correct? (y/N): ".format(value)).lower()
-
- if confirm == "y":
- break
-
- if ":" in value:
- self.bot_token = value
- return await self.sign_in_bot(value)
- else:
- self.phone_number = value
-
- sent_code = await self.send_code(self.phone_number)
- except BadRequest as e:
- print(e.MESSAGE)
- self.phone_number = None
- self.bot_token = None
- else:
- break
-
- if self.force_sms:
- sent_code = await self.resend_code(self.phone_number, sent_code.phone_code_hash)
-
- print("The confirmation code has been sent via {}".format(
- {
- "app": "Telegram app",
- "sms": "SMS",
- "call": "phone call",
- "flash_call": "phone flash call"
- }[sent_code.type]
- ))
-
- while True:
- if not self.phone_code:
- self.phone_code = await ainput("Enter confirmation code: ")
-
- try:
- signed_in = await self.sign_in(self.phone_number, sent_code.phone_code_hash, self.phone_code)
- except BadRequest as e:
- print(e.MESSAGE)
- self.phone_code = None
- except SessionPasswordNeeded as e:
- print(e.MESSAGE)
-
- while True:
- print("Password hint: {}".format(await self.get_password_hint()))
-
- if not self.password:
- self.password = await ainput("Enter password (empty to recover): ")
-
- try:
- if not self.password:
- confirm = await ainput("Confirm password recovery (y/n): ")
-
- if confirm == "y":
- email_pattern = await self.send_recovery_code()
- print("The recovery code has been sent to {}".format(email_pattern))
-
- while True:
- recovery_code = await ainput("Enter recovery code: ")
-
- try:
- return await self.recover_password(recovery_code)
- except BadRequest as e:
- print(e.MESSAGE)
- except Exception as e:
- log.error(e, exc_info=True)
- raise
- else:
- self.password = None
- else:
- return await self.check_password(self.password)
- except BadRequest as e:
- print(e.MESSAGE)
- self.password = None
- else:
- break
-
- if isinstance(signed_in, User):
- return signed_in
-
- while True:
- first_name = await ainput("Enter first name: ")
- last_name = await ainput("Enter last name (empty to skip): ")
-
- try:
- signed_up = await self.sign_up(
- self.phone_number,
- sent_code.phone_code_hash,
- first_name,
- last_name
- )
- except BadRequest as e:
- print(e.MESSAGE)
- else:
- break
-
- if isinstance(signed_in, TermsOfService):
- print("\n" + signed_in.text + "\n")
- await self.accept_terms_of_service(signed_in.id)
-
- return signed_up
-
- async def log_out(self):
- """Log out from Telegram and delete the *\\*.session* file.
-
- When you log out, the current client is stopped and the storage session deleted.
- No more API calls can be made until you start the client and re-authorize again.
-
- Returns:
- ``bool``: On success, True is returned.
-
- Example:
- .. code-block:: python
-
- # Log out.
- app.log_out()
- """
- await self.send(functions.auth.LogOut())
- await self.stop()
- self.storage.delete()
-
- return True
-
- async def start(self):
- """Start the client.
-
- This method connects the client to Telegram and, in case of new sessions, automatically manages the full
- authorization process using an interactive prompt.
-
- Returns:
- :obj:`Client`: The started client itself.
-
- Raises:
- ConnectionError: In case you try to start an already started client.
-
- Example:
- .. code-block:: python
- :emphasize-lines: 4
-
- from pyrogram import Client
-
- app = Client("my_account")
- app.start()
-
- ... # Call API methods
-
- app.stop()
- """
- is_authorized = await self.connect()
-
- try:
- if not is_authorized:
- await self.authorize()
-
- if not self.storage.is_bot() and self.takeout:
- self.takeout_id = (await self.send(functions.account.InitTakeoutSession())).id
- log.warning("Takeout session {} initiated".format(self.takeout_id))
-
- await self.send(functions.updates.GetState())
- except (Exception, KeyboardInterrupt):
- await self.disconnect()
- raise
- else:
- await self.initialize()
- return self
-
- async def stop(self, block: bool = True):
- """Stop the Client.
-
- This method disconnects the client from Telegram and stops the underlying tasks.
-
- Parameters:
- block (``bool``, *optional*):
- Blocks the code execution until the client has been restarted. It is useful with ``block=False`` in case
- you want to stop the own client *within* an handler in order not to cause a deadlock.
- Defaults to True.
-
- Returns:
- :obj:`Client`: The stopped client itself.
-
- Raises:
- ConnectionError: In case you try to stop an already stopped client.
-
- Example:
- .. code-block:: python
- :emphasize-lines: 8
-
- from pyrogram import Client
-
- app = Client("my_account")
- app.start()
-
- ... # Call API methods
-
- app.stop()
- """
-
- async def do_it():
- await self.terminate()
- await self.disconnect()
-
- if block:
- await do_it()
- else:
- asyncio.ensure_future(do_it())
-
- return self
-
- async def restart(self, block: bool = True):
- """Restart the Client.
-
- This method will first call :meth:`~Client.stop` and then :meth:`~Client.start` in a row in order to restart
- a client using a single method.
-
- Parameters:
- block (``bool``, *optional*):
- Blocks the code execution until the client has been restarted. It is useful with ``block=False`` in case
- you want to restart the own client *within* an handler in order not to cause a deadlock.
- Defaults to True.
-
- Returns:
- :obj:`Client`: The restarted client itself.
-
- Raises:
- ConnectionError: In case you try to restart a stopped Client.
-
- Example:
- .. code-block:: python
- :emphasize-lines: 8
-
- from pyrogram import Client
-
- app = Client("my_account")
- app.start()
-
- ... # Call API methods
-
- app.restart()
-
- ... # Call other API methods
-
- app.stop()
- """
-
- async def do_it():
- await self.stop()
- await self.start()
-
- if block:
- await do_it()
- else:
- asyncio.ensure_future(do_it())
-
- return self
-
- @staticmethod
- async def idle(stop_signals: tuple = (SIGINT, SIGTERM, SIGABRT)):
- """Block the main script execution until a signal is received.
-
- This static method will run an infinite loop in order to block the main script execution and prevent it from
- exiting while having client(s) that are still running in the background.
-
- It is useful for event-driven application only, that are, applications which react upon incoming Telegram
- updates through handlers, rather than executing a set of methods sequentially.
-
- The way Pyrogram works, it will keep your handlers in a pool of worker threads, which are executed concurrently
- outside the main thread; calling idle() will ensure the client(s) will be kept alive by not letting the main
- script to end, until you decide to quit.
-
- Once a signal is received (e.g.: from CTRL+C) the inner infinite loop will break and your main script will
- continue. Don't forget to call :meth:`~Client.stop` for each running client before the script ends.
-
- Parameters:
- stop_signals (``tuple``, *optional*):
- Iterable containing signals the signal handler will listen to.
- Defaults to *(SIGINT, SIGTERM, SIGABRT)*.
-
- Example:
- .. code-block:: python
- :emphasize-lines: 13
-
- from pyrogram import Client
-
- app1 = Client("account1")
- app2 = Client("account2")
- app3 = Client("account3")
-
- ... # Set handlers up
-
- app1.start()
- app2.start()
- app3.start()
-
- Client.idle()
-
- app1.stop()
- app2.stop()
- app3.stop()
- """
-
- def signal_handler(_, __):
- logging.info("Stop signal received ({}). Exiting...".format(_))
- Client.is_idling = False
-
- for s in stop_signals:
- signal(s, signal_handler)
-
- Client.is_idling = True
-
- while Client.is_idling:
- await asyncio.sleep(1)
-
- def run(self, coroutine=None):
- """Start the client, idle the main script and finally stop the client.
-
- This is a convenience method that calls :meth:`~Client.start`, :meth:`~Client.idle` and :meth:`~Client.stop` in
- sequence. It makes running a client less verbose, but is not suitable in case you want to run more than one
- client in a single main script, since idle() will block after starting the own client.
-
- Raises:
- ConnectionError: In case you try to run an already started client.
-
- Example:
- .. code-block:: python
- :emphasize-lines: 7
-
- from pyrogram import Client
-
- app = Client("my_account")
-
- ... # Set handlers up
-
- app.run()
- """
- loop = asyncio.get_event_loop()
- run = loop.run_until_complete
-
- if coroutine is not None:
- run(coroutine)
- else:
- run(self.start())
- run(Client.idle())
- run(self.stop())
-
- loop.close()
-
- def add_handler(self, handler: Handler, group: int = 0):
- """Register an update handler.
-
- You can register multiple handlers, but at most one handler within a group will be used for a single update.
- To handle the same update more than once, register your handler using a different group id (lower group id
- == higher priority). This mechanism is explained in greater details at
- :doc:`More on Updates <../../topics/more-on-updates>`.
-
- Parameters:
- handler (``Handler``):
- The handler to be registered.
-
- group (``int``, *optional*):
- The group identifier, defaults to 0.
-
- Returns:
- ``tuple``: A tuple consisting of *(handler, group)*.
-
- Example:
- .. code-block:: python
- :emphasize-lines: 8
-
- from pyrogram import Client, MessageHandler
-
- def dump(client, message):
- print(message)
-
- app = Client("my_account")
-
- app.add_handler(MessageHandler(dump))
-
- app.run()
- """
- if isinstance(handler, DisconnectHandler):
- self.disconnect_handler = handler.callback
- else:
- self.dispatcher.add_handler(handler, group)
-
- return handler, group
-
- def remove_handler(self, handler: Handler, group: int = 0):
- """Remove a previously-registered update handler.
-
- Make sure to provide the right group where the handler was added in. You can use the return value of the
- :meth:`~Client.add_handler` method, a tuple of *(handler, group)*, and pass it directly.
-
- Parameters:
- handler (``Handler``):
- The handler to be removed.
-
- group (``int``, *optional*):
- The group identifier, defaults to 0.
-
- Example:
- .. code-block:: python
- :emphasize-lines: 11
-
- from pyrogram import Client, MessageHandler
-
- def dump(client, message):
- print(message)
-
- app = Client("my_account")
-
- handler = app.add_handler(MessageHandler(dump))
-
- # Starred expression to unpack (handler, group)
- app.remove_handler(*handler)
-
- app.run()
- """
- if isinstance(handler, DisconnectHandler):
- self.disconnect_handler = None
- else:
- self.dispatcher.remove_handler(handler, group)
-
- def stop_transmission(self):
- """Stop downloading or uploading a file.
-
- This method must be called inside a progress callback function in order to stop the transmission at the
- desired time. The progress callback is called every time a file chunk is uploaded/downloaded.
-
- Example:
- .. code-block:: python
- :emphasize-lines: 9
-
- from pyrogram import Client
-
- app = Client("my_account")
-
- # Example to stop transmission once the upload progress reaches 50%
- # Useless in practice, but shows how to stop on command
- def progress(current, total, client):
- if (current * 100 / total) > 50:
- client.stop_transmission()
-
- with app:
- app.send_document("me", "files.zip", progress=progress, progress_args=(app,))
- """
- raise Client.StopTransmission
-
- def export_session_string(self):
- """Export the current authorized session as a serialized string.
-
- Session strings are useful for storing in-memory authorized sessions in a portable, serialized string.
- More detailed information about session strings can be found at the dedicated page of
- :doc:`Storage Engines <../../topics/storage-engines>`.
-
- Returns:
- ``str``: The session serialized into a printable, url-safe string.
-
- Example:
- .. code-block:: python
- :emphasize-lines: 6
-
- from pyrogram import Client
-
- app = Client("my_account")
-
- with app:
- print(app.export_session_string())
- """
- return self.storage.export_session_string()
-
- @property
- def parse_mode(self):
- return self._parse_mode
-
- @parse_mode.setter
- def parse_mode(self, parse_mode: Union[str, None] = "combined"):
- if parse_mode not in self.PARSE_MODES:
- raise ValueError('parse_mode must be one of {} or None. Not "{}"'.format(
- ", ".join('"{}"'.format(m) for m in self.PARSE_MODES[:-1]),
- parse_mode
- ))
-
- self._parse_mode = parse_mode
-
- # TODO: redundant, remove in next major version
- def set_parse_mode(self, parse_mode: Union[str, None] = "combined"):
- """Set the parse mode to be used globally by the client.
-
- When setting the parse mode with this method, all other methods having a *parse_mode* parameter will follow the
- global value by default. The default value *"combined"* enables both Markdown and HTML styles to be used and
- combined together.
-
- Parameters:
- parse_mode (``str``):
- The new parse mode, can be any of: *"combined"*, for the default combined mode. *"markdown"* or *"md"*
- to force Markdown-only styles. *"html"* to force HTML-only styles. *None* to disable the parser
- completely.
-
- Raises:
- ValueError: In case the provided *parse_mode* is not a valid parse mode.
-
- Example:
- .. code-block:: python
- :emphasize-lines: 10,14,18,22
-
- from pyrogram import Client
-
- app = Client("my_account")
-
- with app:
- # Default combined mode: Markdown + HTML
- app.send_message("haskell", "1. **markdown** and html")
-
- # Force Markdown-only, HTML is disabled
- app.set_parse_mode("markdown")
- app.send_message("haskell", "2. **markdown** and html")
-
- # Force HTML-only, Markdown is disabled
- app.set_parse_mode("html")
- app.send_message("haskell", "3. **markdown** and html")
-
- # Disable the parser completely
- app.set_parse_mode(None)
- app.send_message("haskell", "4. **markdown** and html")
-
- # Bring back the default combined mode
- app.set_parse_mode()
- app.send_message("haskell", "5. **markdown** and html")
- """
-
- self.parse_mode = parse_mode
-
- def fetch_peers(self, peers: List[Union[types.User, types.Chat, types.Channel]]) -> bool:
- is_min = False
- parsed_peers = []
-
- for peer in peers:
- if getattr(peer, "min", False):
- is_min = True
- continue
-
- username = None
- phone_number = None
-
- if isinstance(peer, types.User):
- peer_id = peer.id
- access_hash = peer.access_hash
- username = (peer.username or "").lower() or None
- phone_number = peer.phone
- peer_type = "bot" if peer.bot else "user"
- elif isinstance(peer, (types.Chat, types.ChatForbidden)):
- peer_id = -peer.id
- access_hash = 0
- peer_type = "group"
- elif isinstance(peer, (types.Channel, types.ChannelForbidden)):
- peer_id = utils.get_channel_id(peer.id)
- access_hash = peer.access_hash
- username = (getattr(peer, "username", None) or "").lower() or None
- peer_type = "channel" if peer.broadcast else "supergroup"
- else:
- continue
-
- parsed_peers.append((peer_id, access_hash, peer_type, username, phone_number))
-
- self.storage.update_peers(parsed_peers)
-
- return is_min
-
- async def download_worker(self):
- while True:
- packet = await self.download_queue.get()
-
- if packet is None:
- break
-
- temp_file_path = ""
- final_file_path = ""
-
- try:
- data, directory, file_name, done, progress, progress_args, path = packet
-
- temp_file_path = await self.get_file(
- media_type=data.media_type,
- dc_id=data.dc_id,
- document_id=data.document_id,
- access_hash=data.access_hash,
- thumb_size=data.thumb_size,
- peer_id=data.peer_id,
- peer_type=data.peer_type,
- peer_access_hash=data.peer_access_hash,
- volume_id=data.volume_id,
- local_id=data.local_id,
- file_ref=data.file_ref,
- file_size=data.file_size,
- is_big=data.is_big,
- progress=progress,
- progress_args=progress_args
- )
-
- if temp_file_path:
- final_file_path = os.path.abspath(re.sub("\\\\", "/", os.path.join(directory, file_name)))
- os.makedirs(directory, exist_ok=True)
- shutil.move(temp_file_path, final_file_path)
- except Exception as e:
- log.error(e, exc_info=True)
-
- try:
- os.remove(temp_file_path)
- except OSError:
- pass
- else:
- # TODO: "" or None for faulty download, which is better?
- # os.path methods return "" in case something does not exist, I prefer this.
- # For now let's keep None
- path[0] = final_file_path or None
- finally:
- done.set()
-
- async def updates_worker(self):
- while True:
- updates = await self.updates_queue.get()
-
- if updates is None:
- break
-
- try:
- if isinstance(updates, (types.Update, types.UpdatesCombined)):
- is_min = self.fetch_peers(updates.users) or self.fetch_peers(updates.chats)
-
- users = {u.id: u for u in updates.users}
- chats = {c.id: c for c in updates.chats}
-
- for update in updates.updates:
- channel_id = getattr(
- getattr(
- getattr(
- update, "message", None
- ), "to_id", None
- ), "channel_id", None
- ) or getattr(update, "channel_id", None)
-
- pts = getattr(update, "pts", None)
- pts_count = getattr(update, "pts_count", None)
-
- if isinstance(update, types.UpdateChannelTooLong):
- log.warning(update)
-
- if isinstance(update, types.UpdateNewChannelMessage) and is_min:
- message = update.message
-
- if not isinstance(message, types.MessageEmpty):
- try:
- diff = await self.send(
- functions.updates.GetChannelDifference(
- channel=await self.resolve_peer(utils.get_channel_id(channel_id)),
- filter=types.ChannelMessagesFilter(
- ranges=[types.MessageRange(
- min_id=update.message.id,
- max_id=update.message.id
- )]
- ),
- pts=pts - pts_count,
- limit=pts
- )
- )
- except ChannelPrivate:
- pass
- else:
- if not isinstance(diff, types.updates.ChannelDifferenceEmpty):
- users.update({u.id: u for u in diff.users})
- chats.update({c.id: c for c in diff.chats})
-
- self.dispatcher.updates_queue.put_nowait((update, users, chats))
- elif isinstance(updates, (types.UpdateShortMessage, types.UpdateShortChatMessage)):
- diff = await self.send(
- functions.updates.GetDifference(
- pts=updates.pts - updates.pts_count,
- date=updates.date,
- qts=-1
- )
- )
-
- if diff.new_messages:
- self.dispatcher.updates_queue.put_nowait((
- types.UpdateNewMessage(
- message=diff.new_messages[0],
- pts=updates.pts,
- pts_count=updates.pts_count
- ),
- {u.id: u for u in diff.users},
- {c.id: c for c in diff.chats}
- ))
- else:
- self.dispatcher.updates_queue.put_nowait((diff.other_updates[0], {}, {}))
- elif isinstance(updates, types.UpdateShort):
- self.dispatcher.updates_queue.put_nowait((updates.update, {}, {}))
- elif isinstance(updates, types.UpdatesTooLong):
- log.info(updates)
- except Exception as e:
- log.error(e, exc_info=True)
-
- async def send(self, data: TLObject, retries: int = Session.MAX_RETRIES, timeout: float = Session.WAIT_TIMEOUT):
- """Send raw Telegram queries.
-
- This method makes it possible to manually call every single Telegram API method in a low-level manner.
- Available functions are listed in the :obj:`functions ` package and may accept compound
- data types from :obj:`types ` as well as bare types such as ``int``, ``str``, etc...
-
- .. note::
-
- This is a utility method intended to be used **only** when working with raw
- :obj:`functions ` (i.e: a Telegram API method you wish to use which is not
- available yet in the Client class as an easy-to-use method).
-
- Parameters:
- data (``RawFunction``):
- The API Schema function filled with proper arguments.
-
- retries (``int``):
- Number of retries.
-
- timeout (``float``):
- Timeout in seconds.
-
- Returns:
- ``RawType``: The raw type response generated by the query.
-
- Raises:
- RPCError: In case of a Telegram RPC error.
- """
- if not self.is_connected:
- raise ConnectionError("Client has not been started yet")
-
- if self.no_updates:
- data = functions.InvokeWithoutUpdates(query=data)
-
- if self.takeout_id:
- data = functions.InvokeWithTakeout(takeout_id=self.takeout_id, query=data)
-
- r = await self.session.send(data, retries, timeout, self.sleep_threshold)
-
- self.fetch_peers(getattr(r, "users", []))
- self.fetch_peers(getattr(r, "chats", []))
-
- return r
-
- def load_config(self):
- parser = ConfigParser()
- parser.read(str(self.config_file))
-
- if self.bot_token:
- pass
- else:
- self.bot_token = parser.get("pyrogram", "bot_token", fallback=None)
-
- if self.api_id and self.api_hash:
- pass
- else:
- if parser.has_section("pyrogram"):
- self.api_id = parser.getint("pyrogram", "api_id")
- self.api_hash = parser.get("pyrogram", "api_hash")
- else:
- raise AttributeError("No API Key found. More info: https://docs.pyrogram.org/intro/setup")
-
- for option in ["app_version", "device_model", "system_version", "lang_code"]:
- if getattr(self, option):
- pass
- else:
- if parser.has_section("pyrogram"):
- setattr(self, option, parser.get(
- "pyrogram",
- option,
- fallback=getattr(Client, option.upper())
- ))
- else:
- setattr(self, option, getattr(Client, option.upper()))
-
- if self._proxy:
- self._proxy["enabled"] = bool(self._proxy.get("enabled", True))
- else:
- self._proxy = {}
-
- if parser.has_section("proxy"):
- self._proxy["enabled"] = parser.getboolean("proxy", "enabled", fallback=True)
- self._proxy["hostname"] = parser.get("proxy", "hostname")
- self._proxy["port"] = parser.getint("proxy", "port")
- self._proxy["username"] = parser.get("proxy", "username", fallback=None) or None
- self._proxy["password"] = parser.get("proxy", "password", fallback=None) or None
-
- if self.plugins:
- self.plugins = {
- "enabled": bool(self.plugins.get("enabled", True)),
- "root": self.plugins.get("root", None),
- "include": self.plugins.get("include", []),
- "exclude": self.plugins.get("exclude", [])
- }
- else:
- try:
- section = parser["plugins"]
-
- self.plugins = {
- "enabled": section.getboolean("enabled", True),
- "root": section.get("root", None),
- "include": section.get("include", []),
- "exclude": section.get("exclude", [])
- }
-
- include = self.plugins["include"]
- exclude = self.plugins["exclude"]
-
- if include:
- self.plugins["include"] = include.strip().split("\n")
-
- if exclude:
- self.plugins["exclude"] = exclude.strip().split("\n")
-
- except KeyError:
- self.plugins = None
-
- async def load_session(self):
- self.storage.open()
-
- session_empty = any([
- self.storage.test_mode() is None,
- self.storage.auth_key() is None,
- self.storage.user_id() is None,
- self.storage.is_bot() is None
- ])
-
- if session_empty:
- self.storage.dc_id(2)
- self.storage.date(0)
-
- self.storage.test_mode(self.test_mode)
- self.storage.auth_key(await Auth(self, self.storage.dc_id()).create())
- self.storage.user_id(None)
- self.storage.is_bot(None)
-
- def load_plugins(self):
- if self.plugins:
- plugins = self.plugins.copy()
-
- for option in ["include", "exclude"]:
- if plugins[option]:
- plugins[option] = [
- (i.split()[0], i.split()[1:] or None)
- for i in self.plugins[option]
- ]
- else:
- return
-
- if plugins.get("enabled", False):
- root = plugins["root"]
- include = plugins["include"]
- exclude = plugins["exclude"]
-
- count = 0
-
- if not include:
- for path in sorted(Path(root.replace(".", "/")).rglob("*.py")):
- module_path = '.'.join(path.parent.parts + (path.stem,))
- module = import_module(module_path)
-
- for name in vars(module).keys():
- # noinspection PyBroadException
- try:
- handler, group = getattr(module, name).handler
-
- if isinstance(handler, Handler) and isinstance(group, int):
- self.add_handler(handler, group)
-
- log.info('[{}] [LOAD] {}("{}") in group {} from "{}"'.format(
- self.session_name, type(handler).__name__, name, group, module_path))
-
- count += 1
- except Exception:
- pass
- else:
- for path, handlers in include:
- module_path = root + "." + path
- warn_non_existent_functions = True
-
- try:
- module = import_module(module_path)
- except ImportError:
- log.warning('[{}] [LOAD] Ignoring non-existent module "{}"'.format(
- self.session_name, module_path))
- continue
-
- if "__path__" in dir(module):
- log.warning('[{}] [LOAD] Ignoring namespace "{}"'.format(
- self.session_name, module_path))
- continue
-
- if handlers is None:
- handlers = vars(module).keys()
- warn_non_existent_functions = False
-
- for name in handlers:
- # noinspection PyBroadException
- try:
- handler, group = getattr(module, name).handler
-
- if isinstance(handler, Handler) and isinstance(group, int):
- self.add_handler(handler, group)
-
- log.info('[{}] [LOAD] {}("{}") in group {} from "{}"'.format(
- self.session_name, type(handler).__name__, name, group, module_path))
-
- count += 1
- except Exception:
- if warn_non_existent_functions:
- log.warning('[{}] [LOAD] Ignoring non-existent function "{}" from "{}"'.format(
- self.session_name, name, module_path))
-
- if exclude:
- for path, handlers in exclude:
- module_path = root + "." + path
- warn_non_existent_functions = True
-
- try:
- module = import_module(module_path)
- except ImportError:
- log.warning('[{}] [UNLOAD] Ignoring non-existent module "{}"'.format(
- self.session_name, module_path))
- continue
-
- if "__path__" in dir(module):
- log.warning('[{}] [UNLOAD] Ignoring namespace "{}"'.format(
- self.session_name, module_path))
- continue
-
- if handlers is None:
- handlers = vars(module).keys()
- warn_non_existent_functions = False
-
- for name in handlers:
- # noinspection PyBroadException
- try:
- handler, group = getattr(module, name).handler
-
- if isinstance(handler, Handler) and isinstance(group, int):
- self.remove_handler(handler, group)
-
- log.info('[{}] [UNLOAD] {}("{}") from group {} in "{}"'.format(
- self.session_name, type(handler).__name__, name, group, module_path))
-
- count -= 1
- except Exception:
- if warn_non_existent_functions:
- log.warning('[{}] [UNLOAD] Ignoring non-existent function "{}" from "{}"'.format(
- self.session_name, name, module_path))
-
- if count > 0:
- log.info('[{}] Successfully loaded {} plugin{} from "{}"'.format(
- self.session_name, count, "s" if count > 1 else "", root))
- else:
- log.warning('[{}] No plugin loaded from "{}"'.format(
- self.session_name, root))
-
- async def resolve_peer(self, peer_id: Union[int, str]):
- """Get the InputPeer of a known peer id.
- Useful whenever an InputPeer type is required.
-
- .. note::
-
- This is a utility method intended to be used **only** when working with raw
- :obj:`functions ` (i.e: a Telegram API method you wish to use which is not
- available yet in the Client class as an easy-to-use method).
-
- Parameters:
- peer_id (``int`` | ``str``):
- The peer id you want to extract the InputPeer from.
- Can be a direct id (int), a username (str) or a phone number (str).
-
- Returns:
- ``InputPeer``: On success, the resolved peer id is returned in form of an InputPeer object.
-
- Raises:
- KeyError: In case the peer doesn't exist in the internal database.
- """
- if not self.is_connected:
- raise ConnectionError("Client has not been started yet")
-
- try:
- return self.storage.get_peer_by_id(peer_id)
- except KeyError:
- if isinstance(peer_id, str):
- if peer_id in ("self", "me"):
- return types.InputPeerSelf()
-
- peer_id = re.sub(r"[@+\s]", "", peer_id.lower())
-
- try:
- int(peer_id)
- except ValueError:
- try:
- return self.storage.get_peer_by_username(peer_id)
- except KeyError:
- await self.send(
- functions.contacts.ResolveUsername(
- username=peer_id
- )
- )
-
- return self.storage.get_peer_by_username(peer_id)
- else:
- try:
- return self.storage.get_peer_by_phone_number(peer_id)
- except KeyError:
- raise PeerIdInvalid
-
- peer_type = utils.get_peer_type(peer_id)
-
- if peer_type == "user":
- self.fetch_peers(
- await self.send(
- functions.users.GetUsers(
- id=[
- types.InputUser(
- user_id=peer_id,
- access_hash=0
- )
- ]
- )
- )
- )
- elif peer_type == "chat":
- await self.send(
- functions.messages.GetChats(
- id=[-peer_id]
- )
- )
- else:
- await self.send(
- functions.channels.GetChannels(
- id=[
- types.InputChannel(
- channel_id=utils.get_channel_id(peer_id),
- access_hash=0
- )
- ]
- )
- )
-
- try:
- return self.storage.get_peer_by_id(peer_id)
- except KeyError:
- raise PeerIdInvalid
-
- async def save_file(
- self,
- path: Union[str, BinaryIO],
- file_id: int = None,
- file_part: int = 0,
- progress: callable = None,
- progress_args: tuple = ()
- ):
- """Upload a file onto Telegram servers, without actually sending the message to anyone.
- Useful whenever an InputFile type is required.
-
- .. note::
-
- This is a utility method intended to be used **only** when working with raw
- :obj:`functions ` (i.e: a Telegram API method you wish to use which is not
- available yet in the Client class as an easy-to-use method).
-
- Parameters:
- path (``str``):
- The path of the file you want to upload that exists on your local machine.
-
- file_id (``int``, *optional*):
- In case a file part expired, pass the file_id and the file_part to retry uploading that specific chunk.
-
- file_part (``int``, *optional*):
- In case a file part expired, pass the file_id and the file_part to retry uploading that specific chunk.
-
- progress (``callable``, *optional*):
- Pass a callback function to view the file transmission progress.
- The function must take *(current, total)* as positional arguments (look at Other Parameters below for a
- detailed description) and will be called back each time a new file chunk has been successfully
- transmitted.
-
- progress_args (``tuple``, *optional*):
- Extra custom arguments for the progress callback function.
- You can pass anything you need to be available in the progress callback scope; for example, a Message
- object or a Client instance in order to edit the message with the updated progress status.
-
- Other Parameters:
- current (``int``):
- The amount of bytes transmitted so far.
-
- total (``int``):
- The total size of the file.
-
- *args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
-
- Returns:
- ``InputFile``: On success, the uploaded file is returned in form of an InputFile object.
-
- Raises:
- RPCError: In case of a Telegram RPC error.
- """
- if path is None:
- return None
-
- async def worker(session):
- while True:
- data = await queue.get()
-
- if data is None:
- return
-
- try:
- await asyncio.ensure_future(session.send(data))
- except Exception as e:
- logging.error(e)
-
- part_size = 512 * 1024
-
- if isinstance(path, (str, PurePath)):
- fp = open(path, "rb")
- elif isinstance(path, io.IOBase):
- fp = path
- else:
- raise ValueError("Invalid file. Expected a file path as string or a binary (not text) file pointer")
-
- file_name = fp.name
-
- fp.seek(0, os.SEEK_END)
- file_size = fp.tell()
- fp.seek(0)
-
- if file_size == 0:
- raise ValueError("File size equals to 0 B")
-
- if file_size > 2000 * 1024 * 1024:
- raise ValueError("Telegram doesn't support uploading files bigger than 2000 MiB")
-
- file_total_parts = int(math.ceil(file_size / part_size))
- is_big = file_size > 10 * 1024 * 1024
- pool_size = 3 if is_big else 1
- workers_count = 4 if is_big else 1
- is_missing_part = file_id is not None
- file_id = file_id or self.rnd_id()
- md5_sum = md5() if not is_big and not is_missing_part else None
- pool = [Session(self, self.storage.dc_id(), self.storage.auth_key(), is_media=True) for _ in range(pool_size)]
- workers = [asyncio.ensure_future(worker(session)) for session in pool for _ in range(workers_count)]
- queue = asyncio.Queue(16)
-
- try:
- for session in pool:
- await session.start()
-
- with fp:
- fp.seek(part_size * file_part)
-
- while True:
- chunk = fp.read(part_size)
-
- if not chunk:
- if not is_big:
- md5_sum = "".join([hex(i)[2:].zfill(2) for i in md5_sum.digest()])
- break
-
- if is_big:
- rpc = functions.upload.SaveBigFilePart(
- file_id=file_id,
- file_part=file_part,
- file_total_parts=file_total_parts,
- bytes=chunk
- )
- else:
- rpc = functions.upload.SaveFilePart(
- file_id=file_id,
- file_part=file_part,
- bytes=chunk
- )
-
- await queue.put(rpc)
-
- if is_missing_part:
- return
-
- if not is_big:
- md5_sum.update(chunk)
-
- file_part += 1
-
- if progress:
- await progress(min(file_part * part_size, file_size), file_size, *progress_args)
- except Client.StopTransmission:
- raise
- except Exception as e:
- log.error(e, exc_info=True)
- else:
- if is_big:
- return types.InputFileBig(
- id=file_id,
- parts=file_total_parts,
- name=file_name,
-
- )
- else:
- return types.InputFile(
- id=file_id,
- parts=file_total_parts,
- name=file_name,
- md5_checksum=md5_sum
- )
- finally:
- for _ in workers:
- await queue.put(None)
-
- await asyncio.gather(*workers)
-
- for session in pool:
- await session.stop()
-
- async def get_file(
- self,
- media_type: int,
- dc_id: int,
- document_id: int,
- access_hash: int,
- thumb_size: str,
- peer_id: int,
- peer_type: str,
- peer_access_hash: int,
- volume_id: int,
- local_id: int,
- file_ref: str,
- file_size: int,
- is_big: bool,
- progress: callable,
- progress_args: tuple = ()
- ) -> str:
- async with self.media_sessions_lock:
- session = self.media_sessions.get(dc_id, None)
-
- if session is None:
- if dc_id != self.storage.dc_id():
- session = Session(self, dc_id, await Auth(self, dc_id).create(), is_media=True)
- await session.start()
-
- for _ in range(3):
- exported_auth = await self.send(
- functions.auth.ExportAuthorization(
- dc_id=dc_id
- )
- )
-
- try:
- await session.send(
- functions.auth.ImportAuthorization(
- id=exported_auth.id,
- bytes=exported_auth.bytes
- )
- )
- except AuthBytesInvalid:
- continue
- else:
- break
- else:
- await session.stop()
- raise AuthBytesInvalid
- else:
- session = Session(self, dc_id, self.storage.auth_key(), is_media=True)
- await session.start()
-
- self.media_sessions[dc_id] = session
-
- file_ref = utils.decode_file_ref(file_ref)
-
- if media_type == 1:
- if peer_type == "user":
- peer = types.InputPeerUser(
- user_id=peer_id,
- access_hash=peer_access_hash
- )
- elif peer_type == "chat":
- peer = types.InputPeerChat(
- chat_id=peer_id
- )
- else:
- peer = types.InputPeerChannel(
- channel_id=peer_id,
- access_hash=peer_access_hash
- )
-
- location = types.InputPeerPhotoFileLocation(
- peer=peer,
- volume_id=volume_id,
- local_id=local_id,
- big=is_big or None
- )
- elif media_type in (0, 2):
- location = types.InputPhotoFileLocation(
- id=document_id,
- access_hash=access_hash,
- file_reference=file_ref,
- thumb_size=thumb_size
- )
- elif media_type == 14:
- location = types.InputDocumentFileLocation(
- id=document_id,
- access_hash=access_hash,
- file_reference=file_ref,
- thumb_size=thumb_size
- )
- else:
- location = types.InputDocumentFileLocation(
- id=document_id,
- access_hash=access_hash,
- file_reference=file_ref,
- thumb_size=""
- )
-
- limit = 1024 * 1024
- offset = 0
- file_name = ""
-
- try:
- r = await session.send(
- functions.upload.GetFile(
- location=location,
- offset=offset,
- limit=limit
- )
- )
-
- if isinstance(r, types.upload.File):
- with tempfile.NamedTemporaryFile("wb", delete=False) as f:
- file_name = f.name
-
- while True:
- chunk = r.bytes
-
- if not chunk:
- break
-
- f.write(chunk)
-
- offset += limit
-
- if progress:
- await progress(
- min(offset, file_size)
- if file_size != 0
- else offset,
- file_size,
- *progress_args
- )
-
- r = await session.send(
- functions.upload.GetFile(
- location=location,
- offset=offset,
- limit=limit
- )
- )
-
- elif isinstance(r, types.upload.FileCdnRedirect):
- async with self.media_sessions_lock:
- cdn_session = self.media_sessions.get(r.dc_id, None)
-
- if cdn_session is None:
- cdn_session = Session(
- self,
- r.dc_id,
- await Auth(self, r.dc_id).create(), is_media=True, is_cdn=True)
-
- await cdn_session.start()
-
- self.media_sessions[r.dc_id] = cdn_session
-
- try:
- with tempfile.NamedTemporaryFile("wb", delete=False) as f:
- file_name = f.name
-
- while True:
- r2 = await cdn_session.send(
- functions.upload.GetCdnFile(
- file_token=r.file_token,
- offset=offset,
- limit=limit
- )
- )
-
- if isinstance(r2, types.upload.CdnFileReuploadNeeded):
- try:
- await session.send(
- functions.upload.ReuploadCdnFile(
- file_token=r.file_token,
- request_token=r2.request_token
- )
- )
- except VolumeLocNotFound:
- break
- else:
- continue
-
- chunk = r2.bytes
-
- # https://core.telegram.org/cdn#decrypting-files
- decrypted_chunk = AES.ctr256_decrypt(
- chunk,
- r.encryption_key,
- bytearray(
- r.encryption_iv[:-4]
- + (offset // 16).to_bytes(4, "big")
- )
- )
-
- hashes = await session.send(
- functions.upload.GetCdnFileHashes(
- file_token=r.file_token,
- offset=offset
- )
- )
-
- # https://core.telegram.org/cdn#verifying-files
- for i, h in enumerate(hashes):
- cdn_chunk = decrypted_chunk[h.limit * i: h.limit * (i + 1)]
- assert h.hash == sha256(cdn_chunk).digest(), "Invalid CDN hash part {}".format(i)
-
- f.write(decrypted_chunk)
-
- offset += limit
-
- if progress:
- await progress(
- min(offset, file_size)
- if file_size != 0
- else offset,
- file_size,
- *progress_args
- )
-
- if len(chunk) < limit:
- break
- except Exception as e:
- raise e
- except Exception as e:
- if not isinstance(e, Client.StopTransmission):
- log.error(e, exc_info=True)
-
- try:
- os.remove(file_name)
- except OSError:
- pass
-
- return ""
- else:
- return file_name
-
- def guess_mime_type(self, filename: str):
- extension = os.path.splitext(filename)[1]
- return self.extensions_to_mime_types.get(extension)
-
- def guess_extension(self, mime_type: str):
- extensions = self.mime_types_to_extensions.get(mime_type)
-
- if extensions:
- return extensions.split(" ")[0]
diff --git a/pyrogram/client/ext/__init__.py b/pyrogram/client/ext/__init__.py
deleted file mode 100644
index e363d3d4db..0000000000
--- a/pyrogram/client/ext/__init__.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Pyrogram - Telegram MTProto API Client Library for Python
-# Copyright (C) 2017-2020 Dan
-#
-# This file is part of Pyrogram.
-#
-# Pyrogram is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Pyrogram is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with Pyrogram. If not, see .
-
-from .base_client import BaseClient
-from .dispatcher import Dispatcher
-from .emoji import Emoji
-from .file_data import FileData
-from .link import Link
-from .syncer import Syncer
diff --git a/pyrogram/client/ext/emoji.py b/pyrogram/client/ext/emoji.py
deleted file mode 100644
index 97bfc52961..0000000000
--- a/pyrogram/client/ext/emoji.py
+++ /dev/null
@@ -1,7850 +0,0 @@
-# Pyrogram - Telegram MTProto API Client Library for Python
-# Copyright (C) 2017-2020 Dan
-#
-# This file is part of Pyrogram.
-#
-# Pyrogram is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Pyrogram is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with Pyrogram. If not, see .
-
-class Emoji:
- HELMET_WITH_WHITE_CROSS_TYPE_1_2 = "\u26d1\U0001f3fb"
- HELMET_WITH_WHITE_CROSS_TYPE_3 = "\u26d1\U0001f3fc"
- HELMET_WITH_WHITE_CROSS_TYPE_4 = "\u26d1\U0001f3fd"
- HELMET_WITH_WHITE_CROSS_TYPE_5 = "\u26d1\U0001f3fe"
- HELMET_WITH_WHITE_CROSS_TYPE_6 = "\u26d1\U0001f3ff"
- KISS_TYPE_1_2 = "\U0001f48f\U0001f3fb"
- KISS_TYPE_3 = "\U0001f48f\U0001f3fc"
- KISS_TYPE_4 = "\U0001f48f\U0001f3fd"
- KISS_TYPE_5 = "\U0001f48f\U0001f3fe"
- KISS_TYPE_6 = "\U0001f48f\U0001f3ff"
- COUPLE_WITH_HEART_TYPE_1_2 = "\U0001f491\U0001f3fb"
- COUPLE_WITH_HEART_TYPE_3 = "\U0001f491\U0001f3fc"
- COUPLE_WITH_HEART_TYPE_4 = "\U0001f491\U0001f3fd"
- COUPLE_WITH_HEART_TYPE_5 = "\U0001f491\U0001f3fe"
- COUPLE_WITH_HEART_TYPE_6 = "\U0001f491\U0001f3ff"
- SKIER_TYPE_1_2 = "\u26f7\U0001f3fb"
- SKIER_TYPE_3 = "\u26f7\U0001f3fc"
- SKIER_TYPE_4 = "\u26f7\U0001f3fd"
- SKIER_TYPE_5 = "\u26f7\U0001f3fe"
- SKIER_TYPE_6 = "\u26f7\U0001f3ff"
- GRINNING_FACE = "\U0001f600"
- BEAMING_FACE_WITH_SMILING_EYES = "\U0001f601"
- FACE_WITH_TEARS_OF_JOY = "\U0001f602"
- ROLLING_ON_THE_FLOOR_LAUGHING = "\U0001f923"
- GRINNING_FACE_WITH_BIG_EYES = "\U0001f603"
- GRINNING_FACE_WITH_SMILING_EYES = "\U0001f604"
- GRINNING_FACE_WITH_SWEAT = "\U0001f605"
- GRINNING_SQUINTING_FACE = "\U0001f606"
- WINKING_FACE = "\U0001f609"
- SMILING_FACE_WITH_SMILING_EYES = "\U0001f60a"
- FACE_SAVORING_FOOD = "\U0001f60b"
- SMILING_FACE_WITH_SUNGLASSES = "\U0001f60e"
- SMILING_FACE_WITH_HEART_EYES = "\U0001f60d"
- FACE_BLOWING_A_KISS = "\U0001f618"
- SMILING_FACE_WITH_3_HEARTS = "\U0001f970"
- KISSING_FACE = "\U0001f617"
- KISSING_FACE_WITH_SMILING_EYES = "\U0001f619"
- KISSING_FACE_WITH_CLOSED_EYES = "\U0001f61a"
- SMILING_FACE = "\u263a\ufe0f"
- SLIGHTLY_SMILING_FACE = "\U0001f642"
- HUGGING_FACE = "\U0001f917"
- STAR_STRUCK = "\U0001f929"
- THINKING_FACE = "\U0001f914"
- FACE_WITH_RAISED_EYEBROW = "\U0001f928"
- NEUTRAL_FACE = "\U0001f610"
- EXPRESSIONLESS_FACE = "\U0001f611"
- FACE_WITHOUT_MOUTH = "\U0001f636"
- FACE_WITH_ROLLING_EYES = "\U0001f644"
- SMIRKING_FACE = "\U0001f60f"
- PERSEVERING_FACE = "\U0001f623"
- SAD_BUT_RELIEVED_FACE = "\U0001f625"
- FACE_WITH_OPEN_MOUTH = "\U0001f62e"
- ZIPPER_MOUTH_FACE = "\U0001f910"
- HUSHED_FACE = "\U0001f62f"
- SLEEPY_FACE = "\U0001f62a"
- TIRED_FACE = "\U0001f62b"
- SLEEPING_FACE = "\U0001f634"
- RELIEVED_FACE = "\U0001f60c"
- FACE_WITH_TONGUE = "\U0001f61b"
- WINKING_FACE_WITH_TONGUE = "\U0001f61c"
- SQUINTING_FACE_WITH_TONGUE = "\U0001f61d"
- DROOLING_FACE = "\U0001f924"
- UNAMUSED_FACE = "\U0001f612"
- DOWNCAST_FACE_WITH_SWEAT = "\U0001f613"
- PENSIVE_FACE = "\U0001f614"
- CONFUSED_FACE = "\U0001f615"
- UPSIDE_DOWN_FACE = "\U0001f643"
- MONEY_MOUTH_FACE = "\U0001f911"
- ASTONISHED_FACE = "\U0001f632"
- FROWNING_FACE = "\u2639\ufe0f"
- SLIGHTLY_FROWNING_FACE = "\U0001f641"
- CONFOUNDED_FACE = "\U0001f616"
- DISAPPOINTED_FACE = "\U0001f61e"
- WORRIED_FACE = "\U0001f61f"
- FACE_WITH_STEAM_FROM_NOSE = "\U0001f624"
- CRYING_FACE = "\U0001f622"
- LOUDLY_CRYING_FACE = "\U0001f62d"
- FROWNING_FACE_WITH_OPEN_MOUTH = "\U0001f626"
- ANGUISHED_FACE = "\U0001f627"
- FEARFUL_FACE = "\U0001f628"
- WEARY_FACE = "\U0001f629"
- EXPLODING_HEAD = "\U0001f92f"
- GRIMACING_FACE = "\U0001f62c"
- ANXIOUS_FACE_WITH_SWEAT = "\U0001f630"
- FACE_SCREAMING_IN_FEAR = "\U0001f631"
- HOT_FACE = "\U0001f975"
- COLD_FACE = "\U0001f976"
- FLUSHED_FACE = "\U0001f633"
- ZANY_FACE = "\U0001f92a"
- DIZZY_FACE = "\U0001f635"
- POUTING_FACE = "\U0001f621"
- ANGRY_FACE = "\U0001f620"
- FACE_WITH_SYMBOLS_ON_MOUTH = "\U0001f92c"
- FACE_WITH_MEDICAL_MASK = "\U0001f637"
- FACE_WITH_THERMOMETER = "\U0001f912"
- FACE_WITH_HEAD_BANDAGE = "\U0001f915"
- NAUSEATED_FACE = "\U0001f922"
- FACE_VOMITING = "\U0001f92e"
- SNEEZING_FACE = "\U0001f927"
- SMILING_FACE_WITH_HALO = "\U0001f607"
- COWBOY_HAT_FACE = "\U0001f920"
- CLOWN_FACE = "\U0001f921"
- PARTYING_FACE = "\U0001f973"
- WOOZY_FACE = "\U0001f974"
- PLEADING_FACE = "\U0001f97a"
- LYING_FACE = "\U0001f925"
- SHUSHING_FACE = "\U0001f92b"
- FACE_WITH_HAND_OVER_MOUTH = "\U0001f92d"
- FACE_WITH_MONOCLE = "\U0001f9d0"
- NERD_FACE = "\U0001f913"
- SMILING_FACE_WITH_HORNS = "\U0001f608"
- ANGRY_FACE_WITH_HORNS = "\U0001f47f"
- OGRE = "\U0001f479"
- GOBLIN = "\U0001f47a"
- SKULL = "\U0001f480"
- SKULL_AND_CROSSBONES = "\u2620\ufe0f"
- GHOST = "\U0001f47b"
- ALIEN = "\U0001f47d"
- ALIEN_MONSTER = "\U0001f47e"
- ROBOT_FACE = "\U0001f916"
- PILE_OF_POO = "\U0001f4a9"
- GRINNING_CAT_FACE = "\U0001f63a"
- GRINNING_CAT_FACE_WITH_SMILING_EYES = "\U0001f638"
- CAT_FACE_WITH_TEARS_OF_JOY = "\U0001f639"
- SMILING_CAT_FACE_WITH_HEART_EYES = "\U0001f63b"
- CAT_FACE_WITH_WRY_SMILE = "\U0001f63c"
- KISSING_CAT_FACE = "\U0001f63d"
- WEARY_CAT_FACE = "\U0001f640"
- CRYING_CAT_FACE = "\U0001f63f"
- POUTING_CAT_FACE = "\U0001f63e"
- SEE_NO_EVIL_MONKEY = "\U0001f648"
- HEAR_NO_EVIL_MONKEY = "\U0001f649"
- SPEAK_NO_EVIL_MONKEY = "\U0001f64a"
- LIGHT_SKIN_TONE = "\U0001f3fb"
- MEDIUM_LIGHT_SKIN_TONE = "\U0001f3fc"
- MEDIUM_SKIN_TONE = "\U0001f3fd"
- MEDIUM_DARK_SKIN_TONE = "\U0001f3fe"
- DARK_SKIN_TONE = "\U0001f3ff"
- BABY = "\U0001f476"
- BABY_LIGHT_SKIN_TONE = "\U0001f476\U0001f3fb"
- BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f476\U0001f3fc"
- BABY_MEDIUM_SKIN_TONE = "\U0001f476\U0001f3fd"
- BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f476\U0001f3fe"
- BABY_DARK_SKIN_TONE = "\U0001f476\U0001f3ff"
- CHILD = "\U0001f9d2"
- CHILD_LIGHT_SKIN_TONE = "\U0001f9d2\U0001f3fb"
- CHILD_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d2\U0001f3fc"
- CHILD_MEDIUM_SKIN_TONE = "\U0001f9d2\U0001f3fd"
- CHILD_MEDIUM_DARK_SKIN_TONE = "\U0001f9d2\U0001f3fe"
- CHILD_DARK_SKIN_TONE = "\U0001f9d2\U0001f3ff"
- BOY = "\U0001f466"
- BOY_LIGHT_SKIN_TONE = "\U0001f466\U0001f3fb"
- BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f466\U0001f3fc"
- BOY_MEDIUM_SKIN_TONE = "\U0001f466\U0001f3fd"
- BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f466\U0001f3fe"
- BOY_DARK_SKIN_TONE = "\U0001f466\U0001f3ff"
- GIRL = "\U0001f467"
- GIRL_LIGHT_SKIN_TONE = "\U0001f467\U0001f3fb"
- GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f467\U0001f3fc"
- GIRL_MEDIUM_SKIN_TONE = "\U0001f467\U0001f3fd"
- GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f467\U0001f3fe"
- GIRL_DARK_SKIN_TONE = "\U0001f467\U0001f3ff"
- PERSON = "\U0001f9d1"
- ADULT_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb"
- ADULT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc"
- ADULT_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd"
- ADULT_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe"
- ADULT_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff"
- MAN = "\U0001f468"
- MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb"
- MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc"
- MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd"
- MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe"
- MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3ff"
- WOMAN = "\U0001f469"
- WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb"
- WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc"
- WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd"
- WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe"
- WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3ff"
- OLDER_PERSON = "\U0001f9d3"
- OLDER_ADULT_LIGHT_SKIN_TONE = "\U0001f9d3\U0001f3fb"
- OLDER_ADULT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d3\U0001f3fc"
- OLDER_ADULT_MEDIUM_SKIN_TONE = "\U0001f9d3\U0001f3fd"
- OLDER_ADULT_MEDIUM_DARK_SKIN_TONE = "\U0001f9d3\U0001f3fe"
- OLDER_ADULT_DARK_SKIN_TONE = "\U0001f9d3\U0001f3ff"
- OLD_MAN = "\U0001f474"
- OLD_MAN_LIGHT_SKIN_TONE = "\U0001f474\U0001f3fb"
- OLD_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f474\U0001f3fc"
- OLD_MAN_MEDIUM_SKIN_TONE = "\U0001f474\U0001f3fd"
- OLD_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f474\U0001f3fe"
- OLD_MAN_DARK_SKIN_TONE = "\U0001f474\U0001f3ff"
- OLD_WOMAN = "\U0001f475"
- OLD_WOMAN_LIGHT_SKIN_TONE = "\U0001f475\U0001f3fb"
- OLD_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f475\U0001f3fc"
- OLD_WOMAN_MEDIUM_SKIN_TONE = "\U0001f475\U0001f3fd"
- OLD_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f475\U0001f3fe"
- OLD_WOMAN_DARK_SKIN_TONE = "\U0001f475\U0001f3ff"
- MAN_HEALTH_WORKER = "\U0001f468\u200d\u2695\ufe0f"
- MAN_HEALTH_WORKER_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2695\ufe0f"
- MAN_HEALTH_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2695\ufe0f"
- MAN_HEALTH_WORKER_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2695\ufe0f"
- MAN_HEALTH_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2695\ufe0f"
- MAN_HEALTH_WORKER_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2695\ufe0f"
- WOMAN_HEALTH_WORKER = "\U0001f469\u200d\u2695\ufe0f"
- WOMAN_HEALTH_WORKER_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2695\ufe0f"
- WOMAN_HEALTH_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2695\ufe0f"
- WOMAN_HEALTH_WORKER_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2695\ufe0f"
- WOMAN_HEALTH_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2695\ufe0f"
- WOMAN_HEALTH_WORKER_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2695\ufe0f"
- MAN_STUDENT = "\U0001f468\u200d\U0001f393"
- MAN_STUDENT_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f393"
- MAN_STUDENT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f393"
- MAN_STUDENT_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f393"
- MAN_STUDENT_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f393"
- MAN_STUDENT_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f393"
- WOMAN_STUDENT = "\U0001f469\u200d\U0001f393"
- WOMAN_STUDENT_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f393"
- WOMAN_STUDENT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f393"
- WOMAN_STUDENT_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f393"
- WOMAN_STUDENT_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f393"
- WOMAN_STUDENT_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f393"
- MAN_TEACHER = "\U0001f468\u200d\U0001f3eb"
- MAN_TEACHER_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f3eb"
- MAN_TEACHER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f3eb"
- MAN_TEACHER_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f3eb"
- MAN_TEACHER_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f3eb"
- MAN_TEACHER_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f3eb"
- WOMAN_TEACHER = "\U0001f469\u200d\U0001f3eb"
- WOMAN_TEACHER_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f3eb"
- WOMAN_TEACHER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f3eb"
- WOMAN_TEACHER_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f3eb"
- WOMAN_TEACHER_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f3eb"
- WOMAN_TEACHER_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f3eb"
- MAN_JUDGE = "\U0001f468\u200d\u2696\ufe0f"
- MAN_JUDGE_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2696\ufe0f"
- MAN_JUDGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2696\ufe0f"
- MAN_JUDGE_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2696\ufe0f"
- MAN_JUDGE_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2696\ufe0f"
- MAN_JUDGE_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2696\ufe0f"
- WOMAN_JUDGE = "\U0001f469\u200d\u2696\ufe0f"
- WOMAN_JUDGE_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2696\ufe0f"
- WOMAN_JUDGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2696\ufe0f"
- WOMAN_JUDGE_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2696\ufe0f"
- WOMAN_JUDGE_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2696\ufe0f"
- WOMAN_JUDGE_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2696\ufe0f"
- MAN_FARMER = "\U0001f468\u200d\U0001f33e"
- MAN_FARMER_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f33e"
- MAN_FARMER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f33e"
- MAN_FARMER_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f33e"
- MAN_FARMER_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f33e"
- MAN_FARMER_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f33e"
- WOMAN_FARMER = "\U0001f469\u200d\U0001f33e"
- WOMAN_FARMER_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f33e"
- WOMAN_FARMER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f33e"
- WOMAN_FARMER_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f33e"
- WOMAN_FARMER_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f33e"
- WOMAN_FARMER_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f33e"
- MAN_COOK = "\U0001f468\u200d\U0001f373"
- MAN_COOK_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f373"
- MAN_COOK_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f373"
- MAN_COOK_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f373"
- MAN_COOK_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f373"
- MAN_COOK_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f373"
- WOMAN_COOK = "\U0001f469\u200d\U0001f373"
- WOMAN_COOK_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f373"
- WOMAN_COOK_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f373"
- WOMAN_COOK_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f373"
- WOMAN_COOK_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f373"
- WOMAN_COOK_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f373"
- MAN_MECHANIC = "\U0001f468\u200d\U0001f527"
- MAN_MECHANIC_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f527"
- MAN_MECHANIC_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f527"
- MAN_MECHANIC_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f527"
- MAN_MECHANIC_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f527"
- MAN_MECHANIC_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f527"
- WOMAN_MECHANIC = "\U0001f469\u200d\U0001f527"
- WOMAN_MECHANIC_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f527"
- WOMAN_MECHANIC_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f527"
- WOMAN_MECHANIC_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f527"
- WOMAN_MECHANIC_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f527"
- WOMAN_MECHANIC_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f527"
- MAN_FACTORY_WORKER = "\U0001f468\u200d\U0001f3ed"
- MAN_FACTORY_WORKER_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f3ed"
- MAN_FACTORY_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f3ed"
- MAN_FACTORY_WORKER_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f3ed"
- MAN_FACTORY_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f3ed"
- MAN_FACTORY_WORKER_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f3ed"
- WOMAN_FACTORY_WORKER = "\U0001f469\u200d\U0001f3ed"
- WOMAN_FACTORY_WORKER_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f3ed"
- WOMAN_FACTORY_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f3ed"
- WOMAN_FACTORY_WORKER_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f3ed"
- WOMAN_FACTORY_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f3ed"
- WOMAN_FACTORY_WORKER_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f3ed"
- MAN_OFFICE_WORKER = "\U0001f468\u200d\U0001f4bc"
- MAN_OFFICE_WORKER_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f4bc"
- MAN_OFFICE_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f4bc"
- MAN_OFFICE_WORKER_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f4bc"
- MAN_OFFICE_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f4bc"
- MAN_OFFICE_WORKER_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f4bc"
- WOMAN_OFFICE_WORKER = "\U0001f469\u200d\U0001f4bc"
- WOMAN_OFFICE_WORKER_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f4bc"
- WOMAN_OFFICE_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f4bc"
- WOMAN_OFFICE_WORKER_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f4bc"
- WOMAN_OFFICE_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f4bc"
- WOMAN_OFFICE_WORKER_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f4bc"
- MAN_SCIENTIST = "\U0001f468\u200d\U0001f52c"
- MAN_SCIENTIST_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f52c"
- MAN_SCIENTIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f52c"
- MAN_SCIENTIST_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f52c"
- MAN_SCIENTIST_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f52c"
- MAN_SCIENTIST_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f52c"
- WOMAN_SCIENTIST = "\U0001f469\u200d\U0001f52c"
- WOMAN_SCIENTIST_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f52c"
- WOMAN_SCIENTIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f52c"
- WOMAN_SCIENTIST_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f52c"
- WOMAN_SCIENTIST_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f52c"
- WOMAN_SCIENTIST_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f52c"
- MAN_TECHNOLOGIST = "\U0001f468\u200d\U0001f4bb"
- MAN_TECHNOLOGIST_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f4bb"
- MAN_TECHNOLOGIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f4bb"
- MAN_TECHNOLOGIST_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f4bb"
- MAN_TECHNOLOGIST_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f4bb"
- MAN_TECHNOLOGIST_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f4bb"
- WOMAN_TECHNOLOGIST = "\U0001f469\u200d\U0001f4bb"
- WOMAN_TECHNOLOGIST_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f4bb"
- WOMAN_TECHNOLOGIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f4bb"
- WOMAN_TECHNOLOGIST_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f4bb"
- WOMAN_TECHNOLOGIST_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f4bb"
- WOMAN_TECHNOLOGIST_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f4bb"
- MAN_SINGER = "\U0001f468\u200d\U0001f3a4"
- MAN_SINGER_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f3a4"
- MAN_SINGER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f3a4"
- MAN_SINGER_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f3a4"
- MAN_SINGER_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f3a4"
- MAN_SINGER_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f3a4"
- WOMAN_SINGER = "\U0001f469\u200d\U0001f3a4"
- WOMAN_SINGER_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f3a4"
- WOMAN_SINGER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f3a4"
- WOMAN_SINGER_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f3a4"
- WOMAN_SINGER_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f3a4"
- WOMAN_SINGER_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f3a4"
- MAN_ARTIST = "\U0001f468\u200d\U0001f3a8"
- MAN_ARTIST_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f3a8"
- MAN_ARTIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f3a8"
- MAN_ARTIST_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f3a8"
- MAN_ARTIST_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f3a8"
- MAN_ARTIST_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f3a8"
- WOMAN_ARTIST = "\U0001f469\u200d\U0001f3a8"
- WOMAN_ARTIST_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f3a8"
- WOMAN_ARTIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f3a8"
- WOMAN_ARTIST_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f3a8"
- WOMAN_ARTIST_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f3a8"
- WOMAN_ARTIST_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f3a8"
- MAN_PILOT = "\U0001f468\u200d\u2708\ufe0f"
- MAN_PILOT_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2708\ufe0f"
- MAN_PILOT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2708\ufe0f"
- MAN_PILOT_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2708\ufe0f"
- MAN_PILOT_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2708\ufe0f"
- MAN_PILOT_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2708\ufe0f"
- WOMAN_PILOT = "\U0001f469\u200d\u2708\ufe0f"
- WOMAN_PILOT_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2708\ufe0f"
- WOMAN_PILOT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2708\ufe0f"
- WOMAN_PILOT_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2708\ufe0f"
- WOMAN_PILOT_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2708\ufe0f"
- WOMAN_PILOT_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2708\ufe0f"
- MAN_ASTRONAUT = "\U0001f468\u200d\U0001f680"
- MAN_ASTRONAUT_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f680"
- MAN_ASTRONAUT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f680"
- MAN_ASTRONAUT_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f680"
- MAN_ASTRONAUT_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f680"
- MAN_ASTRONAUT_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f680"
- WOMAN_ASTRONAUT = "\U0001f469\u200d\U0001f680"
- WOMAN_ASTRONAUT_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f680"
- WOMAN_ASTRONAUT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f680"
- WOMAN_ASTRONAUT_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f680"
- WOMAN_ASTRONAUT_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f680"
- WOMAN_ASTRONAUT_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f680"
- MAN_FIREFIGHTER = "\U0001f468\u200d\U0001f692"
- MAN_FIREFIGHTER_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f692"
- MAN_FIREFIGHTER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f692"
- MAN_FIREFIGHTER_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f692"
- MAN_FIREFIGHTER_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f692"
- MAN_FIREFIGHTER_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f692"
- WOMAN_FIREFIGHTER = "\U0001f469\u200d\U0001f692"
- WOMAN_FIREFIGHTER_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f692"
- WOMAN_FIREFIGHTER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f692"
- WOMAN_FIREFIGHTER_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f692"
- WOMAN_FIREFIGHTER_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f692"
- WOMAN_FIREFIGHTER_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f692"
- POLICE_OFFICER = "\U0001f46e"
- POLICE_OFFICER_LIGHT_SKIN_TONE = "\U0001f46e\U0001f3fb"
- POLICE_OFFICER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f46e\U0001f3fc"
- POLICE_OFFICER_MEDIUM_SKIN_TONE = "\U0001f46e\U0001f3fd"
- POLICE_OFFICER_MEDIUM_DARK_SKIN_TONE = "\U0001f46e\U0001f3fe"
- POLICE_OFFICER_DARK_SKIN_TONE = "\U0001f46e\U0001f3ff"
- MAN_POLICE_OFFICER = "\U0001f46e\u200d\u2642\ufe0f"
- MAN_POLICE_OFFICER_LIGHT_SKIN_TONE = "\U0001f46e\U0001f3fb\u200d\u2642\ufe0f"
- MAN_POLICE_OFFICER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f46e\U0001f3fc\u200d\u2642\ufe0f"
- MAN_POLICE_OFFICER_MEDIUM_SKIN_TONE = "\U0001f46e\U0001f3fd\u200d\u2642\ufe0f"
- MAN_POLICE_OFFICER_MEDIUM_DARK_SKIN_TONE = "\U0001f46e\U0001f3fe\u200d\u2642\ufe0f"
- MAN_POLICE_OFFICER_DARK_SKIN_TONE = "\U0001f46e\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_POLICE_OFFICER = "\U0001f46e\u200d\u2640\ufe0f"
- WOMAN_POLICE_OFFICER_LIGHT_SKIN_TONE = "\U0001f46e\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_POLICE_OFFICER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f46e\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_POLICE_OFFICER_MEDIUM_SKIN_TONE = "\U0001f46e\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_POLICE_OFFICER_MEDIUM_DARK_SKIN_TONE = "\U0001f46e\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_POLICE_OFFICER_DARK_SKIN_TONE = "\U0001f46e\U0001f3ff\u200d\u2640\ufe0f"
- DETECTIVE = "\U0001f575\ufe0f"
- DETECTIVE_LIGHT_SKIN_TONE = "\U0001f575\U0001f3fb"
- DETECTIVE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f575\U0001f3fc"
- DETECTIVE_MEDIUM_SKIN_TONE = "\U0001f575\U0001f3fd"
- DETECTIVE_MEDIUM_DARK_SKIN_TONE = "\U0001f575\U0001f3fe"
- DETECTIVE_DARK_SKIN_TONE = "\U0001f575\U0001f3ff"
- MAN_DETECTIVE = "\U0001f575\ufe0f\u200d\u2642\ufe0f"
- MAN_DETECTIVE_LIGHT_SKIN_TONE = "\U0001f575\U0001f3fb\u200d\u2642\ufe0f"
- MAN_DETECTIVE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f575\U0001f3fc\u200d\u2642\ufe0f"
- MAN_DETECTIVE_MEDIUM_SKIN_TONE = "\U0001f575\U0001f3fd\u200d\u2642\ufe0f"
- MAN_DETECTIVE_MEDIUM_DARK_SKIN_TONE = "\U0001f575\U0001f3fe\u200d\u2642\ufe0f"
- MAN_DETECTIVE_DARK_SKIN_TONE = "\U0001f575\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_DETECTIVE = "\U0001f575\ufe0f\u200d\u2640\ufe0f"
- WOMAN_DETECTIVE_LIGHT_SKIN_TONE = "\U0001f575\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_DETECTIVE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f575\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_DETECTIVE_MEDIUM_SKIN_TONE = "\U0001f575\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_DETECTIVE_MEDIUM_DARK_SKIN_TONE = "\U0001f575\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_DETECTIVE_DARK_SKIN_TONE = "\U0001f575\U0001f3ff\u200d\u2640\ufe0f"
- GUARD = "\U0001f482"
- GUARD_LIGHT_SKIN_TONE = "\U0001f482\U0001f3fb"
- GUARD_MEDIUM_LIGHT_SKIN_TONE = "\U0001f482\U0001f3fc"
- GUARD_MEDIUM_SKIN_TONE = "\U0001f482\U0001f3fd"
- GUARD_MEDIUM_DARK_SKIN_TONE = "\U0001f482\U0001f3fe"
- GUARD_DARK_SKIN_TONE = "\U0001f482\U0001f3ff"
- MAN_GUARD = "\U0001f482\u200d\u2642\ufe0f"
- MAN_GUARD_LIGHT_SKIN_TONE = "\U0001f482\U0001f3fb\u200d\u2642\ufe0f"
- MAN_GUARD_MEDIUM_LIGHT_SKIN_TONE = "\U0001f482\U0001f3fc\u200d\u2642\ufe0f"
- MAN_GUARD_MEDIUM_SKIN_TONE = "\U0001f482\U0001f3fd\u200d\u2642\ufe0f"
- MAN_GUARD_MEDIUM_DARK_SKIN_TONE = "\U0001f482\U0001f3fe\u200d\u2642\ufe0f"
- MAN_GUARD_DARK_SKIN_TONE = "\U0001f482\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_GUARD = "\U0001f482\u200d\u2640\ufe0f"
- WOMAN_GUARD_LIGHT_SKIN_TONE = "\U0001f482\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_GUARD_MEDIUM_LIGHT_SKIN_TONE = "\U0001f482\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_GUARD_MEDIUM_SKIN_TONE = "\U0001f482\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_GUARD_MEDIUM_DARK_SKIN_TONE = "\U0001f482\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_GUARD_DARK_SKIN_TONE = "\U0001f482\U0001f3ff\u200d\u2640\ufe0f"
- CONSTRUCTION_WORKER = "\U0001f477"
- CONSTRUCTION_WORKER_LIGHT_SKIN_TONE = "\U0001f477\U0001f3fb"
- CONSTRUCTION_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f477\U0001f3fc"
- CONSTRUCTION_WORKER_MEDIUM_SKIN_TONE = "\U0001f477\U0001f3fd"
- CONSTRUCTION_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f477\U0001f3fe"
- CONSTRUCTION_WORKER_DARK_SKIN_TONE = "\U0001f477\U0001f3ff"
- MAN_CONSTRUCTION_WORKER = "\U0001f477\u200d\u2642\ufe0f"
- MAN_CONSTRUCTION_WORKER_LIGHT_SKIN_TONE = "\U0001f477\U0001f3fb\u200d\u2642\ufe0f"
- MAN_CONSTRUCTION_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f477\U0001f3fc\u200d\u2642\ufe0f"
- MAN_CONSTRUCTION_WORKER_MEDIUM_SKIN_TONE = "\U0001f477\U0001f3fd\u200d\u2642\ufe0f"
- MAN_CONSTRUCTION_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f477\U0001f3fe\u200d\u2642\ufe0f"
- MAN_CONSTRUCTION_WORKER_DARK_SKIN_TONE = "\U0001f477\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_CONSTRUCTION_WORKER = "\U0001f477\u200d\u2640\ufe0f"
- WOMAN_CONSTRUCTION_WORKER_LIGHT_SKIN_TONE = "\U0001f477\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_CONSTRUCTION_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f477\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_CONSTRUCTION_WORKER_MEDIUM_SKIN_TONE = "\U0001f477\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_CONSTRUCTION_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f477\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_CONSTRUCTION_WORKER_DARK_SKIN_TONE = "\U0001f477\U0001f3ff\u200d\u2640\ufe0f"
- PRINCE = "\U0001f934"
- PRINCE_LIGHT_SKIN_TONE = "\U0001f934\U0001f3fb"
- PRINCE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f934\U0001f3fc"
- PRINCE_MEDIUM_SKIN_TONE = "\U0001f934\U0001f3fd"
- PRINCE_MEDIUM_DARK_SKIN_TONE = "\U0001f934\U0001f3fe"
- PRINCE_DARK_SKIN_TONE = "\U0001f934\U0001f3ff"
- PRINCESS = "\U0001f478"
- PRINCESS_LIGHT_SKIN_TONE = "\U0001f478\U0001f3fb"
- PRINCESS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f478\U0001f3fc"
- PRINCESS_MEDIUM_SKIN_TONE = "\U0001f478\U0001f3fd"
- PRINCESS_MEDIUM_DARK_SKIN_TONE = "\U0001f478\U0001f3fe"
- PRINCESS_DARK_SKIN_TONE = "\U0001f478\U0001f3ff"
- PERSON_WEARING_TURBAN = "\U0001f473"
- PERSON_WEARING_TURBAN_LIGHT_SKIN_TONE = "\U0001f473\U0001f3fb"
- PERSON_WEARING_TURBAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f473\U0001f3fc"
- PERSON_WEARING_TURBAN_MEDIUM_SKIN_TONE = "\U0001f473\U0001f3fd"
- PERSON_WEARING_TURBAN_MEDIUM_DARK_SKIN_TONE = "\U0001f473\U0001f3fe"
- PERSON_WEARING_TURBAN_DARK_SKIN_TONE = "\U0001f473\U0001f3ff"
- MAN_WEARING_TURBAN = "\U0001f473\u200d\u2642\ufe0f"
- MAN_WEARING_TURBAN_LIGHT_SKIN_TONE = "\U0001f473\U0001f3fb\u200d\u2642\ufe0f"
- MAN_WEARING_TURBAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f473\U0001f3fc\u200d\u2642\ufe0f"
- MAN_WEARING_TURBAN_MEDIUM_SKIN_TONE = "\U0001f473\U0001f3fd\u200d\u2642\ufe0f"
- MAN_WEARING_TURBAN_MEDIUM_DARK_SKIN_TONE = "\U0001f473\U0001f3fe\u200d\u2642\ufe0f"
- MAN_WEARING_TURBAN_DARK_SKIN_TONE = "\U0001f473\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_WEARING_TURBAN = "\U0001f473\u200d\u2640\ufe0f"
- WOMAN_WEARING_TURBAN_LIGHT_SKIN_TONE = "\U0001f473\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_WEARING_TURBAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f473\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_WEARING_TURBAN_MEDIUM_SKIN_TONE = "\U0001f473\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_WEARING_TURBAN_MEDIUM_DARK_SKIN_TONE = "\U0001f473\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_WEARING_TURBAN_DARK_SKIN_TONE = "\U0001f473\U0001f3ff\u200d\u2640\ufe0f"
- MAN_WITH_CHINESE_CAP = "\U0001f472"
- MAN_WITH_CHINESE_CAP_LIGHT_SKIN_TONE = "\U0001f472\U0001f3fb"
- MAN_WITH_CHINESE_CAP_MEDIUM_LIGHT_SKIN_TONE = "\U0001f472\U0001f3fc"
- MAN_WITH_CHINESE_CAP_MEDIUM_SKIN_TONE = "\U0001f472\U0001f3fd"
- MAN_WITH_CHINESE_CAP_MEDIUM_DARK_SKIN_TONE = "\U0001f472\U0001f3fe"
- MAN_WITH_CHINESE_CAP_DARK_SKIN_TONE = "\U0001f472\U0001f3ff"
- WOMAN_WITH_HEADSCARF = "\U0001f9d5"
- PERSON_WITH_HEADSCARF_LIGHT_SKIN_TONE = "\U0001f9d5\U0001f3fb"
- PERSON_WITH_HEADSCARF_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d5\U0001f3fc"
- PERSON_WITH_HEADSCARF_MEDIUM_SKIN_TONE = "\U0001f9d5\U0001f3fd"
- PERSON_WITH_HEADSCARF_MEDIUM_DARK_SKIN_TONE = "\U0001f9d5\U0001f3fe"
- PERSON_WITH_HEADSCARF_DARK_SKIN_TONE = "\U0001f9d5\U0001f3ff"
- MAN_BEARD = "\U0001f9d4"
- BEARDED_PERSON_LIGHT_SKIN_TONE = "\U0001f9d4\U0001f3fb"
- BEARDED_PERSON_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d4\U0001f3fc"
- BEARDED_PERSON_MEDIUM_SKIN_TONE = "\U0001f9d4\U0001f3fd"
- BEARDED_PERSON_MEDIUM_DARK_SKIN_TONE = "\U0001f9d4\U0001f3fe"
- BEARDED_PERSON_DARK_SKIN_TONE = "\U0001f9d4\U0001f3ff"
- PERSON_BLOND_HAIR = "\U0001f471"
- BLOND_HAIRED_PERSON_LIGHT_SKIN_TONE = "\U0001f471\U0001f3fb"
- BLOND_HAIRED_PERSON_MEDIUM_LIGHT_SKIN_TONE = "\U0001f471\U0001f3fc"
- BLOND_HAIRED_PERSON_MEDIUM_SKIN_TONE = "\U0001f471\U0001f3fd"
- BLOND_HAIRED_PERSON_MEDIUM_DARK_SKIN_TONE = "\U0001f471\U0001f3fe"
- BLOND_HAIRED_PERSON_DARK_SKIN_TONE = "\U0001f471\U0001f3ff"
- MAN_BLOND_HAIR = "\U0001f471\u200d\u2642\ufe0f"
- BLOND_HAIRED_MAN_LIGHT_SKIN_TONE = "\U0001f471\U0001f3fb\u200d\u2642\ufe0f"
- BLOND_HAIRED_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f471\U0001f3fc\u200d\u2642\ufe0f"
- BLOND_HAIRED_MAN_MEDIUM_SKIN_TONE = "\U0001f471\U0001f3fd\u200d\u2642\ufe0f"
- BLOND_HAIRED_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f471\U0001f3fe\u200d\u2642\ufe0f"
- BLOND_HAIRED_MAN_DARK_SKIN_TONE = "\U0001f471\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_BLOND_HAIR = "\U0001f471\u200d\u2640\ufe0f"
- BLOND_HAIRED_WOMAN_LIGHT_SKIN_TONE = "\U0001f471\U0001f3fb\u200d\u2640\ufe0f"
- BLOND_HAIRED_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f471\U0001f3fc\u200d\u2640\ufe0f"
- BLOND_HAIRED_WOMAN_MEDIUM_SKIN_TONE = "\U0001f471\U0001f3fd\u200d\u2640\ufe0f"
- BLOND_HAIRED_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f471\U0001f3fe\u200d\u2640\ufe0f"
- BLOND_HAIRED_WOMAN_DARK_SKIN_TONE = "\U0001f471\U0001f3ff\u200d\u2640\ufe0f"
- MAN_RED_HAIRED = "\U0001f468\u200d\U0001f9b0"
- MAN_RED_HAIRED_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f9b0"
- MAN_RED_HAIRED_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f9b0"
- MAN_RED_HAIRED_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f9b0"
- MAN_RED_HAIRED_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f9b0"
- MAN_RED_HAIRED_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f9b0"
- WOMAN_RED_HAIRED = "\U0001f469\u200d\U0001f9b0"
- WOMAN_RED_HAIRED_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f9b0"
- WOMAN_RED_HAIRED_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f9b0"
- WOMAN_RED_HAIRED_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f9b0"
- WOMAN_RED_HAIRED_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f9b0"
- WOMAN_RED_HAIRED_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f9b0"
- MAN_CURLY_HAIRED = "\U0001f468\u200d\U0001f9b1"
- MAN_CURLY_HAIRED_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f9b1"
- MAN_CURLY_HAIRED_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f9b1"
- MAN_CURLY_HAIRED_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f9b1"
- MAN_CURLY_HAIRED_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f9b1"
- MAN_CURLY_HAIRED_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f9b1"
- WOMAN_CURLY_HAIRED = "\U0001f469\u200d\U0001f9b1"
- WOMAN_CURLY_HAIRED_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f9b1"
- WOMAN_CURLY_HAIRED_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f9b1"
- WOMAN_CURLY_HAIRED_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f9b1"
- WOMAN_CURLY_HAIRED_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f9b1"
- WOMAN_CURLY_HAIRED_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f9b1"
- MAN_BALD = "\U0001f468\u200d\U0001f9b2"
- MAN_BALD_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f9b2"
- MAN_BALD_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f9b2"
- MAN_BALD_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f9b2"
- MAN_BALD_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f9b2"
- MAN_BALD_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f9b2"
- WOMAN_BALD = "\U0001f469\u200d\U0001f9b2"
- WOMAN_BALD_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f9b2"
- WOMAN_BALD_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f9b2"
- WOMAN_BALD_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f9b2"
- WOMAN_BALD_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f9b2"
- WOMAN_BALD_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f9b2"
- MAN_WHITE_HAIRED = "\U0001f468\u200d\U0001f9b3"
- MAN_WHITE_HAIRED_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f9b3"
- MAN_WHITE_HAIRED_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f9b3"
- MAN_WHITE_HAIRED_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f9b3"
- MAN_WHITE_HAIRED_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f9b3"
- MAN_WHITE_HAIRED_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f9b3"
- WOMAN_WHITE_HAIRED = "\U0001f469\u200d\U0001f9b3"
- WOMAN_WHITE_HAIRED_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f9b3"
- WOMAN_WHITE_HAIRED_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f9b3"
- WOMAN_WHITE_HAIRED_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f9b3"
- WOMAN_WHITE_HAIRED_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f9b3"
- WOMAN_WHITE_HAIRED_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f9b3"
- MAN_IN_TUXEDO = "\U0001f935"
- MAN_IN_TUXEDO_LIGHT_SKIN_TONE = "\U0001f935\U0001f3fb"
- MAN_IN_TUXEDO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f935\U0001f3fc"
- MAN_IN_TUXEDO_MEDIUM_SKIN_TONE = "\U0001f935\U0001f3fd"
- MAN_IN_TUXEDO_MEDIUM_DARK_SKIN_TONE = "\U0001f935\U0001f3fe"
- MAN_IN_TUXEDO_DARK_SKIN_TONE = "\U0001f935\U0001f3ff"
- BRIDE_WITH_VEIL = "\U0001f470"
- BRIDE_WITH_VEIL_LIGHT_SKIN_TONE = "\U0001f470\U0001f3fb"
- BRIDE_WITH_VEIL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f470\U0001f3fc"
- BRIDE_WITH_VEIL_MEDIUM_SKIN_TONE = "\U0001f470\U0001f3fd"
- BRIDE_WITH_VEIL_MEDIUM_DARK_SKIN_TONE = "\U0001f470\U0001f3fe"
- BRIDE_WITH_VEIL_DARK_SKIN_TONE = "\U0001f470\U0001f3ff"
- PREGNANT_WOMAN = "\U0001f930"
- PREGNANT_WOMAN_LIGHT_SKIN_TONE = "\U0001f930\U0001f3fb"
- PREGNANT_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f930\U0001f3fc"
- PREGNANT_WOMAN_MEDIUM_SKIN_TONE = "\U0001f930\U0001f3fd"
- PREGNANT_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f930\U0001f3fe"
- PREGNANT_WOMAN_DARK_SKIN_TONE = "\U0001f930\U0001f3ff"
- BREAST_FEEDING = "\U0001f931"
- BREAST_FEEDING_LIGHT_SKIN_TONE = "\U0001f931\U0001f3fb"
- BREAST_FEEDING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f931\U0001f3fc"
- BREAST_FEEDING_MEDIUM_SKIN_TONE = "\U0001f931\U0001f3fd"
- BREAST_FEEDING_MEDIUM_DARK_SKIN_TONE = "\U0001f931\U0001f3fe"
- BREAST_FEEDING_DARK_SKIN_TONE = "\U0001f931\U0001f3ff"
- BABY_ANGEL = "\U0001f47c"
- BABY_ANGEL_LIGHT_SKIN_TONE = "\U0001f47c\U0001f3fb"
- BABY_ANGEL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f47c\U0001f3fc"
- BABY_ANGEL_MEDIUM_SKIN_TONE = "\U0001f47c\U0001f3fd"
- BABY_ANGEL_MEDIUM_DARK_SKIN_TONE = "\U0001f47c\U0001f3fe"
- BABY_ANGEL_DARK_SKIN_TONE = "\U0001f47c\U0001f3ff"
- SANTA_CLAUS = "\U0001f385"
- SANTA_CLAUS_LIGHT_SKIN_TONE = "\U0001f385\U0001f3fb"
- SANTA_CLAUS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f385\U0001f3fc"
- SANTA_CLAUS_MEDIUM_SKIN_TONE = "\U0001f385\U0001f3fd"
- SANTA_CLAUS_MEDIUM_DARK_SKIN_TONE = "\U0001f385\U0001f3fe"
- SANTA_CLAUS_DARK_SKIN_TONE = "\U0001f385\U0001f3ff"
- MRS_CLAUS = "\U0001f936"
- MRS_CLAUS_LIGHT_SKIN_TONE = "\U0001f936\U0001f3fb"
- MRS_CLAUS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f936\U0001f3fc"
- MRS_CLAUS_MEDIUM_SKIN_TONE = "\U0001f936\U0001f3fd"
- MRS_CLAUS_MEDIUM_DARK_SKIN_TONE = "\U0001f936\U0001f3fe"
- MRS_CLAUS_DARK_SKIN_TONE = "\U0001f936\U0001f3ff"
- SUPERHERO = "\U0001f9b8"
- SUPERHERO_LIGHT_SKIN_TONE = "\U0001f9b8\U0001f3fb"
- SUPERHERO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b8\U0001f3fc"
- SUPERHERO_MEDIUM_SKIN_TONE = "\U0001f9b8\U0001f3fd"
- SUPERHERO_MEDIUM_DARK_SKIN_TONE = "\U0001f9b8\U0001f3fe"
- SUPERHERO_DARK_SKIN_TONE = "\U0001f9b8\U0001f3ff"
- WOMAN_SUPERHERO = "\U0001f9b8\u200d\u2640\ufe0f"
- WOMAN_SUPERHERO_LIGHT_SKIN_TONE = "\U0001f9b8\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_SUPERHERO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b8\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_SUPERHERO_MEDIUM_SKIN_TONE = "\U0001f9b8\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_SUPERHERO_MEDIUM_DARK_SKIN_TONE = "\U0001f9b8\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_SUPERHERO_DARK_SKIN_TONE = "\U0001f9b8\U0001f3ff\u200d\u2640\ufe0f"
- MAN_SUPERHERO = "\U0001f9b8\u200d\u2642\ufe0f"
- MAN_SUPERHERO_LIGHT_SKIN_TONE = "\U0001f9b8\U0001f3fb\u200d\u2642\ufe0f"
- MAN_SUPERHERO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b8\U0001f3fc\u200d\u2642\ufe0f"
- MAN_SUPERHERO_MEDIUM_SKIN_TONE = "\U0001f9b8\U0001f3fd\u200d\u2642\ufe0f"
- MAN_SUPERHERO_MEDIUM_DARK_SKIN_TONE = "\U0001f9b8\U0001f3fe\u200d\u2642\ufe0f"
- WOMAN_WITH_BUNNY_EARS_TYPE_1_2 = "\U0001f46f\U0001f3fb"
- MAN_SUPERHERO_DARK_SKIN_TONE = "\U0001f9b8\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_WITH_BUNNY_EARS_TYPE_3 = "\U0001f46f\U0001f3fc"
- WOMAN_WITH_BUNNY_EARS_TYPE_4 = "\U0001f46f\U0001f3fd"
- SUPERVILLAIN = "\U0001f9b9"
- WOMAN_WITH_BUNNY_EARS_TYPE_5 = "\U0001f46f\U0001f3fe"
- WOMAN_WITH_BUNNY_EARS_TYPE_6 = "\U0001f46f\U0001f3ff"
- SUPERVILLAIN_LIGHT_SKIN_TONE = "\U0001f9b9\U0001f3fb"
- SUPERVILLAIN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b9\U0001f3fc"
- MEN_WITH_BUNNY_EARS_PARTYING_TYPE_1_2 = "\U0001f46f\U0001f3fb\u200d\u2642\ufe0f"
- SUPERVILLAIN_MEDIUM_SKIN_TONE = "\U0001f9b9\U0001f3fd"
- MEN_WITH_BUNNY_EARS_PARTYING_TYPE_3 = "\U0001f46f\U0001f3fc\u200d\u2642\ufe0f"
- SUPERVILLAIN_MEDIUM_DARK_SKIN_TONE = "\U0001f9b9\U0001f3fe"
- MEN_WITH_BUNNY_EARS_PARTYING_TYPE_4 = "\U0001f46f\U0001f3fd\u200d\u2642\ufe0f"
- SUPERVILLAIN_DARK_SKIN_TONE = "\U0001f9b9\U0001f3ff"
- MEN_WITH_BUNNY_EARS_PARTYING_TYPE_5 = "\U0001f46f\U0001f3fe\u200d\u2642\ufe0f"
- WOMAN_SUPERVILLAIN = "\U0001f9b9\u200d\u2640\ufe0f"
- MEN_WITH_BUNNY_EARS_PARTYING_TYPE_6 = "\U0001f46f\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_SUPERVILLAIN_LIGHT_SKIN_TONE = "\U0001f9b9\U0001f3fb\u200d\u2640\ufe0f"
- WOMEN_WITH_BUNNY_EARS_PARTYING_TYPE_1_2 = "\U0001f46f\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_SUPERVILLAIN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b9\U0001f3fc\u200d\u2640\ufe0f"
- WOMEN_WITH_BUNNY_EARS_PARTYING_TYPE_3 = "\U0001f46f\U0001f3fc\u200d\u2640\ufe0f"
- WOMEN_WITH_BUNNY_EARS_PARTYING_TYPE_4 = "\U0001f46f\U0001f3fd\u200d\u2640\ufe0f"
- WOMEN_WITH_BUNNY_EARS_PARTYING_TYPE_5 = "\U0001f46f\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_SUPERVILLAIN_MEDIUM_SKIN_TONE = "\U0001f9b9\U0001f3fd\u200d\u2640\ufe0f"
- WOMEN_WITH_BUNNY_EARS_PARTYING_TYPE_6 = "\U0001f46f\U0001f3ff\u200d\u2640\ufe0f"
- WOMAN_SUPERVILLAIN_MEDIUM_DARK_SKIN_TONE = "\U0001f9b9\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_SUPERVILLAIN_DARK_SKIN_TONE = "\U0001f9b9\U0001f3ff\u200d\u2640\ufe0f"
- MAN_SUPERVILLAIN = "\U0001f9b9\u200d\u2642\ufe0f"
- MAN_SUPERVILLAIN_LIGHT_SKIN_TONE = "\U0001f9b9\U0001f3fb\u200d\u2642\ufe0f"
- MAN_SUPERVILLAIN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b9\U0001f3fc\u200d\u2642\ufe0f"
- MAN_SUPERVILLAIN_MEDIUM_SKIN_TONE = "\U0001f9b9\U0001f3fd\u200d\u2642\ufe0f"
- MAN_AND_WOMAN_HOLDING_HANDS_TYPE_1_2 = "\U0001f46b\U0001f3fb"
- MAN_AND_WOMAN_HOLDING_HANDS_TYPE_3 = "\U0001f46b\U0001f3fc"
- MAN_SUPERVILLAIN_MEDIUM_DARK_SKIN_TONE = "\U0001f9b9\U0001f3fe\u200d\u2642\ufe0f"
- MAN_AND_WOMAN_HOLDING_HANDS_TYPE_4 = "\U0001f46b\U0001f3fd"
- MAN_AND_WOMAN_HOLDING_HANDS_TYPE_5 = "\U0001f46b\U0001f3fe"
- MAN_SUPERVILLAIN_DARK_SKIN_TONE = "\U0001f9b9\U0001f3ff\u200d\u2642\ufe0f"
- MAN_AND_WOMAN_HOLDING_HANDS_TYPE_6 = "\U0001f46b\U0001f3ff"
- MAGE = "\U0001f9d9"
- TWO_MEN_HOLDING_HANDS_TYPE_1_2 = "\U0001f46c\U0001f3fb"
- TWO_MEN_HOLDING_HANDS_TYPE_3 = "\U0001f46c\U0001f3fc"
- MAGE_LIGHT_SKIN_TONE = "\U0001f9d9\U0001f3fb"
- TWO_MEN_HOLDING_HANDS_TYPE_4 = "\U0001f46c\U0001f3fd"
- MAGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d9\U0001f3fc"
- TWO_MEN_HOLDING_HANDS_TYPE_5 = "\U0001f46c\U0001f3fe"
- MAGE_MEDIUM_SKIN_TONE = "\U0001f9d9\U0001f3fd"
- TWO_MEN_HOLDING_HANDS_TYPE_6 = "\U0001f46c\U0001f3ff"
- MAGE_MEDIUM_DARK_SKIN_TONE = "\U0001f9d9\U0001f3fe"
- MAGE_DARK_SKIN_TONE = "\U0001f9d9\U0001f3ff"
- WOMAN_MAGE = "\U0001f9d9\u200d\u2640\ufe0f"
- TWO_WOMEN_HOLDING_HANDS_TYPE_1_2 = "\U0001f46d\U0001f3fb"
- TWO_WOMEN_HOLDING_HANDS_TYPE_3 = "\U0001f46d\U0001f3fc"
- WOMAN_MAGE_LIGHT_SKIN_TONE = "\U0001f9d9\U0001f3fb\u200d\u2640\ufe0f"
- TWO_WOMEN_HOLDING_HANDS_TYPE_4 = "\U0001f46d\U0001f3fd"
- TWO_WOMEN_HOLDING_HANDS_TYPE_5 = "\U0001f46d\U0001f3fe"
- WOMAN_MAGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d9\U0001f3fc\u200d\u2640\ufe0f"
- TWO_WOMEN_HOLDING_HANDS_TYPE_6 = "\U0001f46d\U0001f3ff"
- WOMAN_MAGE_MEDIUM_SKIN_TONE = "\U0001f9d9\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_MAGE_MEDIUM_DARK_SKIN_TONE = "\U0001f9d9\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_MAGE_DARK_SKIN_TONE = "\U0001f9d9\U0001f3ff\u200d\u2640\ufe0f"
- MAN_MAGE = "\U0001f9d9\u200d\u2642\ufe0f"
- MAN_MAGE_LIGHT_SKIN_TONE = "\U0001f9d9\U0001f3fb\u200d\u2642\ufe0f"
- FAMILY_TYPE_1_2 = "\U0001f46a\U0001f3fb"
- FAMILY_TYPE_3 = "\U0001f46a\U0001f3fc"
- MAN_MAGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d9\U0001f3fc\u200d\u2642\ufe0f"
- FAMILY_TYPE_4 = "\U0001f46a\U0001f3fd"
- FAMILY_TYPE_5 = "\U0001f46a\U0001f3fe"
- MAN_MAGE_MEDIUM_SKIN_TONE = "\U0001f9d9\U0001f3fd\u200d\u2642\ufe0f"
- FAMILY_TYPE_6 = "\U0001f46a\U0001f3ff"
- MAN_MAGE_MEDIUM_DARK_SKIN_TONE = "\U0001f9d9\U0001f3fe\u200d\u2642\ufe0f"
- MAN_MAGE_DARK_SKIN_TONE = "\U0001f9d9\U0001f3ff\u200d\u2642\ufe0f"
- FAIRY = "\U0001f9da"
- FAIRY_LIGHT_SKIN_TONE = "\U0001f9da\U0001f3fb"
- FAIRY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9da\U0001f3fc"
- FAIRY_MEDIUM_SKIN_TONE = "\U0001f9da\U0001f3fd"
- FAIRY_MEDIUM_DARK_SKIN_TONE = "\U0001f9da\U0001f3fe"
- FAIRY_DARK_SKIN_TONE = "\U0001f9da\U0001f3ff"
- WOMAN_FAIRY = "\U0001f9da\u200d\u2640\ufe0f"
- WOMAN_FAIRY_LIGHT_SKIN_TONE = "\U0001f9da\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_FAIRY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9da\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_FAIRY_MEDIUM_SKIN_TONE = "\U0001f9da\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_FAIRY_MEDIUM_DARK_SKIN_TONE = "\U0001f9da\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_FAIRY_DARK_SKIN_TONE = "\U0001f9da\U0001f3ff\u200d\u2640\ufe0f"
- MAN_FAIRY = "\U0001f9da\u200d\u2642\ufe0f"
- MAN_FAIRY_LIGHT_SKIN_TONE = "\U0001f9da\U0001f3fb\u200d\u2642\ufe0f"
- MAN_FAIRY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9da\U0001f3fc\u200d\u2642\ufe0f"
- MAN_FAIRY_MEDIUM_SKIN_TONE = "\U0001f9da\U0001f3fd\u200d\u2642\ufe0f"
- MAN_FAIRY_MEDIUM_DARK_SKIN_TONE = "\U0001f9da\U0001f3fe\u200d\u2642\ufe0f"
- MAN_FAIRY_DARK_SKIN_TONE = "\U0001f9da\U0001f3ff\u200d\u2642\ufe0f"
- VAMPIRE = "\U0001f9db"
- VAMPIRE_LIGHT_SKIN_TONE = "\U0001f9db\U0001f3fb"
- VAMPIRE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9db\U0001f3fc"
- VAMPIRE_MEDIUM_SKIN_TONE = "\U0001f9db\U0001f3fd"
- VAMPIRE_MEDIUM_DARK_SKIN_TONE = "\U0001f9db\U0001f3fe"
- VAMPIRE_DARK_SKIN_TONE = "\U0001f9db\U0001f3ff"
- WOMAN_VAMPIRE = "\U0001f9db\u200d\u2640\ufe0f"
- WOMAN_VAMPIRE_LIGHT_SKIN_TONE = "\U0001f9db\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_VAMPIRE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9db\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_VAMPIRE_MEDIUM_SKIN_TONE = "\U0001f9db\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_VAMPIRE_MEDIUM_DARK_SKIN_TONE = "\U0001f9db\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_VAMPIRE_DARK_SKIN_TONE = "\U0001f9db\U0001f3ff\u200d\u2640\ufe0f"
- MAN_VAMPIRE = "\U0001f9db\u200d\u2642\ufe0f"
- MAN_VAMPIRE_LIGHT_SKIN_TONE = "\U0001f9db\U0001f3fb\u200d\u2642\ufe0f"
- MAN_VAMPIRE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9db\U0001f3fc\u200d\u2642\ufe0f"
- MAN_VAMPIRE_MEDIUM_SKIN_TONE = "\U0001f9db\U0001f3fd\u200d\u2642\ufe0f"
- MAN_VAMPIRE_MEDIUM_DARK_SKIN_TONE = "\U0001f9db\U0001f3fe\u200d\u2642\ufe0f"
- MAN_VAMPIRE_DARK_SKIN_TONE = "\U0001f9db\U0001f3ff\u200d\u2642\ufe0f"
- MERPERSON = "\U0001f9dc"
- MERPERSON_LIGHT_SKIN_TONE = "\U0001f9dc\U0001f3fb"
- MERPERSON_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9dc\U0001f3fc"
- MERPERSON_MEDIUM_SKIN_TONE = "\U0001f9dc\U0001f3fd"
- MERPERSON_MEDIUM_DARK_SKIN_TONE = "\U0001f9dc\U0001f3fe"
- MERPERSON_DARK_SKIN_TONE = "\U0001f9dc\U0001f3ff"
- MERMAID = "\U0001f9dc\u200d\u2640\ufe0f"
- MERMAID_LIGHT_SKIN_TONE = "\U0001f9dc\U0001f3fb\u200d\u2640\ufe0f"
- MERMAID_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9dc\U0001f3fc\u200d\u2640\ufe0f"
- MERMAID_MEDIUM_SKIN_TONE = "\U0001f9dc\U0001f3fd\u200d\u2640\ufe0f"
- MERMAID_MEDIUM_DARK_SKIN_TONE = "\U0001f9dc\U0001f3fe\u200d\u2640\ufe0f"
- MERMAID_DARK_SKIN_TONE = "\U0001f9dc\U0001f3ff\u200d\u2640\ufe0f"
- MERMAN = "\U0001f9dc\u200d\u2642\ufe0f"
- MERMAN_LIGHT_SKIN_TONE = "\U0001f9dc\U0001f3fb\u200d\u2642\ufe0f"
- MERMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9dc\U0001f3fc\u200d\u2642\ufe0f"
- MERMAN_MEDIUM_SKIN_TONE = "\U0001f9dc\U0001f3fd\u200d\u2642\ufe0f"
- MERMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f9dc\U0001f3fe\u200d\u2642\ufe0f"
- MERMAN_DARK_SKIN_TONE = "\U0001f9dc\U0001f3ff\u200d\u2642\ufe0f"
- ELF = "\U0001f9dd"
- ELF_LIGHT_SKIN_TONE = "\U0001f9dd\U0001f3fb"
- ELF_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9dd\U0001f3fc"
- ELF_MEDIUM_SKIN_TONE = "\U0001f9dd\U0001f3fd"
- ELF_MEDIUM_DARK_SKIN_TONE = "\U0001f9dd\U0001f3fe"
- ELF_DARK_SKIN_TONE = "\U0001f9dd\U0001f3ff"
- WOMAN_ELF = "\U0001f9dd\u200d\u2640\ufe0f"
- WOMAN_ELF_LIGHT_SKIN_TONE = "\U0001f9dd\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_ELF_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9dd\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_ELF_MEDIUM_SKIN_TONE = "\U0001f9dd\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_ELF_MEDIUM_DARK_SKIN_TONE = "\U0001f9dd\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_ELF_DARK_SKIN_TONE = "\U0001f9dd\U0001f3ff\u200d\u2640\ufe0f"
- MAN_ELF = "\U0001f9dd\u200d\u2642\ufe0f"
- MAN_ELF_LIGHT_SKIN_TONE = "\U0001f9dd\U0001f3fb\u200d\u2642\ufe0f"
- MAN_ELF_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9dd\U0001f3fc\u200d\u2642\ufe0f"
- MAN_ELF_MEDIUM_SKIN_TONE = "\U0001f9dd\U0001f3fd\u200d\u2642\ufe0f"
- MAN_ELF_MEDIUM_DARK_SKIN_TONE = "\U0001f9dd\U0001f3fe\u200d\u2642\ufe0f"
- MAN_ELF_DARK_SKIN_TONE = "\U0001f9dd\U0001f3ff\u200d\u2642\ufe0f"
- GENIE = "\U0001f9de"
- WOMAN_GENIE = "\U0001f9de\u200d\u2640\ufe0f"
- MAN_GENIE = "\U0001f9de\u200d\u2642\ufe0f"
- ZOMBIE = "\U0001f9df"
- ZOMBIE_LIGHT_SKIN_TONE = "\U0001f9df\U0001f3fb"
- ZOMBIE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9df\U0001f3fc"
- ZOMBIE_MEDIUM_SKIN_TONE = "\U0001f9df\U0001f3fd"
- ZOMBIE_MEDIUM_DARK_SKIN_TONE = "\U0001f9df\U0001f3fe"
- ZOMBIE_DARK_SKIN_TONE = "\U0001f9df\U0001f3ff"
- WOMAN_ZOMBIE = "\U0001f9df\u200d\u2640\ufe0f"
- MAN_ZOMBIE = "\U0001f9df\u200d\u2642\ufe0f"
- PERSON_FROWNING = "\U0001f64d"
- PERSON_FROWNING_LIGHT_SKIN_TONE = "\U0001f64d\U0001f3fb"
- PERSON_FROWNING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64d\U0001f3fc"
- PERSON_FROWNING_MEDIUM_SKIN_TONE = "\U0001f64d\U0001f3fd"
- PERSON_FROWNING_MEDIUM_DARK_SKIN_TONE = "\U0001f64d\U0001f3fe"
- PERSON_FROWNING_DARK_SKIN_TONE = "\U0001f64d\U0001f3ff"
- MAN_FROWNING = "\U0001f64d\u200d\u2642\ufe0f"
- MAN_FROWNING_LIGHT_SKIN_TONE = "\U0001f64d\U0001f3fb\u200d\u2642\ufe0f"
- MAN_FROWNING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64d\U0001f3fc\u200d\u2642\ufe0f"
- MAN_FROWNING_MEDIUM_SKIN_TONE = "\U0001f64d\U0001f3fd\u200d\u2642\ufe0f"
- MAN_FROWNING_MEDIUM_DARK_SKIN_TONE = "\U0001f64d\U0001f3fe\u200d\u2642\ufe0f"
- MAN_FROWNING_DARK_SKIN_TONE = "\U0001f64d\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_FROWNING = "\U0001f64d\u200d\u2640\ufe0f"
- WOMAN_FROWNING_LIGHT_SKIN_TONE = "\U0001f64d\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_FROWNING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64d\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_FROWNING_MEDIUM_SKIN_TONE = "\U0001f64d\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_FROWNING_MEDIUM_DARK_SKIN_TONE = "\U0001f64d\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_FROWNING_DARK_SKIN_TONE = "\U0001f64d\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_POUTING = "\U0001f64e"
- PERSON_POUTING_LIGHT_SKIN_TONE = "\U0001f64e\U0001f3fb"
- PERSON_POUTING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64e\U0001f3fc"
- PERSON_POUTING_MEDIUM_SKIN_TONE = "\U0001f64e\U0001f3fd"
- PERSON_POUTING_MEDIUM_DARK_SKIN_TONE = "\U0001f64e\U0001f3fe"
- PERSON_POUTING_DARK_SKIN_TONE = "\U0001f64e\U0001f3ff"
- MAN_POUTING = "\U0001f64e\u200d\u2642\ufe0f"
- MAN_POUTING_LIGHT_SKIN_TONE = "\U0001f64e\U0001f3fb\u200d\u2642\ufe0f"
- MAN_POUTING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64e\U0001f3fc\u200d\u2642\ufe0f"
- MAN_POUTING_MEDIUM_SKIN_TONE = "\U0001f64e\U0001f3fd\u200d\u2642\ufe0f"
- MAN_POUTING_MEDIUM_DARK_SKIN_TONE = "\U0001f64e\U0001f3fe\u200d\u2642\ufe0f"
- MAN_POUTING_DARK_SKIN_TONE = "\U0001f64e\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_POUTING = "\U0001f64e\u200d\u2640\ufe0f"
- WOMAN_POUTING_LIGHT_SKIN_TONE = "\U0001f64e\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_POUTING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64e\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_POUTING_MEDIUM_SKIN_TONE = "\U0001f64e\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_POUTING_MEDIUM_DARK_SKIN_TONE = "\U0001f64e\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_POUTING_DARK_SKIN_TONE = "\U0001f64e\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_GESTURING_NO = "\U0001f645"
- PERSON_GESTURING_NO_LIGHT_SKIN_TONE = "\U0001f645\U0001f3fb"
- PERSON_GESTURING_NO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f645\U0001f3fc"
- PERSON_GESTURING_NO_MEDIUM_SKIN_TONE = "\U0001f645\U0001f3fd"
- PERSON_GESTURING_NO_MEDIUM_DARK_SKIN_TONE = "\U0001f645\U0001f3fe"
- PERSON_GESTURING_NO_DARK_SKIN_TONE = "\U0001f645\U0001f3ff"
- MAN_GESTURING_NO = "\U0001f645\u200d\u2642\ufe0f"
- MAN_GESTURING_NO_LIGHT_SKIN_TONE = "\U0001f645\U0001f3fb\u200d\u2642\ufe0f"
- MAN_GESTURING_NO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f645\U0001f3fc\u200d\u2642\ufe0f"
- HANDSHAKE_TYPE_1_2 = "\U0001f91d\U0001f3fb"
- HANDSHAKE_TYPE_3 = "\U0001f91d\U0001f3fc"
- MAN_GESTURING_NO_MEDIUM_SKIN_TONE = "\U0001f645\U0001f3fd\u200d\u2642\ufe0f"
- HANDSHAKE_TYPE_4 = "\U0001f91d\U0001f3fd"
- HANDSHAKE_TYPE_5 = "\U0001f91d\U0001f3fe"
- MAN_GESTURING_NO_MEDIUM_DARK_SKIN_TONE = "\U0001f645\U0001f3fe\u200d\u2642\ufe0f"
- HANDSHAKE_TYPE_6 = "\U0001f91d\U0001f3ff"
- MAN_GESTURING_NO_DARK_SKIN_TONE = "\U0001f645\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_GESTURING_NO = "\U0001f645\u200d\u2640\ufe0f"
- WOMAN_GESTURING_NO_LIGHT_SKIN_TONE = "\U0001f645\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_GESTURING_NO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f645\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_GESTURING_NO_MEDIUM_SKIN_TONE = "\U0001f645\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_GESTURING_NO_MEDIUM_DARK_SKIN_TONE = "\U0001f645\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_GESTURING_NO_DARK_SKIN_TONE = "\U0001f645\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_GESTURING_OK = "\U0001f646"
- PERSON_GESTURING_OK_LIGHT_SKIN_TONE = "\U0001f646\U0001f3fb"
- PERSON_GESTURING_OK_MEDIUM_LIGHT_SKIN_TONE = "\U0001f646\U0001f3fc"
- PERSON_GESTURING_OK_MEDIUM_SKIN_TONE = "\U0001f646\U0001f3fd"
- PERSON_GESTURING_OK_MEDIUM_DARK_SKIN_TONE = "\U0001f646\U0001f3fe"
- PERSON_GESTURING_OK_DARK_SKIN_TONE = "\U0001f646\U0001f3ff"
- MAN_GESTURING_OK = "\U0001f646\u200d\u2642\ufe0f"
- MAN_GESTURING_OK_LIGHT_SKIN_TONE = "\U0001f646\U0001f3fb\u200d\u2642\ufe0f"
- MAN_GESTURING_OK_MEDIUM_LIGHT_SKIN_TONE = "\U0001f646\U0001f3fc\u200d\u2642\ufe0f"
- MAN_GESTURING_OK_MEDIUM_SKIN_TONE = "\U0001f646\U0001f3fd\u200d\u2642\ufe0f"
- MAN_GESTURING_OK_MEDIUM_DARK_SKIN_TONE = "\U0001f646\U0001f3fe\u200d\u2642\ufe0f"
- MAN_GESTURING_OK_DARK_SKIN_TONE = "\U0001f646\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_GESTURING_OK = "\U0001f646\u200d\u2640\ufe0f"
- WOMAN_GESTURING_OK_LIGHT_SKIN_TONE = "\U0001f646\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_GESTURING_OK_MEDIUM_LIGHT_SKIN_TONE = "\U0001f646\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_GESTURING_OK_MEDIUM_SKIN_TONE = "\U0001f646\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_GESTURING_OK_MEDIUM_DARK_SKIN_TONE = "\U0001f646\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_GESTURING_OK_DARK_SKIN_TONE = "\U0001f646\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_TIPPING_HAND = "\U0001f481"
- PERSON_TIPPING_HAND_LIGHT_SKIN_TONE = "\U0001f481\U0001f3fb"
- PERSON_TIPPING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f481\U0001f3fc"
- PERSON_TIPPING_HAND_MEDIUM_SKIN_TONE = "\U0001f481\U0001f3fd"
- PERSON_TIPPING_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f481\U0001f3fe"
- PERSON_TIPPING_HAND_DARK_SKIN_TONE = "\U0001f481\U0001f3ff"
- MAN_TIPPING_HAND = "\U0001f481\u200d\u2642\ufe0f"
- MAN_TIPPING_HAND_LIGHT_SKIN_TONE = "\U0001f481\U0001f3fb\u200d\u2642\ufe0f"
- MAN_TIPPING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f481\U0001f3fc\u200d\u2642\ufe0f"
- MAN_TIPPING_HAND_MEDIUM_SKIN_TONE = "\U0001f481\U0001f3fd\u200d\u2642\ufe0f"
- MAN_TIPPING_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f481\U0001f3fe\u200d\u2642\ufe0f"
- MAN_TIPPING_HAND_DARK_SKIN_TONE = "\U0001f481\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_TIPPING_HAND = "\U0001f481\u200d\u2640\ufe0f"
- WOMAN_TIPPING_HAND_LIGHT_SKIN_TONE = "\U0001f481\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_TIPPING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f481\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_TIPPING_HAND_MEDIUM_SKIN_TONE = "\U0001f481\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_TIPPING_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f481\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_TIPPING_HAND_DARK_SKIN_TONE = "\U0001f481\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_RAISING_HAND = "\U0001f64b"
- PERSON_RAISING_HAND_LIGHT_SKIN_TONE = "\U0001f64b\U0001f3fb"
- PERSON_RAISING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64b\U0001f3fc"
- PERSON_RAISING_HAND_MEDIUM_SKIN_TONE = "\U0001f64b\U0001f3fd"
- PERSON_RAISING_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f64b\U0001f3fe"
- PERSON_RAISING_HAND_DARK_SKIN_TONE = "\U0001f64b\U0001f3ff"
- MAN_RAISING_HAND = "\U0001f64b\u200d\u2642\ufe0f"
- MAN_RAISING_HAND_LIGHT_SKIN_TONE = "\U0001f64b\U0001f3fb\u200d\u2642\ufe0f"
- MAN_RAISING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64b\U0001f3fc\u200d\u2642\ufe0f"
- MAN_RAISING_HAND_MEDIUM_SKIN_TONE = "\U0001f64b\U0001f3fd\u200d\u2642\ufe0f"
- MAN_RAISING_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f64b\U0001f3fe\u200d\u2642\ufe0f"
- MAN_RAISING_HAND_DARK_SKIN_TONE = "\U0001f64b\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_RAISING_HAND = "\U0001f64b\u200d\u2640\ufe0f"
- WOMAN_RAISING_HAND_LIGHT_SKIN_TONE = "\U0001f64b\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_RAISING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64b\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_RAISING_HAND_MEDIUM_SKIN_TONE = "\U0001f64b\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_RAISING_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f64b\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_RAISING_HAND_DARK_SKIN_TONE = "\U0001f64b\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_BOWING = "\U0001f647"
- PERSON_BOWING_LIGHT_SKIN_TONE = "\U0001f647\U0001f3fb"
- PERSON_BOWING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f647\U0001f3fc"
- PERSON_BOWING_MEDIUM_SKIN_TONE = "\U0001f647\U0001f3fd"
- PERSON_BOWING_MEDIUM_DARK_SKIN_TONE = "\U0001f647\U0001f3fe"
- PERSON_BOWING_DARK_SKIN_TONE = "\U0001f647\U0001f3ff"
- MAN_BOWING = "\U0001f647\u200d\u2642\ufe0f"
- MAN_BOWING_LIGHT_SKIN_TONE = "\U0001f647\U0001f3fb\u200d\u2642\ufe0f"
- MAN_BOWING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f647\U0001f3fc\u200d\u2642\ufe0f"
- MAN_BOWING_MEDIUM_SKIN_TONE = "\U0001f647\U0001f3fd\u200d\u2642\ufe0f"
- MAN_BOWING_MEDIUM_DARK_SKIN_TONE = "\U0001f647\U0001f3fe\u200d\u2642\ufe0f"
- MAN_BOWING_DARK_SKIN_TONE = "\U0001f647\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_BOWING = "\U0001f647\u200d\u2640\ufe0f"
- WOMAN_BOWING_LIGHT_SKIN_TONE = "\U0001f647\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_BOWING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f647\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_BOWING_MEDIUM_SKIN_TONE = "\U0001f647\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_BOWING_MEDIUM_DARK_SKIN_TONE = "\U0001f647\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_BOWING_DARK_SKIN_TONE = "\U0001f647\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_FACEPALMING = "\U0001f926"
- PERSON_FACEPALMING_LIGHT_SKIN_TONE = "\U0001f926\U0001f3fb"
- PERSON_FACEPALMING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f926\U0001f3fc"
- PERSON_FACEPALMING_MEDIUM_SKIN_TONE = "\U0001f926\U0001f3fd"
- PERSON_FACEPALMING_MEDIUM_DARK_SKIN_TONE = "\U0001f926\U0001f3fe"
- PERSON_FACEPALMING_DARK_SKIN_TONE = "\U0001f926\U0001f3ff"
- MAN_FACEPALMING = "\U0001f926\u200d\u2642\ufe0f"
- MAN_FACEPALMING_LIGHT_SKIN_TONE = "\U0001f926\U0001f3fb\u200d\u2642\ufe0f"
- MAN_FACEPALMING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f926\U0001f3fc\u200d\u2642\ufe0f"
- MAN_FACEPALMING_MEDIUM_SKIN_TONE = "\U0001f926\U0001f3fd\u200d\u2642\ufe0f"
- MAN_FACEPALMING_MEDIUM_DARK_SKIN_TONE = "\U0001f926\U0001f3fe\u200d\u2642\ufe0f"
- MAN_FACEPALMING_DARK_SKIN_TONE = "\U0001f926\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_FACEPALMING = "\U0001f926\u200d\u2640\ufe0f"
- WOMAN_FACEPALMING_LIGHT_SKIN_TONE = "\U0001f926\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_FACEPALMING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f926\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_FACEPALMING_MEDIUM_SKIN_TONE = "\U0001f926\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_FACEPALMING_MEDIUM_DARK_SKIN_TONE = "\U0001f926\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_FACEPALMING_DARK_SKIN_TONE = "\U0001f926\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_SHRUGGING = "\U0001f937"
- PERSON_SHRUGGING_LIGHT_SKIN_TONE = "\U0001f937\U0001f3fb"
- PERSON_SHRUGGING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f937\U0001f3fc"
- PERSON_SHRUGGING_MEDIUM_SKIN_TONE = "\U0001f937\U0001f3fd"
- PERSON_SHRUGGING_MEDIUM_DARK_SKIN_TONE = "\U0001f937\U0001f3fe"
- PERSON_SHRUGGING_DARK_SKIN_TONE = "\U0001f937\U0001f3ff"
- MAN_SHRUGGING = "\U0001f937\u200d\u2642\ufe0f"
- MAN_SHRUGGING_LIGHT_SKIN_TONE = "\U0001f937\U0001f3fb\u200d\u2642\ufe0f"
- MAN_SHRUGGING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f937\U0001f3fc\u200d\u2642\ufe0f"
- MAN_SHRUGGING_MEDIUM_SKIN_TONE = "\U0001f937\U0001f3fd\u200d\u2642\ufe0f"
- MAN_SHRUGGING_MEDIUM_DARK_SKIN_TONE = "\U0001f937\U0001f3fe\u200d\u2642\ufe0f"
- MAN_SHRUGGING_DARK_SKIN_TONE = "\U0001f937\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_SHRUGGING = "\U0001f937\u200d\u2640\ufe0f"
- WOMAN_SHRUGGING_LIGHT_SKIN_TONE = "\U0001f937\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_SHRUGGING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f937\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_SHRUGGING_MEDIUM_SKIN_TONE = "\U0001f937\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_SHRUGGING_MEDIUM_DARK_SKIN_TONE = "\U0001f937\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_SHRUGGING_DARK_SKIN_TONE = "\U0001f937\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_GETTING_MASSAGE = "\U0001f486"
- PERSON_GETTING_MASSAGE_LIGHT_SKIN_TONE = "\U0001f486\U0001f3fb"
- PERSON_GETTING_MASSAGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f486\U0001f3fc"
- PERSON_GETTING_MASSAGE_MEDIUM_SKIN_TONE = "\U0001f486\U0001f3fd"
- PERSON_GETTING_MASSAGE_MEDIUM_DARK_SKIN_TONE = "\U0001f486\U0001f3fe"
- PERSON_GETTING_MASSAGE_DARK_SKIN_TONE = "\U0001f486\U0001f3ff"
- MAN_GETTING_MASSAGE = "\U0001f486\u200d\u2642\ufe0f"
- MAN_GETTING_MASSAGE_LIGHT_SKIN_TONE = "\U0001f486\U0001f3fb\u200d\u2642\ufe0f"
- MAN_GETTING_MASSAGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f486\U0001f3fc\u200d\u2642\ufe0f"
- MAN_GETTING_MASSAGE_MEDIUM_SKIN_TONE = "\U0001f486\U0001f3fd\u200d\u2642\ufe0f"
- MAN_GETTING_MASSAGE_MEDIUM_DARK_SKIN_TONE = "\U0001f486\U0001f3fe\u200d\u2642\ufe0f"
- MAN_GETTING_MASSAGE_DARK_SKIN_TONE = "\U0001f486\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_GETTING_MASSAGE = "\U0001f486\u200d\u2640\ufe0f"
- WOMAN_GETTING_MASSAGE_LIGHT_SKIN_TONE = "\U0001f486\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_GETTING_MASSAGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f486\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_GETTING_MASSAGE_MEDIUM_SKIN_TONE = "\U0001f486\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_GETTING_MASSAGE_MEDIUM_DARK_SKIN_TONE = "\U0001f486\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_GETTING_MASSAGE_DARK_SKIN_TONE = "\U0001f486\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_GETTING_HAIRCUT = "\U0001f487"
- PERSON_GETTING_HAIRCUT_LIGHT_SKIN_TONE = "\U0001f487\U0001f3fb"
- PERSON_GETTING_HAIRCUT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f487\U0001f3fc"
- PERSON_GETTING_HAIRCUT_MEDIUM_SKIN_TONE = "\U0001f487\U0001f3fd"
- PERSON_GETTING_HAIRCUT_MEDIUM_DARK_SKIN_TONE = "\U0001f487\U0001f3fe"
- PERSON_GETTING_HAIRCUT_DARK_SKIN_TONE = "\U0001f487\U0001f3ff"
- MAN_GETTING_HAIRCUT = "\U0001f487\u200d\u2642\ufe0f"
- MAN_GETTING_HAIRCUT_LIGHT_SKIN_TONE = "\U0001f487\U0001f3fb\u200d\u2642\ufe0f"
- MAN_GETTING_HAIRCUT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f487\U0001f3fc\u200d\u2642\ufe0f"
- MAN_GETTING_HAIRCUT_MEDIUM_SKIN_TONE = "\U0001f487\U0001f3fd\u200d\u2642\ufe0f"
- MAN_GETTING_HAIRCUT_MEDIUM_DARK_SKIN_TONE = "\U0001f487\U0001f3fe\u200d\u2642\ufe0f"
- MAN_GETTING_HAIRCUT_DARK_SKIN_TONE = "\U0001f487\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_GETTING_HAIRCUT = "\U0001f487\u200d\u2640\ufe0f"
- WOMAN_GETTING_HAIRCUT_LIGHT_SKIN_TONE = "\U0001f487\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_GETTING_HAIRCUT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f487\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_GETTING_HAIRCUT_MEDIUM_SKIN_TONE = "\U0001f487\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_GETTING_HAIRCUT_MEDIUM_DARK_SKIN_TONE = "\U0001f487\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_GETTING_HAIRCUT_DARK_SKIN_TONE = "\U0001f487\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_WALKING = "\U0001f6b6"
- PERSON_WALKING_LIGHT_SKIN_TONE = "\U0001f6b6\U0001f3fb"
- PERSON_WALKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b6\U0001f3fc"
- PERSON_WALKING_MEDIUM_SKIN_TONE = "\U0001f6b6\U0001f3fd"
- PERSON_WALKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b6\U0001f3fe"
- PERSON_WALKING_DARK_SKIN_TONE = "\U0001f6b6\U0001f3ff"
- MAN_WALKING = "\U0001f6b6\u200d\u2642\ufe0f"
- MAN_WALKING_LIGHT_SKIN_TONE = "\U0001f6b6\U0001f3fb\u200d\u2642\ufe0f"
- MAN_WALKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b6\U0001f3fc\u200d\u2642\ufe0f"
- MAN_WALKING_MEDIUM_SKIN_TONE = "\U0001f6b6\U0001f3fd\u200d\u2642\ufe0f"
- MAN_WALKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b6\U0001f3fe\u200d\u2642\ufe0f"
- MAN_WALKING_DARK_SKIN_TONE = "\U0001f6b6\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_WALKING = "\U0001f6b6\u200d\u2640\ufe0f"
- WOMAN_WALKING_LIGHT_SKIN_TONE = "\U0001f6b6\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_WALKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b6\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_WALKING_MEDIUM_SKIN_TONE = "\U0001f6b6\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_WALKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b6\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_WALKING_DARK_SKIN_TONE = "\U0001f6b6\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_RUNNING = "\U0001f3c3"
- PERSON_RUNNING_LIGHT_SKIN_TONE = "\U0001f3c3\U0001f3fb"
- PERSON_RUNNING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c3\U0001f3fc"
- PERSON_RUNNING_MEDIUM_SKIN_TONE = "\U0001f3c3\U0001f3fd"
- PERSON_RUNNING_MEDIUM_DARK_SKIN_TONE = "\U0001f3c3\U0001f3fe"
- PERSON_RUNNING_DARK_SKIN_TONE = "\U0001f3c3\U0001f3ff"
- MAN_RUNNING = "\U0001f3c3\u200d\u2642\ufe0f"
- MAN_RUNNING_LIGHT_SKIN_TONE = "\U0001f3c3\U0001f3fb\u200d\u2642\ufe0f"
- MAN_RUNNING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c3\U0001f3fc\u200d\u2642\ufe0f"
- MAN_RUNNING_MEDIUM_SKIN_TONE = "\U0001f3c3\U0001f3fd\u200d\u2642\ufe0f"
- MAN_RUNNING_MEDIUM_DARK_SKIN_TONE = "\U0001f3c3\U0001f3fe\u200d\u2642\ufe0f"
- MAN_RUNNING_DARK_SKIN_TONE = "\U0001f3c3\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_RUNNING = "\U0001f3c3\u200d\u2640\ufe0f"
- WOMAN_RUNNING_LIGHT_SKIN_TONE = "\U0001f3c3\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_RUNNING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c3\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_RUNNING_MEDIUM_SKIN_TONE = "\U0001f3c3\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_RUNNING_MEDIUM_DARK_SKIN_TONE = "\U0001f3c3\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_RUNNING_DARK_SKIN_TONE = "\U0001f3c3\U0001f3ff\u200d\u2640\ufe0f"
- WOMAN_DANCING = "\U0001f483"
- WOMAN_DANCING_LIGHT_SKIN_TONE = "\U0001f483\U0001f3fb"
- WOMAN_DANCING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f483\U0001f3fc"
- WOMAN_DANCING_MEDIUM_SKIN_TONE = "\U0001f483\U0001f3fd"
- WOMAN_DANCING_MEDIUM_DARK_SKIN_TONE = "\U0001f483\U0001f3fe"
- WOMAN_DANCING_DARK_SKIN_TONE = "\U0001f483\U0001f3ff"
- MAN_DANCING = "\U0001f57a"
- MAN_DANCING_LIGHT_SKIN_TONE = "\U0001f57a\U0001f3fb"
- MAN_DANCING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f57a\U0001f3fc"
- MAN_DANCING_MEDIUM_SKIN_TONE = "\U0001f57a\U0001f3fd"
- MAN_DANCING_MEDIUM_DARK_SKIN_TONE = "\U0001f57a\U0001f3fe"
- MAN_DANCING_DARK_SKIN_TONE = "\U0001f57a\U0001f3ff"
- PEOPLE_WITH_BUNNY_EARS = "\U0001f46f"
- MEN_WITH_BUNNY_EARS = "\U0001f46f\u200d\u2642\ufe0f"
- WOMEN_WITH_BUNNY_EARS = "\U0001f46f\u200d\u2640\ufe0f"
- PERSON_IN_STEAMY_ROOM = "\U0001f9d6"
- PERSON_IN_STEAMY_ROOM_LIGHT_SKIN_TONE = "\U0001f9d6\U0001f3fb"
- PERSON_IN_STEAMY_ROOM_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d6\U0001f3fc"
- PERSON_IN_STEAMY_ROOM_MEDIUM_SKIN_TONE = "\U0001f9d6\U0001f3fd"
- PERSON_IN_STEAMY_ROOM_MEDIUM_DARK_SKIN_TONE = "\U0001f9d6\U0001f3fe"
- PERSON_IN_STEAMY_ROOM_DARK_SKIN_TONE = "\U0001f9d6\U0001f3ff"
- WOMAN_IN_STEAMY_ROOM = "\U0001f9d6\u200d\u2640\ufe0f"
- WOMAN_IN_STEAMY_ROOM_LIGHT_SKIN_TONE = "\U0001f9d6\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_IN_STEAMY_ROOM_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d6\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_IN_STEAMY_ROOM_MEDIUM_SKIN_TONE = "\U0001f9d6\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_IN_STEAMY_ROOM_MEDIUM_DARK_SKIN_TONE = "\U0001f9d6\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_IN_STEAMY_ROOM_DARK_SKIN_TONE = "\U0001f9d6\U0001f3ff\u200d\u2640\ufe0f"
- MAN_IN_STEAMY_ROOM = "\U0001f9d6\u200d\u2642\ufe0f"
- MAN_IN_STEAMY_ROOM_LIGHT_SKIN_TONE = "\U0001f9d6\U0001f3fb\u200d\u2642\ufe0f"
- MAN_IN_STEAMY_ROOM_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d6\U0001f3fc\u200d\u2642\ufe0f"
- MAN_IN_STEAMY_ROOM_MEDIUM_SKIN_TONE = "\U0001f9d6\U0001f3fd\u200d\u2642\ufe0f"
- MAN_IN_STEAMY_ROOM_MEDIUM_DARK_SKIN_TONE = "\U0001f9d6\U0001f3fe\u200d\u2642\ufe0f"
- MAN_IN_STEAMY_ROOM_DARK_SKIN_TONE = "\U0001f9d6\U0001f3ff\u200d\u2642\ufe0f"
- PERSON_CLIMBING = "\U0001f9d7"
- PERSON_CLIMBING_LIGHT_SKIN_TONE = "\U0001f9d7\U0001f3fb"
- PERSON_CLIMBING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d7\U0001f3fc"
- PERSON_CLIMBING_MEDIUM_SKIN_TONE = "\U0001f9d7\U0001f3fd"
- PERSON_CLIMBING_MEDIUM_DARK_SKIN_TONE = "\U0001f9d7\U0001f3fe"
- PERSON_CLIMBING_DARK_SKIN_TONE = "\U0001f9d7\U0001f3ff"
- WOMAN_CLIMBING = "\U0001f9d7\u200d\u2640\ufe0f"
- WOMAN_CLIMBING_LIGHT_SKIN_TONE = "\U0001f9d7\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_CLIMBING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d7\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_CLIMBING_MEDIUM_SKIN_TONE = "\U0001f9d7\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_CLIMBING_MEDIUM_DARK_SKIN_TONE = "\U0001f9d7\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_CLIMBING_DARK_SKIN_TONE = "\U0001f9d7\U0001f3ff\u200d\u2640\ufe0f"
- MAN_CLIMBING = "\U0001f9d7\u200d\u2642\ufe0f"
- MAN_CLIMBING_LIGHT_SKIN_TONE = "\U0001f9d7\U0001f3fb\u200d\u2642\ufe0f"
- MAN_CLIMBING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d7\U0001f3fc\u200d\u2642\ufe0f"
- MAN_CLIMBING_MEDIUM_SKIN_TONE = "\U0001f9d7\U0001f3fd\u200d\u2642\ufe0f"
- MAN_CLIMBING_MEDIUM_DARK_SKIN_TONE = "\U0001f9d7\U0001f3fe\u200d\u2642\ufe0f"
- MAN_CLIMBING_DARK_SKIN_TONE = "\U0001f9d7\U0001f3ff\u200d\u2642\ufe0f"
- PERSON_IN_LOTUS_POSITION = "\U0001f9d8"
- PERSON_IN_LOTUS_POSITION_LIGHT_SKIN_TONE = "\U0001f9d8\U0001f3fb"
- PERSON_IN_LOTUS_POSITION_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d8\U0001f3fc"
- PERSON_IN_LOTUS_POSITION_MEDIUM_SKIN_TONE = "\U0001f9d8\U0001f3fd"
- PERSON_IN_LOTUS_POSITION_MEDIUM_DARK_SKIN_TONE = "\U0001f9d8\U0001f3fe"
- PERSON_IN_LOTUS_POSITION_DARK_SKIN_TONE = "\U0001f9d8\U0001f3ff"
- WOMAN_IN_LOTUS_POSITION = "\U0001f9d8\u200d\u2640\ufe0f"
- WOMAN_IN_LOTUS_POSITION_LIGHT_SKIN_TONE = "\U0001f9d8\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_IN_LOTUS_POSITION_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d8\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_IN_LOTUS_POSITION_MEDIUM_SKIN_TONE = "\U0001f9d8\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_IN_LOTUS_POSITION_MEDIUM_DARK_SKIN_TONE = "\U0001f9d8\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_IN_LOTUS_POSITION_DARK_SKIN_TONE = "\U0001f9d8\U0001f3ff\u200d\u2640\ufe0f"
- MAN_IN_LOTUS_POSITION = "\U0001f9d8\u200d\u2642\ufe0f"
- MAN_IN_LOTUS_POSITION_LIGHT_SKIN_TONE = "\U0001f9d8\U0001f3fb\u200d\u2642\ufe0f"
- MAN_IN_LOTUS_POSITION_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d8\U0001f3fc\u200d\u2642\ufe0f"
- MAN_IN_LOTUS_POSITION_MEDIUM_SKIN_TONE = "\U0001f9d8\U0001f3fd\u200d\u2642\ufe0f"
- MAN_IN_LOTUS_POSITION_MEDIUM_DARK_SKIN_TONE = "\U0001f9d8\U0001f3fe\u200d\u2642\ufe0f"
- MAN_IN_LOTUS_POSITION_DARK_SKIN_TONE = "\U0001f9d8\U0001f3ff\u200d\u2642\ufe0f"
- PERSON_TAKING_BATH = "\U0001f6c0"
- PERSON_TAKING_BATH_LIGHT_SKIN_TONE = "\U0001f6c0\U0001f3fb"
- PERSON_TAKING_BATH_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6c0\U0001f3fc"
- PERSON_TAKING_BATH_MEDIUM_SKIN_TONE = "\U0001f6c0\U0001f3fd"
- PERSON_TAKING_BATH_MEDIUM_DARK_SKIN_TONE = "\U0001f6c0\U0001f3fe"
- PERSON_TAKING_BATH_DARK_SKIN_TONE = "\U0001f6c0\U0001f3ff"
- PERSON_IN_BED = "\U0001f6cc"
- PERSON_IN_BED_LIGHT_SKIN_TONE = "\U0001f6cc\U0001f3fb"
- PERSON_IN_BED_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6cc\U0001f3fc"
- PERSON_IN_BED_MEDIUM_SKIN_TONE = "\U0001f6cc\U0001f3fd"
- PERSON_IN_BED_MEDIUM_DARK_SKIN_TONE = "\U0001f6cc\U0001f3fe"
- PERSON_IN_BED_DARK_SKIN_TONE = "\U0001f6cc\U0001f3ff"
- MAN_IN_SUIT_LEVITATING = "\U0001f574\ufe0f"
- MAN_IN_SUIT_LEVITATING_LIGHT_SKIN_TONE = "\U0001f574\U0001f3fb"
- MAN_IN_SUIT_LEVITATING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f574\U0001f3fc"
- MAN_IN_SUIT_LEVITATING_MEDIUM_SKIN_TONE = "\U0001f574\U0001f3fd"
- MAN_IN_SUIT_LEVITATING_MEDIUM_DARK_SKIN_TONE = "\U0001f574\U0001f3fe"
- MAN_IN_SUIT_LEVITATING_DARK_SKIN_TONE = "\U0001f574\U0001f3ff"
- SPEAKING_HEAD = "\U0001f5e3\ufe0f"
- BUST_IN_SILHOUETTE = "\U0001f464"
- BUSTS_IN_SILHOUETTE = "\U0001f465"
- PERSON_FENCING = "\U0001f93a"
- HORSE_RACING = "\U0001f3c7"
- HORSE_RACING_LIGHT_SKIN_TONE = "\U0001f3c7\U0001f3fb"
- HORSE_RACING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c7\U0001f3fc"
- HORSE_RACING_MEDIUM_SKIN_TONE = "\U0001f3c7\U0001f3fd"
- HORSE_RACING_MEDIUM_DARK_SKIN_TONE = "\U0001f3c7\U0001f3fe"
- HORSE_RACING_DARK_SKIN_TONE = "\U0001f3c7\U0001f3ff"
- SKIER = "\u26f7\ufe0f"
- SNOWBOARDER = "\U0001f3c2"
- SNOWBOARDER_LIGHT_SKIN_TONE = "\U0001f3c2\U0001f3fb"
- SNOWBOARDER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c2\U0001f3fc"
- SNOWBOARDER_MEDIUM_SKIN_TONE = "\U0001f3c2\U0001f3fd"
- SNOWBOARDER_MEDIUM_DARK_SKIN_TONE = "\U0001f3c2\U0001f3fe"
- SNOWBOARDER_DARK_SKIN_TONE = "\U0001f3c2\U0001f3ff"
- PERSON_GOLFING = "\U0001f3cc\ufe0f"
- PERSON_GOLFING_LIGHT_SKIN_TONE = "\U0001f3cc\U0001f3fb"
- PERSON_GOLFING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3cc\U0001f3fc"
- PERSON_GOLFING_MEDIUM_SKIN_TONE = "\U0001f3cc\U0001f3fd"
- PERSON_GOLFING_MEDIUM_DARK_SKIN_TONE = "\U0001f3cc\U0001f3fe"
- PERSON_GOLFING_DARK_SKIN_TONE = "\U0001f3cc\U0001f3ff"
- MAN_GOLFING = "\U0001f3cc\ufe0f\u200d\u2642\ufe0f"
- MAN_GOLFING_LIGHT_SKIN_TONE = "\U0001f3cc\U0001f3fb\u200d\u2642\ufe0f"
- MAN_GOLFING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3cc\U0001f3fc\u200d\u2642\ufe0f"
- MAN_GOLFING_MEDIUM_SKIN_TONE = "\U0001f3cc\U0001f3fd\u200d\u2642\ufe0f"
- MAN_GOLFING_MEDIUM_DARK_SKIN_TONE = "\U0001f3cc\U0001f3fe\u200d\u2642\ufe0f"
- MAN_GOLFING_DARK_SKIN_TONE = "\U0001f3cc\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_GOLFING = "\U0001f3cc\ufe0f\u200d\u2640\ufe0f"
- WOMAN_GOLFING_LIGHT_SKIN_TONE = "\U0001f3cc\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_GOLFING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3cc\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_GOLFING_MEDIUM_SKIN_TONE = "\U0001f3cc\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_GOLFING_MEDIUM_DARK_SKIN_TONE = "\U0001f3cc\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_GOLFING_DARK_SKIN_TONE = "\U0001f3cc\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_SURFING = "\U0001f3c4"
- PERSON_SURFING_LIGHT_SKIN_TONE = "\U0001f3c4\U0001f3fb"
- PERSON_SURFING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c4\U0001f3fc"
- PERSON_SURFING_MEDIUM_SKIN_TONE = "\U0001f3c4\U0001f3fd"
- PERSON_SURFING_MEDIUM_DARK_SKIN_TONE = "\U0001f3c4\U0001f3fe"
- PERSON_SURFING_DARK_SKIN_TONE = "\U0001f3c4\U0001f3ff"
- MAN_SURFING = "\U0001f3c4\u200d\u2642\ufe0f"
- MAN_SURFING_LIGHT_SKIN_TONE = "\U0001f3c4\U0001f3fb\u200d\u2642\ufe0f"
- MAN_SURFING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c4\U0001f3fc\u200d\u2642\ufe0f"
- MAN_SURFING_MEDIUM_SKIN_TONE = "\U0001f3c4\U0001f3fd\u200d\u2642\ufe0f"
- MAN_SURFING_MEDIUM_DARK_SKIN_TONE = "\U0001f3c4\U0001f3fe\u200d\u2642\ufe0f"
- MAN_SURFING_DARK_SKIN_TONE = "\U0001f3c4\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_SURFING = "\U0001f3c4\u200d\u2640\ufe0f"
- WOMAN_SURFING_LIGHT_SKIN_TONE = "\U0001f3c4\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_SURFING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c4\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_SURFING_MEDIUM_SKIN_TONE = "\U0001f3c4\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_SURFING_MEDIUM_DARK_SKIN_TONE = "\U0001f3c4\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_SURFING_DARK_SKIN_TONE = "\U0001f3c4\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_ROWING_BOAT = "\U0001f6a3"
- PERSON_ROWING_BOAT_LIGHT_SKIN_TONE = "\U0001f6a3\U0001f3fb"
- PERSON_ROWING_BOAT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6a3\U0001f3fc"
- PERSON_ROWING_BOAT_MEDIUM_SKIN_TONE = "\U0001f6a3\U0001f3fd"
- PERSON_ROWING_BOAT_MEDIUM_DARK_SKIN_TONE = "\U0001f6a3\U0001f3fe"
- PERSON_ROWING_BOAT_DARK_SKIN_TONE = "\U0001f6a3\U0001f3ff"
- MAN_ROWING_BOAT = "\U0001f6a3\u200d\u2642\ufe0f"
- MAN_ROWING_BOAT_LIGHT_SKIN_TONE = "\U0001f6a3\U0001f3fb\u200d\u2642\ufe0f"
- MAN_ROWING_BOAT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6a3\U0001f3fc\u200d\u2642\ufe0f"
- MAN_ROWING_BOAT_MEDIUM_SKIN_TONE = "\U0001f6a3\U0001f3fd\u200d\u2642\ufe0f"
- MAN_ROWING_BOAT_MEDIUM_DARK_SKIN_TONE = "\U0001f6a3\U0001f3fe\u200d\u2642\ufe0f"
- MAN_ROWING_BOAT_DARK_SKIN_TONE = "\U0001f6a3\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_ROWING_BOAT = "\U0001f6a3\u200d\u2640\ufe0f"
- WOMAN_ROWING_BOAT_LIGHT_SKIN_TONE = "\U0001f6a3\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_ROWING_BOAT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6a3\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_ROWING_BOAT_MEDIUM_SKIN_TONE = "\U0001f6a3\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_ROWING_BOAT_MEDIUM_DARK_SKIN_TONE = "\U0001f6a3\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_ROWING_BOAT_DARK_SKIN_TONE = "\U0001f6a3\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_SWIMMING = "\U0001f3ca"
- PERSON_SWIMMING_LIGHT_SKIN_TONE = "\U0001f3ca\U0001f3fb"
- PERSON_SWIMMING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3ca\U0001f3fc"
- PERSON_SWIMMING_MEDIUM_SKIN_TONE = "\U0001f3ca\U0001f3fd"
- PERSON_SWIMMING_MEDIUM_DARK_SKIN_TONE = "\U0001f3ca\U0001f3fe"
- PERSON_SWIMMING_DARK_SKIN_TONE = "\U0001f3ca\U0001f3ff"
- MAN_SWIMMING = "\U0001f3ca\u200d\u2642\ufe0f"
- MAN_SWIMMING_LIGHT_SKIN_TONE = "\U0001f3ca\U0001f3fb\u200d\u2642\ufe0f"
- MAN_SWIMMING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3ca\U0001f3fc\u200d\u2642\ufe0f"
- MAN_SWIMMING_MEDIUM_SKIN_TONE = "\U0001f3ca\U0001f3fd\u200d\u2642\ufe0f"
- MAN_SWIMMING_MEDIUM_DARK_SKIN_TONE = "\U0001f3ca\U0001f3fe\u200d\u2642\ufe0f"
- MAN_SWIMMING_DARK_SKIN_TONE = "\U0001f3ca\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_SWIMMING = "\U0001f3ca\u200d\u2640\ufe0f"
- WOMAN_SWIMMING_LIGHT_SKIN_TONE = "\U0001f3ca\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_SWIMMING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3ca\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_SWIMMING_MEDIUM_SKIN_TONE = "\U0001f3ca\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_SWIMMING_MEDIUM_DARK_SKIN_TONE = "\U0001f3ca\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_SWIMMING_DARK_SKIN_TONE = "\U0001f3ca\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_BOUNCING_BALL = "\u26f9\ufe0f"
- PERSON_BOUNCING_BALL_LIGHT_SKIN_TONE = "\u26f9\U0001f3fb"
- PERSON_BOUNCING_BALL_MEDIUM_LIGHT_SKIN_TONE = "\u26f9\U0001f3fc"
- PERSON_BOUNCING_BALL_MEDIUM_SKIN_TONE = "\u26f9\U0001f3fd"
- PERSON_BOUNCING_BALL_MEDIUM_DARK_SKIN_TONE = "\u26f9\U0001f3fe"
- PERSON_BOUNCING_BALL_DARK_SKIN_TONE = "\u26f9\U0001f3ff"
- MAN_BOUNCING_BALL = "\u26f9\ufe0f\u200d\u2642\ufe0f"
- MAN_BOUNCING_BALL_LIGHT_SKIN_TONE = "\u26f9\U0001f3fb\u200d\u2642\ufe0f"
- MAN_BOUNCING_BALL_MEDIUM_LIGHT_SKIN_TONE = "\u26f9\U0001f3fc\u200d\u2642\ufe0f"
- MAN_BOUNCING_BALL_MEDIUM_SKIN_TONE = "\u26f9\U0001f3fd\u200d\u2642\ufe0f"
- MAN_BOUNCING_BALL_MEDIUM_DARK_SKIN_TONE = "\u26f9\U0001f3fe\u200d\u2642\ufe0f"
- MAN_BOUNCING_BALL_DARK_SKIN_TONE = "\u26f9\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_BOUNCING_BALL = "\u26f9\ufe0f\u200d\u2640\ufe0f"
- WOMAN_BOUNCING_BALL_LIGHT_SKIN_TONE = "\u26f9\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_BOUNCING_BALL_MEDIUM_LIGHT_SKIN_TONE = "\u26f9\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_BOUNCING_BALL_MEDIUM_SKIN_TONE = "\u26f9\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_BOUNCING_BALL_MEDIUM_DARK_SKIN_TONE = "\u26f9\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_BOUNCING_BALL_DARK_SKIN_TONE = "\u26f9\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_LIFTING_WEIGHTS = "\U0001f3cb\ufe0f"
- PERSON_LIFTING_WEIGHTS_LIGHT_SKIN_TONE = "\U0001f3cb\U0001f3fb"
- PERSON_LIFTING_WEIGHTS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3cb\U0001f3fc"
- PERSON_LIFTING_WEIGHTS_MEDIUM_SKIN_TONE = "\U0001f3cb\U0001f3fd"
- PERSON_LIFTING_WEIGHTS_MEDIUM_DARK_SKIN_TONE = "\U0001f3cb\U0001f3fe"
- PERSON_LIFTING_WEIGHTS_DARK_SKIN_TONE = "\U0001f3cb\U0001f3ff"
- MAN_LIFTING_WEIGHTS = "\U0001f3cb\ufe0f\u200d\u2642\ufe0f"
- MAN_LIFTING_WEIGHTS_LIGHT_SKIN_TONE = "\U0001f3cb\U0001f3fb\u200d\u2642\ufe0f"
- MAN_LIFTING_WEIGHTS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3cb\U0001f3fc\u200d\u2642\ufe0f"
- MAN_LIFTING_WEIGHTS_MEDIUM_SKIN_TONE = "\U0001f3cb\U0001f3fd\u200d\u2642\ufe0f"
- MAN_LIFTING_WEIGHTS_MEDIUM_DARK_SKIN_TONE = "\U0001f3cb\U0001f3fe\u200d\u2642\ufe0f"
- MAN_LIFTING_WEIGHTS_DARK_SKIN_TONE = "\U0001f3cb\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_LIFTING_WEIGHTS = "\U0001f3cb\ufe0f\u200d\u2640\ufe0f"
- WOMAN_LIFTING_WEIGHTS_LIGHT_SKIN_TONE = "\U0001f3cb\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_LIFTING_WEIGHTS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3cb\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_LIFTING_WEIGHTS_MEDIUM_SKIN_TONE = "\U0001f3cb\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_LIFTING_WEIGHTS_MEDIUM_DARK_SKIN_TONE = "\U0001f3cb\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_LIFTING_WEIGHTS_DARK_SKIN_TONE = "\U0001f3cb\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_BIKING = "\U0001f6b4"
- PERSON_BIKING_LIGHT_SKIN_TONE = "\U0001f6b4\U0001f3fb"
- PERSON_BIKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b4\U0001f3fc"
- PERSON_BIKING_MEDIUM_SKIN_TONE = "\U0001f6b4\U0001f3fd"
- PERSON_BIKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b4\U0001f3fe"
- PERSON_BIKING_DARK_SKIN_TONE = "\U0001f6b4\U0001f3ff"
- MAN_BIKING = "\U0001f6b4\u200d\u2642\ufe0f"
- MAN_BIKING_LIGHT_SKIN_TONE = "\U0001f6b4\U0001f3fb\u200d\u2642\ufe0f"
- MAN_BIKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b4\U0001f3fc\u200d\u2642\ufe0f"
- MAN_BIKING_MEDIUM_SKIN_TONE = "\U0001f6b4\U0001f3fd\u200d\u2642\ufe0f"
- MAN_BIKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b4\U0001f3fe\u200d\u2642\ufe0f"
- MAN_BIKING_DARK_SKIN_TONE = "\U0001f6b4\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_BIKING = "\U0001f6b4\u200d\u2640\ufe0f"
- WOMAN_BIKING_LIGHT_SKIN_TONE = "\U0001f6b4\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_BIKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b4\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_BIKING_MEDIUM_SKIN_TONE = "\U0001f6b4\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_BIKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b4\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_BIKING_DARK_SKIN_TONE = "\U0001f6b4\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_MOUNTAIN_BIKING = "\U0001f6b5"
- PERSON_MOUNTAIN_BIKING_LIGHT_SKIN_TONE = "\U0001f6b5\U0001f3fb"
- PERSON_MOUNTAIN_BIKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b5\U0001f3fc"
- PERSON_MOUNTAIN_BIKING_MEDIUM_SKIN_TONE = "\U0001f6b5\U0001f3fd"
- PERSON_MOUNTAIN_BIKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b5\U0001f3fe"
- PERSON_MOUNTAIN_BIKING_DARK_SKIN_TONE = "\U0001f6b5\U0001f3ff"
- MAN_MOUNTAIN_BIKING = "\U0001f6b5\u200d\u2642\ufe0f"
- MAN_MOUNTAIN_BIKING_LIGHT_SKIN_TONE = "\U0001f6b5\U0001f3fb\u200d\u2642\ufe0f"
- MAN_MOUNTAIN_BIKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b5\U0001f3fc\u200d\u2642\ufe0f"
- MAN_MOUNTAIN_BIKING_MEDIUM_SKIN_TONE = "\U0001f6b5\U0001f3fd\u200d\u2642\ufe0f"
- MAN_MOUNTAIN_BIKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b5\U0001f3fe\u200d\u2642\ufe0f"
- MAN_MOUNTAIN_BIKING_DARK_SKIN_TONE = "\U0001f6b5\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_MOUNTAIN_BIKING = "\U0001f6b5\u200d\u2640\ufe0f"
- WOMAN_MOUNTAIN_BIKING_LIGHT_SKIN_TONE = "\U0001f6b5\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_MOUNTAIN_BIKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b5\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_MOUNTAIN_BIKING_MEDIUM_SKIN_TONE = "\U0001f6b5\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_MOUNTAIN_BIKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b5\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_MOUNTAIN_BIKING_DARK_SKIN_TONE = "\U0001f6b5\U0001f3ff\u200d\u2640\ufe0f"
- RACING_CAR = "\U0001f3ce\ufe0f"
- MOTORCYCLE = "\U0001f3cd\ufe0f"
- PERSON_CARTWHEELING = "\U0001f938"
- PERSON_CARTWHEELING_LIGHT_SKIN_TONE = "\U0001f938\U0001f3fb"
- PERSON_CARTWHEELING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f938\U0001f3fc"
- PERSON_CARTWHEELING_MEDIUM_SKIN_TONE = "\U0001f938\U0001f3fd"
- WRESTLERS_TYPE_1_2 = "\U0001f93c\U0001f3fb"
- PERSON_CARTWHEELING_MEDIUM_DARK_SKIN_TONE = "\U0001f938\U0001f3fe"
- WRESTLERS_TYPE_3 = "\U0001f93c\U0001f3fc"
- PERSON_CARTWHEELING_DARK_SKIN_TONE = "\U0001f938\U0001f3ff"
- MAN_CARTWHEELING = "\U0001f938\u200d\u2642\ufe0f"
- WRESTLERS_TYPE_4 = "\U0001f93c\U0001f3fd"
- WRESTLERS_TYPE_5 = "\U0001f93c\U0001f3fe"
- MAN_CARTWHEELING_LIGHT_SKIN_TONE = "\U0001f938\U0001f3fb\u200d\u2642\ufe0f"
- WRESTLERS_TYPE_6 = "\U0001f93c\U0001f3ff"
- MAN_CARTWHEELING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f938\U0001f3fc\u200d\u2642\ufe0f"
- MEN_WRESTLING_TYPE_1_2 = "\U0001f93c\U0001f3fb\u200d\u2642\ufe0f"
- MEN_WRESTLING_TYPE_3 = "\U0001f93c\U0001f3fc\u200d\u2642\ufe0f"
- MEN_WRESTLING_TYPE_4 = "\U0001f93c\U0001f3fd\u200d\u2642\ufe0f"
- MAN_CARTWHEELING_MEDIUM_SKIN_TONE = "\U0001f938\U0001f3fd\u200d\u2642\ufe0f"
- MEN_WRESTLING_TYPE_5 = "\U0001f93c\U0001f3fe\u200d\u2642\ufe0f"
- MEN_WRESTLING_TYPE_6 = "\U0001f93c\U0001f3ff\u200d\u2642\ufe0f"
- MAN_CARTWHEELING_MEDIUM_DARK_SKIN_TONE = "\U0001f938\U0001f3fe\u200d\u2642\ufe0f"
- WOMEN_WRESTLING_TYPE_1_2 = "\U0001f93c\U0001f3fb\u200d\u2640\ufe0f"
- MAN_CARTWHEELING_DARK_SKIN_TONE = "\U0001f938\U0001f3ff\u200d\u2642\ufe0f"
- WOMEN_WRESTLING_TYPE_3 = "\U0001f93c\U0001f3fc\u200d\u2640\ufe0f"
- WOMEN_WRESTLING_TYPE_4 = "\U0001f93c\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_CARTWHEELING = "\U0001f938\u200d\u2640\ufe0f"
- WOMEN_WRESTLING_TYPE_5 = "\U0001f93c\U0001f3fe\u200d\u2640\ufe0f"
- WOMEN_WRESTLING_TYPE_6 = "\U0001f93c\U0001f3ff\u200d\u2640\ufe0f"
- WOMAN_CARTWHEELING_LIGHT_SKIN_TONE = "\U0001f938\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_CARTWHEELING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f938\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_CARTWHEELING_MEDIUM_SKIN_TONE = "\U0001f938\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_CARTWHEELING_MEDIUM_DARK_SKIN_TONE = "\U0001f938\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_CARTWHEELING_DARK_SKIN_TONE = "\U0001f938\U0001f3ff\u200d\u2640\ufe0f"
- PEOPLE_WRESTLING = "\U0001f93c"
- MEN_WRESTLING = "\U0001f93c\u200d\u2642\ufe0f"
- WOMEN_WRESTLING = "\U0001f93c\u200d\u2640\ufe0f"
- PERSON_PLAYING_WATER_POLO = "\U0001f93d"
- PERSON_PLAYING_WATER_POLO_LIGHT_SKIN_TONE = "\U0001f93d\U0001f3fb"
- PERSON_PLAYING_WATER_POLO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f93d\U0001f3fc"
- PERSON_PLAYING_WATER_POLO_MEDIUM_SKIN_TONE = "\U0001f93d\U0001f3fd"
- PERSON_PLAYING_WATER_POLO_MEDIUM_DARK_SKIN_TONE = "\U0001f93d\U0001f3fe"
- PERSON_PLAYING_WATER_POLO_DARK_SKIN_TONE = "\U0001f93d\U0001f3ff"
- MAN_PLAYING_WATER_POLO = "\U0001f93d\u200d\u2642\ufe0f"
- MAN_PLAYING_WATER_POLO_LIGHT_SKIN_TONE = "\U0001f93d\U0001f3fb\u200d\u2642\ufe0f"
- MAN_PLAYING_WATER_POLO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f93d\U0001f3fc\u200d\u2642\ufe0f"
- MAN_PLAYING_WATER_POLO_MEDIUM_SKIN_TONE = "\U0001f93d\U0001f3fd\u200d\u2642\ufe0f"
- MAN_PLAYING_WATER_POLO_MEDIUM_DARK_SKIN_TONE = "\U0001f93d\U0001f3fe\u200d\u2642\ufe0f"
- MAN_PLAYING_WATER_POLO_DARK_SKIN_TONE = "\U0001f93d\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_PLAYING_WATER_POLO = "\U0001f93d\u200d\u2640\ufe0f"
- WOMAN_PLAYING_WATER_POLO_LIGHT_SKIN_TONE = "\U0001f93d\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_PLAYING_WATER_POLO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f93d\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_PLAYING_WATER_POLO_MEDIUM_SKIN_TONE = "\U0001f93d\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_PLAYING_WATER_POLO_MEDIUM_DARK_SKIN_TONE = "\U0001f93d\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_PLAYING_WATER_POLO_DARK_SKIN_TONE = "\U0001f93d\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_PLAYING_HANDBALL = "\U0001f93e"
- PERSON_PLAYING_HANDBALL_LIGHT_SKIN_TONE = "\U0001f93e\U0001f3fb"
- PERSON_PLAYING_HANDBALL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f93e\U0001f3fc"
- PERSON_PLAYING_HANDBALL_MEDIUM_SKIN_TONE = "\U0001f93e\U0001f3fd"
- PERSON_PLAYING_HANDBALL_MEDIUM_DARK_SKIN_TONE = "\U0001f93e\U0001f3fe"
- PERSON_PLAYING_HANDBALL_DARK_SKIN_TONE = "\U0001f93e\U0001f3ff"
- MAN_PLAYING_HANDBALL = "\U0001f93e\u200d\u2642\ufe0f"
- MAN_PLAYING_HANDBALL_LIGHT_SKIN_TONE = "\U0001f93e\U0001f3fb\u200d\u2642\ufe0f"
- MAN_PLAYING_HANDBALL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f93e\U0001f3fc\u200d\u2642\ufe0f"
- MAN_PLAYING_HANDBALL_MEDIUM_SKIN_TONE = "\U0001f93e\U0001f3fd\u200d\u2642\ufe0f"
- MAN_PLAYING_HANDBALL_MEDIUM_DARK_SKIN_TONE = "\U0001f93e\U0001f3fe\u200d\u2642\ufe0f"
- MAN_PLAYING_HANDBALL_DARK_SKIN_TONE = "\U0001f93e\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_PLAYING_HANDBALL = "\U0001f93e\u200d\u2640\ufe0f"
- WOMAN_PLAYING_HANDBALL_LIGHT_SKIN_TONE = "\U0001f93e\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_PLAYING_HANDBALL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f93e\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_PLAYING_HANDBALL_MEDIUM_SKIN_TONE = "\U0001f93e\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_PLAYING_HANDBALL_MEDIUM_DARK_SKIN_TONE = "\U0001f93e\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_PLAYING_HANDBALL_DARK_SKIN_TONE = "\U0001f93e\U0001f3ff\u200d\u2640\ufe0f"
- PERSON_JUGGLING = "\U0001f939"
- PERSON_JUGGLING_LIGHT_SKIN_TONE = "\U0001f939\U0001f3fb"
- PERSON_JUGGLING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f939\U0001f3fc"
- PERSON_JUGGLING_MEDIUM_SKIN_TONE = "\U0001f939\U0001f3fd"
- PERSON_JUGGLING_MEDIUM_DARK_SKIN_TONE = "\U0001f939\U0001f3fe"
- PERSON_JUGGLING_DARK_SKIN_TONE = "\U0001f939\U0001f3ff"
- MAN_JUGGLING = "\U0001f939\u200d\u2642\ufe0f"
- MAN_JUGGLING_LIGHT_SKIN_TONE = "\U0001f939\U0001f3fb\u200d\u2642\ufe0f"
- MAN_JUGGLING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f939\U0001f3fc\u200d\u2642\ufe0f"
- MAN_JUGGLING_MEDIUM_SKIN_TONE = "\U0001f939\U0001f3fd\u200d\u2642\ufe0f"
- MAN_JUGGLING_MEDIUM_DARK_SKIN_TONE = "\U0001f939\U0001f3fe\u200d\u2642\ufe0f"
- MAN_JUGGLING_DARK_SKIN_TONE = "\U0001f939\U0001f3ff\u200d\u2642\ufe0f"
- WOMAN_JUGGLING = "\U0001f939\u200d\u2640\ufe0f"
- WOMAN_JUGGLING_LIGHT_SKIN_TONE = "\U0001f939\U0001f3fb\u200d\u2640\ufe0f"
- WOMAN_JUGGLING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f939\U0001f3fc\u200d\u2640\ufe0f"
- WOMAN_JUGGLING_MEDIUM_SKIN_TONE = "\U0001f939\U0001f3fd\u200d\u2640\ufe0f"
- WOMAN_JUGGLING_MEDIUM_DARK_SKIN_TONE = "\U0001f939\U0001f3fe\u200d\u2640\ufe0f"
- WOMAN_JUGGLING_DARK_SKIN_TONE = "\U0001f939\U0001f3ff\u200d\u2640\ufe0f"
- MAN_AND_WOMAN_HOLDING_HANDS = "\U0001f46b"
- TWO_MEN_HOLDING_HANDS = "\U0001f46c"
- TWO_WOMEN_HOLDING_HANDS = "\U0001f46d"
- KISS = "\U0001f48f"
- KISS_WOMAN_MAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468"
- KISS_MAN_MAN = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468"
- KISS_WOMAN_WOMAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469"
- COUPLE_WITH_HEART = "\U0001f491"
- COUPLE_WITH_HEART_WOMAN_MAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f468"
- COUPLE_WITH_HEART_MAN_MAN = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f468"
- COUPLE_WITH_HEART_WOMAN_WOMAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f469"
- FAMILY = "\U0001f46a"
- FAMILY_MAN_WOMAN_BOY = "\U0001f468\u200d\U0001f469\u200d\U0001f466"
- FAMILY_MAN_WOMAN_GIRL = "\U0001f468\u200d\U0001f469\u200d\U0001f467"
- FAMILY_MAN_WOMAN_GIRL_BOY = "\U0001f468\u200d\U0001f469\u200d\U0001f467\u200d\U0001f466"
- FAMILY_MAN_WOMAN_BOY_BOY = "\U0001f468\u200d\U0001f469\u200d\U0001f466\u200d\U0001f466"
- FAMILY_MAN_WOMAN_GIRL_GIRL = "\U0001f468\u200d\U0001f469\u200d\U0001f467\u200d\U0001f467"
- FAMILY_MAN_MAN_BOY = "\U0001f468\u200d\U0001f468\u200d\U0001f466"
- FAMILY_MAN_MAN_GIRL = "\U0001f468\u200d\U0001f468\u200d\U0001f467"
- FAMILY_MAN_MAN_GIRL_BOY = "\U0001f468\u200d\U0001f468\u200d\U0001f467\u200d\U0001f466"
- FAMILY_MAN_MAN_BOY_BOY = "\U0001f468\u200d\U0001f468\u200d\U0001f466\u200d\U0001f466"
- FAMILY_MAN_MAN_GIRL_GIRL = "\U0001f468\u200d\U0001f468\u200d\U0001f467\u200d\U0001f467"
- FAMILY_WOMAN_WOMAN_BOY = "\U0001f469\u200d\U0001f469\u200d\U0001f466"
- FAMILY_WOMAN_WOMAN_GIRL = "\U0001f469\u200d\U0001f469\u200d\U0001f467"
- FAMILY_WOMAN_WOMAN_GIRL_BOY = "\U0001f469\u200d\U0001f469\u200d\U0001f467\u200d\U0001f466"
- FAMILY_WOMAN_WOMAN_BOY_BOY = "\U0001f469\u200d\U0001f469\u200d\U0001f466\u200d\U0001f466"
- FAMILY_WOMAN_WOMAN_GIRL_GIRL = "\U0001f469\u200d\U0001f469\u200d\U0001f467\u200d\U0001f467"
- FAMILY_MAN_BOY = "\U0001f468\u200d\U0001f466"
- FAMILY_MAN_BOY_BOY = "\U0001f468\u200d\U0001f466\u200d\U0001f466"
- FAMILY_MAN_GIRL = "\U0001f468\u200d\U0001f467"
- FAMILY_MAN_GIRL_BOY = "\U0001f468\u200d\U0001f467\u200d\U0001f466"
- FAMILY_MAN_GIRL_GIRL = "\U0001f468\u200d\U0001f467\u200d\U0001f467"
- FAMILY_WOMAN_BOY = "\U0001f469\u200d\U0001f466"
- FAMILY_WOMAN_BOY_BOY = "\U0001f469\u200d\U0001f466\u200d\U0001f466"
- FAMILY_WOMAN_GIRL = "\U0001f469\u200d\U0001f467"
- FAMILY_WOMAN_GIRL_BOY = "\U0001f469\u200d\U0001f467\u200d\U0001f466"
- FAMILY_WOMAN_GIRL_GIRL = "\U0001f469\u200d\U0001f467\u200d\U0001f467"
- SELFIE = "\U0001f933"
- SELFIE_LIGHT_SKIN_TONE = "\U0001f933\U0001f3fb"
- SELFIE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f933\U0001f3fc"
- SELFIE_MEDIUM_SKIN_TONE = "\U0001f933\U0001f3fd"
- SELFIE_MEDIUM_DARK_SKIN_TONE = "\U0001f933\U0001f3fe"
- SELFIE_DARK_SKIN_TONE = "\U0001f933\U0001f3ff"
- FLEXED_BICEPS = "\U0001f4aa"
- FLEXED_BICEPS_LIGHT_SKIN_TONE = "\U0001f4aa\U0001f3fb"
- FLEXED_BICEPS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f4aa\U0001f3fc"
- FLEXED_BICEPS_MEDIUM_SKIN_TONE = "\U0001f4aa\U0001f3fd"
- FLEXED_BICEPS_MEDIUM_DARK_SKIN_TONE = "\U0001f4aa\U0001f3fe"
- FLEXED_BICEPS_DARK_SKIN_TONE = "\U0001f4aa\U0001f3ff"
- LEG = "\U0001f9b5"
- LEG_LIGHT_SKIN_TONE = "\U0001f9b5\U0001f3fb"
- LEG_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b5\U0001f3fc"
- LEG_MEDIUM_SKIN_TONE = "\U0001f9b5\U0001f3fd"
- LEG_MEDIUM_DARK_SKIN_TONE = "\U0001f9b5\U0001f3fe"
- LEG_DARK_SKIN_TONE = "\U0001f9b5\U0001f3ff"
- FOOT = "\U0001f9b6"
- FOOT_LIGHT_SKIN_TONE = "\U0001f9b6\U0001f3fb"
- FOOT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b6\U0001f3fc"
- FOOT_MEDIUM_SKIN_TONE = "\U0001f9b6\U0001f3fd"
- FOOT_MEDIUM_DARK_SKIN_TONE = "\U0001f9b6\U0001f3fe"
- FOOT_DARK_SKIN_TONE = "\U0001f9b6\U0001f3ff"
- BACKHAND_INDEX_POINTING_LEFT = "\U0001f448"
- BACKHAND_INDEX_POINTING_LEFT_LIGHT_SKIN_TONE = "\U0001f448\U0001f3fb"
- BACKHAND_INDEX_POINTING_LEFT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f448\U0001f3fc"
- BACKHAND_INDEX_POINTING_LEFT_MEDIUM_SKIN_TONE = "\U0001f448\U0001f3fd"
- BACKHAND_INDEX_POINTING_LEFT_MEDIUM_DARK_SKIN_TONE = "\U0001f448\U0001f3fe"
- BACKHAND_INDEX_POINTING_LEFT_DARK_SKIN_TONE = "\U0001f448\U0001f3ff"
- BACKHAND_INDEX_POINTING_RIGHT = "\U0001f449"
- BACKHAND_INDEX_POINTING_RIGHT_LIGHT_SKIN_TONE = "\U0001f449\U0001f3fb"
- BACKHAND_INDEX_POINTING_RIGHT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f449\U0001f3fc"
- BACKHAND_INDEX_POINTING_RIGHT_MEDIUM_SKIN_TONE = "\U0001f449\U0001f3fd"
- BACKHAND_INDEX_POINTING_RIGHT_MEDIUM_DARK_SKIN_TONE = "\U0001f449\U0001f3fe"
- BACKHAND_INDEX_POINTING_RIGHT_DARK_SKIN_TONE = "\U0001f449\U0001f3ff"
- INDEX_POINTING_UP = "\u261d\ufe0f"
- INDEX_POINTING_UP_LIGHT_SKIN_TONE = "\u261d\U0001f3fb"
- INDEX_POINTING_UP_MEDIUM_LIGHT_SKIN_TONE = "\u261d\U0001f3fc"
- INDEX_POINTING_UP_MEDIUM_SKIN_TONE = "\u261d\U0001f3fd"
- INDEX_POINTING_UP_MEDIUM_DARK_SKIN_TONE = "\u261d\U0001f3fe"
- INDEX_POINTING_UP_DARK_SKIN_TONE = "\u261d\U0001f3ff"
- BACKHAND_INDEX_POINTING_UP = "\U0001f446"
- BACKHAND_INDEX_POINTING_UP_LIGHT_SKIN_TONE = "\U0001f446\U0001f3fb"
- BACKHAND_INDEX_POINTING_UP_MEDIUM_LIGHT_SKIN_TONE = "\U0001f446\U0001f3fc"
- BACKHAND_INDEX_POINTING_UP_MEDIUM_SKIN_TONE = "\U0001f446\U0001f3fd"
- BACKHAND_INDEX_POINTING_UP_MEDIUM_DARK_SKIN_TONE = "\U0001f446\U0001f3fe"
- BACKHAND_INDEX_POINTING_UP_DARK_SKIN_TONE = "\U0001f446\U0001f3ff"
- MIDDLE_FINGER = "\U0001f595"
- MIDDLE_FINGER_LIGHT_SKIN_TONE = "\U0001f595\U0001f3fb"
- MIDDLE_FINGER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f595\U0001f3fc"
- MIDDLE_FINGER_MEDIUM_SKIN_TONE = "\U0001f595\U0001f3fd"
- MIDDLE_FINGER_MEDIUM_DARK_SKIN_TONE = "\U0001f595\U0001f3fe"
- MIDDLE_FINGER_DARK_SKIN_TONE = "\U0001f595\U0001f3ff"
- BACKHAND_INDEX_POINTING_DOWN = "\U0001f447"
- BACKHAND_INDEX_POINTING_DOWN_LIGHT_SKIN_TONE = "\U0001f447\U0001f3fb"
- BACKHAND_INDEX_POINTING_DOWN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f447\U0001f3fc"
- BACKHAND_INDEX_POINTING_DOWN_MEDIUM_SKIN_TONE = "\U0001f447\U0001f3fd"
- BACKHAND_INDEX_POINTING_DOWN_MEDIUM_DARK_SKIN_TONE = "\U0001f447\U0001f3fe"
- BACKHAND_INDEX_POINTING_DOWN_DARK_SKIN_TONE = "\U0001f447\U0001f3ff"
- VICTORY_HAND = "\u270c\ufe0f"
- VICTORY_HAND_LIGHT_SKIN_TONE = "\u270c\U0001f3fb"
- VICTORY_HAND_MEDIUM_LIGHT_SKIN_TONE = "\u270c\U0001f3fc"
- VICTORY_HAND_MEDIUM_SKIN_TONE = "\u270c\U0001f3fd"
- VICTORY_HAND_MEDIUM_DARK_SKIN_TONE = "\u270c\U0001f3fe"
- VICTORY_HAND_DARK_SKIN_TONE = "\u270c\U0001f3ff"
- CROSSED_FINGERS = "\U0001f91e"
- CROSSED_FINGERS_LIGHT_SKIN_TONE = "\U0001f91e\U0001f3fb"
- CROSSED_FINGERS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f91e\U0001f3fc"
- CROSSED_FINGERS_MEDIUM_SKIN_TONE = "\U0001f91e\U0001f3fd"
- CROSSED_FINGERS_MEDIUM_DARK_SKIN_TONE = "\U0001f91e\U0001f3fe"
- CROSSED_FINGERS_DARK_SKIN_TONE = "\U0001f91e\U0001f3ff"
- VULCAN_SALUTE = "\U0001f596"
- VULCAN_SALUTE_LIGHT_SKIN_TONE = "\U0001f596\U0001f3fb"
- VULCAN_SALUTE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f596\U0001f3fc"
- VULCAN_SALUTE_MEDIUM_SKIN_TONE = "\U0001f596\U0001f3fd"
- VULCAN_SALUTE_MEDIUM_DARK_SKIN_TONE = "\U0001f596\U0001f3fe"
- VULCAN_SALUTE_DARK_SKIN_TONE = "\U0001f596\U0001f3ff"
- SIGN_OF_THE_HORNS = "\U0001f918"
- SIGN_OF_THE_HORNS_LIGHT_SKIN_TONE = "\U0001f918\U0001f3fb"
- SIGN_OF_THE_HORNS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f918\U0001f3fc"
- SIGN_OF_THE_HORNS_MEDIUM_SKIN_TONE = "\U0001f918\U0001f3fd"
- SIGN_OF_THE_HORNS_MEDIUM_DARK_SKIN_TONE = "\U0001f918\U0001f3fe"
- SIGN_OF_THE_HORNS_DARK_SKIN_TONE = "\U0001f918\U0001f3ff"
- CALL_ME_HAND = "\U0001f919"
- CALL_ME_HAND_LIGHT_SKIN_TONE = "\U0001f919\U0001f3fb"
- CALL_ME_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f919\U0001f3fc"
- CALL_ME_HAND_MEDIUM_SKIN_TONE = "\U0001f919\U0001f3fd"
- CALL_ME_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f919\U0001f3fe"
- CALL_ME_HAND_DARK_SKIN_TONE = "\U0001f919\U0001f3ff"
- HAND_WITH_FINGERS_SPLAYED = "\U0001f590\ufe0f"
- HAND_WITH_FINGERS_SPLAYED_LIGHT_SKIN_TONE = "\U0001f590\U0001f3fb"
- HAND_WITH_FINGERS_SPLAYED_MEDIUM_LIGHT_SKIN_TONE = "\U0001f590\U0001f3fc"
- HAND_WITH_FINGERS_SPLAYED_MEDIUM_SKIN_TONE = "\U0001f590\U0001f3fd"
- HAND_WITH_FINGERS_SPLAYED_MEDIUM_DARK_SKIN_TONE = "\U0001f590\U0001f3fe"
- HAND_WITH_FINGERS_SPLAYED_DARK_SKIN_TONE = "\U0001f590\U0001f3ff"
- RAISED_HAND = "\u270b"
- RAISED_HAND_LIGHT_SKIN_TONE = "\u270b\U0001f3fb"
- RAISED_HAND_MEDIUM_LIGHT_SKIN_TONE = "\u270b\U0001f3fc"
- RAISED_HAND_MEDIUM_SKIN_TONE = "\u270b\U0001f3fd"
- RAISED_HAND_MEDIUM_DARK_SKIN_TONE = "\u270b\U0001f3fe"
- RAISED_HAND_DARK_SKIN_TONE = "\u270b\U0001f3ff"
- OK_HAND = "\U0001f44c"
- OK_HAND_LIGHT_SKIN_TONE = "\U0001f44c\U0001f3fb"
- OK_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f44c\U0001f3fc"
- OK_HAND_MEDIUM_SKIN_TONE = "\U0001f44c\U0001f3fd"
- OK_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f44c\U0001f3fe"
- OK_HAND_DARK_SKIN_TONE = "\U0001f44c\U0001f3ff"
- THUMBS_UP = "\U0001f44d"
- THUMBS_UP_LIGHT_SKIN_TONE = "\U0001f44d\U0001f3fb"
- THUMBS_UP_MEDIUM_LIGHT_SKIN_TONE = "\U0001f44d\U0001f3fc"
- THUMBS_UP_MEDIUM_SKIN_TONE = "\U0001f44d\U0001f3fd"
- THUMBS_UP_MEDIUM_DARK_SKIN_TONE = "\U0001f44d\U0001f3fe"
- THUMBS_UP_DARK_SKIN_TONE = "\U0001f44d\U0001f3ff"
- THUMBS_DOWN = "\U0001f44e"
- THUMBS_DOWN_LIGHT_SKIN_TONE = "\U0001f44e\U0001f3fb"
- THUMBS_DOWN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f44e\U0001f3fc"
- THUMBS_DOWN_MEDIUM_SKIN_TONE = "\U0001f44e\U0001f3fd"
- THUMBS_DOWN_MEDIUM_DARK_SKIN_TONE = "\U0001f44e\U0001f3fe"
- THUMBS_DOWN_DARK_SKIN_TONE = "\U0001f44e\U0001f3ff"
- RAISED_FIST = "\u270a"
- RAISED_FIST_LIGHT_SKIN_TONE = "\u270a\U0001f3fb"
- RAISED_FIST_MEDIUM_LIGHT_SKIN_TONE = "\u270a\U0001f3fc"
- RAISED_FIST_MEDIUM_SKIN_TONE = "\u270a\U0001f3fd"
- RAISED_FIST_MEDIUM_DARK_SKIN_TONE = "\u270a\U0001f3fe"
- RAISED_FIST_DARK_SKIN_TONE = "\u270a\U0001f3ff"
- ONCOMING_FIST = "\U0001f44a"
- ONCOMING_FIST_LIGHT_SKIN_TONE = "\U0001f44a\U0001f3fb"
- ONCOMING_FIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f44a\U0001f3fc"
- ONCOMING_FIST_MEDIUM_SKIN_TONE = "\U0001f44a\U0001f3fd"
- ONCOMING_FIST_MEDIUM_DARK_SKIN_TONE = "\U0001f44a\U0001f3fe"
- ONCOMING_FIST_DARK_SKIN_TONE = "\U0001f44a\U0001f3ff"
- LEFT_FACING_FIST = "\U0001f91b"
- LEFT_FACING_FIST_LIGHT_SKIN_TONE = "\U0001f91b\U0001f3fb"
- LEFT_FACING_FIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f91b\U0001f3fc"
- LEFT_FACING_FIST_MEDIUM_SKIN_TONE = "\U0001f91b\U0001f3fd"
- LEFT_FACING_FIST_MEDIUM_DARK_SKIN_TONE = "\U0001f91b\U0001f3fe"
- LEFT_FACING_FIST_DARK_SKIN_TONE = "\U0001f91b\U0001f3ff"
- RIGHT_FACING_FIST = "\U0001f91c"
- RIGHT_FACING_FIST_LIGHT_SKIN_TONE = "\U0001f91c\U0001f3fb"
- RIGHT_FACING_FIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f91c\U0001f3fc"
- RIGHT_FACING_FIST_MEDIUM_SKIN_TONE = "\U0001f91c\U0001f3fd"
- RIGHT_FACING_FIST_MEDIUM_DARK_SKIN_TONE = "\U0001f91c\U0001f3fe"
- RIGHT_FACING_FIST_DARK_SKIN_TONE = "\U0001f91c\U0001f3ff"
- RAISED_BACK_OF_HAND = "\U0001f91a"
- RAISED_BACK_OF_HAND_LIGHT_SKIN_TONE = "\U0001f91a\U0001f3fb"
- RAISED_BACK_OF_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f91a\U0001f3fc"
- RAISED_BACK_OF_HAND_MEDIUM_SKIN_TONE = "\U0001f91a\U0001f3fd"
- RAISED_BACK_OF_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f91a\U0001f3fe"
- RAISED_BACK_OF_HAND_DARK_SKIN_TONE = "\U0001f91a\U0001f3ff"
- WAVING_HAND = "\U0001f44b"
- WAVING_HAND_LIGHT_SKIN_TONE = "\U0001f44b\U0001f3fb"
- WAVING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f44b\U0001f3fc"
- WAVING_HAND_MEDIUM_SKIN_TONE = "\U0001f44b\U0001f3fd"
- WAVING_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f44b\U0001f3fe"
- WAVING_HAND_DARK_SKIN_TONE = "\U0001f44b\U0001f3ff"
- LOVE_YOU_GESTURE = "\U0001f91f"
- LOVE_YOU_GESTURE_LIGHT_SKIN_TONE = "\U0001f91f\U0001f3fb"
- LOVE_YOU_GESTURE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f91f\U0001f3fc"
- LOVE_YOU_GESTURE_MEDIUM_SKIN_TONE = "\U0001f91f\U0001f3fd"
- LOVE_YOU_GESTURE_MEDIUM_DARK_SKIN_TONE = "\U0001f91f\U0001f3fe"
- LOVE_YOU_GESTURE_DARK_SKIN_TONE = "\U0001f91f\U0001f3ff"
- WRITING_HAND = "\u270d\ufe0f"
- WRITING_HAND_LIGHT_SKIN_TONE = "\u270d\U0001f3fb"
- WRITING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\u270d\U0001f3fc"
- WRITING_HAND_MEDIUM_SKIN_TONE = "\u270d\U0001f3fd"
- WRITING_HAND_MEDIUM_DARK_SKIN_TONE = "\u270d\U0001f3fe"
- WRITING_HAND_DARK_SKIN_TONE = "\u270d\U0001f3ff"
- CLAPPING_HANDS = "\U0001f44f"
- CLAPPING_HANDS_LIGHT_SKIN_TONE = "\U0001f44f\U0001f3fb"
- CLAPPING_HANDS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f44f\U0001f3fc"
- CLAPPING_HANDS_MEDIUM_SKIN_TONE = "\U0001f44f\U0001f3fd"
- CLAPPING_HANDS_MEDIUM_DARK_SKIN_TONE = "\U0001f44f\U0001f3fe"
- CLAPPING_HANDS_DARK_SKIN_TONE = "\U0001f44f\U0001f3ff"
- OPEN_HANDS = "\U0001f450"
- OPEN_HANDS_LIGHT_SKIN_TONE = "\U0001f450\U0001f3fb"
- OPEN_HANDS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f450\U0001f3fc"
- OPEN_HANDS_MEDIUM_SKIN_TONE = "\U0001f450\U0001f3fd"
- OPEN_HANDS_MEDIUM_DARK_SKIN_TONE = "\U0001f450\U0001f3fe"
- OPEN_HANDS_DARK_SKIN_TONE = "\U0001f450\U0001f3ff"
- RAISING_HANDS = "\U0001f64c"
- RAISING_HANDS_LIGHT_SKIN_TONE = "\U0001f64c\U0001f3fb"
- RAISING_HANDS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64c\U0001f3fc"
- RAISING_HANDS_MEDIUM_SKIN_TONE = "\U0001f64c\U0001f3fd"
- RAISING_HANDS_MEDIUM_DARK_SKIN_TONE = "\U0001f64c\U0001f3fe"
- RAISING_HANDS_DARK_SKIN_TONE = "\U0001f64c\U0001f3ff"
- PALMS_UP_TOGETHER = "\U0001f932"
- PALMS_UP_TOGETHER_LIGHT_SKIN_TONE = "\U0001f932\U0001f3fb"
- PALMS_UP_TOGETHER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f932\U0001f3fc"
- PALMS_UP_TOGETHER_MEDIUM_SKIN_TONE = "\U0001f932\U0001f3fd"
- PALMS_UP_TOGETHER_MEDIUM_DARK_SKIN_TONE = "\U0001f932\U0001f3fe"
- PALMS_UP_TOGETHER_DARK_SKIN_TONE = "\U0001f932\U0001f3ff"
- FOLDED_HANDS = "\U0001f64f"
- FOLDED_HANDS_LIGHT_SKIN_TONE = "\U0001f64f\U0001f3fb"
- FOLDED_HANDS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64f\U0001f3fc"
- FOLDED_HANDS_MEDIUM_SKIN_TONE = "\U0001f64f\U0001f3fd"
- FOLDED_HANDS_MEDIUM_DARK_SKIN_TONE = "\U0001f64f\U0001f3fe"
- FOLDED_HANDS_DARK_SKIN_TONE = "\U0001f64f\U0001f3ff"
- HANDSHAKE = "\U0001f91d"
- NAIL_POLISH = "\U0001f485"
- NAIL_POLISH_LIGHT_SKIN_TONE = "\U0001f485\U0001f3fb"
- NAIL_POLISH_MEDIUM_LIGHT_SKIN_TONE = "\U0001f485\U0001f3fc"
- NAIL_POLISH_MEDIUM_SKIN_TONE = "\U0001f485\U0001f3fd"
- NAIL_POLISH_MEDIUM_DARK_SKIN_TONE = "\U0001f485\U0001f3fe"
- NAIL_POLISH_DARK_SKIN_TONE = "\U0001f485\U0001f3ff"
- EAR = "\U0001f442"
- EAR_LIGHT_SKIN_TONE = "\U0001f442\U0001f3fb"
- EAR_MEDIUM_LIGHT_SKIN_TONE = "\U0001f442\U0001f3fc"
- EAR_MEDIUM_SKIN_TONE = "\U0001f442\U0001f3fd"
- EAR_MEDIUM_DARK_SKIN_TONE = "\U0001f442\U0001f3fe"
- EAR_DARK_SKIN_TONE = "\U0001f442\U0001f3ff"
- NOSE = "\U0001f443"
- NOSE_LIGHT_SKIN_TONE = "\U0001f443\U0001f3fb"
- NOSE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f443\U0001f3fc"
- NOSE_MEDIUM_SKIN_TONE = "\U0001f443\U0001f3fd"
- NOSE_MEDIUM_DARK_SKIN_TONE = "\U0001f443\U0001f3fe"
- NOSE_DARK_SKIN_TONE = "\U0001f443\U0001f3ff"
- RED_HAIR = "\U0001f9b0"
- CURLY_HAIR = "\U0001f9b1"
- BALD = "\U0001f9b2"
- WHITE_HAIR = "\U0001f9b3"
- FOOTPRINTS = "\U0001f463"
- EYES = "\U0001f440"
- EYE = "\U0001f441\ufe0f"
- EYE_IN_SPEECH_BUBBLE = "\U0001f441\u200d\U0001f5e8"
- BRAIN = "\U0001f9e0"
- BONE = "\U0001f9b4"
- TOOTH = "\U0001f9b7"
- TONGUE = "\U0001f445"
- MOUTH = "\U0001f444"
- KISS_MARK = "\U0001f48b"
- HEART_WITH_ARROW = "\U0001f498"
- RED_HEART = "\u2764\ufe0f"
- BEATING_HEART = "\U0001f493"
- BROKEN_HEART = "\U0001f494"
- TWO_HEARTS = "\U0001f495"
- SPARKLING_HEART = "\U0001f496"
- GROWING_HEART = "\U0001f497"
- BLUE_HEART = "\U0001f499"
- GREEN_HEART = "\U0001f49a"
- YELLOW_HEART = "\U0001f49b"
- ORANGE_HEART = "\U0001f9e1"
- PURPLE_HEART = "\U0001f49c"
- BLACK_HEART = "\U0001f5a4"
- HEART_WITH_RIBBON = "\U0001f49d"
- REVOLVING_HEARTS = "\U0001f49e"
- HEART_DECORATION = "\U0001f49f"
- HEAVY_HEART_EXCLAMATION = "\u2763\ufe0f"
- LOVE_LETTER = "\U0001f48c"
- ZZZ = "\U0001f4a4"
- ANGER_SYMBOL = "\U0001f4a2"
- BOMB = "\U0001f4a3"
- COLLISION = "\U0001f4a5"
- SWEAT_DROPLETS = "\U0001f4a6"
- DASHING_AWAY = "\U0001f4a8"
- DIZZY = "\U0001f4ab"
- SPEECH_BALLOON = "\U0001f4ac"
- LEFT_SPEECH_BUBBLE = "\U0001f5e8\ufe0f"
- RIGHT_ANGER_BUBBLE = "\U0001f5ef\ufe0f"
- THOUGHT_BALLOON = "\U0001f4ad"
- HOLE = "\U0001f573\ufe0f"
- GLASSES = "\U0001f453"
- SUNGLASSES = "\U0001f576\ufe0f"
- GOGGLES = "\U0001f97d"
- LAB_COAT = "\U0001f97c"
- NECKTIE = "\U0001f454"
- T_SHIRT = "\U0001f455"
- JEANS = "\U0001f456"
- SCARF = "\U0001f9e3"
- GLOVES = "\U0001f9e4"
- COAT = "\U0001f9e5"
- SOCKS = "\U0001f9e6"
- DRESS = "\U0001f457"
- KIMONO = "\U0001f458"
- BIKINI = "\U0001f459"
- WOMAN_S_CLOTHES = "\U0001f45a"
- PURSE = "\U0001f45b"
- HANDBAG = "\U0001f45c"
- CLUTCH_BAG = "\U0001f45d"
- SHOPPING_BAGS = "\U0001f6cd\ufe0f"
- BACKPACK = "\U0001f392"
- MAN_S_SHOE = "\U0001f45e"
- RUNNING_SHOE = "\U0001f45f"
- HIKING_BOOT = "\U0001f97e"
- FLAT_SHOE = "\U0001f97f"
- HIGH_HEELED_SHOE = "\U0001f460"
- WOMAN_S_SANDAL = "\U0001f461"
- WOMAN_S_BOOT = "\U0001f462"
- CROWN = "\U0001f451"
- WOMAN_S_HAT = "\U0001f452"
- TOP_HAT = "\U0001f3a9"
- GRADUATION_CAP = "\U0001f393"
- BILLED_CAP = "\U0001f9e2"
- RESCUE_WORKER_S_HELMET = "\u26d1\ufe0f"
- PRAYER_BEADS = "\U0001f4ff"
- LIPSTICK = "\U0001f484"
- RING = "\U0001f48d"
- GEM_STONE = "\U0001f48e"
- MONKEY_FACE = "\U0001f435"
- MONKEY = "\U0001f412"
- GORILLA = "\U0001f98d"
- DOG_FACE = "\U0001f436"
- DOG = "\U0001f415"
- POODLE = "\U0001f429"
- WOLF_FACE = "\U0001f43a"
- FOX_FACE = "\U0001f98a"
- RACCOON = "\U0001f99d"
- CAT_FACE = "\U0001f431"
- CAT = "\U0001f408"
- LION_FACE = "\U0001f981"
- TIGER_FACE = "\U0001f42f"
- TIGER = "\U0001f405"
- LEOPARD = "\U0001f406"
- HORSE_FACE = "\U0001f434"
- HORSE = "\U0001f40e"
- UNICORN_FACE = "\U0001f984"
- ZEBRA = "\U0001f993"
- DEER = "\U0001f98c"
- COW_FACE = "\U0001f42e"
- OX = "\U0001f402"
- WATER_BUFFALO = "\U0001f403"
- COW = "\U0001f404"
- PIG_FACE = "\U0001f437"
- PIG = "\U0001f416"
- BOAR = "\U0001f417"
- PIG_NOSE = "\U0001f43d"
- RAM = "\U0001f40f"
- EWE = "\U0001f411"
- GOAT = "\U0001f410"
- CAMEL = "\U0001f42a"
- TWO_HUMP_CAMEL = "\U0001f42b"
- LLAMA = "\U0001f999"
- GIRAFFE = "\U0001f992"
- ELEPHANT = "\U0001f418"
- RHINOCEROS = "\U0001f98f"
- HIPPOPOTAMUS = "\U0001f99b"
- MOUSE_FACE = "\U0001f42d"
- MOUSE = "\U0001f401"
- RAT = "\U0001f400"
- HAMSTER_FACE = "\U0001f439"
- RABBIT_FACE = "\U0001f430"
- RABBIT = "\U0001f407"
- CHIPMUNK = "\U0001f43f\ufe0f"
- HEDGEHOG = "\U0001f994"
- BAT = "\U0001f987"
- BEAR_FACE = "\U0001f43b"
- KOALA = "\U0001f428"
- PANDA_FACE = "\U0001f43c"
- KANGAROO = "\U0001f998"
- BADGER = "\U0001f9a1"
- PAW_PRINTS = "\U0001f43e"
- TURKEY_2 = "\U0001f983"
- CHICKEN = "\U0001f414"
- ROOSTER = "\U0001f413"
- HATCHING_CHICK = "\U0001f423"
- BABY_CHICK = "\U0001f424"
- FRONT_FACING_BABY_CHICK = "\U0001f425"
- BIRD = "\U0001f426"
- PENGUIN = "\U0001f427"
- DOVE = "\U0001f54a\ufe0f"
- EAGLE = "\U0001f985"
- DUCK = "\U0001f986"
- SWAN = "\U0001f9a2"
- OWL = "\U0001f989"
- PEACOCK = "\U0001f99a"
- PARROT = "\U0001f99c"
- FROG_FACE = "\U0001f438"
- CROCODILE = "\U0001f40a"
- TURTLE = "\U0001f422"
- LIZARD = "\U0001f98e"
- SNAKE = "\U0001f40d"
- DRAGON_FACE = "\U0001f432"
- DRAGON = "\U0001f409"
- SAUROPOD = "\U0001f995"
- T_REX = "\U0001f996"
- SPOUTING_WHALE = "\U0001f433"
- WHALE = "\U0001f40b"
- DOLPHIN = "\U0001f42c"
- FISH = "\U0001f41f"
- TROPICAL_FISH = "\U0001f420"
- BLOWFISH = "\U0001f421"
- SHARK = "\U0001f988"
- OCTOPUS = "\U0001f419"
- SPIRAL_SHELL = "\U0001f41a"
- CRAB = "\U0001f980"
- LOBSTER = "\U0001f99e"
- SHRIMP = "\U0001f990"
- SQUID = "\U0001f991"
- SNAIL = "\U0001f40c"
- BUTTERFLY = "\U0001f98b"
- BUG = "\U0001f41b"
- ANT = "\U0001f41c"
- HONEYBEE = "\U0001f41d"
- LADY_BEETLE = "\U0001f41e"
- CRICKET = "\U0001f997"
- SPIDER = "\U0001f577\ufe0f"
- SPIDER_WEB = "\U0001f578\ufe0f"
- SCORPION = "\U0001f982"
- MOSQUITO = "\U0001f99f"
- MICROBE = "\U0001f9a0"
- BOUQUET = "\U0001f490"
- CHERRY_BLOSSOM = "\U0001f338"
- WHITE_FLOWER = "\U0001f4ae"
- ROSETTE = "\U0001f3f5\ufe0f"
- ROSE = "\U0001f339"
- WILTED_FLOWER = "\U0001f940"
- HIBISCUS = "\U0001f33a"
- SUNFLOWER = "\U0001f33b"
- BLOSSOM = "\U0001f33c"
- TULIP = "\U0001f337"
- SEEDLING = "\U0001f331"
- EVERGREEN_TREE = "\U0001f332"
- DECIDUOUS_TREE = "\U0001f333"
- PALM_TREE = "\U0001f334"
- CACTUS = "\U0001f335"
- SHEAF_OF_RICE = "\U0001f33e"
- HERB = "\U0001f33f"
- SHAMROCK = "\u2618\ufe0f"
- FOUR_LEAF_CLOVER = "\U0001f340"
- MAPLE_LEAF = "\U0001f341"
- FALLEN_LEAF = "\U0001f342"
- LEAF_FLUTTERING_IN_WIND = "\U0001f343"
- GRAPES = "\U0001f347"
- MELON = "\U0001f348"
- WATERMELON = "\U0001f349"
- TANGERINE = "\U0001f34a"
- LEMON = "\U0001f34b"
- BANANA = "\U0001f34c"
- PINEAPPLE = "\U0001f34d"
- MANGO = "\U0001f96d"
- RED_APPLE = "\U0001f34e"
- GREEN_APPLE = "\U0001f34f"
- PEAR = "\U0001f350"
- PEACH = "\U0001f351"
- CHERRIES = "\U0001f352"
- STRAWBERRY = "\U0001f353"
- KIWI_FRUIT = "\U0001f95d"
- TOMATO = "\U0001f345"
- COCONUT = "\U0001f965"
- AVOCADO = "\U0001f951"
- EGGPLANT = "\U0001f346"
- POTATO = "\U0001f954"
- CARROT = "\U0001f955"
- EAR_OF_CORN = "\U0001f33d"
- HOT_PEPPER = "\U0001f336\ufe0f"
- CUCUMBER = "\U0001f952"
- LEAFY_GREEN = "\U0001f96c"
- BROCCOLI = "\U0001f966"
- MUSHROOM = "\U0001f344"
- PEANUTS = "\U0001f95c"
- CHESTNUT = "\U0001f330"
- BREAD = "\U0001f35e"
- CROISSANT = "\U0001f950"
- BAGUETTE_BREAD = "\U0001f956"
- PRETZEL = "\U0001f968"
- BAGEL = "\U0001f96f"
- PANCAKES = "\U0001f95e"
- CHEESE_WEDGE = "\U0001f9c0"
- MEAT_ON_BONE = "\U0001f356"
- POULTRY_LEG = "\U0001f357"
- CUT_OF_MEAT = "\U0001f969"
- BACON = "\U0001f953"
- HAMBURGER = "\U0001f354"
- FRENCH_FRIES = "\U0001f35f"
- PIZZA = "\U0001f355"
- HOT_DOG = "\U0001f32d"
- SANDWICH = "\U0001f96a"
- TACO = "\U0001f32e"
- BURRITO = "\U0001f32f"
- STUFFED_FLATBREAD = "\U0001f959"
- EGG = "\U0001f95a"
- COOKING = "\U0001f373"
- SHALLOW_PAN_OF_FOOD = "\U0001f958"
- POT_OF_FOOD = "\U0001f372"
- BOWL_WITH_SPOON = "\U0001f963"
- GREEN_SALAD = "\U0001f957"
- POPCORN = "\U0001f37f"
- SALT = "\U0001f9c2"
- CANNED_FOOD = "\U0001f96b"
- BENTO_BOX = "\U0001f371"
- RICE_CRACKER = "\U0001f358"
- RICE_BALL = "\U0001f359"
- COOKED_RICE = "\U0001f35a"
- CURRY_RICE = "\U0001f35b"
- STEAMING_BOWL = "\U0001f35c"
- SPAGHETTI = "\U0001f35d"
- ROASTED_SWEET_POTATO = "\U0001f360"
- ODEN = "\U0001f362"
- SUSHI = "\U0001f363"
- FRIED_SHRIMP = "\U0001f364"
- FISH_CAKE_WITH_SWIRL = "\U0001f365"
- MOON_CAKE = "\U0001f96e"
- DANGO = "\U0001f361"
- DUMPLING = "\U0001f95f"
- FORTUNE_COOKIE = "\U0001f960"
- TAKEOUT_BOX = "\U0001f961"
- SOFT_ICE_CREAM = "\U0001f366"
- SHAVED_ICE = "\U0001f367"
- ICE_CREAM = "\U0001f368"
- DOUGHNUT = "\U0001f369"
- COOKIE = "\U0001f36a"
- BIRTHDAY_CAKE = "\U0001f382"
- SHORTCAKE = "\U0001f370"
- CUPCAKE = "\U0001f9c1"
- PIE = "\U0001f967"
- CHOCOLATE_BAR = "\U0001f36b"
- CANDY = "\U0001f36c"
- LOLLIPOP = "\U0001f36d"
- CUSTARD = "\U0001f36e"
- HONEY_POT = "\U0001f36f"
- BABY_BOTTLE = "\U0001f37c"
- GLASS_OF_MILK = "\U0001f95b"
- HOT_BEVERAGE = "\u2615"
- TEACUP_WITHOUT_HANDLE = "\U0001f375"
- SAKE = "\U0001f376"
- BOTTLE_WITH_POPPING_CORK = "\U0001f37e"
- WINE_GLASS = "\U0001f377"
- COCKTAIL_GLASS = "\U0001f378"
- TROPICAL_DRINK = "\U0001f379"
- BEER_MUG = "\U0001f37a"
- CLINKING_BEER_MUGS = "\U0001f37b"
- CLINKING_GLASSES = "\U0001f942"
- TUMBLER_GLASS = "\U0001f943"
- CUP_WITH_STRAW = "\U0001f964"
- CHOPSTICKS = "\U0001f962"
- FORK_AND_KNIFE_WITH_PLATE = "\U0001f37d\ufe0f"
- FORK_AND_KNIFE = "\U0001f374"
- SPOON = "\U0001f944"
- KITCHEN_KNIFE = "\U0001f52a"
- AMPHORA = "\U0001f3fa"
- GLOBE_SHOWING_EUROPE_AFRICA = "\U0001f30d"
- GLOBE_SHOWING_AMERICAS = "\U0001f30e"
- GLOBE_SHOWING_ASIA_AUSTRALIA = "\U0001f30f"
- GLOBE_WITH_MERIDIANS = "\U0001f310"
- WORLD_MAP = "\U0001f5fa\ufe0f"
- MAP_OF_JAPAN = "\U0001f5fe"
- COMPASS = "\U0001f9ed"
- SNOW_CAPPED_MOUNTAIN = "\U0001f3d4\ufe0f"
- MOUNTAIN = "\u26f0\ufe0f"
- VOLCANO = "\U0001f30b"
- MOUNT_FUJI = "\U0001f5fb"
- CAMPING = "\U0001f3d5\ufe0f"
- BEACH_WITH_UMBRELLA = "\U0001f3d6\ufe0f"
- DESERT = "\U0001f3dc\ufe0f"
- DESERT_ISLAND = "\U0001f3dd\ufe0f"
- NATIONAL_PARK = "\U0001f3de\ufe0f"
- STADIUM = "\U0001f3df\ufe0f"
- CLASSICAL_BUILDING = "\U0001f3db\ufe0f"
- BUILDING_CONSTRUCTION = "\U0001f3d7\ufe0f"
- HOUSES = "\U0001f3d8\ufe0f"
- DERELICT_HOUSE = "\U0001f3da\ufe0f"
- HOUSE = "\U0001f3e0"
- HOUSE_WITH_GARDEN = "\U0001f3e1"
- BRICK = "\U0001f9f1"
- OFFICE_BUILDING = "\U0001f3e2"
- JAPANESE_POST_OFFICE = "\U0001f3e3"
- POST_OFFICE = "\U0001f3e4"
- HOSPITAL = "\U0001f3e5"
- BANK = "\U0001f3e6"
- HOTEL = "\U0001f3e8"
- LOVE_HOTEL = "\U0001f3e9"
- CONVENIENCE_STORE = "\U0001f3ea"
- SCHOOL = "\U0001f3eb"
- DEPARTMENT_STORE = "\U0001f3ec"
- FACTORY = "\U0001f3ed"
- JAPANESE_CASTLE = "\U0001f3ef"
- CASTLE = "\U0001f3f0"
- WEDDING = "\U0001f492"
- TOKYO_TOWER = "\U0001f5fc"
- STATUE_OF_LIBERTY = "\U0001f5fd"
- CHURCH = "\u26ea"
- MOSQUE = "\U0001f54c"
- SYNAGOGUE = "\U0001f54d"
- SHINTO_SHRINE = "\u26e9\ufe0f"
- KAABA = "\U0001f54b"
- FOUNTAIN = "\u26f2"
- TENT = "\u26fa"
- FOGGY = "\U0001f301"
- NIGHT_WITH_STARS = "\U0001f303"
- CITYSCAPE = "\U0001f3d9\ufe0f"
- SUNRISE_OVER_MOUNTAINS = "\U0001f304"
- SUNRISE = "\U0001f305"
- CITYSCAPE_AT_DUSK = "\U0001f306"
- SUNSET = "\U0001f307"
- BRIDGE_AT_NIGHT = "\U0001f309"
- HOT_SPRINGS = "\u2668\ufe0f"
- MILKY_WAY = "\U0001f30c"
- CAROUSEL_HORSE = "\U0001f3a0"
- FERRIS_WHEEL = "\U0001f3a1"
- ROLLER_COASTER = "\U0001f3a2"
- BARBER_POLE = "\U0001f488"
- CIRCUS_TENT = "\U0001f3aa"
- LOCOMOTIVE = "\U0001f682"
- RAILWAY_CAR = "\U0001f683"
- HIGH_SPEED_TRAIN = "\U0001f684"
- BULLET_TRAIN = "\U0001f685"
- TRAIN = "\U0001f686"
- METRO = "\U0001f687"
- LIGHT_RAIL = "\U0001f688"
- STATION = "\U0001f689"
- TRAM = "\U0001f68a"
- MONORAIL = "\U0001f69d"
- MOUNTAIN_RAILWAY = "\U0001f69e"
- TRAM_CAR = "\U0001f68b"
- BUS = "\U0001f68c"
- ONCOMING_BUS = "\U0001f68d"
- TROLLEYBUS = "\U0001f68e"
- MINIBUS = "\U0001f690"
- AMBULANCE = "\U0001f691"
- FIRE_ENGINE = "\U0001f692"
- POLICE_CAR = "\U0001f693"
- ONCOMING_POLICE_CAR = "\U0001f694"
- TAXI = "\U0001f695"
- ONCOMING_TAXI = "\U0001f696"
- AUTOMOBILE = "\U0001f697"
- ONCOMING_AUTOMOBILE = "\U0001f698"
- SPORT_UTILITY_VEHICLE = "\U0001f699"
- DELIVERY_TRUCK = "\U0001f69a"
- ARTICULATED_LORRY = "\U0001f69b"
- TRACTOR = "\U0001f69c"
- BICYCLE = "\U0001f6b2"
- KICK_SCOOTER = "\U0001f6f4"
- SKATEBOARD = "\U0001f6f9"
- MOTOR_SCOOTER = "\U0001f6f5"
- BUS_STOP = "\U0001f68f"
- MOTORWAY = "\U0001f6e3\ufe0f"
- RAILWAY_TRACK = "\U0001f6e4\ufe0f"
- OIL_DRUM = "\U0001f6e2\ufe0f"
- FUEL_PUMP = "\u26fd"
- POLICE_CAR_LIGHT = "\U0001f6a8"
- HORIZONTAL_TRAFFIC_LIGHT = "\U0001f6a5"
- VERTICAL_TRAFFIC_LIGHT = "\U0001f6a6"
- STOP_SIGN = "\U0001f6d1"
- CONSTRUCTION = "\U0001f6a7"
- ANCHOR = "\u2693"
- SAILBOAT = "\u26f5"
- CANOE = "\U0001f6f6"
- SPEEDBOAT = "\U0001f6a4"
- PASSENGER_SHIP = "\U0001f6f3\ufe0f"
- FERRY = "\u26f4\ufe0f"
- MOTOR_BOAT = "\U0001f6e5\ufe0f"
- SHIP = "\U0001f6a2"
- AIRPLANE = "\u2708\ufe0f"
- SMALL_AIRPLANE = "\U0001f6e9\ufe0f"
- AIRPLANE_DEPARTURE = "\U0001f6eb"
- AIRPLANE_ARRIVAL = "\U0001f6ec"
- SEAT = "\U0001f4ba"
- HELICOPTER = "\U0001f681"
- SUSPENSION_RAILWAY = "\U0001f69f"
- MOUNTAIN_CABLEWAY = "\U0001f6a0"
- AERIAL_TRAMWAY = "\U0001f6a1"
- SATELLITE = "\U0001f6f0\ufe0f"
- ROCKET = "\U0001f680"
- FLYING_SAUCER = "\U0001f6f8"
- BELLHOP_BELL = "\U0001f6ce\ufe0f"
- LUGGAGE = "\U0001f9f3"
- HOURGLASS_DONE = "\u231b"
- HOURGLASS_NOT_DONE = "\u23f3"
- WATCH = "\u231a"
- ALARM_CLOCK = "\u23f0"
- STOPWATCH = "\u23f1\ufe0f"
- TIMER_CLOCK = "\u23f2\ufe0f"
- MANTELPIECE_CLOCK = "\U0001f570\ufe0f"
- TWELVE_O_CLOCK = "\U0001f55b"
- TWELVE_THIRTY = "\U0001f567"
- ONE_O_CLOCK = "\U0001f550"
- ONE_THIRTY = "\U0001f55c"
- TWO_O_CLOCK = "\U0001f551"
- TWO_THIRTY = "\U0001f55d"
- THREE_O_CLOCK = "\U0001f552"
- THREE_THIRTY = "\U0001f55e"
- FOUR_O_CLOCK = "\U0001f553"
- FOUR_THIRTY = "\U0001f55f"
- FIVE_O_CLOCK = "\U0001f554"
- FIVE_THIRTY = "\U0001f560"
- SIX_O_CLOCK = "\U0001f555"
- SIX_THIRTY = "\U0001f561"
- SEVEN_O_CLOCK = "\U0001f556"
- SEVEN_THIRTY = "\U0001f562"
- EIGHT_O_CLOCK = "\U0001f557"
- EIGHT_THIRTY = "\U0001f563"
- NINE_O_CLOCK = "\U0001f558"
- NINE_THIRTY = "\U0001f564"
- TEN_O_CLOCK = "\U0001f559"
- TEN_THIRTY = "\U0001f565"
- ELEVEN_O_CLOCK = "\U0001f55a"
- ELEVEN_THIRTY = "\U0001f566"
- NEW_MOON = "\U0001f311"
- WAXING_CRESCENT_MOON = "\U0001f312"
- FIRST_QUARTER_MOON = "\U0001f313"
- WAXING_GIBBOUS_MOON = "\U0001f314"
- FULL_MOON = "\U0001f315"
- WANING_GIBBOUS_MOON = "\U0001f316"
- LAST_QUARTER_MOON = "\U0001f317"
- WANING_CRESCENT_MOON = "\U0001f318"
- CRESCENT_MOON = "\U0001f319"
- NEW_MOON_FACE = "\U0001f31a"
- FIRST_QUARTER_MOON_FACE = "\U0001f31b"
- LAST_QUARTER_MOON_FACE = "\U0001f31c"
- THERMOMETER = "\U0001f321\ufe0f"
- SUN = "\u2600\ufe0f"
- FULL_MOON_FACE = "\U0001f31d"
- SUN_WITH_FACE = "\U0001f31e"
- STAR = "\u2b50"
- GLOWING_STAR = "\U0001f31f"
- SHOOTING_STAR = "\U0001f320"
- CLOUD = "\u2601\ufe0f"
- SUN_BEHIND_CLOUD = "\u26c5"
- CLOUD_WITH_LIGHTNING_AND_RAIN = "\u26c8\ufe0f"
- SUN_BEHIND_SMALL_CLOUD = "\U0001f324\ufe0f"
- SUN_BEHIND_LARGE_CLOUD = "\U0001f325\ufe0f"
- SUN_BEHIND_RAIN_CLOUD = "\U0001f326\ufe0f"
- CLOUD_WITH_RAIN = "\U0001f327\ufe0f"
- CLOUD_WITH_SNOW = "\U0001f328\ufe0f"
- CLOUD_WITH_LIGHTNING = "\U0001f329\ufe0f"
- TORNADO = "\U0001f32a\ufe0f"
- FOG = "\U0001f32b\ufe0f"
- WIND_FACE = "\U0001f32c\ufe0f"
- CYCLONE = "\U0001f300"
- RAINBOW = "\U0001f308"
- CLOSED_UMBRELLA = "\U0001f302"
- UMBRELLA = "\u2602\ufe0f"
- UMBRELLA_WITH_RAIN_DROPS = "\u2614"
- UMBRELLA_ON_GROUND = "\u26f1\ufe0f"
- HIGH_VOLTAGE = "\u26a1"
- SNOWFLAKE = "\u2744\ufe0f"
- SNOWMAN = "\u2603\ufe0f"
- SNOWMAN_WITHOUT_SNOW = "\u26c4"
- COMET = "\u2604\ufe0f"
- FIRE = "\U0001f525"
- DROPLET = "\U0001f4a7"
- WATER_WAVE = "\U0001f30a"
- JACK_O_LANTERN = "\U0001f383"
- CHRISTMAS_TREE = "\U0001f384"
- FIREWORKS = "\U0001f386"
- SPARKLER = "\U0001f387"
- FIRECRACKER = "\U0001f9e8"
- SPARKLES = "\u2728"
- BALLOON = "\U0001f388"
- PARTY_POPPER = "\U0001f389"
- CONFETTI_BALL = "\U0001f38a"
- TANABATA_TREE = "\U0001f38b"
- PINE_DECORATION = "\U0001f38d"
- JAPANESE_DOLLS = "\U0001f38e"
- CARP_STREAMER = "\U0001f38f"
- WIND_CHIME = "\U0001f390"
- MOON_VIEWING_CEREMONY = "\U0001f391"
- RED_ENVELOPE = "\U0001f9e7"
- RIBBON = "\U0001f380"
- WRAPPED_GIFT = "\U0001f381"
- REMINDER_RIBBON = "\U0001f397\ufe0f"
- ADMISSION_TICKETS = "\U0001f39f\ufe0f"
- TICKET = "\U0001f3ab"
- MILITARY_MEDAL = "\U0001f396\ufe0f"
- TROPHY = "\U0001f3c6"
- SPORTS_MEDAL = "\U0001f3c5"
- FIRST_PLACE_MEDAL = "\U0001f947"
- SECOND_PLACE_MEDAL = "\U0001f948"
- THIRD_PLACE_MEDAL = "\U0001f949"
- SOCCER_BALL = "\u26bd"
- BASEBALL = "\u26be"
- SOFTBALL = "\U0001f94e"
- BASKETBALL = "\U0001f3c0"
- VOLLEYBALL = "\U0001f3d0"
- AMERICAN_FOOTBALL = "\U0001f3c8"
- RUGBY_FOOTBALL = "\U0001f3c9"
- TENNIS = "\U0001f3be"
- FLYING_DISC = "\U0001f94f"
- BOWLING = "\U0001f3b3"
- CRICKET_GAME = "\U0001f3cf"
- FIELD_HOCKEY = "\U0001f3d1"
- ICE_HOCKEY = "\U0001f3d2"
- LACROSSE = "\U0001f94d"
- PING_PONG = "\U0001f3d3"
- BADMINTON = "\U0001f3f8"
- BOXING_GLOVE = "\U0001f94a"
- MARTIAL_ARTS_UNIFORM = "\U0001f94b"
- GOAL_NET = "\U0001f945"
- FLAG_IN_HOLE = "\u26f3"
- ICE_SKATE = "\u26f8\ufe0f"
- FISHING_POLE = "\U0001f3a3"
- RUNNING_SHIRT = "\U0001f3bd"
- SKIS = "\U0001f3bf"
- SLED = "\U0001f6f7"
- CURLING_STONE = "\U0001f94c"
- DIRECT_HIT = "\U0001f3af"
- POOL_8_BALL = "\U0001f3b1"
- CRYSTAL_BALL = "\U0001f52e"
- NAZAR_AMULET = "\U0001f9ff"
- VIDEO_GAME = "\U0001f3ae"
- JOYSTICK = "\U0001f579\ufe0f"
- SLOT_MACHINE = "\U0001f3b0"
- GAME_DIE = "\U0001f3b2"
- JIGSAW = "\U0001f9e9"
- TEDDY_BEAR = "\U0001f9f8"
- SPADE_SUIT = "\u2660\ufe0f"
- HEART_SUIT = "\u2665\ufe0f"
- DIAMOND_SUIT = "\u2666\ufe0f"
- CLUB_SUIT = "\u2663\ufe0f"
- CHESS_PAWN = "\u265f\ufe0f"
- JOKER = "\U0001f0cf"
- MAHJONG_RED_DRAGON = "\U0001f004"
- FLOWER_PLAYING_CARDS = "\U0001f3b4"
- PERFORMING_ARTS = "\U0001f3ad"
- FRAMED_PICTURE = "\U0001f5bc\ufe0f"
- ARTIST_PALETTE = "\U0001f3a8"
- MUTED_SPEAKER = "\U0001f507"
- SPEAKER_LOW_VOLUME = "\U0001f508"
- SPEAKER_MEDIUM_VOLUME = "\U0001f509"
- SPEAKER_HIGH_VOLUME = "\U0001f50a"
- LOUDSPEAKER = "\U0001f4e2"
- MEGAPHONE = "\U0001f4e3"
- POSTAL_HORN = "\U0001f4ef"
- BELL = "\U0001f514"
- BELL_WITH_SLASH = "\U0001f515"
- MUSICAL_SCORE = "\U0001f3bc"
- MUSICAL_NOTE = "\U0001f3b5"
- MUSICAL_NOTES = "\U0001f3b6"
- STUDIO_MICROPHONE = "\U0001f399\ufe0f"
- LEVEL_SLIDER = "\U0001f39a\ufe0f"
- CONTROL_KNOBS = "\U0001f39b\ufe0f"
- MICROPHONE = "\U0001f3a4"
- HEADPHONE = "\U0001f3a7"
- RADIO = "\U0001f4fb"
- SAXOPHONE = "\U0001f3b7"
- GUITAR = "\U0001f3b8"
- MUSICAL_KEYBOARD = "\U0001f3b9"
- TRUMPET = "\U0001f3ba"
- VIOLIN = "\U0001f3bb"
- DRUM = "\U0001f941"
- MOBILE_PHONE = "\U0001f4f1"
- MOBILE_PHONE_WITH_ARROW = "\U0001f4f2"
- TELEPHONE = "\u260e\ufe0f"
- TELEPHONE_RECEIVER = "\U0001f4de"
- PAGER = "\U0001f4df"
- FAX_MACHINE = "\U0001f4e0"
- BATTERY = "\U0001f50b"
- ELECTRIC_PLUG = "\U0001f50c"
- LAPTOP_COMPUTER = "\U0001f4bb"
- DESKTOP_COMPUTER = "\U0001f5a5\ufe0f"
- PRINTER = "\U0001f5a8\ufe0f"
- KEYBOARD = "\u2328\ufe0f"
- COMPUTER_MOUSE = "\U0001f5b1\ufe0f"
- TRACKBALL = "\U0001f5b2\ufe0f"
- COMPUTER_DISK = "\U0001f4bd"
- FLOPPY_DISK = "\U0001f4be"
- OPTICAL_DISK = "\U0001f4bf"
- DVD = "\U0001f4c0"
- ABACUS = "\U0001f9ee"
- MOVIE_CAMERA = "\U0001f3a5"
- FILM_FRAMES = "\U0001f39e\ufe0f"
- FILM_PROJECTOR = "\U0001f4fd\ufe0f"
- CLAPPER_BOARD = "\U0001f3ac"
- TELEVISION = "\U0001f4fa"
- CAMERA = "\U0001f4f7"
- CAMERA_WITH_FLASH = "\U0001f4f8"
- VIDEO_CAMERA = "\U0001f4f9"
- VIDEOCASSETTE = "\U0001f4fc"
- MAGNIFYING_GLASS_TILTED_LEFT = "\U0001f50d"
- MAGNIFYING_GLASS_TILTED_RIGHT = "\U0001f50e"
- CANDLE = "\U0001f56f\ufe0f"
- LIGHT_BULB = "\U0001f4a1"
- FLASHLIGHT = "\U0001f526"
- RED_PAPER_LANTERN = "\U0001f3ee"
- NOTEBOOK_WITH_DECORATIVE_COVER = "\U0001f4d4"
- CLOSED_BOOK = "\U0001f4d5"
- OPEN_BOOK = "\U0001f4d6"
- GREEN_BOOK = "\U0001f4d7"
- BLUE_BOOK = "\U0001f4d8"
- ORANGE_BOOK = "\U0001f4d9"
- BOOKS = "\U0001f4da"
- NOTEBOOK = "\U0001f4d3"
- LEDGER = "\U0001f4d2"
- PAGE_WITH_CURL = "\U0001f4c3"
- SCROLL = "\U0001f4dc"
- PAGE_FACING_UP = "\U0001f4c4"
- NEWSPAPER = "\U0001f4f0"
- ROLLED_UP_NEWSPAPER = "\U0001f5de\ufe0f"
- BOOKMARK_TABS = "\U0001f4d1"
- BOOKMARK = "\U0001f516"
- LABEL = "\U0001f3f7\ufe0f"
- MONEY_BAG = "\U0001f4b0"
- YEN_BANKNOTE = "\U0001f4b4"
- DOLLAR_BANKNOTE = "\U0001f4b5"
- EURO_BANKNOTE = "\U0001f4b6"
- POUND_BANKNOTE = "\U0001f4b7"
- MONEY_WITH_WINGS = "\U0001f4b8"
- CREDIT_CARD = "\U0001f4b3"
- RECEIPT = "\U0001f9fe"
- CHART_INCREASING_WITH_YEN = "\U0001f4b9"
- CURRENCY_EXCHANGE = "\U0001f4b1"
- HEAVY_DOLLAR_SIGN = "\U0001f4b2"
- ENVELOPE = "\u2709\ufe0f"
- E_MAIL = "\U0001f4e7"
- INCOMING_ENVELOPE = "\U0001f4e8"
- ENVELOPE_WITH_ARROW = "\U0001f4e9"
- OUTBOX_TRAY = "\U0001f4e4"
- INBOX_TRAY = "\U0001f4e5"
- PACKAGE = "\U0001f4e6"
- CLOSED_MAILBOX_WITH_RAISED_FLAG = "\U0001f4eb"
- CLOSED_MAILBOX_WITH_LOWERED_FLAG = "\U0001f4ea"
- OPEN_MAILBOX_WITH_RAISED_FLAG = "\U0001f4ec"
- OPEN_MAILBOX_WITH_LOWERED_FLAG = "\U0001f4ed"
- POSTBOX = "\U0001f4ee"
- BALLOT_BOX_WITH_BALLOT = "\U0001f5f3\ufe0f"
- PENCIL = "\u270f\ufe0f"
- BLACK_NIB = "\u2712\ufe0f"
- FOUNTAIN_PEN = "\U0001f58b\ufe0f"
- PEN = "\U0001f58a\ufe0f"
- PAINTBRUSH = "\U0001f58c\ufe0f"
- CRAYON = "\U0001f58d\ufe0f"
- MEMO = "\U0001f4dd"
- BRIEFCASE = "\U0001f4bc"
- FILE_FOLDER = "\U0001f4c1"
- OPEN_FILE_FOLDER = "\U0001f4c2"
- CARD_INDEX_DIVIDERS = "\U0001f5c2\ufe0f"
- CALENDAR = "\U0001f4c5"
- TEAR_OFF_CALENDAR = "\U0001f4c6"
- SPIRAL_NOTEPAD = "\U0001f5d2\ufe0f"
- SPIRAL_CALENDAR = "\U0001f5d3\ufe0f"
- CARD_INDEX = "\U0001f4c7"
- CHART_INCREASING = "\U0001f4c8"
- CHART_DECREASING = "\U0001f4c9"
- BAR_CHART = "\U0001f4ca"
- CLIPBOARD = "\U0001f4cb"
- PUSHPIN = "\U0001f4cc"
- ROUND_PUSHPIN = "\U0001f4cd"
- PAPERCLIP = "\U0001f4ce"
- LINKED_PAPERCLIPS = "\U0001f587\ufe0f"
- STRAIGHT_RULER = "\U0001f4cf"
- TRIANGULAR_RULER = "\U0001f4d0"
- SCISSORS = "\u2702\ufe0f"
- CARD_FILE_BOX = "\U0001f5c3\ufe0f"
- FILE_CABINET = "\U0001f5c4\ufe0f"
- WASTEBASKET = "\U0001f5d1\ufe0f"
- LOCKED = "\U0001f512"
- UNLOCKED = "\U0001f513"
- LOCKED_WITH_PEN = "\U0001f50f"
- LOCKED_WITH_KEY = "\U0001f510"
- KEY = "\U0001f511"
- OLD_KEY = "\U0001f5dd\ufe0f"
- HAMMER = "\U0001f528"
- PICK = "\u26cf\ufe0f"
- HAMMER_AND_PICK = "\u2692\ufe0f"
- HAMMER_AND_WRENCH = "\U0001f6e0\ufe0f"
- DAGGER = "\U0001f5e1\ufe0f"
- CROSSED_SWORDS = "\u2694\ufe0f"
- PISTOL = "\U0001f52b"
- BOW_AND_ARROW = "\U0001f3f9"
- SHIELD = "\U0001f6e1\ufe0f"
- WRENCH = "\U0001f527"
- NUT_AND_BOLT = "\U0001f529"
- GEAR = "\u2699\ufe0f"
- CLAMP = "\U0001f5dc\ufe0f"
- BALANCE_SCALE = "\u2696\ufe0f"
- LINK = "\U0001f517"
- CHAINS = "\u26d3\ufe0f"
- TOOLBOX = "\U0001f9f0"
- MAGNET = "\U0001f9f2"
- ALEMBIC = "\u2697\ufe0f"
- TEST_TUBE = "\U0001f9ea"
- PETRI_DISH = "\U0001f9eb"
- DNA = "\U0001f9ec"
- FIRE_EXTINGUISHER = "\U0001f9ef"
- MICROSCOPE = "\U0001f52c"
- TELESCOPE = "\U0001f52d"
- SATELLITE_ANTENNA = "\U0001f4e1"
- SYRINGE = "\U0001f489"
- PILL = "\U0001f48a"
- DOOR = "\U0001f6aa"
- BED = "\U0001f6cf\ufe0f"
- COUCH_AND_LAMP = "\U0001f6cb\ufe0f"
- TOILET = "\U0001f6bd"
- SHOWER = "\U0001f6bf"
- BATHTUB = "\U0001f6c1"
- LOTION_BOTTLE = "\U0001f9f4"
- THREAD = "\U0001f9f5"
- YARN = "\U0001f9f6"
- SAFETY_PIN = "\U0001f9f7"
- BROOM = "\U0001f9f9"
- BASKET = "\U0001f9fa"
- ROLL_OF_PAPER = "\U0001f9fb"
- SOAP = "\U0001f9fc"
- SPONGE = "\U0001f9fd"
- SHOPPING_CART = "\U0001f6d2"
- CIGARETTE = "\U0001f6ac"
- COFFIN = "\u26b0\ufe0f"
- FUNERAL_URN = "\u26b1\ufe0f"
- MOAI = "\U0001f5ff"
- ATM_SIGN = "\U0001f3e7"
- LITTER_IN_BIN_SIGN = "\U0001f6ae"
- POTABLE_WATER = "\U0001f6b0"
- WHEELCHAIR_SYMBOL = "\u267f"
- MEN_S_ROOM = "\U0001f6b9"
- WOMEN_S_ROOM = "\U0001f6ba"
- RESTROOM = "\U0001f6bb"
- BABY_SYMBOL = "\U0001f6bc"
- WATER_CLOSET = "\U0001f6be"
- PASSPORT_CONTROL = "\U0001f6c2"
- CUSTOMS = "\U0001f6c3"
- BAGGAGE_CLAIM = "\U0001f6c4"
- LEFT_LUGGAGE = "\U0001f6c5"
- WARNING = "\u26a0\ufe0f"
- CHILDREN_CROSSING = "\U0001f6b8"
- NO_ENTRY = "\u26d4"
- PROHIBITED = "\U0001f6ab"
- NO_BICYCLES = "\U0001f6b3"
- NO_SMOKING = "\U0001f6ad"
- NO_LITTERING = "\U0001f6af"
- NON_POTABLE_WATER = "\U0001f6b1"
- NO_PEDESTRIANS = "\U0001f6b7"
- NO_MOBILE_PHONES = "\U0001f4f5"
- NO_ONE_UNDER_EIGHTEEN = "\U0001f51e"
- RADIOACTIVE = "\u2622\ufe0f"
- BIOHAZARD = "\u2623\ufe0f"
- UP_ARROW = "\u2b06\ufe0f"
- UP_RIGHT_ARROW = "\u2197\ufe0f"
- RIGHT_ARROW = "\u27a1\ufe0f"
- DOWN_RIGHT_ARROW = "\u2198\ufe0f"
- DOWN_ARROW = "\u2b07\ufe0f"
- DOWN_LEFT_ARROW = "\u2199\ufe0f"
- LEFT_ARROW = "\u2b05\ufe0f"
- UP_LEFT_ARROW = "\u2196\ufe0f"
- UP_DOWN_ARROW = "\u2195\ufe0f"
- LEFT_RIGHT_ARROW = "\u2194\ufe0f"
- RIGHT_ARROW_CURVING_LEFT = "\u21a9\ufe0f"
- LEFT_ARROW_CURVING_RIGHT = "\u21aa\ufe0f"
- RIGHT_ARROW_CURVING_UP = "\u2934\ufe0f"
- RIGHT_ARROW_CURVING_DOWN = "\u2935\ufe0f"
- CLOCKWISE_VERTICAL_ARROWS = "\U0001f503"
- COUNTERCLOCKWISE_ARROWS_BUTTON = "\U0001f504"
- BACK_ARROW = "\U0001f519"
- END_ARROW = "\U0001f51a"
- ON_ARROW = "\U0001f51b"
- SOON_ARROW = "\U0001f51c"
- TOP_ARROW = "\U0001f51d"
- PLACE_OF_WORSHIP = "\U0001f6d0"
- ATOM_SYMBOL = "\u269b\ufe0f"
- INFINITY = "\u267e\ufe0f"
- OM = "\U0001f549\ufe0f"
- STAR_OF_DAVID = "\u2721\ufe0f"
- WHEEL_OF_DHARMA = "\u2638\ufe0f"
- YIN_YANG = "\u262f\ufe0f"
- LATIN_CROSS = "\u271d\ufe0f"
- ORTHODOX_CROSS = "\u2626\ufe0f"
- STAR_AND_CRESCENT = "\u262a\ufe0f"
- PEACE_SYMBOL = "\u262e\ufe0f"
- MENORAH = "\U0001f54e"
- DOTTED_SIX_POINTED_STAR = "\U0001f52f"
- ARIES = "\u2648"
- TAURUS = "\u2649"
- GEMINI = "\u264a"
- CANCER = "\u264b"
- LEO = "\u264c"
- VIRGO = "\u264d"
- LIBRA = "\u264e"
- SCORPIO = "\u264f"
- SAGITTARIUS = "\u2650"
- CAPRICORN = "\u2651"
- AQUARIUS = "\u2652"
- PISCES = "\u2653"
- OPHIUCHUS = "\u26ce"
- SHUFFLE_TRACKS_BUTTON = "\U0001f500"
- REPEAT_BUTTON = "\U0001f501"
- REPEAT_SINGLE_BUTTON = "\U0001f502"
- PLAY_BUTTON = "\u25b6\ufe0f"
- FAST_FORWARD_BUTTON = "\u23e9"
- NEXT_TRACK_BUTTON = "\u23ed\ufe0f"
- PLAY_OR_PAUSE_BUTTON = "\u23ef\ufe0f"
- REVERSE_BUTTON = "\u25c0\ufe0f"
- FAST_REVERSE_BUTTON = "\u23ea"
- LAST_TRACK_BUTTON = "\u23ee\ufe0f"
- UPWARDS_BUTTON = "\U0001f53c"
- FAST_UP_BUTTON = "\u23eb"
- DOWNWARDS_BUTTON = "\U0001f53d"
- FAST_DOWN_BUTTON = "\u23ec"
- PAUSE_BUTTON = "\u23f8\ufe0f"
- STOP_BUTTON = "\u23f9\ufe0f"
- RECORD_BUTTON = "\u23fa\ufe0f"
- EJECT_BUTTON = "\u23cf\ufe0f"
- CINEMA = "\U0001f3a6"
- DIM_BUTTON = "\U0001f505"
- BRIGHT_BUTTON = "\U0001f506"
- ANTENNA_BARS = "\U0001f4f6"
- VIBRATION_MODE = "\U0001f4f3"
- MOBILE_PHONE_OFF = "\U0001f4f4"
- FEMALE_SIGN = "\u2640\ufe0f"
- MALE_SIGN = "\u2642\ufe0f"
- MEDICAL_SYMBOL = "\u2695\ufe0f"
- RECYCLING_SYMBOL = "\u267b\ufe0f"
- FLEUR_DE_LIS = "\u269c\ufe0f"
- TRIDENT_EMBLEM = "\U0001f531"
- NAME_BADGE = "\U0001f4db"
- JAPANESE_SYMBOL_FOR_BEGINNER = "\U0001f530"
- HEAVY_LARGE_CIRCLE = "\u2b55"
- WHITE_HEAVY_CHECK_MARK = "\u2705"
- BALLOT_BOX_WITH_CHECK = "\u2611\ufe0f"
- HEAVY_CHECK_MARK = "\u2714\ufe0f"
- HEAVY_MULTIPLICATION_X = "\u2716\ufe0f"
- CROSS_MARK = "\u274c"
- CROSS_MARK_BUTTON = "\u274e"
- HEAVY_PLUS_SIGN = "\u2795"
- HEAVY_MINUS_SIGN = "\u2796"
- HEAVY_DIVISION_SIGN = "\u2797"
- CURLY_LOOP = "\u27b0"
- DOUBLE_CURLY_LOOP = "\u27bf"
- PART_ALTERNATION_MARK = "\u303d\ufe0f"
- EIGHT_SPOKED_ASTERISK = "\u2733\ufe0f"
- EIGHT_POINTED_STAR = "\u2734\ufe0f"
- SPARKLE = "\u2747\ufe0f"
- DOUBLE_EXCLAMATION_MARK = "\u203c\ufe0f"
- EXCLAMATION_QUESTION_MARK = "\u2049\ufe0f"
- QUESTION_MARK = "\u2753"
- WHITE_QUESTION_MARK = "\u2754"
- WHITE_EXCLAMATION_MARK = "\u2755"
- EXCLAMATION_MARK = "\u2757"
- WAVY_DASH = "\u3030\ufe0f"
- COPYRIGHT = "\xa9\ufe0f"
- REGISTERED = "\xae\ufe0f"
- TRADE_MARK = "\u2122\ufe0f"
- KEYCAP_NUMBER_SIGN = "#\ufe0f\u20e3"
- KEYCAP_ASTERISK = "*\ufe0f\u20e3"
- KEYCAP_DIGIT_ZERO = "0\ufe0f\u20e3"
- KEYCAP_DIGIT_ONE = "1\ufe0f\u20e3"
- KEYCAP_DIGIT_TWO = "2\ufe0f\u20e3"
- KEYCAP_DIGIT_THREE = "3\ufe0f\u20e3"
- KEYCAP_DIGIT_FOUR = "4\ufe0f\u20e3"
- KEYCAP_DIGIT_FIVE = "5\ufe0f\u20e3"
- KEYCAP_DIGIT_SIX = "6\ufe0f\u20e3"
- KEYCAP_DIGIT_SEVEN = "7\ufe0f\u20e3"
- KEYCAP_DIGIT_EIGHT = "8\ufe0f\u20e3"
- KEYCAP_DIGIT_NINE = "9\ufe0f\u20e3"
- KEYCAP_10 = "\U0001f51f"
- HUNDRED_POINTS = "\U0001f4af"
- INPUT_LATIN_UPPERCASE = "\U0001f520"
- INPUT_LATIN_LOWERCASE = "\U0001f521"
- INPUT_NUMBERS = "\U0001f522"
- INPUT_SYMBOLS = "\U0001f523"
- INPUT_LATIN_LETTERS = "\U0001f524"
- A_BUTTON_BLOOD_TYPE = "\U0001f170\ufe0f"
- AB_BUTTON_BLOOD_TYPE = "\U0001f18e"
- B_BUTTON_BLOOD_TYPE = "\U0001f171\ufe0f"
- CL_BUTTON = "\U0001f191"
- COOL_BUTTON = "\U0001f192"
- FREE_BUTTON = "\U0001f193"
- INFORMATION = "\u2139\ufe0f"
- ID_BUTTON = "\U0001f194"
- CIRCLED_M = "\u24c2\ufe0f"
- NEW_BUTTON = "\U0001f195"
- NG_BUTTON = "\U0001f196"
- O_BUTTON_BLOOD_TYPE = "\U0001f17e\ufe0f"
- OK_BUTTON = "\U0001f197"
- P_BUTTON = "\U0001f17f\ufe0f"
- SOS_BUTTON = "\U0001f198"
- UP_BUTTON = "\U0001f199"
- VS_BUTTON = "\U0001f19a"
- JAPANESE_HERE_BUTTON = "\U0001f201"
- JAPANESE_SERVICE_CHARGE_BUTTON = "\U0001f202\ufe0f"
- JAPANESE_MONTHLY_AMOUNT_BUTTON = "\U0001f237\ufe0f"
- JAPANESE_NOT_FREE_OF_CHARGE_BUTTON = "\U0001f236"
- JAPANESE_RESERVED_BUTTON = "\U0001f22f"
- JAPANESE_BARGAIN_BUTTON = "\U0001f250"
- JAPANESE_DISCOUNT_BUTTON = "\U0001f239"
- JAPANESE_FREE_OF_CHARGE_BUTTON = "\U0001f21a"
- JAPANESE_PROHIBITED_BUTTON = "\U0001f232"
- JAPANESE_ACCEPTABLE_BUTTON = "\U0001f251"
- JAPANESE_APPLICATION_BUTTON = "\U0001f238"
- JAPANESE_PASSING_GRADE_BUTTON = "\U0001f234"
- JAPANESE_VACANCY_BUTTON = "\U0001f233"
- JAPANESE_CONGRATULATIONS_BUTTON = "\u3297\ufe0f"
- JAPANESE_SECRET_BUTTON = "\u3299\ufe0f"
- JAPANESE_OPEN_FOR_BUSINESS_BUTTON = "\U0001f23a"
- JAPANESE_NO_VACANCY_BUTTON = "\U0001f235"
- BLACK_SMALL_SQUARE = "\u25aa\ufe0f"
- WHITE_SMALL_SQUARE = "\u25ab\ufe0f"
- WHITE_MEDIUM_SQUARE = "\u25fb\ufe0f"
- BLACK_MEDIUM_SQUARE = "\u25fc\ufe0f"
- WHITE_MEDIUM_SMALL_SQUARE = "\u25fd"
- BLACK_MEDIUM_SMALL_SQUARE = "\u25fe"
- BLACK_LARGE_SQUARE = "\u2b1b"
- WHITE_LARGE_SQUARE = "\u2b1c"
- LARGE_ORANGE_DIAMOND = "\U0001f536"
- LARGE_BLUE_DIAMOND = "\U0001f537"
- SMALL_ORANGE_DIAMOND = "\U0001f538"
- SMALL_BLUE_DIAMOND = "\U0001f539"
- RED_TRIANGLE_POINTED_UP = "\U0001f53a"
- RED_TRIANGLE_POINTED_DOWN = "\U0001f53b"
- DIAMOND_WITH_A_DOT = "\U0001f4a0"
- RADIO_BUTTON = "\U0001f518"
- BLACK_SQUARE_BUTTON = "\U0001f532"
- WHITE_SQUARE_BUTTON = "\U0001f533"
- WHITE_CIRCLE = "\u26aa"
- BLACK_CIRCLE = "\u26ab"
- RED_CIRCLE = "\U0001f534"
- BLUE_CIRCLE = "\U0001f535"
- CHEQUERED_FLAG = "\U0001f3c1"
- TRIANGULAR_FLAG = "\U0001f6a9"
- CROSSED_FLAGS = "\U0001f38c"
- BLACK_FLAG = "\U0001f3f4"
- WHITE_FLAG = "\U0001f3f3\ufe0f"
- RAINBOW_FLAG = "\U0001f3f3\ufe0f\u200d\U0001f308"
- PIRATE_FLAG = "\U0001f3f4\u200d\u2620\ufe0f"
- ASCENSION_ISLAND = "\U0001f1e6\U0001f1e8"
- ANDORRA = "\U0001f1e6\U0001f1e9"
- UNITED_ARAB_EMIRATES = "\U0001f1e6\U0001f1ea"
- AFGHANISTAN = "\U0001f1e6\U0001f1eb"
- ANTIGUA_AND_BARBUDA = "\U0001f1e6\U0001f1ec"
- ANGUILLA = "\U0001f1e6\U0001f1ee"
- ALBANIA = "\U0001f1e6\U0001f1f1"
- ARMENIA = "\U0001f1e6\U0001f1f2"
- ANGOLA = "\U0001f1e6\U0001f1f4"
- ANTARCTICA = "\U0001f1e6\U0001f1f6"
- ARGENTINA = "\U0001f1e6\U0001f1f7"
- AMERICAN_SAMOA = "\U0001f1e6\U0001f1f8"
- AUSTRIA = "\U0001f1e6\U0001f1f9"
- AUSTRALIA = "\U0001f1e6\U0001f1fa"
- ARUBA = "\U0001f1e6\U0001f1fc"
- ALAND_ISLANDS = "\U0001f1e6\U0001f1fd"
- AZERBAIJAN = "\U0001f1e6\U0001f1ff"
- BOSNIA_AND_HERZEGOVINA = "\U0001f1e7\U0001f1e6"
- BARBADOS = "\U0001f1e7\U0001f1e7"
- BANGLADESH = "\U0001f1e7\U0001f1e9"
- BELGIUM = "\U0001f1e7\U0001f1ea"
- BURKINA_FASO = "\U0001f1e7\U0001f1eb"
- BULGARIA = "\U0001f1e7\U0001f1ec"
- BAHRAIN = "\U0001f1e7\U0001f1ed"
- BURUNDI = "\U0001f1e7\U0001f1ee"
- BENIN = "\U0001f1e7\U0001f1ef"
- ST_BARTHELEMY = "\U0001f1e7\U0001f1f1"
- BERMUDA = "\U0001f1e7\U0001f1f2"
- BRUNEI = "\U0001f1e7\U0001f1f3"
- BOLIVIA = "\U0001f1e7\U0001f1f4"
- CARIBBEAN_NETHERLANDS = "\U0001f1e7\U0001f1f6"
- BRAZIL = "\U0001f1e7\U0001f1f7"
- BAHAMAS = "\U0001f1e7\U0001f1f8"
- BHUTAN = "\U0001f1e7\U0001f1f9"
- BOUVET_ISLAND = "\U0001f1e7\U0001f1fb"
- BOTSWANA = "\U0001f1e7\U0001f1fc"
- BELARUS = "\U0001f1e7\U0001f1fe"
- BELIZE = "\U0001f1e7\U0001f1ff"
- CANADA = "\U0001f1e8\U0001f1e6"
- COCOS_KEELING_ISLANDS = "\U0001f1e8\U0001f1e8"
- CONGO_KINSHASA = "\U0001f1e8\U0001f1e9"
- CENTRAL_AFRICAN_REPUBLIC = "\U0001f1e8\U0001f1eb"
- CONGO_BRAZZAVILLE = "\U0001f1e8\U0001f1ec"
- SWITZERLAND = "\U0001f1e8\U0001f1ed"
- COTE_D_IVOIRE = "\U0001f1e8\U0001f1ee"
- COOK_ISLANDS = "\U0001f1e8\U0001f1f0"
- CHILE = "\U0001f1e8\U0001f1f1"
- CAMEROON = "\U0001f1e8\U0001f1f2"
- CHINA = "\U0001f1e8\U0001f1f3"
- COLOMBIA = "\U0001f1e8\U0001f1f4"
- CLIPPERTON_ISLAND = "\U0001f1e8\U0001f1f5"
- COSTA_RICA = "\U0001f1e8\U0001f1f7"
- CUBA = "\U0001f1e8\U0001f1fa"
- CAPE_VERDE = "\U0001f1e8\U0001f1fb"
- CURACAO = "\U0001f1e8\U0001f1fc"
- CHRISTMAS_ISLAND = "\U0001f1e8\U0001f1fd"
- CYPRUS = "\U0001f1e8\U0001f1fe"
- CZECHIA = "\U0001f1e8\U0001f1ff"
- GERMANY = "\U0001f1e9\U0001f1ea"
- DIEGO_GARCIA = "\U0001f1e9\U0001f1ec"
- DJIBOUTI = "\U0001f1e9\U0001f1ef"
- DENMARK = "\U0001f1e9\U0001f1f0"
- DOMINICA = "\U0001f1e9\U0001f1f2"
- DOMINICAN_REPUBLIC = "\U0001f1e9\U0001f1f4"
- ALGERIA = "\U0001f1e9\U0001f1ff"
- CEUTA_AND_MELILLA = "\U0001f1ea\U0001f1e6"
- ECUADOR = "\U0001f1ea\U0001f1e8"
- ESTONIA = "\U0001f1ea\U0001f1ea"
- EGYPT = "\U0001f1ea\U0001f1ec"
- WESTERN_SAHARA = "\U0001f1ea\U0001f1ed"
- ERITREA = "\U0001f1ea\U0001f1f7"
- SPAIN = "\U0001f1ea\U0001f1f8"
- ETHIOPIA = "\U0001f1ea\U0001f1f9"
- EUROPEAN_UNION = "\U0001f1ea\U0001f1fa"
- FINLAND = "\U0001f1eb\U0001f1ee"
- FIJI = "\U0001f1eb\U0001f1ef"
- FALKLAND_ISLANDS = "\U0001f1eb\U0001f1f0"
- MICRONESIA = "\U0001f1eb\U0001f1f2"
- FAROE_ISLANDS = "\U0001f1eb\U0001f1f4"
- FRANCE = "\U0001f1eb\U0001f1f7"
- GABON = "\U0001f1ec\U0001f1e6"
- UNITED_KINGDOM = "\U0001f1ec\U0001f1e7"
- GRENADA = "\U0001f1ec\U0001f1e9"
- GEORGIA = "\U0001f1ec\U0001f1ea"
- FRENCH_GUIANA = "\U0001f1ec\U0001f1eb"
- GUERNSEY = "\U0001f1ec\U0001f1ec"
- GHANA = "\U0001f1ec\U0001f1ed"
- GIBRALTAR = "\U0001f1ec\U0001f1ee"
- GREENLAND = "\U0001f1ec\U0001f1f1"
- GAMBIA = "\U0001f1ec\U0001f1f2"
- GUINEA = "\U0001f1ec\U0001f1f3"
- GUADELOUPE = "\U0001f1ec\U0001f1f5"
- EQUATORIAL_GUINEA = "\U0001f1ec\U0001f1f6"
- GREECE = "\U0001f1ec\U0001f1f7"
- SOUTH_GEORGIA_AND_SOUTH_SANDWICH_ISLANDS = "\U0001f1ec\U0001f1f8"
- GUATEMALA = "\U0001f1ec\U0001f1f9"
- GUAM = "\U0001f1ec\U0001f1fa"
- GUINEA_BISSAU = "\U0001f1ec\U0001f1fc"
- GUYANA = "\U0001f1ec\U0001f1fe"
- HONG_KONG_SAR_CHINA = "\U0001f1ed\U0001f1f0"
- HEARD_AND_MCDONALD_ISLANDS = "\U0001f1ed\U0001f1f2"
- HONDURAS = "\U0001f1ed\U0001f1f3"
- CROATIA = "\U0001f1ed\U0001f1f7"
- HAITI = "\U0001f1ed\U0001f1f9"
- HUNGARY = "\U0001f1ed\U0001f1fa"
- CANARY_ISLANDS = "\U0001f1ee\U0001f1e8"
- INDONESIA = "\U0001f1ee\U0001f1e9"
- IRELAND = "\U0001f1ee\U0001f1ea"
- ISRAEL = "\U0001f1ee\U0001f1f1"
- ISLE_OF_MAN = "\U0001f1ee\U0001f1f2"
- INDIA = "\U0001f1ee\U0001f1f3"
- BRITISH_INDIAN_OCEAN_TERRITORY = "\U0001f1ee\U0001f1f4"
- IRAQ = "\U0001f1ee\U0001f1f6"
- IRAN = "\U0001f1ee\U0001f1f7"
- ICELAND = "\U0001f1ee\U0001f1f8"
- ITALY = "\U0001f1ee\U0001f1f9"
- JERSEY = "\U0001f1ef\U0001f1ea"
- JAMAICA = "\U0001f1ef\U0001f1f2"
- JORDAN = "\U0001f1ef\U0001f1f4"
- JAPAN = "\U0001f1ef\U0001f1f5"
- KENYA = "\U0001f1f0\U0001f1ea"
- KYRGYZSTAN = "\U0001f1f0\U0001f1ec"
- CAMBODIA = "\U0001f1f0\U0001f1ed"
- KIRIBATI = "\U0001f1f0\U0001f1ee"
- COMOROS = "\U0001f1f0\U0001f1f2"
- ST_KITTS_AND_NEVIS = "\U0001f1f0\U0001f1f3"
- NORTH_KOREA = "\U0001f1f0\U0001f1f5"
- SOUTH_KOREA = "\U0001f1f0\U0001f1f7"
- KUWAIT = "\U0001f1f0\U0001f1fc"
- CAYMAN_ISLANDS = "\U0001f1f0\U0001f1fe"
- KAZAKHSTAN = "\U0001f1f0\U0001f1ff"
- LAOS = "\U0001f1f1\U0001f1e6"
- LEBANON = "\U0001f1f1\U0001f1e7"
- ST_LUCIA = "\U0001f1f1\U0001f1e8"
- LIECHTENSTEIN = "\U0001f1f1\U0001f1ee"
- SRI_LANKA = "\U0001f1f1\U0001f1f0"
- LIBERIA = "\U0001f1f1\U0001f1f7"
- LESOTHO = "\U0001f1f1\U0001f1f8"
- LITHUANIA = "\U0001f1f1\U0001f1f9"
- LUXEMBOURG = "\U0001f1f1\U0001f1fa"
- LATVIA = "\U0001f1f1\U0001f1fb"
- LIBYA = "\U0001f1f1\U0001f1fe"
- MOROCCO = "\U0001f1f2\U0001f1e6"
- MONACO = "\U0001f1f2\U0001f1e8"
- MOLDOVA = "\U0001f1f2\U0001f1e9"
- MONTENEGRO = "\U0001f1f2\U0001f1ea"
- ST_MARTIN = "\U0001f1f2\U0001f1eb"
- MADAGASCAR = "\U0001f1f2\U0001f1ec"
- MARSHALL_ISLANDS = "\U0001f1f2\U0001f1ed"
- MACEDONIA = "\U0001f1f2\U0001f1f0"
- MALI = "\U0001f1f2\U0001f1f1"
- MYANMAR_BURMA = "\U0001f1f2\U0001f1f2"
- MONGOLIA = "\U0001f1f2\U0001f1f3"
- MACAU_SAR_CHINA = "\U0001f1f2\U0001f1f4"
- NORTHERN_MARIANA_ISLANDS = "\U0001f1f2\U0001f1f5"
- MARTINIQUE = "\U0001f1f2\U0001f1f6"
- MAURITANIA = "\U0001f1f2\U0001f1f7"
- MONTSERRAT = "\U0001f1f2\U0001f1f8"
- MALTA = "\U0001f1f2\U0001f1f9"
- MAURITIUS = "\U0001f1f2\U0001f1fa"
- MALDIVES = "\U0001f1f2\U0001f1fb"
- MALAWI = "\U0001f1f2\U0001f1fc"
- MEXICO = "\U0001f1f2\U0001f1fd"
- MALAYSIA = "\U0001f1f2\U0001f1fe"
- MOZAMBIQUE = "\U0001f1f2\U0001f1ff"
- NAMIBIA = "\U0001f1f3\U0001f1e6"
- NEW_CALEDONIA = "\U0001f1f3\U0001f1e8"
- NIGER = "\U0001f1f3\U0001f1ea"
- NORFOLK_ISLAND = "\U0001f1f3\U0001f1eb"
- NIGERIA = "\U0001f1f3\U0001f1ec"
- NICARAGUA = "\U0001f1f3\U0001f1ee"
- NETHERLANDS = "\U0001f1f3\U0001f1f1"
- NORWAY = "\U0001f1f3\U0001f1f4"
- NEPAL = "\U0001f1f3\U0001f1f5"
- NAURU = "\U0001f1f3\U0001f1f7"
- NIUE = "\U0001f1f3\U0001f1fa"
- NEW_ZEALAND = "\U0001f1f3\U0001f1ff"
- OMAN = "\U0001f1f4\U0001f1f2"
- PANAMA = "\U0001f1f5\U0001f1e6"
- PERU = "\U0001f1f5\U0001f1ea"
- FRENCH_POLYNESIA = "\U0001f1f5\U0001f1eb"
- PAPUA_NEW_GUINEA = "\U0001f1f5\U0001f1ec"
- PHILIPPINES = "\U0001f1f5\U0001f1ed"
- PAKISTAN = "\U0001f1f5\U0001f1f0"
- POLAND = "\U0001f1f5\U0001f1f1"
- ST_PIERRE_AND_MIQUELON = "\U0001f1f5\U0001f1f2"
- PITCAIRN_ISLANDS = "\U0001f1f5\U0001f1f3"
- PUERTO_RICO = "\U0001f1f5\U0001f1f7"
- PALESTINIAN_TERRITORIES = "\U0001f1f5\U0001f1f8"
- PORTUGAL = "\U0001f1f5\U0001f1f9"
- PALAU = "\U0001f1f5\U0001f1fc"
- PARAGUAY = "\U0001f1f5\U0001f1fe"
- QATAR = "\U0001f1f6\U0001f1e6"
- REUNION = "\U0001f1f7\U0001f1ea"
- ROMANIA = "\U0001f1f7\U0001f1f4"
- SERBIA = "\U0001f1f7\U0001f1f8"
- RUSSIA = "\U0001f1f7\U0001f1fa"
- RWANDA = "\U0001f1f7\U0001f1fc"
- SAUDI_ARABIA = "\U0001f1f8\U0001f1e6"
- SOLOMON_ISLANDS = "\U0001f1f8\U0001f1e7"
- SEYCHELLES = "\U0001f1f8\U0001f1e8"
- SUDAN = "\U0001f1f8\U0001f1e9"
- SWEDEN = "\U0001f1f8\U0001f1ea"
- SINGAPORE = "\U0001f1f8\U0001f1ec"
- ST_HELENA = "\U0001f1f8\U0001f1ed"
- SLOVENIA = "\U0001f1f8\U0001f1ee"
- SVALBARD_AND_JAN_MAYEN = "\U0001f1f8\U0001f1ef"
- SLOVAKIA = "\U0001f1f8\U0001f1f0"
- SIERRA_LEONE = "\U0001f1f8\U0001f1f1"
- SAN_MARINO = "\U0001f1f8\U0001f1f2"
- SENEGAL = "\U0001f1f8\U0001f1f3"
- SOMALIA = "\U0001f1f8\U0001f1f4"
- SURINAME = "\U0001f1f8\U0001f1f7"
- SOUTH_SUDAN = "\U0001f1f8\U0001f1f8"
- SAO_TOME_AND_PRINCIPE = "\U0001f1f8\U0001f1f9"
- EL_SALVADOR = "\U0001f1f8\U0001f1fb"
- SINT_MAARTEN = "\U0001f1f8\U0001f1fd"
- SYRIA = "\U0001f1f8\U0001f1fe"
- SWAZILAND = "\U0001f1f8\U0001f1ff"
- TRISTAN_DA_CUNHA = "\U0001f1f9\U0001f1e6"
- TURKS_AND_CAICOS_ISLANDS = "\U0001f1f9\U0001f1e8"
- CHAD = "\U0001f1f9\U0001f1e9"
- FRENCH_SOUTHERN_TERRITORIES = "\U0001f1f9\U0001f1eb"
- TOGO = "\U0001f1f9\U0001f1ec"
- THAILAND = "\U0001f1f9\U0001f1ed"
- TAJIKISTAN = "\U0001f1f9\U0001f1ef"
- TOKELAU = "\U0001f1f9\U0001f1f0"
- TIMOR_LESTE = "\U0001f1f9\U0001f1f1"
- TURKMENISTAN = "\U0001f1f9\U0001f1f2"
- TUNISIA = "\U0001f1f9\U0001f1f3"
- TONGA = "\U0001f1f9\U0001f1f4"
- TURKEY = "\U0001f1f9\U0001f1f7"
- TRINIDAD_AND_TOBAGO = "\U0001f1f9\U0001f1f9"
- TUVALU = "\U0001f1f9\U0001f1fb"
- TAIWAN = "\U0001f1f9\U0001f1fc"
- TANZANIA = "\U0001f1f9\U0001f1ff"
- UKRAINE = "\U0001f1fa\U0001f1e6"
- UGANDA = "\U0001f1fa\U0001f1ec"
- U_S_OUTLYING_ISLANDS = "\U0001f1fa\U0001f1f2"
- UNITED_NATIONS = "\U0001f1fa\U0001f1f3"
- UNITED_STATES = "\U0001f1fa\U0001f1f8"
- URUGUAY = "\U0001f1fa\U0001f1fe"
- UZBEKISTAN = "\U0001f1fa\U0001f1ff"
- VATICAN_CITY = "\U0001f1fb\U0001f1e6"
- ST_VINCENT_AND_GRENADINES = "\U0001f1fb\U0001f1e8"
- VENEZUELA = "\U0001f1fb\U0001f1ea"
- BRITISH_VIRGIN_ISLANDS = "\U0001f1fb\U0001f1ec"
- U_S_VIRGIN_ISLANDS = "\U0001f1fb\U0001f1ee"
- VIETNAM = "\U0001f1fb\U0001f1f3"
- VANUATU = "\U0001f1fb\U0001f1fa"
- WALLIS_AND_FUTUNA = "\U0001f1fc\U0001f1eb"
- SAMOA = "\U0001f1fc\U0001f1f8"
- KOSOVO = "\U0001f1fd\U0001f1f0"
- YEMEN = "\U0001f1fe\U0001f1ea"
- MAYOTTE = "\U0001f1fe\U0001f1f9"
- SOUTH_AFRICA = "\U0001f1ff\U0001f1e6"
- ZAMBIA = "\U0001f1ff\U0001f1f2"
- ZIMBABWE = "\U0001f1ff\U0001f1fc"
- ENGLAND = "\U0001f3f4\U000e0067\U000e0062\U000e0065\U000e006e\U000e0067\U000e007f"
- SCOTLAND = "\U0001f3f4\U000e0067\U000e0062\U000e0073\U000e0063\U000e0074\U000e007f"
- WALES = "\U0001f3f4\U000e0067\U000e0062\U000e0077\U000e006c\U000e0073\U000e007f"
- MODERN_PENTATHLON = "\U0001f93b"
- RIFLE = "\U0001f946"
- REGIONAL_INDICATOR_SYMBOL_LETTER_A = "\U0001f1e6"
- REGIONAL_INDICATOR_SYMBOL_LETTER_B = "\U0001f1e7"
- REGIONAL_INDICATOR_SYMBOL_LETTER_C = "\U0001f1e8"
- REGIONAL_INDICATOR_SYMBOL_LETTER_D = "\U0001f1e9"
- REGIONAL_INDICATOR_SYMBOL_LETTER_E = "\U0001f1ea"
- REGIONAL_INDICATOR_SYMBOL_LETTER_F = "\U0001f1eb"
- REGIONAL_INDICATOR_SYMBOL_LETTER_G = "\U0001f1ec"
- REGIONAL_INDICATOR_SYMBOL_LETTER_H = "\U0001f1ed"
- REGIONAL_INDICATOR_SYMBOL_LETTER_I = "\U0001f1ee"
- REGIONAL_INDICATOR_SYMBOL_LETTER_J = "\U0001f1ef"
- REGIONAL_INDICATOR_SYMBOL_LETTER_K = "\U0001f1f0"
- REGIONAL_INDICATOR_SYMBOL_LETTER_L = "\U0001f1f1"
- REGIONAL_INDICATOR_SYMBOL_LETTER_M = "\U0001f1f2"
- REGIONAL_INDICATOR_SYMBOL_LETTER_N = "\U0001f1f3"
- REGIONAL_INDICATOR_SYMBOL_LETTER_O = "\U0001f1f4"
- REGIONAL_INDICATOR_SYMBOL_LETTER_P = "\U0001f1f5"
- REGIONAL_INDICATOR_SYMBOL_LETTER_Q = "\U0001f1f6"
- REGIONAL_INDICATOR_SYMBOL_LETTER_R = "\U0001f1f7"
- REGIONAL_INDICATOR_SYMBOL_LETTER_S = "\U0001f1f8"
- REGIONAL_INDICATOR_SYMBOL_LETTER_T = "\U0001f1f9"
- REGIONAL_INDICATOR_SYMBOL_LETTER_U = "\U0001f1fa"
- REGIONAL_INDICATOR_SYMBOL_LETTER_V = "\U0001f1fb"
- REGIONAL_INDICATOR_SYMBOL_LETTER_W = "\U0001f1fc"
- REGIONAL_INDICATOR_SYMBOL_LETTER_X = "\U0001f1fd"
- REGIONAL_INDICATOR_SYMBOL_LETTER_Y = "\U0001f1fe"
- REGIONAL_INDICATOR_SYMBOL_LETTER_Z = "\U0001f1ff"
- DINO_CAT = "\U0001f431\u200d\U0001f409"
- NINJA_CAT = "\U0001f431\u200d\U0001f464"
- STUNT_CAT = "\U0001f431\u200d\U0001f3cd"
- ASTRO_CAT = "\U0001f431\u200d\U0001f680"
- HACKER_CAT = "\U0001f431\u200d\U0001f4bb"
- HIPSTER_CAT = "\U0001f431\u200d\U0001f453"
- OLYMPIC_RINGS = "\u25ef\u200d\u25ef\u200d\u25ef\u200d\u25ef\u200d\u25ef"
- FLAG_FOR_SUKHBAATAR_MN_051 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0035\U000e0031\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb"
- FLAG_FOR_ORKHON_MN_035 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0033\U000e0035\U000e007f"
- FLAG_FOR_TIRIS_ZEMMOUR_MR_11 = "\U0001f3f4\U000e006d\U000e0072\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_KHOVD_MN_043 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0034\U000e0033\U000e007f"
- FLAG_FOR_ASSABA_MR_03 = "\U0001f3f4\U000e006d\U000e0072\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_BRAKNA_MR_05 = "\U0001f3f4\U000e006d\U000e0072\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_GORGOL_MR_04 = "\U0001f3f4\U000e006d\U000e0072\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_ARKHANGAI_MN_073 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0037\U000e0033\U000e007f"
- FLAG_FOR_AKMOLA_KZ_AKM = "\U0001f3f4\U000e006b\U000e007a\U000e0061\U000e006b\U000e006d\U000e007f"
- FLAG_FOR_BIRKIRKARA_MT_04 = "\U0001f3f4\U000e006d\U000e0074\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_IKLIN_MT_19 = "\U0001f3f4\U000e006d\U000e0074\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_NAXXAR_MT_38 = "\U0001f3f4\U000e006d\U000e0074\U000e0033\U000e0038\U000e007f"
- FLAG_FOR_KALKARA_MT_21 = "\U0001f3f4\U000e006d\U000e0074\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_FONTANA_MT_10 = "\U0001f3f4\U000e006d\U000e0074\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_LIJA_MT_24 = "\U0001f3f4\U000e006d\U000e0074\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_FGURA_MT_08 = "\U0001f3f4\U000e006d\U000e0074\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_GUDJA_MT_11 = "\U0001f3f4\U000e006d\U000e0074\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_NOUAKCHOTT_SUD_MR_15 = "\U0001f3f4\U000e006d\U000e0072\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_MUNXAR_MT_36 = "\U0001f3f4\U000e006d\U000e0074\U000e0033\U000e0036\U000e007f"
- FLAG_FOR_G_AJNSIELEM_MT_13 = "\U0001f3f4\U000e006d\U000e0074\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_BIRGU_MT_03 = "\U0001f3f4\U000e006d\U000e0074\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_ATTARD_MT_01 = "\U0001f3f4\U000e006d\U000e0074\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_AMRUN_MT_18 = "\U0001f3f4\U000e006d\U000e0074\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_G_ARB_MT_14 = "\U0001f3f4\U000e006d\U000e0074\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_MARSAXLOKK_MT_28 = "\U0001f3f4\U000e006d\U000e0074\U000e0032\U000e0038\U000e007f"
- FLAG_FOR_G_AXAQ_MT_17 = "\U0001f3f4\U000e006d\U000e0074\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_MQABBA_MT_33 = "\U0001f3f4\U000e006d\U000e0074\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_GZIRA_MT_12 = "\U0001f3f4\U000e006d\U000e0074\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_NADUR_MT_37 = "\U0001f3f4\U000e006d\U000e0074\U000e0033\U000e0037\U000e007f"
- FLAG_FOR_MOSTA_MT_32 = "\U0001f3f4\U000e006d\U000e0074\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_MELLIE_A_MT_30 = "\U0001f3f4\U000e006d\U000e0074\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_PAOLA_MT_39 = "\U0001f3f4\U000e006d\U000e0074\U000e0033\U000e0039\U000e007f"
- FLAG_FOR_KERCEM_MT_22 = "\U0001f3f4\U000e006d\U000e0074\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_KIRKOP_MT_23 = "\U0001f3f4\U000e006d\U000e0074\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_MSIDA_MT_34 = "\U0001f3f4\U000e006d\U000e0074\U000e0033\U000e0034\U000e007f"
- FLAG_FOR_DINGLI_MT_07 = "\U0001f3f4\U000e006d\U000e0074\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_FLORIANA_MT_09 = "\U0001f3f4\U000e006d\U000e0074\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_COSPICUA_MT_06 = "\U0001f3f4\U000e006d\U000e0074\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_NOUAKCHOTT_NORD_MR_14 = "\U0001f3f4\U000e006d\U000e0072\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_G_ARG_UR_MT_15 = "\U0001f3f4\U000e006d\U000e0074\U000e0031\U000e0035\U000e007f"
- COUPLE_WITH_HEART_WOMAN_DARK_SKIN_TONE_WOMAN = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469"
- FLAG_FOR_IMTARFA_MT_35 = "\U0001f3f4\U000e006d\U000e0074\U000e0033\U000e0035\U000e007f"
- FLAG_FOR_BIRZEBBUGA_MT_05 = "\U0001f3f4\U000e006d\U000e0074\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_BALZAN_MT_02 = "\U0001f3f4\U000e006d\U000e0074\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_REDANGE_LU_RD = "\U0001f3f4\U000e006c\U000e0075\U000e0072\U000e0064\U000e007f"
- FLAG_FOR_VALLETTA_MT_60 = "\U0001f3f4\U000e006d\U000e0074\U000e0036\U000e0030\U000e007f"
- FLAG_FOR_QRENDI_MT_44 = "\U0001f3f4\U000e006d\U000e0074\U000e0034\U000e0034\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_FLACQ_MU_FL = "\U0001f3f4\U000e006d\U000e0075\U000e0066\U000e006c\U000e007f"
- FLAG_FOR_SANTA_LUCIJA_MT_53 = "\U0001f3f4\U000e006d\U000e0074\U000e0035\U000e0033\U000e007f"
- FLAG_FOR_ZEJTUN_MT_67 = "\U0001f3f4\U000e006d\U000e0074\U000e0036\U000e0037\U000e007f"
- FLAG_FOR_FUNAFUTI_TV_FUN = "\U0001f3f4\U000e0074\U000e0076\U000e0066\U000e0075\U000e006e\U000e007f"
- FLAG_FOR_PEMBROKE_MT_40 = "\U0001f3f4\U000e006d\U000e0074\U000e0034\U000e0030\U000e007f"
- FLAG_FOR_CUREPIPE_MU_CU = "\U0001f3f4\U000e006d\U000e0075\U000e0063\U000e0075\U000e007f"
- FLAG_FOR_ZURRIEQ_MT_68 = "\U0001f3f4\U000e006d\U000e0074\U000e0036\U000e0038\U000e007f"
- FLAG_FOR_QORMI_MT_43 = "\U0001f3f4\U000e006d\U000e0074\U000e0034\U000e0033\U000e007f"
- FLAG_FOR_SAINT_LAWRENCE_MT_50 = "\U0001f3f4\U000e006d\U000e0074\U000e0035\U000e0030\U000e007f"
- FLAG_FOR_ZABBAR_MT_64 = "\U0001f3f4\U000e006d\U000e0074\U000e0036\U000e0034\U000e007f"
- FLAG_FOR_PAMPLEMOUSSES_MU_PA = "\U0001f3f4\U000e006d\U000e0075\U000e0070\U000e0061\U000e007f"
- FLAG_FOR_QALA_MT_42 = "\U0001f3f4\U000e006d\U000e0074\U000e0034\U000e0032\U000e007f"
- FLAG_FOR_SLIEMA_MT_56 = "\U0001f3f4\U000e006d\U000e0074\U000e0035\U000e0036\U000e007f"
- FLAG_FOR_TARXIEN_MT_59 = "\U0001f3f4\U000e006d\U000e0074\U000e0035\U000e0039\U000e007f"
- FLAG_FOR_TA_XBIEX_MT_58 = "\U0001f3f4\U000e006d\U000e0074\U000e0035\U000e0038\U000e007f"
- KISS_WOMAN_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe"
- FLAG_FOR_XAG_RA_MT_61 = "\U0001f3f4\U000e006d\U000e0074\U000e0036\U000e0031\U000e007f"
- FLAG_FOR_SWIEQI_MT_57 = "\U0001f3f4\U000e006d\U000e0074\U000e0035\U000e0037\U000e007f"
- FLAG_FOR_SAN_GWANN_MT_49 = "\U0001f3f4\U000e006d\U000e0074\U000e0034\U000e0039\U000e007f"
- FLAG_FOR_ZEBBUG_MT_66 = "\U0001f3f4\U000e006d\U000e0074\U000e0036\U000e0036\U000e007f"
- FLAG_FOR_SIGGIEWI_MT_55 = "\U0001f3f4\U000e006d\U000e0074\U000e0035\U000e0035\U000e007f"
- FLAG_FOR_PORT_LOUIS_MU_PU = "\U0001f3f4\U000e006d\U000e0075\U000e0070\U000e0075\U000e007f"
- FLAG_FOR_SANTA_VENERA_MT_54 = "\U0001f3f4\U000e006d\U000e0074\U000e0035\U000e0034\U000e007f"
- FLAG_FOR_XG_AJRA_MT_63 = "\U0001f3f4\U000e006d\U000e0074\U000e0036\U000e0033\U000e007f"
- FLAG_FOR_CENTRAL_MW_C = "\U0001f3f4\U000e006d\U000e0077\U000e0063\U000e007f"
- FLAG_FOR_SOUTH_PROVINCE_MV_SU = "\U0001f3f4\U000e006d\U000e0076\U000e0073\U000e0075\U000e007f"
- FLAG_FOR_TRIESENBERG_LI_10 = "\U0001f3f4\U000e006c\U000e0069\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_VACOAS_PHOENIX_MU_VP = "\U0001f3f4\U000e006d\U000e0075\U000e0076\U000e0070\U000e007f"
- FLAG_FOR_ANENII_NOI_MD_AN = "\U0001f3f4\U000e006d\U000e0064\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_GUANAJUATO_MX_GUA = "\U0001f3f4\U000e006d\U000e0078\U000e0067\U000e0075\U000e0061\U000e007f"
- FLAG_FOR_MALE_MV_MLE = "\U0001f3f4\U000e006d\U000e0076\U000e006d\U000e006c\U000e0065\U000e007f"
- FLAG_FOR_OAXACA_MX_OAX = "\U0001f3f4\U000e006d\U000e0078\U000e006f\U000e0061\U000e0078\U000e007f"
- FLAG_FOR_CENTRAL_PROVINCE_MV_CE = "\U0001f3f4\U000e006d\U000e0076\U000e0063\U000e0065\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_MUNSTER_IE_M = "\U0001f3f4\U000e0069\U000e0065\U000e006d\U000e007f"
- FLAG_FOR_MANGYSTAU_KZ_MAN = "\U0001f3f4\U000e006b\U000e007a\U000e006d\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_BAJA_CALIFORNIA_SUR_MX_BCS = "\U0001f3f4\U000e006d\U000e0078\U000e0062\U000e0063\U000e0073\U000e007f"
- FLAG_FOR_CAMPECHE_MX_CAM = "\U0001f3f4\U000e006d\U000e0078\U000e0063\U000e0061\U000e006d\U000e007f"
- FLAG_FOR_KYOTO_JP_26 = "\U0001f3f4\U000e006a\U000e0070\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_KOHGILUYEH_AND_BOYER_AHMAD_IR_18 = "\U0001f3f4\U000e0069\U000e0072\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_HIDALGO_MX_HID = "\U0001f3f4\U000e006d\U000e0078\U000e0068\U000e0069\U000e0064\U000e007f"
- FLAG_FOR_CHLEF_DZ_02 = "\U0001f3f4\U000e0064\U000e007a\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_QUATRE_BORNES_MU_QB = "\U0001f3f4\U000e006d\U000e0075\U000e0071\U000e0062\U000e007f"
- FLAG_FOR_PLAINES_WILHEMS_MU_PW = "\U0001f3f4\U000e006d\U000e0075\U000e0070\U000e0077\U000e007f"
- FLAG_FOR_SAVANNE_MU_SA = "\U0001f3f4\U000e006d\U000e0075\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_SOUTHERN_MW_S = "\U0001f3f4\U000e006d\U000e0077\U000e0073\U000e007f"
- FLAG_FOR_COAHUILA_MX_COA = "\U0001f3f4\U000e006d\U000e0078\U000e0063\U000e006f\U000e0061\U000e007f"
- FLAG_FOR_NEGERI_SEMBILAN_MY_05 = "\U0001f3f4\U000e006d\U000e0079\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_SOFALA_MZ_S = "\U0001f3f4\U000e006d\U000e007a\U000e0073\U000e007f"
- FLAG_FOR_LABUAN_MY_15 = "\U0001f3f4\U000e006d\U000e0079\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_NUEVO_LEON_MX_NLE = "\U0001f3f4\U000e006d\U000e0078\U000e006e\U000e006c\U000e0065\U000e007f"
- FLAG_FOR_LA_SOURCE_MC_SO = "\U0001f3f4\U000e006d\U000e0063\U000e0073\U000e006f\U000e007f"
- FLAG_FOR_SOUTH_GYEONGSANG_KR_48 = "\U0001f3f4\U000e006b\U000e0072\U000e0034\U000e0038\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FLAG_FOR_GAZA_MZ_G = "\U0001f3f4\U000e006d\U000e007a\U000e0067\U000e007f"
- TAG_GRAVE_ACCENT = "\U000e0060"
- FLAG_FOR_MALACCA_MY_04 = "\U0001f3f4\U000e006d\U000e0079\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_CABO_DELGADO_MZ_P = "\U0001f3f4\U000e006d\U000e007a\U000e0070\U000e007f"
- FLAG_FOR_TLAXCALA_MX_TLA = "\U0001f3f4\U000e006d\U000e0078\U000e0074\U000e006c\U000e0061\U000e007f"
- FLAG_FOR_APULIA_IT_75 = "\U0001f3f4\U000e0069\U000e0074\U000e0037\U000e0035\U000e007f"
- FLAG_FOR_NAMPULA_MZ_N = "\U0001f3f4\U000e006d\U000e007a\U000e006e\U000e007f"
- FLAG_FOR_OGOOUE_LOLO_GA_7 = "\U0001f3f4\U000e0067\U000e0061\U000e0037\U000e007f"
- FLAG_FOR_ERONGO_NA_ER = "\U0001f3f4\U000e006e\U000e0061\U000e0065\U000e0072\U000e007f"
- FLAG_FOR_TETE_MZ_T = "\U0001f3f4\U000e006d\U000e007a\U000e0074\U000e007f"
- FLAG_FOR_UPPER_NORTH_PROVINCE_MV_UN = "\U0001f3f4\U000e006d\U000e0076\U000e0075\U000e006e\U000e007f"
- FLAG_FOR_MANICA_MZ_B = "\U0001f3f4\U000e006d\U000e007a\U000e0062\U000e007f"
- FLAG_FOR_PUTRAJAYA_MY_16 = "\U0001f3f4\U000e006d\U000e0079\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_MAPUTO_MZ_MPM = "\U0001f3f4\U000e006d\U000e007a\U000e006d\U000e0070\U000e006d\U000e007f"
- FLAG_FOR_HARDAP_NA_HA = "\U0001f3f4\U000e006e\U000e0061\U000e0068\U000e0061\U000e007f"
- FLAG_FOR_NIASSA_MZ_A = "\U0001f3f4\U000e006d\U000e007a\U000e0061\U000e007f"
- FLAG_FOR_BAGO_MM_02 = "\U0001f3f4\U000e006d\U000e006d\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_INHAMBANE_MZ_I = "\U0001f3f4\U000e006d\U000e007a\U000e0069\U000e007f"
- FLAG_FOR_ZAMBEZI_NA_CA = "\U0001f3f4\U000e006e\U000e0061\U000e0063\U000e0061\U000e007f"
- FLAG_FOR_PERLIS_MY_09 = "\U0001f3f4\U000e006d\U000e0079\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_KAVANGO_WEST_NA_KW = "\U0001f3f4\U000e006e\U000e0061\U000e006b\U000e0077\U000e007f"
- FLAG_FOR_RIVIERE_DU_REMPART_MU_RR = "\U0001f3f4\U000e006d\U000e0075\U000e0072\U000e0072\U000e007f"
- FLAG_FOR_ZACATECAS_MX_ZAC = "\U0001f3f4\U000e006d\U000e0078\U000e007a\U000e0061\U000e0063\U000e007f"
- FLAG_FOR_OSHANA_NA_ON = "\U0001f3f4\U000e006e\U000e0061\U000e006f\U000e006e\U000e007f"
- FLAG_FOR_DOSSO_NE_3 = "\U0001f3f4\U000e006e\U000e0065\U000e0033\U000e007f"
- FLAG_FOR_KHOMAS_NA_KH = "\U0001f3f4\U000e006e\U000e0061\U000e006b\U000e0068\U000e007f"
- FLAG_FOR_TILLABERI_NE_6 = "\U0001f3f4\U000e006e\U000e0065\U000e0036\U000e007f"
- FLAG_FOR_KANO_NG_KN = "\U0001f3f4\U000e006e\U000e0067\U000e006b\U000e006e\U000e007f"
- FLAG_FOR_ANAMBRA_NG_AN = "\U0001f3f4\U000e006e\U000e0067\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_NIAMEY_NE_8 = "\U0001f3f4\U000e006e\U000e0065\U000e0038\U000e007f"
- FLAG_FOR_KADUNA_NG_KD = "\U0001f3f4\U000e006e\U000e0067\U000e006b\U000e0064\U000e007f"
- FLAG_FOR_JIGAWA_NG_JI = "\U0001f3f4\U000e006e\U000e0067\U000e006a\U000e0069\U000e007f"
- FLAG_FOR_MARADI_NE_4 = "\U0001f3f4\U000e006e\U000e0065\U000e0034\U000e007f"
- FLAG_FOR_OMUSATI_NA_OS = "\U0001f3f4\U000e006e\U000e0061\U000e006f\U000e0073\U000e007f"
- FLAG_FOR_AGADEZ_NE_1 = "\U0001f3f4\U000e006e\U000e0065\U000e0031\U000e007f"
- FLAG_FOR_KARAS_NA_KA = "\U0001f3f4\U000e006e\U000e0061\U000e006b\U000e0061\U000e007f"
- FLAG_FOR_BENUE_NG_BE = "\U0001f3f4\U000e006e\U000e0067\U000e0062\U000e0065\U000e007f"
- FLAG_FOR_KUNENE_NA_KU = "\U0001f3f4\U000e006e\U000e0061\U000e006b\U000e0075\U000e007f"
- FLAG_FOR_OHANGWENA_NA_OW = "\U0001f3f4\U000e006e\U000e0061\U000e006f\U000e0077\U000e007f"
- FLAG_FOR_EKITI_NG_EK = "\U0001f3f4\U000e006e\U000e0067\U000e0065\U000e006b\U000e007f"
- FLAG_FOR_SIDI_BEL_ABBES_DZ_22 = "\U0001f3f4\U000e0064\U000e007a\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_EBONYI_NG_EB = "\U0001f3f4\U000e006e\U000e0067\U000e0065\U000e0062\U000e007f"
- FLAG_FOR_TAHOUA_NE_5 = "\U0001f3f4\U000e006e\U000e0065\U000e0035\U000e007f"
- FLAG_FOR_KATSINA_NG_KT = "\U0001f3f4\U000e006e\U000e0067\U000e006b\U000e0074\U000e007f"
- FLAG_FOR_BAYELSA_NG_BY = "\U0001f3f4\U000e006e\U000e0067\U000e0062\U000e0079\U000e007f"
- FLAG_FOR_ABIA_NG_AB = "\U0001f3f4\U000e006e\U000e0067\U000e0061\U000e0062\U000e007f"
- FLAG_FOR_OTJOZONDJUPA_NA_OD = "\U0001f3f4\U000e006e\U000e0061\U000e006f\U000e0064\U000e007f"
- FLAG_FOR_ZINDER_NE_7 = "\U0001f3f4\U000e006e\U000e0065\U000e0037\U000e007f"
- MAN_WITH_HEADSCARF_LIGHT_SKIN_TONE = "\U0001f9d5\U0001f3fb\u200d\u2642\ufe0f"
- FLAG_FOR_DIFFA_NE_2 = "\U0001f3f4\U000e006e\U000e0065\U000e0032\U000e007f"
- FLAG_FOR_AKWA_IBOM_NG_AK = "\U0001f3f4\U000e006e\U000e0067\U000e0061\U000e006b\U000e007f"
- FLAG_FOR_BOACO_NI_BO = "\U0001f3f4\U000e006e\U000e0069\U000e0062\U000e006f\U000e007f"
- FLAG_FOR_OYO_NG_OY = "\U0001f3f4\U000e006e\U000e0067\U000e006f\U000e0079\U000e007f"
- FLAG_FOR_CHONTALES_NI_CO = "\U0001f3f4\U000e006e\U000e0069\U000e0063\U000e006f\U000e007f"
- FLAG_FOR_NUEVA_SEGOVIA_NI_NS = "\U0001f3f4\U000e006e\U000e0069\U000e006e\U000e0073\U000e007f"
- FLAG_FOR_ROTUMA_FJ_R = "\U0001f3f4\U000e0066\U000e006a\U000e0072\U000e007f"
- FLAG_FOR_ESTELI_NI_ES = "\U0001f3f4\U000e006e\U000e0069\U000e0065\U000e0073\U000e007f"
- FLAG_FOR_MAYOTTE_FR_MAY = "\U0001f3f4\U000e0066\U000e0072\U000e006d\U000e0061\U000e0079\U000e007f"
- FLAG_FOR_TARABA_NG_TA = "\U0001f3f4\U000e006e\U000e0067\U000e0074\U000e0061\U000e007f"
- FLAG_FOR_CARAZO_NI_CA = "\U0001f3f4\U000e006e\U000e0069\U000e0063\U000e0061\U000e007f"
- FLAG_FOR_JINOTEGA_NI_JI = "\U0001f3f4\U000e006e\U000e0069\U000e006a\U000e0069\U000e007f"
- FLAG_FOR_GELDERLAND_NL_GE = "\U0001f3f4\U000e006e\U000e006c\U000e0067\U000e0065\U000e007f"
- FLAG_FOR_NORTHERN_DISTRICT_IL_Z = "\U0001f3f4\U000e0069\U000e006c\U000e007a\U000e007f"
- FLAG_FOR_NASARAWA_NG_NA = "\U0001f3f4\U000e006e\U000e0067\U000e006e\U000e0061\U000e007f"
- FLAG_FOR_MANAGUA_NI_MN = "\U0001f3f4\U000e006e\U000e0069\U000e006d\U000e006e\U000e007f"
- FLAG_FOR_SANCTI_SPIRITUS_CU_07 = "\U0001f3f4\U000e0063\U000e0075\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_ZAMFARA_NG_ZA = "\U0001f3f4\U000e006e\U000e0067\U000e007a\U000e0061\U000e007f"
- FLAG_FOR_CHINANDEGA_NI_CI = "\U0001f3f4\U000e006e\U000e0069\U000e0063\U000e0069\U000e007f"
- FLAG_FOR_MATAGALPA_NI_MT = "\U0001f3f4\U000e006e\U000e0069\U000e006d\U000e0074\U000e007f"
- FLAG_FOR_MADRIZ_NI_MD = "\U0001f3f4\U000e006e\U000e0069\U000e006d\U000e0064\U000e007f"
- FLAG_FOR_RIVAS_NI_RI = "\U0001f3f4\U000e006e\U000e0069\U000e0072\U000e0069\U000e007f"
- FLAG_FOR_SAINT_JAMES_JM_08 = "\U0001f3f4\U000e006a\U000e006d\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_EL_PROGRESO_GT_PR = "\U0001f3f4\U000e0067\U000e0074\U000e0070\U000e0072\U000e007f"
- FLAG_FOR_ATLANTICO_NORTE_NI_AN = "\U0001f3f4\U000e006e\U000e0069\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_PLATEAU_NG_PL = "\U0001f3f4\U000e006e\U000e0067\U000e0070\U000e006c\U000e007f"
- FLAG_FOR_KABARDINO_BALKAR_RU_KB = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e0062\U000e007f"
- FLAG_FOR_FLEVOLAND_NL_FL = "\U0001f3f4\U000e006e\U000e006c\U000e0066\U000e006c\U000e007f"
- FLAG_FOR_KWARA_NG_KW = "\U0001f3f4\U000e006e\U000e0067\U000e006b\U000e0077\U000e007f"
- FLAG_FOR_GRANADA_NI_GR = "\U0001f3f4\U000e006e\U000e0069\U000e0067\U000e0072\U000e007f"
- FLAG_FOR_SANTIAGO_DE_CUBA_CU_13 = "\U0001f3f4\U000e0063\U000e0075\U000e0031\U000e0033\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_VESTFOLD_NO_07 = "\U0001f3f4\U000e006e\U000e006f\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_PURWANCHAL_NP_4 = "\U0001f3f4\U000e006e\U000e0070\U000e0034\U000e007f"
- FLAG_FOR_STFOLD_NO_01 = "\U0001f3f4\U000e006e\U000e006f\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_S_R_TR_NDELAG_NO_16 = "\U0001f3f4\U000e006e\U000e006f\U000e0031\U000e0036\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_JAN_MAYEN_NO_22 = "\U0001f3f4\U000e006e\U000e006f\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_LARVOTTO_MC_LA = "\U0001f3f4\U000e006d\U000e0063\U000e006c\U000e0061\U000e007f"
- FLAG_FOR_CENTRAL_NP_1 = "\U0001f3f4\U000e006e\U000e0070\U000e0031\U000e007f"
- FLAG_FOR_TELEMARK_NO_08 = "\U0001f3f4\U000e006e\U000e006f\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_MADHYA_PASHCHIMANCHAL_NP_2 = "\U0001f3f4\U000e006e\U000e0070\U000e0032\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff"
- FLAG_FOR_AUST_AGDER_NO_09 = "\U0001f3f4\U000e006e\U000e006f\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_BALZERS_LI_01 = "\U0001f3f4\U000e006c\U000e0069\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_M_RE_OG_ROMSDAL_NO_15 = "\U0001f3f4\U000e006e\U000e006f\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_NORD_TR_NDELAG_NO_17 = "\U0001f3f4\U000e006e\U000e006f\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_AKERSHUS_NO_02 = "\U0001f3f4\U000e006e\U000e006f\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_BUSKERUD_NO_06 = "\U0001f3f4\U000e006e\U000e006f\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_BOE_NR_06 = "\U0001f3f4\U000e006e\U000e0072\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_NORDLAND_NO_18 = "\U0001f3f4\U000e006e\U000e006f\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_PRILEP_MK_62 = "\U0001f3f4\U000e006d\U000e006b\U000e0036\U000e0032\U000e007f"
- FLAG_FOR_BAITI_NR_05 = "\U0001f3f4\U000e006e\U000e0072\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_ANETAN_NR_03 = "\U0001f3f4\U000e006e\U000e0072\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_BUADA_NR_07 = "\U0001f3f4\U000e006e\U000e0072\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_NZEREKORE_REGION_GN_N = "\U0001f3f4\U000e0067\U000e006e\U000e006e\U000e007f"
- FLAG_FOR_ONDO_NG_ON = "\U0001f3f4\U000e006e\U000e0067\U000e006f\U000e006e\U000e007f"
- FLAG_FOR_OPPLAND_NO_05 = "\U0001f3f4\U000e006e\U000e006f\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_ANIBARE_NR_04 = "\U0001f3f4\U000e006e\U000e0072\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_MUSCAT_OM_MA = "\U0001f3f4\U000e006f\U000e006d\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_CHATHAM_ISLANDS_NZ_CIT = "\U0001f3f4\U000e006e\U000e007a\U000e0063\U000e0069\U000e0074\U000e007f"
- FLAG_FOR_UNGHENI_MD_UN = "\U0001f3f4\U000e006d\U000e0064\U000e0075\U000e006e\U000e007f"
- FLAG_FOR_KANKAN_REGION_GN_K = "\U0001f3f4\U000e0067\U000e006e\U000e006b\U000e007f"
- KISS_WOMAN_DARK_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb"
- FLAG_FOR_DAYKUNDI_AF_DAY = "\U0001f3f4\U000e0061\U000e0066\U000e0064\U000e0061\U000e0079\U000e007f"
- FLAG_FOR_MUSANDAM_OM_MU = "\U0001f3f4\U000e006f\U000e006d\U000e006d\U000e0075\U000e007f"
- FLAG_FOR_KARAK_JO_KA = "\U0001f3f4\U000e006a\U000e006f\U000e006b\U000e0061\U000e007f"
- FLAG_FOR_JANUB_ASH_SHARQIYAH_OM_SJ = "\U0001f3f4\U000e006f\U000e006d\U000e0073\U000e006a\U000e007f"
- FLAG_FOR_WAIKATO_NZ_WKO = "\U0001f3f4\U000e006e\U000e007a\U000e0077\U000e006b\U000e006f\U000e007f"
- FLAG_FOR_TELSIAI_COUNTY_LT_TE = "\U0001f3f4\U000e006c\U000e0074\U000e0074\U000e0065\U000e007f"
- FLAG_FOR_SHAMAL_ASH_SHARQIYAH_OM_SS = "\U0001f3f4\U000e006f\U000e006d\U000e0073\U000e0073\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_U = "\U000e0055"
- FLAG_FOR_IJUW_NR_10 = "\U0001f3f4\U000e006e\U000e0072\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_COLON_PA_3 = "\U0001f3f4\U000e0070\U000e0061\U000e0033\U000e007f"
- FLAG_FOR_SHAMAL_AL_BATINAH_OM_BS = "\U0001f3f4\U000e006f\U000e006d\U000e0062\U000e0073\U000e007f"
- FLAG_FOR_DHOFAR_OM_ZU = "\U0001f3f4\U000e006f\U000e006d\U000e007a\U000e0075\U000e007f"
- FLAG_FOR_AD_DHAHIRAH_OM_ZA = "\U0001f3f4\U000e006f\U000e006d\U000e007a\U000e0061\U000e007f"
- FLAG_FOR_GISBORNE_NZ_GIS = "\U0001f3f4\U000e006e\U000e007a\U000e0067\U000e0069\U000e0073\U000e007f"
- FLAG_FOR_ALOJA_LV_005 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_TROMS_NO_19 = "\U0001f3f4\U000e006e\U000e006f\U000e0031\U000e0039\U000e007f"
- KISS_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_NIBOK_NR_12 = "\U0001f3f4\U000e006e\U000e0072\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_JANUB_AL_BATINAH_OM_BJ = "\U0001f3f4\U000e006f\U000e006d\U000e0062\U000e006a\U000e007f"
- FLAG_FOR_TUMBES_PE_TUM = "\U0001f3f4\U000e0070\U000e0065\U000e0074\U000e0075\U000e006d\U000e007f"
- FLAG_FOR_EL_CALLAO_PE_CAL = "\U0001f3f4\U000e0070\U000e0065\U000e0063\U000e0061\U000e006c\U000e007f"
- FLAG_FOR_PUNO_PE_PUN = "\U0001f3f4\U000e0070\U000e0065\U000e0070\U000e0075\U000e006e\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_PASCO_PE_PAS = "\U0001f3f4\U000e0070\U000e0065\U000e0070\U000e0061\U000e0073\U000e007f"
- FLAG_FOR_LIMA_PE_LMA = "\U0001f3f4\U000e0070\U000e0065\U000e006c\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_MECKLENBURG_VORPOMMERN_DE_MV = "\U0001f3f4\U000e0064\U000e0065\U000e006d\U000e0076\U000e007f"
- FLAG_FOR_PIURA_PE_PIU = "\U0001f3f4\U000e0070\U000e0065\U000e0070\U000e0069\U000e0075\U000e007f"
- FLAG_FOR_ICA_PE_ICA = "\U0001f3f4\U000e0070\U000e0065\U000e0069\U000e0063\U000e0061\U000e007f"
- FLAG_FOR_GITEGA_BI_GI = "\U0001f3f4\U000e0062\U000e0069\U000e0067\U000e0069\U000e007f"
- FLAG_FOR_UCAYALI_PE_UCA = "\U0001f3f4\U000e0070\U000e0065\U000e0075\U000e0063\U000e0061\U000e007f"
- FLAG_FOR_DENIGOMODU_NR_08 = "\U0001f3f4\U000e006e\U000e0072\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_HUANUCO_PE_HUC = "\U0001f3f4\U000e0070\U000e0065\U000e0068\U000e0075\U000e0063\U000e007f"
- FLAG_FOR_JUNIN_PE_JUN = "\U0001f3f4\U000e0070\U000e0065\U000e006a\U000e0075\U000e006e\U000e007f"
- FLAG_FOR_LA_LIBERTAD_PE_LAL = "\U0001f3f4\U000e0070\U000e0065\U000e006c\U000e0061\U000e006c\U000e007f"
- FLAG_FOR_CHIMBU_PG_CPK = "\U0001f3f4\U000e0070\U000e0067\U000e0063\U000e0070\U000e006b\U000e007f"
- FLAG_FOR_CAJAMARCA_PE_CAJ = "\U0001f3f4\U000e0070\U000e0065\U000e0063\U000e0061\U000e006a\U000e007f"
- FLAG_FOR_BALKAN_TM_B = "\U0001f3f4\U000e0074\U000e006d\U000e0062\U000e007f"
- FLAG_FOR_VERAGUAS_PA_9 = "\U0001f3f4\U000e0070\U000e0061\U000e0039\U000e007f"
- FLAG_FOR_LAMBAYEQUE_PE_LAM = "\U0001f3f4\U000e0070\U000e0065\U000e006c\U000e0061\U000e006d\U000e007f"
- FLAG_FOR_AMAZONAS_PE_AMA = "\U0001f3f4\U000e0070\U000e0065\U000e0061\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_NORTH_JEOLLA_KR_45 = "\U0001f3f4\U000e006b\U000e0072\U000e0034\U000e0035\U000e007f"
- FLAG_FOR_HUANCAVELICA_PE_HUV = "\U0001f3f4\U000e0070\U000e0065\U000e0068\U000e0075\U000e0076\U000e007f"
- FLAG_FOR_DARIEN_PA_5 = "\U0001f3f4\U000e0070\U000e0061\U000e0035\U000e007f"
- FLAG_FOR_ROGALAND_NO_11 = "\U0001f3f4\U000e006e\U000e006f\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_LORETO_PE_LOR = "\U0001f3f4\U000e0070\U000e0065\U000e006c\U000e006f\U000e0072\U000e007f"
- FLAG_FOR_SAN_MARTIN_PE_SAM = "\U0001f3f4\U000e0070\U000e0065\U000e0073\U000e0061\U000e006d\U000e007f"
- FLAG_FOR_CHONGQING_CN_50 = "\U0001f3f4\U000e0063\U000e006e\U000e0035\U000e0030\U000e007f"
- FLAG_FOR_SANDAUN_PG_SAN = "\U0001f3f4\U000e0070\U000e0067\U000e0073\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_CIUDAD_DE_MEXICO_MX_CMX = "\U0001f3f4\U000e006d\U000e0078\U000e0063\U000e006d\U000e0078\U000e007f"
- FLAG_FOR_OSUN_NG_OS = "\U0001f3f4\U000e006e\U000e0067\U000e006f\U000e0073\U000e007f"
- MAHJONG_TILE_TWO_OF_CIRCLES = "\U0001f01a"
- FLAG_FOR_HEDMARK_NO_04 = "\U0001f3f4\U000e006e\U000e006f\U000e0030\U000e0034\U000e007f"
- COUPLE_WITH_HEART_MAN_MAN_MEDIUM_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_NORTHERN_MINDANAO_PH_10 = "\U0001f3f4\U000e0070\U000e0068\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_MADANG_PG_MPM = "\U0001f3f4\U000e0070\U000e0067\U000e006d\U000e0070\U000e006d\U000e007f"
- FLAG_FOR_WESTERN_PG_WPD = "\U0001f3f4\U000e0070\U000e0067\U000e0077\U000e0070\U000e0064\U000e007f"
- FLAG_FOR_SOUTH_PYONGAN_KP_02 = "\U0001f3f4\U000e006b\U000e0070\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_EASTERN_VISAYAS_PH_08 = "\U0001f3f4\U000e0070\U000e0068\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_WESTERN_FJ_W = "\U0001f3f4\U000e0066\U000e006a\U000e0077\U000e007f"
- FLAG_FOR_SOCCSKSARGEN_PH_12 = "\U0001f3f4\U000e0070\U000e0068\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_MOROBE_PG_MPL = "\U0001f3f4\U000e0070\U000e0067\U000e006d\U000e0070\U000e006c\U000e007f"
- FLAG_FOR_MIMAROPA_PH_41 = "\U0001f3f4\U000e0070\U000e0068\U000e0034\U000e0031\U000e007f"
- COUPLE_WITH_HEART_WOMAN_LIGHT_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe"
- FLAG_FOR_HELA_PG_HLA = "\U0001f3f4\U000e0070\U000e0067\U000e0068\U000e006c\U000e0061\U000e007f"
- FLAG_FOR_CALABARZON_PH_40 = "\U0001f3f4\U000e0070\U000e0068\U000e0034\U000e0030\U000e007f"
- FLAG_FOR_ZAMBOANGA_PENINSULA_PH_09 = "\U0001f3f4\U000e0070\U000e0068\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_HERRERA_PA_6 = "\U0001f3f4\U000e0070\U000e0061\U000e0036\U000e007f"
- COUPLE_WITH_HEART_MAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb"
- FLAG_FOR_EDO_NG_ED = "\U0001f3f4\U000e006e\U000e0067\U000e0065\U000e0064\U000e007f"
- FLAG_FOR_MILNE_BAY_PG_MBA = "\U0001f3f4\U000e0070\U000e0067\U000e006d\U000e0062\U000e0061\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_WESTERN_VISAYAS_PH_06 = "\U0001f3f4\U000e0070\U000e0068\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_ANABAR_NR_02 = "\U0001f3f4\U000e006e\U000e0072\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_CARAGA_PH_13 = "\U0001f3f4\U000e0070\U000e0068\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_KOGI_NG_KO = "\U0001f3f4\U000e006e\U000e0067\U000e006b\U000e006f\U000e007f"
- FLAG_FOR_GUANACASTE_CR_G = "\U0001f3f4\U000e0063\U000e0072\U000e0067\U000e007f"
- FLAG_FOR_COROZAL_BZ_CZL = "\U0001f3f4\U000e0062\U000e007a\U000e0063\U000e007a\U000e006c\U000e007f"
- FLAG_FOR_ALSUNGA_LV_006 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_TULKARM_PS_TKM = "\U0001f3f4\U000e0070\U000e0073\U000e0074\U000e006b\U000e006d\U000e007f"
- FLAG_FOR_OPOLE_PL_OP = "\U0001f3f4\U000e0070\U000e006c\U000e006f\U000e0070\U000e007f"
- FLAG_FOR_KHYBER_PAKHTUNKHWA_PK_KP = "\U0001f3f4\U000e0070\U000e006b\U000e006b\U000e0070\U000e007f"
- FLAG_FOR_WEST_POMERANIA_PL_ZP = "\U0001f3f4\U000e0070\U000e006c\U000e007a\U000e0070\U000e007f"
- FLAG_FOR_KURDAMIR_AZ_KUR = "\U0001f3f4\U000e0061\U000e007a\U000e006b\U000e0075\U000e0072\U000e007f"
- FLAG_FOR_LUBUSZ_PL_LB = "\U0001f3f4\U000e0070\U000e006c\U000e006c\U000e0062\U000e007f"
- FLAG_FOR_HEBRON_PS_HBN = "\U0001f3f4\U000e0070\U000e0073\U000e0068\U000e0062\U000e006e\U000e007f"
- FLAG_FOR_RAFAH_PS_RFH = "\U0001f3f4\U000e0070\U000e0073\U000e0072\U000e0066\U000e0068\U000e007f"
- FLAG_FOR_WARMIAN_MASURIA_PL_WN = "\U0001f3f4\U000e0070\U000e006c\U000e0077\U000e006e\U000e007f"
- FLAG_FOR_PUNJAB_PK_PB = "\U0001f3f4\U000e0070\U000e006b\U000e0070\U000e0062\U000e007f"
- FLAG_FOR_AVEIRO_PT_01 = "\U0001f3f4\U000e0070\U000e0074\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_MAZOVIA_PL_MZ = "\U0001f3f4\U000e0070\U000e006c\U000e006d\U000e007a\U000e007f"
- FLAG_FOR_LUBLIN_PL_LU = "\U0001f3f4\U000e0070\U000e006c\U000e006c\U000e0075\U000e007f"
- FLAG_FOR_NABLUS_PS_NBS = "\U0001f3f4\U000e0070\U000e0073\U000e006e\U000e0062\U000e0073\U000e007f"
- FLAG_FOR_QALQILYA_PS_QQA = "\U0001f3f4\U000e0070\U000e0073\U000e0071\U000e0071\U000e0061\U000e007f"
- FLAG_FOR_KUYAVIAN_POMERANIA_PL_KP = "\U0001f3f4\U000e0070\U000e006c\U000e006b\U000e0070\U000e007f"
- FLAG_FOR_SINDH_PK_SD = "\U0001f3f4\U000e0070\U000e006b\U000e0073\U000e0064\U000e007f"
- FLAG_FOR_PODLASKIE_PL_PD = "\U0001f3f4\U000e0070\U000e006c\U000e0070\U000e0064\U000e007f"
- FLAG_FOR_DAVAO_PH_11 = "\U0001f3f4\U000e0070\U000e0068\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_SUBCARPATHIA_PL_PK = "\U0001f3f4\U000e0070\U000e006c\U000e0070\U000e006b\U000e007f"
- FLAG_FOR_ODZ_PL_LD = "\U0001f3f4\U000e0070\U000e006c\U000e006c\U000e0064\U000e007f"
- FLAG_FOR_SALFIT_PS_SLT = "\U0001f3f4\U000e0070\U000e0073\U000e0073\U000e006c\U000e0074\U000e007f"
- FLAG_FOR_JENIN_PS_JEN = "\U0001f3f4\U000e0070\U000e0073\U000e006a\U000e0065\U000e006e\U000e007f"
- FLAG_FOR_SILESIA_PL_SL = "\U0001f3f4\U000e0070\U000e006c\U000e0073\U000e006c\U000e007f"
- FLAG_FOR_KHAN_YUNIS_PS_KYS = "\U0001f3f4\U000e0070\U000e0073\U000e006b\U000e0079\U000e0073\U000e007f"
- TAG_RIGHT_SQUARE_BRACKET = "\U000e005d"
- FLAG_FOR_MOSCOW_PROVINCE_RU_MOS = "\U0001f3f4\U000e0072\U000e0075\U000e006d\U000e006f\U000e0073\U000e007f"
- FLAG_FOR_TUSCANY_IT_52 = "\U0001f3f4\U000e0069\U000e0074\U000e0035\U000e0032\U000e007f"
- FLAG_FOR_BICOL_PH_05 = "\U0001f3f4\U000e0070\U000e0068\U000e0030\U000e0035\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_K = "\U000e004b"
- FLAG_FOR_LOWER_SILESIAN_PL_DS = "\U0001f3f4\U000e0070\U000e006c\U000e0064\U000e0073\U000e007f"
- FLAG_FOR_CAGAYAN_VALLEY_PH_02 = "\U0001f3f4\U000e0070\U000e0068\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_RIO_DE_JANEIRO_BR_RJ = "\U0001f3f4\U000e0062\U000e0072\U000e0072\U000e006a\U000e007f"
- FLAG_FOR_EVORA_PT_07 = "\U0001f3f4\U000e0070\U000e0074\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_NGARAARD_PW_214 = "\U0001f3f4\U000e0070\U000e0077\U000e0032\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_BRAGANCA_PT_04 = "\U0001f3f4\U000e0070\U000e0074\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_SHIDA_KARTLI_GE_SK = "\U0001f3f4\U000e0067\U000e0065\U000e0073\U000e006b\U000e007f"
- FLAG_FOR_MENENG_NR_11 = "\U0001f3f4\U000e006e\U000e0072\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_AIMELIIK_PW_002 = "\U0001f3f4\U000e0070\U000e0077\U000e0030\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_AMAMBAY_PY_13 = "\U0001f3f4\U000e0070\U000e0079\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_HATOHOBEI_PW_050 = "\U0001f3f4\U000e0070\U000e0077\U000e0030\U000e0035\U000e0030\U000e007f"
- FLAG_FOR_CENTRAL_PY_11 = "\U0001f3f4\U000e0070\U000e0079\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_COIMBRA_PT_06 = "\U0001f3f4\U000e0070\U000e0074\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_CENTRAL_PG_CPM = "\U0001f3f4\U000e0070\U000e0067\U000e0063\U000e0070\U000e006d\U000e007f"
- FLAG_FOR_KOROR_PW_150 = "\U0001f3f4\U000e0070\U000e0077\U000e0031\U000e0035\U000e0030\U000e007f"
- FLAG_FOR_COCLE_PA_2 = "\U0001f3f4\U000e0070\U000e0061\U000e0032\U000e007f"
- FLAG_FOR_NEEMBUCU_PY_12 = "\U0001f3f4\U000e0070\U000e0079\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_AIRAI_PW_004 = "\U0001f3f4\U000e0070\U000e0077\U000e0030\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_SANTAREM_PT_14 = "\U0001f3f4\U000e0070\U000e0074\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_NGATPANG_PW_224 = "\U0001f3f4\U000e0070\U000e0077\U000e0032\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_PORTALEGRE_PT_12 = "\U0001f3f4\U000e0070\U000e0074\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_LEIRIA_PT_10 = "\U0001f3f4\U000e0070\U000e0074\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_NGARDMAU_PW_222 = "\U0001f3f4\U000e0070\U000e0077\U000e0032\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_NGCHESAR_PW_226 = "\U0001f3f4\U000e0070\U000e0077\U000e0032\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_NORTH_HWANGHAE_KP_06 = "\U0001f3f4\U000e006b\U000e0070\U000e0030\U000e0036\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_WESTERN_NP_3 = "\U0001f3f4\U000e006e\U000e0070\U000e0033\U000e007f"
- FLAG_FOR_VIANA_DO_CASTELO_PT_16 = "\U0001f3f4\U000e0070\U000e0074\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_CANINDEYU_PY_14 = "\U0001f3f4\U000e0070\U000e0079\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_CORDILLERA_PY_3 = "\U0001f3f4\U000e0070\U000e0079\U000e0033\U000e007f"
- FLAG_FOR_CAAZAPA_PY_6 = "\U0001f3f4\U000e0070\U000e0079\U000e0036\U000e007f"
- FLAG_FOR_COVASNA_RO_CV = "\U0001f3f4\U000e0072\U000e006f\U000e0063\U000e0076\U000e007f"
- FLAG_FOR_GIURGIU_RO_GR = "\U0001f3f4\U000e0072\U000e006f\U000e0067\U000e0072\U000e007f"
- FLAG_FOR_DAMBOVITA_RO_DB = "\U0001f3f4\U000e0072\U000e006f\U000e0064\U000e0062\U000e007f"
- FLAG_FOR_ITAPUA_PY_7 = "\U0001f3f4\U000e0070\U000e0079\U000e0037\U000e007f"
- FLAG_FOR_CAAGUAZU_PY_5 = "\U0001f3f4\U000e0070\U000e0079\U000e0035\U000e007f"
- FLAG_FOR_SAN_PEDRO_PY_2 = "\U0001f3f4\U000e0070\U000e0079\U000e0032\U000e007f"
- FLAG_FOR_NGEREMLENGUI_PW_227 = "\U0001f3f4\U000e0070\U000e0077\U000e0032\U000e0032\U000e0037\U000e007f"
- FLAG_FOR_BIHOR_RO_BH = "\U0001f3f4\U000e0072\U000e006f\U000e0062\U000e0068\U000e007f"
- FLAG_FOR_DOLJ_RO_DJ = "\U0001f3f4\U000e0072\U000e006f\U000e0064\U000e006a\U000e007f"
- FLAG_FOR_ARGES_RO_AG = "\U0001f3f4\U000e0072\U000e006f\U000e0061\U000e0067\U000e007f"
- FLAG_FOR_AL_KHOR_QA_KH = "\U0001f3f4\U000e0071\U000e0061\U000e006b\U000e0068\U000e007f"
- FLAG_FOR_GILGIT_BALTISTAN_PK_GB = "\U0001f3f4\U000e0070\U000e006b\U000e0067\U000e0062\U000e007f"
- FLAG_FOR_GUAIRA_PY_4 = "\U0001f3f4\U000e0070\U000e0079\U000e0034\U000e007f"
- FLAG_FOR_PARAGUARI_PY_9 = "\U0001f3f4\U000e0070\U000e0079\U000e0039\U000e007f"
- FLAG_FOR_CAPITAL_IS_1 = "\U0001f3f4\U000e0069\U000e0073\U000e0031\U000e007f"
- FLAG_FOR_GALATI_RO_GL = "\U0001f3f4\U000e0072\U000e006f\U000e0067\U000e006c\U000e007f"
- FLAG_FOR_ARAD_RO_AR = "\U0001f3f4\U000e0072\U000e006f\U000e0061\U000e0072\U000e007f"
- FLAG_FOR_BRAILA_RO_BR = "\U0001f3f4\U000e0072\U000e006f\U000e0062\U000e0072\U000e007f"
- FLAG_FOR_TIVAT_ME_19 = "\U0001f3f4\U000e006d\U000e0065\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_HARGHITA_RO_HR = "\U0001f3f4\U000e0072\U000e006f\U000e0068\U000e0072\U000e007f"
- FLAG_FOR_MISIONES_PY_8 = "\U0001f3f4\U000e0070\U000e0079\U000e0038\U000e007f"
- FLAG_FOR_AL_DAAYEN_QA_ZA = "\U0001f3f4\U000e0071\U000e0061\U000e007a\U000e0061\U000e007f"
- FLAG_FOR_DIKHIL_DJ_DI = "\U0001f3f4\U000e0064\U000e006a\U000e0064\U000e0069\U000e007f"
- FLAG_FOR_OLT_RO_OT = "\U0001f3f4\U000e0072\U000e006f\U000e006f\U000e0074\U000e007f"
- FLAG_FOR_BRANICEVO_RS_11 = "\U0001f3f4\U000e0072\U000e0073\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_RASINA_RS_19 = "\U0001f3f4\U000e0072\U000e0073\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_SUCEAVA_RO_SV = "\U0001f3f4\U000e0072\U000e006f\U000e0073\U000e0076\U000e007f"
- FLAG_FOR_ZAJECAR_RS_15 = "\U0001f3f4\U000e0072\U000e0073\U000e0031\U000e0035\U000e007f"
- WHITE_HEART_SUIT = "\u2661"
- FLAG_FOR_JABLANICA_RS_23 = "\U0001f3f4\U000e0072\U000e0073\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_SUMADIJA_RS_12 = "\U0001f3f4\U000e0072\U000e0073\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_PIROT_RS_22 = "\U0001f3f4\U000e0072\U000e0073\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_MURES_RO_MS = "\U0001f3f4\U000e0072\U000e006f\U000e006d\U000e0073\U000e007f"
- FLAG_FOR_TELEORMAN_RO_TR = "\U0001f3f4\U000e0072\U000e006f\U000e0074\U000e0072\U000e007f"
- FLAG_FOR_MACVA_RS_08 = "\U0001f3f4\U000e0072\U000e0073\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_MORAVICA_RS_17 = "\U0001f3f4\U000e0072\U000e0073\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_ILFOV_RO_IF = "\U0001f3f4\U000e0072\U000e006f\U000e0069\U000e0066\U000e007f"
- FLAG_FOR_PRAHOVA_RO_PH = "\U0001f3f4\U000e0072\U000e006f\U000e0070\U000e0068\U000e007f"
- FLAG_FOR_LOS_LAGOS_CL_LL = "\U0001f3f4\U000e0063\U000e006c\U000e006c\U000e006c\U000e007f"
- FLAG_FOR_TULCEA_RO_TL = "\U0001f3f4\U000e0072\U000e006f\U000e0074\U000e006c\U000e007f"
- FLAG_FOR_IALOMITA_RO_IL = "\U0001f3f4\U000e0072\U000e006f\U000e0069\U000e006c\U000e007f"
- FLAG_FOR_MOULINS_MC_MU = "\U0001f3f4\U000e006d\U000e0063\U000e006d\U000e0075\U000e007f"
- FLAG_FOR_KOLUBARA_RS_09 = "\U0001f3f4\U000e0072\U000e0073\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_ZLATIBOR_RS_16 = "\U0001f3f4\U000e0072\U000e0073\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_SALAJ_RO_SJ = "\U0001f3f4\U000e0072\U000e006f\U000e0073\U000e006a\U000e007f"
- FLAG_FOR_VASLUI_RO_VS = "\U0001f3f4\U000e0072\U000e006f\U000e0076\U000e0073\U000e007f"
- FLAG_FOR_POMORAVLJE_RS_13 = "\U0001f3f4\U000e0072\U000e0073\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_NISAVA_RS_20 = "\U0001f3f4\U000e0072\U000e0073\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_MEHEDINTI_RO_MH = "\U0001f3f4\U000e0072\U000e006f\U000e006d\U000e0068\U000e007f"
- FLAG_FOR_RASKA_RS_18 = "\U0001f3f4\U000e0072\U000e0073\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_PCINJA_RS_24 = "\U0001f3f4\U000e0072\U000e0073\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_BEOGRAD_RS_00 = "\U0001f3f4\U000e0072\U000e0073\U000e0030\U000e0030\U000e007f"
- FLAG_FOR_TACNA_PE_TAC = "\U0001f3f4\U000e0070\U000e0065\U000e0074\U000e0061\U000e0063\U000e007f"
- FLAG_FOR_BELGOROD_RU_BEL = "\U0001f3f4\U000e0072\U000e0075\U000e0062\U000e0065\U000e006c\U000e007f"
- FLAG_FOR_KURGAN_RU_KGN = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e0067\U000e006e\U000e007f"
- FLAG_FOR_CHELYABINSK_RU_CHE = "\U0001f3f4\U000e0072\U000e0075\U000e0063\U000e0068\U000e0065\U000e007f"
- FLAG_FOR_KIROV_RU_KIR = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e0069\U000e0072\U000e007f"
- KISS_MAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb"
- FLAG_FOR_UTTAR_PRADESH_IN_UP = "\U0001f3f4\U000e0069\U000e006e\U000e0075\U000e0070\U000e007f"
- FLAG_FOR_KOMI_RU_KO = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e006f\U000e007f"
- FLAG_FOR_IVANOVO_RU_IVA = "\U0001f3f4\U000e0072\U000e0075\U000e0069\U000e0076\U000e0061\U000e007f"
- FLAG_FOR_ALBA_RO_AB = "\U0001f3f4\U000e0072\U000e006f\U000e0061\U000e0062\U000e007f"
- FLAG_FOR_KHANTY_MANSI_RU_KHM = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e0068\U000e006d\U000e007f"
- FLAG_FOR_KALUGA_RU_KLU = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e006c\U000e0075\U000e007f"
- FLAG_FOR_PECS_HU_PS = "\U0001f3f4\U000e0068\U000e0075\U000e0070\U000e0073\U000e007f"
- FLAG_FOR_MARI_EL_RU_ME = "\U0001f3f4\U000e0072\U000e0075\U000e006d\U000e0065\U000e007f"
- FLAG_FOR_IRKUTSK_RU_IRK = "\U0001f3f4\U000e0072\U000e0075\U000e0069\U000e0072\U000e006b\U000e007f"
- FLAG_FOR_PLAV_ME_13 = "\U0001f3f4\U000e006d\U000e0065\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_GRAND_KRU_LR_GK = "\U0001f3f4\U000e006c\U000e0072\U000e0067\U000e006b\U000e007f"
- FLAG_FOR_SIEM_REAP_KH_17 = "\U0001f3f4\U000e006b\U000e0068\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_KAMCHATKA_KRAI_RU_KAM = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e0061\U000e006d\U000e007f"
- FLAG_FOR_ALTAI_RU_AL = "\U0001f3f4\U000e0072\U000e0075\U000e0061\U000e006c\U000e007f"
- FLAG_FOR_MORDOVIA_RU_MO = "\U0001f3f4\U000e0072\U000e0075\U000e006d\U000e006f\U000e007f"
- FLAG_FOR_ASTRAKHAN_RU_AST = "\U0001f3f4\U000e0072\U000e0075\U000e0061\U000e0073\U000e0074\U000e007f"
- FLAG_FOR_KARACHAY_CHERKESS_RU_KC = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e0063\U000e007f"
- FLAG_FOR_KEMEROVO_RU_KEM = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e0065\U000e006d\U000e007f"
- FLAG_FOR_ENGA_PG_EPW = "\U0001f3f4\U000e0070\U000e0067\U000e0065\U000e0070\U000e0077\U000e007f"
- FLAG_FOR_VOLOGDA_RU_VLG = "\U0001f3f4\U000e0072\U000e0075\U000e0076\U000e006c\U000e0067\U000e007f"
- FLAG_FOR_TOMSK_RU_TOM = "\U0001f3f4\U000e0072\U000e0075\U000e0074\U000e006f\U000e006d\U000e007f"
- FLAG_FOR_VLADIMIR_RU_VLA = "\U0001f3f4\U000e0072\U000e0075\U000e0076\U000e006c\U000e0061\U000e007f"
- FLAG_FOR_CONCEPCION_PY_1 = "\U0001f3f4\U000e0070\U000e0079\U000e0031\U000e007f"
- FLAG_FOR_BAUCHI_NG_BA = "\U0001f3f4\U000e006e\U000e0067\U000e0062\U000e0061\U000e007f"
- FLAG_FOR_NIZHNY_NOVGOROD_RU_NIZ = "\U0001f3f4\U000e0072\U000e0075\U000e006e\U000e0069\U000e007a\U000e007f"
- FLAG_FOR_ORENBURG_RU_ORE = "\U0001f3f4\U000e0072\U000e0075\U000e006f\U000e0072\U000e0065\U000e007f"
- FLAG_FOR_NOVOSIBIRSK_RU_NVS = "\U0001f3f4\U000e0072\U000e0075\U000e006e\U000e0076\U000e0073\U000e007f"
- FLAG_FOR_SAINT_JOHN_GD_04 = "\U0001f3f4\U000e0067\U000e0064\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_TVER_RU_TVE = "\U0001f3f4\U000e0072\U000e0075\U000e0074\U000e0076\U000e0065\U000e007f"
- FLAG_FOR_NOVGOROD_RU_NGR = "\U0001f3f4\U000e0072\U000e0075\U000e006e\U000e0067\U000e0072\U000e007f"
- FLAG_FOR_TULA_RU_TUL = "\U0001f3f4\U000e0072\U000e0075\U000e0074\U000e0075\U000e006c\U000e007f"
- FLAG_FOR_CASTELO_BRANCO_PT_05 = "\U0001f3f4\U000e0070\U000e0074\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_PRESIDENTE_HAYES_PY_15 = "\U0001f3f4\U000e0070\U000e0079\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_SMOLENSK_RU_SMO = "\U0001f3f4\U000e0072\U000e0075\U000e0073\U000e006d\U000e006f\U000e007f"
- FLAG_FOR_TYUMEN_RU_TYU = "\U0001f3f4\U000e0072\U000e0075\U000e0074\U000e0079\U000e0075\U000e007f"
- FLAG_FOR_SVERDLOVSK_RU_SVE = "\U0001f3f4\U000e0072\U000e0075\U000e0073\U000e0076\U000e0065\U000e007f"
- FLAG_FOR_DAMAN_AND_DIU_IN_DD = "\U0001f3f4\U000e0069\U000e006e\U000e0064\U000e0064\U000e007f"
- FLAG_FOR_SARATOV_RU_SAR = "\U0001f3f4\U000e0072\U000e0075\U000e0073\U000e0061\U000e0072\U000e007f"
- FLAG_FOR_NENETS_RU_NEN = "\U0001f3f4\U000e0072\U000e0075\U000e006e\U000e0065\U000e006e\U000e007f"
- FLAG_FOR_XIANGKHOUANG_LA_XI = "\U0001f3f4\U000e006c\U000e0061\U000e0078\U000e0069\U000e007f"
- FLAG_FOR_PSKOV_RU_PSK = "\U0001f3f4\U000e0072\U000e0075\U000e0070\U000e0073\U000e006b\U000e007f"
- FLAG_FOR_OTAGO_NZ_OTA = "\U0001f3f4\U000e006e\U000e007a\U000e006f\U000e0074\U000e0061\U000e007f"
- FLAG_FOR_CANTERBURY_NZ_CAN = "\U0001f3f4\U000e006e\U000e007a\U000e0063\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_HA_IL_SA_06 = "\U0001f3f4\U000e0073\U000e0061\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_EASTERN_RW_02 = "\U0001f3f4\U000e0072\U000e0077\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_TUVA_RU_TY = "\U0001f3f4\U000e0072\U000e0075\U000e0074\U000e0079\U000e007f"
- FLAG_FOR_ANSE_BOILEAU_SC_02 = "\U0001f3f4\U000e0073\U000e0063\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_ZABAYKALSKY_KRAI_RU_ZAB = "\U0001f3f4\U000e0072\U000e0075\U000e007a\U000e0061\U000e0062\U000e007f"
- FLAG_FOR_BAIE_SAINTE_ANNE_SC_07 = "\U0001f3f4\U000e0073\U000e0063\U000e0030\U000e0037\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_CHOISEUL_SB_CH = "\U0001f3f4\U000e0073\U000e0062\U000e0063\U000e0068\U000e007f"
- FLAG_FOR_SOUTHERN_RW_05 = "\U0001f3f4\U000e0072\U000e0077\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_VAS_HU_VA = "\U0001f3f4\U000e0068\U000e0075\U000e0076\U000e0061\U000e007f"
- FLAG_FOR_ASIR_SA_14 = "\U0001f3f4\U000e0073\U000e0061\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_NAJRAN_SA_10 = "\U0001f3f4\U000e0073\U000e0061\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_AL_JAWF_SA_12 = "\U0001f3f4\U000e0073\U000e0061\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_WESTERN_RW_04 = "\U0001f3f4\U000e0072\U000e0077\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_RENNELL_AND_BELLONA_SB_RB = "\U0001f3f4\U000e0073\U000e0062\U000e0072\U000e0062\U000e007f"
- FLAG_FOR_EASTERN_SA_04 = "\U0001f3f4\U000e0073\U000e0061\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_MALAITA_SB_ML = "\U0001f3f4\U000e0073\U000e0062\U000e006d\U000e006c\U000e007f"
- FLAG_FOR_KRASNOYARSK_KRAI_RU_KYA = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e0079\U000e0061\U000e007f"
- FLAG_FOR_BEAU_VALLON_SC_08 = "\U0001f3f4\U000e0073\U000e0063\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_KIGALI_RW_01 = "\U0001f3f4\U000e0072\U000e0077\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_ISABEL_SB_IS = "\U0001f3f4\U000e0073\U000e0062\U000e0069\U000e0073\U000e007f"
- FLAG_FOR_NORTHERN_BORDERS_SA_08 = "\U0001f3f4\U000e0073\U000e0061\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_YAROSLAVL_RU_YAR = "\U0001f3f4\U000e0072\U000e0075\U000e0079\U000e0061\U000e0072\U000e007f"
- FLAG_FOR_WILTZ_LU_WI = "\U0001f3f4\U000e006c\U000e0075\U000e0077\U000e0069\U000e007f"
- FLAG_FOR_HONIARA_SB_CT = "\U0001f3f4\U000e0073\U000e0062\U000e0063\U000e0074\U000e007f"
- FLAG_FOR_NORTHERN_RW_03 = "\U0001f3f4\U000e0072\U000e0077\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_SONSOROL_PW_370 = "\U0001f3f4\U000e0070\U000e0077\U000e0033\U000e0037\U000e0030\U000e007f"
- FLAG_FOR_TABUK_SA_07 = "\U0001f3f4\U000e0073\U000e0061\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_LA_RIVIERE_ANGLAISE_SC_16 = "\U0001f3f4\U000e0073\U000e0063\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_GRAND_ANSE_MAHE_SC_13 = "\U0001f3f4\U000e0073\U000e0063\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_POINTE_LA_RUE_SC_20 = "\U0001f3f4\U000e0073\U000e0063\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_CASCADE_SC_11 = "\U0001f3f4\U000e0073\U000e0063\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_NORTH_DARFUR_SD_DN = "\U0001f3f4\U000e0073\U000e0064\U000e0064\U000e006e\U000e007f"
- FLAG_FOR_WEST_KURDUFAN_SD_GK = "\U0001f3f4\U000e0073\U000e0064\U000e0067\U000e006b\U000e007f"
- FLAG_FOR_RIVER_NILE_SD_NR = "\U0001f3f4\U000e0073\U000e0064\U000e006e\U000e0072\U000e007f"
- FLAG_FOR_EAST_DARFUR_SD_DE = "\U0001f3f4\U000e0073\U000e0064\U000e0064\U000e0065\U000e007f"
- FLAG_FOR_NORRBOTTEN_SE_BD = "\U0001f3f4\U000e0073\U000e0065\U000e0062\U000e0064\U000e007f"
- FLAG_FOR_SODERMANLAND_SE_D = "\U0001f3f4\U000e0073\U000e0065\U000e0064\U000e007f"
- FLAG_FOR_TAKAMAKA_SC_23 = "\U0001f3f4\U000e0073\U000e0063\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_FRENCH_POLYNESIA_FR_PF = "\U0001f3f4\U000e0066\U000e0072\U000e0070\U000e0066\U000e007f"
- FLAG_FOR_AL_QADARIF_SD_GD = "\U0001f3f4\U000e0073\U000e0064\U000e0067\U000e0064\U000e007f"
- FLAG_FOR_VASTERBOTTEN_SE_AC = "\U0001f3f4\U000e0073\U000e0065\U000e0061\U000e0063\U000e007f"
- FLAG_FOR_NORTHERN_SD_NO = "\U0001f3f4\U000e0073\U000e0064\U000e006e\U000e006f\U000e007f"
- FLAG_FOR_MONT_FLEURI_SC_18 = "\U0001f3f4\U000e0073\U000e0063\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_CENTRAL_SB_CE = "\U0001f3f4\U000e0073\U000e0062\U000e0063\U000e0065\U000e007f"
- FLAG_FOR_CENTRAL_DARFUR_SD_DC = "\U0001f3f4\U000e0073\U000e0064\U000e0064\U000e0063\U000e007f"
- FLAG_FOR_VOLGOGRAD_RU_VGG = "\U0001f3f4\U000e0072\U000e0075\U000e0076\U000e0067\U000e0067\U000e007f"
- FLAG_FOR_PLAISANCE_SC_19 = "\U0001f3f4\U000e0073\U000e0063\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_MONT_BUXTON_SC_17 = "\U0001f3f4\U000e0073\U000e0063\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_KASSALA_SD_KA = "\U0001f3f4\U000e0073\U000e0064\U000e006b\U000e0061\U000e007f"
- FLAG_FOR_LES_MAMELLES_SC_24 = "\U0001f3f4\U000e0073\U000e0063\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_GLACIS_SC_12 = "\U0001f3f4\U000e0073\U000e0063\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_ROSTOV_RU_ROS = "\U0001f3f4\U000e0072\U000e0075\U000e0072\U000e006f\U000e0073\U000e007f"
- FLAG_FOR_SENNAR_SD_SI = "\U0001f3f4\U000e0073\U000e0064\U000e0073\U000e0069\U000e007f"
- FLAG_FOR_LA_DIGUE_SC_15 = "\U0001f3f4\U000e0073\U000e0063\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_SOUTH_DARFUR_SD_DS = "\U0001f3f4\U000e0073\U000e0064\U000e0064\U000e0073\U000e007f"
- FLAG_FOR_WHITE_NILE_SD_NW = "\U0001f3f4\U000e0073\U000e0064\U000e006e\U000e0077\U000e007f"
- FLAG_FOR_AL_JAZIRAH_SD_GZ = "\U0001f3f4\U000e0073\U000e0064\U000e0067\U000e007a\U000e007f"
- FLAG_FOR_SOUTH_KURDUFAN_SD_KS = "\U0001f3f4\U000e0073\U000e0064\U000e006b\U000e0073\U000e007f"
- FLAG_FOR_NORTH_KURDUFAN_SD_KN = "\U0001f3f4\U000e0073\U000e0064\U000e006b\U000e006e\U000e007f"
- FLAG_FOR_PORT_GLAUD_SC_21 = "\U0001f3f4\U000e0073\U000e0063\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_OSTERGOTLAND_SE_E = "\U0001f3f4\U000e0073\U000e0065\U000e0065\U000e007f"
- FLAG_FOR_GRAND_ANSE_PRASLIN_SC_14 = "\U0001f3f4\U000e0073\U000e0063\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_JONKOPING_SE_F = "\U0001f3f4\U000e0073\U000e0065\U000e0066\U000e007f"
- FLAG_FOR_VARMLAND_SE_S = "\U0001f3f4\U000e0073\U000e0065\U000e0073\U000e007f"
- FLAG_FOR_CERKLJE_NA_GORENJSKEM_SI_012 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_CERKNO_SI_014 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_SVETI_NIKOLE_MK_69 = "\U0001f3f4\U000e006d\U000e006b\U000e0036\U000e0039\U000e007f"
- FLAG_FOR_NORTH_EAST_SG_02 = "\U0001f3f4\U000e0073\U000e0067\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_SOUTH_EAST_SG_04 = "\U0001f3f4\U000e0073\U000e0067\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_NORTH_WEST_SG_03 = "\U0001f3f4\U000e0073\U000e0067\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_DESTRNIK_SI_018 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_SOUTH_WEST_SG_05 = "\U0001f3f4\U000e0073\U000e0067\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_BRDA_SI_007 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_OREBRO_SE_T = "\U0001f3f4\U000e0073\U000e0065\U000e0074\U000e007f"
- FLAG_FOR_KRONOBERG_SE_G = "\U0001f3f4\U000e0073\U000e0065\U000e0067\U000e007f"
- FLAG_FOR_ASCENSION_ISLAND_SH_AC = "\U0001f3f4\U000e0073\U000e0068\U000e0061\U000e0063\U000e007f"
- FLAG_FOR_VASTMANLAND_SE_U = "\U0001f3f4\U000e0073\U000e0065\U000e0075\U000e007f"
- FLAG_FOR_CERKNICA_SI_013 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_CRENSOVCI_SI_015 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_REZINA_MD_RE = "\U0001f3f4\U000e006d\U000e0064\U000e0072\U000e0065\U000e007f"
- KISS_WOMAN_LIGHT_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff"
- FLAG_FOR_BLED_SI_003 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_GOIAS_BR_GO = "\U0001f3f4\U000e0062\U000e0072\U000e0067\U000e006f\U000e007f"
- FLAG_FOR_BELTINCI_SI_002 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_CRNOMELJ_SI_017 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_BREZOVICA_SI_008 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_MINYA_EG_MN = "\U0001f3f4\U000e0065\U000e0067\U000e006d\U000e006e\U000e007f"
- FLAG_FOR_RIVIERE_NOIRE_MU_BL = "\U0001f3f4\U000e006d\U000e0075\U000e0062\U000e006c\U000e007f"
- FLAG_FOR_GOVI_ALTAI_MN_065 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0036\U000e0035\U000e007f"
- FLAG_FOR_AJDOVSCINA_SI_001 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_BOROVNICA_SI_005 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_JURSINCI_SI_042 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0034\U000e0032\U000e007f"
- FLAG_FOR_IDRIJA_SI_036 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0033\U000e0036\U000e007f"
- FLAG_FOR_KUZMA_SI_056 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0035\U000e0036\U000e007f"
- FLAG_FOR_ULYANOVSK_RU_ULY = "\U0001f3f4\U000e0072\U000e0075\U000e0075\U000e006c\U000e0079\U000e007f"
- FLAG_FOR_IZOLA_SI_040 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0034\U000e0030\U000e007f"
- FLAG_FOR_KOZJE_SI_051 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0035\U000e0031\U000e007f"
- FLAG_FOR_KUNGOTA_SI_055 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0035\U000e0035\U000e007f"
- FLAG_FOR_JESENICE_SI_041 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_GORNJI_GRAD_SI_030 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_DIVACA_SI_019 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_IVANCNA_GORICA_SI_039 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0033\U000e0039\U000e007f"
- FLAG_FOR_KRSKO_SI_054 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0035\U000e0034\U000e007f"
- FLAG_FOR_KAMNIK_SI_043 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0034\U000e0033\U000e007f"
- FLAG_FOR_DOBREPOLJE_SI_020 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_SALOVCI_SI_033 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_KOBILJE_SI_047 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0034\U000e0037\U000e007f"
- FLAG_FOR_HRASTNIK_SI_034 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0033\U000e0034\U000e007f"
- FLAG_FOR_DOBROVA_POLHOV_GRADEC_SI_021 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_DRAVOGRAD_SI_025 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0032\U000e0035\U000e007f"
- FLAG_FOR_STOCKHOLM_SE_AB = "\U0001f3f4\U000e0073\U000e0065\U000e0061\U000e0062\U000e007f"
- FLAG_FOR_DUPLEK_SI_026 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_SALACGRIVA_LV_086 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0038\U000e0036\U000e007f"
- FLAG_FOR_KOCEVJE_SI_048 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0034\U000e0038\U000e007f"
- FLAG_FOR_KRANJSKA_GORA_SI_053 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0035\U000e0033\U000e007f"
- FLAG_FOR_KANAL_SI_044 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0034\U000e0034\U000e007f"
- FLAG_FOR_GORNJI_PETROVCI_SI_031 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0033\U000e0031\U000e007f"
- FLAG_FOR_GROSUPLJE_SI_032 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_GORISNICA_SI_028 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0032\U000e0038\U000e007f"
- FLAG_FOR_TEMOTU_SB_TE = "\U0001f3f4\U000e0073\U000e0062\U000e0074\U000e0065\U000e007f"
- FLAG_FOR_DORNAVA_SI_024 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_DOMZALE_SI_023 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_KOBARID_SI_046 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0034\U000e0036\U000e007f"
- FLAG_FOR_GORNJA_RADGONA_SI_029 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0032\U000e0039\U000e007f"
- FLAG_FOR_ILIRSKA_BISTRICA_SI_038 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0033\U000e0038\U000e007f"
- FLAG_FOR_KOMEN_SI_049 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0034\U000e0039\U000e007f"
- FLAG_FOR_MARIBOR_SI_070 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0037\U000e0030\U000e007f"
- FLAG_FOR_MEZICA_SI_074 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0037\U000e0034\U000e007f"
- FLAG_FOR_LUCE_SI_067 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0036\U000e0037\U000e007f"
- FLAG_FOR_PODVELKA_SI_093 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0039\U000e0033\U000e007f"
- FLAG_FOR_LOSKI_POTOK_SI_066 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0036\U000e0036\U000e007f"
- FLAG_FOR_NAZARJE_SI_083 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0038\U000e0033\U000e007f"
- FLAG_FOR_LITIJA_SI_060 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0036\U000e0030\U000e007f"
- FLAG_FOR_LUKOVICA_SI_068 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0036\U000e0038\U000e007f"
- FLAG_FOR_PESNICA_SI_089 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0038\U000e0039\U000e007f"
- FLAG_FOR_OSILNICA_SI_088 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0038\U000e0038\U000e007f"
- FLAG_FOR_LENDAVA_SI_059 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0035\U000e0039\U000e007f"
- FLAG_FOR_MIREN_KOSTANJEVICA_SI_075 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0037\U000e0035\U000e007f"
- FLAG_FOR_MORAVSKE_TOPLICE_SI_078 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0037\U000e0038\U000e007f"
- FLAG_FOR_PODCETRTEK_SI_092 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0039\U000e0032\U000e007f"
- FLAG_FOR_LJUTOMER_SI_063 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0036\U000e0033\U000e007f"
- FLAG_FOR_LASKO_SI_057 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0035\U000e0037\U000e007f"
- FLAG_FOR_PIVKA_SI_091 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0039\U000e0031\U000e007f"
- FLAG_FOR_METLIKA_SI_073 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0037\U000e0033\U000e007f"
- FLAG_FOR_HERCEG_NOVI_ME_08 = "\U0001f3f4\U000e006d\U000e0065\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_LOSKA_DOLINA_SI_065 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0036\U000e0035\U000e007f"
- FLAG_FOR_ANSE_ETOILE_SC_03 = "\U0001f3f4\U000e0073\U000e0063\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_ORMOZ_SI_087 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0038\U000e0037\U000e007f"
- FLAG_FOR_LOGATEC_SI_064 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0036\U000e0034\U000e007f"
- FLAG_FOR_NAKLO_SI_082 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0038\U000e0032\U000e007f"
- FLAG_FOR_NOVA_GORICA_SI_084 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0038\U000e0034\U000e007f"
- FLAG_FOR_LJUBNO_SI_062 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0036\U000e0032\U000e007f"
- FLAG_FOR_MISLINJA_SI_076 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0037\U000e0036\U000e007f"
- FLAG_FOR_MEDVODE_SI_071 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0037\U000e0031\U000e007f"
- FLAG_FOR_POSTOJNA_SI_094 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0039\U000e0034\U000e007f"
- FLAG_FOR_MORAVCE_SI_077 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0037\U000e0037\U000e007f"
- FLAG_FOR_LJUBLJANA_SI_061 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0036\U000e0031\U000e007f"
- FLAG_FOR_MAJSPERK_SI_069 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0036\U000e0039\U000e007f"
- FLAG_FOR_MENGES_SI_072 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0037\U000e0032\U000e007f"
- FLAG_FOR_MUTA_SI_081 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0038\U000e0031\U000e007f"
- FLAG_FOR_MOZIRJE_SI_079 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0037\U000e0039\U000e007f"
- FLAG_FOR_MURSKA_SOBOTA_SI_080 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0038\U000e0030\U000e007f"
- FLAG_FOR_RIBNICA_SI_104 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_SKOFLJICA_SI_123 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_SEZANA_SI_111 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_TRBOVLJE_SI_129 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0032\U000e0039\U000e007f"
- FLAG_FOR_SLOVENSKE_KONJICE_SI_114 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_STORE_SI_127 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0032\U000e0037\U000e007f"
- FLAG_FOR_PUCONCI_SI_097 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0039\U000e0037\U000e007f"
- FLAG_FOR_TREBNJE_SI_130 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_ROGATEC_SI_107 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_TOLMIN_SI_128 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0032\U000e0038\U000e007f"
- FLAG_FOR_RADOVLJICA_SI_102 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_SEVNICA_SI_110 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_STARSE_SI_115 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_RADLJE_OB_DRAVI_SI_101 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_PTUJ_SI_096 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0039\U000e0036\U000e007f"
- FLAG_FOR_SLOVENSKA_BISTRICA_SI_113 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_SEMIC_SI_109 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_PREDDVOR_SI_095 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0039\U000e0035\U000e007f"
- FLAG_FOR_RADECE_SI_099 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0039\U000e0039\U000e007f"
- FLAG_FOR_SOSTANJ_SI_126 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_ROGASKA_SLATINA_SI_106 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_TRZIC_SI_131 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0033\U000e0031\U000e007f"
- FLAG_FOR_RUSE_SI_108 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_SMARJE_PRI_JELSAH_SI_124 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_TURNISCE_SI_132 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_SKOCJAN_SI_121 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_SVETI_JURIJ_SI_116 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_RACE_FRAM_SI_098 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0039\U000e0038\U000e007f"
- FLAG_FOR_SLOVENJ_GRADEC_SI_112 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_SENTILJ_SI_118 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_ROGASOVCI_SI_105 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_SENTJERNEJ_SI_119 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_SENCUR_SI_117 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_SENTJUR_SI_120 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_RAVNE_NA_KOROSKEM_SI_103 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_DOLENJSKE_TOPLICE_SI_157 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0035\U000e0037\U000e007f"
- FLAG_FOR_MIKLAVZ_NA_DRAVSKEM_POLJU_SI_169 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0036\U000e0039\U000e007f"
- FLAG_FOR_VIDEM_SI_135 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0033\U000e0035\U000e007f"
- FLAG_FOR_ZRECE_SI_144 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0034\U000e0034\U000e007f"
- FLAG_FOR_WEST_DARFUR_SD_DW = "\U0001f3f4\U000e0073\U000e0064\U000e0064\U000e0077\U000e007f"
- FLAG_FOR_KOSTEL_SI_165 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0036\U000e0035\U000e007f"
- FLAG_FOR_VOJNIK_SI_139 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0033\U000e0039\U000e007f"
- FLAG_FOR_BENEDIKT_SI_148 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0034\U000e0038\U000e007f"
- FLAG_FOR_HORJUL_SI_162 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0036\U000e0032\U000e007f"
- FLAG_FOR_OPLOTNICA_SI_171 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0037\U000e0031\U000e007f"
- FLAG_FOR_JEZERSKO_SI_163 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0036\U000e0033\U000e007f"
- FLAG_FOR_VITANJE_SI_137 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0033\U000e0037\U000e007f"
- FLAG_FOR_ZAGORJE_OB_SAVI_SI_142 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0034\U000e0032\U000e007f"
- FLAG_FOR_VUZENICA_SI_141 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_VIPAVA_SI_136 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0033\U000e0036\U000e007f"
- FLAG_FOR_HAJDINA_SI_159 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0035\U000e0039\U000e007f"
- FLAG_FOR_ZELEZNIKI_SI_146 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0034\U000e0036\U000e007f"
- FLAG_FOR_ZIRI_SI_147 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0034\U000e0037\U000e007f"
- FLAG_FOR_KRIZEVCI_SI_166 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0036\U000e0036\U000e007f"
- FLAG_FOR_CERKVENJAK_SI_153 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0035\U000e0033\U000e007f"
- FLAG_FOR_VRHNIKA_SI_140 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0034\U000e0030\U000e007f"
- FLAG_FOR_HOCE_SLIVNICA_SI_160 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0036\U000e0030\U000e007f"
- FLAG_FOR_VODICE_SI_138 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0033\U000e0038\U000e007f"
- FLAG_FOR_MIRNA_PEC_SI_170 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0037\U000e0030\U000e007f"
- FLAG_FOR_MARKOVCI_SI_168 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0036\U000e0038\U000e007f"
- FLAG_FOR_HODOS_SI_161 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0036\U000e0031\U000e007f"
- FLAG_FOR_DOBRNA_SI_155 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0035\U000e0035\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FLAG_FOR_KOMENDA_SI_164 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0036\U000e0034\U000e007f"
- FLAG_FOR_ZALEC_SI_190 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0039\U000e0030\U000e007f"
- FLAG_FOR_TRNOVSKA_VAS_SI_185 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0038\U000e0035\U000e007f"
- FLAG_FOR_SMARTNO_PRI_LITIJI_SI_194 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0039\U000e0034\U000e007f"
- FLAG_FOR_GORJE_SI_207 = "\U0001f3f4\U000e0073\U000e0069\U000e0032\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_PREBOLD_SI_174 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0037\U000e0034\U000e007f"
- FLAG_FOR_SELNICA_OB_DRAVI_SI_178 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0037\U000e0038\U000e007f"
- FLAG_FOR_APACE_SI_195 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0039\U000e0035\U000e007f"
- FLAG_FOR_CIRKULANE_SI_196 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0039\U000e0036\U000e007f"
- FLAG_FOR_SOLCAVA_SI_180 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0038\U000e0030\U000e007f"
- FLAG_FOR_SEMPETER_VRTOJBA_SI_183 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0038\U000e0033\U000e007f"
- FLAG_FOR_VALLON_DE_LA_ROUSSE_MC_VR = "\U0001f3f4\U000e006d\U000e0063\U000e0076\U000e0072\U000e007f"
- FLAG_FOR_SODRAZICA_SI_179 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0037\U000e0039\U000e007f"
- FLAG_FOR_RENCE_VOGRSKO_SI_201 = "\U0001f3f4\U000e0073\U000e0069\U000e0032\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_PREVALJE_SI_175 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0037\U000e0035\U000e007f"
- FLAG_FOR_POLJCANE_SI_200 = "\U0001f3f4\U000e0073\U000e0069\U000e0032\U000e0030\U000e0030\U000e007f"
- FLAG_FOR_RIBNICA_NA_POHORJU_SI_177 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0037\U000e0037\U000e007f"
- FLAG_FOR_VERZEJ_SI_188 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0038\U000e0038\U000e007f"
- FLAG_FOR_MAKOLE_SI_198 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0039\U000e0038\U000e007f"
- FLAG_FOR_PODLEHNIK_SI_172 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0037\U000e0032\U000e007f"
- FLAG_FOR_POLZELA_SI_173 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0037\U000e0033\U000e007f"
- FLAG_FOR_RAZKRIZJE_SI_176 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0037\U000e0036\U000e007f"
- FLAG_FOR_TABOR_SI_184 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0038\U000e0034\U000e007f"
- FLAG_FOR_KOSTANJEVICA_NA_KRKI_SI_197 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0039\U000e0037\U000e007f"
- FLAG_FOR_ZETALE_SI_191 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0039\U000e0031\U000e007f"
- FLAG_FOR_ZUZEMBERK_SI_193 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0039\U000e0033\U000e007f"
- FLAG_FOR_STRAZA_SI_203 = "\U0001f3f4\U000e0073\U000e0069\U000e0032\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_VRANSKO_SI_189 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0038\U000e0039\U000e007f"
- FLAG_FOR_TUBAS_PS_TBS = "\U0001f3f4\U000e0070\U000e0073\U000e0074\U000e0062\U000e0073\U000e007f"
- FLAG_FOR_TRZIN_SI_186 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0038\U000e0036\U000e007f"
- FLAG_FOR_SVETI_TOMAZ_SI_205 = "\U0001f3f4\U000e0073\U000e0069\U000e0032\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_MOKRONOG_TREBELNO_SI_199 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0039\U000e0039\U000e007f"
- FLAG_FOR_WESTERN_AREA_SL_W = "\U0001f3f4\U000e0073\U000e006c\U000e0077\U000e007f"
- FLAG_FOR_CALABRIA_IT_78 = "\U0001f3f4\U000e0069\U000e0074\U000e0037\U000e0038\U000e007f"
- FLAG_FOR_SERRAVALLE_SM_09 = "\U0001f3f4\U000e0073\U000e006d\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_FAETANO_SM_04 = "\U0001f3f4\U000e0073\U000e006d\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_SENTRUPERT_SI_211 = "\U0001f3f4\U000e0073\U000e0069\U000e0032\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_TRNAVA_SK_TA = "\U0001f3f4\U000e0073\U000e006b\U000e0074\U000e0061\U000e007f"
- FLAG_FOR_ACQUAVIVA_SM_01 = "\U0001f3f4\U000e0073\U000e006d\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_SOUTHERN_SL_S = "\U0001f3f4\U000e0073\U000e006c\U000e0073\U000e007f"
- FLAG_FOR_PRESOV_SK_PV = "\U0001f3f4\U000e0073\U000e006b\U000e0070\U000e0076\U000e007f"
- FLAG_FOR_KOSICE_SK_KI = "\U0001f3f4\U000e0073\U000e006b\U000e006b\U000e0069\U000e007f"
- FLAG_FOR_NORTHERN_SL_N = "\U0001f3f4\U000e0073\U000e006c\U000e006e\U000e007f"
- FLAG_FOR_KAOLACK_SN_KL = "\U0001f3f4\U000e0073\U000e006e\U000e006b\U000e006c\U000e007f"
- FLAG_FOR_SAN_MARINO_SM_07 = "\U0001f3f4\U000e0073\U000e006d\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_FIORENTINO_SM_05 = "\U0001f3f4\U000e0073\U000e006d\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_TAMBACOUNDA_SN_TC = "\U0001f3f4\U000e0073\U000e006e\U000e0074\U000e0063\U000e007f"
- FLAG_FOR_SEOUL_KR_11 = "\U0001f3f4\U000e006b\U000e0072\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_CHIESANUOVA_SM_02 = "\U0001f3f4\U000e0073\U000e006d\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_KOLDA_SN_KD = "\U0001f3f4\U000e0073\U000e006e\U000e006b\U000e0064\U000e007f"
- FLAG_FOR_KAFFRINE_SN_KA = "\U0001f3f4\U000e0073\U000e006e\U000e006b\U000e0061\U000e007f"
- FLAG_FOR_SEDHIOU_SN_SE = "\U0001f3f4\U000e0073\U000e006e\U000e0073\U000e0065\U000e007f"
- FLAG_FOR_FATICK_SN_FK = "\U0001f3f4\U000e0073\U000e006e\U000e0066\U000e006b\U000e007f"
- FLAG_FOR_TRENCIN_SK_TC = "\U0001f3f4\U000e0073\U000e006b\U000e0074\U000e0063\U000e007f"
- FLAG_FOR_BANSKA_BYSTRICA_SK_BC = "\U0001f3f4\U000e0073\U000e006b\U000e0062\U000e0063\U000e007f"
- FLAG_FOR_LOUGA_SN_LG = "\U0001f3f4\U000e0073\U000e006e\U000e006c\U000e0067\U000e007f"
- FLAG_FOR_NITRA_SK_NI = "\U0001f3f4\U000e0073\U000e006b\U000e006e\U000e0069\U000e007f"
- FLAG_FOR_RECICA_OB_SAVINJI_SI_209 = "\U0001f3f4\U000e0073\U000e0069\U000e0032\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_RAJASTHAN_IN_RJ = "\U0001f3f4\U000e0069\U000e006e\U000e0072\U000e006a\U000e007f"
- FLAG_FOR_LENINGRAD_RU_LEN = "\U0001f3f4\U000e0072\U000e0075\U000e006c\U000e0065\U000e006e\U000e007f"
- FLAG_FOR_ZILINA_SK_ZI = "\U0001f3f4\U000e0073\U000e006b\U000e007a\U000e0069\U000e007f"
- FLAG_FOR_BORGO_MAGGIORE_SM_06 = "\U0001f3f4\U000e0073\U000e006d\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_MATAM_SN_MT = "\U0001f3f4\U000e0073\U000e006e\U000e006d\U000e0074\U000e007f"
- FLAG_FOR_DOMAGNANO_SM_03 = "\U0001f3f4\U000e0073\U000e006d\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_KEDOUGOU_SN_KE = "\U0001f3f4\U000e0073\U000e006e\U000e006b\U000e0065\U000e007f"
- FLAG_FOR_MIRNA_SI_212 = "\U0001f3f4\U000e0073\U000e0069\U000e0032\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_THIES_SN_TH = "\U0001f3f4\U000e0073\U000e006e\U000e0074\U000e0068\U000e007f"
- FLAG_FOR_MONTEGIARDINO_SM_08 = "\U0001f3f4\U000e0073\U000e006d\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_VALCEA_RO_VL = "\U0001f3f4\U000e0072\U000e006f\U000e0076\U000e006c\U000e007f"
- FLAG_FOR_CLUJ_RO_CJ = "\U0001f3f4\U000e0072\U000e006f\U000e0063\U000e006a\U000e007f"
- FLAG_FOR_TOGDHEER_SO_TO = "\U0001f3f4\U000e0073\U000e006f\U000e0074\U000e006f\U000e007f"
- FLAG_FOR_UPPER_NILE_SS_NU = "\U0001f3f4\U000e0073\U000e0073\U000e006e\U000e0075\U000e007f"
- FLAG_FOR_SARAMACCA_SR_SA = "\U0001f3f4\U000e0073\U000e0072\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_WESTERN_BAHR_EL_GHAZAL_SS_BW = "\U0001f3f4\U000e0073\U000e0073\U000e0062\U000e0077\U000e007f"
- FLAG_FOR_WARRAP_SS_WR = "\U0001f3f4\U000e0073\U000e0073\U000e0077\U000e0072\U000e007f"
- DIE_FACE_6 = "\u2685"
- FLAG_FOR_NICKERIE_SR_NI = "\U0001f3f4\U000e0073\U000e0072\U000e006e\U000e0069\U000e007f"
- FLAG_FOR_EASTERN_EQUATORIA_SS_EE = "\U0001f3f4\U000e0073\U000e0073\U000e0065\U000e0065\U000e007f"
- FLAG_FOR_BAKOOL_SO_BK = "\U0001f3f4\U000e0073\U000e006f\U000e0062\U000e006b\U000e007f"
- FLAG_FOR_PARAMARIBO_SR_PM = "\U0001f3f4\U000e0073\U000e0072\U000e0070\U000e006d\U000e007f"
- FLAG_FOR_WANICA_SR_WA = "\U0001f3f4\U000e0073\U000e0072\U000e0077\U000e0061\U000e007f"
- FLAG_FOR_ANGAUR_PW_010 = "\U0001f3f4\U000e0070\U000e0077\U000e0030\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_MUDUG_SO_MU = "\U0001f3f4\U000e0073\U000e006f\U000e006d\U000e0075\U000e007f"
- FLAG_FOR_MIDDLE_JUBA_SO_JD = "\U0001f3f4\U000e0073\U000e006f\U000e006a\U000e0064\U000e007f"
- FLAG_FOR_WESTERN_EQUATORIA_SS_EW = "\U0001f3f4\U000e0073\U000e0073\U000e0065\U000e0077\U000e007f"
- FLAG_FOR_PRINCIPE_ST_P = "\U0001f3f4\U000e0073\U000e0074\U000e0070\U000e007f"
- FLAG_FOR_CORONIE_SR_CR = "\U0001f3f4\U000e0073\U000e0072\U000e0063\U000e0072\U000e007f"
- FLAG_FOR_CONSTANTA_RO_CT = "\U0001f3f4\U000e0072\U000e006f\U000e0063\U000e0074\U000e007f"
- FLAG_FOR_HIRAN_SO_HI = "\U0001f3f4\U000e0073\U000e006f\U000e0068\U000e0069\U000e007f"
- FLAG_FOR_KARELIA_RU_KR = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e0072\U000e007f"
- FLAG_FOR_LOWER_SHEBELLE_SO_SH = "\U0001f3f4\U000e0073\U000e006f\U000e0073\U000e0068\U000e007f"
- FLAG_FOR_GEDO_SO_GE = "\U0001f3f4\U000e0073\U000e006f\U000e0067\U000e0065\U000e007f"
- FLAG_FOR_ZIGUINCHOR_SN_ZG = "\U0001f3f4\U000e0073\U000e006e\U000e007a\U000e0067\U000e007f"
- FLAG_FOR_BOQUERON_PY_19 = "\U0001f3f4\U000e0070\U000e0079\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_MIDDLE_SHEBELLE_SO_SD = "\U0001f3f4\U000e0073\U000e006f\U000e0073\U000e0064\U000e007f"
- FLAG_FOR_SANAAG_SO_SA = "\U0001f3f4\U000e0073\U000e006f\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_BROKOPONDO_SR_BR = "\U0001f3f4\U000e0073\U000e0072\U000e0062\U000e0072\U000e007f"
- FLAG_FOR_BREZICE_SI_009 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_HRPELJE_KOZINA_SI_035 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0033\U000e0035\U000e007f"
- FLAG_FOR_AWDAL_SO_AW = "\U0001f3f4\U000e0073\U000e006f\U000e0061\U000e0077\U000e007f"
- FLAG_FOR_LATAKIA_SY_LA = "\U0001f3f4\U000e0073\U000e0079\U000e006c\U000e0061\U000e007f"
- FLAG_FOR_AS_SUWAYDA_SY_SU = "\U0001f3f4\U000e0073\U000e0079\U000e0073\U000e0075\U000e007f"
- FLAG_FOR_AR_RAQQAH_SY_RA = "\U0001f3f4\U000e0073\U000e0079\U000e0072\U000e0061\U000e007f"
- FLAG_FOR_CUSCATLAN_SV_CU = "\U0001f3f4\U000e0073\U000e0076\U000e0063\U000e0075\U000e007f"
- FLAG_FOR_CHALATENANGO_SV_CH = "\U0001f3f4\U000e0073\U000e0076\U000e0063\U000e0068\U000e007f"
- FLAG_FOR_GALGUDUUD_SO_GA = "\U0001f3f4\U000e0073\U000e006f\U000e0067\U000e0061\U000e007f"
- FLAG_FOR_DOBROVNIK_SI_156 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0035\U000e0036\U000e007f"
- FLAG_FOR_BORKOU_TD_BO = "\U0001f3f4\U000e0074\U000e0064\U000e0062\U000e006f\U000e007f"
- FLAG_FOR_LUBOMBO_SZ_LU = "\U0001f3f4\U000e0073\U000e007a\U000e006c\U000e0075\U000e007f"
- FLAG_FOR_MANZINI_SZ_MA = "\U0001f3f4\U000e0073\U000e007a\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_MORAZAN_SV_MO = "\U0001f3f4\U000e0073\U000e0076\U000e006d\U000e006f\U000e007f"
- FLAG_FOR_DARAA_SY_DR = "\U0001f3f4\U000e0073\U000e0079\U000e0064\U000e0072\U000e007f"
- FLAG_FOR_SANTA_ANA_SV_SA = "\U0001f3f4\U000e0073\U000e0076\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_TARTUS_SY_TA = "\U0001f3f4\U000e0073\U000e0079\U000e0074\U000e0061\U000e007f"
- FLAG_FOR_SHISELWENI_SZ_SH = "\U0001f3f4\U000e0073\U000e007a\U000e0073\U000e0068\U000e007f"
- FLAG_FOR_LA_UNION_SV_UN = "\U0001f3f4\U000e0073\U000e0076\U000e0075\U000e006e\U000e007f"
- FLAG_FOR_BATHA_TD_BA = "\U0001f3f4\U000e0074\U000e0064\U000e0062\U000e0061\U000e007f"
- FLAG_FOR_KANEM_TD_KA = "\U0001f3f4\U000e0074\U000e0064\U000e006b\U000e0061\U000e007f"
- FLAG_FOR_GUADELOUPE_FR_GUA = "\U0001f3f4\U000e0066\U000e0072\U000e0067\U000e0075\U000e0061\U000e007f"
- FLAG_FOR_QUNEITRA_SY_QU = "\U0001f3f4\U000e0073\U000e0079\U000e0071\U000e0075\U000e007f"
- FLAG_FOR_HOMS_SY_HI = "\U0001f3f4\U000e0073\U000e0079\U000e0068\U000e0069\U000e007f"
- FLAG_FOR_AL_HASAKAH_SY_HA = "\U0001f3f4\U000e0073\U000e0079\U000e0068\U000e0061\U000e007f"
- FLAG_FOR_HAMA_SY_HM = "\U0001f3f4\U000e0073\U000e0079\U000e0068\U000e006d\U000e007f"
- FLAG_FOR_AHUACHAPAN_SV_AH = "\U0001f3f4\U000e0073\U000e0076\U000e0061\U000e0068\U000e007f"
- FLAG_FOR_SONSONATE_SV_SO = "\U0001f3f4\U000e0073\U000e0076\U000e0073\U000e006f\U000e007f"
- FLAG_FOR_CABANAS_SV_CA = "\U0001f3f4\U000e0073\U000e0076\U000e0063\U000e0061\U000e007f"
- FLAG_FOR_ENNEDI_EST_TD_EE = "\U0001f3f4\U000e0074\U000e0064\U000e0065\U000e0065\U000e007f"
- FLAG_FOR_ALEPPO_SY_HL = "\U0001f3f4\U000e0073\U000e0079\U000e0068\U000e006c\U000e007f"
- FLAG_FOR_GOVISUMBER_MN_064 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0036\U000e0034\U000e007f"
- FLAG_FOR_LA_LIBERTAD_SV_LI = "\U0001f3f4\U000e0073\U000e0076\U000e006c\U000e0069\U000e007f"
- FLAG_FOR_BAHR_EL_GAZEL_TD_BG = "\U0001f3f4\U000e0074\U000e0064\U000e0062\U000e0067\U000e007f"
- FLAG_FOR_SIPALIWINI_SR_SI = "\U0001f3f4\U000e0073\U000e0072\U000e0073\U000e0069\U000e007f"
- FLAG_FOR_FINNMARK_NO_20 = "\U0001f3f4\U000e006e\U000e006f\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_NONTHABURI_TH_12 = "\U0001f3f4\U000e0074\U000e0068\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_PATHUM_THANI_TH_13 = "\U0001f3f4\U000e0074\U000e0068\U000e0031\U000e0033\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_WADI_FIRA_TD_WF = "\U0001f3f4\U000e0074\U000e0064\U000e0077\U000e0066\U000e007f"
- FLAG_FOR_PRACHIN_BURI_TH_25 = "\U0001f3f4\U000e0074\U000e0068\U000e0032\U000e0035\U000e007f"
- FLAG_FOR_BURI_RAM_TH_31 = "\U0001f3f4\U000e0074\U000e0068\U000e0033\U000e0031\U000e007f"
- FLAG_FOR_NAKHON_RATCHASIMA_TH_30 = "\U0001f3f4\U000e0074\U000e0068\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_N_DJAMENA_TD_ND = "\U0001f3f4\U000e0074\U000e0064\U000e006e\U000e0064\U000e007f"
- FLAG_FOR_PHRA_NAKHON_SI_AYUTTHAYA_TH_14 = "\U0001f3f4\U000e0074\U000e0068\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_MARSASKALA_MT_27 = "\U0001f3f4\U000e006d\U000e0074\U000e0032\U000e0037\U000e007f"
- FLAG_FOR_LOGONE_OCCIDENTAL_TD_LO = "\U0001f3f4\U000e0074\U000e0064\U000e006c\U000e006f\U000e007f"
- FLAG_FOR_CHACHOENGSAO_TH_24 = "\U0001f3f4\U000e0074\U000e0068\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_TIBESTI_TD_TI = "\U0001f3f4\U000e0074\U000e0064\U000e0074\U000e0069\U000e007f"
- FLAG_FOR_CHAI_NAT_TH_18 = "\U0001f3f4\U000e0074\U000e0068\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_MOYEN_CHARI_TD_MC = "\U0001f3f4\U000e0074\U000e0064\U000e006d\U000e0063\U000e007f"
- FLAG_FOR_TANDJILE_TD_TA = "\U0001f3f4\U000e0074\U000e0064\U000e0074\U000e0061\U000e007f"
- FLAG_FOR_SAINT_HELENA_SH_HL = "\U0001f3f4\U000e0073\U000e0068\U000e0068\U000e006c\U000e007f"
- FLAG_FOR_PLATEAUX_TG_P = "\U0001f3f4\U000e0074\U000e0067\U000e0070\U000e007f"
- FLAG_FOR_SALAMAT_TD_SA = "\U0001f3f4\U000e0074\U000e0064\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_CHON_BURI_TH_20 = "\U0001f3f4\U000e0074\U000e0068\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_MANDOUL_TD_MA = "\U0001f3f4\U000e0074\U000e0064\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_MAYO_KEBBI_EST_TD_ME = "\U0001f3f4\U000e0074\U000e0064\U000e006d\U000e0065\U000e007f"
- FLAG_FOR_SURIN_TH_32 = "\U0001f3f4\U000e0074\U000e0068\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_ARDAHAN_TR_75 = "\U0001f3f4\U000e0074\U000e0072\U000e0037\U000e0035\U000e007f"
- FLAG_FOR_NAKHON_NAYOK_TH_26 = "\U0001f3f4\U000e0074\U000e0068\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_SARABURI_TH_19 = "\U0001f3f4\U000e0074\U000e0068\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_RIF_DIMASHQ_SY_RD = "\U0001f3f4\U000e0073\U000e0079\U000e0072\U000e0064\U000e007f"
- FLAG_FOR_SAMUT_PRAKAN_TH_11 = "\U0001f3f4\U000e0074\U000e0068\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_SA_KAEO_TH_27 = "\U0001f3f4\U000e0074\U000e0068\U000e0032\U000e0037\U000e007f"
- FLAG_FOR_GUERA_TD_GR = "\U0001f3f4\U000e0074\U000e0064\U000e0067\U000e0072\U000e007f"
- FLAG_FOR_OUADDAI_TD_OD = "\U0001f3f4\U000e0074\U000e0064\U000e006f\U000e0064\U000e007f"
- FLAG_FOR_SAVANES_TG_S = "\U0001f3f4\U000e0074\U000e0067\U000e0073\U000e007f"
- FLAG_FOR_PHRAE_TH_54 = "\U0001f3f4\U000e0074\U000e0068\U000e0035\U000e0034\U000e007f"
- FLAG_FOR_KHON_KAEN_TH_40 = "\U0001f3f4\U000e0074\U000e0068\U000e0034\U000e0030\U000e007f"
- FLAG_FOR_UTHAI_THANI_TH_61 = "\U0001f3f4\U000e0074\U000e0068\U000e0036\U000e0031\U000e007f"
- FLAG_FOR_MUKDAHAN_TH_49 = "\U0001f3f4\U000e0074\U000e0068\U000e0034\U000e0039\U000e007f"
- FLAG_FOR_PHITSANULOK_TH_65 = "\U0001f3f4\U000e0074\U000e0068\U000e0036\U000e0035\U000e007f"
- FLAG_FOR_LAMPANG_TH_52 = "\U0001f3f4\U000e0074\U000e0068\U000e0035\U000e0032\U000e007f"
- FLAG_FOR_SUPHANBURI_TH_72 = "\U0001f3f4\U000e0074\U000e0068\U000e0037\U000e0032\U000e007f"
- FLAG_FOR_RATCHABURI_TH_70 = "\U0001f3f4\U000e0074\U000e0068\U000e0037\U000e0030\U000e007f"
- FLAG_FOR_UDON_THANI_TH_41 = "\U0001f3f4\U000e0074\U000e0068\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_LOEI_TH_42 = "\U0001f3f4\U000e0074\U000e0068\U000e0034\U000e0032\U000e007f"
- FLAG_FOR_NONG_KHAI_TH_43 = "\U0001f3f4\U000e0074\U000e0068\U000e0034\U000e0033\U000e007f"
- FLAG_FOR_NAKHON_SAWAN_TH_60 = "\U0001f3f4\U000e0074\U000e0068\U000e0036\U000e0030\U000e007f"
- FLAG_FOR_PHETCHABUN_TH_67 = "\U0001f3f4\U000e0074\U000e0068\U000e0036\U000e0037\U000e007f"
- FLAG_FOR_SAKON_NAKHON_TH_47 = "\U0001f3f4\U000e0074\U000e0068\U000e0034\U000e0037\U000e007f"
- FLAG_FOR_KALASIN_TH_46 = "\U0001f3f4\U000e0074\U000e0068\U000e0034\U000e0036\U000e007f"
- FLAG_FOR_KANCHANABURI_TH_71 = "\U0001f3f4\U000e0074\U000e0068\U000e0037\U000e0031\U000e007f"
- FLAG_FOR_TOTONICAPAN_GT_TO = "\U0001f3f4\U000e0067\U000e0074\U000e0074\U000e006f\U000e007f"
- FLAG_FOR_SAMUT_SAKHON_TH_74 = "\U0001f3f4\U000e0074\U000e0068\U000e0037\U000e0034\U000e007f"
- FLAG_FOR_TIGRAY_ET_TI = "\U0001f3f4\U000e0065\U000e0074\U000e0074\U000e0069\U000e007f"
- FLAG_FOR_NAKHON_PHANOM_TH_48 = "\U0001f3f4\U000e0074\U000e0068\U000e0034\U000e0038\U000e007f"
- FLAG_FOR_NAKHON_PATHOM_TH_73 = "\U0001f3f4\U000e0074\U000e0068\U000e0037\U000e0033\U000e007f"
- FLAG_FOR_UBON_RATCHATHANI_TH_34 = "\U0001f3f4\U000e0074\U000e0068\U000e0033\U000e0034\U000e007f"
- FLAG_FOR_KAMPHAENG_PHET_TH_62 = "\U0001f3f4\U000e0074\U000e0068\U000e0036\U000e0032\U000e007f"
- FLAG_FOR_YASOTHON_TH_35 = "\U0001f3f4\U000e0074\U000e0068\U000e0033\U000e0035\U000e007f"
- FLAG_FOR_CHIANG_RAI_TH_57 = "\U0001f3f4\U000e0074\U000e0068\U000e0035\U000e0037\U000e007f"
- FLAG_FOR_CHIANG_MAI_TH_50 = "\U0001f3f4\U000e0074\U000e0068\U000e0035\U000e0030\U000e007f"
- FLAG_FOR_NONG_BUA_LAM_PHU_TH_39 = "\U0001f3f4\U000e0074\U000e0068\U000e0033\U000e0039\U000e007f"
- FLAG_FOR_TAK_TH_63 = "\U0001f3f4\U000e0074\U000e0068\U000e0036\U000e0033\U000e007f"
- FLAG_FOR_BUENG_KAN_TH_38 = "\U0001f3f4\U000e0074\U000e0068\U000e0033\U000e0038\U000e007f"
- FLAG_FOR_LAMPHUN_TH_51 = "\U0001f3f4\U000e0074\U000e0068\U000e0035\U000e0031\U000e007f"
- FLAG_FOR_PHAYAO_TH_56 = "\U0001f3f4\U000e0074\U000e0068\U000e0035\U000e0036\U000e007f"
- FLAG_FOR_ROI_ET_TH_45 = "\U0001f3f4\U000e0074\U000e0068\U000e0034\U000e0035\U000e007f"
- FLAG_FOR_PHICHIT_TH_66 = "\U0001f3f4\U000e0074\U000e0068\U000e0036\U000e0036\U000e007f"
- FLAG_FOR_MAHA_SARAKHAM_TH_44 = "\U0001f3f4\U000e0074\U000e0068\U000e0034\U000e0034\U000e007f"
- FLAG_FOR_SI_SA_KET_TH_33 = "\U0001f3f4\U000e0074\U000e0068\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_NAN_TH_55 = "\U0001f3f4\U000e0074\U000e0068\U000e0035\U000e0035\U000e007f"
- FLAG_FOR_SUKHOTHAI_TH_64 = "\U0001f3f4\U000e0074\U000e0068\U000e0036\U000e0034\U000e007f"
- FLAG_FOR_AILEU_TL_AL = "\U0001f3f4\U000e0074\U000e006c\U000e0061\U000e006c\U000e007f"
- FLAG_FOR_MOQUEGUA_PE_MOQ = "\U0001f3f4\U000e0070\U000e0065\U000e006d\U000e006f\U000e0071\U000e007f"
- FLAG_FOR_BAUCAU_TL_BA = "\U0001f3f4\U000e0074\U000e006c\U000e0062\U000e0061\U000e007f"
- FLAG_FOR_AINARO_TL_AN = "\U0001f3f4\U000e0074\U000e006c\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_YAP_FM_YAP = "\U0001f3f4\U000e0066\U000e006d\U000e0079\U000e0061\U000e0070\U000e007f"
- FLAG_FOR_SATUN_TH_91 = "\U0001f3f4\U000e0074\U000e0068\U000e0039\U000e0031\U000e007f"
- FLAG_FOR_PHANG_NGA_TH_82 = "\U0001f3f4\U000e0074\U000e0068\U000e0038\U000e0032\U000e007f"
- FLAG_FOR_TRANG_TH_92 = "\U0001f3f4\U000e0074\U000e0068\U000e0039\U000e0032\U000e007f"
- FLAG_FOR_SONGKHLA_TH_90 = "\U0001f3f4\U000e0074\U000e0068\U000e0039\U000e0030\U000e007f"
- FLAG_FOR_DASOGUZ_TM_D = "\U0001f3f4\U000e0074\U000e006d\U000e0064\U000e007f"
- KISS_WOMAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_PATTAYA_TH_S = "\U0001f3f4\U000e0074\U000e0068\U000e0073\U000e007f"
- FLAG_FOR_BLEKINGE_SE_K = "\U0001f3f4\U000e0073\U000e0065\U000e006b\U000e007f"
- FLAG_FOR_MANATUTO_TL_MT = "\U0001f3f4\U000e0074\U000e006c\U000e006d\U000e0074\U000e007f"
- FLAG_FOR_PATTANI_TH_94 = "\U0001f3f4\U000e0074\U000e0068\U000e0039\U000e0034\U000e007f"
- FLAG_FOR_HIROSHIMA_JP_34 = "\U0001f3f4\U000e006a\U000e0070\U000e0033\U000e0034\U000e007f"
- FLAG_FOR_JIWAKA_PG_JWK = "\U0001f3f4\U000e0070\U000e0067\U000e006a\U000e0077\U000e006b\U000e007f"
- FLAG_FOR_LIQUICA_TL_LI = "\U0001f3f4\U000e0074\U000e006c\U000e006c\U000e0069\U000e007f"
- FLAG_FOR_KHATLON_TJ_KT = "\U0001f3f4\U000e0074\U000e006a\U000e006b\U000e0074\U000e007f"
- FLAG_FOR_SUGHD_TJ_SU = "\U0001f3f4\U000e0074\U000e006a\U000e0073\U000e0075\U000e007f"
- FLAG_FOR_VIQUEQUE_TL_VI = "\U0001f3f4\U000e0074\U000e006c\U000e0076\U000e0069\U000e007f"
- FLAG_FOR_BOBONARO_TL_BO = "\U0001f3f4\U000e0074\U000e006c\U000e0062\U000e006f\U000e007f"
- FLAG_FOR_SURAT_THANI_TH_84 = "\U0001f3f4\U000e0074\U000e0068\U000e0038\U000e0034\U000e007f"
- FLAG_FOR_RANONG_TH_85 = "\U0001f3f4\U000e0074\U000e0068\U000e0038\U000e0035\U000e007f"
- FLAG_FOR_NORD_EST_HT_NE = "\U0001f3f4\U000e0068\U000e0074\U000e006e\U000e0065\U000e007f"
- FLAG_FOR_PRACHUAP_KHIRI_KHAN_TH_77 = "\U0001f3f4\U000e0074\U000e0068\U000e0037\U000e0037\U000e007f"
- FLAG_FOR_PHETCHABURI_TH_76 = "\U0001f3f4\U000e0074\U000e0068\U000e0037\U000e0036\U000e007f"
- FLAG_FOR_NARATHIWAT_TH_96 = "\U0001f3f4\U000e0074\U000e0068\U000e0039\U000e0036\U000e007f"
- FLAG_FOR_MAHDIA_TN_53 = "\U0001f3f4\U000e0074\U000e006e\U000e0035\U000e0033\U000e007f"
- FLAG_FOR_TONGATAPU_TO_04 = "\U0001f3f4\U000e0074\U000e006f\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_VAVA_U_TO_05 = "\U0001f3f4\U000e0074\U000e006f\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_KAIROUAN_TN_41 = "\U0001f3f4\U000e0074\U000e006e\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_BOLU_TR_14 = "\U0001f3f4\U000e0074\U000e0072\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_BINGOL_TR_12 = "\U0001f3f4\U000e0074\U000e0072\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_AMASYA_TR_05 = "\U0001f3f4\U000e0074\U000e0072\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_BEJA_TN_31 = "\U0001f3f4\U000e0074\U000e006e\U000e0033\U000e0031\U000e007f"
- FLAG_FOR_ZAGHOUAN_TN_22 = "\U0001f3f4\U000e0074\U000e006e\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_BILECIK_TR_11 = "\U0001f3f4\U000e0074\U000e0072\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_AGRI_TR_04 = "\U0001f3f4\U000e0074\U000e0072\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_KEF_TN_33 = "\U0001f3f4\U000e0074\U000e006e\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_MANOUBA_TN_14 = "\U0001f3f4\U000e0074\U000e006e\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_MEDENINE_TN_82 = "\U0001f3f4\U000e0074\U000e006e\U000e0038\U000e0032\U000e007f"
- FLAG_FOR_BALIKESIR_TR_10 = "\U0001f3f4\U000e0074\U000e0072\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_EWA_NR_09 = "\U0001f3f4\U000e006e\U000e0072\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_TOZEUR_TN_72 = "\U0001f3f4\U000e0074\U000e006e\U000e0037\U000e0032\U000e007f"
- FLAG_FOR_EUA_TO_01 = "\U0001f3f4\U000e0074\U000e006f\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_KASSERINE_TN_42 = "\U0001f3f4\U000e0074\U000e006e\U000e0034\U000e0032\U000e007f"
- FLAG_FOR_GABES_TN_81 = "\U0001f3f4\U000e0074\U000e006e\U000e0038\U000e0031\U000e007f"
- FLAG_FOR_KAUNAS_LT_16 = "\U0001f3f4\U000e006c\U000e0074\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_SILIANA_TN_34 = "\U0001f3f4\U000e0074\U000e006e\U000e0033\U000e0034\U000e007f"
- FLAG_FOR_JENDOUBA_TN_32 = "\U0001f3f4\U000e0074\U000e006e\U000e0033\U000e0032\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FLAG_FOR_BIZERTE_TN_23 = "\U0001f3f4\U000e0074\U000e006e\U000e0032\U000e0033\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_SKIN_TONE_WOMAN = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469"
- FLAG_FOR_NIUAS_TO_03 = "\U0001f3f4\U000e0074\U000e006f\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_AYDIN_TR_09 = "\U0001f3f4\U000e0074\U000e0072\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_SIDI_BOUZID_TN_43 = "\U0001f3f4\U000e0074\U000e006e\U000e0034\U000e0033\U000e007f"
- FLAG_FOR_JOHOR_MY_01 = "\U0001f3f4\U000e006d\U000e0079\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_KEBILI_TN_73 = "\U0001f3f4\U000e0074\U000e006e\U000e0037\U000e0033\U000e007f"
- FLAG_FOR_TATAOUINE_TN_83 = "\U0001f3f4\U000e0074\U000e006e\U000e0038\U000e0033\U000e007f"
- FLAG_FOR_MONASTIR_TN_52 = "\U0001f3f4\U000e0074\U000e006e\U000e0035\U000e0032\U000e007f"
- FLAG_FOR_ARTVIN_TR_08 = "\U0001f3f4\U000e0074\U000e0072\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_GRAUBUNDEN_CH_GR = "\U0001f3f4\U000e0063\U000e0068\U000e0067\U000e0072\U000e007f"
- FLAG_FOR_MALATYA_TR_44 = "\U0001f3f4\U000e0074\U000e0072\U000e0034\U000e0034\U000e007f"
- FLAG_FOR_DENIZLI_TR_20 = "\U0001f3f4\U000e0074\U000e0072\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_RIZE_TR_53 = "\U0001f3f4\U000e0074\U000e0072\U000e0035\U000e0033\U000e007f"
- FLAG_FOR_DIYARBAKIR_TR_21 = "\U0001f3f4\U000e0074\U000e0072\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_EDIRNE_TR_22 = "\U0001f3f4\U000e0074\U000e0072\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_BURSA_TR_16 = "\U0001f3f4\U000e0074\U000e0072\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_SIIRT_TR_56 = "\U0001f3f4\U000e0074\U000e0072\U000e0035\U000e0036\U000e007f"
- FLAG_FOR_BOKE_REGION_GN_B = "\U0001f3f4\U000e0067\U000e006e\U000e0062\U000e007f"
- FLAG_FOR_KAHRAMANMARAS_TR_46 = "\U0001f3f4\U000e0074\U000e0072\U000e0034\U000e0036\U000e007f"
- FLAG_FOR_MARDIN_TR_47 = "\U0001f3f4\U000e0074\U000e0072\U000e0034\U000e0037\U000e007f"
- FLAG_FOR_ERZURUM_TR_25 = "\U0001f3f4\U000e0074\U000e0072\U000e0032\U000e0035\U000e007f"
- FLAG_FOR_ORO_PG_NPP = "\U0001f3f4\U000e0070\U000e0067\U000e006e\U000e0070\U000e0070\U000e007f"
- FLAG_FOR_NIGDE_TR_51 = "\U0001f3f4\U000e0074\U000e0072\U000e0035\U000e0031\U000e007f"
- FLAG_FOR_ORDU_TR_52 = "\U0001f3f4\U000e0074\U000e0072\U000e0035\U000e0032\U000e007f"
- FLAG_FOR_NGOBE_BUGLE_PA_NB = "\U0001f3f4\U000e0070\U000e0061\U000e006e\U000e0062\U000e007f"
- FLAG_FOR_HAKKARI_TR_30 = "\U0001f3f4\U000e0074\U000e0072\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_SAMSUN_TR_55 = "\U0001f3f4\U000e0074\U000e0072\U000e0035\U000e0035\U000e007f"
- FLAG_FOR_HATAY_TR_31 = "\U0001f3f4\U000e0074\U000e0072\U000e0033\U000e0031\U000e007f"
- FLAG_FOR_SAKARYA_TR_54 = "\U0001f3f4\U000e0074\U000e0072\U000e0035\U000e0034\U000e007f"
- FLAG_FOR_KIRKLARELI_TR_39 = "\U0001f3f4\U000e0074\U000e0072\U000e0033\U000e0039\U000e007f"
- FLAG_FOR_VICTORIA_MT_45 = "\U0001f3f4\U000e006d\U000e0074\U000e0034\U000e0035\U000e007f"
- FLAG_FOR_KIRSEHIR_TR_40 = "\U0001f3f4\U000e0074\U000e0072\U000e0034\U000e0030\U000e007f"
- FLAG_FOR_ISPARTA_TR_32 = "\U0001f3f4\U000e0074\U000e0072\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_ESKISEHIR_TR_26 = "\U0001f3f4\U000e0074\U000e0072\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_BURDUR_TR_15 = "\U0001f3f4\U000e0074\U000e0072\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_MANISA_TR_45 = "\U0001f3f4\U000e0074\U000e0072\U000e0034\U000e0035\U000e007f"
- FLAG_FOR_PRAHA_HLAVNI_MESTO_CZ_10 = "\U0001f3f4\U000e0063\U000e007a\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_ELAZIG_TR_23 = "\U0001f3f4\U000e0074\U000e0072\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_CANAKKALE_TR_17 = "\U0001f3f4\U000e0074\U000e0072\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_MAYARO_RIO_CLARO_TT_MRC = "\U0001f3f4\U000e0074\U000e0074\U000e006d\U000e0072\U000e0063\U000e007f"
- FLAG_FOR_TOKAT_TR_60 = "\U0001f3f4\U000e0074\U000e0072\U000e0036\U000e0030\U000e007f"
- FLAG_FOR_TOBAGO_TT_TOB = "\U0001f3f4\U000e0074\U000e0074\U000e0074\U000e006f\U000e0062\U000e007f"
- FLAG_FOR_DIEGO_MARTIN_TT_DMN = "\U0001f3f4\U000e0074\U000e0074\U000e0064\U000e006d\U000e006e\U000e007f"
- FLAG_FOR_SAN_FERNANDO_TT_SFO = "\U0001f3f4\U000e0074\U000e0074\U000e0073\U000e0066\U000e006f\U000e007f"
- FLAG_FOR_KILIS_TR_79 = "\U0001f3f4\U000e0074\U000e0072\U000e0037\U000e0039\U000e007f"
- KISS_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc"
- FLAG_FOR_PENZA_RU_PNZ = "\U0001f3f4\U000e0072\U000e0075\U000e0070\U000e006e\U000e007a\U000e007f"
- FLAG_FOR_SANLIURFA_TR_63 = "\U0001f3f4\U000e0074\U000e0072\U000e0036\U000e0033\U000e007f"
- FLAG_FOR_ERZINCAN_TR_24 = "\U0001f3f4\U000e0074\U000e0072\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_TEKIRDAG_TR_59 = "\U0001f3f4\U000e0074\U000e0072\U000e0035\U000e0039\U000e007f"
- FLAG_FOR_KIRIKKALE_TR_71 = "\U0001f3f4\U000e0074\U000e0072\U000e0037\U000e0031\U000e007f"
- FLAG_FOR_IGDIR_TR_76 = "\U0001f3f4\U000e0074\U000e0072\U000e0037\U000e0036\U000e007f"
- FLAG_FOR_COUVA_TABAQUITE_TALPARO_TT_CTT = "\U0001f3f4\U000e0074\U000e0074\U000e0063\U000e0074\U000e0074\U000e007f"
- FLAG_FOR_KARAMAN_TR_70 = "\U0001f3f4\U000e0074\U000e0072\U000e0037\U000e0030\U000e007f"
- FLAG_FOR_ZONGULDAK_TR_67 = "\U0001f3f4\U000e0074\U000e0072\U000e0036\U000e0037\U000e007f"
- FLAG_FOR_TUNCELI_TR_62 = "\U0001f3f4\U000e0074\U000e0072\U000e0036\U000e0032\U000e007f"
- FLAG_FOR_POINT_FORTIN_TT_PTF = "\U0001f3f4\U000e0074\U000e0074\U000e0070\U000e0074\U000e0066\U000e007f"
- FLAG_FOR_PENAL_DEBE_TT_PED = "\U0001f3f4\U000e0074\U000e0074\U000e0070\U000e0065\U000e0064\U000e007f"
- FLAG_FOR_SAN_JUAN_LAVENTILLE_TT_SJL = "\U0001f3f4\U000e0074\U000e0074\U000e0073\U000e006a\U000e006c\U000e007f"
- FLAG_FOR_PRINCES_TOWN_TT_PRT = "\U0001f3f4\U000e0074\U000e0074\U000e0070\U000e0072\U000e0074\U000e007f"
- FLAG_FOR_YALOVA_TR_77 = "\U0001f3f4\U000e0074\U000e0072\U000e0037\U000e0037\U000e007f"
- FLAG_FOR_BAYBURT_TR_69 = "\U0001f3f4\U000e0074\U000e0072\U000e0036\U000e0039\U000e007f"
- FLAG_FOR_BAIE_LAZARE_SC_06 = "\U0001f3f4\U000e0073\U000e0063\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_CHAGUANAS_TT_CHA = "\U0001f3f4\U000e0074\U000e0074\U000e0063\U000e0068\U000e0061\U000e007f"
- FLAG_FOR_BARTIN_TR_74 = "\U0001f3f4\U000e0074\U000e0072\U000e0037\U000e0034\U000e007f"
- FLAG_FOR_SIPARIA_TT_SIP = "\U0001f3f4\U000e0074\U000e0074\U000e0073\U000e0069\U000e0070\U000e007f"
- FLAG_FOR_SINOP_TR_57 = "\U0001f3f4\U000e0074\U000e0072\U000e0035\U000e0037\U000e007f"
- FLAG_FOR_GAZIANTEP_TR_27 = "\U0001f3f4\U000e0074\U000e0072\U000e0032\U000e0037\U000e007f"
- FLAG_FOR_KARABUK_TR_78 = "\U0001f3f4\U000e0074\U000e0072\U000e0037\U000e0038\U000e007f"
- FLAG_FOR_SANTA_BARBARA_HN_SB = "\U0001f3f4\U000e0068\U000e006e\U000e0073\U000e0062\U000e007f"
- FLAG_FOR_CHIAYI_COUNTY_TW_CYI = "\U0001f3f4\U000e0074\U000e0077\U000e0063\U000e0079\U000e0069\U000e007f"
- FLAG_FOR_KAGERA_TZ_05 = "\U0001f3f4\U000e0074\U000e007a\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_NANUMEA_TV_NMA = "\U0001f3f4\U000e0074\U000e0076\U000e006e\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_TAINAN_TW_TNN = "\U0001f3f4\U000e0074\U000e0077\U000e0074\U000e006e\U000e006e\U000e007f"
- FLAG_FOR_DODOMA_TZ_03 = "\U0001f3f4\U000e0074\U000e007a\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_CHIAYI_TW_CYQ = "\U0001f3f4\U000e0074\U000e0077\U000e0063\U000e0079\U000e0071\U000e007f"
- FLAG_FOR_YUNLIN_TW_YUN = "\U0001f3f4\U000e0074\U000e0077\U000e0079\U000e0075\U000e006e\U000e007f"
- FLAG_FOR_NEW_TAIPEI_TW_NWT = "\U0001f3f4\U000e0074\U000e0077\U000e006e\U000e0077\U000e0074\U000e007f"
- FLAG_FOR_KINMEN_TW_KIN = "\U0001f3f4\U000e0074\U000e0077\U000e006b\U000e0069\U000e006e\U000e007f"
- FLAG_FOR_HUALIEN_TW_HUA = "\U0001f3f4\U000e0074\U000e0077\U000e0068\U000e0075\U000e0061\U000e007f"
- FLAG_FOR_TAICHUNG_TW_TXG = "\U0001f3f4\U000e0074\U000e0077\U000e0074\U000e0078\U000e0067\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FLAG_FOR_PINGTUNG_TW_PIF = "\U0001f3f4\U000e0074\U000e0077\U000e0070\U000e0069\U000e0066\U000e007f"
- FLAG_FOR_IRINGA_TZ_04 = "\U0001f3f4\U000e0074\U000e007a\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_KEELUNG_TW_KEE = "\U0001f3f4\U000e0074\U000e0077\U000e006b\U000e0065\U000e0065\U000e007f"
- KISS_MAN_MEDIUM_DARK_SKIN_TONE_MAN = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468"
- FLAG_FOR_AGLONA_LV_001 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_CANKOVA_SI_152 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0035\U000e0032\U000e007f"
- FLAG_FOR_ARUSHA_TZ_01 = "\U0001f3f4\U000e0074\U000e007a\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_NUI_TV_NUI = "\U0001f3f4\U000e0074\U000e0076\U000e006e\U000e0075\U000e0069\U000e007f"
- FLAG_FOR_YILAN_TW_ILA = "\U0001f3f4\U000e0074\U000e0077\U000e0069\U000e006c\U000e0061\U000e007f"
- FLAG_FOR_VERACRUZ_MX_VER = "\U0001f3f4\U000e006d\U000e0078\U000e0076\U000e0065\U000e0072\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_LIENCHIANG_TW_LIE = "\U0001f3f4\U000e0074\U000e0077\U000e006c\U000e0069\U000e0065\U000e007f"
- FLAG_FOR_NUKUFETAU_TV_NKF = "\U0001f3f4\U000e0074\U000e0076\U000e006e\U000e006b\U000e0066\U000e007f"
- FLAG_FOR_VAITUPU_TV_VAI = "\U0001f3f4\U000e0074\U000e0076\U000e0076\U000e0061\U000e0069\U000e007f"
- FLAG_FOR_VOLYN_UA_07 = "\U0001f3f4\U000e0075\U000e0061\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_MTWARA_TZ_17 = "\U0001f3f4\U000e0074\U000e007a\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_TAMBOV_RU_TAM = "\U0001f3f4\U000e0072\U000e0075\U000e0074\U000e0061\U000e006d\U000e007f"
- FLAG_FOR_KATAVI_TZ_28 = "\U0001f3f4\U000e0074\U000e007a\U000e0032\U000e0038\U000e007f"
- FLAG_FOR_SOUTH_PEMBA_TZ_10 = "\U0001f3f4\U000e0074\U000e007a\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_RUKWA_TZ_20 = "\U0001f3f4\U000e0074\U000e007a\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_PORT_LOUIS_DISTRICT_MU_PL = "\U0001f3f4\U000e006d\U000e0075\U000e0070\U000e006c\U000e007f"
- FLAG_FOR_MANYARA_TZ_26 = "\U0001f3f4\U000e0074\U000e007a\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_SEVASTOPOL_UA_40 = "\U0001f3f4\U000e0075\U000e0061\U000e0034\U000e0030\U000e007f"
- FLAG_FOR_NJOMBE_TZ_29 = "\U0001f3f4\U000e0074\U000e007a\U000e0032\U000e0039\U000e007f"
- FLAG_FOR_ZAPORIZHZHYA_UA_23 = "\U0001f3f4\U000e0075\U000e0061\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_MBEYA_TZ_14 = "\U0001f3f4\U000e0074\U000e007a\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_KYIVSHCHYNA_UA_32 = "\U0001f3f4\U000e0075\U000e0061\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_RUVUMA_TZ_21 = "\U0001f3f4\U000e0074\U000e007a\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_SHINYANGA_TZ_22 = "\U0001f3f4\U000e0074\U000e007a\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_ZAKARPATTIA_UA_21 = "\U0001f3f4\U000e0075\U000e0061\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_NORTE_GW_N = "\U0001f3f4\U000e0067\U000e0077\U000e006e\U000e007f"
- FLAG_FOR_RIVNENSHCHYNA_UA_56 = "\U0001f3f4\U000e0075\U000e0061\U000e0035\U000e0036\U000e007f"
- FLAG_FOR_SAINT_GEORGE_DM_04 = "\U0001f3f4\U000e0064\U000e006d\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_ODESHCHYNA_UA_51 = "\U0001f3f4\U000e0075\U000e0061\U000e0035\U000e0031\U000e007f"
- FLAG_FOR_SIMIYU_TZ_30 = "\U0001f3f4\U000e0074\U000e007a\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_GEITA_TZ_27 = "\U0001f3f4\U000e0074\U000e007a\U000e0032\U000e0037\U000e007f"
- FLAG_FOR_POLTAVSHCHYNA_UA_53 = "\U0001f3f4\U000e0075\U000e0061\U000e0035\U000e0033\U000e007f"
- FLAG_FOR_TABORA_TZ_24 = "\U0001f3f4\U000e0074\U000e007a\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_SINGIDA_TZ_23 = "\U0001f3f4\U000e0074\U000e007a\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_MWANZA_TZ_18 = "\U0001f3f4\U000e0074\U000e007a\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_SELENGE_MN_049 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0034\U000e0039\U000e007f"
- FLAG_FOR_VINNYCHCHYNA_UA_05 = "\U0001f3f4\U000e0075\U000e0061\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_FLORIDA_US_FL = "\U0001f3f4\U000e0075\U000e0073\U000e0066\U000e006c\U000e007f"
- FLAG_FOR_LOFA_LR_LO = "\U0001f3f4\U000e006c\U000e0072\U000e006c\U000e006f\U000e007f"
- RECYCLING_SYMBOL_FOR_TYPE_7_PLASTICS = "\u2679"
- FLAG_FOR_BAKER_ISLAND_UM_81 = "\U0001f3f4\U000e0075\U000e006d\U000e0038\U000e0031\U000e007f"
- FLAG_FOR_NORTHERN_UG_N = "\U0001f3f4\U000e0075\U000e0067\U000e006e\U000e007f"
- FLAG_FOR_INGUSHETIA_RU_IN = "\U0001f3f4\U000e0072\U000e0075\U000e0069\U000e006e\U000e007f"
- FLAG_FOR_KHERSONSHCHYNA_UA_65 = "\U0001f3f4\U000e0075\U000e0061\U000e0036\U000e0035\U000e007f"
- FLAG_FOR_WAKE_ISLAND_UM_79 = "\U0001f3f4\U000e0075\U000e006d\U000e0037\U000e0039\U000e007f"
- FLAG_FOR_PALMYRA_ATOLL_UM_95 = "\U0001f3f4\U000e0075\U000e006d\U000e0039\U000e0035\U000e007f"
- FLAG_FOR_KHARKIVSHCHYNA_UA_63 = "\U0001f3f4\U000e0075\U000e0061\U000e0036\U000e0033\U000e007f"
- FLAG_FOR_KHMELNYCHCHYNA_UA_68 = "\U0001f3f4\U000e0075\U000e0061\U000e0036\U000e0038\U000e007f"
- FLAG_FOR_WESTERN_UG_W = "\U0001f3f4\U000e0075\U000e0067\U000e0077\U000e007f"
- FLAG_FOR_EASTERN_UG_E = "\U0001f3f4\U000e0075\U000e0067\U000e0065\U000e007f"
- FLAG_FOR_IDLIB_SY_ID = "\U0001f3f4\U000e0073\U000e0079\U000e0069\U000e0064\U000e007f"
- FLAG_FOR_TERNOPILSHCHYNA_UA_61 = "\U0001f3f4\U000e0075\U000e0061\U000e0036\U000e0031\U000e007f"
- FLAG_FOR_CHERNIVTSI_OBLAST_UA_77 = "\U0001f3f4\U000e0075\U000e0061\U000e0037\U000e0037\U000e007f"
- FLAG_FOR_PARA_SR_PR = "\U0001f3f4\U000e0073\U000e0072\U000e0070\U000e0072\U000e007f"
- FLAG_FOR_SUMSHCHYNA_UA_59 = "\U0001f3f4\U000e0075\U000e0061\U000e0035\U000e0039\U000e007f"
- FAMILY_WOMAN_WOMAN_BABY_BOY = "\U0001f469\u200d\U0001f469\u200d\U0001f476\u200d\U0001f466"
- FLAG_FOR_JERICHO_PS_JRH = "\U0001f3f4\U000e0070\U000e0073\U000e006a\U000e0072\U000e0068\U000e007f"
- FLAG_FOR_MIDWAY_ATOLL_UM_71 = "\U0001f3f4\U000e0075\U000e006d\U000e0037\U000e0031\U000e007f"
- FLAG_FOR_JOHNSTON_ATOLL_UM_67 = "\U0001f3f4\U000e0075\U000e006d\U000e0036\U000e0037\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_CANELONES_UY_CA = "\U0001f3f4\U000e0075\U000e0079\U000e0063\U000e0061\U000e007f"
- FLAG_FOR_KOSTROMA_RU_KOS = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e006f\U000e0073\U000e007f"
- FLAG_FOR_JARVIS_ISLAND_UM_86 = "\U0001f3f4\U000e0075\U000e006d\U000e0038\U000e0036\U000e007f"
- FLAG_FOR_PENNSYLVANIA_US_PA = "\U0001f3f4\U000e0075\U000e0073\U000e0070\U000e0061\U000e007f"
- FLAG_FOR_PUEBLA_MX_PUE = "\U0001f3f4\U000e006d\U000e0078\U000e0070\U000e0075\U000e0065\U000e007f"
- FLAG_FOR_SVETA_TROJICA_V_SLOVENSKIH_GORICAH_SI_204 = "\U0001f3f4\U000e0073\U000e0069\U000e0032\U000e0030\U000e0034\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_CHERKASHCHYNA_UA_71 = "\U0001f3f4\U000e0075\U000e0061\U000e0037\U000e0031\U000e007f"
- FLAG_FOR_ALEXANDRIA_EG_ALX = "\U0001f3f4\U000e0065\U000e0067\U000e0061\U000e006c\U000e0078\U000e007f"
- FLAG_FOR_CENTRAL_MACEDONIA_GR_B = "\U0001f3f4\U000e0067\U000e0072\U000e0062\U000e007f"
- FLAG_FOR_ARTIGAS_UY_AR = "\U0001f3f4\U000e0075\U000e0079\U000e0061\U000e0072\U000e007f"
- FLAG_FOR_OSLO_NO_03 = "\U0001f3f4\U000e006e\U000e006f\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_LOGONE_ORIENTAL_TD_LR = "\U0001f3f4\U000e0074\U000e0064\U000e006c\U000e0072\U000e007f"
- FLAG_FOR_SINT_EUSTATIUS_NL_BQ3 = "\U0001f3f4\U000e006e\U000e006c\U000e0062\U000e0071\U000e0033\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FLAG_FOR_KINGMAN_REEF_UM_89 = "\U0001f3f4\U000e0075\U000e006d\U000e0038\U000e0039\U000e007f"
- FLAG_FOR_DNIPROPETROVSHCHYNA_UA_12 = "\U0001f3f4\U000e0075\U000e0061\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_VRANCEA_RO_VN = "\U0001f3f4\U000e0072\U000e006f\U000e0076\U000e006e\U000e007f"
- FLAG_FOR_NORTH_PEMBA_TZ_06 = "\U0001f3f4\U000e0074\U000e007a\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_MONTEVIDEO_UY_MO = "\U0001f3f4\U000e0075\U000e0079\U000e006d\U000e006f\U000e007f"
- FLAG_FOR_COLONIA_UY_CO = "\U0001f3f4\U000e0075\U000e0079\U000e0063\U000e006f\U000e007f"
- FLAG_FOR_JIZZAKH_UZ_JI = "\U0001f3f4\U000e0075\U000e007a\U000e006a\U000e0069\U000e007f"
- FLAG_FOR_OKLAHOMA_US_OK = "\U0001f3f4\U000e0075\U000e0073\U000e006f\U000e006b\U000e007f"
- FLAG_FOR_TREINTA_Y_TRES_UY_TT = "\U0001f3f4\U000e0075\U000e0079\U000e0074\U000e0074\U000e007f"
- FLAG_FOR_SOUTH_CAROLINA_US_SC = "\U0001f3f4\U000e0075\U000e0073\U000e0073\U000e0063\U000e007f"
- FLAG_FOR_PAYSANDU_UY_PA = "\U0001f3f4\U000e0075\U000e0079\U000e0070\U000e0061\U000e007f"
- FLAG_FOR_TASHKENT_PROVINCE_UZ_TO = "\U0001f3f4\U000e0075\U000e007a\U000e0074\U000e006f\U000e007f"
- FLAG_FOR_NAMANGAN_UZ_NG = "\U0001f3f4\U000e0075\U000e007a\U000e006e\U000e0067\U000e007f"
- FLAG_FOR_DURAZNO_UY_DU = "\U0001f3f4\U000e0075\U000e0079\U000e0064\U000e0075\U000e007f"
- FLAG_FOR_ARAGUA_VE_D = "\U0001f3f4\U000e0076\U000e0065\U000e0064\U000e007f"
- FLAG_FOR_KARAKALPAKSTAN_UZ_QR = "\U0001f3f4\U000e0075\U000e007a\U000e0071\U000e0072\U000e007f"
- FLAG_FOR_CERRO_LARGO_UY_CL = "\U0001f3f4\U000e0075\U000e0079\U000e0063\U000e006c\U000e007f"
- FLAG_FOR_KELANTAN_MY_03 = "\U0001f3f4\U000e006d\U000e0079\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_FLORES_UY_FS = "\U0001f3f4\U000e0075\U000e0079\U000e0066\U000e0073\U000e007f"
- FLAG_FOR_FERGANA_UZ_FA = "\U0001f3f4\U000e0075\U000e007a\U000e0066\U000e0061\U000e007f"
- FLAG_FOR_MARYLAND_US_MD = "\U0001f3f4\U000e0075\U000e0073\U000e006d\U000e0064\U000e007f"
- FLAG_FOR_ANZOATEGUI_VE_B = "\U0001f3f4\U000e0076\U000e0065\U000e0062\U000e007f"
- FLAG_FOR_SAINT_ANDREW_VC_02 = "\U0001f3f4\U000e0076\U000e0063\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_BUKHARA_UZ_BU = "\U0001f3f4\U000e0075\U000e007a\U000e0062\U000e0075\U000e007f"
- FLAG_FOR_MELEKEOK_PW_212 = "\U0001f3f4\U000e0070\U000e0077\U000e0032\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_TELENESTI_MD_TE = "\U0001f3f4\U000e006d\U000e0064\U000e0074\U000e0065\U000e007f"
- FLAG_FOR_CHARLOTTE_VC_01 = "\U0001f3f4\U000e0076\U000e0063\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_ANDIJAN_UZ_AN = "\U0001f3f4\U000e0075\U000e007a\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_SALTO_UY_SA = "\U0001f3f4\U000e0075\U000e0079\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_SORIANO_UY_SO = "\U0001f3f4\U000e0075\U000e0079\U000e0073\U000e006f\U000e007f"
- FLAG_FOR_SIRDARYO_UZ_SI = "\U0001f3f4\U000e0075\U000e007a\U000e0073\U000e0069\U000e007f"
- FLAG_FOR_TASHKENT_UZ_TK = "\U0001f3f4\U000e0075\U000e007a\U000e0074\U000e006b\U000e007f"
- FLAG_FOR_CAPITAL_VE_A = "\U0001f3f4\U000e0076\U000e0065\U000e0061\U000e007f"
- FLAG_FOR_SAINT_DAVID_VC_03 = "\U0001f3f4\U000e0076\U000e0063\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_MALDONADO_UY_MA = "\U0001f3f4\U000e0075\U000e0079\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_RIO_NEGRO_UY_RN = "\U0001f3f4\U000e0075\U000e0079\U000e0072\U000e006e\U000e007f"
- FLAG_FOR_LAVALLEJA_UY_LA = "\U0001f3f4\U000e0075\U000e0079\U000e006c\U000e0061\U000e007f"
- FLAG_FOR_NAVOIY_UZ_NW = "\U0001f3f4\U000e0075\U000e007a\U000e006e\U000e0077\U000e007f"
- FLAG_FOR_SAMARQAND_UZ_SA = "\U0001f3f4\U000e0075\U000e007a\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_SURXONDARYO_UZ_SU = "\U0001f3f4\U000e0075\U000e007a\U000e0073\U000e0075\U000e007f"
- FLAG_FOR_QASHQADARYO_UZ_QA = "\U0001f3f4\U000e0075\U000e007a\U000e0071\U000e0061\U000e007f"
- FLAG_FOR_TACUAREMBO_UY_TA = "\U0001f3f4\U000e0075\U000e0079\U000e0074\U000e0061\U000e007f"
- FLAG_FOR_SON_LA_VN_05 = "\U0001f3f4\U000e0076\U000e006e\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_LANG_SON_VN_09 = "\U0001f3f4\U000e0076\U000e006e\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_HA_GIANG_VN_03 = "\U0001f3f4\U000e0076\U000e006e\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_MIRANDA_VE_M = "\U0001f3f4\U000e0076\U000e0065\U000e006d\U000e007f"
- FLAG_FOR_TUYEN_QUANG_VN_07 = "\U0001f3f4\U000e0076\U000e006e\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_THANH_HOA_VN_21 = "\U0001f3f4\U000e0076\U000e006e\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_NGHE_AN_VN_22 = "\U0001f3f4\U000e0076\U000e006e\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_COJEDES_VE_H = "\U0001f3f4\U000e0076\U000e0065\U000e0068\U000e007f"
- FLAG_FOR_CAO_BANG_VN_04 = "\U0001f3f4\U000e0076\U000e006e\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_QUANG_NGAI_VN_29 = "\U0001f3f4\U000e0076\U000e006e\U000e0032\U000e0039\U000e007f"
- FLAG_FOR_SANTANDER_CO_SAN = "\U0001f3f4\U000e0063\U000e006f\U000e0073\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_NINH_BINH_VN_18 = "\U0001f3f4\U000e0076\U000e006e\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_YEN_BAI_VN_06 = "\U0001f3f4\U000e0076\U000e006e\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_THAI_BINH_VN_20 = "\U0001f3f4\U000e0076\U000e006e\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_BARINAS_VE_E = "\U0001f3f4\U000e0076\U000e0065\U000e0065\U000e007f"
- FLAG_FOR_HA_TINH_VN_23 = "\U0001f3f4\U000e0076\U000e006e\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_LOWER_RIVER_DIVISION_GM_L = "\U0001f3f4\U000e0067\U000e006d\U000e006c\U000e007f"
- FLAG_FOR_IG_SI_037 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0033\U000e0037\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_LARA_VE_K = "\U0001f3f4\U000e0076\U000e0065\U000e006b\U000e007f"
- FLAG_FOR_QUANG_NINH_VN_13 = "\U0001f3f4\U000e0076\U000e006e\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_AU_CAP_SC_04 = "\U0001f3f4\U000e0073\U000e0063\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_HOA_BINH_VN_14 = "\U0001f3f4\U000e0076\U000e006e\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_KON_TUM_VN_28 = "\U0001f3f4\U000e0076\U000e006e\U000e0032\U000e0038\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_ZANZIBAR_URBAN_WEST_TZ_15 = "\U0001f3f4\U000e0074\U000e007a\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_OECUSSE_TL_OE = "\U0001f3f4\U000e0074\U000e006c\U000e006f\U000e0065\U000e007f"
- FLAG_FOR_YARACUY_VE_U = "\U0001f3f4\U000e0076\U000e0065\U000e0075\U000e007f"
- FLAG_FOR_BINH_PHUOC_VN_58 = "\U0001f3f4\U000e0076\U000e006e\U000e0035\U000e0038\U000e007f"
- FLAG_FOR_NINH_THUAN_VN_36 = "\U0001f3f4\U000e0076\U000e006e\U000e0033\U000e0036\U000e007f"
- FLAG_FOR_OSHIKOTO_NA_OT = "\U0001f3f4\U000e006e\U000e0061\U000e006f\U000e0074\U000e007f"
- FLAG_FOR_CARGADOS_CARAJOS_MU_CC = "\U0001f3f4\U000e006d\U000e0075\U000e0063\U000e0063\U000e007f"
- FLAG_FOR_PHU_YEN_VN_32 = "\U0001f3f4\U000e0076\U000e006e\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_NAM_INH_VN_67 = "\U0001f3f4\U000e0076\U000e006e\U000e0036\U000e0037\U000e007f"
- FLAG_FOR_BAC_GIANG_VN_54 = "\U0001f3f4\U000e0076\U000e006e\U000e0035\U000e0034\U000e007f"
- FLAG_FOR_TIEN_GIANG_VN_46 = "\U0001f3f4\U000e0076\U000e006e\U000e0034\U000e0036\U000e007f"
- FLAG_FOR_NORTHERN_MW_N = "\U0001f3f4\U000e006d\U000e0077\U000e006e\U000e007f"
- FLAG_FOR_CAN_THO_VN_CT = "\U0001f3f4\U000e0076\U000e006e\U000e0063\U000e0074\U000e007f"
- FLAG_FOR_BINH_THUAN_VN_40 = "\U0001f3f4\U000e0076\U000e006e\U000e0034\U000e0030\U000e007f"
- FLAG_FOR_AK_LAK_VN_33 = "\U0001f3f4\U000e0076\U000e006e\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_LAM_ONG_VN_35 = "\U0001f3f4\U000e0076\U000e006e\U000e0033\U000e0035\U000e007f"
- FLAG_FOR_BEN_TRE_VN_50 = "\U0001f3f4\U000e0076\U000e006e\U000e0035\U000e0030\U000e007f"
- FLAG_FOR_TAY_NINH_VN_37 = "\U0001f3f4\U000e0076\U000e006e\U000e0033\U000e0037\U000e007f"
- FLAG_FOR_BINH_INH_VN_31 = "\U0001f3f4\U000e0076\U000e006e\U000e0033\U000e0031\U000e007f"
- FLAG_FOR_BAC_LIEU_VN_55 = "\U0001f3f4\U000e0076\U000e006e\U000e0035\U000e0035\U000e007f"
- FLAG_FOR_ONG_THAP_VN_45 = "\U0001f3f4\U000e0076\U000e006e\U000e0034\U000e0035\U000e007f"
- FLAG_FOR_KIEN_GIANG_VN_47 = "\U0001f3f4\U000e0076\U000e006e\U000e0034\U000e0037\U000e007f"
- FLAG_FOR_ONG_NAI_VN_39 = "\U0001f3f4\U000e0076\U000e006e\U000e0033\U000e0039\U000e007f"
- FLAG_FOR_BA_RIA_VUNG_TAU_VN_43 = "\U0001f3f4\U000e0076\U000e006e\U000e0034\U000e0033\U000e007f"
- FLAG_FOR_UTAH_US_UT = "\U0001f3f4\U000e0075\U000e0073\U000e0075\U000e0074\U000e007f"
- FLAG_FOR_VINH_PHUC_VN_70 = "\U0001f3f4\U000e0076\U000e006e\U000e0037\U000e0030\U000e007f"
- FLAG_FOR_IEN_BIEN_VN_71 = "\U0001f3f4\U000e0076\U000e006e\U000e0037\U000e0031\U000e007f"
- FLAG_FOR_BAC_KAN_VN_53 = "\U0001f3f4\U000e0076\U000e006e\U000e0035\U000e0033\U000e007f"
- FLAG_FOR_DA_NANG_VN_DN = "\U0001f3f4\U000e0076\U000e006e\U000e0064\U000e006e\U000e007f"
- FLAG_FOR_HA_NAM_VN_63 = "\U0001f3f4\U000e0076\U000e006e\U000e0036\U000e0033\U000e007f"
- FLAG_FOR_AK_NONG_VN_72 = "\U0001f3f4\U000e0076\U000e006e\U000e0037\U000e0032\U000e007f"
- FLAG_FOR_SOC_TRANG_VN_52 = "\U0001f3f4\U000e0076\U000e006e\U000e0035\U000e0032\U000e007f"
- FLAG_FOR_GIA_LAI_VN_30 = "\U0001f3f4\U000e0076\U000e006e\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_CA_MAU_VN_59 = "\U0001f3f4\U000e0076\U000e006e\U000e0035\U000e0039\U000e007f"
- FLAG_FOR_BOLIVAR_VE_F = "\U0001f3f4\U000e0076\U000e0065\U000e0066\U000e007f"
- FLAG_FOR_KHANH_HOA_VN_34 = "\U0001f3f4\U000e0076\U000e006e\U000e0033\U000e0034\U000e007f"
- FLAG_FOR_LONG_AN_VN_41 = "\U0001f3f4\U000e0076\U000e006e\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_SHEFA_VU_SEE = "\U0001f3f4\U000e0076\U000e0075\U000e0073\U000e0065\U000e0065\U000e007f"
- FLAG_FOR_AMRAN_YE_AM = "\U0001f3f4\U000e0079\U000e0065\U000e0061\U000e006d\U000e007f"
- FLAG_FOR_RAYMAH_YE_RA = "\U0001f3f4\U000e0079\U000e0065\U000e0072\U000e0061\U000e007f"
- FLAG_FOR_MAE_HONG_SON_TH_58 = "\U0001f3f4\U000e0074\U000e0068\U000e0035\U000e0038\U000e007f"
- FLAG_FOR_AL_MAHRAH_YE_MR = "\U0001f3f4\U000e0079\U000e0065\U000e006d\U000e0072\U000e007f"
- FLAG_FOR_AL_MAHWIT_YE_MW = "\U0001f3f4\U000e0079\U000e0065\U000e006d\U000e0077\U000e007f"
- FLAG_FOR_SATUPA_ITEA_WS_SA = "\U0001f3f4\U000e0077\U000e0073\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_GAGA_EMAUGA_WS_GE = "\U0001f3f4\U000e0077\U000e0073\U000e0067\U000e0065\U000e007f"
- FLAG_FOR_HAIPHONG_VN_HP = "\U0001f3f4\U000e0076\U000e006e\U000e0068\U000e0070\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_DHALE_YE_DA = "\U0001f3f4\U000e0079\U000e0065\U000e0064\U000e0061\U000e007f"
- FLAG_FOR_DHAMAR_YE_DH = "\U0001f3f4\U000e0079\U000e0065\U000e0064\U000e0068\U000e007f"
- FLAG_FOR_TUAMASAGA_WS_TU = "\U0001f3f4\U000e0077\U000e0073\U000e0074\U000e0075\U000e007f"
- FLAG_FOR_AL_BAYDA_YE_BA = "\U0001f3f4\U000e0079\U000e0065\U000e0062\U000e0061\U000e007f"
- FLAG_FOR_HAJJAH_YE_HJ = "\U0001f3f4\U000e0079\U000e0065\U000e0068\U000e006a\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_SHABWAH_YE_SH = "\U0001f3f4\U000e0079\U000e0065\U000e0073\U000e0068\U000e007f"
- FAMILY_WOMAN_MAN_GIRL_BOY = "\U0001f469\u200d\U0001f468\u200d\U0001f467\u200d\U0001f466"
- FLAG_FOR_ATUA_WS_AT = "\U0001f3f4\U000e0077\U000e0073\U000e0061\U000e0074\U000e007f"
- FLAG_FOR_UVEA_WF_UV = "\U0001f3f4\U000e0077\U000e0066\U000e0075\U000e0076\U000e007f"
- FLAG_FOR_PENAMA_VU_PAM = "\U0001f3f4\U000e0076\U000e0075\U000e0070\U000e0061\U000e006d\U000e007f"
- FLAG_FOR_CRNA_NA_KOROSKEM_SI_016 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_ADAN_YE_AD = "\U0001f3f4\U000e0079\U000e0065\U000e0061\U000e0064\U000e007f"
- FLAG_FOR_ABYAN_YE_AB = "\U0001f3f4\U000e0079\U000e0065\U000e0061\U000e0062\U000e007f"
- FLAG_FOR_PALAULI_WS_PA = "\U0001f3f4\U000e0077\U000e0073\U000e0070\U000e0061\U000e007f"
- FLAG_FOR_CENTAR_ZUPA_MK_78 = "\U0001f3f4\U000e006d\U000e006b\U000e0037\U000e0038\U000e007f"
- FLAG_FOR_VA_A_O_FONOTI_WS_VF = "\U0001f3f4\U000e0077\U000e0073\U000e0076\U000e0066\U000e007f"
- FLAG_FOR_BULAWAYO_ZW_BU = "\U0001f3f4\U000e007a\U000e0077\U000e0062\U000e0075\U000e007f"
- FLAG_FOR_HARARE_ZW_HA = "\U0001f3f4\U000e007a\U000e0077\U000e0068\U000e0061\U000e007f"
- FLAG_FOR_GAUTENG_ZA_GT = "\U0001f3f4\U000e007a\U000e0061\U000e0067\U000e0074\U000e007f"
- FLAG_FOR_TAIZ_YE_TA = "\U0001f3f4\U000e0079\U000e0065\U000e0074\U000e0061\U000e007f"
- FLAG_FOR_NEAMT_RO_NT = "\U0001f3f4\U000e0072\U000e006f\U000e006e\U000e0074\U000e007f"
- FLAG_FOR_NORTHERN_ZM_05 = "\U0001f3f4\U000e007a\U000e006d\U000e0030\U000e0035\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_MUCHINGA_ZM_10 = "\U0001f3f4\U000e007a\U000e006d\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_COPPERBELT_ZM_08 = "\U0001f3f4\U000e007a\U000e006d\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_NORTH_WESTERN_ZM_06 = "\U0001f3f4\U000e007a\U000e006d\U000e0030\U000e0036\U000e007f"
- KISS_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc"
- FLAG_FOR_LUAPULA_ZM_04 = "\U0001f3f4\U000e007a\U000e006d\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_LIMPOPO_ZA_LP = "\U0001f3f4\U000e007a\U000e0061\U000e006c\U000e0070\U000e007f"
- FLAG_FOR_KOCAELI_TR_41 = "\U0001f3f4\U000e0074\U000e0072\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_LUSAKA_ZM_09 = "\U0001f3f4\U000e007a\U000e006d\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_WESTERN_ZM_01 = "\U0001f3f4\U000e007a\U000e006d\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_REPUBLIKA_SRPSKA_BA_SRP = "\U0001f3f4\U000e0062\U000e0061\U000e0073\U000e0072\U000e0070\U000e007f"
- FLAG_FOR_NORTHERN_CAPE_ZA_NC = "\U0001f3f4\U000e007a\U000e0061\U000e006e\U000e0063\U000e007f"
- FLAG_FOR_SOUTHLAND_NZ_STL = "\U0001f3f4\U000e006e\U000e007a\U000e0073\U000e0074\U000e006c\U000e007f"
- FLAG_FOR_MPUMALANGA_ZA_MP = "\U0001f3f4\U000e007a\U000e0061\U000e006d\U000e0070\U000e007f"
- FLAG_FOR_EASTERN_ZM_03 = "\U0001f3f4\U000e007a\U000e006d\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_MATABELELAND_NORTH_ZW_MN = "\U0001f3f4\U000e007a\U000e0077\U000e006d\U000e006e\U000e007f"
- FLAG_FOR_MASHONALAND_EAST_ZW_ME = "\U0001f3f4\U000e007a\U000e0077\U000e006d\U000e0065\U000e007f"
- FLAG_FOR_CENTRAL_ZM_02 = "\U0001f3f4\U000e007a\U000e006d\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_MASHONALAND_WEST_ZW_MW = "\U0001f3f4\U000e007a\U000e0077\U000e006d\U000e0077\U000e007f"
- FLAG_FOR_SOUTHERN_ZM_07 = "\U0001f3f4\U000e007a\U000e006d\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_MASVINGO_ZW_MV = "\U0001f3f4\U000e007a\U000e0077\U000e006d\U000e0076\U000e007f"
- FLAG_FOR_MATABELELAND_SOUTH_ZW_MS = "\U0001f3f4\U000e007a\U000e0077\U000e006d\U000e0073\U000e007f"
- FLAG_FOR_EASTERN_CAPE_ZA_EC = "\U0001f3f4\U000e007a\U000e0061\U000e0065\U000e0063\U000e007f"
- FLAG_FOR_NEW_VALLEY_EG_WAD = "\U0001f3f4\U000e0065\U000e0067\U000e0077\U000e0061\U000e0064\U000e007f"
- FLAG_FOR_BOLIVAR_EC_B = "\U0001f3f4\U000e0065\U000e0063\U000e0062\U000e007f"
- FLAG_FOR_CHANTHABURI_TH_22 = "\U0001f3f4\U000e0074\U000e0068\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_ARTA_DJ_AR = "\U0001f3f4\U000e0064\U000e006a\U000e0061\U000e0072\U000e007f"
- TAG_COLON = "\U000e003a"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FAMILY_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_NIUTAO_TV_NIT = "\U0001f3f4\U000e0074\U000e0076\U000e006e\U000e0069\U000e0074\U000e007f"
- TAG_HYPHEN_MINUS = "\U000e002d"
- FLAG_FOR_PRIMORSKY_KRAI_RU_PRI = "\U0001f3f4\U000e0072\U000e0075\U000e0070\U000e0072\U000e0069\U000e007f"
- FLAG_FOR_MANICALAND_ZW_MA = "\U0001f3f4\U000e007a\U000e0077\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_CHUY_KG_C = "\U0001f3f4\U000e006b\U000e0067\U000e0063\U000e007f"
- FLAG_FOR_MAINE_US_ME = "\U0001f3f4\U000e0075\U000e0073\U000e006d\U000e0065\U000e007f"
- FLAG_FOR_LOWER_JUBA_SO_JH = "\U0001f3f4\U000e0073\U000e006f\U000e006a\U000e0068\U000e007f"
- FLAG_FOR_FUKUSHIMA_JP_07 = "\U0001f3f4\U000e006a\U000e0070\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_PUDUCHERRY_IN_PY = "\U0001f3f4\U000e0069\U000e006e\U000e0070\U000e0079\U000e007f"
- FLAG_FOR_KRABI_TH_81 = "\U0001f3f4\U000e0074\U000e0068\U000e0038\U000e0031\U000e007f"
- FLAG_FOR_UTRECHT_NL_UT = "\U0001f3f4\U000e006e\U000e006c\U000e0075\U000e0074\U000e007f"
- FLAG_FOR_MANITOBA_CA_MB = "\U0001f3f4\U000e0063\U000e0061\U000e006d\U000e0062\U000e007f"
- FLAG_FOR_GAGA_IFOMAUGA_WS_GI = "\U0001f3f4\U000e0077\U000e0073\U000e0067\U000e0069\U000e007f"
- FLAG_FOR_NORTH_KHORASAN_IR_31 = "\U0001f3f4\U000e0069\U000e0072\U000e0033\U000e0031\U000e007f"
- KISS_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe"
- FLAG_FOR_IOWA_US_IA = "\U0001f3f4\U000e0075\U000e0073\U000e0069\U000e0061\U000e007f"
- FLAG_FOR_LARNACA_CY_03 = "\U0001f3f4\U000e0063\U000e0079\U000e0030\U000e0033\U000e007f"
- RESTRICTED_LEFT_ENTRY_2 = "\u26e1"
- FLAG_FOR_NORMANDIE_FR_NOR = "\U0001f3f4\U000e0066\U000e0072\U000e006e\U000e006f\U000e0072\U000e007f"
- FLAG_FOR_HAWAII_US_HI = "\U0001f3f4\U000e0075\U000e0073\U000e0068\U000e0069\U000e007f"
- FLAG_FOR_ZAMBEZIA_MZ_Q = "\U0001f3f4\U000e006d\U000e007a\U000e0071\U000e007f"
- FLAG_FOR_MURMANSK_RU_MUR = "\U0001f3f4\U000e0072\U000e0075\U000e006d\U000e0075\U000e0072\U000e007f"
- FLAG_FOR_CANARIES_LC_12 = "\U0001f3f4\U000e006c\U000e0063\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_NEW_HAMPSHIRE_US_NH = "\U0001f3f4\U000e0075\U000e0073\U000e006e\U000e0068\U000e007f"
- FLAG_FOR_DJIBOUTI_DJ_DJ = "\U0001f3f4\U000e0064\U000e006a\U000e0064\U000e006a\U000e007f"
- FLAG_FOR_JIZAN_SA_09 = "\U0001f3f4\U000e0073\U000e0061\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_MARSA_MT_26 = "\U0001f3f4\U000e006d\U000e0074\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_MUGLA_TR_48 = "\U0001f3f4\U000e0074\U000e0072\U000e0034\U000e0038\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_G = "\U000e0047"
- FLAG_FOR_LAANE_VIRU_EE_59 = "\U0001f3f4\U000e0065\U000e0065\U000e0035\U000e0039\U000e007f"
- FLAG_FOR_SAN_JOSE_UY_SJ = "\U0001f3f4\U000e0075\U000e0079\U000e0073\U000e006a\U000e007f"
- FLAG_FOR_NORTH_GAZA_PS_NGZ = "\U0001f3f4\U000e0070\U000e0073\U000e006e\U000e0067\U000e007a\U000e007f"
- FLAG_FOR_MANUS_PG_MRL = "\U0001f3f4\U000e0070\U000e0067\U000e006d\U000e0072\U000e006c\U000e007f"
- FLAG_FOR_SIVAS_TR_58 = "\U0001f3f4\U000e0074\U000e0072\U000e0035\U000e0038\U000e007f"
- WOMAN_IN_TUXEDO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f935\U0001f3fc\u200d\u2640\ufe0f"
- KISS_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468"
- FLAG_FOR_LESSER_POLAND_PL_MA = "\U0001f3f4\U000e0070\U000e006c\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_WEST_MACEDONIA_GR_C = "\U0001f3f4\U000e0067\U000e0072\U000e0063\U000e007f"
- FLAG_FOR_DEMIR_HISAR_MK_25 = "\U0001f3f4\U000e006d\U000e006b\U000e0032\U000e0035\U000e007f"
- FLAG_FOR_ARKHABIL_SUQUTRA_YE_SU = "\U0001f3f4\U000e0079\U000e0065\U000e0073\U000e0075\U000e007f"
- FLAG_FOR_COMMEWIJNE_SR_CM = "\U0001f3f4\U000e0073\U000e0072\U000e0063\U000e006d\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f467\U0001f3ff"
- COUPLE_WITH_HEART_WOMAN_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb"
- FLAG_FOR_PRYKARPATTIA_UA_26 = "\U0001f3f4\U000e0075\U000e0061\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_NUEVA_ESPARTA_VE_O = "\U0001f3f4\U000e0076\U000e0065\U000e006f\U000e007f"
- FLAG_FOR_HARJU_EE_37 = "\U0001f3f4\U000e0065\U000e0065\U000e0033\U000e0037\U000e007f"
- FLAG_FOR_GUJARAT_IN_GJ = "\U0001f3f4\U000e0069\U000e006e\U000e0067\U000e006a\U000e007f"
- FLAG_FOR_JEKABPILS_MUNICIPALITY_LV_042 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0034\U000e0032\U000e007f"
- FLAG_FOR_NAVASSA_ISLAND_UM_76 = "\U0001f3f4\U000e0075\U000e006d\U000e0037\U000e0036\U000e007f"
- KISS_MAN_DARK_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_OGRE_LV_067 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0036\U000e0037\U000e007f"
- FLAG_FOR_YAREN_NR_14 = "\U0001f3f4\U000e006e\U000e0072\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_SCHELLENBERG_LI_08 = "\U0001f3f4\U000e006c\U000e0069\U000e0030\U000e0038\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FLAG_FOR_TELANGANA_IN_TG = "\U0001f3f4\U000e0069\U000e006e\U000e0074\U000e0067\U000e007f"
- FLAG_FOR_OROMIA_ET_OR = "\U0001f3f4\U000e0065\U000e0074\U000e006f\U000e0072\U000e007f"
- FLAG_FOR_UUSIMAA_FI_18 = "\U0001f3f4\U000e0066\U000e0069\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_SASSANDRA_MARAHOUE_CI_SM = "\U0001f3f4\U000e0063\U000e0069\U000e0073\U000e006d\U000e007f"
- FLAG_FOR_HA_APAI_TO_02 = "\U0001f3f4\U000e0074\U000e006f\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_GUAYAS_EC_G = "\U0001f3f4\U000e0065\U000e0063\U000e0067\U000e007f"
- FLAG_FOR_DUZCE_TR_81 = "\U0001f3f4\U000e0074\U000e0072\U000e0038\U000e0031\U000e007f"
- FLAG_FOR_APURIMAC_PE_APU = "\U0001f3f4\U000e0070\U000e0065\U000e0061\U000e0070\U000e0075\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FAMILY_WOMAN_MAN_BABY_BOY = "\U0001f469\u200d\U0001f468\u200d\U0001f476\u200d\U0001f466"
- FLAG_FOR_SOUTHERN_NATIONS_NATIONALITIES_AND_PEOPLES_ET_SN = "\U0001f3f4\U000e0065\U000e0074\U000e0073\U000e006e\U000e007f"
- FLAG_FOR_CHOCO_CO_CHO = "\U0001f3f4\U000e0063\U000e006f\U000e0063\U000e0068\U000e006f\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FLAG_FOR_SAINT_PATRICK_VC_05 = "\U0001f3f4\U000e0076\U000e0063\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_HAWALLI_KW_HA = "\U0001f3f4\U000e006b\U000e0077\U000e0068\U000e0061\U000e007f"
- FLAG_FOR_ADRAR_MR_07 = "\U0001f3f4\U000e006d\U000e0072\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_BOUENZA_CG_11 = "\U0001f3f4\U000e0063\U000e0067\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_WYOMING_US_WY = "\U0001f3f4\U000e0075\U000e0073\U000e0077\U000e0079\U000e007f"
- FLAG_FOR_BAY_ISLANDS_HN_IB = "\U0001f3f4\U000e0068\U000e006e\U000e0069\U000e0062\U000e007f"
- FLAG_FOR_HSINCHU_TW_HSZ = "\U0001f3f4\U000e0074\U000e0077\U000e0068\U000e0073\U000e007a\U000e007f"
- TAG_FULL_STOP = "\U000e002e"
- FLAG_FOR_VAKAGA_CF_VK = "\U0001f3f4\U000e0063\U000e0066\U000e0076\U000e006b\U000e007f"
- FLAG_FOR_ALBERTA_CA_AB = "\U0001f3f4\U000e0063\U000e0061\U000e0061\U000e0062\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_PORTUGUESA_VE_P = "\U0001f3f4\U000e0076\U000e0065\U000e0070\U000e007f"
- FLAG_FOR_ILE_DE_FRANCE_FR_IDF = "\U0001f3f4\U000e0066\U000e0072\U000e0069\U000e0064\U000e0066\U000e007f"
- FLAG_FOR_MISSISSIPPI_US_MS = "\U0001f3f4\U000e0075\U000e0073\U000e006d\U000e0073\U000e007f"
- FLAG_FOR_SKOFJA_LOKA_SI_122 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_VAINODE_LV_100 = "\U0001f3f4\U000e006c\U000e0076\U000e0031\U000e0030\U000e0030\U000e007f"
- FLAG_FOR_AUSTRALIAN_CAPITAL_TERRITORY_AU_ACT = "\U0001f3f4\U000e0061\U000e0075\U000e0061\U000e0063\U000e0074\U000e007f"
- FLAG_FOR_GUARICO_VE_J = "\U0001f3f4\U000e0076\U000e0065\U000e006a\U000e007f"
- FLAG_FOR_SAINT_CATHERINE_JM_14 = "\U0001f3f4\U000e006a\U000e006d\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_SOKOTO_NG_SO = "\U0001f3f4\U000e006e\U000e0067\U000e0073\U000e006f\U000e007f"
- FLAG_FOR_AREQUIPA_PE_ARE = "\U0001f3f4\U000e0070\U000e0065\U000e0061\U000e0072\U000e0065\U000e007f"
- FLAG_FOR_SONORA_MX_SON = "\U0001f3f4\U000e006d\U000e0078\U000e0073\U000e006f\U000e006e\U000e007f"
- FLAG_FOR_CHANGHUA_TW_CHA = "\U0001f3f4\U000e0074\U000e0077\U000e0063\U000e0068\U000e0061\U000e007f"
- FLAG_FOR_LERIBE_LS_C = "\U0001f3f4\U000e006c\U000e0073\U000e0063\U000e007f"
- FLAG_FOR_SAINTE_DEVOTE_CHAPEL_MC_SD = "\U0001f3f4\U000e006d\U000e0063\U000e0073\U000e0064\U000e007f"
- FLAG_FOR_ISSYK_KUL_KG_Y = "\U0001f3f4\U000e006b\U000e0067\U000e0079\U000e007f"
- FLAG_FOR_CHANDIGARH_IN_CH = "\U0001f3f4\U000e0069\U000e006e\U000e0063\U000e0068\U000e007f"
- FAMILY_MAN_MAN_BOY_BABY = "\U0001f468\u200d\U0001f468\u200d\U0001f466\u200d\U0001f476"
- FLAG_FOR_ARAGON_ES_AR = "\U0001f3f4\U000e0065\U000e0073\U000e0061\U000e0072\U000e007f"
- KISS_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_PLASNICA_MK_61 = "\U0001f3f4\U000e006d\U000e006b\U000e0036\U000e0031\U000e007f"
- FLAG_FOR_ANTALYA_TR_07 = "\U0001f3f4\U000e0074\U000e0072\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_VARAZDIN_HR_05 = "\U0001f3f4\U000e0068\U000e0072\U000e0030\U000e0035\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_TAFEA_VU_TAE = "\U0001f3f4\U000e0076\U000e0075\U000e0074\U000e0061\U000e0065\U000e007f"
- FLAG_FOR_VELIKE_LASCE_SI_134 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0033\U000e0034\U000e007f"
- FLAG_FOR_QUERETARO_MX_QUE = "\U0001f3f4\U000e006d\U000e0078\U000e0071\U000e0075\U000e0065\U000e007f"
- FLAG_FOR_DEIR_AL_BALAH_PS_DEB = "\U0001f3f4\U000e0070\U000e0073\U000e0064\U000e0065\U000e0062\U000e007f"
- FLAG_FOR_MEXICO_STATE_MX_MEX = "\U0001f3f4\U000e006d\U000e0078\U000e006d\U000e0065\U000e0078\U000e007f"
- FLAG_FOR_LEON_NI_LE = "\U0001f3f4\U000e006e\U000e0069\U000e006c\U000e0065\U000e007f"
- FLAG_FOR_NORTH_PROVINCE_MV_NO = "\U0001f3f4\U000e006d\U000e0076\U000e006e\U000e006f\U000e007f"
- FLAG_FOR_ST_BARTHELEMY_FR_BL = "\U0001f3f4\U000e0066\U000e0072\U000e0062\U000e006c\U000e007f"
- FLAG_FOR_HORDALAND_NO_12 = "\U0001f3f4\U000e006e\U000e006f\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_PLZENSKY_KRAJ_CZ_32 = "\U0001f3f4\U000e0063\U000e007a\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_EGER_HU_EG = "\U0001f3f4\U000e0068\U000e0075\U000e0065\U000e0067\U000e007f"
- FLAG_FOR_TABASCO_MX_TAB = "\U0001f3f4\U000e006d\U000e0078\U000e0074\U000e0061\U000e0062\U000e007f"
- FLAG_FOR_FLANDERS_BE_VLG = "\U0001f3f4\U000e0062\U000e0065\U000e0076\U000e006c\U000e0067\U000e007f"
- FLAG_FOR_KERMANSHAH_IR_17 = "\U0001f3f4\U000e0069\U000e0072\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_APURE_VE_C = "\U0001f3f4\U000e0076\U000e0065\U000e0063\U000e007f"
- FLAG_FOR_SILA_TD_SI = "\U0001f3f4\U000e0074\U000e0064\U000e0073\U000e0069\U000e007f"
- FLAG_FOR_DURANGO_MX_DUR = "\U0001f3f4\U000e006d\U000e0078\U000e0064\U000e0075\U000e0072\U000e007f"
- FLAG_FOR_MARAMURES_RO_MM = "\U0001f3f4\U000e0072\U000e006f\U000e006d\U000e006d\U000e007f"
- FLAG_FOR_VELENJE_SI_133 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_SAINT_JOHN_DM_05 = "\U0001f3f4\U000e0064\U000e006d\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_NORTH_GYEONGSANG_KR_47 = "\U0001f3f4\U000e006b\U000e0072\U000e0034\U000e0037\U000e007f"
- FLAG_FOR_MOROGORO_TZ_16 = "\U0001f3f4\U000e0074\U000e007a\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_NORTH_HOLLAND_NL_NH = "\U0001f3f4\U000e006e\U000e006c\U000e006e\U000e0068\U000e007f"
- FLAG_FOR_MERIDA_VE_L = "\U0001f3f4\U000e0076\U000e0065\U000e006c\U000e007f"
- FLAG_FOR_AUCKLAND_NZ_AUK = "\U0001f3f4\U000e006e\U000e007a\U000e0061\U000e0075\U000e006b\U000e007f"
- FLAG_FOR_RIO_GRANDE_DO_SUL_BR_RS = "\U0001f3f4\U000e0062\U000e0072\U000e0072\U000e0073\U000e007f"
- FLAG_FOR_RYAZAN_RU_RYA = "\U0001f3f4\U000e0072\U000e0075\U000e0072\U000e0079\U000e0061\U000e007f"
- FLAG_FOR_DAR_ES_SALAAM_TZ_02 = "\U0001f3f4\U000e0074\U000e007a\U000e0030\U000e0032\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FLAG_FOR_GAFSA_TN_71 = "\U0001f3f4\U000e0074\U000e006e\U000e0037\U000e0031\U000e007f"
- FLAG_FOR_MASHONALAND_CENTRAL_ZW_MC = "\U0001f3f4\U000e007a\U000e0077\U000e006d\U000e0063\U000e007f"
- FLAG_FOR_BOVEC_SI_006 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_ANKARAN_SI_213 = "\U0001f3f4\U000e0073\U000e0069\U000e0032\U000e0031\U000e0033\U000e007f"
- KISS_MAN_MEDIUM_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb"
- TAG_LATIN_CAPITAL_LETTER_O = "\U000e004f"
- FLAG_FOR_GUERRERO_MX_GRO = "\U0001f3f4\U000e006d\U000e0078\U000e0067\U000e0072\U000e006f\U000e007f"
- FLAG_FOR_DOBJE_SI_154 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0035\U000e0034\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FLAG_FOR_RETALHULEU_GT_RE = "\U0001f3f4\U000e0067\U000e0074\U000e0072\U000e0065\U000e007f"
- FLAG_FOR_NARINO_CO_NAR = "\U0001f3f4\U000e0063\U000e006f\U000e006e\U000e0061\U000e0072\U000e007f"
- FLAG_FOR_TUNIS_TN_11 = "\U0001f3f4\U000e0074\U000e006e\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_TIBET_CN_54 = "\U0001f3f4\U000e0063\U000e006e\U000e0035\U000e0034\U000e007f"
- FLAG_FOR_MALAMPA_VU_MAP = "\U0001f3f4\U000e0076\U000e0075\U000e006d\U000e0061\U000e0070\U000e007f"
- FLAG_FOR_PIEDMONT_IT_21 = "\U0001f3f4\U000e0069\U000e0074\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_KAYSERI_TR_38 = "\U0001f3f4\U000e0074\U000e0072\U000e0033\U000e0038\U000e007f"
- FLAG_FOR_EQUATEUR_CD_EQ = "\U0001f3f4\U000e0063\U000e0064\U000e0065\U000e0071\U000e007f"
- FLAG_FOR_SABAH_MY_12 = "\U0001f3f4\U000e006d\U000e0079\U000e0031\U000e0032\U000e007f"
- COUPLE_WITH_HEART_WOMAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb"
- FLAG_FOR_NYANGA_GA_5 = "\U0001f3f4\U000e0067\U000e0061\U000e0035\U000e007f"
- FLAG_FOR_TAVASTIA_PROPER_FI_06 = "\U0001f3f4\U000e0066\U000e0069\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_CARAS_SEVERIN_RO_CS = "\U0001f3f4\U000e0072\U000e006f\U000e0063\U000e0073\U000e007f"
- FLAG_FOR_CENTRAL_VISAYAS_PH_07 = "\U0001f3f4\U000e0070\U000e0068\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_MASERU_LS_A = "\U0001f3f4\U000e006c\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_SAINT_ANDREW_GD_01 = "\U0001f3f4\U000e0067\U000e0064\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_LAI_CHAU_VN_01 = "\U0001f3f4\U000e0076\U000e006e\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_CHAIYAPHUM_TH_36 = "\U0001f3f4\U000e0074\U000e0068\U000e0033\U000e0036\U000e007f"
- FLAG_FOR_ESMERALDAS_EC_E = "\U0001f3f4\U000e0065\U000e0063\U000e0065\U000e007f"
- FLAG_FOR_DILI_TL_DI = "\U0001f3f4\U000e0074\U000e006c\U000e0064\U000e0069\U000e007f"
- FLAG_FOR_USULUTAN_SV_US = "\U0001f3f4\U000e0073\U000e0076\U000e0075\U000e0073\U000e007f"
- FLAG_FOR_MARSABIT_KE_25 = "\U0001f3f4\U000e006b\U000e0065\U000e0032\U000e0035\U000e007f"
- FLAG_FOR_FALCON_VE_I = "\U0001f3f4\U000e0076\U000e0065\U000e0069\U000e007f"
- FLAG_FOR_ZANZAN_CI_ZZ = "\U0001f3f4\U000e0063\U000e0069\U000e007a\U000e007a\U000e007f"
- FLAG_FOR_NORD_UBANGI_CD_NU = "\U0001f3f4\U000e0063\U000e0064\U000e006e\U000e0075\U000e007f"
- FLAG_FOR_PAILIN_KH_24 = "\U0001f3f4\U000e006b\U000e0068\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_CASTILE_AND_LEON_ES_CL = "\U0001f3f4\U000e0065\U000e0073\U000e0063\U000e006c\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_SAMUT_SONGKHRAM_TH_75 = "\U0001f3f4\U000e0074\U000e0068\U000e0037\U000e0035\U000e007f"
- FLAG_FOR_ADRAR_DZ_01 = "\U0001f3f4\U000e0064\U000e007a\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_EAST_SEPIK_PG_ESW = "\U0001f3f4\U000e0070\U000e0067\U000e0065\U000e0073\U000e0077\U000e007f"
- FLAG_FOR_EMILIA_ROMAGNA_IT_45 = "\U0001f3f4\U000e0069\U000e0074\U000e0034\U000e0035\U000e007f"
- FLAG_FOR_CHUMPHON_TH_86 = "\U0001f3f4\U000e0074\U000e0068\U000e0038\U000e0036\U000e007f"
- FLAG_FOR_MAZSALACA_LV_060 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0036\U000e0030\U000e007f"
- FLAG_FOR_BARI_SO_BR = "\U0001f3f4\U000e0073\U000e006f\U000e0062\U000e0072\U000e007f"
- FLAG_FOR_ALAND_ISLANDS_FI_01 = "\U0001f3f4\U000e0066\U000e0069\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_QUANG_NAM_VN_27 = "\U0001f3f4\U000e0076\U000e006e\U000e0032\U000e0037\U000e007f"
- FLAG_FOR_LINE_ISLANDS_KI_L = "\U0001f3f4\U000e006b\U000e0069\U000e006c\U000e007f"
- FLAG_FOR_KAGOSHIMA_JP_46 = "\U0001f3f4\U000e006a\U000e0070\U000e0034\U000e0036\U000e007f"
- FLAG_FOR_CAIRO_EG_C = "\U0001f3f4\U000e0065\U000e0067\U000e0063\U000e007f"
- FLAG_FOR_KUTAHYA_TR_43 = "\U0001f3f4\U000e0074\U000e0072\U000e0034\U000e0033\U000e007f"
- FAMILY_MAN_WOMAN_BOY_BABY = "\U0001f468\u200d\U0001f469\u200d\U0001f466\u200d\U0001f476"
- FLAG_FOR_AL_BAHAH_SA_11 = "\U0001f3f4\U000e0073\U000e0061\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_GREATER_POLAND_PL_WP = "\U0001f3f4\U000e0070\U000e006c\U000e0077\U000e0070\U000e007f"
- FLAG_FOR_WEST_AZARBAIJAN_IR_02 = "\U0001f3f4\U000e0069\U000e0072\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_YAMALO_NENETS_OKRUG_RU_YAN = "\U0001f3f4\U000e0072\U000e0075\U000e0079\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_MONTANA_US_MT = "\U0001f3f4\U000e0075\U000e0073\U000e006d\U000e0074\U000e007f"
- KISS_WOMAN_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_POMEROON_SUPENAAM_GY_PM = "\U0001f3f4\U000e0067\U000e0079\U000e0070\U000e006d\U000e007f"
- FLAG_FOR_GWANGJU_CITY_KR_29 = "\U0001f3f4\U000e006b\U000e0072\U000e0032\U000e0039\U000e007f"
- FLAG_FOR_DONECHCHYNA_UA_14 = "\U0001f3f4\U000e0075\U000e0061\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_SAFI_MT_47 = "\U0001f3f4\U000e006d\U000e0074\U000e0034\U000e0037\U000e007f"
- COUPLE_WITH_HEART_MAN_WOMAN_LIGHT_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb"
- KISS_MAN_DARK_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc"
- FLAG_FOR_ANTIOQUIA_CO_ANT = "\U0001f3f4\U000e0063\U000e006f\U000e0061\U000e006e\U000e0074\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_KRANJ_SI_052 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0035\U000e0032\U000e007f"
- FLAG_FOR_MIYAGI_JP_04 = "\U0001f3f4\U000e006a\U000e0070\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_MARGIBI_LR_MG = "\U0001f3f4\U000e006c\U000e0072\U000e006d\U000e0067\U000e007f"
- FLAG_FOR_ZULIA_VE_V = "\U0001f3f4\U000e0076\U000e0065\U000e0076\U000e007f"
- FLAG_FOR_VAISIGANO_WS_VS = "\U0001f3f4\U000e0077\U000e0073\U000e0076\U000e0073\U000e007f"
- FLAG_FOR_GLARUS_CH_GL = "\U0001f3f4\U000e0063\U000e0068\U000e0067\U000e006c\U000e007f"
- FLAG_FOR_BECHAR_DZ_08 = "\U0001f3f4\U000e0064\U000e007a\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_EMBERA_PA_EM = "\U0001f3f4\U000e0070\U000e0061\U000e0065\U000e006d\U000e007f"
- FLAG_FOR_LUQA_MT_25 = "\U0001f3f4\U000e006d\U000e0074\U000e0032\U000e0035\U000e007f"
- FLAG_FOR_IBB_YE_IB = "\U0001f3f4\U000e0079\U000e0065\U000e0069\U000e0062\U000e007f"
- FLAG_FOR_EAST_BERBICE_CORENTYNE_GY_EB = "\U0001f3f4\U000e0067\U000e0079\U000e0065\U000e0062\U000e007f"
- FLAG_FOR_U_S_VIRGIN_ISLANDS_US_VI = "\U0001f3f4\U000e0075\U000e0073\U000e0076\U000e0069\U000e007f"
- FLAG_FOR_PHATTHALUNG_TH_93 = "\U0001f3f4\U000e0074\U000e0068\U000e0039\U000e0033\U000e007f"
- FLAG_FOR_YUCATAN_MX_YUC = "\U0001f3f4\U000e006d\U000e0078\U000e0079\U000e0075\U000e0063\U000e007f"
- FLAG_FOR_KALMYKIA_RU_KL = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e006c\U000e007f"
- FLAG_FOR_ANDALUSIA_ES_AN = "\U0001f3f4\U000e0065\U000e0073\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_CAPELLEN_LU_CA = "\U0001f3f4\U000e006c\U000e0075\U000e0063\U000e0061\U000e007f"
- COUPLE_WITH_HEART_WOMAN_LIGHT_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_POOL_CG_12 = "\U0001f3f4\U000e0063\U000e0067\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_CAUSENI_MD_CS = "\U0001f3f4\U000e006d\U000e0064\U000e0063\U000e0073\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_SZABOLCS_SZATMAR_BEREG_HU_SZ = "\U0001f3f4\U000e0068\U000e0075\U000e0073\U000e007a\U000e007f"
- FLAG_FOR_ZANZIBAR_NORTH_TZ_07 = "\U0001f3f4\U000e0074\U000e007a\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_AL_JAWF_YE_JA = "\U0001f3f4\U000e0079\U000e0065\U000e006a\U000e0061\U000e007f"
- FLAG_FOR_KOKNESE_LV_046 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0034\U000e0036\U000e007f"
- FLAG_FOR_DELTA_NG_DE = "\U0001f3f4\U000e006e\U000e0067\U000e0064\U000e0065\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f476\U0001f3ff"
- SALTIRE = "\u2613"
- FLAG_FOR_NORTH_SINAI_EG_SIN = "\U0001f3f4\U000e0065\U000e0067\U000e0073\U000e0069\U000e006e\U000e007f"
- KISS_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd"
- FAMILY_MAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_GORENJA_VAS_POLJANE_SI_027 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0032\U000e0037\U000e007f"
- WHITE_FLAG_WITH_HORIZONTAL_MIDDLE_BLACK_STRIPE = "\u26ff"
- FLAG_FOR_XEWKIJA_MT_62 = "\U0001f3f4\U000e006d\U000e0074\U000e0036\U000e0032\U000e007f"
- FLAG_FOR_BAC_NINH_VN_56 = "\U0001f3f4\U000e0076\U000e006e\U000e0035\U000e0036\U000e007f"
- FLAG_FOR_HADJER_LAMIS_TD_HL = "\U0001f3f4\U000e0074\U000e0064\U000e0068\U000e006c\U000e007f"
- FLAG_FOR_SAINT_MICHAEL_BB_08 = "\U0001f3f4\U000e0062\U000e0062\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_MAPUTO_PROVINCE_MZ_L = "\U0001f3f4\U000e006d\U000e007a\U000e006c\U000e007f"
- FLAG_FOR_GUIDIMAKA_MR_10 = "\U0001f3f4\U000e006d\U000e0072\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_ARACINOVO_MK_02 = "\U0001f3f4\U000e006d\U000e006b\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_PAHANG_MY_06 = "\U0001f3f4\U000e006d\U000e0079\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_SVAY_RIENG_KH_20 = "\U0001f3f4\U000e006b\U000e0068\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_JELGAVA_MUNICIPALITY_LV_041 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_NORTHERN_OSTROBOTHNIA_FI_14 = "\U0001f3f4\U000e0066\U000e0069\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_SOUSSE_TN_51 = "\U0001f3f4\U000e0074\U000e006e\U000e0035\U000e0031\U000e007f"
- FLAG_FOR_ODRANCI_SI_086 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0038\U000e0036\U000e007f"
- FLAG_FOR_ALTO_PARANA_PY_10 = "\U0001f3f4\U000e0070\U000e0079\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_WASHINGTON_US_WA = "\U0001f3f4\U000e0075\U000e0073\U000e0077\U000e0061\U000e007f"
- FLAG_FOR_TAOYUAN_TW_TAO = "\U0001f3f4\U000e0074\U000e0077\U000e0074\U000e0061\U000e006f\U000e007f"
- FLAG_FOR_OMSK_RU_OMS = "\U0001f3f4\U000e0072\U000e0075\U000e006f\U000e006d\U000e0073\U000e007f"
- FLAG_FOR_BRATISLAVA_SK_BL = "\U0001f3f4\U000e0073\U000e006b\U000e0062\U000e006c\U000e007f"
- FLAG_FOR_GIFU_JP_21 = "\U0001f3f4\U000e006a\U000e0070\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_CHIRIQUI_PA_4 = "\U0001f3f4\U000e0070\U000e0061\U000e0034\U000e007f"
- FLAG_FOR_HESSE_DE_HE = "\U0001f3f4\U000e0064\U000e0065\U000e0068\U000e0065\U000e007f"
- FLAG_FOR_AIWO_NR_01 = "\U0001f3f4\U000e006e\U000e0072\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_MA_RIB_YE_MA = "\U0001f3f4\U000e0079\U000e0065\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_SINT_EUSTATIUS_BQ_SE = "\U0001f3f4\U000e0062\U000e0071\U000e0073\U000e0065\U000e007f"
- FLAG_FOR_ASSAM_IN_AS = "\U0001f3f4\U000e0069\U000e006e\U000e0061\U000e0073\U000e007f"
- FLAG_FOR_HUNEDOARA_RO_HD = "\U0001f3f4\U000e0072\U000e006f\U000e0068\U000e0064\U000e007f"
- FLAG_FOR_VENTSPILS_MUNICIPALITY_LV_106 = "\U0001f3f4\U000e006c\U000e0076\U000e0031\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_SAITAMA_JP_11 = "\U0001f3f4\U000e006a\U000e0070\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_CAPITAL_DISTRICT_CO_DC = "\U0001f3f4\U000e0063\U000e006f\U000e0064\U000e0063\U000e007f"
- FLAG_FOR_SOUTH_CENTRAL_PROVINCE_MV_SC = "\U0001f3f4\U000e006d\U000e0076\U000e0073\U000e0063\U000e007f"
- FLAG_FOR_CHARI_BAGUIRMI_TD_CB = "\U0001f3f4\U000e0074\U000e0064\U000e0063\U000e0062\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_ALYTUS_MUNICIPALITY_LT_02 = "\U0001f3f4\U000e006c\U000e0074\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_HANOI_VN_HN = "\U0001f3f4\U000e0076\U000e006e\U000e0068\U000e006e\U000e007f"
- FLAG_FOR_CRIMEA_UA_43 = "\U0001f3f4\U000e0075\U000e0061\U000e0034\U000e0033\U000e007f"
- FLAG_FOR_SAINT_ANDREW_JM_02 = "\U0001f3f4\U000e006a\U000e006d\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_SANMA_VU_SAM = "\U0001f3f4\U000e0076\U000e0075\U000e0073\U000e0061\U000e006d\U000e007f"
- FLAG_FOR_KHOJAVEND_AZ_XVD = "\U0001f3f4\U000e0061\U000e007a\U000e0078\U000e0076\U000e0064\U000e007f"
- FLAG_FOR_LOWER_SAXONY_DE_NI = "\U0001f3f4\U000e0064\U000e0065\U000e006e\U000e0069\U000e007f"
- FLAG_FOR_SAN_MARCOS_GT_SM = "\U0001f3f4\U000e0067\U000e0074\U000e0073\U000e006d\U000e007f"
- FLAG_FOR_HUNG_YEN_VN_66 = "\U0001f3f4\U000e0076\U000e006e\U000e0036\U000e0036\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_SINALOA_MX_SIN = "\U0001f3f4\U000e006d\U000e0078\U000e0073\U000e0069\U000e006e\U000e007f"
- FLAG_FOR_MICHIGAN_US_MI = "\U0001f3f4\U000e0075\U000e0073\U000e006d\U000e0069\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FLAG_FOR_BURYAT_RU_BU = "\U0001f3f4\U000e0072\U000e0075\U000e0062\U000e0075\U000e007f"
- FLAG_FOR_PODUNAVLJE_RS_10 = "\U0001f3f4\U000e0072\U000e0073\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_CURACAO_NL_CW = "\U0001f3f4\U000e006e\U000e006c\U000e0063\U000e0077\U000e007f"
- FLAG_FOR_GUANGDONG_CN_44 = "\U0001f3f4\U000e0063\U000e006e\U000e0034\U000e0034\U000e007f"
- FLAG_FOR_VASTRA_GOTALAND_SE_O = "\U0001f3f4\U000e0073\U000e0065\U000e006f\U000e007f"
- FLAG_FOR_XORAZM_UZ_XO = "\U0001f3f4\U000e0075\U000e007a\U000e0078\U000e006f\U000e007f"
- FLAG_FOR_CENTRALE_TG_C = "\U0001f3f4\U000e0074\U000e0067\U000e0063\U000e007f"
- FLAG_FOR_BUCHAREST_RO_B = "\U0001f3f4\U000e0072\U000e006f\U000e0062\U000e007f"
- FLAG_FOR_SREDISCE_OB_DRAVI_SI_202 = "\U0001f3f4\U000e0073\U000e0069\U000e0032\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_HODMEZOVASARHELY_HU_HV = "\U0001f3f4\U000e0068\U000e0075\U000e0068\U000e0076\U000e007f"
- FLAG_FOR_BUENOS_AIRES_AR_C = "\U0001f3f4\U000e0061\U000e0072\U000e0063\U000e007f"
- FLAG_FOR_KERALA_IN_KL = "\U0001f3f4\U000e0069\U000e006e\U000e006b\U000e006c\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FLAG_FOR_PHUKET_TH_83 = "\U0001f3f4\U000e0074\U000e0068\U000e0038\U000e0033\U000e007f"
- FLAG_FOR_SOUTH_KAZAKHSTAN_KZ_YUZ = "\U0001f3f4\U000e006b\U000e007a\U000e0079\U000e0075\U000e007a\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FAMILY_MAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f476\U0001f3fb"
- KISS_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_BETHLEHEM_PS_BTH = "\U0001f3f4\U000e0070\U000e0073\U000e0062\U000e0074\U000e0068\U000e007f"
- FLAG_FOR_OZOLNIEKI_LV_069 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0036\U000e0039\U000e007f"
- FLAG_FOR_BUZAU_RO_BZ = "\U0001f3f4\U000e0072\U000e006f\U000e0062\U000e007a\U000e007f"
- FLAG_FOR_OUAKA_CF_UK = "\U0001f3f4\U000e0063\U000e0066\U000e0075\U000e006b\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FLAG_FOR_BONG_LR_BG = "\U0001f3f4\U000e006c\U000e0072\U000e0062\U000e0067\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_LEBAP_TM_L = "\U0001f3f4\U000e0074\U000e006d\U000e006c\U000e007f"
- FLAG_FOR_VORONEZH_RU_VOR = "\U0001f3f4\U000e0072\U000e0075\U000e0076\U000e006f\U000e0072\U000e007f"
- KISS_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe"
- FLAG_FOR_SAN_JOSE_CR_SJ = "\U0001f3f4\U000e0063\U000e0072\U000e0073\U000e006a\U000e007f"
- FLAG_FOR_KISUMU_KE_17 = "\U0001f3f4\U000e006b\U000e0065\U000e0031\U000e0037\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_LAHIJ_YE_LA = "\U0001f3f4\U000e0079\U000e0065\U000e006c\U000e0061\U000e007f"
- FLAG_FOR_RACHA_LECHKHUMI_AND_KVEMO_SVANETI_GE_RL = "\U0001f3f4\U000e0067\U000e0065\U000e0072\U000e006c\U000e007f"
- FLAG_FOR_ULCINJ_ME_20 = "\U0001f3f4\U000e006d\U000e0065\U000e0032\U000e0030\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_OSH_KG_GO = "\U0001f3f4\U000e006b\U000e0067\U000e0067\U000e006f\U000e007f"
- FLAG_FOR_AMAZONAS_VE_Z = "\U0001f3f4\U000e0076\U000e0065\U000e007a\U000e007f"
- FLAG_FOR_NORTH_RHINE_WESTPHALIA_DE_NW = "\U0001f3f4\U000e0064\U000e0065\U000e006e\U000e0077\U000e007f"
- FLAG_FOR_MONAGAS_VE_N = "\U0001f3f4\U000e0076\U000e0065\U000e006e\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_CANTABRIA_ES_CB = "\U0001f3f4\U000e0065\U000e0073\U000e0063\U000e0062\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FLAG_FOR_M_SILA_DZ_28 = "\U0001f3f4\U000e0064\U000e007a\U000e0032\U000e0038\U000e007f"
- FAMILY_WOMAN_MAN_BOY = "\U0001f469\u200d\U0001f468\u200d\U0001f466"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FAMILY_WOMAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FLAG_FOR_EASTERN_HIGHLANDS_PG_EHG = "\U0001f3f4\U000e0070\U000e0067\U000e0065\U000e0068\U000e0067\U000e007f"
- FLAG_FOR_OHRID_MK_58 = "\U0001f3f4\U000e006d\U000e006b\U000e0035\U000e0038\U000e007f"
- FLAG_FOR_SATU_MARE_RO_SM = "\U0001f3f4\U000e0072\U000e006f\U000e0073\U000e006d\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_Y = "\U000e0059"
- FLAG_FOR_CHERNIHIVSHCHYNA_UA_74 = "\U0001f3f4\U000e0075\U000e0061\U000e0037\U000e0034\U000e007f"
- TAG_DIGIT_TWO = "\U000e0032"
- FLAG_FOR_RODRIGUES_MU_RO = "\U0001f3f4\U000e006d\U000e0075\U000e0072\U000e006f\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MAN_DARK_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff"
- FAMILY_MAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_HAWKE_S_BAY_NZ_HKB = "\U0001f3f4\U000e006e\U000e007a\U000e0068\U000e006b\U000e0062\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_SANT_JULIA_DE_LORIA_AD_06 = "\U0001f3f4\U000e0061\U000e0064\U000e0030\U000e0036\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_AN_GIANG_VN_44 = "\U0001f3f4\U000e0076\U000e006e\U000e0034\U000e0034\U000e007f"
- FLAG_FOR_UPPSALA_SE_C = "\U0001f3f4\U000e0073\U000e0065\U000e0063\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_UDMURT_RU_UD = "\U0001f3f4\U000e0072\U000e0075\U000e0075\U000e0064\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_ERMERA_TL_ER = "\U0001f3f4\U000e0074\U000e006c\U000e0065\U000e0072\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_PRIMORJE_GORSKI_KOTAR_HR_08 = "\U0001f3f4\U000e0068\U000e0072\U000e0030\U000e0038\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_MUS_TR_49 = "\U0001f3f4\U000e0074\U000e0072\U000e0034\U000e0039\U000e007f"
- FLAG_FOR_AD_DAKHILIYAH_OM_DA = "\U0001f3f4\U000e006f\U000e006d\U000e0064\U000e0061\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_ORIENTAL_MA_04 = "\U0001f3f4\U000e006d\U000e0061\U000e0030\U000e0034\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FLAG_FOR_MAYO_KEBBI_OUEST_TD_MO = "\U0001f3f4\U000e0074\U000e0064\U000e006d\U000e006f\U000e007f"
- FLAG_FOR_TBILISI_GE_TB = "\U0001f3f4\U000e0067\U000e0065\U000e0074\U000e0062\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_PHU_THO_VN_68 = "\U0001f3f4\U000e0076\U000e006e\U000e0036\U000e0038\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FLAG_FOR_FREE_ZA_FS = "\U0001f3f4\U000e007a\U000e0061\U000e0066\U000e0073\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_SUCRE_VE_R = "\U0001f3f4\U000e0076\U000e0065\U000e0072\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_SALGOTARJAN_HU_ST = "\U0001f3f4\U000e0068\U000e0075\U000e0073\U000e0074\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_RAYONG_TH_21 = "\U0001f3f4\U000e0074\U000e0068\U000e0032\U000e0031\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc"
- FAMILY_MAN_MAN_BABY_GIRL = "\U0001f468\u200d\U0001f468\u200d\U0001f476\u200d\U0001f467"
- FAMILY_WOMAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FAMILY_WOMAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FLAG_FOR_SUD_EST_HT_SE = "\U0001f3f4\U000e0068\U000e0074\U000e0073\U000e0065\U000e007f"
- FLAG_FOR_CETINJE_ME_06 = "\U0001f3f4\U000e006d\U000e0065\U000e0030\U000e0036\U000e007f"
- KISS_WOMAN_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_OVERIJSSEL_NL_OV = "\U0001f3f4\U000e006e\U000e006c\U000e006f\U000e0076\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_SMARTNO_OB_PAKI_SI_125 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0032\U000e0035\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_CENTRAL_ANDROS_BS_CS = "\U0001f3f4\U000e0062\U000e0073\U000e0063\U000e0073\U000e007f"
- FLAG_FOR_GAZA_PS_GZA = "\U0001f3f4\U000e0070\U000e0073\U000e0067\U000e007a\U000e0061\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_TASMANIA_AU_TAS = "\U0001f3f4\U000e0061\U000e0075\U000e0074\U000e0061\U000e0073\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_GAMBELA_ET_GA = "\U0001f3f4\U000e0065\U000e0074\U000e0067\U000e0061\U000e007f"
- FLAG_FOR_SAINT_PETERSBURG_RU_SPE = "\U0001f3f4\U000e0072\U000e0075\U000e0073\U000e0070\U000e0065\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_NORTH_OSSETIA_ALANIA_RU_SE = "\U0001f3f4\U000e0072\U000e0075\U000e0073\U000e0065\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FAMILY_WOMAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_GALICIA_ES_GA = "\U0001f3f4\U000e0065\U000e0073\U000e0067\U000e0061\U000e007f"
- TAG_REVERSE_SOLIDUS = "\U000e005c"
- KISS_MAN_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc"
- FLAG_FOR_KILIMANJARO_TZ_09 = "\U0001f3f4\U000e0074\U000e007a\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_GIRESUN_TR_28 = "\U0001f3f4\U000e0074\U000e0072\U000e0032\U000e0038\U000e007f"
- FLAG_FOR_KEBBI_NG_KE = "\U0001f3f4\U000e006e\U000e0067\U000e006b\U000e0065\U000e007f"
- FLAG_FOR_MAROWIJNE_SR_MA = "\U0001f3f4\U000e0073\U000e0072\U000e006d\U000e0061\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FAMILY_WOMAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_SOUTHWEST_FINLAND_FI_19 = "\U0001f3f4\U000e0066\U000e0069\U000e0031\U000e0039\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FAMILY_WOMAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_BOKEO_LA_BK = "\U0001f3f4\U000e006c\U000e0061\U000e0062\U000e006b\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FAMILY_WOMAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FAMILY_WOMAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FLAG_FOR_GASH_BARKA_ER_GB = "\U0001f3f4\U000e0065\U000e0072\U000e0067\U000e0062\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_ARUNACHAL_PRADESH_IN_AR = "\U0001f3f4\U000e0069\U000e006e\U000e0061\U000e0072\U000e007f"
- COUPLE_WITH_HEART_MAN_MAN_DARK_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff"
- FAMILY_MAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FAMILY_WOMAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_MINNESOTA_US_MN = "\U0001f3f4\U000e0075\U000e0073\U000e006d\U000e006e\U000e007f"
- FLAG_FOR_ROZAJE_ME_17 = "\U0001f3f4\U000e006d\U000e0065\U000e0031\U000e0037\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FAMILY_WOMAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_EL_OUED_DZ_39 = "\U0001f3f4\U000e0064\U000e007a\U000e0033\U000e0039\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_OMNOGOVI_MN_053 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0035\U000e0033\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_WEST_COAST_DIVISION_GM_W = "\U0001f3f4\U000e0067\U000e006d\U000e0077\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_MALUKU_ISLANDS_ID_ML = "\U0001f3f4\U000e0069\U000e0064\U000e006d\U000e006c\U000e007f"
- FLAG_FOR_SVETI_JURIJ_V_SLOVENSKIH_GORICAH_SI_210 = "\U0001f3f4\U000e0073\U000e0069\U000e0032\U000e0031\U000e0030\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_TANGA_TZ_25 = "\U0001f3f4\U000e0074\U000e007a\U000e0032\U000e0035\U000e007f"
- FLAG_FOR_FAR_NORTH_CM_EN = "\U0001f3f4\U000e0063\U000e006d\U000e0065\U000e006e\U000e007f"
- FLAG_FOR_SANNAT_MT_52 = "\U0001f3f4\U000e006d\U000e0074\U000e0035\U000e0032\U000e007f"
- FLAG_FOR_INNER_MONGOLIA_CN_15 = "\U0001f3f4\U000e0063\U000e006e\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_ST_PIERRE_ANDAMP_MIQUELON_FR_PM = "\U0001f3f4\U000e0066\U000e0072\U000e0070\U000e006d\U000e007f"
- NKO_SYMBOL_GBAKURUNEN = "\u07f7"
- FLAG_FOR_RIVER_GEE_LR_RG = "\U0001f3f4\U000e006c\U000e0072\U000e0072\U000e0067\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_NAIROBI_COUNTY_KE_30 = "\U0001f3f4\U000e006b\U000e0065\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_ORYOL_RU_ORL = "\U0001f3f4\U000e0072\U000e0075\U000e006f\U000e0072\U000e006c\U000e007f"
- FLAG_FOR_BEJA_PT_02 = "\U0001f3f4\U000e0070\U000e0074\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_SKOPJE_MK_85 = "\U0001f3f4\U000e006d\U000e006b\U000e0038\U000e0035\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_MOUNT_LEBANON_LB_JL = "\U0001f3f4\U000e006c\U000e0062\U000e006a\U000e006c\U000e007f"
- FLAG_FOR_PERM_KRAI_RU_PER = "\U0001f3f4\U000e0072\U000e0075\U000e0070\U000e0065\U000e0072\U000e007f"
- FAMILY_WOMAN_WOMAN_BABY_BABY = "\U0001f469\u200d\U0001f469\u200d\U0001f476\u200d\U0001f476"
- KISS_MAN_WOMAN_LIGHT_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_ISLA_DE_LA_JUVENTUD_CU_99 = "\U0001f3f4\U000e0063\U000e0075\U000e0039\U000e0039\U000e007f"
- UNMARRIED_PARTNERSHIP_SYMBOL = "\u26af"
- FLAG_FOR_LAGUNES_CI_LG = "\U0001f3f4\U000e0063\U000e0069\U000e006c\U000e0067\U000e007f"
- FLAG_FOR_WESTERN_AUSTRALIA_AU_WA = "\U0001f3f4\U000e0061\U000e0075\U000e0077\U000e0061\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FAMILY_WOMAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_HEREDIA_CR_H = "\U0001f3f4\U000e0063\U000e0072\U000e0068\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_AIGA_I_LE_TAI_WS_AL = "\U0001f3f4\U000e0077\U000e0073\U000e0061\U000e006c\U000e007f"
- KISS_WOMAN_LIGHT_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe"
- FLAG_FOR_BAVARIA_DE_BY = "\U0001f3f4\U000e0064\U000e0065\U000e0062\U000e0079\U000e007f"
- FLAG_FOR_VALPARAISO_CL_VS = "\U0001f3f4\U000e0063\U000e006c\U000e0076\U000e0073\U000e007f"
- WOMAN_IN_BUSINESS_SUIT_LEVITATING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f574\U0001f3fc\u200d\u2640\ufe0f"
- FLAG_FOR_BAGHDAD_IQ_BG = "\U0001f3f4\U000e0069\U000e0071\U000e0062\U000e0067\U000e007f"
- FLAG_FOR_TENNESSEE_US_TN = "\U0001f3f4\U000e0075\U000e0073\U000e0074\U000e006e\U000e007f"
- FAMILY_MAN_WOMAN_BABY = "\U0001f468\u200d\U0001f469\u200d\U0001f476"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FLAG_FOR_LA_PAZ_SV_PA = "\U0001f3f4\U000e0073\U000e0076\U000e0070\U000e0061\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_RABAT_MT_46 = "\U0001f3f4\U000e006d\U000e0074\U000e0034\U000e0036\U000e007f"
- FLAG_FOR_IMO_NG_IM = "\U0001f3f4\U000e006e\U000e0067\U000e0069\U000e006d\U000e007f"
- FLAG_FOR_WELLINGTON_NZ_WGN = "\U0001f3f4\U000e006e\U000e007a\U000e0077\U000e0067\U000e006e\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_ZABLJAK_ME_21 = "\U0001f3f4\U000e006d\U000e0065\U000e0032\U000e0031\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_BORNO_NG_BO = "\U0001f3f4\U000e006e\U000e0067\U000e0062\U000e006f\U000e007f"
- FLAG_FOR_NAKURU_KE_31 = "\U0001f3f4\U000e006b\U000e0065\U000e0033\U000e0031\U000e007f"
- FLAG_FOR_CARABOBO_VE_G = "\U0001f3f4\U000e0076\U000e0065\U000e0067\U000e007f"
- FLAG_FOR_TEHRAN_IR_07 = "\U0001f3f4\U000e0069\U000e0072\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_BADEN_WURTTEMBERG_DE_BW = "\U0001f3f4\U000e0064\U000e0065\U000e0062\U000e0077\U000e007f"
- FLAG_FOR_YANGON_MM_06 = "\U0001f3f4\U000e006d\U000e006d\U000e0030\U000e0036\U000e007f"
- TAG_LEFT_PARENTHESIS = "\U000e0028"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_USTECKY_KRAJ_CZ_42 = "\U0001f3f4\U000e0063\U000e007a\U000e0034\U000e0032\U000e007f"
- FLAG_FOR_KUALA_LUMPUR_MY_14 = "\U0001f3f4\U000e006d\U000e0079\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_AL_WUSTA_OM_WU = "\U0001f3f4\U000e006f\U000e006d\U000e0077\U000e0075\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FLAG_FOR_SOUTH_JEOLLA_KR_46 = "\U0001f3f4\U000e006b\U000e0072\U000e0034\U000e0036\U000e007f"
- FLAG_FOR_KHUZESTAN_IR_10 = "\U0001f3f4\U000e0069\U000e0072\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_NANTOU_TW_NAN = "\U0001f3f4\U000e0074\U000e0077\U000e006e\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_DUSHANBE_TJ_DU = "\U0001f3f4\U000e0074\U000e006a\U000e0064\U000e0075\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_LIMBURG_NL_LI = "\U0001f3f4\U000e006e\U000e006c\U000e006c\U000e0069\U000e007f"
- FLAG_FOR_AYACUCHO_PE_AYA = "\U0001f3f4\U000e0070\U000e0065\U000e0061\U000e0079\U000e0061\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_SAINT_PHILIP_AG_08 = "\U0001f3f4\U000e0061\U000e0067\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_VALKA_LV_101 = "\U0001f3f4\U000e006c\U000e0076\U000e0031\U000e0030\U000e0031\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_MDINA_MT_29 = "\U0001f3f4\U000e006d\U000e0074\U000e0032\U000e0039\U000e007f"
- FLAG_FOR_NORTHERN_DENMARK_DK_81 = "\U0001f3f4\U000e0064\U000e006b\U000e0038\U000e0031\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FLAG_FOR_GUAM_US_GU = "\U0001f3f4\U000e0075\U000e0073\U000e0067\U000e0075\U000e007f"
- FLAG_FOR_SELANGOR_MY_10 = "\U0001f3f4\U000e006d\U000e0079\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_PRINCE_EDWARD_ISLAND_CA_PE = "\U0001f3f4\U000e0063\U000e0061\U000e0070\U000e0065\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_GORNO_BADAKHSHAN_TJ_GB = "\U0001f3f4\U000e0074\U000e006a\U000e0067\U000e0062\U000e007f"
- FLAG_FOR_OGUN_NG_OG = "\U0001f3f4\U000e006e\U000e0067\U000e006f\U000e0067\U000e007f"
- FLAG_FOR_EASTERN_LK_5 = "\U0001f3f4\U000e006c\U000e006b\U000e0035\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FLAG_FOR_SANTA_ROSA_GT_SR = "\U0001f3f4\U000e0067\U000e0074\U000e0073\U000e0072\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_JAFARA_LY_JI = "\U0001f3f4\U000e006c\U000e0079\U000e006a\U000e0069\U000e007f"
- FLAG_FOR_BASILICATA_IT_77 = "\U0001f3f4\U000e0069\U000e0074\U000e0037\U000e0037\U000e007f"
- FLAG_FOR_GRONINGEN_NL_GR = "\U0001f3f4\U000e006e\U000e006c\U000e0067\U000e0072\U000e007f"
- FLAG_FOR_MATO_GROSSO_DO_SUL_BR_MS = "\U0001f3f4\U000e0062\U000e0072\U000e006d\U000e0073\U000e007f"
- FLAG_FOR_KANDAL_KH_8 = "\U0001f3f4\U000e006b\U000e0068\U000e0038\U000e007f"
- FLAG_FOR_NORTH_WEST_ZA_NW = "\U0001f3f4\U000e007a\U000e0061\U000e006e\U000e0077\U000e007f"
- FLAG_FOR_CONNECTICUT_US_CT = "\U0001f3f4\U000e0075\U000e0073\U000e0063\U000e0074\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FLAG_FOR_HEBEI_CN_13 = "\U0001f3f4\U000e0063\U000e006e\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_FA_ASALELEAGA_WS_FA = "\U0001f3f4\U000e0077\U000e0073\U000e0066\U000e0061\U000e007f"
- FLAG_FOR_ALBORZ_IR_32 = "\U0001f3f4\U000e0069\U000e0072\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_BRASLOVCE_SI_151 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0035\U000e0031\U000e007f"
- FLAG_FOR_HARYANA_IN_HR = "\U0001f3f4\U000e0069\U000e006e\U000e0068\U000e0072\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe"
- FLAG_FOR_SAN_VICENTE_SV_SV = "\U0001f3f4\U000e0073\U000e0076\U000e0073\U000e0076\U000e007f"
- FLAG_FOR_MATO_GROSSO_BR_MT = "\U0001f3f4\U000e0062\U000e0072\U000e006d\U000e0074\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FLAG_FOR_PELOPONNESE_GR_J = "\U0001f3f4\U000e0067\U000e0072\U000e006a\U000e007f"
- FLAG_FOR_ADAMAWA_NG_AD = "\U0001f3f4\U000e006e\U000e0067\U000e0061\U000e0064\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FLAG_FOR_KWAZULU_NATAL_ZA_NL = "\U0001f3f4\U000e007a\U000e0061\U000e006e\U000e006c\U000e007f"
- FLAG_FOR_SINT_MAARTEN_NL_SX = "\U0001f3f4\U000e006e\U000e006c\U000e0073\U000e0078\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f466\U0001f3fe"
- TAG_SPACE = "\U000e0020"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_CORDILLERA_ADMINISTRATIVE_PH_15 = "\U0001f3f4\U000e0070\U000e0068\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_AUCE_LV_010 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_ROCHA_UY_RO = "\U0001f3f4\U000e0075\U000e0079\U000e0072\U000e006f\U000e007f"
- FLAG_FOR_FRIESLAND_NL_FR = "\U0001f3f4\U000e006e\U000e006c\U000e0066\U000e0072\U000e007f"
- FLAG_FOR_AUVERGNE_RHONE_ALPES_FR_ARA = "\U0001f3f4\U000e0066\U000e0072\U000e0061\U000e0072\U000e0061\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_NOHIYAHOI_TOBEI_JUMHURI_TJ_RA = "\U0001f3f4\U000e0074\U000e006a\U000e0072\U000e0061\U000e007f"
- APPLE_LOGO = "\uf8ff"
- FLAG_FOR_SAO_TOME_ST_S = "\U0001f3f4\U000e0073\U000e0074\U000e0073\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_ANDHRA_PRADESH_IN_AP = "\U0001f3f4\U000e0069\U000e006e\U000e0061\U000e0070\U000e007f"
- FLAG_FOR_INCUKALNS_LV_037 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0033\U000e0037\U000e007f"
- FLAG_FOR_KAKHETI_GE_KA = "\U0001f3f4\U000e0067\U000e0065\U000e006b\U000e0061\U000e007f"
- FLAG_FOR_BOURGOGNE_FRANCHE_COMTE_FR_BFC = "\U0001f3f4\U000e0066\U000e0072\U000e0062\U000e0066\U000e0063\U000e007f"
- KISS_WOMAN_MEDIUM_SKIN_TONE_MAN = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468"
- FLAG_FOR_ENNEDI_OUEST_TD_EO = "\U0001f3f4\U000e0074\U000e0064\U000e0065\U000e006f\U000e007f"
- FLAG_FOR_SOUSS_MASSA_DRAA_MA_13 = "\U0001f3f4\U000e006d\U000e0061\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_USAK_TR_64 = "\U0001f3f4\U000e0074\U000e0072\U000e0036\U000e0034\U000e007f"
- FLAG_FOR_JEJU_KR_49 = "\U0001f3f4\U000e006b\U000e0072\U000e0034\U000e0039\U000e007f"
- FLAG_FOR_CHHATTISGARH_IN_CT = "\U0001f3f4\U000e0069\U000e006e\U000e0063\U000e0074\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f476\U0001f3fb"
- KISS_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FAMILY_MAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_TLEMCEN_DZ_13 = "\U0001f3f4\U000e0064\U000e007a\U000e0031\U000e0033\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FLAG_FOR_QUINTANA_ROO_MX_ROO = "\U0001f3f4\U000e006d\U000e0078\U000e0072\U000e006f\U000e006f\U000e007f"
- FLAG_FOR_WESTERN_IS_3 = "\U0001f3f4\U000e0069\U000e0073\U000e0033\U000e007f"
- FLAG_FOR_BANAADIR_SO_BN = "\U0001f3f4\U000e0073\U000e006f\U000e0062\U000e006e\U000e007f"
- FLAG_FOR_RHINELAND_PALATINATE_DE_RP = "\U0001f3f4\U000e0064\U000e0065\U000e0072\U000e0070\U000e007f"
- FLAG_FOR_MARITIME_TG_M = "\U0001f3f4\U000e0074\U000e0067\U000e006d\U000e007f"
- FLAG_FOR_GYOR_MOSON_SOPRON_HU_GS = "\U0001f3f4\U000e0068\U000e0075\U000e0067\U000e0073\U000e007f"
- FLAG_FOR_BEN_AROUS_TN_13 = "\U0001f3f4\U000e0074\U000e006e\U000e0031\U000e0033\U000e007f"
- WOMAN_IN_BUSINESS_SUIT_LEVITATING_LIGHT_SKIN_TONE = "\U0001f574\U0001f3fb\u200d\u2640\ufe0f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FAMILY_WOMAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FLAG_FOR_FUKUI_JP_18 = "\U0001f3f4\U000e006a\U000e0070\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_EAST_NEW_BRITAIN_PG_EBR = "\U0001f3f4\U000e0070\U000e0067\U000e0065\U000e0062\U000e0072\U000e007f"
- VARIATION_SELECTOR_16 = "\ufe0f"
- FLAG_FOR_CENTRAL_EQUATORIA_SS_EC = "\U0001f3f4\U000e0073\U000e0073\U000e0065\U000e0063\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FLAG_FOR_KHAMMOUANE_LA_KH = "\U0001f3f4\U000e006c\U000e0061\U000e006b\U000e0068\U000e007f"
- FLAG_FOR_DADRA_AND_NAGAR_HAVELI_IN_DN = "\U0001f3f4\U000e0069\U000e006e\U000e0064\U000e006e\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_SOUTHERN_RED_SEA_ER_DK = "\U0001f3f4\U000e0065\U000e0072\U000e0064\U000e006b\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FAMILY_MAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_VOJVODINA_RS_VO = "\U0001f3f4\U000e0072\U000e0073\U000e0076\U000e006f\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_ATLANTICO_SUR_NI_AS = "\U0001f3f4\U000e006e\U000e0069\U000e0061\U000e0073\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FAMILY_MAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FLAG_FOR_KERMAN_IR_15 = "\U0001f3f4\U000e0069\U000e0072\U000e0031\U000e0035\U000e007f"
- KISS_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468"
- FAMILY_MAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_KALMAR_SE_H = "\U0001f3f4\U000e0073\U000e0065\U000e0068\U000e007f"
- COUPLE_WITH_HEART_MAN_LIGHT_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe"
- FLAG_FOR_ALMATY_REGION_KZ_ALM = "\U0001f3f4\U000e006b\U000e007a\U000e0061\U000e006c\U000e006d\U000e007f"
- FLAG_FOR_ZLINSKY_KRAJ_CZ_72 = "\U0001f3f4\U000e0063\U000e007a\U000e0037\U000e0032\U000e007f"
- FLAG_FOR_SANGRE_GRANDE_TT_SGE = "\U0001f3f4\U000e0074\U000e0074\U000e0073\U000e0067\U000e0065\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_PUERTO_RICO_US_PR = "\U0001f3f4\U000e0075\U000e0073\U000e0070\U000e0072\U000e007f"
- FLAG_FOR_ALO_WF_AL = "\U0001f3f4\U000e0077\U000e0066\U000e0061\U000e006c\U000e007f"
- FLAG_FOR_WASHINGTON_DC_US_DC = "\U0001f3f4\U000e0075\U000e0073\U000e0064\U000e0063\U000e007f"
- FLAG_FOR_LA_REUNION_FR_LRE = "\U0001f3f4\U000e0066\U000e0072\U000e006c\U000e0072\U000e0065\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_GRAD_SI_158 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0035\U000e0038\U000e007f"
- FLAG_FOR_TEXAS_US_TX = "\U0001f3f4\U000e0075\U000e0073\U000e0074\U000e0078\U000e007f"
- MAN_ZOMBIE_MEDIUM_DARK_SKIN_TONE = "\U0001f9df\U0001f3fe\u200d\u2642\ufe0f"
- FLAG_FOR_PARAIBA_BR_PB = "\U0001f3f4\U000e0062\U000e0072\U000e0070\U000e0062\U000e007f"
- FLAG_FOR_VARGAS_VE_X = "\U0001f3f4\U000e0076\U000e0065\U000e0078\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_H = "\U000e0048"
- FLAG_FOR_BERN_CH_BE = "\U0001f3f4\U000e0063\U000e0068\U000e0062\U000e0065\U000e007f"
- FLAG_FOR_MARA_TZ_13 = "\U0001f3f4\U000e0074\U000e007a\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_THURINGIA_DE_TH = "\U0001f3f4\U000e0064\U000e0065\U000e0074\U000e0068\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f466\U0001f3fb"
- TAG_LATIN_CAPITAL_LETTER_R = "\U000e0052"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_GOTLAND_SE_I = "\U0001f3f4\U000e0073\U000e0065\U000e0069\U000e007f"
- FLAG_FOR_ANDAMAN_AND_NICOBAR_ISLANDS_IN_AN = "\U0001f3f4\U000e0069\U000e006e\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_SAN_ANDRES_ANDAMP_PROVIDENCIA_CO_SAP = "\U0001f3f4\U000e0063\U000e006f\U000e0073\U000e0061\U000e0070\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FLAG_FOR_SOUTHERN_DENMARK_DK_83 = "\U0001f3f4\U000e0064\U000e006b\U000e0038\U000e0033\U000e007f"
- FLAG_FOR_AMUR_RU_AMU = "\U0001f3f4\U000e0072\U000e0075\U000e0061\U000e006d\U000e0075\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FLAG_FOR_NAGASAKI_JP_42 = "\U0001f3f4\U000e006a\U000e0070\U000e0034\U000e0032\U000e007f"
- FLAG_FOR_NEWFOUNDLAND_AND_LABRADOR_CA_NL = "\U0001f3f4\U000e0063\U000e0061\U000e006e\U000e006c\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f467\U0001f3ff"
- TAG_GREATER_THAN_SIGN = "\U000e003e"
- FLAG_FOR_RAMALLAH_AND_AL_BIREH_PS_RBH = "\U0001f3f4\U000e0070\U000e0073\U000e0072\U000e0062\U000e0068\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f467\U0001f3fd"
- KISS_MAN_MAN_MEDIUM_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_ANTOFAGASTA_CL_AN = "\U0001f3f4\U000e0063\U000e006c\U000e0061\U000e006e\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FAMILY_MAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f466\U0001f3fb"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb"
- KISS_MAN_MEDIUM_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff"
- FLAG_FOR_CHUVASH_RU_CU = "\U0001f3f4\U000e0072\U000e0075\U000e0063\U000e0075\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FAMILY_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FAMILY_WOMAN_WOMAN_BOY_GIRL = "\U0001f469\u200d\U0001f469\u200d\U0001f466\u200d\U0001f467"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_ULSTER_IE_U = "\U0001f3f4\U000e0069\U000e0065\U000e0075\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FLAG_FOR_NABEUL_TN_21 = "\U0001f3f4\U000e0074\U000e006e\U000e0032\U000e0031\U000e007f"
- FAMILY_MAN_BABY_BABY = "\U0001f468\u200d\U0001f476\u200d\U0001f476"
- FLAG_FOR_TAIPEI_TW_TPE = "\U0001f3f4\U000e0074\U000e0077\U000e0074\U000e0070\U000e0065\U000e007f"
- COUPLE_WITH_HEART_MAN_WOMAN_DARK_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff"
- FAMILY_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FLAG_FOR_ZEELAND_NL_ZE = "\U0001f3f4\U000e006e\U000e006c\U000e007a\U000e0065\U000e007f"
- FLAG_FOR_JAVA_ID_JW = "\U0001f3f4\U000e0069\U000e0064\U000e006a\U000e0077\U000e007f"
- FLAG_FOR_AZAD_KASHMIR_PK_JK = "\U0001f3f4\U000e0070\U000e006b\U000e006a\U000e006b\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_UNITY_SS_UY = "\U0001f3f4\U000e0073\U000e0073\U000e0075\U000e0079\U000e007f"
- FLAG_FOR_CENTRAL_LUZON_PH_03 = "\U0001f3f4\U000e0070\U000e0068\U000e0030\U000e0033\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_SOUTHERN_LK_3 = "\U0001f3f4\U000e006c\U000e006b\U000e0033\U000e007f"
- FLAG_FOR_SAO_PAULO_BR_SP = "\U0001f3f4\U000e0062\U000e0072\U000e0073\U000e0070\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_JAMMU_AND_KASHMIR_IN_JK = "\U0001f3f4\U000e0069\U000e006e\U000e006a\U000e006b\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_CAT_ISLAND_BS_CI = "\U0001f3f4\U000e0062\U000e0073\U000e0063\U000e0069\U000e007f"
- FLAG_FOR_LAGHOUAT_DZ_03 = "\U0001f3f4\U000e0064\U000e007a\U000e0030\U000e0033\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_MARJ_LY_MJ = "\U0001f3f4\U000e006c\U000e0079\U000e006d\U000e006a\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f476\U0001f3fc"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb"
- FLAG_FOR_TRUJILLO_VE_T = "\U0001f3f4\U000e0076\U000e0065\U000e0074\U000e007f"
- WOMAN_WITH_HEADSCARF_MEDIUM_DARK_SKIN_TONE = "\U0001f9d5\U0001f3fe\u200d\u2640\ufe0f"
- FLAG_FOR_SAARLAND_DE_SL = "\U0001f3f4\U000e0064\U000e0065\U000e0073\U000e006c\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_TRENTINO_SOUTH_TYROL_IT_32 = "\U0001f3f4\U000e0069\U000e0074\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_KHARTOUM_SD_KH = "\U0001f3f4\U000e0073\U000e0064\U000e006b\U000e0068\U000e007f"
- TAG_EXCLAMATION_MARK = "\U000e0021"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_TRANSNISTRIA_MD_SN = "\U0001f3f4\U000e006d\U000e0064\U000e0073\U000e006e\U000e007f"
- FLAG_FOR_PINAR_DEL_RIO_CU_01 = "\U0001f3f4\U000e0063\U000e0075\U000e0030\U000e0031\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_KEDAH_MY_02 = "\U0001f3f4\U000e006d\U000e0079\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_JILIN_CN_22 = "\U0001f3f4\U000e0063\U000e006e\U000e0032\U000e0032\U000e007f"
- ZERO_WIDTH_JOINER = "\u200d"
- FAMILY_WOMAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FLAG_FOR_MANUFAHI_TL_MF = "\U0001f3f4\U000e0074\U000e006c\U000e006d\U000e0066\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_STUDENICANI_MK_74 = "\U0001f3f4\U000e006d\U000e006b\U000e0037\U000e0034\U000e007f"
- FLAG_FOR_ILUKSTE_LV_036 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0033\U000e0036\U000e007f"
- FLAG_FOR_MAZANDARAN_IR_21 = "\U0001f3f4\U000e0069\U000e0072\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_VISEU_PT_18 = "\U0001f3f4\U000e0070\U000e0074\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_ESTUAIRE_GA_1 = "\U0001f3f4\U000e0067\U000e0061\U000e0031\U000e007f"
- FLAG_FOR_GANSU_CN_62 = "\U0001f3f4\U000e0063\U000e006e\U000e0036\U000e0032\U000e007f"
- FLAG_FOR_SOUTH_KHORASAN_IR_29 = "\U0001f3f4\U000e0069\U000e0072\U000e0032\U000e0039\U000e007f"
- FLAG_FOR_DIOURBEL_SN_DB = "\U0001f3f4\U000e0073\U000e006e\U000e0064\U000e0062\U000e007f"
- FLAG_FOR_MORELOS_MX_MOR = "\U0001f3f4\U000e006d\U000e0078\U000e006d\U000e006f\U000e0072\U000e007f"
- FLAG_FOR_DELAWARE_US_DE = "\U0001f3f4\U000e0075\U000e0073\U000e0064\U000e0065\U000e007f"
- FLAG_FOR_SIGAVE_WF_SG = "\U0001f3f4\U000e0077\U000e0066\U000e0073\U000e0067\U000e007f"
- FLAG_FOR_RIVERA_UY_RV = "\U0001f3f4\U000e0075\U000e0079\U000e0072\U000e0076\U000e007f"
- FLAG_FOR_TUNGURAHUA_EC_T = "\U0001f3f4\U000e0065\U000e0063\U000e0074\U000e007f"
- BEAMED_DESCENDING_MUSICAL_NOTES = "\U0001f39d"
- FLAG_FOR_KALININGRAD_RU_KGD = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e0067\U000e0064\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_T = "\U000e0054"
- FLAG_FOR_TOMBOUCTOU_ML_6 = "\U0001f3f4\U000e006d\U000e006c\U000e0036\U000e007f"
- COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc"
- FLAG_FOR_ENCAMP_AD_03 = "\U0001f3f4\U000e0061\U000e0064\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_MIAOLI_TW_MIA = "\U0001f3f4\U000e0074\U000e0077\U000e006d\U000e0069\U000e0061\U000e007f"
- FLAG_FOR_KENTUCKY_US_KY = "\U0001f3f4\U000e0075\U000e0073\U000e006b\U000e0079\U000e007f"
- FLAG_FOR_GUSINJE_ME_22 = "\U0001f3f4\U000e006d\U000e0065\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_SAATLY_AZ_SAT = "\U0001f3f4\U000e0061\U000e007a\U000e0073\U000e0061\U000e0074\U000e007f"
- FLAG_FOR_NUNAVUT_CA_NU = "\U0001f3f4\U000e0063\U000e0061\U000e006e\U000e0075\U000e007f"
- FLAG_FOR_SPANISH_WELLS_BS_SW = "\U0001f3f4\U000e0062\U000e0073\U000e0073\U000e0077\U000e007f"
- FLAG_FOR_BITLIS_TR_13 = "\U0001f3f4\U000e0074\U000e0072\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_BADGHIS_AF_BDG = "\U0001f3f4\U000e0061\U000e0066\U000e0062\U000e0064\U000e0067\U000e007f"
- KISS_MAN_DARK_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_SAGA_JP_41 = "\U0001f3f4\U000e006a\U000e0070\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_ST_PAUL_S_BAY_MT_51 = "\U0001f3f4\U000e006d\U000e0074\U000e0035\U000e0031\U000e007f"
- FLAG_FOR_TORBA_VU_TOB = "\U0001f3f4\U000e0076\U000e0075\U000e0074\U000e006f\U000e0062\U000e007f"
- KISS_MAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_BERLIN_DE_BE = "\U0001f3f4\U000e0064\U000e0065\U000e0062\U000e0065\U000e007f"
- FLAG_FOR_BABITE_LV_012 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_EL_VALLE_DO_37 = "\U0001f3f4\U000e0064\U000e006f\U000e0033\U000e0037\U000e007f"
- FLAG_FOR_BENI_SUEF_EG_BNS = "\U0001f3f4\U000e0065\U000e0067\U000e0062\U000e006e\U000e0073\U000e007f"
- FLAG_FOR_SFAX_TN_61 = "\U0001f3f4\U000e0074\U000e006e\U000e0036\U000e0031\U000e007f"
- FLAG_FOR_MONTE_CARLO_MC_MC = "\U0001f3f4\U000e006d\U000e0063\U000e006d\U000e0063\U000e007f"
- FLAG_FOR_YUNNAN_CN_53 = "\U0001f3f4\U000e0063\U000e006e\U000e0035\U000e0033\U000e007f"
- FLAG_FOR_KLAIPEDOS_MUNICIPALITY_LT_20 = "\U0001f3f4\U000e006c\U000e0074\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_BARINGO_KE_01 = "\U0001f3f4\U000e006b\U000e0065\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_CENTRAL_RIVER_DIVISION_GM_M = "\U0001f3f4\U000e0067\U000e006d\U000e006d\U000e007f"
- FLAG_FOR_AMANAT_AL_ASIMAH_YE_SA = "\U0001f3f4\U000e0079\U000e0065\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_HAUTS_BASSINS_BF_09 = "\U0001f3f4\U000e0062\U000e0066\U000e0030\U000e0039\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f476\U0001f3fe"
- TAG_EQUALS_SIGN = "\U000e003d"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_SENGLEA_MT_20 = "\U0001f3f4\U000e006d\U000e0074\U000e0032\U000e0030\U000e007f"
- ALTERNATE_ONE_WAY_LEFT_WAY_TRAFFIC = "\u26d5"
- FLAG_FOR_G_ASRI_MT_16 = "\U0001f3f4\U000e006d\U000e0074\U000e0031\U000e0036\U000e007f"
- WHITE_CHESS_PAWN = "\u2659"
- FLAG_FOR_HAU_GIANG_VN_73 = "\U0001f3f4\U000e0076\U000e006e\U000e0037\U000e0033\U000e007f"
- MAN_ZOMBIE_MEDIUM_SKIN_TONE = "\U0001f9df\U0001f3fd\u200d\u2642\ufe0f"
- FLAG_FOR_TEARCE_MK_75 = "\U0001f3f4\U000e006d\U000e006b\U000e0037\U000e0035\U000e007f"
- FLAG_FOR_FAMAGUSTA_CY_04 = "\U0001f3f4\U000e0063\U000e0079\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_COTOPAXI_EC_X = "\U0001f3f4\U000e0065\U000e0063\U000e0078\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_ANG_THONG_TH_15 = "\U0001f3f4\U000e0074\U000e0068\U000e0031\U000e0035\U000e007f"
- RECYCLING_SYMBOL_FOR_TYPE_2_PLASTICS = "\u2674"
- FLAG_FOR_SETUBAL_PT_15 = "\U0001f3f4\U000e0070\U000e0074\U000e0031\U000e0035\U000e007f"
- BLACK_CIRCLE_WITH_WHITE_DOT_RIGHT = "\u2688"
- WHITE_SPADE_SUIT = "\u2664"
- FLAG_FOR_DAGDA_LV_024 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_BAR_ME_02 = "\U0001f3f4\U000e006d\U000e0065\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_CATALONIA_ES_CT = "\U0001f3f4\U000e0065\U000e0073\U000e0063\U000e0074\U000e007f"
- COUPLE_WITH_HEART_MAN_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe"
- FLAG_FOR_WESTERN_SB_WE = "\U0001f3f4\U000e0073\U000e0062\U000e0077\U000e0065\U000e007f"
- FLAG_FOR_BAYQONGYR_KZ_BAY = "\U0001f3f4\U000e006b\U000e007a\U000e0062\U000e0061\U000e0079\U000e007f"
- NOTE_PAD = "\U0001f5ca"
- BLACK_CHESS_KING = "\u265a"
- FLAG_FOR_PORTO_PT_13 = "\U0001f3f4\U000e0070\U000e0074\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_KAMPONG_CHHNANG_KH_4 = "\U0001f3f4\U000e006b\U000e0068\U000e0034\U000e007f"
- FLAG_FOR_DAKAR_SN_DK = "\U0001f3f4\U000e0073\U000e006e\U000e0064\U000e006b\U000e007f"
- FLAG_FOR_FEDERAL_CAPITAL_TERRITORY_PL_PM = "\U0001f3f4\U000e0070\U000e006c\U000e0070\U000e006d\U000e007f"
- WHITE_TOUCHTONE_TELEPHONE = "\U0001f57e"
- FLAG_FOR_TAMIL_NADU_IN_TN = "\U0001f3f4\U000e0069\U000e006e\U000e0074\U000e006e\U000e007f"
- FLAG_FOR_BRAGA_PT_03 = "\U0001f3f4\U000e0070\U000e0074\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_SPELUGUES_MC_SP = "\U0001f3f4\U000e006d\U000e0063\U000e0073\U000e0070\U000e007f"
- FLAG_FOR_JHARKHAND_IN_JH = "\U0001f3f4\U000e0069\U000e006e\U000e006a\U000e0068\U000e007f"
- FLAG_FOR_BOCAS_DEL_TORO_PA_1 = "\U0001f3f4\U000e0070\U000e0061\U000e0031\U000e007f"
- FLAG_FOR_CANAR_EC_F = "\U0001f3f4\U000e0065\U000e0063\U000e0066\U000e007f"
- FLAG_FOR_AICHI_JP_23 = "\U0001f3f4\U000e006a\U000e0070\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_OMAHEKE_NA_OH = "\U0001f3f4\U000e006e\U000e0061\U000e006f\U000e0068\U000e007f"
- FLAG_FOR_MERSIN_TR_33 = "\U0001f3f4\U000e0074\U000e0072\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_OSH_REGION_KG_O = "\U0001f3f4\U000e006b\U000e0067\U000e006f\U000e007f"
- FLAG_FOR_MIYAZAKI_JP_45 = "\U0001f3f4\U000e006a\U000e0070\U000e0034\U000e0035\U000e007f"
- WHITE_RIGHT_POINTING_INDEX = "\u261e"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff"
- FLAG_FOR_PAIJANNE_TAVASTIA_FI_16 = "\U0001f3f4\U000e0066\U000e0069\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_TARANAKI_NZ_TKI = "\U0001f3f4\U000e006e\U000e007a\U000e0074\U000e006b\U000e0069\U000e007f"
- FLAG_FOR_ILLINOIS_US_IL = "\U0001f3f4\U000e0075\U000e0073\U000e0069\U000e006c\U000e007f"
- FLAG_FOR_BAMYAN_AF_BAM = "\U0001f3f4\U000e0061\U000e0066\U000e0062\U000e0061\U000e006d\U000e007f"
- FLAG_FOR_FLORIDA_UY_FD = "\U0001f3f4\U000e0075\U000e0079\U000e0066\U000e0064\U000e007f"
- UP_POINTING_AIRPLANE = "\U0001f6e7"
- FLAG_FOR_THAI_NGUYEN_VN_69 = "\U0001f3f4\U000e0076\U000e006e\U000e0036\U000e0039\U000e007f"
- FLAG_FOR_VIROVITICA_PODRAVINA_HR_10 = "\U0001f3f4\U000e0068\U000e0072\U000e0031\U000e0030\U000e007f"
- KISS_MAN_LIGHT_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe"
- WHITE_LEFT_POINTING_INDEX = "\u261c"
- FLAG_FOR_KIGOMA_TZ_08 = "\U0001f3f4\U000e0074\U000e007a\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_SUL_GW_S = "\U0001f3f4\U000e0067\U000e0077\U000e0073\U000e007f"
- FLAG_FOR_BELIZE_BZ_BZ = "\U0001f3f4\U000e0062\U000e007a\U000e0062\U000e007a\U000e007f"
- FLAG_FOR_HHOHHO_SZ_HH = "\U0001f3f4\U000e0073\U000e007a\U000e0068\U000e0068\U000e007f"
- FLAG_FOR_AKTOBE_KZ_AKT = "\U0001f3f4\U000e006b\U000e007a\U000e0061\U000e006b\U000e0074\U000e007f"
- FLAG_FOR_ZHEJIANG_CN_33 = "\U0001f3f4\U000e0063\U000e006e\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_EL_PARAISO_HN_EP = "\U0001f3f4\U000e0068\U000e006e\U000e0065\U000e0070\U000e007f"
- MONOGRAM_FOR_YIN = "\u268b"
- FLAG_FOR_NUGAL_SO_NU = "\U0001f3f4\U000e0073\U000e006f\U000e006e\U000e0075\U000e007f"
- MAHJONG_TILE_NINE_OF_CHARACTERS = "\U0001f00f"
- FLAG_FOR_ATTICA_GR_I = "\U0001f3f4\U000e0067\U000e0072\U000e0069\U000e007f"
- NOTE_PAGE = "\U0001f5c9"
- FLAG_FOR_DURBE_LV_028 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0032\U000e0038\U000e007f"
- FLAG_FOR_CAYO_BZ_CY = "\U0001f3f4\U000e0062\U000e007a\U000e0063\U000e0079\U000e007f"
- SOFT_SHELL_FLOPPY_DISK = "\U0001f5ac"
- FLAG_FOR_SAKHA_RU_SA = "\U0001f3f4\U000e0072\U000e0075\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_SEGOU_ML_4 = "\U0001f3f4\U000e006d\U000e006c\U000e0034\U000e007f"
- FLAG_FOR_BALKH_AF_BAL = "\U0001f3f4\U000e0061\U000e0066\U000e0062\U000e0061\U000e006c\U000e007f"
- FLAG_FOR_WESTFJORDS_IS_4 = "\U0001f3f4\U000e0069\U000e0073\U000e0034\U000e007f"
- FLAG_FOR_CALIFORNIA_US_CA = "\U0001f3f4\U000e0075\U000e0073\U000e0063\U000e0061\U000e007f"
- FLAG_FOR_SETIF_DZ_19 = "\U0001f3f4\U000e0064\U000e007a\U000e0031\U000e0039\U000e007f"
- TAG_COMMA = "\U000e002c"
- FLAG_FOR_BAJA_VERAPAZ_GT_BV = "\U0001f3f4\U000e0067\U000e0074\U000e0062\U000e0076\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_E = "\U000e0045"
- FLAG_FOR_WEST_CM_OU = "\U0001f3f4\U000e0063\U000e006d\U000e006f\U000e0075\U000e007f"
- FLAG_FOR_SHAANXI_CN_61 = "\U0001f3f4\U000e0063\U000e006e\U000e0036\U000e0031\U000e007f"
- FLAG_FOR_SOUTH_CM_SU = "\U0001f3f4\U000e0063\U000e006d\U000e0073\U000e0075\U000e007f"
- FLAG_FOR_RAKHINE_MM_16 = "\U0001f3f4\U000e006d\U000e006d\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_BARIMA_WAINI_GY_BA = "\U0001f3f4\U000e0067\U000e0079\U000e0062\U000e0061\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_SANA_A_YE_SN = "\U0001f3f4\U000e0079\U000e0065\U000e0073\U000e006e\U000e007f"
- FLAG_FOR_VILNIAUS_MUNICIPALITY_LT_57 = "\U0001f3f4\U000e006c\U000e0074\U000e0035\U000e0037\U000e007f"
- FLAG_FOR_RANKOVCE_MK_65 = "\U0001f3f4\U000e006d\U000e006b\U000e0036\U000e0035\U000e007f"
- FLAG_FOR_WEST_BENGAL_IN_WB = "\U0001f3f4\U000e0069\U000e006e\U000e0077\U000e0062\U000e007f"
- TAG_LEFT_CURLY_BRACKET = "\U000e007b"
- FLAG_FOR_KIROVOHRADSCHYNA_UA_35 = "\U0001f3f4\U000e0075\U000e0061\U000e0033\U000e0035\U000e007f"
- LEFT_THOUGHT_BUBBLE = "\U0001f5ec"
- FLAG_FOR_KAPOSVAR_HU_KV = "\U0001f3f4\U000e0068\U000e0075\U000e006b\U000e0076\U000e007f"
- RIGHT_SPEAKER_WITH_THREE_SOUND_WAVES = "\U0001f56a"
- FLAG_FOR_ARIMA_TT_ARI = "\U0001f3f4\U000e0074\U000e0074\U000e0061\U000e0072\U000e0069\U000e007f"
- WHITE_CLUB_SUIT = "\u2667"
- REVERSED_THUMBS_DOWN_SIGN = "\U0001f593"
- BEAMED_EIGHTH_NOTES = "\u266b"
- FLAG_FOR_JUFRA_LY_JU = "\U0001f3f4\U000e006c\U000e0079\U000e006a\U000e0075\U000e007f"
- FLAG_FOR_BAGHLAN_AF_BGL = "\U0001f3f4\U000e0061\U000e0066\U000e0062\U000e0067\U000e006c\U000e007f"
- TAG_RIGHT_PARENTHESIS = "\U000e0029"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FLAG_FOR_OHIO_US_OH = "\U0001f3f4\U000e0075\U000e0073\U000e006f\U000e0068\U000e007f"
- CANCEL_TAG = "\U000e007f"
- FLAG_FOR_ST_MARTIN_FR_MF = "\U0001f3f4\U000e0066\U000e0072\U000e006d\U000e0066\U000e007f"
- RIGHT_HAND_TELEPHONE_RECEIVER = "\U0001f57d"
- COUPLE_WITH_HEART_MAN_MEDIUM_DARK_SKIN_TONE_MAN = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468"
- FLAG_FOR_ASTANA_KZ_AST = "\U0001f3f4\U000e006b\U000e007a\U000e0061\U000e0073\U000e0074\U000e007f"
- FLAG_FOR_EASTERN_SL_E = "\U0001f3f4\U000e0073\U000e006c\U000e0065\U000e007f"
- FLAG_FOR_YALA_TH_95 = "\U0001f3f4\U000e0074\U000e0068\U000e0039\U000e0035\U000e007f"
- FLAG_FOR_AHAL_TM_A = "\U0001f3f4\U000e0074\U000e006d\U000e0061\U000e007f"
- KISS_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb"
- MAHJONG_TILE_SIX_OF_CIRCLES = "\U0001f01e"
- TURNED_BLACK_SHOGI_PIECE = "\u26ca"
- FLAG_FOR_WOQOOYI_GALBEED_SO_WO = "\U0001f3f4\U000e0073\U000e006f\U000e0077\U000e006f\U000e007f"
- COUPLE_WITH_HEART_MAN_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc"
- FLAG_FOR_MAGWAY_MM_03 = "\U0001f3f4\U000e006d\U000e006d\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_SAVANNAKHET_LA_SV = "\U0001f3f4\U000e006c\U000e0061\U000e0073\U000e0076\U000e007f"
- FLAG_FOR_CRETE_GR_M = "\U0001f3f4\U000e0067\U000e0072\U000e006d\U000e007f"
- FLAG_FOR_BIRZAI_LT_06 = "\U0001f3f4\U000e006c\U000e0074\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_NGIWAL_PW_228 = "\U0001f3f4\U000e0070\U000e0077\U000e0032\U000e0032\U000e0038\U000e007f"
- FLAG_FOR_RADOVIS_MK_64 = "\U0001f3f4\U000e006d\U000e006b\U000e0036\U000e0034\U000e007f"
- FLOWER = "\u2698"
- FLAG_FOR_PLANKEN_LI_05 = "\U0001f3f4\U000e006c\U000e0069\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_MANGROVE_CAY_BS_MC = "\U0001f3f4\U000e0062\U000e0073\U000e006d\U000e0063\U000e007f"
- FLAG_FOR_EMBU_KE_06 = "\U0001f3f4\U000e006b\U000e0065\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_FARAH_AF_FRA = "\U0001f3f4\U000e0061\U000e0066\U000e0066\U000e0072\U000e0061\U000e007f"
- THREE_RAYS_BELOW = "\U0001f5e5"
- COUPLE_WITH_HEART_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_THURGAU_CH_TG = "\U0001f3f4\U000e0063\U000e0068\U000e0074\U000e0067\U000e007f"
- FLAG_FOR_KAMPONG_CHAM_KH_3 = "\U0001f3f4\U000e006b\U000e0068\U000e0033\U000e007f"
- FLAG_FOR_LESSER_SUNDA_ISLANDS_ID_NU = "\U0001f3f4\U000e0069\U000e0064\U000e006e\U000e0075\U000e007f"
- FLAG_FOR_BERRY_ISLANDS_BS_BY = "\U0001f3f4\U000e0062\U000e0073\U000e0062\U000e0079\U000e007f"
- TWO_SPEECH_BUBBLES = "\U0001f5ea"
- FLAG_FOR_WEST_GREECE_GR_G = "\U0001f3f4\U000e0067\U000e0072\U000e0067\U000e007f"
- WHITE_SUN = "\U0001f323"
- TAG_ASTERISK = "\U000e002a"
- PAGE_WITH_CIRCLED_TEXT = "\U0001f5df"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FLAG_FOR_OGOOUE_MARITIME_GA_8 = "\U0001f3f4\U000e0067\U000e0061\U000e0038\U000e007f"
- FLAG_FOR_MADEIRA_PT_30 = "\U0001f3f4\U000e0070\U000e0074\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_GURIA_GE_GU = "\U0001f3f4\U000e0067\U000e0065\U000e0067\U000e0075\U000e007f"
- FLAG_FOR_PARA_BR_PA = "\U0001f3f4\U000e0062\U000e0072\U000e0070\U000e0061\U000e007f"
- FAMILY_WOMAN_BABY_BABY = "\U0001f469\u200d\U0001f476\u200d\U0001f476"
- FLAG_FOR_SCHAFFHAUSEN_CH_SH = "\U0001f3f4\U000e0063\U000e0068\U000e0073\U000e0068\U000e007f"
- FLAG_FOR_GHOR_AF_GHO = "\U0001f3f4\U000e0061\U000e0066\U000e0067\U000e0068\U000e006f\U000e007f"
- FLAG_FOR_ARKANSAS_US_AR = "\U0001f3f4\U000e0075\U000e0073\U000e0061\U000e0072\U000e007f"
- FLAG_FOR_DRENTHE_NL_DR = "\U0001f3f4\U000e006e\U000e006c\U000e0064\U000e0072\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_GHAZNI_AF_GHA = "\U0001f3f4\U000e0061\U000e0066\U000e0067\U000e0068\U000e0061\U000e007f"
- FLAG_FOR_OZAMA_DO_40 = "\U0001f3f4\U000e0064\U000e006f\U000e0034\U000e0030\U000e007f"
- FLAG_FOR_HERAT_AF_HER = "\U0001f3f4\U000e0061\U000e0066\U000e0068\U000e0065\U000e0072\U000e007f"
- TAG_DIGIT_FOUR = "\U000e0034"
- FLAG_FOR_NEBRASKA_US_NE = "\U0001f3f4\U000e0075\U000e0073\U000e006e\U000e0065\U000e007f"
- FLAG_FOR_ARICA_Y_PARINACOTA_CL_AP = "\U0001f3f4\U000e0063\U000e006c\U000e0061\U000e0070\U000e007f"
- FLAG_FOR_ZANJAN_IR_11 = "\U0001f3f4\U000e0069\U000e0072\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_BRANDENBURG_DE_BB = "\U0001f3f4\U000e0064\U000e0065\U000e0062\U000e0062\U000e007f"
- FLAG_FOR_BISTRICA_OB_SOTLI_SI_149 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0034\U000e0039\U000e007f"
- MAHJONG_TILE_NORTH_WIND = "\U0001f003"
- FLAG_FOR_ALABAMA_US_AL = "\U0001f3f4\U000e0075\U000e0073\U000e0061\U000e006c\U000e007f"
- FLAG_FOR_AL_RAYYAN_QA_RA = "\U0001f3f4\U000e0071\U000e0061\U000e0072\U000e0061\U000e007f"
- LOWER_RIGHT_PENCIL = "\u270e"
- FLAG_FOR_SKRUNDA_LV_093 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0039\U000e0033\U000e007f"
- NUMBER_SIGN = "#\ufe0f"
- EMPTY_NOTE_PAGE = "\U0001f5c6"
- DIGIT_FOUR = "4\ufe0f"
- FLAG_FOR_KIDAL_ML_8 = "\U0001f3f4\U000e006d\U000e006c\U000e0038\U000e007f"
- FLAG_FOR_BACAU_RO_BC = "\U0001f3f4\U000e0072\U000e006f\U000e0062\U000e0063\U000e007f"
- BACK_OF_ENVELOPE = "\U0001f582"
- MAN_ZOMBIE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9df\U0001f3fc\u200d\u2642\ufe0f"
- FLAG_FOR_BURGENLAND_AT_1 = "\U0001f3f4\U000e0061\U000e0074\U000e0031\U000e007f"
- FLAG_FOR_KAYANGEL_PW_100 = "\U0001f3f4\U000e0070\U000e0077\U000e0031\U000e0030\U000e0030\U000e007f"
- FLAG_FOR_TOPLICA_RS_21 = "\U0001f3f4\U000e0072\U000e0073\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_KRASNODAR_KRAI_RU_KDA = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e0064\U000e0061\U000e007f"
- FLAG_FOR_LAUTEM_TL_LA = "\U0001f3f4\U000e0074\U000e006c\U000e006c\U000e0061\U000e007f"
- UPPER_RIGHT_PENCIL = "\u2710"
- FLAG_FOR_BANGKOK_TH_10 = "\U0001f3f4\U000e0074\U000e0068\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_BOUGAINVILLE_PG_NSB = "\U0001f3f4\U000e0070\U000e0067\U000e006e\U000e0073\U000e0062\U000e007f"
- FLAG_FOR_GRENADINES_VC_06 = "\U0001f3f4\U000e0076\U000e0063\U000e0030\U000e0036\U000e007f"
- WIRED_KEYBOARD = "\U0001f5ae"
- FLAG_FOR_KABUL_AF_KAB = "\U0001f3f4\U000e0061\U000e0066\U000e006b\U000e0061\U000e0062\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_J = "\U000e004a"
- FLAG_FOR_AMAZONAS_CO_AMA = "\U0001f3f4\U000e0063\U000e006f\U000e0061\U000e006d\U000e0061\U000e007f"
- DIGIT_NINE = "9\ufe0f"
- FLAG_FOR_TASMAN_NZ_TAS = "\U0001f3f4\U000e006e\U000e007a\U000e0074\U000e0061\U000e0073\U000e007f"
- FLAG_FOR_STYRIA_AT_6 = "\U0001f3f4\U000e0061\U000e0074\U000e0036\U000e007f"
- FLAG_FOR_GABORONE_BW_GA = "\U0001f3f4\U000e0062\U000e0077\U000e0067\U000e0061\U000e007f"
- FLAG_FOR_SAINT_MARK_GD_05 = "\U0001f3f4\U000e0067\U000e0064\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_VALLE_DEL_CAUCA_CO_VAC = "\U0001f3f4\U000e0063\U000e006f\U000e0076\U000e0061\U000e0063\U000e007f"
- FLAG_FOR_KHAKASSIA_RU_KK = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e006b\U000e007f"
- FLAG_FOR_MISRATA_LY_MI = "\U0001f3f4\U000e006c\U000e0079\U000e006d\U000e0069\U000e007f"
- FLAG_FOR_QUEENSLAND_AU_QLD = "\U0001f3f4\U000e0061\U000e0075\U000e0071\U000e006c\U000e0064\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FLAG_FOR_OSAKA_JP_27 = "\U0001f3f4\U000e006a\U000e0070\U000e0032\U000e0037\U000e007f"
- FLAG_FOR_MICHOACAN_MX_MIC = "\U0001f3f4\U000e006d\U000e0078\U000e006d\U000e0069\U000e0063\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FAMILY_MAN_WOMAN_BOY_GIRL = "\U0001f468\u200d\U0001f469\u200d\U0001f466\u200d\U0001f467"
- KISS_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe"
- BLACK_UP_POINTING_BACKHAND_INDEX = "\U0001f5a2"
- RIGHT_SPEAKER = "\U0001f568"
- COMBINING_ENCLOSING_KEYCAP = "\u20e3"
- FLAG_FOR_AZUAY_EC_A = "\U0001f3f4\U000e0065\U000e0063\U000e0061\U000e007f"
- FLAG_FOR_LUHANSHCHYNA_UA_09 = "\U0001f3f4\U000e0075\U000e0061\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_MAHARASHTRA_IN_MH = "\U0001f3f4\U000e0069\U000e006e\U000e006d\U000e0068\U000e007f"
- UPPER_RIGHT_SHADOWED_WHITE_CIRCLE = "\U0001f53f"
- FLAG_FOR_INSULAR_GQ_I = "\U0001f3f4\U000e0067\U000e0071\U000e0069\U000e007f"
- JUPITER = "\u2643"
- FLAG_FOR_AKKAR_LB_AK = "\U0001f3f4\U000e006c\U000e0062\U000e0061\U000e006b\U000e007f"
- FLAG_FOR_SOHAG_EG_SHG = "\U0001f3f4\U000e0065\U000e0067\U000e0073\U000e0068\U000e0067\U000e007f"
- FLAG_FOR_MOHELI_KM_M = "\U0001f3f4\U000e006b\U000e006d\U000e006d\U000e007f"
- FLAG_FOR_AL_AHMADI_KW_AH = "\U0001f3f4\U000e006b\U000e0077\U000e0061\U000e0068\U000e007f"
- WOMAN_IN_TUXEDO_LIGHT_SKIN_TONE = "\U0001f935\U0001f3fb\u200d\u2640\ufe0f"
- FLAG_FOR_GUADALCANAL_SB_GU = "\U0001f3f4\U000e0073\U000e0062\U000e0067\U000e0075\U000e007f"
- FLAG_FOR_CIBITOKE_BI_CI = "\U0001f3f4\U000e0062\U000e0069\U000e0063\U000e0069\U000e007f"
- WOMAN_ZOMBIE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9df\U0001f3fc\u200d\u2640\ufe0f"
- FLAG_FOR_BAS_UELE_CD_BU = "\U0001f3f4\U000e0063\U000e0064\U000e0062\U000e0075\U000e007f"
- FLAG_FOR_NEVIS_KN_N = "\U0001f3f4\U000e006b\U000e006e\U000e006e\U000e007f"
- FLAG_FOR_BONAIRE_BQ_BO = "\U0001f3f4\U000e0062\U000e0071\U000e0062\U000e006f\U000e007f"
- FLAG_FOR_ANCASH_PE_ANC = "\U0001f3f4\U000e0070\U000e0065\U000e0061\U000e006e\U000e0063\U000e007f"
- CAR_SLIDING = "\u26d0"
- DIGRAM_FOR_LESSER_YANG = "\u268e"
- THREE_NETWORKED_COMPUTERS = "\U0001f5a7"
- FLAG_FOR_ASUNCION_PY_ASU = "\U0001f3f4\U000e0070\U000e0079\U000e0061\U000e0073\U000e0075\U000e007f"
- CROSS_POMMEE_WITH_HALF_CIRCLE_BELOW = "\U0001f541"
- FLAG_FOR_TOLIMA_CO_TOL = "\U0001f3f4\U000e0063\U000e006f\U000e0074\U000e006f\U000e006c\U000e007f"
- TAG_DIGIT_ONE = "\U000e0031"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_JEWISH_RU_YEV = "\U0001f3f4\U000e0072\U000e0075\U000e0079\U000e0065\U000e0076\U000e007f"
- FLAG_FOR_LA_PAZ_HN_LP = "\U0001f3f4\U000e0068\U000e006e\U000e006c\U000e0070\U000e007f"
- FLAG_FOR_RIO_SAN_JUAN_NI_SJ = "\U0001f3f4\U000e006e\U000e0069\U000e0073\U000e006a\U000e007f"
- FLAG_FOR_PAYS_DE_LA_LOIRE_FR_PDL = "\U0001f3f4\U000e0066\U000e0072\U000e0070\U000e0064\U000e006c\U000e007f"
- FLAG_FOR_RIVERS_NG_RI = "\U0001f3f4\U000e006e\U000e0067\U000e0072\U000e0069\U000e007f"
- OLD_PERSONAL_COMPUTER = "\U0001f5b3"
- FLAG_FOR_DAEGU_KR_27 = "\U0001f3f4\U000e006b\U000e0072\U000e0032\U000e0037\U000e007f"
- EMPTY_NOTE_PAD = "\U0001f5c7"
- FLAG_FOR_SHAN_MM_17 = "\U0001f3f4\U000e006d\U000e006d\U000e0031\U000e0037\U000e007f"
- BLACK_FLAG_2 = "\u2691"
- MAHJONG_TILE_SEVEN_OF_CHARACTERS = "\U0001f00d"
- FAMILY_MAN_BOY_GIRL = "\U0001f468\u200d\U0001f466\u200d\U0001f467"
- FLAG_FOR_ADANA_TR_01 = "\U0001f3f4\U000e0074\U000e0072\U000e0030\U000e0031\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_C = "\U000e0043"
- TWO_BUTTON_MOUSE = "\U0001f5b0"
- ASTERISK = "*\ufe0f"
- MAHJONG_TILE_FOUR_OF_CIRCLES = "\U0001f01c"
- FLAG_FOR_KAPISA_AF_KAP = "\U0001f3f4\U000e0061\U000e0066\U000e006b\U000e0061\U000e0070\U000e007f"
- FLAG_FOR_MON_MM_15 = "\U0001f3f4\U000e006d\U000e006d\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_AL_BURAIMI_OM_BU = "\U0001f3f4\U000e006f\U000e006d\U000e0062\U000e0075\U000e007f"
- FLAG_FOR_AGALEGA_MU_AG = "\U0001f3f4\U000e006d\U000e0075\U000e0061\U000e0067\U000e007f"
- ONE_BUTTON_MOUSE = "\U0001f5af"
- FLAG_FOR_LOGAR_AF_LOG = "\U0001f3f4\U000e0061\U000e0066\U000e006c\U000e006f\U000e0067\U000e007f"
- FLAG_FOR_BEL_OMBRE_SC_10 = "\U0001f3f4\U000e0073\U000e0063\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_ORANGE_WALK_BZ_OW = "\U0001f3f4\U000e0062\U000e007a\U000e006f\U000e0077\U000e007f"
- MALE_WITH_STROKE_AND_MALE_AND_FEMALE_SIGN = "\u26a7"
- FLAG_FOR_KANDAHAR_AF_KAN = "\U0001f3f4\U000e0061\U000e0066\U000e006b\U000e0061\U000e006e\U000e007f"
- TAPE_CARTRIDGE = "\U0001f5ad"
- FLAG_FOR_ULAANBAATAR_MN_1 = "\U0001f3f4\U000e006d\U000e006e\U000e0031\U000e007f"
- FLAG_FOR_FARYAB_AF_FYB = "\U0001f3f4\U000e0061\U000e0066\U000e0066\U000e0079\U000e0062\U000e007f"
- TAG_LATIN_SMALL_LETTER_F = "\U000e0066"
- FLAG_FOR_PARWAN_AF_PAR = "\U0001f3f4\U000e0061\U000e0066\U000e0070\U000e0061\U000e0072\U000e007f"
- FLAG_FOR_NIMRUZ_AF_NIM = "\U0001f3f4\U000e0061\U000e0066\U000e006e\U000e0069\U000e006d\U000e007f"
- FLAG_FOR_HIIU_EE_39 = "\U0001f3f4\U000e0065\U000e0065\U000e0033\U000e0039\U000e007f"
- FLAG_FOR_EXTREMADURA_ES_EX = "\U0001f3f4\U000e0065\U000e0073\U000e0065\U000e0078\U000e007f"
- FLAG_FOR_SABA_BQ_SA = "\U0001f3f4\U000e0062\U000e0071\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_KARLOVAC_HR_04 = "\U0001f3f4\U000e0068\U000e0072\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_BROD_POSAVINA_HR_12 = "\U0001f3f4\U000e0068\U000e0072\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_NANGARHAR_AF_NAN = "\U0001f3f4\U000e0061\U000e0066\U000e006e\U000e0061\U000e006e\U000e007f"
- MAHJONG_TILE_SEVEN_OF_CIRCLES = "\U0001f01f"
- TRIGRAM_FOR_HEAVEN = "\u2630"
- DIGIT_SEVEN = "7\ufe0f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc"
- RECYCLING_SYMBOL_FOR_TYPE_1_PLASTICS = "\u2673"
- FLAG_FOR_CORSE_FR_COR = "\U0001f3f4\U000e0066\U000e0072\U000e0063\U000e006f\U000e0072\U000e007f"
- MAN_WITH_HEADSCARF_MEDIUM_SKIN_TONE = "\U0001f9d5\U0001f3fd\u200d\u2642\ufe0f"
- FLAG_FOR_HAMADAN_IR_24 = "\U0001f3f4\U000e0069\U000e0072\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_FARS_IR_14 = "\U0001f3f4\U000e0069\U000e0072\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_FRENCH_GUIANA_FR_GF = "\U0001f3f4\U000e0066\U000e0072\U000e0067\U000e0066\U000e007f"
- FLAG_FOR_TICINO_CH_TI = "\U0001f3f4\U000e0063\U000e0068\U000e0074\U000e0069\U000e007f"
- FLAG_FOR_BOR_RS_14 = "\U0001f3f4\U000e0072\U000e0073\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_UTTARADIT_TH_53 = "\U0001f3f4\U000e0074\U000e0068\U000e0035\U000e0033\U000e007f"
- TAG_LATIN_SMALL_LETTER_M = "\U000e006d"
- FLAG_FOR_BAMAKO_ML_BKO = "\U0001f3f4\U000e006d\U000e006c\U000e0062\U000e006b\U000e006f\U000e007f"
- FLAG_FOR_ESPIRITO_SANTO_BR_ES = "\U0001f3f4\U000e0062\U000e0072\U000e0065\U000e0073\U000e007f"
- TAG_LATIN_SMALL_LETTER_R = "\U000e0072"
- FLAG_FOR_BOLIKHAMSAI_LA_BL = "\U0001f3f4\U000e006c\U000e0061\U000e0062\U000e006c\U000e007f"
- BULLHORN_WITH_SOUND_WAVES = "\U0001f56c"
- FLAG_FOR_HALLAND_SE_N = "\U0001f3f4\U000e0073\U000e0065\U000e006e\U000e007f"
- FLAG_FOR_UPPER_DEMERARA_BERBICE_GY_UD = "\U0001f3f4\U000e0067\U000e0079\U000e0075\U000e0064\U000e007f"
- WOMAN_ZOMBIE_MEDIUM_SKIN_TONE = "\U0001f9df\U0001f3fd\u200d\u2640\ufe0f"
- FLAG_FOR_ZIROVNICA_SI_192 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0039\U000e0032\U000e007f"
- FLAG_FOR_TAITUNG_TW_TTT = "\U0001f3f4\U000e0074\U000e0077\U000e0074\U000e0074\U000e0074\U000e007f"
- FLAG_FOR_NANUMANGA_TV_NMG = "\U0001f3f4\U000e0074\U000e0076\U000e006e\U000e006d\U000e0067\U000e007f"
- FLAG_FOR_TUNAPUNA_PIARCO_TT_TUP = "\U0001f3f4\U000e0074\U000e0074\U000e0074\U000e0075\U000e0070\U000e007f"
- TAG_DIGIT_SEVEN = "\U000e0037"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe"
- KEYBOARD_AND_MOUSE = "\U0001f5a6"
- MAHJONG_TILE_GREEN_DRAGON = "\U0001f005"
- FLAG_FOR_CEUTA_ES_CE = "\U0001f3f4\U000e0065\U000e0073\U000e0063\U000e0065\U000e007f"
- KISS_MAN_MEDIUM_SKIN_TONE_WOMAN = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469"
- FLAG_FOR_SABARAGAMUWA_LK_9 = "\U0001f3f4\U000e006c\U000e006b\U000e0039\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f466\U0001f3fe"
- COUPLE_WITH_HEART_MAN_LIGHT_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_BUTNAN_LY_BU = "\U0001f3f4\U000e006c\U000e0079\U000e0062\U000e0075\U000e007f"
- FLAG_FOR_COLIMA_MX_COL = "\U0001f3f4\U000e006d\U000e0078\U000e0063\U000e006f\U000e006c\U000e007f"
- FLAG_FOR_QUEBEC_CA_QC = "\U0001f3f4\U000e0063\U000e0061\U000e0071\U000e0063\U000e007f"
- WHITE_DOWN_POINTING_INDEX = "\u261f"
- FLAG_FOR_CUNDINAMARCA_CO_CUN = "\U0001f3f4\U000e0063\U000e006f\U000e0063\U000e0075\U000e006e\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_D = "\U000e0044"
- FLAG_FOR_DAMASCUS_SY_DI = "\U0001f3f4\U000e0073\U000e0079\U000e0064\U000e0069\U000e007f"
- FLAG_FOR_DUBAI_AE_DU = "\U0001f3f4\U000e0061\U000e0065\U000e0064\U000e0075\U000e007f"
- SHIBUYA = "\ue50a"
- FLAG_FOR_KAYES_ML_1 = "\U0001f3f4\U000e006d\U000e006c\U000e0031\U000e007f"
- FLAG_FOR_CEARA_BR_CE = "\U0001f3f4\U000e0062\U000e0072\U000e0063\U000e0065\U000e007f"
- FLAG_FOR_SHARJAH_AE_SH = "\U0001f3f4\U000e0061\U000e0065\U000e0073\U000e0068\U000e007f"
- FLAG_FOR_EASTERN_IS_7 = "\U0001f3f4\U000e0069\U000e0073\U000e0037\U000e007f"
- WHITE_CHESS_BISHOP = "\u2657"
- FLAG_FOR_AFAR_ET_AF = "\U0001f3f4\U000e0065\U000e0074\U000e0061\U000e0066\U000e007f"
- TAG_QUESTION_MARK = "\U000e003f"
- FAMILY_WOMAN_GIRL_BABY = "\U0001f469\u200d\U0001f467\u200d\U0001f476"
- FLAG_FOR_RADENCI_SI_100 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0030\U000e0030\U000e007f"
- FLAG_FOR_LIMA_REGION_PE_LIM = "\U0001f3f4\U000e0070\U000e0065\U000e006c\U000e0069\U000e006d\U000e007f"
- FLAG_FOR_NORTH_CENTRAL_PROVINCE_MV_NC = "\U0001f3f4\U000e006d\U000e0076\U000e006e\U000e0063\U000e007f"
- DOCUMENT_WITH_PICTURE = "\U0001f5bb"
- FLAG_FOR_VALAIS_CH_VS = "\U0001f3f4\U000e0063\U000e0068\U000e0076\U000e0073\U000e007f"
- FLAG_FOR_BAY_OF_PLENTY_NZ_BOP = "\U0001f3f4\U000e006e\U000e007a\U000e0062\U000e006f\U000e0070\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_P = "\U000e0050"
- FLAG_FOR_BASSE_KOTTO_CF_BK = "\U0001f3f4\U000e0063\U000e0066\U000e0062\U000e006b\U000e007f"
- DOCUMENT_WITH_TEXT_AND_PICTURE = "\U0001f5ba"
- TAG_DIGIT_NINE = "\U000e0039"
- WOMAN_IN_TUXEDO_MEDIUM_DARK_SKIN_TONE = "\U0001f935\U0001f3fe\u200d\u2640\ufe0f"
- FLAG_FOR_ZURICH_CH_ZH = "\U0001f3f4\U000e0063\U000e0068\U000e007a\U000e0068\U000e007f"
- MAHJONG_TILE_THREE_OF_CIRCLES = "\U0001f01b"
- FLAG_FOR_LOG_DRAGOMER_SI_208 = "\U0001f3f4\U000e0073\U000e0069\U000e0032\U000e0030\U000e0038\U000e007f"
- MAN_ZOMBIE_DARK_SKIN_TONE = "\U0001f9df\U0001f3ff\u200d\u2642\ufe0f"
- FLAG_FOR_ARIZONA_US_AZ = "\U0001f3f4\U000e0075\U000e0073\U000e0061\U000e007a\U000e007f"
- FLAG_FOR_PAKTIKA_AF_PKA = "\U0001f3f4\U000e0061\U000e0066\U000e0070\U000e006b\U000e0061\U000e007f"
- PROHIBITED_SIGN = "\U0001f6c7"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb"
- FLAG_FOR_ALASKA_US_AK = "\U0001f3f4\U000e0075\U000e0073\U000e0061\U000e006b\U000e007f"
- FLAG_FOR_SOOL_SO_SO = "\U0001f3f4\U000e0073\U000e006f\U000e0073\U000e006f\U000e007f"
- FLAG_FOR_LAGHMAN_AF_LAG = "\U0001f3f4\U000e0061\U000e0066\U000e006c\U000e0061\U000e0067\U000e007f"
- BLACK_CIRCLE_WITH_TWO_WHITE_DOTS = "\u2689"
- FLAG_FOR_NUKULAELAE_TV_NKL = "\U0001f3f4\U000e0074\U000e0076\U000e006e\U000e006b\U000e006c\U000e007f"
- FLAG_FOR_ABKHAZIA_GE_AB = "\U0001f3f4\U000e0067\U000e0065\U000e0061\U000e0062\U000e007f"
- FLAG_FOR_ESCH_SUR_ALZETTE_LU_ES = "\U0001f3f4\U000e006c\U000e0075\U000e0065\U000e0073\U000e007f"
- FLAG_FOR_MANIPUR_IN_MN = "\U0001f3f4\U000e0069\U000e006e\U000e006d\U000e006e\U000e007f"
- FLAG_FOR_HELMAND_AF_HEL = "\U0001f3f4\U000e0061\U000e0066\U000e0068\U000e0065\U000e006c\U000e007f"
- FLAG_FOR_VICHADA_CO_VID = "\U0001f3f4\U000e0063\U000e006f\U000e0076\U000e0069\U000e0064\U000e007f"
- DOCUMENT = "\U0001f5ce"
- FLAG_FOR_ISLAMABAD_PK_IS = "\U0001f3f4\U000e0070\U000e006b\U000e0069\U000e0073\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FLAG_FOR_RAS_AL_KHAIMAH_AE_RK = "\U0001f3f4\U000e0061\U000e0065\U000e0072\U000e006b\U000e007f"
- FAMILY_MAN_BABY = "\U0001f468\u200d\U0001f476"
- FLAG_FOR_KONYA_TR_42 = "\U0001f3f4\U000e0074\U000e0072\U000e0034\U000e0032\U000e007f"
- FLAG_FOR_CANKIRI_TR_18 = "\U0001f3f4\U000e0074\U000e0072\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_GANJA_AZ_GA = "\U0001f3f4\U000e0061\U000e007a\U000e0067\U000e0061\U000e007f"
- MAHJONG_TILE_SIX_OF_CHARACTERS = "\U0001f00c"
- TAG_LATIN_CAPITAL_LETTER_M = "\U000e004d"
- FLAG_FOR_OITA_JP_44 = "\U0001f3f4\U000e006a\U000e0070\U000e0034\U000e0034\U000e007f"
- FLAG_FOR_GUATEMALA_GT_GU = "\U0001f3f4\U000e0067\U000e0074\U000e0067\U000e0075\U000e007f"
- FLAG_FOR_NORTH_BRABANT_NL_NB = "\U0001f3f4\U000e006e\U000e006c\U000e006e\U000e0062\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f476\U0001f3fb"
- KISS_WOMAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_GILBERT_ISLANDS_KI_G = "\U0001f3f4\U000e006b\U000e0069\U000e0067\U000e007f"
- FLAG_FOR_PAKTIA_AF_PIA = "\U0001f3f4\U000e0061\U000e0066\U000e0070\U000e0069\U000e0061\U000e007f"
- FLAG_FOR_PARDUBICKY_KRAJ_CZ_53 = "\U0001f3f4\U000e0063\U000e007a\U000e0035\U000e0033\U000e007f"
- FLAG_FOR_SALCININKAI_LT_42 = "\U0001f3f4\U000e006c\U000e0074\U000e0034\U000e0032\U000e007f"
- BALLOT_BOX_WITH_BOLD_CHECK = "\U0001f5f9"
- FLAG_FOR_CORUM_TR_19 = "\U0001f3f4\U000e0074\U000e0072\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_SAMANGAN_AF_SAM = "\U0001f3f4\U000e0061\U000e0066\U000e0073\U000e0061\U000e006d\U000e007f"
- FLAG_FOR_MASAYA_NI_MS = "\U0001f3f4\U000e006e\U000e0069\U000e006d\U000e0073\U000e007f"
- FLAG_FOR_CSONGRAD_HU_CS = "\U0001f3f4\U000e0068\U000e0075\U000e0063\U000e0073\U000e007f"
- FLAG_FOR_AKSARAY_TR_68 = "\U0001f3f4\U000e0074\U000e0072\U000e0036\U000e0038\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_SAINT_MARY_AG_05 = "\U0001f3f4\U000e0061\U000e0067\U000e0030\U000e0035\U000e007f"
- WOMAN_IN_BUSINESS_SUIT_LEVITATING_DARK_SKIN_TONE = "\U0001f574\U0001f3ff\u200d\u2640\ufe0f"
- TAG_COMMERCIAL_AT = "\U000e0040"
- FLAG_FOR_BERANE_ME_03 = "\U0001f3f4\U000e006d\U000e0065\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_MARYLAND_LR_MY = "\U0001f3f4\U000e006c\U000e0072\U000e006d\U000e0079\U000e007f"
- FLAG_FOR_KARA_TG_K = "\U0001f3f4\U000e0074\U000e0067\U000e006b\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f466\U0001f3fe"
- OPTICAL_DISC_ICON = "\U0001f5b8"
- FLAG_FOR_MASCARA_DZ_29 = "\U0001f3f4\U000e0064\U000e007a\U000e0032\U000e0039\U000e007f"
- THREE_RAYS_LEFT = "\U0001f5e6"
- RECYCLING_SYMBOL_FOR_TYPE_3_PLASTICS = "\u2675"
- FLAG_FOR_REDONDA_AG_11 = "\U0001f3f4\U000e0061\U000e0067\U000e0031\U000e0031\U000e007f"
- FAX_ICON = "\U0001f5b7"
- FLAG_FOR_GAGAUZIA_MD_GA = "\U0001f3f4\U000e006d\U000e0064\U000e0067\U000e0061\U000e007f"
- THREE_SPEECH_BUBBLES = "\U0001f5eb"
- TAG_LATIN_SMALL_LETTER_S = "\U000e0073"
- FLAG_FOR_WAKAYAMA_JP_30 = "\U0001f3f4\U000e006a\U000e0070\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_SZEKSZARD_HU_SS = "\U0001f3f4\U000e0068\U000e0075\U000e0073\U000e0073\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f466\U0001f3fb"
- OVERLAP = "\U0001f5d7"
- FLAG_FOR_HSINCHU_COUNTY_TW_HSQ = "\U0001f3f4\U000e0074\U000e0077\U000e0068\U000e0073\U000e0071\U000e007f"
- MAHJONG_TILE_EAST_WIND = "\U0001f000"
- FLAG_FOR_GOMBE_NG_GO = "\U0001f3f4\U000e006e\U000e0067\U000e0067\U000e006f\U000e007f"
- FLAG_FOR_VILNIUS_LT_58 = "\U0001f3f4\U000e006c\U000e0074\U000e0035\U000e0038\U000e007f"
- TAG_LATIN_SMALL_LETTER_O = "\U000e006f"
- PAGE = "\U0001f5cf"
- STOCK_CHART = "\U0001f5e0"
- FLAG_FOR_SAINT_JOHN_AG_04 = "\U0001f3f4\U000e0061\U000e0067\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_VERMONT_US_VT = "\U0001f3f4\U000e0075\U000e0073\U000e0076\U000e0074\U000e007f"
- FLAG_FOR_MURCIA_REGION_ES_MC = "\U0001f3f4\U000e0065\U000e0073\U000e006d\U000e0063\U000e007f"
- FLAG_FOR_PWANI_TZ_19 = "\U0001f3f4\U000e0074\U000e007a\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_SOMALI_ET_SO = "\U0001f3f4\U000e0065\U000e0074\U000e0073\U000e006f\U000e007f"
- MAN_WITH_HEADSCARF_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d5\U0001f3fc\u200d\u2642\ufe0f"
- DESKTOP_WINDOW = "\U0001f5d4"
- FLAG_FOR_MADONA_LV_059 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0035\U000e0039\U000e007f"
- FLAG_FOR_SING_BURI_TH_17 = "\U0001f3f4\U000e0074\U000e0068\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_MOKA_MU_MO = "\U0001f3f4\U000e006d\U000e0075\U000e006d\U000e006f\U000e007f"
- KISS_MAN_LIGHT_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f466\U0001f3fc"
- BLACK_LEFT_POINTING_BACKHAND_INDEX = "\U0001f59c"
- REVERSED_VICTORY_HAND = "\U0001f594"
- FAMILY_WOMAN_WOMAN_BABY = "\U0001f469\u200d\U0001f469\u200d\U0001f476"
- FLAG_FOR_MICOUD_LC_08 = "\U0001f3f4\U000e006c\U000e0063\U000e0030\U000e0038\U000e007f"
- TRIGRAM_FOR_MOUNTAIN = "\u2636"
- WOMAN_WITH_HEADSCARF_2 = "\U0001f9d5\u200d\u2640\ufe0f"
- FLAG_FOR_MARCHE_IT_57 = "\U0001f3f4\U000e0069\U000e0074\U000e0035\U000e0037\U000e007f"
- MAHJONG_TILE_FIVE_OF_CIRCLES = "\U0001f01d"
- FLAG_FOR_COVA_LIMA_TL_CO = "\U0001f3f4\U000e0074\U000e006c\U000e0063\U000e006f\U000e007f"
- KISS_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468"
- FAMILY_MAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_BEL_AIR_SC_09 = "\U0001f3f4\U000e0073\U000e0063\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_VILA_REAL_PT_17 = "\U0001f3f4\U000e0070\U000e0074\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_MACAU_SAR_CHINA_CN_92 = "\U0001f3f4\U000e0063\U000e006e\U000e0039\U000e0032\U000e007f"
- FLAG_FOR_SOUTH_DAKOTA_US_SD = "\U0001f3f4\U000e0075\U000e0073\U000e0073\U000e0064\U000e007f"
- FLAG_FOR_WEST_PANAMA_PA_10 = "\U0001f3f4\U000e0070\U000e0061\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_CHIAPAS_MX_CHP = "\U0001f3f4\U000e006d\U000e0078\U000e0063\U000e0068\U000e0070\U000e007f"
- FLAG_FOR_KUKES_COUNTY_AL_07 = "\U0001f3f4\U000e0061\U000e006c\U000e0030\U000e0037\U000e007f"
- PAGES = "\U0001f5d0"
- TAG_LATIN_CAPITAL_LETTER_L = "\U000e004c"
- EMPTY_PAGES = "\U0001f5cd"
- FLAG_FOR_SVETA_ANA_SI_181 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0038\U000e0031\U000e007f"
- FLAG_FOR_SKRIVERI_LV_092 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0039\U000e0032\U000e007f"
- FLAG_FOR_KITUI_KE_18 = "\U0001f3f4\U000e006b\U000e0065\U000e0031\U000e0038\U000e007f"
- FIRST_QUARTER_MOON_2 = "\u263d"
- FLAG_FOR_PELELIU_PW_350 = "\U0001f3f4\U000e0070\U000e0077\U000e0033\U000e0035\U000e0030\U000e007f"
- FLAG_FOR_MARY_TM_M = "\U0001f3f4\U000e0074\U000e006d\U000e006d\U000e007f"
- FLAG_FOR_UPPER_SOUTH_PROVINCE_MV_US = "\U0001f3f4\U000e006d\U000e0076\U000e0075\U000e0073\U000e007f"
- FLAG_FOR_MAKKAH_SA_02 = "\U0001f3f4\U000e0073\U000e0061\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_ZEBBUG_GOZO_MT_65 = "\U0001f3f4\U000e006d\U000e0074\U000e0036\U000e0035\U000e007f"
- FLAG_FOR_OSMANIYE_TR_80 = "\U0001f3f4\U000e0074\U000e0072\U000e0038\U000e0030\U000e007f"
- BLACK_TWO_WAY_LEFT_WAY_TRAFFIC = "\u26d6"
- FLAG_FOR_LAGOS_NG_LA = "\U0001f3f4\U000e006e\U000e0067\U000e006c\U000e0061\U000e007f"
- MAHJONG_TILE_JOKER = "\U0001f02a"
- FLAG_FOR_KARS_TR_36 = "\U0001f3f4\U000e0074\U000e0072\U000e0033\U000e0036\U000e007f"
- FLAG_FOR_NAYARIT_MX_NAY = "\U0001f3f4\U000e006d\U000e0078\U000e006e\U000e0061\U000e0079\U000e007f"
- CUP_ON_BLACK_SQUARE = "\u26fe"
- FLAG_FOR_RIVERCESS_LR_RI = "\U0001f3f4\U000e006c\U000e0072\U000e0072\U000e0069\U000e007f"
- THREE_RAYS_ABOVE = "\U0001f5e4"
- FLAG_FOR_UABOE_NR_13 = "\U0001f3f4\U000e006e\U000e0072\U000e0031\U000e0033\U000e007f"
- TAG_LATIN_SMALL_LETTER_P = "\U000e0070"
- FLAG_FOR_MGARR_MT_31 = "\U0001f3f4\U000e006d\U000e0074\U000e0033\U000e0031\U000e007f"
- FLAG_FOR_SALAVAN_LA_SL = "\U0001f3f4\U000e006c\U000e0061\U000e0073\U000e006c\U000e007f"
- FLAG_FOR_AJMAN_AE_AJ = "\U0001f3f4\U000e0061\U000e0065\U000e0061\U000e006a\U000e007f"
- FLAG_FOR_DEMIR_KAPIJA_MK_24 = "\U0001f3f4\U000e006d\U000e006b\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_KHABAROVSK_KRAI_RU_KHA = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e0068\U000e0061\U000e007f"
- COUPLE_WITH_HEART_MAN_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_WEST_KAZAKHSTAN_KZ_ZAP = "\U0001f3f4\U000e006b\U000e007a\U000e007a\U000e0061\U000e0070\U000e007f"
- TAG_LATIN_SMALL_LETTER_W = "\U000e0077"
- ADI_SHAKTI = "\u262c"
- BOYS_SYMBOL = "\U0001f6c9"
- FLAG_FOR_NORTHERN_BAHR_EL_GHAZAL_SS_BN = "\U0001f3f4\U000e0073\U000e0073\U000e0062\U000e006e\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FLAG_FOR_LINDI_TZ_12 = "\U0001f3f4\U000e0074\U000e007a\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_KUNAR_AF_KNR = "\U0001f3f4\U000e0061\U000e0066\U000e006b\U000e006e\U000e0072\U000e007f"
- FOLDER = "\U0001f5c0"
- COUPLE_WITH_HEART_MAN_MAN_LIGHT_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb"
- TAG_NUMBER_SIGN = "\U000e0023"
- FLAG_FOR_VALENCIAN_COMMUNITY_ES_VC = "\U0001f3f4\U000e0065\U000e0073\U000e0076\U000e0063\U000e007f"
- TAG_RIGHT_CURLY_BRACKET = "\U000e007d"
- FLAG_FOR_SAINT_PAUL_AG_06 = "\U0001f3f4\U000e0061\U000e0067\U000e0030\U000e0036\U000e007f"
- WOMAN_IN_TUXEDO = "\U0001f935\u200d\u2640\ufe0f"
- FLAG_FOR_SICILY_IT_82 = "\U0001f3f4\U000e0069\U000e0074\U000e0038\U000e0032\U000e007f"
- FLAG_FOR_LEZHE_COUNTY_AL_08 = "\U0001f3f4\U000e0061\U000e006c\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_CHIHUAHUA_MX_CHH = "\U0001f3f4\U000e006d\U000e0078\U000e0063\U000e0068\U000e0068\U000e007f"
- BLACK_RIGHT_POINTING_BACKHAND_INDEX = "\U0001f59d"
- WHITE_LATIN_CROSS = "\U0001f546"
- FLAG_FOR_NORD_OUEST_HT_NO = "\U0001f3f4\U000e0068\U000e0074\U000e006e\U000e006f\U000e007f"
- DIGIT_ONE = "1\ufe0f"
- PORTABLE_STEREO = "\U0001f4fe"
- FLAG_FOR_MADINAT_ASH_SHAMAL_QA_MS = "\U0001f3f4\U000e0071\U000e0061\U000e006d\U000e0073\U000e007f"
- BULLHORN = "\U0001f56b"
- TAG_DIGIT_SIX = "\U000e0036"
- FLAG_FOR_SIKKIM_IN_SK = "\U0001f3f4\U000e0069\U000e006e\U000e0073\U000e006b\U000e007f"
- CANCELLATION_X = "\U0001f5d9"
- LEFT_WRITING_HAND = "\U0001f58e"
- MAHJONG_TILE_FOUR_OF_CHARACTERS = "\U0001f00a"
- RINGING_BELL = "\U0001f56d"
- FLAG_FOR_TIRANA_COUNTY_AL_11 = "\U0001f3f4\U000e0061\U000e006c\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_TRAT_TH_23 = "\U0001f3f4\U000e0074\U000e0068\U000e0032\U000e0033\U000e007f"
- TAG_LATIN_SMALL_LETTER_D = "\U000e0064"
- FLAG_FOR_SAMARA_RU_SAM = "\U0001f3f4\U000e0072\U000e0075\U000e0073\U000e0061\U000e006d\U000e007f"
- FLAG_FOR_NGOUNIE_GA_4 = "\U0001f3f4\U000e0067\U000e0061\U000e0034\U000e007f"
- BLACK_ROSETTE = "\U0001f3f6"
- TAG_CIRCUMFLEX_ACCENT = "\U000e005e"
- FLAG_FOR_IASI_RO_IS = "\U0001f3f4\U000e0072\U000e006f\U000e0069\U000e0073\U000e007f"
- FLAG_FOR_GEORGIA_US_GA = "\U0001f3f4\U000e0075\U000e0073\U000e0067\U000e0061\U000e007f"
- FLAG_FOR_DURRES_COUNTY_AL_02 = "\U0001f3f4\U000e0061\U000e006c\U000e0030\U000e0032\U000e007f"
- KISS_MAN_LIGHT_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_TAZA_AL_HOCEIMA_TAOUNATE_MA_03 = "\U0001f3f4\U000e006d\U000e0061\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_LOMBARDY_IT_25 = "\U0001f3f4\U000e0069\U000e0074\U000e0032\U000e0035\U000e007f"
- FLAG_FOR_TRABZON_TR_61 = "\U0001f3f4\U000e0074\U000e0072\U000e0036\U000e0031\U000e007f"
- FLAG_FOR_UROZGAN_AF_URU = "\U0001f3f4\U000e0061\U000e0066\U000e0075\U000e0072\U000e0075\U000e007f"
- FLAG_FOR_CENTRAL_GH_CP = "\U0001f3f4\U000e0067\U000e0068\U000e0063\U000e0070\U000e007f"
- WOMAN_ZOMBIE_LIGHT_SKIN_TONE = "\U0001f9df\U0001f3fb\u200d\u2640\ufe0f"
- MAHJONG_TILE_SUMMER = "\U0001f027"
- FLAG_FOR_KIDRICEVO_SI_045 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0034\U000e0035\U000e007f"
- FLAG_FOR_RAZAVI_KHORASAN_IR_30 = "\U0001f3f4\U000e0069\U000e0072\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_KOTAYK_AM_KT = "\U0001f3f4\U000e0061\U000e006d\U000e006b\U000e0074\U000e007f"
- TELEPHONE_RECEIVER_WITH_PAGE = "\U0001f57c"
- FLAG_FOR_SHKODER_COUNTY_AL_10 = "\U0001f3f4\U000e0061\U000e006c\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_AL_WAKRAH_QA_WA = "\U0001f3f4\U000e0071\U000e0061\U000e0077\U000e0061\U000e007f"
- TAG_LATIN_SMALL_LETTER_U = "\U000e0075"
- FLAG_FOR_CHACO_AR_H = "\U0001f3f4\U000e0061\U000e0072\U000e0068\U000e007f"
- BLACK_HARD_SHELL_FLOPPY_DISK = "\U0001f5aa"
- FAMILY_MAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FLAG_FOR_HOKKAIDO_JP_01 = "\U0001f3f4\U000e006a\U000e0070\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_GEGHARKUNIK_AM_GR = "\U0001f3f4\U000e0061\U000e006d\U000e0067\U000e0072\U000e007f"
- FLAG_FOR_BLACK_POINT_BS_BP = "\U0001f3f4\U000e0062\U000e0073\U000e0062\U000e0070\U000e007f"
- FLAG_FOR_LUXOR_EG_LX = "\U0001f3f4\U000e0065\U000e0067\U000e006c\U000e0078\U000e007f"
- FLAG_FOR_WISCONSIN_US_WI = "\U0001f3f4\U000e0075\U000e0073\U000e0077\U000e0069\U000e007f"
- FLAG_FOR_MONACO_VILLE_MC_MO = "\U0001f3f4\U000e006d\U000e0063\U000e006d\U000e006f\U000e007f"
- FLAG_FOR_ARMAVIR_AM_AV = "\U0001f3f4\U000e0061\U000e006d\U000e0061\U000e0076\U000e007f"
- MAHJONG_TILE_EIGHT_OF_BAMBOOS = "\U0001f017"
- TRIGRAM_FOR_EARTH = "\u2637"
- FLAG_FOR_THUA_THIEN_HUE_VN_26 = "\U0001f3f4\U000e0076\U000e006e\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_POINTE_NOIRE_CG_16 = "\U0001f3f4\U000e0063\U000e0067\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_SAKHALIN_RU_SAK = "\U0001f3f4\U000e0072\U000e0075\U000e0073\U000e0061\U000e006b\U000e007f"
- TAG_LATIN_SMALL_LETTER_Z = "\U000e007a"
- FLAG_FOR_PAKRUOJIS_LT_30 = "\U0001f3f4\U000e006c\U000e0074\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_APE_LV_009 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0030\U000e0039\U000e007f"
- LOWER_RIGHT_SHADOWED_WHITE_CIRCLE = "\U0001f53e"
- FLAG_FOR_ARUBA_NL_AW = "\U0001f3f4\U000e006e\U000e006c\U000e0061\U000e0077\U000e007f"
- COUPLE_WITH_HEART_WOMAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_KIEV_UA_30 = "\U0001f3f4\U000e0075\U000e0061\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_PORT_SAID_EG_PTS = "\U0001f3f4\U000e0065\U000e0067\U000e0070\U000e0074\U000e0073\U000e007f"
- MAXIMIZE = "\U0001f5d6"
- FLAG_FOR_TRA_VINH_VN_51 = "\U0001f3f4\U000e0076\U000e006e\U000e0035\U000e0031\U000e007f"
- FLAG_FOR_RIYADH_SA_01 = "\U0001f3f4\U000e0073\U000e0061\U000e0030\U000e0031\U000e007f"
- GIRLS_SYMBOL = "\U0001f6ca"
- FLAG_FOR_SKIKDA_DZ_21 = "\U0001f3f4\U000e0064\U000e007a\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_ABU_DHABI_AE_AZ = "\U0001f3f4\U000e0061\U000e0065\U000e0061\U000e007a\U000e007f"
- MAHJONG_TILE_ONE_OF_CIRCLES = "\U0001f019"
- BLACK_DOWN_POINTING_BACKHAND_INDEX = "\U0001f5a3"
- MAHJONG_TILE_NINE_OF_CIRCLES = "\U0001f021"
- FLAG_FOR_RIGA_LV_RIX = "\U0001f3f4\U000e006c\U000e0076\U000e0072\U000e0069\U000e0078\U000e007f"
- FLAG_FOR_MAKIRA_ULAWA_SB_MK = "\U0001f3f4\U000e0073\U000e0062\U000e006d\U000e006b\U000e007f"
- FLAG_FOR_JUTIAPA_GT_JU = "\U0001f3f4\U000e0067\U000e0074\U000e006a\U000e0075\U000e007f"
- FLAG_FOR_LORESTAN_IR_20 = "\U0001f3f4\U000e0069\U000e0072\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_BASHKORTOSTAN_RU_BA = "\U0001f3f4\U000e0072\U000e0075\U000e0062\U000e0061\U000e007f"
- FLAG_FOR_BUSAN_KR_26 = "\U0001f3f4\U000e006b\U000e0072\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_MWARO_BI_MW = "\U0001f3f4\U000e0062\U000e0069\U000e006d\U000e0077\U000e007f"
- FLAG_FOR_ASTURIAS_ES_AS = "\U0001f3f4\U000e0065\U000e0073\U000e0061\U000e0073\U000e007f"
- FLAG_FOR_ALTA_VERAPAZ_GT_AV = "\U0001f3f4\U000e0067\U000e0074\U000e0061\U000e0076\U000e007f"
- FLAG_FOR_BRUNEI_MUARA_BN_BM = "\U0001f3f4\U000e0062\U000e006e\U000e0062\U000e006d\U000e007f"
- FLAG_FOR_LOVRENC_NA_POHORJU_SI_167 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0036\U000e0037\U000e007f"
- FLAG_FOR_WALLIS_ANDAMP_FUTUNA_FR_WF = "\U0001f3f4\U000e0066\U000e0072\U000e0077\U000e0066\U000e007f"
- KISS_MAN_WOMAN_DARK_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_LORI_AM_LO = "\U0001f3f4\U000e0061\U000e006d\U000e006c\U000e006f\U000e007f"
- KISS_MAN_DARK_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb"
- FLAG_FOR_GIZA_EG_GZ = "\U0001f3f4\U000e0065\U000e0067\U000e0067\U000e007a\U000e007f"
- FLAG_FOR_SAINT_MARY_JM_05 = "\U0001f3f4\U000e006a\U000e006d\U000e0030\U000e0035\U000e007f"
- DIGIT_FIVE = "5\ufe0f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_MAGADAN_RU_MAG = "\U0001f3f4\U000e0072\U000e0075\U000e006d\U000e0061\U000e0067\U000e007f"
- LEFT_ANGER_BUBBLE = "\U0001f5ee"
- DIGIT_EIGHT = "8\ufe0f"
- SIDEWAYS_BLACK_UP_POINTING_INDEX = "\U0001f5a0"
- FLAG_FOR_SOUTHERN_HIGHLANDS_PG_SHM = "\U0001f3f4\U000e0070\U000e0067\U000e0073\U000e0068\U000e006d\U000e007f"
- FLAG_FOR_NURISTAN_AF_NUR = "\U0001f3f4\U000e0061\U000e0066\U000e006e\U000e0075\U000e0072\U000e007f"
- FLAG_FOR_LOUISIANA_US_LA = "\U0001f3f4\U000e0075\U000e0073\U000e006c\U000e0061\U000e007f"
- FLAG_FOR_MAULE_CL_ML = "\U0001f3f4\U000e0063\U000e006c\U000e006d\U000e006c\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FLAG_FOR_PANAMA_PA_8 = "\U0001f3f4\U000e0070\U000e0061\U000e0038\U000e007f"
- FLAG_FOR_IZMIR_TR_35 = "\U0001f3f4\U000e0074\U000e0072\U000e0033\U000e0035\U000e007f"
- FLAG_FOR_CABINDA_AO_CAB = "\U0001f3f4\U000e0061\U000e006f\U000e0063\U000e0061\U000e0062\U000e007f"
- OPEN_FOLDER = "\U0001f5c1"
- FLAG_FOR_VAUD_CH_VD = "\U0001f3f4\U000e0063\U000e0068\U000e0076\U000e0064\U000e007f"
- LIGHTNING_MOOD = "\U0001f5f2"
- KISS_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc"
- FLAG_FOR_SUCRE_CO_SUC = "\U0001f3f4\U000e0063\U000e006f\U000e0073\U000e0075\U000e0063\U000e007f"
- MAHJONG_TILE_WHITE_DRAGON = "\U0001f006"
- FLAG_FOR_MADRE_DE_DIOS_PE_MDD = "\U0001f3f4\U000e0070\U000e0065\U000e006d\U000e0064\U000e0064\U000e007f"
- FLAG_FOR_BENGUELA_AO_BGU = "\U0001f3f4\U000e0061\U000e006f\U000e0062\U000e0067\U000e0075\U000e007f"
- FLAG_FOR_ST_JULIAN_S_MT_48 = "\U0001f3f4\U000e006d\U000e0074\U000e0034\U000e0038\U000e007f"
- FLAG_FOR_TIMIS_RO_TM = "\U0001f3f4\U000e0072\U000e006f\U000e0074\U000e006d\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_BIE_AO_BIE = "\U0001f3f4\U000e0061\U000e006f\U000e0062\U000e0069\U000e0065\U000e007f"
- MAHJONG_TILE_WINTER = "\U0001f029"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FLAG_FOR_BLUE_NILE_SD_NB = "\U0001f3f4\U000e0073\U000e0064\U000e006e\U000e0062\U000e007f"
- EMPTY_DOCUMENT = "\U0001f5cb"
- MINIMIZE = "\U0001f5d5"
- FLAG_FOR_KWALE_KE_19 = "\U0001f3f4\U000e006b\U000e0065\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_GRAND_PORT_MU_GP = "\U0001f3f4\U000e006d\U000e0075\U000e0067\U000e0070\U000e007f"
- FLAG_FOR_CHIMBORAZO_EC_H = "\U0001f3f4\U000e0065\U000e0063\U000e0068\U000e007f"
- FLAG_FOR_HUAMBO_AO_HUA = "\U0001f3f4\U000e0061\U000e006f\U000e0068\U000e0075\U000e0061\U000e007f"
- FLAG_FOR_CUANZA_SUL_AO_CUS = "\U0001f3f4\U000e0061\U000e006f\U000e0063\U000e0075\U000e0073\U000e007f"
- FLAG_FOR_BREMEN_DE_HB = "\U0001f3f4\U000e0064\U000e0065\U000e0068\U000e0062\U000e007f"
- LIPS = "\U0001f5e2"
- FLAG_FOR_ALTO_PARAGUAY_PY_16 = "\U0001f3f4\U000e0070\U000e0079\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_NEW_YORK_US_NY = "\U0001f3f4\U000e0075\U000e0073\U000e006e\U000e0079\U000e007f"
- KISS_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb"
- FLAG_FOR_NORTH_CAROLINA_US_NC = "\U0001f3f4\U000e0075\U000e0073\U000e006e\U000e0063\U000e007f"
- COUPLE_WITH_HEART_WOMAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff"
- WHITE_CIRCLE_WITH_TWO_DOTS = "\u2687"
- KISS_MAN_MEDIUM_SKIN_TONE_MAN = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468"
- MAN_ZOMBIE_LIGHT_SKIN_TONE = "\U0001f9df\U0001f3fb\u200d\u2642\ufe0f"
- FLAG_FOR_PERAK_MY_08 = "\U0001f3f4\U000e006d\U000e0079\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_SISAK_MOSLAVINA_HR_03 = "\U0001f3f4\U000e0068\U000e0072\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_ARDABIL_IR_03 = "\U0001f3f4\U000e0069\U000e0072\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_KARNATAKA_IN_KA = "\U0001f3f4\U000e0069\U000e006e\U000e006b\U000e0061\U000e007f"
- LEFT_HAND_TELEPHONE_RECEIVER = "\U0001f57b"
- FLAG_FOR_NEVADA_US_NV = "\U0001f3f4\U000e0075\U000e0073\U000e006e\U000e0076\U000e007f"
- FLAG_FOR_DIBER_COUNTY_AL_09 = "\U0001f3f4\U000e0061\U000e006c\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_LUNDA_SUL_AO_LSU = "\U0001f3f4\U000e0061\U000e006f\U000e006c\U000e0073\U000e0075\U000e007f"
- KISS_WOMAN_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb"
- SIDEWAYS_WHITE_DOWN_POINTING_INDEX = "\U0001f59f"
- FLAG_FOR_NAKHON_SI_THAMMARAT_TH_80 = "\U0001f3f4\U000e0074\U000e0068\U000e0038\U000e0030\U000e007f"
- FLAG_FOR_KYRENIA_CY_06 = "\U0001f3f4\U000e0063\U000e0079\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_GUNA_YALA_PA_KY = "\U0001f3f4\U000e0070\U000e0061\U000e006b\U000e0079\U000e007f"
- FLAG_FOR_HUILA_AO_HUI = "\U0001f3f4\U000e0061\U000e006f\U000e0068\U000e0075\U000e0069\U000e007f"
- FLAG_FOR_NAAMA_DZ_45 = "\U0001f3f4\U000e0064\U000e007a\U000e0034\U000e0035\U000e007f"
- FLAG_FOR_SAR_E_POL_AF_SAR = "\U0001f3f4\U000e0061\U000e0066\U000e0073\U000e0061\U000e0072\U000e007f"
- COUPLE_WITH_HEART_WOMAN_LIGHT_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_META_CO_MET = "\U0001f3f4\U000e0063\U000e006f\U000e006d\U000e0065\U000e0074\U000e007f"
- FLAG_FOR_NORTHWEST_TERRITORIES_CA_NT = "\U0001f3f4\U000e0063\U000e0061\U000e006e\U000e0074\U000e007f"
- FLAG_FOR_PENGHU_TW_PEN = "\U0001f3f4\U000e0074\U000e0077\U000e0070\U000e0065\U000e006e\U000e007f"
- FLAG_FOR_TOKYO_JP_13 = "\U0001f3f4\U000e006a\U000e0070\U000e0031\U000e0033\U000e007f"
- COUPLE_WITH_HEART_WOMAN_DARK_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb"
- TAG_LATIN_SMALL_LETTER_X = "\U000e0078"
- FLAG_FOR_SAINT_GEORGE_AG_03 = "\U0001f3f4\U000e0061\U000e0067\U000e0030\U000e0033\U000e007f"
- REVERSED_RAISED_HAND_WITH_FINGERS_SPLAYED = "\U0001f591"
- JAPANESE_BANK_SYMBOL = "\u26fb"
- FLAG_FOR_CUANZA_NORTE_AO_CNO = "\U0001f3f4\U000e0061\U000e006f\U000e0063\U000e006e\U000e006f\U000e007f"
- FLAG_FOR_NANA_GREBIZI_CF_KB = "\U0001f3f4\U000e0063\U000e0066\U000e006b\U000e0062\U000e007f"
- FLAG_FOR_MALANJE_AO_MAL = "\U0001f3f4\U000e0061\U000e006f\U000e006d\U000e0061\U000e006c\U000e007f"
- ROTATED_HEAVY_BLACK_HEART_BULLET = "\u2765"
- REVERSED_THUMBS_UP_SIGN = "\U0001f592"
- CELTIC_CROSS = "\U0001f548"
- KISS_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc"
- SYMBOL_FOR_MARKS_CHAPTER = "\U0001f545"
- TAG_LATIN_SMALL_LETTER_E = "\U000e0065"
- FLAG_FOR_NIGER_NG_NI = "\U0001f3f4\U000e006e\U000e0067\U000e006e\U000e0069\U000e007f"
- TAG_DIGIT_EIGHT = "\U000e0038"
- MAHJONG_TILE_ORCHID = "\U0001f023"
- TAG_LATIN_CAPITAL_LETTER_B = "\U000e0042"
- COUPLE_WITH_HEART_MAN_MEDIUM_DARK_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb"
- FLAG_FOR_BEIRUT_LB_BA = "\U0001f3f4\U000e006c\U000e0062\U000e0062\U000e0061\U000e007f"
- BLACK_DROPLET = "\U0001f322"
- FLAG_FOR_KALBAJAR_AZ_KAL = "\U0001f3f4\U000e0061\U000e007a\U000e006b\U000e0061\U000e006c\U000e007f"
- FLAG_FOR_BINH_DUONG_VN_57 = "\U0001f3f4\U000e0076\U000e006e\U000e0035\U000e0037\U000e007f"
- FLAG_FOR_NAMIBE_AO_NAM = "\U0001f3f4\U000e0061\U000e006f\U000e006e\U000e0061\U000e006d\U000e007f"
- FLAG_FOR_CALARASI_RO_CL = "\U0001f3f4\U000e0072\U000e006f\U000e0063\U000e006c\U000e007f"
- CIRCLED_CROSS_POMMEE = "\U0001f540"
- FLAG_FOR_A_ANA_WS_AA = "\U0001f3f4\U000e0077\U000e0073\U000e0061\U000e0061\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f467\U0001f3fb"
- BALLOT_SCRIPT_X = "\U0001f5f4"
- MAHJONG_TILE_WEST_WIND = "\U0001f002"
- MAHJONG_TILE_EIGHT_OF_CIRCLES = "\U0001f020"
- FLAG_FOR_MOXICO_AO_MOX = "\U0001f3f4\U000e0061\U000e006f\U000e006d\U000e006f\U000e0078\U000e007f"
- EMPTY_NOTE = "\U0001f5c5"
- FLAG_FOR_MISSOURI_US_MO = "\U0001f3f4\U000e0075\U000e0073\U000e006d\U000e006f\U000e007f"
- FLAG_FOR_PENANG_MY_07 = "\U0001f3f4\U000e006d\U000e0079\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_WAJIR_KE_46 = "\U0001f3f4\U000e006b\U000e0065\U000e0034\U000e0036\U000e007f"
- FLAG_FOR_CANILLO_AD_02 = "\U0001f3f4\U000e0061\U000e0064\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_VIRGINIA_US_VA = "\U0001f3f4\U000e0075\U000e0073\U000e0076\U000e0061\U000e007f"
- CROSS_POMMEE = "\U0001f542"
- FLAG_FOR_FIER_COUNTY_AL_04 = "\U0001f3f4\U000e0061\U000e006c\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_SCHLESWIG_HOLSTEIN_DE_SH = "\U0001f3f4\U000e0064\U000e0065\U000e0073\U000e0068\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe"
- FLAG_FOR_LUALABA_CD_LU = "\U0001f3f4\U000e0063\U000e0064\U000e006c\U000e0075\U000e007f"
- NORTHEAST_POINTING_AIRPLANE = "\U0001f6ea"
- FAMILY_WOMAN_WOMAN_GIRL_BABY = "\U0001f469\u200d\U0001f469\u200d\U0001f467\u200d\U0001f476"
- MAHJONG_TILE_SEVEN_OF_BAMBOOS = "\U0001f016"
- FLAG_FOR_AGSTAFA_AZ_AGA = "\U0001f3f4\U000e0061\U000e007a\U000e0061\U000e0067\U000e0061\U000e007f"
- FLAG_FOR_AMNAT_CHAROEN_TH_37 = "\U0001f3f4\U000e0074\U000e0068\U000e0033\U000e0037\U000e007f"
- FLAG_FOR_QUANG_TRI_VN_25 = "\U0001f3f4\U000e0076\U000e006e\U000e0032\U000e0035\U000e007f"
- STAMPED_ENVELOPE = "\U0001f583"
- BEATS_1_LOGO = "\uf79c"
- FLAG_FOR_AFYONKARAHISAR_TR_03 = "\U0001f3f4\U000e0074\U000e0072\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_MASSACHUSETTS_US_MA = "\U0001f3f4\U000e0075\U000e0073\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_GULF_PG_GPK = "\U0001f3f4\U000e0070\U000e0067\U000e0067\U000e0070\U000e006b\U000e007f"
- FLAG_FOR_UIGE_AO_UIG = "\U0001f3f4\U000e0061\U000e006f\U000e0075\U000e0069\U000e0067\U000e007f"
- KISS_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_SAINT_KITTS_KN_K = "\U0001f3f4\U000e006b\U000e006e\U000e006b\U000e007f"
- FLAG_FOR_CUANDO_CUBANGO_AO_CCU = "\U0001f3f4\U000e0061\U000e006f\U000e0063\U000e0063\U000e0075\U000e007f"
- KISS_WOMAN_MEDIUM_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb"
- FLAG_FOR_SAN_LUIS_AR_D = "\U0001f3f4\U000e0061\U000e0072\U000e0064\U000e007f"
- FLAG_FOR_ZHYTOMYRSHCHYNA_UA_18 = "\U0001f3f4\U000e0075\U000e0061\U000e0031\U000e0038\U000e007f"
- MAHJONG_TILE_TWO_OF_BAMBOOS = "\U0001f011"
- FLAG_FOR_SAINT_THOMAS_JM_03 = "\U0001f3f4\U000e006a\U000e006d\U000e0030\U000e0033\U000e007f"
- TAG_LATIN_SMALL_LETTER_I = "\U000e0069"
- VESTA = "\u26b6"
- TAG_LATIN_SMALL_LETTER_Y = "\U000e0079"
- TAG_LATIN_SMALL_LETTER_Q = "\U000e0071"
- SIDEWAYS_WHITE_LEFT_POINTING_INDEX = "\U0001f598"
- FLAG_FOR_IDAHO_US_ID = "\U0001f3f4\U000e0075\U000e0073\U000e0069\U000e0064\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_Z = "\U000e005a"
- FLAG_FOR_SYUNIK_AM_SU = "\U0001f3f4\U000e0061\U000e006d\U000e0073\U000e0075\U000e007f"
- FLAG_FOR_EAST_KAZAKHSTAN_KZ_VOS = "\U0001f3f4\U000e006b\U000e007a\U000e0076\U000e006f\U000e0073\U000e007f"
- FLAG_FOR_JAMTLAND_SE_Z = "\U0001f3f4\U000e0073\U000e0065\U000e007a\U000e007f"
- WOMAN_ZOMBIE_MEDIUM_DARK_SKIN_TONE = "\U0001f9df\U0001f3fe\u200d\u2640\ufe0f"
- FLAG_FOR_NEVSEHIR_TR_50 = "\U0001f3f4\U000e0074\U000e0072\U000e0035\U000e0030\U000e007f"
- FLAG_FOR_SKANE_SE_M = "\U0001f3f4\U000e0073\U000e0065\U000e006d\U000e007f"
- KISS_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc"
- FRAME_WITH_AN_X = "\U0001f5be"
- FLAG_FOR_SANTIAGO_DEL_ESTERO_AR_G = "\U0001f3f4\U000e0061\U000e0072\U000e0067\U000e007f"
- FLAG_FOR_LA_MASSANA_AD_04 = "\U0001f3f4\U000e0061\U000e0064\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_STAVROPOL_KRAI_RU_STA = "\U0001f3f4\U000e0072\U000e0075\U000e0073\U000e0074\U000e0061\U000e007f"
- FAMILY_MAN_BABY_GIRL = "\U0001f468\u200d\U0001f476\u200d\U0001f467"
- NEUTER = "\u26b2"
- FLAG_FOR_TRIPURA_IN_TR = "\U0001f3f4\U000e0069\U000e006e\U000e0074\U000e0072\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FLAG_FOR_ENUGU_NG_EN = "\U0001f3f4\U000e006e\U000e0067\U000e0065\U000e006e\U000e007f"
- FLAG_FOR_EL_ORO_EC_O = "\U0001f3f4\U000e0065\U000e0063\U000e006f\U000e007f"
- SQUARED_KEY = "\u26bf"
- MAHJONG_TILE_NINE_OF_BAMBOOS = "\U0001f018"
- PRINTER_ICON = "\U0001f5b6"
- SESQUIQUADRATE = "\u26bc"
- FAMILY_WOMAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f466\U0001f3ff"
- MAHJONG_TILE_SIX_OF_BAMBOOS = "\U0001f015"
- WOMAN_IN_TUXEDO_DARK_SKIN_TONE = "\U0001f935\U0001f3ff\u200d\u2640\ufe0f"
- FLAG_FOR_LA_RIOJA_AR_F = "\U0001f3f4\U000e0061\U000e0072\U000e0066\U000e007f"
- FLAG_FOR_BUSHEHR_IR_06 = "\U0001f3f4\U000e0069\U000e0072\U000e0030\U000e0036\U000e007f"
- DIGIT_THREE = "3\ufe0f"
- FLAG_FOR_LUXEMBOURG_LU_LU = "\U0001f3f4\U000e006c\U000e0075\U000e006c\U000e0075\U000e007f"
- FLAG_FOR_DAGESTAN_RU_DA = "\U0001f3f4\U000e0072\U000e0075\U000e0064\U000e0061\U000e007f"
- BLACK_DRAUGHTS_KING = "\u26c3"
- WHITE_DRAUGHTS_KING = "\u26c1"
- FLAG_FOR_CATAMARCA_AR_K = "\U0001f3f4\U000e0061\U000e0072\U000e006b\U000e007f"
- TAG_LATIN_SMALL_LETTER_B = "\U000e0062"
- FLAG_FOR_BARBUDA_AG_10 = "\U0001f3f4\U000e0061\U000e0067\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_MARL_NZ_MBH = "\U0001f3f4\U000e006e\U000e007a\U000e006d\U000e0062\U000e0068\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f476\U0001f3fb"
- BLACK_SNOWMAN = "\u26c7"
- ASTRONOMICAL_SYMBOL_FOR_URANUS = "\u26e2"
- FLAG_FOR_LAO_CAI_VN_02 = "\U0001f3f4\U000e0076\U000e006e\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_JURA_CH_JU = "\U0001f3f4\U000e0063\U000e0068\U000e006a\U000e0075\U000e007f"
- MAHJONG_TILE_FOUR_OF_BAMBOOS = "\U0001f013"
- TAG_LATIN_CAPITAL_LETTER_N = "\U000e004e"
- FAMILY_MAN_BABY_BOY = "\U0001f468\u200d\U0001f476\u200d\U0001f466"
- FLAG_FOR_MISIONES_AR_N = "\U0001f3f4\U000e0061\U000e0072\U000e006e\U000e007f"
- WOMAN_ZOMBIE_DARK_SKIN_TONE = "\U0001f9df\U0001f3ff\u200d\u2640\ufe0f"
- FAMILY_WOMAN_BABY = "\U0001f469\u200d\U0001f476"
- PALLAS = "\u26b4"
- DIGIT_SIX = "6\ufe0f"
- DOUBLED_MALE_SIGN = "\u26a3"
- FLAG_FOR_JOWZJAN_AF_JOW = "\U0001f3f4\U000e0061\U000e0066\U000e006a\U000e006f\U000e0077\U000e007f"
- FLAG_FOR_ESCALDES_ENGORDANY_AD_08 = "\U0001f3f4\U000e0061\U000e0064\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_MYKOLAYIVSCHYNA_UA_48 = "\U0001f3f4\U000e0075\U000e0061\U000e0034\U000e0038\U000e007f"
- FLAG_FOR_DEIR_EZ_ZOR_SY_DY = "\U0001f3f4\U000e0073\U000e0079\U000e0064\U000e0079\U000e007f"
- RIGHT_SPEECH_BUBBLE = "\U0001f5e9"
- TAG_DIGIT_ZERO = "\U000e0030"
- FLAG_FOR_FUJAIRAH_AE_FU = "\U0001f3f4\U000e0061\U000e0065\U000e0066\U000e0075\U000e007f"
- LEFT_CLOSED_ENTRY = "\u26dc"
- MAHJONG_TILE_BAMBOO = "\U0001f024"
- SQUARED_SALTIRE = "\u26dd"
- BLACK_MOON_LILITH = "\u26b8"
- FLAG_FOR_LUNDA_NORTE_AO_LNO = "\U0001f3f4\U000e0061\U000e006f\U000e006c\U000e006e\U000e006f\U000e007f"
- DRIVE_SLOW_SIGN = "\u26da"
- FLAG_FOR_GRAND_CAPE_MOUNT_LR_CM = "\U0001f3f4\U000e006c\U000e0072\U000e0063\U000e006d\U000e007f"
- FLAG_FOR_FORMOSA_AR_P = "\U0001f3f4\U000e0061\U000e0072\U000e0070\U000e007f"
- FLAG_FOR_WEST_NEW_BRITAIN_PG_WBK = "\U0001f3f4\U000e0070\U000e0067\U000e0077\U000e0062\U000e006b\U000e007f"
- BLACK_LEFT_LANE_MERGE = "\u26d8"
- FLAG_FOR_ARARAT_AM_AR = "\U0001f3f4\U000e0061\U000e006d\U000e0061\U000e0072\U000e007f"
- SEXTILE = "\u26b9"
- FLAG_FOR_SAN_JUAN_AR_J = "\U0001f3f4\U000e0061\U000e0072\U000e006a\U000e007f"
- FLAG_FOR_BLOKE_SI_150 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0035\U000e0030\U000e007f"
- INCREASE_FONT_SIZE_SYMBOL = "\U0001f5da"
- FLAG_FOR_ANHUI_CN_34 = "\U0001f3f4\U000e0063\U000e006e\U000e0033\U000e0034\U000e007f"
- FLAG_FOR_NORTH_AEGEAN_GR_K = "\U0001f3f4\U000e0067\U000e0072\U000e006b\U000e007f"
- FAMILY_MAN_WOMAN_BABY_GIRL = "\U0001f468\u200d\U0001f469\u200d\U0001f476\u200d\U0001f467"
- FLAG_FOR_HADRAMAUT_YE_HD = "\U0001f3f4\U000e0079\U000e0065\U000e0068\U000e0064\U000e007f"
- TURNED_WHITE_SHOGI_PIECE = "\u26c9"
- MALE_WITH_STROKE_SIGN = "\u26a6"
- RESTRICTED_LEFT_ENTRY_1 = "\u26e0"
- FLAG_FOR_HAVANA_CU_03 = "\U0001f3f4\U000e0063\U000e0075\U000e0030\U000e0033\U000e007f"
- LOWER_LEFT_PENCIL = "\U0001f589"
- FLAG_FOR_CHUBUT_AR_U = "\U0001f3f4\U000e0061\U000e0072\U000e0075\U000e007f"
- CLOCKWISE_RIGHT_AND_LEFT_SEMICIRCLE_ARROWS = "\U0001f5d8"
- FLAG_FOR_SANTIAGO_METROPOLITAN_CL_RM = "\U0001f3f4\U000e0063\U000e006c\U000e0072\U000e006d\U000e007f"
- CASTLE_2 = "\u26eb"
- THREE_RAYS_RIGHT = "\U0001f5e7"
- JUNO = "\u26b5"
- FLAG_FOR_HAI_DUONG_VN_61 = "\U0001f3f4\U000e0076\U000e006e\U000e0036\U000e0031\U000e007f"
- FLAG_FOR_ABSHERON_AZ_ABS = "\U0001f3f4\U000e0061\U000e007a\U000e0061\U000e0062\U000e0073\U000e007f"
- FLAG_FOR_CORRIENTES_AR_W = "\U0001f3f4\U000e0061\U000e0072\U000e0077\U000e007f"
- MAHJONG_TILE_SOUTH_WIND = "\U0001f001"
- FLAG_FOR_GRAND_CASABLANCA_MA_08 = "\U0001f3f4\U000e006d\U000e0061\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_NGARCHELONG_PW_218 = "\U0001f3f4\U000e0070\U000e0077\U000e0032\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_CORDOBA_AR_X = "\U0001f3f4\U000e0061\U000e0072\U000e0078\U000e007f"
- FLAG_FOR_CENTRAL_SINGAPORE_SG_01 = "\U0001f3f4\U000e0073\U000e0067\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_CAMPANIA_IT_72 = "\U0001f3f4\U000e0069\U000e0074\U000e0037\U000e0032\U000e007f"
- FLAG_FOR_CIBAO_NORTE_DO_35 = "\U0001f3f4\U000e0064\U000e006f\U000e0033\U000e0035\U000e007f"
- MAHJONG_TILE_THREE_OF_BAMBOOS = "\U0001f012"
- FLAG_FOR_ARAGATSOTN_AM_AG = "\U0001f3f4\U000e0061\U000e006d\U000e0061\U000e0067\U000e007f"
- FLAG_FOR_GRAND_GEDEH_LR_GG = "\U0001f3f4\U000e006c\U000e0072\U000e0067\U000e0067\U000e007f"
- FLAG_FOR_ABRUZZO_IT_65 = "\U0001f3f4\U000e0069\U000e0074\U000e0036\U000e0035\U000e007f"
- CERES = "\u26b3"
- FAMILY_MAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FLAG_FOR_CARINTHIA_AT_2 = "\U0001f3f4\U000e0061\U000e0074\U000e0032\U000e007f"
- MARRIAGE_SYMBOL = "\u26ad"
- LIGHTNING = "\u2607"
- SUN_2 = "\u2609"
- FLAG_FOR_CENTRAL_GREECE_GR_H = "\U0001f3f4\U000e0067\U000e0072\U000e0068\U000e007f"
- FAMILY_WOMAN_MAN_BOY_GIRL = "\U0001f469\u200d\U0001f468\u200d\U0001f466\u200d\U0001f467"
- FLAG_FOR_BASEL_LANDSCHAFT_CH_BL = "\U0001f3f4\U000e0063\U000e0068\U000e0062\U000e006c\U000e007f"
- FLAG_FOR_UTTARAKHAND_IN_UT = "\U0001f3f4\U000e0069\U000e006e\U000e0075\U000e0074\U000e007f"
- UP_POINTING_SMALL_AIRPLANE = "\U0001f6e8"
- FLAG_FOR_MENDOZA_AR_M = "\U0001f3f4\U000e0061\U000e0072\U000e006d\U000e007f"
- FLAG_FOR_MAMOU_REGION_GN_M = "\U0001f3f4\U000e0067\U000e006e\U000e006d\U000e007f"
- FLAG_FOR_ATTAPEU_LA_AT = "\U0001f3f4\U000e006c\U000e0061\U000e0061\U000e0074\U000e007f"
- FLAG_FOR_SABA_NL_BQ2 = "\U0001f3f4\U000e006e\U000e006c\U000e0062\U000e0071\U000e0032\U000e007f"
- FLYING_ENVELOPE = "\U0001f585"
- FLAG_FOR_KIRKUK_IQ_KI = "\U0001f3f4\U000e0069\U000e0071\U000e006b\U000e0069\U000e007f"
- BLACK_PUSHPIN = "\U0001f588"
- CROSSING_LANES = "\u26cc"
- FAMILY_WOMAN_BABY_BOY = "\U0001f469\u200d\U0001f476\u200d\U0001f466"
- TAG_LATIN_SMALL_LETTER_T = "\U000e0074"
- COUPLE_WITH_HEART_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469"
- MOOD_BUBBLE = "\U0001f5f0"
- MAHJONG_TILE_PLUM = "\U0001f022"
- FLAG_FOR_NOUAKCHOTT_OUEST_MR_13 = "\U0001f3f4\U000e006d\U000e0072\U000e0031\U000e0033\U000e007f"
- RIGHT_THOUGHT_BUBBLE = "\U0001f5ed"
- DIGIT_ZERO = "0\ufe0f"
- FLAG_FOR_SAXONY_DE_SN = "\U0001f3f4\U000e0064\U000e0065\U000e0073\U000e006e\U000e007f"
- FLAG_FOR_SACATEPEQUEZ_GT_SA = "\U0001f3f4\U000e0067\U000e0074\U000e0073\U000e0061\U000e007f"
- KISS_MAN_DARK_SKIN_TONE_MAN = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468"
- DESCENDING_NODE = "\u260b"
- FLAG_FOR_VIEUX_FORT_LC_11 = "\U0001f3f4\U000e006c\U000e0063\U000e0031\U000e0031\U000e007f"
- ONCOMING_FIRE_ENGINE = "\U0001f6f1"
- FLAG_FOR_QUANG_BINH_VN_24 = "\U0001f3f4\U000e0076\U000e006e\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_TYROL_AT_7 = "\U0001f3f4\U000e0061\U000e0074\U000e0037\U000e007f"
- FLAG_FOR_FRANCISTOWN_BW_FR = "\U0001f3f4\U000e0062\U000e0077\U000e0066\U000e0072\U000e007f"
- DISABLED_CAR = "\u26cd"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_MBOMOU_CF_MB = "\U0001f3f4\U000e0063\U000e0066\U000e006d\U000e0062\U000e007f"
- ASCENDING_NODE = "\u260a"
- FLAG_FOR_ILOCOS_PH_01 = "\U0001f3f4\U000e0070\U000e0068\U000e0030\U000e0031\U000e007f"
- HEAVY_CIRCLE_WITH_STROKE_AND_TWO_DOTS_ABOVE = "\u26e3"
- MAHJONG_TILE_FIVE_OF_BAMBOOS = "\U0001f014"
- FLAG_FOR_SAINT_GEORGE_GD_03 = "\U0001f3f4\U000e0067\U000e0064\U000e0030\U000e0033\U000e007f"
- COUPLE_WITH_HEART_WOMAN_LIGHT_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe"
- FLAG_FOR_TAIWAN_CN_71 = "\U0001f3f4\U000e0063\U000e006e\U000e0037\U000e0031\U000e007f"
- FLAG_FOR_VENETO_IT_34 = "\U0001f3f4\U000e0069\U000e0074\U000e0033\U000e0034\U000e007f"
- FLAG_FOR_LUANDA_AO_LUA = "\U0001f3f4\U000e0061\U000e006f\U000e006c\U000e0075\U000e0061\U000e007f"
- FLAG_FOR_SAINT_LOUIS_SN_SL = "\U0001f3f4\U000e0073\U000e006e\U000e0073\U000e006c\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f467\U0001f3ff"
- EMPTY_PAGE = "\U0001f5cc"
- BOUQUET_OF_FLOWERS = "\U0001f395"
- FLAG_FOR_XAISOMBOUN_LA_XS = "\U0001f3f4\U000e006c\U000e0061\U000e0078\U000e0073\U000e007f"
- FLAG_FOR_TUCUMAN_AR_T = "\U0001f3f4\U000e0061\U000e0072\U000e0074\U000e007f"
- RAIN = "\u26c6"
- FAMILY_MAN_MAN_BOY_GIRL = "\U0001f468\u200d\U0001f468\u200d\U0001f466\u200d\U0001f467"
- FLAG_FOR_ANKARA_TR_06 = "\U0001f3f4\U000e0074\U000e0072\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_GUIZHOU_CN_52 = "\U0001f3f4\U000e0063\U000e006e\U000e0035\U000e0032\U000e007f"
- FLAG_FOR_SVALBARD_NO_21 = "\U0001f3f4\U000e006e\U000e006f\U000e0032\U000e0031\U000e007f"
- FARSI_SYMBOL = "\u262b"
- PENTAGRAM = "\u26e4"
- HARD_DISK = "\U0001f5b4"
- FLAG_FOR_VORARLBERG_AT_8 = "\U0001f3f4\U000e0061\U000e0074\U000e0038\U000e007f"
- NO_PIRACY = "\U0001f572"
- RECYCLING_SYMBOL_FOR_TYPE_6_PLASTICS = "\u2678"
- OPPOSITION = "\u260d"
- FLAG_FOR_ZAIRE_AO_ZAI = "\U0001f3f4\U000e0061\U000e006f\U000e007a\U000e0061\U000e0069\U000e007f"
- FLAG_FOR_AMHARA_ET_AM = "\U0001f3f4\U000e0065\U000e0074\U000e0061\U000e006d\U000e007f"
- MAHJONG_TILE_SPRING = "\U0001f026"
- FLAG_FOR_RED_SEA_SD_RS = "\U0001f3f4\U000e0073\U000e0064\U000e0072\U000e0073\U000e007f"
- FLAG_FOR_PIETA_MT_41 = "\U0001f3f4\U000e006d\U000e0074\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_ZABUL_AF_ZAB = "\U0001f3f4\U000e0061\U000e0066\U000e007a\U000e0061\U000e0062\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f467\U0001f3fd"
- BLACK_SMILING_FACE = "\u263b"
- FLAG_FOR_SANTA_CRUZ_BO_S = "\U0001f3f4\U000e0062\U000e006f\U000e0073\U000e007f"
- KISS_MAN_DARK_SKIN_TONE_WOMAN = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469"
- BLACK_FOLDER = "\U0001f5bf"
- FLAG_FOR_SANTA_CATARINA_BR_SC = "\U0001f3f4\U000e0062\U000e0072\U000e0073\U000e0063\U000e007f"
- KISS_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469"
- FAMILY_WOMAN_MAN_GIRL_BABY = "\U0001f469\u200d\U0001f468\u200d\U0001f467\u200d\U0001f476"
- FLAG_FOR_BASQUE_COUNTRY_ES_PV = "\U0001f3f4\U000e0065\U000e0073\U000e0070\U000e0076\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_V = "\U000e0056"
- FLAG_FOR_MANABI_EC_M = "\U0001f3f4\U000e0065\U000e0063\U000e006d\U000e007f"
- LAST_QUARTER_MOON_2 = "\u263e"
- FLAG_FOR_NAVARRA_CHARTERED_COMMUNITY_ES_NC = "\U0001f3f4\U000e0065\U000e0073\U000e006e\U000e0063\U000e007f"
- INVERTED_PENTAGRAM = "\u26e7"
- FAMILY_WOMAN_MAN_GIRL = "\U0001f469\u200d\U0001f468\u200d\U0001f467"
- FLAG_FOR_DALARNA_SE_W = "\U0001f3f4\U000e0073\U000e0065\U000e0077\U000e007f"
- MAHJONG_TILE_TWO_OF_CHARACTERS = "\U0001f008"
- BITCOIN_SIGN = "\u20bf"
- FLAG_FOR_CHUUK_FM_TRK = "\U0001f3f4\U000e0066\U000e006d\U000e0074\U000e0072\U000e006b\U000e007f"
- FLAG_FOR_KERICHO_KE_12 = "\U0001f3f4\U000e006b\U000e0065\U000e0031\U000e0032\U000e007f"
- BLACK_LEFT_POINTING_INDEX = "\u261a"
- BLACK_RIGHT_POINTING_INDEX = "\u261b"
- KISS_MAN_LIGHT_SKIN_TONE_WOMAN = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469"
- FLAG_FOR_SARAWAK_MY_13 = "\U0001f3f4\U000e006d\U000e0079\U000e0031\U000e0033\U000e007f"
- BLACK_DRAUGHTS_MAN = "\u26c2"
- FLAG_FOR_BEAU_BASSIN_ROSE_HILL_MU_BR = "\U0001f3f4\U000e006d\U000e0075\U000e0062\U000e0072\U000e007f"
- FLAG_FOR_GOA_IN_GA = "\U0001f3f4\U000e0069\U000e006e\U000e0067\U000e0061\U000e007f"
- FLAG_FOR_PERNAMBUCO_BR_PE = "\U0001f3f4\U000e0062\U000e0072\U000e0070\U000e0065\U000e007f"
- WOMAN_WITH_HEADSCARF_DARK_SKIN_TONE = "\U0001f9d5\U0001f3ff\u200d\u2640\ufe0f"
- FLAG_FOR_YUKON_CA_YT = "\U0001f3f4\U000e0063\U000e0061\U000e0079\U000e0074\U000e007f"
- FLAG_FOR_SICHUAN_CN_51 = "\U0001f3f4\U000e0063\U000e006e\U000e0035\U000e0031\U000e007f"
- FLAG_FOR_LAKES_SS_LK = "\U0001f3f4\U000e0073\U000e0073\U000e006c\U000e006b\U000e007f"
- HAMMER_AND_SICKLE = "\u262d"
- FLAG_FOR_BEIJING_CN_11 = "\U0001f3f4\U000e0063\U000e006e\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_UPPER_AUSTRIA_AT_4 = "\U0001f3f4\U000e0061\U000e0074\U000e0034\U000e007f"
- FLAG_FOR_LAPLAND_FI_10 = "\U0001f3f4\U000e0066\U000e0069\U000e0031\U000e0030\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_HIMACHAL_PRADESH_IN_HP = "\U0001f3f4\U000e0069\U000e006e\U000e0068\U000e0070\U000e007f"
- FLAG_FOR_VELIKA_POLANA_SI_187 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0038\U000e0037\U000e007f"
- FLAG_FOR_MUSLIM_MINDANAO_PH_14 = "\U0001f3f4\U000e0070\U000e0068\U000e0031\U000e0034\U000e007f"
- HEADSTONE_GRAVEYARD_SYMBOL = "\u26fc"
- CLAMSHELL_MOBILE_PHONE = "\U0001f581"
- FLAG_FOR_KOSOVO_METOHIJA_RS_KM = "\U0001f3f4\U000e0072\U000e0073\U000e006b\U000e006d\U000e007f"
- DIGIT_TWO = "2\ufe0f"
- FLAG_FOR_PUNJAB_IN_PB = "\U0001f3f4\U000e0069\U000e006e\U000e0070\U000e0062\U000e007f"
- SIDEWAYS_BLACK_DOWN_POINTING_INDEX = "\U0001f5a1"
- FLAG_FOR_DOHA_QA_DA = "\U0001f3f4\U000e0071\U000e0061\U000e0064\U000e0061\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f476\U0001f3ff"
- DOUBLED_FEMALE_SIGN = "\u26a2"
- BLACK_SKULL_AND_CROSSBONES = "\U0001f571"
- FAMILY_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_ZEALAND_DK_85 = "\U0001f3f4\U000e0064\U000e006b\U000e0038\U000e0035\U000e007f"
- STAFF_OF_HERMES = "\u269a"
- QUINCUNX = "\u26bb"
- FLAG_FOR_SANTA_FE_AR_S = "\U0001f3f4\U000e0061\U000e0072\U000e0073\U000e007f"
- FLAG_FOR_ADIYAMAN_TR_02 = "\U0001f3f4\U000e0074\U000e0072\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_KAFR_EL_SHEIKH_EG_KFS = "\U0001f3f4\U000e0065\U000e0067\U000e006b\U000e0066\U000e0073\U000e007f"
- FLAG_FOR_ASTARA_AZ_AST = "\U0001f3f4\U000e0061\U000e007a\U000e0061\U000e0073\U000e0074\U000e007f"
- FLAG_FOR_SAINT_PATRICK_DM_09 = "\U0001f3f4\U000e0064\U000e006d\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_AGDAM_AZ_AGM = "\U0001f3f4\U000e0061\U000e007a\U000e0061\U000e0067\U000e006d\U000e007f"
- FLAG_FOR_TIERRA_DEL_FUEGO_AR_V = "\U0001f3f4\U000e0061\U000e0072\U000e0076\U000e007f"
- SIDEWAYS_BLACK_LEFT_POINTING_INDEX = "\U0001f59a"
- TAG_DIGIT_FIVE = "\U000e0035"
- FLAG_FOR_KANSAS_US_KS = "\U0001f3f4\U000e0075\U000e0073\U000e006b\U000e0073\U000e007f"
- MUSIC_FLAT_SIGN = "\u266d"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f476\U0001f3fc"
- BALLOT_BOX_WITH_X = "\u2612"
- TAG_LOW_LINE = "\U000e005f"
- FLAG_FOR_ADYGEA_RU_AD = "\U0001f3f4\U000e0072\U000e0075\U000e0061\U000e0064\U000e007f"
- TELEPHONE_ON_TOP_OF_MODEM = "\U0001f580"
- FLAG_FOR_NINGXIA_CN_64 = "\U0001f3f4\U000e0063\U000e006e\U000e0036\U000e0034\U000e007f"
- FLAG_FOR_GAVLEBORG_SE_X = "\U0001f3f4\U000e0073\U000e0065\U000e0078\U000e007f"
- FLAG_FOR_AGSU_AZ_AGU = "\U0001f3f4\U000e0061\U000e007a\U000e0061\U000e0067\U000e0075\U000e007f"
- HISTORIC_SITE = "\u26ec"
- FLAG_FOR_KAGAWA_JP_37 = "\U0001f3f4\U000e006a\U000e0070\U000e0033\U000e0037\U000e007f"
- FLAG_FOR_BOMI_LR_BM = "\U0001f3f4\U000e006c\U000e0072\U000e0062\U000e006d\U000e007f"
- FLAG_FOR_MIDLANDS_ZW_MI = "\U0001f3f4\U000e007a\U000e0077\U000e006d\U000e0069\U000e007f"
- FLAG_FOR_AGHJABADI_AZ_AGC = "\U0001f3f4\U000e0061\U000e007a\U000e0061\U000e0067\U000e0063\U000e007f"
- SIDEWAYS_WHITE_UP_POINTING_INDEX = "\U0001f59e"
- KISS_MAN_WOMAN = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469"
- FLAG_FOR_NEUQUEN_AR_Q = "\U0001f3f4\U000e0061\U000e0072\U000e0071\U000e007f"
- FLAG_FOR_AZORES_PT_20 = "\U0001f3f4\U000e0070\U000e0074\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_BAS_CONGO_CD_BC = "\U0001f3f4\U000e0063\U000e0064\U000e0062\U000e0063\U000e007f"
- FLAG_FOR_BILASUVAR_AZ_BIL = "\U0001f3f4\U000e0061\U000e007a\U000e0062\U000e0069\U000e006c\U000e007f"
- FLAG_FOR_KURSK_RU_KRS = "\U0001f3f4\U000e0072\U000e0075\U000e006b\U000e0072\U000e0073\U000e007f"
- FLAG_FOR_BARDA_AZ_BAR = "\U0001f3f4\U000e0061\U000e007a\U000e0062\U000e0061\U000e0072\U000e007f"
- TRIGRAM_FOR_LAKE = "\u2631"
- FLAG_FOR_JABRAYIL_AZ_CAB = "\U0001f3f4\U000e0061\U000e007a\U000e0063\U000e0061\U000e0062\U000e007f"
- NOTCHED_RIGHT_SEMICIRCLE_WITH_THREE_DOTS = "\U0001f544"
- FLAG_FOR_FIZULI_AZ_FUZ = "\U0001f3f4\U000e0061\U000e007a\U000e0066\U000e0075\U000e007a\U000e007f"
- FLAG_FOR_BEYLAGAN_AZ_BEY = "\U0001f3f4\U000e0061\U000e007a\U000e0062\U000e0065\U000e0079\U000e007f"
- FLAG_FOR_NIARI_CG_9 = "\U0001f3f4\U000e0063\U000e0067\U000e0039\U000e007f"
- FAMILY_WOMAN_MAN_BABY = "\U0001f469\u200d\U0001f468\u200d\U0001f476"
- FAMILY_WOMAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f466\U0001f3ff"
- WHITE_DRAUGHTS_MAN = "\u26c0"
- FLAG_FOR_SAINT_JOSEPH_DM_06 = "\U0001f3f4\U000e0064\U000e006d\U000e0030\U000e0036\U000e007f"
- DIGRAM_FOR_LESSER_YIN = "\u268d"
- TAG_DIGIT_THREE = "\U000e0033"
- FLAG_FOR_PAPUA_ISLANDS_ID_PP = "\U0001f3f4\U000e0069\U000e0064\U000e0070\U000e0070\U000e007f"
- FLAG_FOR_HARBOUR_ISLAND_BS_HI = "\U0001f3f4\U000e0062\U000e0073\U000e0068\U000e0069\U000e007f"
- FLAG_FOR_YEREVAN_AM_ER = "\U0001f3f4\U000e0061\U000e006d\U000e0065\U000e0072\U000e007f"
- KISS_WOMAN_LIGHT_SKIN_TONE_WOMAN = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469"
- ANKH = "\u2625"
- LIGHT_CHECK_MARK = "\U0001f5f8"
- KISS_WOMAN_WOMAN_DARK_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_GOYCHAY_AZ_GOY = "\U0001f3f4\U000e0061\U000e007a\U000e0067\U000e006f\U000e0079\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_A = "\U000e0041"
- FLAG_FOR_PORT_HERCULES_MC_PH = "\U0001f3f4\U000e006d\U000e0063\U000e0070\U000e0068\U000e007f"
- CIRCLED_CROSSING_LANES = "\u26d2"
- MONOGRAM_FOR_YANG = "\u268a"
- FLAG_FOR_CESAR_CO_CES = "\U0001f3f4\U000e0063\U000e006f\U000e0063\U000e0065\U000e0073\U000e007f"
- DECREASE_FONT_SIZE_SYMBOL = "\U0001f5db"
- BALLOT_BOLD_SCRIPT_X = "\U0001f5f6"
- FLAG_FOR_JERUSALEM_PS_JEM = "\U0001f3f4\U000e0070\U000e0073\U000e006a\U000e0065\U000e006d\U000e007f"
- FLAG_FOR_UMM_SALAL_QA_US = "\U0001f3f4\U000e0071\U000e0061\U000e0075\U000e0073\U000e007f"
- BLACK_CHESS_BISHOP = "\u265d"
- FLAG_FOR_KALIMANTAN_ID_KA = "\U0001f3f4\U000e0069\U000e0064\U000e006b\U000e0061\U000e007f"
- BALLOT_BOX = "\u2610"
- FLAG_FOR_BRYANSK_RU_BRY = "\U0001f3f4\U000e0072\U000e0075\U000e0062\U000e0072\U000e0079\U000e007f"
- KISS_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe"
- FLAG_FOR_AGDASH_AZ_AGS = "\U0001f3f4\U000e0061\U000e007a\U000e0061\U000e0067\U000e0073\U000e007f"
- FLAG_FOR_GOYGOL_AZ_GYG = "\U0001f3f4\U000e0061\U000e007a\U000e0067\U000e0079\U000e0067\U000e007f"
- FLAG_FOR_HAJIGABUL_AZ_HAC = "\U0001f3f4\U000e0061\U000e007a\U000e0068\U000e0061\U000e0063\U000e007f"
- FLAG_FOR_KASTAMONU_TR_37 = "\U0001f3f4\U000e0074\U000e0072\U000e0033\U000e0037\U000e007f"
- FLAG_FOR_REZEKNE_MUNICIPALITY_LV_077 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0037\U000e0037\U000e007f"
- FLAG_FOR_BONAIRE_NL_BQ1 = "\U0001f3f4\U000e006e\U000e006c\U000e0062\U000e0071\U000e0031\U000e007f"
- FLAG_FOR_TAVUSH_AM_TV = "\U0001f3f4\U000e0061\U000e006d\U000e0074\U000e0076\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f476\U0001f3fc"
- WHITE_TELEPHONE = "\u260f"
- FLAG_FOR_VEST_AGDER_NO_10 = "\U0001f3f4\U000e006e\U000e006f\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_GORANBOY_AZ_GOR = "\U0001f3f4\U000e0061\U000e007a\U000e0067\U000e006f\U000e0072\U000e007f"
- FLAG_FOR_CROSS_RIVER_NG_CR = "\U0001f3f4\U000e006e\U000e0067\U000e0063\U000e0072\U000e007f"
- FLAG_FOR_IMISHLI_AZ_IMI = "\U0001f3f4\U000e0061\U000e007a\U000e0069\U000e006d\U000e0069\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_TANGANYIKA_CD_TA = "\U0001f3f4\U000e0063\U000e0064\U000e0074\U000e0061\U000e007f"
- BLACK_STAR = "\u2605"
- CAUTION_SIGN = "\u2621"
- FLAG_FOR_SHANGHAI_CN_31 = "\U0001f3f4\U000e0063\U000e006e\U000e0033\U000e0031\U000e007f"
- CHI_RHO = "\u2627"
- BALLOT_BOX_WITH_BOLD_SCRIPT_X = "\U0001f5f7"
- TRIGRAM_FOR_FIRE = "\u2632"
- FLAG_FOR_WEST_VIRGINIA_US_WV = "\U0001f3f4\U000e0075\U000e0073\U000e0077\U000e0076\U000e007f"
- FLAG_FOR_CLIPPERTON_ISLAND_FR_CP = "\U0001f3f4\U000e0066\U000e0072\U000e0063\U000e0070\U000e007f"
- EIGHTH_NOTE = "\u266a"
- CROSS_OF_LORRAINE = "\u2628"
- CADUCEUS = "\u2624"
- FLAG_FOR_GORJ_RO_GJ = "\U0001f3f4\U000e0072\U000e006f\U000e0067\U000e006a\U000e007f"
- OUTLINED_WHITE_STAR = "\u269d"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_ALTAI_KRAI_RU_ALT = "\U0001f3f4\U000e0072\U000e0075\U000e0061\U000e006c\U000e0074\U000e007f"
- KISS_WOMAN_MEDIUM_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_LACHIN_AZ_LAC = "\U0001f3f4\U000e0061\U000e007a\U000e006c\U000e0061\U000e0063\U000e007f"
- FLAG_FOR_TAKHAR_AF_TAK = "\U0001f3f4\U000e0061\U000e0066\U000e0074\U000e0061\U000e006b\U000e007f"
- FLAG_FOR_LANKARAN_AZ_LA = "\U0001f3f4\U000e0061\U000e007a\U000e006c\U000e0061\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_S = "\U000e0053"
- FLAG_FOR_CENTRAL_UG_C = "\U0001f3f4\U000e0075\U000e0067\U000e0063\U000e007f"
- FLAG_FOR_ZUG_CH_ZG = "\U0001f3f4\U000e0063\U000e0068\U000e007a\U000e0067\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_I = "\U000e0049"
- BEAMED_ASCENDING_MUSICAL_NOTES = "\U0001f39c"
- FLAG_FOR_LERIK_AZ_LER = "\U0001f3f4\U000e0061\U000e007a\U000e006c\U000e0065\U000e0072\U000e007f"
- PLUTO = "\u2647"
- FLAG_FOR_AMERICAN_SAMOA_US_AS = "\U0001f3f4\U000e0075\U000e0073\U000e0061\U000e0073\U000e007f"
- PARTIALLY_RECYCLED_PAPER_SYMBOL = "\u267d"
- FLAG_FOR_OKINAWA_JP_47 = "\U0001f3f4\U000e006a\U000e0070\U000e0034\U000e0037\U000e007f"
- FLAG_FOR_GADABAY_AZ_GAD = "\U0001f3f4\U000e0061\U000e007a\U000e0067\U000e0061\U000e0064\U000e007f"
- FLAG_FOR_VASTERNORRLAND_SE_Y = "\U0001f3f4\U000e0073\U000e0065\U000e0079\U000e007f"
- FLAG_FOR_ORDINO_AD_05 = "\U0001f3f4\U000e0061\U000e0064\U000e0030\U000e0035\U000e007f"
- EARTH = "\u2641"
- VERTICAL_MALE_WITH_STROKE_SIGN = "\u26a8"
- TAG_VERTICAL_LINE = "\U000e007c"
- COUPLE_WITH_HEART_MAN_LIGHT_SKIN_TONE_MAN = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468"
- FLAG_FOR_NAFTALAN_AZ_NA = "\U0001f3f4\U000e0061\U000e007a\U000e006e\U000e0061\U000e007f"
- FLAG_FOR_MASALLY_AZ_MAS = "\U0001f3f4\U000e0061\U000e007a\U000e006d\U000e0061\U000e0073\U000e007f"
- FLAG_FOR_MINGACHEVIR_AZ_MI = "\U0001f3f4\U000e0061\U000e007a\U000e006d\U000e0069\U000e007f"
- FLAG_FOR_KVEMO_KARTLI_GE_KK = "\U0001f3f4\U000e0067\U000e0065\U000e006b\U000e006b\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_X = "\U000e0058"
- HEART_WITH_TIP_ON_THE_LEFT = "\U0001f394"
- TAG_PERCENT_SIGN = "\U000e0025"
- SATURN = "\u2644"
- NEPTUNE = "\u2646"
- FLAG_FOR_LAS_TUNAS_CU_10 = "\U0001f3f4\U000e0063\U000e0075\U000e0031\U000e0030\U000e007f"
- THREE_LINES_CONVERGING_RIGHT = "\u269e"
- FAMILY_WOMAN_WOMAN_BOY_BABY = "\U0001f469\u200d\U0001f469\u200d\U0001f466\u200d\U0001f476"
- REVERSED_ROTATED_FLORAL_HEART_BULLET = "\u2619"
- FLAG_FOR_FAIYUM_EG_FYM = "\U0001f3f4\U000e0065\U000e0067\U000e0066\U000e0079\U000e006d\U000e007f"
- FLAG_FOR_CELJE_SI_011 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_GILAN_IR_19 = "\U0001f3f4\U000e0069\U000e0072\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_PANEVEZIO_MUNICIPALITY_LT_32 = "\U0001f3f4\U000e006c\U000e0074\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_AYSEN_CL_AI = "\U0001f3f4\U000e0063\U000e006c\U000e0061\U000e0069\U000e007f"
- SCREEN = "\U0001f5b5"
- WHITE_CHESS_ROOK = "\u2656"
- FLAG_FOR_WEST_COAST_NZ_WTC = "\U0001f3f4\U000e006e\U000e007a\U000e0077\U000e0074\U000e0063\U000e007f"
- FLAG_FOR_TANGIER_TETOUAN_MA_01 = "\U0001f3f4\U000e006d\U000e0061\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_NEFTCHALA_AZ_NEF = "\U0001f3f4\U000e0061\U000e007a\U000e006e\U000e0065\U000e0066\U000e007f"
- FLAG_FOR_MOSCOW_RU_MOW = "\U0001f3f4\U000e0072\U000e0075\U000e006d\U000e006f\U000e0077\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff"
- WHITE_CHESS_QUEEN = "\u2655"
- FLAG_FOR_ISMAILLI_AZ_ISM = "\U0001f3f4\U000e0061\U000e007a\U000e0069\U000e0073\U000e006d\U000e007f"
- BLACK_CROSS_ON_SHIELD = "\u26e8"
- FLAG_FOR_TARACLIA_MD_TA = "\U0001f3f4\U000e006d\U000e0064\U000e0074\U000e0061\U000e007f"
- FLAG_FOR_DROCHIA_MD_DR = "\U0001f3f4\U000e006d\U000e0064\U000e0064\U000e0072\U000e007f"
- FLAG_FOR_ONTARIO_CA_ON = "\U0001f3f4\U000e0063\U000e0061\U000e006f\U000e006e\U000e007f"
- EAST_SYRIAC_CROSS = "\u2671"
- TAG_PLUS_SIGN = "\U000e002b"
- DIGRAM_FOR_GREATER_YIN = "\u268f"
- WHITE_PENNANT = "\U0001f3f1"
- COUPLE_WITH_HEART_MAN_LIGHT_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_GOBUSTAN_AZ_QOB = "\U0001f3f4\U000e0061\U000e007a\U000e0071\U000e006f\U000e0062\U000e007f"
- FLAG_FOR_NORTHERN_IRELAND_GB_NIR = "\U0001f3f4\U000e0067\U000e0062\U000e006e\U000e0069\U000e0072\U000e007f"
- KISS_MAN_WOMAN_MEDIUM_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb"
- FLAG_FOR_NAPO_EC_N = "\U0001f3f4\U000e0065\U000e0063\U000e006e\U000e007f"
- FLAG_FOR_KORCE_COUNTY_AL_06 = "\U0001f3f4\U000e0061\U000e006c\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_QABALA_AZ_QAB = "\U0001f3f4\U000e0061\U000e007a\U000e0071\U000e0061\U000e0062\U000e007f"
- TRIGRAM_FOR_WIND = "\u2634"
- FLAG_FOR_NANA_MAMBERE_CF_NM = "\U0001f3f4\U000e0063\U000e0066\U000e006e\U000e006d\U000e007f"
- FLAG_FOR_OGHUZ_AZ_OGU = "\U0001f3f4\U000e0061\U000e007a\U000e006f\U000e0067\U000e0075\U000e007f"
- KISS_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_SMARJESKE_TOPLICE_SI_206 = "\U0001f3f4\U000e0073\U000e0069\U000e0032\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_HO_CHI_MINH_CITY_VN_SG = "\U0001f3f4\U000e0076\U000e006e\U000e0073\U000e0067\U000e007f"
- FLAG_FOR_QUBADLI_AZ_QBI = "\U0001f3f4\U000e0061\U000e007a\U000e0071\U000e0062\U000e0069\U000e007f"
- FLAG_FOR_SUD_UBANGI_CD_SU = "\U0001f3f4\U000e0063\U000e0064\U000e0073\U000e0075\U000e007f"
- KISS_WOMAN_LIGHT_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff"
- RECYCLING_SYMBOL_FOR_TYPE_5_PLASTICS = "\u2677"
- MAHJONG_TILE_CHRYSANTHEMUM = "\U0001f025"
- FLAG_FOR_BRASOV_RO_BV = "\U0001f3f4\U000e0072\U000e006f\U000e0062\U000e0076\U000e007f"
- FLAG_FOR_MOGILA_MK_53 = "\U0001f3f4\U000e006d\U000e006b\U000e0035\U000e0033\U000e007f"
- THUNDERSTORM = "\u2608"
- FLAG_FOR_JALILABAD_AZ_CAL = "\U0001f3f4\U000e0061\U000e007a\U000e0063\U000e0061\U000e006c\U000e007f"
- FLAG_FOR_QUSAR_AZ_QUS = "\U0001f3f4\U000e0061\U000e007a\U000e0071\U000e0075\U000e0073\U000e007f"
- TAG_QUOTATION_MARK = "\U000e0022"
- DIE_FACE_3 = "\u2682"
- FAMILY_WOMAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_QAZAKH_AZ_QAZ = "\U0001f3f4\U000e0061\U000e007a\U000e0071\U000e0061\U000e007a\U000e007f"
- KISS_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb"
- FLAG_FOR_KAVANGO_EAST_NA_KE = "\U0001f3f4\U000e006e\U000e0061\U000e006b\U000e0065\U000e007f"
- FLAG_FOR_QAKH_AZ_QAX = "\U0001f3f4\U000e0061\U000e007a\U000e0071\U000e0061\U000e0078\U000e007f"
- FLAG_FOR_SAINT_PETER_AG_07 = "\U0001f3f4\U000e0061\U000e0067\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_BAJA_CALIFORNIA_MX_BCN = "\U0001f3f4\U000e006d\U000e0078\U000e0062\U000e0063\U000e006e\U000e007f"
- KISS_WOMAN_DARK_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_ASGABAT_TM_S = "\U0001f3f4\U000e0074\U000e006d\U000e0073\U000e007f"
- FLAG_FOR_SABIRABAD_AZ_SAB = "\U0001f3f4\U000e0061\U000e007a\U000e0073\U000e0061\U000e0062\U000e007f"
- BLACK_SHOGI_PIECE = "\u2617"
- THREE_LINES_CONVERGING_LEFT = "\u269f"
- FAMILY_WOMAN_BOY_BABY = "\U0001f469\u200d\U0001f466\u200d\U0001f476"
- MUSIC_NATURAL_SIGN = "\u266e"
- FLAG_FOR_QUTHING_LS_G = "\U0001f3f4\U000e006c\U000e0073\U000e0067\U000e007f"
- FLAG_FOR_JONGLEI_SS_JG = "\U0001f3f4\U000e0073\U000e0073\U000e006a\U000e0067\U000e007f"
- FLAG_FOR_NELSON_NZ_NSN = "\U0001f3f4\U000e006e\U000e007a\U000e006e\U000e0073\U000e006e\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_VIENNA_AT_9 = "\U0001f3f4\U000e0061\U000e0074\U000e0039\U000e007f"
- FLAG_FOR_SHABRAN_AZ_SBN = "\U0001f3f4\U000e0061\U000e007a\U000e0073\U000e0062\U000e006e\U000e007f"
- DIE_FACE_4 = "\u2683"
- WHITE_SHOGI_PIECE = "\u2616"
- RECYCLING_SYMBOL_FOR_TYPE_4_PLASTICS = "\u2676"
- FLAG_FOR_MAKEDONSKI_BROD_MK_52 = "\U0001f3f4\U000e006d\U000e006b\U000e0035\U000e0032\U000e007f"
- KISS_WOMAN_MAN_MEDIUM_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_SHAKI_DISTRICT_AZ_SAK = "\U0001f3f4\U000e0061\U000e007a\U000e0073\U000e0061\U000e006b\U000e007f"
- URANUS = "\u2645"
- FLAG_FOR_QUBA_AZ_QBA = "\U0001f3f4\U000e0061\U000e007a\U000e0071\U000e0062\U000e0061\U000e007f"
- FLAG_FOR_SAMUKH_AZ_SMX = "\U0001f3f4\U000e0061\U000e007a\U000e0073\U000e006d\U000e0078\U000e007f"
- FLAG_FOR_FEDERAL_CAPITAL_TERRITORY_NG_FC = "\U0001f3f4\U000e006e\U000e0067\U000e0066\U000e0063\U000e007f"
- FLAG_FOR_FRIULI_VENEZIA_GIULIA_IT_36 = "\U0001f3f4\U000e0069\U000e0074\U000e0033\U000e0036\U000e007f"
- WHITE_FLAG_2 = "\u2690"
- DIE_FACE_2 = "\u2681"
- FLAG_FOR_SHAKI_AZ_SA = "\U0001f3f4\U000e0061\U000e007a\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_LA_PAMPA_AR_L = "\U0001f3f4\U000e0061\U000e0072\U000e006c\U000e007f"
- FLAG_FOR_SIAZAN_AZ_SIY = "\U0001f3f4\U000e0061\U000e007a\U000e0073\U000e0069\U000e0079\U000e007f"
- FLAG_FOR_NEW_IRELAND_PG_NIK = "\U0001f3f4\U000e0070\U000e0067\U000e006e\U000e0069\U000e006b\U000e007f"
- FLAG_FOR_AKMENE_LT_01 = "\U0001f3f4\U000e006c\U000e0074\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_SAINT_LOUIS_SC_22 = "\U0001f3f4\U000e0073\U000e0063\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_UPPER_TAKUTU_UPPER_ESSEQUIBO_GY_UT = "\U0001f3f4\U000e0067\U000e0079\U000e0075\U000e0074\U000e007f"
- FLAG_FOR_SHIRVAN_AZ_SR = "\U0001f3f4\U000e0061\U000e007a\U000e0073\U000e0072\U000e007f"
- FLAG_FOR_HAUT_MBOMOU_CF_HM = "\U0001f3f4\U000e0063\U000e0066\U000e0068\U000e006d\U000e007f"
- TRIANGLE_WITH_ROUNDED_CORNERS = "\U0001f6c6"
- FLAG_FOR_SHAMAKHI_AZ_SMI = "\U0001f3f4\U000e0061\U000e007a\U000e0073\U000e006d\U000e0069\U000e007f"
- KISS_WOMAN_DARK_SKIN_TONE_MAN = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468"
- FAMILY_MAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f467\U0001f3ff"
- KISS_WOMAN_DARK_SKIN_TONE_WOMAN = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469"
- DOCUMENT_WITH_TEXT = "\U0001f5b9"
- FLAG_FOR_TOVUZ_AZ_TOV = "\U0001f3f4\U000e0061\U000e007a\U000e0074\U000e006f\U000e0076\U000e007f"
- FLAG_FOR_PORT_MORESBY_PG_NCD = "\U0001f3f4\U000e0070\U000e0067\U000e006e\U000e0063\U000e0064\U000e007f"
- WHITE_SUN_WITH_RAYS = "\u263c"
- FAMILY_MAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FAMILY_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f467\U0001f3fd"
- MAHJONG_TILE_AUTUMN = "\U0001f028"
- FLAG_FOR_UJAR_AZ_UCA = "\U0001f3f4\U000e0061\U000e007a\U000e0075\U000e0063\U000e0061\U000e007f"
- FLAG_FOR_STRUMICA_MK_73 = "\U0001f3f4\U000e006d\U000e006b\U000e0037\U000e0033\U000e007f"
- FLAG_FOR_LVIVSHCHYNA_UA_46 = "\U0001f3f4\U000e0075\U000e0061\U000e0034\U000e0036\U000e007f"
- TAG_LATIN_SMALL_LETTER_H = "\U000e0068"
- KISS_MAN_DARK_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb"
- FAMILY_MAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f466\U0001f3ff"
- SEMISEXTILE = "\u26ba"
- BLACK_TOUCHTONE_TELEPHONE = "\U0001f57f"
- WHITE_CIRCLE_WITH_DOT_RIGHT = "\u2686"
- FAMILY_MAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_LIPETSK_RU_LIP = "\U0001f3f4\U000e0072\U000e0075\U000e006c\U000e0069\U000e0070\U000e007f"
- FLAG_FOR_DOL_PRI_LJUBLJANI_SI_022 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0032\U000e0032\U000e007f"
- KISS_MAN_MAN_DARK_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff"
- WHITE_DIAMOND_IN_SQUARE = "\u26cb"
- COUPLE_WITH_HEART_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_KHIZI_AZ_XIZ = "\U0001f3f4\U000e0061\U000e007a\U000e0078\U000e0069\U000e007a\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f467\U0001f3fd"
- KISS_WOMAN_DARK_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb"
- UP_POINTING_MILITARY_AIRPLANE = "\U0001f6e6"
- FLAG_FOR_KHOJALI_AZ_XCI = "\U0001f3f4\U000e0061\U000e007a\U000e0078\U000e0063\U000e0069\U000e007f"
- FLAG_FOR_YEVLAKH_DISTRICT_AZ_YEV = "\U0001f3f4\U000e0061\U000e007a\U000e0079\U000e0065\U000e0076\U000e007f"
- FLAG_FOR_ZANZIBAR_CENTRAL_SOUTH_TZ_11 = "\U0001f3f4\U000e0074\U000e007a\U000e0031\U000e0031\U000e007f"
- TAG_LEFT_SQUARE_BRACKET = "\U000e005b"
- FAMILY_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_NORTHLAND_NZ_NTL = "\U0001f3f4\U000e006e\U000e007a\U000e006e\U000e0074\U000e006c\U000e007f"
- DIVORCE_SYMBOL = "\u26ae"
- FLAG_FOR_BALAKAN_AZ_BAL = "\U0001f3f4\U000e0061\U000e007a\U000e0062\U000e0061\U000e006c\U000e007f"
- FLAG_FOR_PROVENCE_ALPES_COTE_D_AZUR_FR_PAC = "\U0001f3f4\U000e0066\U000e0072\U000e0070\U000e0061\U000e0063\U000e007f"
- FLAG_FOR_SHUSHA_AZ_SUS = "\U0001f3f4\U000e0061\U000e007a\U000e0073\U000e0075\U000e0073\U000e007f"
- COUPLE_WITH_HEART_WOMAN_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe"
- FLAG_FOR_MONTSERRADO_LR_MO = "\U0001f3f4\U000e006c\U000e0072\U000e006d\U000e006f\U000e007f"
- FAMILY_MAN_MAN_GIRL_BABY = "\U0001f468\u200d\U0001f468\u200d\U0001f467\u200d\U0001f476"
- FLAG_FOR_YARDYMLI_AZ_YAR = "\U0001f3f4\U000e0061\U000e007a\U000e0079\U000e0061\U000e0072\U000e007f"
- FLAG_FOR_SALYAN_AZ_SAL = "\U0001f3f4\U000e0061\U000e007a\U000e0073\U000e0061\U000e006c\U000e007f"
- MALE_AND_FEMALE_SIGN = "\u26a5"
- FLAG_FOR_NEW_CALEDONIA_FR_NC = "\U0001f3f4\U000e0066\U000e0072\U000e006e\U000e0063\U000e007f"
- FRAME_WITH_TILES = "\U0001f5bd"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FAMILY_MAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_SAINT_THOMAS_BB_11 = "\U0001f3f4\U000e0062\U000e0062\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_CONSTANTINE_DZ_25 = "\U0001f3f4\U000e0064\U000e007a\U000e0032\U000e0035\U000e007f"
- FLAG_FOR_YEVLAKH_AZ_YE = "\U0001f3f4\U000e0061\U000e007a\U000e0079\U000e0065\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f476\U0001f3ff"
- COUPLE_WITH_HEART_MAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc"
- COUPLE_WITH_HEART_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc"
- FLAG_FOR_BOTOSANI_RO_BT = "\U0001f3f4\U000e0072\U000e006f\U000e0062\U000e0074\U000e007f"
- FLAG_FOR_ZAQATALA_AZ_ZAQ = "\U0001f3f4\U000e0061\U000e007a\U000e007a\U000e0061\U000e0071\U000e007f"
- FLAG_FOR_CHIN_MM_14 = "\U0001f3f4\U000e006d\U000e006d\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_KHOST_AF_KHO = "\U0001f3f4\U000e0061\U000e0066\U000e006b\U000e0068\U000e006f\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f476\U0001f3fb"
- QUARTER_NOTE = "\u2669"
- HEAVY_LATIN_CROSS = "\U0001f547"
- FLAG_FOR_QUINDIO_CO_QUI = "\U0001f3f4\U000e0063\U000e006f\U000e0071\U000e0075\U000e0069\U000e007f"
- FLAG_FOR_CUSCO_PE_CUS = "\U0001f3f4\U000e0070\U000e0065\U000e0063\U000e0075\U000e0073\U000e007f"
- COUPLE_WITH_HEART_WOMAN_WOMAN_DARK_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff"
- MAHJONG_TILE_BACK = "\U0001f02b"
- FLAG_FOR_SAINT_ANDREW_BB_02 = "\U0001f3f4\U000e0062\U000e0062\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_SOUTH_HOLLAND_NL_ZH = "\U0001f3f4\U000e006e\U000e006c\U000e007a\U000e0068\U000e007f"
- FLAG_FOR_LAC_TD_LC = "\U0001f3f4\U000e0074\U000e0064\U000e006c\U000e0063\U000e007f"
- FLAG_FOR_VELIKO_TARNOVO_BG_04 = "\U0001f3f4\U000e0062\U000e0067\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_EASTERN_FJ_E = "\U0001f3f4\U000e0066\U000e006a\U000e0065\U000e007f"
- COUPLE_WITH_HEART_MAN_WOMAN_MEDIUM_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_SHAMKIR_AZ_SKR = "\U0001f3f4\U000e0061\U000e007a\U000e0073\U000e006b\U000e0072\U000e007f"
- PEN_OVER_STAMPED_ENVELOPE = "\U0001f586"
- FLAG_FOR_BALEARIC_ISLANDS_ES_IB = "\U0001f3f4\U000e0065\U000e0073\U000e0069\U000e0062\U000e007f"
- FLAG_FOR_BATKEN_KG_B = "\U0001f3f4\U000e006b\U000e0067\U000e0062\U000e007f"
- FLAG_FOR_NAKHCHIVAN_AR_AZ_NX = "\U0001f3f4\U000e0061\U000e007a\U000e006e\U000e0078\U000e007f"
- FLAG_FOR_SAINT_LUCY_BB_07 = "\U0001f3f4\U000e0062\U000e0062\U000e0030\U000e0037\U000e007f"
- TAG_LATIN_SMALL_LETTER_N = "\U000e006e"
- FLAG_FOR_INDIANA_US_IN = "\U0001f3f4\U000e0075\U000e0073\U000e0069\U000e006e\U000e007f"
- FLAG_FOR_SAINT_JOSEPH_BB_06 = "\U0001f3f4\U000e0062\U000e0062\U000e0030\U000e0036\U000e007f"
- FAMILY_MAN_WOMAN_BABY_BOY = "\U0001f468\u200d\U0001f469\u200d\U0001f476\u200d\U0001f466"
- FLAG_FOR_TARTAR_AZ_TAR = "\U0001f3f4\U000e0061\U000e007a\U000e0074\U000e0061\U000e0072\U000e007f"
- CONJUNCTION = "\u260c"
- FLAG_FOR_SAINT_ROMAN_MC_SR = "\U0001f3f4\U000e006d\U000e0063\U000e0073\U000e0072\U000e007f"
- FLAG_FOR_BREST_BY_BR = "\U0001f3f4\U000e0062\U000e0079\U000e0062\U000e0072\U000e007f"
- WOMAN_IN_TUXEDO_MEDIUM_SKIN_TONE = "\U0001f935\U0001f3fd\u200d\u2640\ufe0f"
- FLAG_FOR_SASKATCHEWAN_CA_SK = "\U0001f3f4\U000e0063\U000e0061\U000e0073\U000e006b\U000e007f"
- FLAG_FOR_SAINT_GEORGE_VC_04 = "\U0001f3f4\U000e0076\U000e0063\U000e0030\U000e0034\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f466\U0001f3fb"
- MAHJONG_TILE_THREE_OF_CHARACTERS = "\U0001f009"
- FLAG_FOR_SAINT_PHILIP_BB_10 = "\U0001f3f4\U000e0062\U000e0062\U000e0031\U000e0030\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_ZARDAB_AZ_ZAR = "\U0001f3f4\U000e0061\U000e007a\U000e007a\U000e0061\U000e0072\U000e007f"
- FAMILY_MAN_MAN_BABY_BOY = "\U0001f468\u200d\U0001f468\u200d\U0001f476\u200d\U0001f466"
- FLAG_FOR_BARISAL_BD_A = "\U0001f3f4\U000e0062\U000e0064\U000e0061\U000e007f"
- FLAG_FOR_SANTO_DOMINGO_DE_LOS_TSACHILAS_EC_SD = "\U0001f3f4\U000e0065\U000e0063\U000e0073\U000e0064\U000e007f"
- FLAG_FOR_ZANGILAN_AZ_ZAN = "\U0001f3f4\U000e0061\U000e007a\U000e007a\U000e0061\U000e006e\U000e007f"
- INTERLOCKED_FEMALE_AND_MALE_SIGN = "\u26a4"
- FLAG_FOR_WESTERN_LK_1 = "\U0001f3f4\U000e006c\U000e006b\U000e0031\U000e007f"
- FLAG_FOR_KINGSTON_JM_01 = "\U0001f3f4\U000e006a\U000e006d\U000e0030\U000e0031\U000e007f"
- DIESEL_LOCOMOTIVE = "\U0001f6f2"
- NOTE = "\U0001f5c8"
- MAHJONG_TILE_EIGHT_OF_CHARACTERS = "\U0001f00e"
- SIDEWAYS_WHITE_RIGHT_POINTING_INDEX = "\U0001f599"
- TAG_LESS_THAN_SIGN = "\U000e003c"
- FLAG_FOR_RAJSHAHI_DIVISION_BD_E = "\U0001f3f4\U000e0062\U000e0064\U000e0065\U000e007f"
- KISS_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc"
- FAMILY_WOMAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_SARDINIA_IT_88 = "\U0001f3f4\U000e0069\U000e0074\U000e0038\U000e0038\U000e007f"
- HEAVY_WHITE_DOWN_POINTING_TRIANGLE = "\u26db"
- FLAG_FOR_KHULNA_DIVISION_BD_D = "\U0001f3f4\U000e0062\U000e0064\U000e0064\U000e007f"
- FLAG_FOR_SAINT_PETER_BB_09 = "\U0001f3f4\U000e0062\U000e0062\U000e0030\U000e0039\U000e007f"
- MUSIC_SHARP_SIGN = "\u266f"
- RIGHT_HANDED_INTERLACED_PENTAGRAM = "\u26e5"
- TAG_LATIN_SMALL_LETTER_C = "\U000e0063"
- FLAG_FOR_ADDIS_ABABA_ET_AA = "\U0001f3f4\U000e0065\U000e0074\U000e0061\U000e0061\U000e007f"
- FLAG_FOR_PORTLAND_JM_04 = "\U0001f3f4\U000e006a\U000e006d\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_MYMENSINGH_DIVISION_BD_H = "\U0001f3f4\U000e0062\U000e0064\U000e0068\U000e007f"
- FLAG_FOR_PORT_OF_SPAIN_TT_POS = "\U0001f3f4\U000e0074\U000e0074\U000e0070\U000e006f\U000e0073\U000e007f"
- FLAG_FOR_CASANARE_CO_CAS = "\U0001f3f4\U000e0063\U000e006f\U000e0063\U000e0061\U000e0073\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_Q = "\U000e0051"
- TRIGRAM_FOR_THUNDER = "\u2633"
- POCKET_CALCULATOR = "\U0001f5a9"
- RIGHT_SPEAKER_WITH_ONE_SOUND_WAVE = "\U0001f569"
- FLAG_FOR_LOS_SANTOS_PA_7 = "\U0001f3f4\U000e0070\U000e0061\U000e0037\U000e007f"
- FLAG_FOR_LOWER_AUSTRIA_AT_3 = "\U0001f3f4\U000e0061\U000e0074\U000e0033\U000e007f"
- FLAG_FOR_SUMQAYIT_AZ_SM = "\U0001f3f4\U000e0061\U000e007a\U000e0073\U000e006d\U000e007f"
- FLAG_FOR_CASCADES_BF_02 = "\U0001f3f4\U000e0062\U000e0066\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_BOUCLE_DU_MOUHOUN_BF_01 = "\U0001f3f4\U000e0062\U000e0066\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_AL_HUDAYDAH_YE_HU = "\U0001f3f4\U000e0079\U000e0065\U000e0068\U000e0075\U000e007f"
- FLAG_FOR_SAINT_PATRICK_GD_06 = "\U0001f3f4\U000e0067\U000e0064\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_NOVA_SCOTIA_CA_NS = "\U0001f3f4\U000e0063\U000e0061\U000e006e\U000e0073\U000e007f"
- FLAG_FOR_MINAS_GERAIS_BR_MG = "\U0001f3f4\U000e0062\U000e0072\U000e006d\U000e0067\U000e007f"
- FLAG_FOR_CENTRE_SUD_BF_07 = "\U0001f3f4\U000e0062\U000e0066\U000e0030\U000e0037\U000e007f"
- MUSICAL_KEYBOARD_WITH_JACKS = "\U0001f398"
- FLAG_FOR_BENGO_AO_BGO = "\U0001f3f4\U000e0061\U000e006f\U000e0062\U000e0067\U000e006f\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_CENTRE_OUEST_BF_06 = "\U0001f3f4\U000e0062\U000e0066\U000e0030\U000e0036\U000e007f"
- GEAR_WITHOUT_HUB = "\u26ed"
- FAMILY_MAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FLAG_FOR_CENTRE_BF_03 = "\U0001f3f4\U000e0062\U000e0066\U000e0030\U000e0033\U000e007f"
- FAMILY_WOMAN_MAN_GIRL_GIRL = "\U0001f469\u200d\U0001f468\u200d\U0001f467\u200d\U0001f467"
- WHITE_TWO_WAY_LEFT_WAY_TRAFFIC = "\u26d7"
- FLAG_FOR_HOWLAND_ISLAND_UM_84 = "\U0001f3f4\U000e0075\U000e006d\U000e0038\U000e0034\U000e007f"
- FLAG_FOR_EST_BF_08 = "\U0001f3f4\U000e0062\U000e0066\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_ELBASAN_COUNTY_AL_03 = "\U0001f3f4\U000e0061\U000e006c\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_RATAK_CHAIN_MH_T = "\U0001f3f4\U000e006d\U000e0068\U000e0074\U000e007f"
- FLAG_FOR_CANARY_ISLANDS_ES_CN = "\U0001f3f4\U000e0065\U000e0073\U000e0063\U000e006e\U000e007f"
- FLAG_FOR_PLATEAU_CENTRAL_BF_11 = "\U0001f3f4\U000e0062\U000e0066\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_DOUKKALA_ABDA_MA_10 = "\U0001f3f4\U000e006d\U000e0061\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_TERENGGANU_MY_11 = "\U0001f3f4\U000e006d\U000e0079\U000e0031\U000e0031\U000e007f"
- MAN_WITH_HEADSCARF_MEDIUM_DARK_SKIN_TONE = "\U0001f9d5\U0001f3fe\u200d\u2642\ufe0f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_SANTA_CRUZ_AR_Z = "\U0001f3f4\U000e0061\U000e0072\U000e007a\U000e007f"
- FLAG_FOR_DHAKA_DIVISION_BD_C = "\U0001f3f4\U000e0062\U000e0064\U000e0063\U000e007f"
- FLAG_FOR_JUJUY_AR_Y = "\U0001f3f4\U000e0061\U000e0072\U000e0079\U000e007f"
- CIRCLED_INFORMATION_SOURCE = "\U0001f6c8"
- FLAG_FOR_SYLHET_DIVISION_BD_G = "\U0001f3f4\U000e0062\U000e0064\U000e0067\U000e007f"
- FLAG_FOR_VIDIN_BG_05 = "\U0001f3f4\U000e0062\U000e0067\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_ARKHANGELSK_RU_ARK = "\U0001f3f4\U000e0072\U000e0075\U000e0061\U000e0072\U000e006b\U000e007f"
- MAHJONG_TILE_ONE_OF_CHARACTERS = "\U0001f007"
- FLAG_FOR_BADAKHSHAN_AF_BDS = "\U0001f3f4\U000e0061\U000e0066\U000e0062\U000e0064\U000e0073\U000e007f"
- FLAG_FOR_ALGIERS_DZ_16 = "\U0001f3f4\U000e0064\U000e007a\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_STEPANAKERT_AZ_XA = "\U0001f3f4\U000e0061\U000e007a\U000e0078\U000e0061\U000e007f"
- FLAG_FOR_GABROVO_BG_07 = "\U0001f3f4\U000e0062\U000e0067\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_BUENOS_AIRES_PROVINCE_AR_B = "\U0001f3f4\U000e0061\U000e0072\U000e0062\U000e007f"
- FLAG_FOR_DOBRICH_BG_08 = "\U0001f3f4\U000e0062\U000e0067\U000e0030\U000e0038\U000e007f"
- BLACK_PENNANT = "\U0001f3f2"
- FLAG_FOR_CENTRE_EST_BF_04 = "\U0001f3f4\U000e0062\U000e0066\U000e0030\U000e0034\U000e007f"
- COUPLE_WITH_HEART_MAN_DARK_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb"
- KISS_MAN_LIGHT_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_BAHIA_BR_BA = "\U0001f3f4\U000e0062\U000e0072\U000e0062\U000e0061\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb"
- MAHJONG_TILE_FIVE_OF_CHARACTERS = "\U0001f00b"
- KISS_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_AKITA_JP_05 = "\U0001f3f4\U000e006a\U000e0070\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_KYUSTENDIL_BG_10 = "\U0001f3f4\U000e0062\U000e0067\U000e0031\U000e0030\U000e007f"
- CHIRON = "\u26b7"
- FLAG_FOR_RALIK_CHAIN_MH_L = "\U0001f3f4\U000e006d\U000e0068\U000e006c\U000e007f"
- FLAG_FOR_LOVECH_BG_11 = "\U0001f3f4\U000e0062\U000e0067\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_VAYOTS_DZOR_AM_VD = "\U0001f3f4\U000e0061\U000e006d\U000e0076\U000e0064\U000e007f"
- FLAG_FOR_BANTEAY_MEANCHEY_KH_1 = "\U0001f3f4\U000e006b\U000e0068\U000e0031\U000e007f"
- FLAG_FOR_PAZARDZHIK_BG_13 = "\U0001f3f4\U000e0062\U000e0067\U000e0031\U000e0033\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f467\U0001f3fe"
- DIE_FACE_5 = "\u2684"
- FAMILY_WOMAN_WOMAN_BABY_GIRL = "\U0001f469\u200d\U0001f469\u200d\U0001f476\u200d\U0001f467"
- FLAG_FOR_BLAGOEVGRAD_BG_01 = "\U0001f3f4\U000e0062\U000e0067\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_CARRIACOU_AND_PETITE_MARTINIQUE_GD_10 = "\U0001f3f4\U000e0067\U000e0064\U000e0031\U000e0030\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_PLOVDIV_BG_16 = "\U0001f3f4\U000e0062\U000e0067\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_PLEVEN_BG_15 = "\U0001f3f4\U000e0062\U000e0067\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_NORD_BF_10 = "\U0001f3f4\U000e0062\U000e0066\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_KURDISTAN_IR_16 = "\U0001f3f4\U000e0069\U000e0072\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_DASHKASAN_AZ_DAS = "\U0001f3f4\U000e0061\U000e007a\U000e0064\U000e0061\U000e0073\U000e007f"
- COUPLE_WITH_HEART_MAN_DARK_SKIN_TONE_MAN = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468"
- FLAG_FOR_BORDJ_BOU_ARRERIDJ_DZ_34 = "\U0001f3f4\U000e0064\U000e007a\U000e0033\U000e0034\U000e007f"
- TAG_AMPERSAND = "\U000e0026"
- FLAG_FOR_VALLEE_DU_BANDAMA_CI_VB = "\U0001f3f4\U000e0063\U000e0069\U000e0076\U000e0062\U000e007f"
- FLAG_FOR_RAZGRAD_BG_17 = "\U0001f3f4\U000e0062\U000e0067\U000e0031\U000e0037\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_SOFIA_BG_22 = "\U0001f3f4\U000e0062\U000e0067\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_SOFIA_DISTRICT_BG_23 = "\U0001f3f4\U000e0062\U000e0067\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_TARGOVISHTE_BG_25 = "\U0001f3f4\U000e0062\U000e0067\U000e0032\U000e0035\U000e007f"
- FLAG_FOR_LOPBURI_TH_16 = "\U0001f3f4\U000e0074\U000e0068\U000e0031\U000e0036\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_CUNENE_AO_CNN = "\U0001f3f4\U000e0061\U000e006f\U000e0063\U000e006e\U000e006e\U000e007f"
- FLAG_FOR_ADJARA_GE_AJ = "\U0001f3f4\U000e0067\U000e0065\U000e0061\U000e006a\U000e007f"
- COUPLE_WITH_HEART_MAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_VARNA_BG_03 = "\U0001f3f4\U000e0062\U000e0067\U000e0030\U000e0033\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_YOBE_NG_YO = "\U0001f3f4\U000e006e\U000e0067\U000e0079\U000e006f\U000e007f"
- FLAG_FOR_PERNIK_BG_14 = "\U0001f3f4\U000e0062\U000e0067\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_BAY_SOMALIA_SO_BY = "\U0001f3f4\U000e0073\U000e006f\U000e0062\U000e0079\U000e007f"
- FLAG_FOR_SAINT_GEORGE_BB_03 = "\U0001f3f4\U000e0062\U000e0062\U000e0030\U000e0033\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f476\U0001f3fb"
- WOMAN_WITH_HEADSCARF_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d5\U0001f3fc\u200d\u2640\ufe0f"
- FLAG_FOR_WESTERN_CAPE_ZA_WC = "\U0001f3f4\U000e007a\U000e0061\U000e0077\U000e0063\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FLAG_FOR_HASKOVO_BG_26 = "\U0001f3f4\U000e0062\U000e0067\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_YAMBOL_BG_28 = "\U0001f3f4\U000e0062\U000e0067\U000e0032\U000e0038\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_SCHAAN_LI_07 = "\U0001f3f4\U000e006c\U000e0069\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_STREDOCESKY_KRAJ_CZ_20 = "\U0001f3f4\U000e0063\U000e007a\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_ZAVRC_SI_143 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0034\U000e0033\U000e007f"
- COUPLE_WITH_HEART_WOMAN_LIGHT_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff"
- FLAG_FOR_TACHIRA_VE_S = "\U0001f3f4\U000e0076\U000e0065\U000e0073\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_SOUTHERN_BH_14 = "\U0001f3f4\U000e0062\U000e0068\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_SIBIU_RO_SB = "\U0001f3f4\U000e0072\U000e006f\U000e0073\U000e0062\U000e007f"
- COUPLE_WITH_HEART_WOMAN_LIGHT_SKIN_TONE_WOMAN = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469"
- DIE_FACE_1 = "\u2680"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_SOUTHERN_IS_8 = "\U0001f3f4\U000e0069\U000e0073\U000e0038\U000e007f"
- FLAG_FOR_MUHARRAQ_BH_15 = "\U0001f3f4\U000e0062\U000e0068\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_BRUSSELS_BE_BRU = "\U0001f3f4\U000e0062\U000e0065\U000e0062\U000e0072\U000e0075\U000e007f"
- KISS_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff"
- WOMAN_WITH_HEADSCARF_MEDIUM_SKIN_TONE = "\U0001f9d5\U0001f3fd\u200d\u2640\ufe0f"
- FLAG_FOR_CENTRE_NORD_BF_05 = "\U0001f3f4\U000e0062\U000e0066\U000e0030\U000e0035\U000e007f"
- ENVELOPE_WITH_LIGHTNING = "\U0001f584"
- FLAG_FOR_COLORADO_US_CO = "\U0001f3f4\U000e0075\U000e0073\U000e0063\U000e006f\U000e007f"
- FLAG_FOR_CAPITAL_BH_13 = "\U0001f3f4\U000e0062\U000e0068\U000e0031\U000e0033\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_TATARSTAN_RU_TA = "\U0001f3f4\U000e0072\U000e0075\U000e0074\U000e0061\U000e007f"
- FLAG_FOR_NORTHERN_BH_17 = "\U0001f3f4\U000e0062\U000e0068\U000e0031\U000e0037\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_BUJUMBURA_BI_BM = "\U0001f3f4\U000e0062\U000e0069\U000e0062\U000e006d\U000e007f"
- WEST_SYRIAC_CROSS = "\u2670"
- FLAG_FOR_SA_DAH_YE_SD = "\U0001f3f4\U000e0079\U000e0065\U000e0073\U000e0064\U000e007f"
- FLAG_FOR_AL_QASSIM_SA_05 = "\U0001f3f4\U000e0073\U000e0061\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_CANKUZO_BI_CA = "\U0001f3f4\U000e0062\U000e0069\U000e0063\U000e0061\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FLAG_FOR_NORTHERN_TERRITORY_AU_NT = "\U0001f3f4\U000e0061\U000e0075\U000e006e\U000e0074\U000e007f"
- CROSS_OF_JERUSALEM = "\u2629"
- FLAG_FOR_CHUKOTKA_OKRUG_RU_CHU = "\U0001f3f4\U000e0072\U000e0075\U000e0063\U000e0068\U000e0075\U000e007f"
- FLAG_FOR_KARDZHALI_BG_09 = "\U0001f3f4\U000e0062\U000e0067\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_SALA_LV_085 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0038\U000e0035\U000e007f"
- FLAG_FOR_CENTRAL_DENMARK_DK_82 = "\U0001f3f4\U000e0064\U000e006b\U000e0038\U000e0032\U000e007f"
- FLAG_FOR_BURURI_BI_BR = "\U0001f3f4\U000e0062\U000e0069\U000e0062\U000e0072\U000e007f"
- FLAG_FOR_WALLONIA_BE_WAL = "\U0001f3f4\U000e0062\U000e0065\U000e0077\U000e0061\U000e006c\U000e007f"
- KISS_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd"
- TAG_LATIN_SMALL_LETTER_G = "\U000e0067"
- FLAG_FOR_MARTINIQUE_FR_MQ = "\U0001f3f4\U000e0066\U000e0072\U000e006d\U000e0071\U000e007f"
- FLAG_FOR_KARUZI_BI_KR = "\U0001f3f4\U000e0062\U000e0069\U000e006b\U000e0072\U000e007f"
- FLAG_FOR_BABYLON_IQ_BB = "\U0001f3f4\U000e0069\U000e0071\U000e0062\U000e0062\U000e007f"
- FLAG_FOR_KIRUNDO_BI_KI = "\U0001f3f4\U000e0062\U000e0069\U000e006b\U000e0069\U000e007f"
- FLAG_FOR_LANKARAN_DISTRICT_AZ_LAN = "\U0001f3f4\U000e0061\U000e007a\U000e006c\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_MURAMVYA_BI_MU = "\U0001f3f4\U000e0062\U000e0069\U000e006d\U000e0075\U000e007f"
- FLAG_FOR_MUYINGA_BI_MY = "\U0001f3f4\U000e0062\U000e0069\U000e006d\U000e0079\U000e007f"
- FLAG_FOR_TIANJIN_CN_12 = "\U0001f3f4\U000e0063\U000e006e\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_LAAYOUNE_BOUJDOUR_SAKIA_EL_HAMRA_MA_15 = "\U0001f3f4\U000e006d\U000e0061\U000e0031\U000e0035\U000e007f"
- DIGRAM_FOR_GREATER_YANG = "\u268c"
- FLAG_FOR_SHUMEN_BG_27 = "\U0001f3f4\U000e0062\U000e0067\U000e0032\U000e0037\U000e007f"
- RECYCLED_PAPER_SYMBOL = "\u267c"
- FLAG_FOR_NGOZI_BI_NG = "\U0001f3f4\U000e0062\U000e0069\U000e006e\U000e0067\U000e007f"
- FAMILY_WOMAN_MAN_BOY_BOY = "\U0001f469\u200d\U0001f468\u200d\U0001f466\u200d\U0001f466"
- KISS_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_SISTAN_AND_BALUCHESTAN_IR_13 = "\U0001f3f4\U000e0069\U000e0072\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_RUMONGE_BI_RM = "\U0001f3f4\U000e0062\U000e0069\U000e0072\U000e006d\U000e007f"
- FLAG_FOR_AOSTA_VALLEY_IT_23 = "\U0001f3f4\U000e0069\U000e0074\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_NOVO_MESTO_SI_085 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0038\U000e0035\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f476\U0001f3fc"
- BEAMED_SIXTEENTH_NOTES = "\u266c"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_HAUTS_DE_FRANCE_FR_HDF = "\U0001f3f4\U000e0066\U000e0072\U000e0068\U000e0064\U000e0066\U000e007f"
- FLAG_FOR_RIO_NEGRO_AR_R = "\U0001f3f4\U000e0061\U000e0072\U000e0072\U000e007f"
- WHITE_CHESS_KNIGHT = "\u2658"
- FLAG_FOR_ALIBORI_BJ_AL = "\U0001f3f4\U000e0062\U000e006a\U000e0061\U000e006c\U000e007f"
- FLAG_FOR_DONGA_BJ_DO = "\U0001f3f4\U000e0062\U000e006a\U000e0064\U000e006f\U000e007f"
- FLAG_FOR_HAMBURG_DE_HH = "\U0001f3f4\U000e0064\U000e0065\U000e0068\U000e0068\U000e007f"
- FLAG_FOR_SAHEL_BF_12 = "\U0001f3f4\U000e0062\U000e0066\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_ATAKORA_BJ_AK = "\U0001f3f4\U000e0062\U000e006a\U000e0061\U000e006b\U000e007f"
- FLAG_FOR_RUYIGI_BI_RY = "\U0001f3f4\U000e0062\U000e0069\U000e0072\U000e0079\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469"
- FLAG_FOR_MA_AN_JO_MN = "\U0001f3f4\U000e006a\U000e006f\U000e006d\U000e006e\U000e007f"
- FLAG_FOR_SMOLYAN_BG_21 = "\U0001f3f4\U000e0062\U000e0067\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_LITTORAL_BJ_LI = "\U0001f3f4\U000e0062\U000e006a\U000e006c\U000e0069\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_ZOU_BJ_ZO = "\U0001f3f4\U000e0062\U000e006a\U000e007a\U000e006f\U000e007f"
- FLAG_FOR_RED_SEA_EG_BA = "\U0001f3f4\U000e0065\U000e0067\U000e0062\U000e0061\U000e007f"
- FLAG_FOR_VLORE_COUNTY_AL_12 = "\U0001f3f4\U000e0061\U000e006c\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_KOPER_SI_050 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0035\U000e0030\U000e007f"
- KISS_WOMAN_DARK_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd"
- FAMILY_WOMAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FLAG_FOR_MANAWATU_WANGANUI_NZ_MWT = "\U0001f3f4\U000e006e\U000e007a\U000e006d\U000e0077\U000e0074\U000e007f"
- FLAG_FOR_ENTRE_RIOS_AR_E = "\U0001f3f4\U000e0061\U000e0072\U000e0065\U000e007f"
- FLAG_FOR_NORTH_DAKOTA_US_ND = "\U0001f3f4\U000e0075\U000e0073\U000e006e\U000e0064\U000e007f"
- MEDIUM_SMALL_WHITE_CIRCLE = "\u26ac"
- FLAG_FOR_BEQAA_LB_BI = "\U0001f3f4\U000e006c\U000e0062\U000e0062\U000e0069\U000e007f"
- FLAG_FOR_SEKONG_LA_XE = "\U0001f3f4\U000e006c\U000e0061\U000e0078\U000e0065\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_OUEME_BJ_OU = "\U0001f3f4\U000e0062\U000e006a\U000e006f\U000e0075\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc"
- BALLOT_BOX_WITH_SCRIPT_X = "\U0001f5f5"
- FLAG_FOR_TUTONG_BN_TU = "\U0001f3f4\U000e0062\U000e006e\U000e0074\U000e0075\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_VRATSA_BG_06 = "\U0001f3f4\U000e0062\U000e0067\U000e0030\U000e0036\U000e007f"
- MAN_WITH_HEADSCARF = "\U0001f9d5\u200d\u2642\ufe0f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468"
- FAMILY_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_KHENTII_MN_039 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0033\U000e0039\U000e007f"
- FLAG_FOR_DELTA_AMACURO_VE_Y = "\U0001f3f4\U000e0076\U000e0065\U000e0079\U000e007f"
- RECYCLING_SYMBOL_FOR_GENERIC_MATERIALS = "\u267a"
- FLAG_FOR_ASHANTI_GH_AH = "\U0001f3f4\U000e0067\U000e0068\U000e0061\U000e0068\U000e007f"
- FLAG_FOR_DOLNENI_MK_27 = "\U0001f3f4\U000e006d\U000e006b\U000e0032\U000e0037\U000e007f"
- BLACK_TRUCK = "\u26df"
- KISS_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe"
- FLAG_FOR_BORGOU_BJ_BO = "\U0001f3f4\U000e0062\U000e006a\U000e0062\U000e006f\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_SAINT_JAMES_BB_04 = "\U0001f3f4\U000e0062\U000e0062\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_PANDO_BO_N = "\U0001f3f4\U000e0062\U000e006f\U000e006e\U000e007f"
- FLAG_FOR_LA_PAZ_BO_L = "\U0001f3f4\U000e0062\U000e006f\U000e006c\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_STARA_ZAGORA_BG_24 = "\U0001f3f4\U000e0062\U000e0067\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_CHUQUISACA_BO_H = "\U0001f3f4\U000e0062\U000e006f\U000e0068\U000e007f"
- FLAG_FOR_GUMUSHANE_TR_29 = "\U0001f3f4\U000e0074\U000e0072\U000e0032\U000e0039\U000e007f"
- FLAG_FOR_PANJSHIR_AF_PAN = "\U0001f3f4\U000e0061\U000e0066\U000e0070\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_COCHABAMBA_BO_C = "\U0001f3f4\U000e0062\U000e006f\U000e0063\U000e007f"
- FLAG_FOR_ROCHE_CAIMAN_SC_25 = "\U0001f3f4\U000e0073\U000e0063\U000e0032\U000e0035\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f467\U0001f3ff"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_BRCKO_DISTRICT_BA_BRC = "\U0001f3f4\U000e0062\U000e0061\U000e0062\U000e0072\U000e0063\U000e007f"
- FLAG_FOR_BRETAGNE_FR_BRE = "\U0001f3f4\U000e0066\U000e0072\U000e0062\U000e0072\U000e0065\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe"
- FLAG_FOR_CHECHEN_RU_CE = "\U0001f3f4\U000e0072\U000e0075\U000e0063\U000e0065\U000e007f"
- FLAG_FOR_KICEVO_MK_40 = "\U0001f3f4\U000e006d\U000e006b\U000e0034\U000e0030\U000e007f"
- FLAG_FOR_SAINT_JOHN_BB_05 = "\U0001f3f4\U000e0062\U000e0062\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_NORTHERN_MARIANA_ISLANDS_US_MP = "\U0001f3f4\U000e0075\U000e0073\U000e006d\U000e0070\U000e007f"
- KISS_WOMAN_MAN_LIGHT_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb"
- FLAG_FOR_KAUNAS_COUNTY_LT_KU = "\U0001f3f4\U000e006c\U000e0074\U000e006b\U000e0075\U000e007f"
- FLAG_FOR_GJIROKASTER_COUNTY_AL_05 = "\U0001f3f4\U000e0061\U000e006c\U000e0030\U000e0035\U000e007f"
- KISS_MAN_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe"
- KISS_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc"
- KISS_MAN_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe"
- COUPLE_WITH_HEART_WOMAN_DARK_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd"
- KISS_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_LENART_SI_058 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0035\U000e0038\U000e007f"
- FLAG_FOR_TEMBURONG_BN_TE = "\U0001f3f4\U000e0062\U000e006e\U000e0074\U000e0065\U000e007f"
- FLAG_FOR_BELAIT_BN_BE = "\U0001f3f4\U000e0062\U000e006e\U000e0062\U000e0065\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb"
- KISS_WOMAN_LIGHT_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd"
- COUPLE_WITH_HEART_MAN_MEDIUM_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb"
- FAMILY_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FLAG_FOR_POTOSI_BO_P = "\U0001f3f4\U000e0062\U000e006f\U000e0070\U000e007f"
- KISS_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd"
- KISS_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc"
- MAN_WITH_HEADSCARF_DARK_SKIN_TONE = "\U0001f9d5\U0001f3ff\u200d\u2642\ufe0f"
- KISS_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f467\U0001f3fe"
- COUPLE_WITH_HEART_WOMAN_DARK_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc"
- SQUARE_FOUR_CORNERS = "\u26f6"
- KISS_WOMAN_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc"
- KISS_MAN_MEDIUM_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb"
- MAHJONG_TILE_ONE_OF_BAMBOOS = "\U0001f010"
- FLAG_FOR_TARIJA_BO_T = "\U0001f3f4\U000e0062\U000e006f\U000e0074\U000e007f"
- BLACK_CHESS_ROOK = "\u265c"
- FLAG_FOR_PREAH_VIHEAR_KH_13 = "\U0001f3f4\U000e006b\U000e0068\U000e0031\U000e0033\U000e007f"
- TRIGRAM_FOR_WATER = "\u2635"
- FLAG_FOR_VICTORIA_AU_VIC = "\U0001f3f4\U000e0061\U000e0075\U000e0076\U000e0069\U000e0063\U000e007f"
- KISS_MAN_MEDIUM_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff"
- FLAG_FOR_ANDORRA_LA_VELLA_AD_07 = "\U0001f3f4\U000e0061\U000e0064\U000e0030\U000e0037\U000e007f"
- KISS_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe"
- FLAG_FOR_ACRE_BR_AC = "\U0001f3f4\U000e0062\U000e0072\U000e0061\U000e0063\U000e007f"
- KISS_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_URI_CH_UR = "\U0001f3f4\U000e0063\U000e0068\U000e0075\U000e0072\U000e007f"
- KISS_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd"
- KISS_WOMAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff"
- COUPLE_WITH_HEART_MAN_LIGHT_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f467\U0001f3fc"
- KISS_WOMAN_DARK_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_SAN_SALVADOR_SV_SS = "\U0001f3f4\U000e0073\U000e0076\U000e0073\U000e0073\U000e007f"
- KISS_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe"
- KISS_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_MADRID_AUTONOMOUS_COMMUNITY_ES_MD = "\U0001f3f4\U000e0065\U000e0073\U000e006d\U000e0064\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_COLLINES_BJ_CO = "\U0001f3f4\U000e0062\U000e006a\U000e0063\U000e006f\U000e007f"
- KISS_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb"
- FLAG_FOR_KAYANZA_BI_KY = "\U0001f3f4\U000e0062\U000e0069\U000e006b\U000e0079\U000e007f"
- FLAG_FOR_AOMORI_JP_02 = "\U0001f3f4\U000e006a\U000e0070\U000e0030\U000e0032\U000e007f"
- TURNED_OK_HAND_SIGN = "\U0001f58f"
- BOOK = "\U0001f56e"
- COUPLE_WITH_HEART_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc"
- COUPLE_WITH_HEART_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd"
- KISS_WOMAN_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe"
- FLAG_FOR_FARO_PT_08 = "\U0001f3f4\U000e0070\U000e0074\U000e0030\U000e0038\U000e007f"
- COUPLE_WITH_HEART_MAN_DARK_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc"
- COUPLE_WITH_HEART_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe"
- FALLING_DIAGONAL_IN_WHITE_CIRCLE_IN_BLACK_SQUARE = "\u26de"
- FLAG_FOR_FRENCH_SOUTHERN_TERRITORIES_FR_TF = "\U0001f3f4\U000e0066\U000e0072\U000e0074\U000e0066\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_ISTANBUL_TR_34 = "\U0001f3f4\U000e0074\U000e0072\U000e0033\U000e0034\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_SUD_OUEST_BF_13 = "\U0001f3f4\U000e0062\U000e0066\U000e0031\U000e0033\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_FEDERAL_DEPENDENCIES_VE_W = "\U0001f3f4\U000e0076\U000e0065\U000e0077\U000e007f"
- COUPLE_WITH_HEART_MAN_DARK_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb"
- KISS_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb"
- FAMILY_MAN_WOMAN_GIRL_BABY = "\U0001f468\u200d\U0001f469\u200d\U0001f467\u200d\U0001f476"
- FLAG_FOR_LONG_ISLAND_BS_LI = "\U0001f3f4\U000e0062\U000e0073\U000e006c\U000e0069\U000e007f"
- FLAG_FOR_RANGPUR_DIVISION_BD_F = "\U0001f3f4\U000e0062\U000e0064\U000e0066\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff"
- FLAG_FOR_ALAGOAS_BR_AL = "\U0001f3f4\U000e0062\U000e0072\U000e0061\U000e006c\U000e007f"
- COUPLE_WITH_HEART_MAN_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe"
- KISS_WOMAN_MAN_DARK_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff"
- FLAG_FOR_MAIDAN_WARDAK_AF_WAR = "\U0001f3f4\U000e0061\U000e0066\U000e0077\U000e0061\U000e0072\U000e007f"
- COUPLE_WITH_HEART_MAN_DARK_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd"
- COUPLE_WITH_HEART_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff"
- FAMILY_MAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f467\U0001f3fb"
- COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_JALISCO_MX_JAL = "\U0001f3f4\U000e006d\U000e0078\U000e006a\U000e0061\U000e006c\U000e007f"
- FLAG_FOR_LAZIO_IT_62 = "\U0001f3f4\U000e0069\U000e0074\U000e0036\U000e0032\U000e007f"
- FLAG_FOR_SERGIPE_BR_SE = "\U0001f3f4\U000e0062\U000e0072\U000e0073\U000e0065\U000e007f"
- KISS_MAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_KOUFFO_BJ_KO = "\U0001f3f4\U000e0062\U000e006a\U000e006b\U000e006f\U000e007f"
- TAG_LATIN_SMALL_LETTER_L = "\U000e006c"
- TAG_LATIN_SMALL_LETTER_J = "\U000e006a"
- FLAG_FOR_BAKU_AZ_BA = "\U0001f3f4\U000e0061\U000e007a\U000e0062\U000e0061\U000e007f"
- FLAG_FOR_DAUGAVPILS_MUNICIPALITY_LV_025 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0032\U000e0035\U000e007f"
- KISS_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_VINH_LONG_VN_49 = "\U0001f3f4\U000e0076\U000e006e\U000e0034\U000e0039\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff"
- FLAG_FOR_STRASENI_MD_ST = "\U0001f3f4\U000e006d\U000e0064\U000e0073\U000e0074\U000e007f"
- FLAG_FOR_RORAIMA_BR_RR = "\U0001f3f4\U000e0062\U000e0072\U000e0072\U000e0072\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FLAG_FOR_BIMINI_BS_BI = "\U0001f3f4\U000e0062\U000e0073\U000e0062\U000e0069\U000e007f"
- COUPLE_WITH_HEART_MAN_DARK_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_NORTHERN_RED_SEA_ER_SK = "\U0001f3f4\U000e0065\U000e0072\U000e0073\U000e006b\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff"
- FLAG_FOR_TIARET_DZ_14 = "\U0001f3f4\U000e0064\U000e007a\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_SOGN_OG_FJORDANE_NO_14 = "\U0001f3f4\U000e006e\U000e006f\U000e0031\U000e0034\U000e007f"
- WHITE_LEFT_LANE_MERGE = "\u26d9"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_KHACHMAZ_AZ_XAC = "\U0001f3f4\U000e0061\U000e007a\U000e0078\U000e0061\U000e0063\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_SVETI_ANDRAZ_V_SLOVENSKIH_GORICAH_SI_182 = "\U0001f3f4\U000e0073\U000e0069\U000e0031\U000e0038\U000e0032\U000e007f"
- FLAG_FOR_BALOCHISTAN_PK_BA = "\U0001f3f4\U000e0070\U000e006b\U000e0062\U000e0061\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FLAG_FOR_TOCANTINS_BR_TO = "\U0001f3f4\U000e0062\U000e0072\U000e0074\U000e006f\U000e007f"
- FAMILY_WOMAN_MAN_BABY_GIRL = "\U0001f469\u200d\U0001f468\u200d\U0001f476\u200d\U0001f467"
- TAG_SEMICOLON = "\U000e003b"
- FLAG_FOR_EAST_GRAND_BAHAMA_BS_EG = "\U0001f3f4\U000e0062\U000e0073\U000e0065\U000e0067\U000e007f"
- FLAG_FOR_SOUTH_AEGEAN_GR_L = "\U0001f3f4\U000e0067\U000e0072\U000e006c\U000e007f"
- WOMAN_IN_BUSINESS_SUIT_LEVITATING = "\U0001f574\ufe0f\u200d\u2640\ufe0f"
- FLAG_FOR_MAKAMBA_BI_MA = "\U0001f3f4\U000e0062\U000e0069\U000e006d\U000e0061\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc"
- FLAG_FOR_CROOKED_ISLAND_BS_CK = "\U0001f3f4\U000e0062\U000e0073\U000e0063\U000e006b\U000e007f"
- KISS_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc"
- TAG_LATIN_SMALL_LETTER_K = "\U000e006b"
- FLAG_FOR_EXUMA_BS_EX = "\U0001f3f4\U000e0062\U000e0073\U000e0065\U000e0078\U000e007f"
- COUPLE_WITH_HEART_MAN_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe"
- FAMILY_MAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_PLATEAU_BJ_PL = "\U0001f3f4\U000e0062\U000e006a\U000e0070\U000e006c\U000e007f"
- KISS_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_FEDERAL_DISTRICT_BR_DF = "\U0001f3f4\U000e0062\U000e0072\U000e0064\U000e0066\U000e007f"
- FLAG_FOR_NEW_SOUTH_WALES_AU_NSW = "\U0001f3f4\U000e0061\U000e0075\U000e006e\U000e0073\U000e0077\U000e007f"
- FLAG_FOR_NORTH_ABACO_BS_NO = "\U0001f3f4\U000e0062\U000e0073\U000e006e\U000e006f\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FLAG_FOR_JERUSALEM_IL_JM = "\U0001f3f4\U000e0069\U000e006c\U000e006a\U000e006d\U000e007f"
- FLAG_FOR_INAGUA_BS_IN = "\U0001f3f4\U000e0062\U000e0073\U000e0069\U000e006e\U000e007f"
- FLAG_FOR_BOHINJ_SI_004 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_FREEPORT_BS_FP = "\U0001f3f4\U000e0062\U000e0073\U000e0066\U000e0070\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_CENTRAL_ELEUTHERA_BS_CE = "\U0001f3f4\U000e0062\U000e0073\U000e0063\U000e0065\U000e007f"
- FLAG_FOR_GRAND_CAY_BS_GC = "\U0001f3f4\U000e0062\U000e0073\U000e0067\U000e0063\U000e007f"
- TAG_LATIN_SMALL_LETTER_A = "\U000e0061"
- FLAG_FOR_MAYAGUANA_BS_MG = "\U0001f3f4\U000e0062\U000e0073\U000e006d\U000e0067\U000e007f"
- FLAG_FOR_SOUTH_AUSTRALIA_AU_SA = "\U0001f3f4\U000e0061\U000e0075\U000e0073\U000e0061\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f466\U0001f3fb"
- COUPLE_WITH_HEART_WOMAN_DARK_SKIN_TONE_MAN = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_KAOHSIUNG_TW_KHH = "\U0001f3f4\U000e0074\U000e0077\U000e006b\U000e0068\U000e0068\U000e007f"
- WOMAN_IN_BUSINESS_SUIT_LEVITATING_MEDIUM_DARK_SKIN_TONE = "\U0001f574\U0001f3fe\u200d\u2640\ufe0f"
- FLAG_FOR_TRANS_NZOIA_KE_42 = "\U0001f3f4\U000e006b\U000e0065\U000e0034\U000e0032\U000e007f"
- COUPLE_WITH_HEART_WOMAN_DARK_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb"
- FLAG_FOR_NORTH_ANDROS_BS_NS = "\U0001f3f4\U000e0062\U000e0073\U000e006e\U000e0073\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd"
- FAMILY_WOMAN_MAN_BOY_BABY = "\U0001f469\u200d\U0001f468\u200d\U0001f466\u200d\U0001f476"
- KISS_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FAMILY_MAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_OREGON_US_OR = "\U0001f3f4\U000e0075\U000e0073\U000e006f\U000e0072\U000e007f"
- KISS_MAN_LIGHT_SKIN_TONE_MAN = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468"
- FAMILY_MAN_BOY_BABY = "\U0001f468\u200d\U0001f466\u200d\U0001f476"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f467\U0001f3fb"
- KISS_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe"
- FLAG_FOR_OCCITANIE_FR_OCC = "\U0001f3f4\U000e0066\U000e0072\U000e006f\U000e0063\U000e0063\U000e007f"
- FLAG_FOR_EAST_AZERBAIJAN_IR_01 = "\U0001f3f4\U000e0069\U000e0072\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_SOUTH_ANDROS_BS_SA = "\U0001f3f4\U000e0062\U000e0073\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_AMAZONAS_BR_AM = "\U0001f3f4\U000e0062\U000e0072\U000e0061\U000e006d\U000e007f"
- FLAG_FOR_TANA_RIVER_KE_40 = "\U0001f3f4\U000e006b\U000e0065\U000e0034\U000e0030\U000e007f"
- KISS_MAN_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe"
- GEAR_WITH_HANDLES = "\u26ee"
- FLAG_FOR_SOUTH_ELEUTHERA_BS_SE = "\U0001f3f4\U000e0062\U000e0073\U000e0073\U000e0065\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_SKIN_TONE_WOMAN = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469"
- KISS_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff"
- KISS_MAN_MEDIUM_DARK_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb"
- KISS_MAN_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc"
- KISS_MAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb"
- KISS_WOMAN_LIGHT_SKIN_TONE_MAN = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468"
- COUPLE_WITH_HEART_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f467\U0001f3fe"
- KISS_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_SKIN_TONE_MAN = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468"
- KISS_WOMAN_MEDIUM_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff"
- FLAG_FOR_BUDAPEST_HU_BU = "\U0001f3f4\U000e0068\U000e0075\U000e0062\U000e0075\U000e007f"
- KISS_MAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff"
- KISS_MAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc"
- SIDEWAYS_BLACK_RIGHT_POINTING_INDEX = "\U0001f59b"
- KISS_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff"
- KISS_WOMAN_LIGHT_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe"
- KISS_WOMAN_DARK_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_SOUTH_ABACO_BS_SO = "\U0001f3f4\U000e0062\U000e0073\U000e0073\U000e006f\U000e007f"
- KISS_WOMAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb"
- COUPLE_WITH_HEART_MAN_DARK_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_RUM_CAY_BS_RC = "\U0001f3f4\U000e0062\U000e0073\U000e0072\U000e0063\U000e007f"
- TAG_SOLIDUS = "\U000e002f"
- COUPLE_WITH_HEART_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff"
- FAMILY_MAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f466\U0001f3fd"
- COUPLE_WITH_HEART_MAN_MEDIUM_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff"
- FAMILY_MAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FAMILY_MAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f476\U0001f3ff"
- COUPLE_WITH_HEART_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe"
- FAMILY_WOMAN_BOY_GIRL = "\U0001f469\u200d\U0001f466\u200d\U0001f467"
- COUPLE_WITH_HEART_MAN_LIGHT_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe"
- FLAG_FOR_ANSE_ROYALE_SC_05 = "\U0001f3f4\U000e0073\U000e0063\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_DELHI_IN_DL = "\U0001f3f4\U000e0069\U000e006e\U000e0064\U000e006c\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FAMILY_MAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f476\U0001f3fb"
- KISS_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_THIMPHU_BT_15 = "\U0001f3f4\U000e0062\U000e0074\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_CIEGO_DE_AVILA_CU_08 = "\U0001f3f4\U000e0063\U000e0075\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_PARO_BT_11 = "\U0001f3f4\U000e0062\U000e0074\U000e0031\U000e0031\U000e007f"
- KISS_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe"
- FLAG_FOR_HAA_BT_13 = "\U0001f3f4\U000e0062\U000e0074\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_MADHYA_PRADESH_IN_MP = "\U0001f3f4\U000e0069\U000e006e\U000e006d\U000e0070\U000e007f"
- KISS_MAN_LIGHT_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_WEST_GRAND_BAHAMA_BS_WG = "\U0001f3f4\U000e0062\U000e0073\U000e0077\U000e0067\U000e007f"
- FLAG_FOR_PYONGYANG_KP_01 = "\U0001f3f4\U000e006b\U000e0070\U000e0030\U000e0031\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f469\U0001f3fd\u200d\U0001f466\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_DAGANA_BT_22 = "\U0001f3f4\U000e0062\U000e0074\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_ZHEMGANG_BT_34 = "\U0001f3f4\U000e0062\U000e0074\U000e0033\U000e0034\U000e007f"
- FLAG_FOR_SARPANG_BT_31 = "\U0001f3f4\U000e0062\U000e0074\U000e0033\U000e0031\U000e007f"
- KISS_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_KUNDUZ_AF_KDZ = "\U0001f3f4\U000e0061\U000e0066\U000e006b\U000e0064\U000e007a\U000e007f"
- FLAG_FOR_TRASHIGANG_BT_41 = "\U0001f3f4\U000e0062\U000e0074\U000e0034\U000e0031\U000e007f"
- COUPLE_WITH_HEART_WOMAN_DARK_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_TRONGSA_BT_32 = "\U0001f3f4\U000e0062\U000e0074\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_BUMTHANG_BT_33 = "\U0001f3f4\U000e0062\U000e0074\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_MONGAR_BT_42 = "\U0001f3f4\U000e0062\U000e0074\U000e0034\U000e0032\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f466\U0001f3ff"
- KISS_WOMAN_LIGHT_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_PEMAGATSHEL_BT_43 = "\U0001f3f4\U000e0062\U000e0074\U000e0034\U000e0033\U000e007f"
- FLAG_FOR_ACKLINS_BS_AK = "\U0001f3f4\U000e0062\U000e0073\U000e0061\U000e006b\U000e007f"
- FLAG_FOR_CHOBE_BW_CH = "\U0001f3f4\U000e0062\U000e0077\U000e0063\U000e0068\U000e007f"
- FLAG_FOR_SALTA_AR_A = "\U0001f3f4\U000e0061\U000e0072\U000e0061\U000e007f"
- FLAG_FOR_LHUNTSE_BT_44 = "\U0001f3f4\U000e0062\U000e0074\U000e0034\U000e0034\U000e007f"
- FLAG_FOR_TRASHIYANGTSE_BT_TY = "\U0001f3f4\U000e0062\U000e0074\U000e0074\U000e0079\U000e007f"
- COUPLE_WITH_HEART_MAN_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe"
- FLAG_FOR_NEW_MEXICO_US_NM = "\U0001f3f4\U000e0075\U000e0073\U000e006e\U000e006d\U000e007f"
- FAMILY_MAN_MAN_BABY = "\U0001f468\u200d\U0001f468\u200d\U0001f476"
- LIGHTNING_MOOD_BUBBLE = "\U0001f5f1"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_JWANENG_BW_JW = "\U0001f3f4\U000e0062\U000e0077\U000e006a\U000e0077\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f467\U0001f3fd"
- KISS_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb"
- COUPLE_WITH_HEART_MAN_MEDIUM_SKIN_TONE_MAN = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468"
- FLAG_FOR_SOUTH_EAST_BW_SE = "\U0001f3f4\U000e0062\U000e0077\U000e0073\U000e0065\U000e007f"
- LEFT_HANDED_INTERLACED_PENTAGRAM = "\u26e6"
- FLAG_FOR_ATLANTIQUE_BJ_AQ = "\U0001f3f4\U000e0062\U000e006a\U000e0061\U000e0071\U000e007f"
- FLAG_FOR_CENTRAL_BW_CE = "\U0001f3f4\U000e0062\U000e0077\U000e0063\U000e0065\U000e007f"
- FLAG_FOR_WANGDUE_PHODRANG_BT_24 = "\U0001f3f4\U000e0062\U000e0074\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_KGATLENG_BW_KL = "\U0001f3f4\U000e0062\U000e0077\U000e006b\U000e006c\U000e007f"
- FLAG_FOR_RONDONIA_BR_RO = "\U0001f3f4\U000e0062\U000e0072\U000e0072\U000e006f\U000e007f"
- FLAG_FOR_CENTRAL_FINLAND_FI_08 = "\U0001f3f4\U000e0066\U000e0069\U000e0030\U000e0038\U000e007f"
- KISS_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469"
- FLAG_FOR_RUTANA_BI_RT = "\U0001f3f4\U000e0062\U000e0069\U000e0072\U000e0074\U000e007f"
- FLAG_FOR_GHANZI_BW_GH = "\U0001f3f4\U000e0062\U000e0077\U000e0067\U000e0068\U000e007f"
- FLAG_FOR_KGALAGADI_BW_KG = "\U0001f3f4\U000e0062\U000e0077\U000e006b\U000e0067\U000e007f"
- FLAG_FOR_NORTH_EAST_BW_NE = "\U0001f3f4\U000e0062\U000e0077\U000e006e\U000e0065\U000e007f"
- FLAG_FOR_TISINA_SI_010 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_KWENENG_BW_KW = "\U0001f3f4\U000e0062\U000e0077\U000e006b\U000e0077\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MAN_LIGHT_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb"
- FLAG_FOR_SAMDRUP_JONGKHAR_BT_45 = "\U0001f3f4\U000e0062\U000e0074\U000e0034\U000e0035\U000e007f"
- FLAG_FOR_SAMTSE_BT_14 = "\U0001f3f4\U000e0062\U000e0074\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_JIHOCESKY_KRAJ_CZ_31 = "\U0001f3f4\U000e0063\U000e007a\U000e0033\U000e0031\U000e007f"
- FLAG_FOR_CHRIST_CHURCH_BB_01 = "\U0001f3f4\U000e0062\U000e0062\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_SELIBE_PHIKWE_BW_SP = "\U0001f3f4\U000e0062\U000e0077\U000e0073\U000e0070\U000e007f"
- KISS_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe"
- COUPLE_WITH_HEART_MAN_LIGHT_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff"
- FAMILY_MAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FAMILY_MAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FLAG_FOR_NORTH_WEST_BW_NW = "\U0001f3f4\U000e0062\U000e0077\U000e006e\U000e0077\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468"
- FLAG_FOR_SOWA_TOWN_BW_ST = "\U0001f3f4\U000e0062\U000e0077\U000e0073\U000e0074\U000e007f"
- FAMILY_WOMAN_MAN_BABY_BABY = "\U0001f469\u200d\U0001f468\u200d\U0001f476\u200d\U0001f476"
- WHITE_CHESS_KING = "\u2654"
- FLAG_FOR_ORURO_BO_O = "\U0001f3f4\U000e0062\U000e006f\U000e006f\U000e007f"
- FLAG_FOR_PHOENIX_ISLANDS_KI_P = "\U0001f3f4\U000e006b\U000e0069\U000e0070\U000e007f"
- FLAG_FOR_PIAUI_BR_PI = "\U0001f3f4\U000e0062\U000e0072\U000e0070\U000e0069\U000e007f"
- FLAG_FOR_HRODNA_BY_HR = "\U0001f3f4\U000e0062\U000e0079\U000e0068\U000e0072\U000e007f"
- FLAG_FOR_HOMEL_BY_HO = "\U0001f3f4\U000e0062\U000e0079\U000e0068\U000e006f\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_MINSK_BY_HM = "\U0001f3f4\U000e0062\U000e0079\U000e0068\U000e006d\U000e007f"
- KISS_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe"
- FLAG_FOR_CHITTAGONG_DIVISION_BD_B = "\U0001f3f4\U000e0062\U000e0064\U000e0062\U000e007f"
- MAP_SYMBOL_FOR_LIGHTHOUSE = "\u26ef"
- FAMILY_WOMAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_MOORE_S_ISLAND_BS_MI = "\U0001f3f4\U000e0062\U000e0073\U000e006d\U000e0069\U000e007f"
- FLAG_FOR_MINSK_REGION_BY_MI = "\U0001f3f4\U000e0062\U000e0079\U000e006d\U000e0069\U000e007f"
- COUPLE_WITH_HEART_MAN_LIGHT_SKIN_TONE_WOMAN = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_GUARDA_PT_09 = "\U0001f3f4\U000e0070\U000e0074\U000e0030\U000e0039\U000e007f"
- KISS_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469"
- FAMILY_MAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FAMILY_WOMAN_BABY_GIRL = "\U0001f469\u200d\U0001f476\u200d\U0001f467"
- FAMILY_MAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE_BOY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f466\U0001f3fb\u200d\U0001f466\U0001f3fb"
- FLAG_FOR_VITEBSK_BY_VI = "\U0001f3f4\U000e0062\U000e0079\U000e0076\U000e0069\U000e007f"
- FLAG_FOR_CASTILE_LA_MANCHA_ES_CM = "\U0001f3f4\U000e0065\U000e0073\U000e0063\U000e006d\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_ALMATY_KZ_ALA = "\U0001f3f4\U000e006b\U000e007a\U000e0061\U000e006c\U000e0061\U000e007f"
- FLAG_FOR_METRO_MANILA_PH_00 = "\U0001f3f4\U000e0070\U000e0068\U000e0030\U000e0030\U000e007f"
- FLAG_FOR_MAGILEU_BY_MA = "\U0001f3f4\U000e0062\U000e0079\U000e006d\U000e0061\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f476\U0001f3fb"
- COUPLE_WITH_HEART_MAN_DARK_SKIN_TONE_WOMAN = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469"
- FLAG_FOR_SILISTRA_BG_19 = "\U0001f3f4\U000e0062\U000e0067\U000e0031\U000e0039\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_STANN_CREEK_BZ_SC = "\U0001f3f4\U000e0062\U000e007a\U000e0073\U000e0063\U000e007f"
- FLAG_FOR_NORTH_ELEUTHERA_BS_NE = "\U0001f3f4\U000e0062\U000e0073\U000e006e\U000e0065\U000e007f"
- FLAG_FOR_NEW_BRUNSWICK_CA_NB = "\U0001f3f4\U000e0063\U000e0061\U000e006e\U000e0062\U000e007f"
- FAMILY_MAN_GIRL_BABY = "\U0001f468\u200d\U0001f467\u200d\U0001f476"
- COUPLE_WITH_HEART_WOMAN_LIGHT_SKIN_TONE_MAN = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468"
- COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd"
- COUPLE_WITH_HEART_WOMAN_LIGHT_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_TOLEDO_BZ_TOL = "\U0001f3f4\U000e0062\U000e007a\U000e0074\U000e006f\U000e006c\U000e007f"
- KISS_WOMAN_MEDIUM_SKIN_TONE_WOMAN = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469"
- KISS_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff"
- FAMILY_MAN_MAN_BABY_BABY = "\U0001f468\u200d\U0001f468\u200d\U0001f476\u200d\U0001f476"
- FLAG_FOR_TAMAULIPAS_MX_TAM = "\U0001f3f4\U000e006d\U000e0078\U000e0074\U000e0061\U000e006d\U000e007f"
- FLAG_FOR_TRISTAN_DA_CUNHA_SH_TA = "\U0001f3f4\U000e0073\U000e0068\U000e0074\U000e0061\U000e007f"
- FAMILY_MAN_WOMAN_BABY_BABY = "\U0001f468\u200d\U0001f469\u200d\U0001f476\u200d\U0001f476"
- FLAG_FOR_SAN_LUIS_POTOSI_MX_SLP = "\U0001f3f4\U000e006d\U000e0078\U000e0073\U000e006c\U000e0070\U000e007f"
- FLAG_FOR_VIENTIANE_PROVINCE_LA_VI = "\U0001f3f4\U000e006c\U000e0061\U000e0076\U000e0069\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FLAG_FOR_SOUTHERN_BW_SO = "\U0001f3f4\U000e0062\U000e0077\U000e0073\U000e006f\U000e007f"
- FLAG_FOR_MAMBERE_KADEI_CF_HS = "\U0001f3f4\U000e0063\U000e0066\U000e0068\U000e0073\U000e007f"
- FLAG_FOR_ITURI_CD_IT = "\U0001f3f4\U000e0063\U000e0064\U000e0069\U000e0074\U000e007f"
- NOTCHED_LEFT_SEMICIRCLE_WITH_THREE_DOTS = "\U0001f543"
- FLAG_FOR_MAI_NDOMBE_CD_MN = "\U0001f3f4\U000e0063\U000e0064\U000e006d\U000e006e\U000e007f"
- FLAG_FOR_SOUTH_KIVU_CD_SK = "\U0001f3f4\U000e0063\U000e0064\U000e0073\U000e006b\U000e007f"
- FLAG_FOR_KASAI_CENTRAL_CD_KC = "\U0001f3f4\U000e0063\U000e0064\U000e006b\U000e0063\U000e007f"
- FLAG_FOR_HAUT_UELE_CD_HU = "\U0001f3f4\U000e0063\U000e0064\U000e0068\U000e0075\U000e007f"
- FLAG_FOR_KWANGO_CD_KG = "\U0001f3f4\U000e0063\U000e0064\U000e006b\U000e0067\U000e007f"
- FLAG_FOR_SWIETOKRZYSKIE_PL_SK = "\U0001f3f4\U000e0070\U000e006c\U000e0073\U000e006b\U000e007f"
- FLAG_FOR_KASAI_CD_KS = "\U0001f3f4\U000e0063\U000e0064\U000e006b\U000e0073\U000e007f"
- FLAG_FOR_RAGGED_ISLAND_BS_RI = "\U0001f3f4\U000e0062\U000e0073\U000e0072\U000e0069\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FLAG_FOR_MANIEMA_CD_MA = "\U0001f3f4\U000e0063\U000e0064\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_SANKURU_CD_SA = "\U0001f3f4\U000e0063\U000e0064\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_MONTANA_BG_12 = "\U0001f3f4\U000e0062\U000e0067\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_OUHAM_CF_AC = "\U0001f3f4\U000e0063\U000e0066\U000e0061\U000e0063\U000e007f"
- FLAG_FOR_HAUT_LOMAMI_CD_HL = "\U0001f3f4\U000e0063\U000e0064\U000e0068\U000e006c\U000e007f"
- FLAG_FOR_BAMINGUI_BANGORAN_CF_BB = "\U0001f3f4\U000e0063\U000e0066\U000e0062\U000e0062\U000e007f"
- FLAG_FOR_BUBANZA_BI_BB = "\U0001f3f4\U000e0062\U000e0069\U000e0062\U000e0062\U000e007f"
- FLAG_FOR_KINSHASA_CD_KN = "\U0001f3f4\U000e0063\U000e0064\U000e006b\U000e006e\U000e007f"
- FLAG_FOR_KASAI_ORIENTAL_CD_KE = "\U0001f3f4\U000e0063\U000e0064\U000e006b\U000e0065\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_MONGALA_CD_MO = "\U0001f3f4\U000e0063\U000e0064\U000e006d\U000e006f\U000e007f"
- FLAG_FOR_TSHUAPA_CD_TU = "\U0001f3f4\U000e0063\U000e0064\U000e0074\U000e0075\U000e007f"
- FLAG_FOR_TSHOPO_CD_TO = "\U0001f3f4\U000e0063\U000e0064\U000e0074\U000e006f\U000e007f"
- FLAG_FOR_LUCERNE_CH_LU = "\U0001f3f4\U000e0063\U000e0068\U000e006c\U000e0075\U000e007f"
- FLAG_FOR_RIO_GRANDE_DO_NORTE_BR_RN = "\U0001f3f4\U000e0062\U000e0072\U000e0072\U000e006e\U000e007f"
- WOMAN_WITH_HEADSCARF_LIGHT_SKIN_TONE = "\U0001f9d5\U0001f3fb\u200d\u2640\ufe0f"
- FAMILY_MAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_LOBAYE_CF_LB = "\U0001f3f4\U000e0063\U000e0066\U000e006c\U000e0062\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_LOMAMI_CD_LO = "\U0001f3f4\U000e0063\U000e0064\U000e006c\U000e006f\U000e007f"
- FLAG_FOR_KWILU_CD_KL = "\U0001f3f4\U000e0063\U000e0064\U000e006b\U000e006c\U000e007f"
- FLAG_FOR_LOBATSE_BW_LO = "\U0001f3f4\U000e0062\U000e0077\U000e006c\U000e006f\U000e007f"
- FLAG_FOR_SANGHA_CG_13 = "\U0001f3f4\U000e0063\U000e0067\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_KOUILOU_CG_5 = "\U0001f3f4\U000e0063\U000e0067\U000e0035\U000e007f"
- FLAG_FOR_LIKOUALA_CG_7 = "\U0001f3f4\U000e0063\U000e0067\U000e0037\U000e007f"
- FLAG_FOR_BANGUI_CF_BGF = "\U0001f3f4\U000e0063\U000e0066\U000e0062\U000e0067\U000e0066\U000e007f"
- FLAG_FOR_SANGHA_MBAERE_CF_SE = "\U0001f3f4\U000e0063\U000e0066\U000e0073\U000e0065\U000e007f"
- FLAG_FOR_NIDWALDEN_CH_NW = "\U0001f3f4\U000e0063\U000e0068\U000e006e\U000e0077\U000e007f"
- FLAG_FOR_ST_GALLEN_CH_SG = "\U0001f3f4\U000e0063\U000e0068\U000e0073\U000e0067\U000e007f"
- FLAG_FOR_LEKOUMOU_CG_2 = "\U0001f3f4\U000e0063\U000e0067\U000e0032\U000e007f"
- FLAG_FOR_MONO_BJ_MO = "\U0001f3f4\U000e0062\U000e006a\U000e006d\U000e006f\U000e007f"
- FLAG_FOR_APPENZELL_INNERRHODEN_CH_AI = "\U0001f3f4\U000e0063\U000e0068\U000e0061\U000e0069\U000e007f"
- FLAG_FOR_AARGAU_CH_AG = "\U0001f3f4\U000e0063\U000e0068\U000e0061\U000e0067\U000e007f"
- FLAG_FOR_CUVETTE_OUEST_CG_15 = "\U0001f3f4\U000e0063\U000e0067\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_BRAZZAVILLE_CG_BZV = "\U0001f3f4\U000e0063\U000e0067\U000e0062\U000e007a\U000e0076\U000e007f"
- FLAG_FOR_CUVETTE_CG_8 = "\U0001f3f4\U000e0063\U000e0067\U000e0038\U000e007f"
- FLAG_FOR_LOS_RIOS_CL_LR = "\U0001f3f4\U000e0063\U000e006c\U000e006c\U000e0072\U000e007f"
- FLAG_FOR_MONTAGNES_CI_MG = "\U0001f3f4\U000e0063\U000e0069\U000e006d\U000e0067\U000e007f"
- FLAG_FOR_BAS_SASSANDRA_CI_BS = "\U0001f3f4\U000e0063\U000e0069\U000e0062\U000e0073\U000e007f"
- FLAG_FOR_BASEL_STADT_CH_BS = "\U0001f3f4\U000e0063\U000e0068\U000e0062\U000e0073\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FLAG_FOR_LITTORAL_CM_LT = "\U0001f3f4\U000e0063\U000e006d\U000e006c\U000e0074\U000e007f"
- FLAG_FOR_NORTHWEST_CM_NW = "\U0001f3f4\U000e0063\U000e006d\U000e006e\U000e0077\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_FRIBOURG_CH_FR = "\U0001f3f4\U000e0063\U000e0068\U000e0066\U000e0072\U000e007f"
- FLAG_FOR_ATACAMA_CL_AT = "\U0001f3f4\U000e0063\U000e006c\U000e0061\U000e0074\U000e007f"
- FLAG_FOR_SAVANES_CI_SV = "\U0001f3f4\U000e0063\U000e0069\U000e0073\U000e0076\U000e007f"
- FLAG_FOR_COQUIMBO_CL_CO = "\U0001f3f4\U000e0063\U000e006c\U000e0063\U000e006f\U000e007f"
- FLAG_FOR_ADAMAWA_CM_AD = "\U0001f3f4\U000e0063\U000e006d\U000e0061\U000e0064\U000e007f"
- FLAG_FOR_AL_MADINAH_SA_03 = "\U0001f3f4\U000e0073\U000e0061\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_SOUTHWEST_CM_SW = "\U0001f3f4\U000e0063\U000e006d\U000e0073\U000e0077\U000e007f"
- FLAG_FOR_NORTH_CM_NO = "\U0001f3f4\U000e0063\U000e006d\U000e006e\U000e006f\U000e007f"
- COUPLE_WITH_HEART_MAN_WOMAN = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f469"
- FLAG_FOR_DENGUELE_CI_DN = "\U0001f3f4\U000e0063\U000e0069\U000e0064\U000e006e\U000e007f"
- FLAG_FOR_MAGALLANES_REGION_CL_MA = "\U0001f3f4\U000e0063\U000e006c\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_HAUT_KATANGA_CD_HK = "\U0001f3f4\U000e0063\U000e0064\U000e0068\U000e006b\U000e007f"
- FLAG_FOR_GOH_DJIBOUA_CI_GD = "\U0001f3f4\U000e0063\U000e0069\U000e0067\U000e0064\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_WOROBA_CI_WR = "\U0001f3f4\U000e0063\U000e0069\U000e0077\U000e0072\U000e007f"
- FLAG_FOR_COMOE_CI_CM = "\U0001f3f4\U000e0063\U000e0069\U000e0063\U000e006d\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_YAMOUSSOUKRO_CI_YM = "\U0001f3f4\U000e0063\U000e0069\U000e0079\U000e006d\U000e007f"
- FLAG_FOR_LACS_CI_LC = "\U0001f3f4\U000e0063\U000e0069\U000e006c\U000e0063\U000e007f"
- FLAG_FOR_TARAPACA_CL_TA = "\U0001f3f4\U000e0063\U000e006c\U000e0074\U000e0061\U000e007f"
- FLAG_FOR_PANEVEZYS_COUNTY_LT_PN = "\U0001f3f4\U000e006c\U000e0074\U000e0070\U000e006e\U000e007f"
- FLAG_FOR_CENTRE_CM_CE = "\U0001f3f4\U000e0063\U000e006d\U000e0063\U000e0065\U000e007f"
- FLAG_FOR_GUANGXI_CN_45 = "\U0001f3f4\U000e0063\U000e006e\U000e0034\U000e0035\U000e007f"
- FLAG_FOR_HENAN_CN_41 = "\U0001f3f4\U000e0063\U000e006e\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_JIANGSU_CN_32 = "\U0001f3f4\U000e0063\U000e006e\U000e0033\U000e0032\U000e007f"
- BLACK_CHESS_KNIGHT = "\u265e"
- WHITE_HARD_SHELL_FLOPPY_DISK = "\U0001f5ab"
- FLAG_FOR_BOYACA_CO_BOY = "\U0001f3f4\U000e0063\U000e006f\U000e0062\U000e006f\U000e0079\U000e007f"
- FLAG_FOR_FUJIAN_CN_35 = "\U0001f3f4\U000e0063\U000e006e\U000e0033\U000e0035\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_CAQUETA_CO_CAQ = "\U0001f3f4\U000e0063\U000e006f\U000e0063\U000e0061\U000e0071\U000e007f"
- FLAG_FOR_JIANGXI_CN_36 = "\U0001f3f4\U000e0063\U000e006e\U000e0033\U000e0036\U000e007f"
- FLAG_FOR_OMBELLA_M_POKO_CF_MP = "\U0001f3f4\U000e0063\U000e0066\U000e006d\U000e0070\U000e007f"
- FLAG_FOR_RUSE_BG_18 = "\U0001f3f4\U000e0062\U000e0067\U000e0031\U000e0038\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f468\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_LIBERTADOR_GENERAL_BERNARDO_O_HIGGINS_CL_LI = "\U0001f3f4\U000e0063\U000e006c\U000e006c\U000e0069\U000e007f"
- FLAG_FOR_HAINAN_CN_46 = "\U0001f3f4\U000e0063\U000e006e\U000e0034\U000e0036\U000e007f"
- FLAG_FOR_BATMAN_TR_72 = "\U0001f3f4\U000e0074\U000e0072\U000e0037\U000e0032\U000e007f"
- FLAG_FOR_CALDAS_CO_CAL = "\U0001f3f4\U000e0063\U000e006f\U000e0063\U000e0061\U000e006c\U000e007f"
- FLAG_FOR_QINGHAI_CN_63 = "\U0001f3f4\U000e0063\U000e006e\U000e0036\U000e0033\U000e007f"
- FLAG_FOR_ARAUCA_CO_ARA = "\U0001f3f4\U000e0063\U000e006f\U000e0061\U000e0072\U000e0061\U000e007f"
- COUPLE_WITH_HEART_WOMAN_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe"
- FLAG_FOR_GUAVIARE_CO_GUV = "\U0001f3f4\U000e0063\U000e006f\U000e0067\U000e0075\U000e0076\U000e007f"
- FLAG_FOR_VAUPES_CO_VAU = "\U0001f3f4\U000e0063\U000e006f\U000e0076\U000e0061\U000e0075\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc"
- FLAG_FOR_CARTAGO_CR_C = "\U0001f3f4\U000e0063\U000e0072\U000e0063\U000e007f"
- FLAG_FOR_LA_GUAJIRA_CO_LAG = "\U0001f3f4\U000e0063\U000e006f\U000e006c\U000e0061\U000e0067\U000e007f"
- FLAG_FOR_MATANZAS_CU_04 = "\U0001f3f4\U000e0063\U000e0075\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_ARIANA_TN_12 = "\U0001f3f4\U000e0074\U000e006e\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_LIMON_CR_L = "\U0001f3f4\U000e0063\U000e0072\U000e006c\U000e007f"
- FLAG_FOR_FEDERALLY_ADMINISTERED_TRIBAL_AREAS_PK_TA = "\U0001f3f4\U000e0070\U000e006b\U000e0074\U000e0061\U000e007f"
- FLAG_FOR_CIENFUEGOS_CU_06 = "\U0001f3f4\U000e0063\U000e0075\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_CORDOBA_CO_COR = "\U0001f3f4\U000e0063\U000e006f\U000e0063\U000e006f\U000e0072\U000e007f"
- FLAG_FOR_NORTE_DE_SANTANDER_CO_NSA = "\U0001f3f4\U000e0063\U000e006f\U000e006e\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_HUBEI_CN_42 = "\U0001f3f4\U000e0063\U000e006e\U000e0034\U000e0032\U000e007f"
- FLAG_FOR_PUNTARENAS_CR_P = "\U0001f3f4\U000e0063\U000e0072\U000e0070\U000e007f"
- FLAG_FOR_CAMAGUEY_CU_09 = "\U0001f3f4\U000e0063\U000e0075\U000e0030\U000e0039\U000e007f"
- KISS_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_SAN_SALVADOR_BS_SS = "\U0001f3f4\U000e0062\U000e0073\U000e0073\U000e0073\U000e007f"
- FLAG_FOR_LIMASSOL_CY_02 = "\U0001f3f4\U000e0063\U000e0079\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_TSIRANG_BT_21 = "\U0001f3f4\U000e0062\U000e0074\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_MORAVSKOSLEZSKY_KRAJ_CZ_80 = "\U0001f3f4\U000e0063\U000e007a\U000e0038\U000e0030\U000e007f"
- FLAG_FOR_SLIVEN_BG_20 = "\U0001f3f4\U000e0062\U000e0067\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_BURGAS_BG_02 = "\U0001f3f4\U000e0062\U000e0067\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_SOTAVENTO_ISLANDS_CV_S = "\U0001f3f4\U000e0063\U000e0076\U000e0073\U000e007f"
- FLAG_FOR_SALZBURG_AT_5 = "\U0001f3f4\U000e0061\U000e0074\U000e0035\U000e007f"
- FLAG_FOR_KRAJ_VYSOCINA_CZ_63 = "\U0001f3f4\U000e0063\U000e007a\U000e0036\U000e0033\U000e007f"
- FLAG_FOR_HOLGUIN_CU_11 = "\U0001f3f4\U000e0063\U000e0075\U000e0031\U000e0031\U000e007f"
- KISS_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469"
- FLAG_FOR_PARANA_BR_PR = "\U0001f3f4\U000e0062\U000e0072\U000e0070\U000e0072\U000e007f"
- FLAG_FOR_GUANTANAMO_CU_14 = "\U0001f3f4\U000e0063\U000e0075\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_XINJIANG_CN_65 = "\U0001f3f4\U000e0063\U000e006e\U000e0036\U000e0035\U000e007f"
- FLAG_FOR_KRALOVEHRADECKY_KRAJ_CZ_52 = "\U0001f3f4\U000e0063\U000e007a\U000e0035\U000e0032\U000e007f"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f476\U0001f3fb"
- FLAG_FOR_KARLOVARSKY_KRAJ_CZ_41 = "\U0001f3f4\U000e0063\U000e007a\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_AMAPA_BR_AP = "\U0001f3f4\U000e0062\U000e0072\U000e0061\U000e0070\U000e007f"
- FLAG_FOR_GASA_BT_GA = "\U0001f3f4\U000e0062\U000e0074\U000e0067\U000e0061\U000e007f"
- FLAG_FOR_BARLAVENTO_ISLANDS_CV_B = "\U0001f3f4\U000e0063\U000e0076\U000e0062\U000e007f"
- FLAG_FOR_MAYABEQUE_CU_16 = "\U0001f3f4\U000e0063\U000e0075\U000e0031\U000e0036\U000e007f"
- KISS_MAN_DARK_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_LIBERECKY_KRAJ_CZ_51 = "\U0001f3f4\U000e0063\U000e007a\U000e0035\U000e0031\U000e007f"
- FLAG_FOR_CIBAO_NOROESTE_DO_34 = "\U0001f3f4\U000e0064\U000e006f\U000e0033\U000e0034\U000e007f"
- FLAG_FOR_RISARALDA_CO_RIS = "\U0001f3f4\U000e0063\U000e006f\U000e0072\U000e0069\U000e0073\U000e007f"
- FLAG_FOR_HOPE_TOWN_BS_HT = "\U0001f3f4\U000e0062\U000e0073\U000e0068\U000e0074\U000e007f"
- FLAG_FOR_BRITISH_COLUMBIA_CA_BC = "\U0001f3f4\U000e0063\U000e0061\U000e0062\U000e0063\U000e007f"
- FLAG_FOR_NICOSIA_CY_01 = "\U0001f3f4\U000e0063\U000e0079\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_SHANXI_CN_14 = "\U0001f3f4\U000e0063\U000e006e\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_SAXONY_ANHALT_DE_ST = "\U0001f3f4\U000e0064\U000e0065\U000e0073\U000e0074\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_TADJOURAH_DJ_TA = "\U0001f3f4\U000e0064\U000e006a\U000e0074\U000e0061\U000e007f"
- FLAG_FOR_CAPITAL_REGION_DK_84 = "\U0001f3f4\U000e0064\U000e006b\U000e0038\U000e0034\U000e007f"
- FLAG_FOR_HIGUAMO_DO_39 = "\U0001f3f4\U000e0064\U000e006f\U000e0033\U000e0039\U000e007f"
- FLAG_FOR_CIBAO_NORDESTE_DO_33 = "\U0001f3f4\U000e0064\U000e006f\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_CIBAO_SUR_DO_36 = "\U0001f3f4\U000e0064\U000e006f\U000e0033\U000e0036\U000e007f"
- COUPLE_WITH_HEART_MAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb"
- FLAG_FOR_POHNPEI_FM_PNI = "\U0001f3f4\U000e0066\U000e006d\U000e0070\U000e006e\U000e0069\U000e007f"
- FLAG_FOR_VALDESIA_DO_41 = "\U0001f3f4\U000e0064\U000e006f\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_YOZGAT_TR_66 = "\U0001f3f4\U000e0074\U000e0072\U000e0036\U000e0036\U000e007f"
- FLAG_FOR_CAUCA_CO_CAU = "\U0001f3f4\U000e0063\U000e006f\U000e0063\U000e0061\U000e0075\U000e007f"
- FLAG_FOR_OLOMOUCKY_KRAJ_CZ_71 = "\U0001f3f4\U000e0063\U000e007a\U000e0037\U000e0031\U000e007f"
- FLAG_FOR_SAINT_MARK_DM_08 = "\U0001f3f4\U000e0064\U000e006d\U000e0030\U000e0038\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FAMILY_WOMAN_LIGHT_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f469\U0001f3fb\u200d\U0001f467\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_KHENCHELA_DZ_40 = "\U0001f3f4\U000e0064\U000e007a\U000e0034\U000e0030\U000e007f"
- FAMILY_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_TIZI_OUZOU_DZ_15 = "\U0001f3f4\U000e0064\U000e007a\U000e0031\U000e0035\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f467\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FLAG_FOR_MOSTAGANEM_DZ_27 = "\U0001f3f4\U000e0064\U000e007a\U000e0032\U000e0037\U000e007f"
- FLAG_FOR_OUARGLA_DZ_30 = "\U0001f3f4\U000e0064\U000e007a\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_BOUMERDES_DZ_35 = "\U0001f3f4\U000e0064\U000e007a\U000e0033\U000e0035\U000e007f"
- FLAG_FOR_TIPASA_DZ_42 = "\U0001f3f4\U000e0064\U000e007a\U000e0034\U000e0032\U000e007f"
- FLAG_FOR_BISKRA_DZ_07 = "\U0001f3f4\U000e0064\U000e007a\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_MEDEA_DZ_26 = "\U0001f3f4\U000e0064\U000e007a\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_SOUK_AHRAS_DZ_41 = "\U0001f3f4\U000e0064\U000e007a\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_ANNABA_DZ_23 = "\U0001f3f4\U000e0064\U000e007a\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_WESTERN_HIGHLANDS_PG_WHM = "\U0001f3f4\U000e0070\U000e0067\U000e0077\U000e0068\U000e006d\U000e007f"
- FLAG_FOR_TINDOUF_DZ_37 = "\U0001f3f4\U000e0064\U000e007a\U000e0033\U000e0037\U000e007f"
- FLAG_FOR_DJELFA_DZ_17 = "\U0001f3f4\U000e0064\U000e007a\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_MILA_DZ_43 = "\U0001f3f4\U000e0064\U000e007a\U000e0034\U000e0033\U000e007f"
- FLAG_FOR_BATNA_DZ_05 = "\U0001f3f4\U000e0064\U000e007a\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_TISSEMSILT_DZ_38 = "\U0001f3f4\U000e0064\U000e007a\U000e0033\U000e0038\U000e007f"
- FLAG_FOR_EL_BAYADH_DZ_32 = "\U0001f3f4\U000e0064\U000e007a\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_HUILA_CO_HUI = "\U0001f3f4\U000e0063\U000e006f\U000e0068\U000e0075\U000e0069\U000e007f"
- FLAG_FOR_ENRIQUILLO_DO_38 = "\U0001f3f4\U000e0064\U000e006f\U000e0033\U000e0038\U000e007f"
- FLAG_FOR_SUDUR_PASHCHIMANCHAL_NP_5 = "\U0001f3f4\U000e006e\U000e0070\U000e0035\U000e007f"
- FLAG_FOR_BEJAIA_DZ_06 = "\U0001f3f4\U000e0064\U000e007a\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_BOUIRA_DZ_10 = "\U0001f3f4\U000e0064\U000e007a\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_ILLIZI_DZ_33 = "\U0001f3f4\U000e0064\U000e007a\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_PLATEAUX_CG_14 = "\U0001f3f4\U000e0063\U000e0067\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_SAINT_DAVID_DM_03 = "\U0001f3f4\U000e0064\U000e006d\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_TAMANGHASSET_DZ_11 = "\U0001f3f4\U000e0064\U000e007a\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_MORONA_SANTIAGO_EC_S = "\U0001f3f4\U000e0065\U000e0063\U000e0073\U000e007f"
- FLAG_FOR_VALGA_EE_82 = "\U0001f3f4\U000e0065\U000e0065\U000e0038\U000e0032\U000e007f"
- FLAG_FOR_RELIZANE_DZ_48 = "\U0001f3f4\U000e0064\U000e007a\U000e0034\U000e0038\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FLAG_FOR_LOJA_EC_L = "\U0001f3f4\U000e0065\U000e0063\U000e006c\U000e007f"
- FLAG_FOR_GHARDAIA_DZ_47 = "\U0001f3f4\U000e0064\U000e007a\U000e0034\U000e0037\U000e007f"
- FLAG_FOR_PASTAZA_EC_Y = "\U0001f3f4\U000e0065\U000e0063\U000e0079\U000e007f"
- FLAG_FOR_AIN_TEMOUCHENT_DZ_46 = "\U0001f3f4\U000e0064\U000e007a\U000e0034\U000e0036\U000e007f"
- FLAG_FOR_LOS_RIOS_EC_R = "\U0001f3f4\U000e0065\U000e0063\U000e0072\U000e007f"
- FLAG_FOR_LAANE_EE_57 = "\U0001f3f4\U000e0065\U000e0065\U000e0035\U000e0037\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FLAG_FOR_SAARE_EE_74 = "\U0001f3f4\U000e0065\U000e0065\U000e0037\U000e0034\U000e007f"
- FLAG_FOR_JOGEVA_EE_49 = "\U0001f3f4\U000e0065\U000e0065\U000e0034\U000e0039\U000e007f"
- FLAG_FOR_POLVA_EE_65 = "\U0001f3f4\U000e0065\U000e0065\U000e0036\U000e0035\U000e007f"
- FLAG_FOR_JARVA_EE_51 = "\U0001f3f4\U000e0065\U000e0065\U000e0035\U000e0031\U000e007f"
- FLAG_FOR_PAPHOS_CY_05 = "\U0001f3f4\U000e0063\U000e0079\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_PARNU_EE_67 = "\U0001f3f4\U000e0065\U000e0065\U000e0036\U000e0037\U000e007f"
- FLAG_FOR_CARCHI_EC_C = "\U0001f3f4\U000e0065\U000e0063\U000e0063\U000e007f"
- FLAG_FOR_SUCUMBIOS_EC_U = "\U0001f3f4\U000e0065\U000e0063\U000e0075\U000e007f"
- FLAG_FOR_OUM_EL_BOUAGHI_DZ_04 = "\U0001f3f4\U000e0064\U000e007a\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_GALAPAGOS_EC_W = "\U0001f3f4\U000e0065\U000e0063\U000e0077\U000e007f"
- FLAG_FOR_GHARBIA_EG_GH = "\U0001f3f4\U000e0065\U000e0067\U000e0067\U000e0068\U000e007f"
- FLAG_FOR_DAKAHLIA_EG_DK = "\U0001f3f4\U000e0065\U000e0067\U000e0064\U000e006b\U000e007f"
- FLAG_FOR_AL_SHARQIA_EG_SHR = "\U0001f3f4\U000e0065\U000e0067\U000e0073\U000e0068\U000e0072\U000e007f"
- FLAG_FOR_QALYUBIA_EG_KB = "\U0001f3f4\U000e0065\U000e0067\U000e006b\U000e0062\U000e007f"
- FLAG_FOR_FEDERATION_OF_BOSNIA_AND_HERZEGOVINA_BA_BIH = "\U0001f3f4\U000e0062\U000e0061\U000e0062\U000e0069\U000e0068\U000e007f"
- FLAG_FOR_CENTRAL_ABACO_BS_CO = "\U0001f3f4\U000e0062\U000e0073\U000e0063\U000e006f\U000e007f"
- FLAG_FOR_MONUFIA_EG_MNF = "\U0001f3f4\U000e0065\U000e0067\U000e006d\U000e006e\U000e0066\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE_GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f476\U0001f3fe\u200d\U0001f467\U0001f3fe"
- FLAG_FOR_BUJUMBURA_RURAL_BI_BL = "\U0001f3f4\U000e0062\U000e0069\U000e0062\U000e006c\U000e007f"
- FLAG_FOR_MAEKEL_ER_MA = "\U0001f3f4\U000e0065\U000e0072\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_ISMAILIA_EG_IS = "\U0001f3f4\U000e0065\U000e0067\U000e0069\U000e0073\U000e007f"
- FLAG_FOR_SAIDA_DZ_20 = "\U0001f3f4\U000e0064\U000e007a\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_QENA_EG_KN = "\U0001f3f4\U000e0065\U000e0067\U000e006b\U000e006e\U000e007f"
- FLAG_FOR_TARTU_EE_78 = "\U0001f3f4\U000e0065\U000e0065\U000e0037\U000e0038\U000e007f"
- FLAG_FOR_ANSEBA_ER_AN = "\U0001f3f4\U000e0065\U000e0072\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_ASWAN_EG_ASN = "\U0001f3f4\U000e0065\U000e0067\U000e0061\U000e0073\U000e006e\U000e007f"
- FLAG_FOR_DEBUB_ER_DU = "\U0001f3f4\U000e0065\U000e0072\U000e0064\U000e0075\U000e007f"
- FLAG_FOR_ASYUT_EG_AST = "\U0001f3f4\U000e0065\U000e0067\U000e0061\U000e0073\U000e0074\U000e007f"
- FLAG_FOR_BEHEIRA_EG_BH = "\U0001f3f4\U000e0065\U000e0067\U000e0062\U000e0068\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f476\U0001f3fe"
- FLAG_FOR_IMBABURA_EC_I = "\U0001f3f4\U000e0065\U000e0063\U000e0069\U000e007f"
- FLAG_FOR_VILJANDI_EE_84 = "\U0001f3f4\U000e0065\U000e0065\U000e0038\U000e0034\U000e007f"
- FLAG_FOR_VORU_EE_86 = "\U0001f3f4\U000e0065\U000e0065\U000e0038\U000e0036\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe"
- FLAG_FOR_HAUTE_KOTTO_CF_HK = "\U0001f3f4\U000e0063\U000e0066\U000e0068\U000e006b\U000e007f"
- FLAG_FOR_GUAINIA_CO_GUA = "\U0001f3f4\U000e0063\U000e006f\U000e0067\U000e0075\U000e0061\U000e007f"
- FLAG_FOR_DAMIETTA_EG_DT = "\U0001f3f4\U000e0065\U000e0067\U000e0064\U000e0074\U000e007f"
- FLAG_FOR_SAINT_PAUL_DM_10 = "\U0001f3f4\U000e0064\U000e006d\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_KAINUU_FI_05 = "\U0001f3f4\U000e0066\U000e0069\U000e0030\U000e0035\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f467\U0001f3fd"
- FLAG_FOR_KYMENLAAKSO_FI_09 = "\U0001f3f4\U000e0066\U000e0069\U000e0030\U000e0039\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd"
- FLAG_FOR_BENISHANGUL_GUMUZ_ET_BE = "\U0001f3f4\U000e0065\U000e0074\U000e0062\U000e0065\U000e007f"
- FLAG_FOR_SOUTH_KARELIA_FI_02 = "\U0001f3f4\U000e0066\U000e0069\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_PUNAKHA_BT_23 = "\U0001f3f4\U000e0062\U000e0074\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_YUMA_DO_42 = "\U0001f3f4\U000e0064\U000e006f\U000e0034\U000e0032\U000e007f"
- FLAG_FOR_SANTA_ELENA_EC_SE = "\U0001f3f4\U000e0065\U000e0063\U000e0073\U000e0065\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f467\U0001f3fc"
- KISS_MAN_MEDIUM_SKIN_TONE_WOMAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff"
- FLAG_FOR_BISTRITA_NASAUD_RO_BN = "\U0001f3f4\U000e0072\U000e006f\U000e0062\U000e006e\U000e007f"
- FLAG_FOR_KEMO_CF_KG = "\U0001f3f4\U000e0063\U000e0066\U000e006b\U000e0067\U000e007f"
- FLAG_FOR_BLIDA_DZ_09 = "\U0001f3f4\U000e0064\U000e007a\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_HARARI_ET_HA = "\U0001f3f4\U000e0065\U000e0074\U000e0068\U000e0061\U000e007f"
- FLAG_FOR_ARTEMISA_CU_15 = "\U0001f3f4\U000e0063\U000e0075\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_SOUTHERN_OSTROBOTHNIA_FI_03 = "\U0001f3f4\U000e0066\U000e0069\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_OBOCK_DJ_OB = "\U0001f3f4\U000e0064\U000e006a\U000e006f\U000e0062\U000e007f"
- FLAG_FOR_MATROUH_EG_MT = "\U0001f3f4\U000e0065\U000e0067\U000e006d\U000e0074\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_W = "\U000e0057"
- FLAG_FOR_VILLA_CLARA_CU_05 = "\U0001f3f4\U000e0063\U000e0075\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_CENTRAL_FJ_C = "\U0001f3f4\U000e0066\U000e006a\U000e0063\U000e007f"
- FLAG_FOR_NORTH_KARELIA_FI_13 = "\U0001f3f4\U000e0066\U000e0069\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_CHUKHA_BT_12 = "\U0001f3f4\U000e0062\U000e0074\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_BENI_BO_B = "\U0001f3f4\U000e0062\U000e006f\U000e0062\U000e007f"
- FLAG_FOR_ORAN_DZ_31 = "\U0001f3f4\U000e0064\U000e007a\U000e0033\U000e0031\U000e007f"
- FLAG_FOR_NORTHERN_SAVONIA_FI_15 = "\U0001f3f4\U000e0066\U000e0069\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_APPENZELL_AUSSERRHODEN_CH_AR = "\U0001f3f4\U000e0063\U000e0068\U000e0061\U000e0072\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_PIRKANMAA_FI_11 = "\U0001f3f4\U000e0066\U000e0069\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_KOSRAE_FM_KSA = "\U0001f3f4\U000e0066\U000e006d\U000e006b\U000e0073\U000e0061\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_OUHAM_PENDE_CF_OP = "\U0001f3f4\U000e0063\U000e0066\U000e006f\U000e0070\U000e007f"
- FLAG_FOR_BIO_BIO_CL_BI = "\U0001f3f4\U000e0063\U000e006c\U000e0062\U000e0069\U000e007f"
- HORIZONTAL_MALE_WITH_STROKE_SIGN = "\u26a9"
- FLAG_FOR_NOUVELLE_AQUITAINE_FR_NAQ = "\U0001f3f4\U000e0066\U000e0072\U000e006e\U000e0061\U000e0071\U000e007f"
- FLAG_FOR_ANSE_AUX_PINS_SC_01 = "\U0001f3f4\U000e0073\U000e0063\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_SAINT_DAVID_GD_02 = "\U0001f3f4\U000e0067\U000e0064\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_OGOOUE_IVINDO_GA_6 = "\U0001f3f4\U000e0067\U000e0061\U000e0036\U000e007f"
- FLAG_FOR_ZAMORA_CHINCHIPE_EC_Z = "\U0001f3f4\U000e0065\U000e0063\U000e007a\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe"
- FLAG_FOR_MOYEN_OGOOUE_GA_3 = "\U0001f3f4\U000e0067\U000e0061\U000e0033\U000e007f"
- FLAG_FOR_SATAKUNTA_FI_17 = "\U0001f3f4\U000e0066\U000e0069\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_BRONG_AHAFO_GH_BA = "\U0001f3f4\U000e0067\U000e0068\U000e0062\U000e0061\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_VAN_TR_65 = "\U0001f3f4\U000e0074\U000e0072\U000e0036\U000e0035\U000e007f"
- FLAG_FOR_MTSKHETA_MTIANETI_GE_MM = "\U0001f3f4\U000e0067\U000e0065\U000e006d\U000e006d\U000e007f"
- FLAG_FOR_TEBESSA_DZ_12 = "\U0001f3f4\U000e0064\U000e007a\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_WOLEU_NTEM_GA_9 = "\U0001f3f4\U000e0067\U000e0061\U000e0039\U000e007f"
- FLAG_FOR_SAMEGRELO_ZEMO_SVANETI_GE_SZ = "\U0001f3f4\U000e0067\U000e0065\U000e0073\U000e007a\U000e007f"
- FLAG_FOR_IMERETI_GE_IM = "\U0001f3f4\U000e0067\U000e0065\U000e0069\U000e006d\U000e007f"
- FLAG_FOR_SAMTSKHE_JAVAKHETI_GE_SJ = "\U0001f3f4\U000e0067\U000e0065\U000e0073\U000e006a\U000e007f"
- FLAG_FOR_ABIDJAN_CI_AB = "\U0001f3f4\U000e0063\U000e0069\U000e0061\U000e0062\U000e007f"
- FLAG_FOR_SHIRAK_AM_SH = "\U0001f3f4\U000e0061\U000e006d\U000e0073\U000e0068\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_GUELMA_DZ_24 = "\U0001f3f4\U000e0064\U000e007a\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_HAUT_OGOOUE_GA_2 = "\U0001f3f4\U000e0067\U000e0061\U000e0032\U000e007f"
- FLAG_FOR_JIHOMORAVSKY_KRAJ_CZ_64 = "\U0001f3f4\U000e0063\U000e007a\U000e0036\U000e0034\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_KUJALLEQ_GL_KU = "\U0001f3f4\U000e0067\U000e006c\U000e006b\U000e0075\U000e007f"
- FLAG_FOR_THESSALY_GR_E = "\U0001f3f4\U000e0067\U000e0072\U000e0065\U000e007f"
- FLAG_FOR_EPIRUS_GR_D = "\U0001f3f4\U000e0067\U000e0072\U000e0064\U000e007f"
- FLAG_FOR_PICHINCHA_EC_P = "\U0001f3f4\U000e0065\U000e0063\U000e0070\U000e007f"
- FLAG_FOR_ALI_SABIEH_DJ_AS = "\U0001f3f4\U000e0064\U000e006a\U000e0061\U000e0073\U000e007f"
- FLAG_FOR_NORTHERN_FJ_N = "\U0001f3f4\U000e0066\U000e006a\U000e006e\U000e007f"
- FLAG_FOR_NORTHERN_GH_NP = "\U0001f3f4\U000e0067\U000e0068\U000e006e\U000e0070\U000e007f"
- FLAG_FOR_UPPER_WEST_GH_UW = "\U0001f3f4\U000e0067\U000e0068\U000e0075\U000e0077\U000e007f"
- FLAG_FOR_UPPER_EAST_GH_UE = "\U0001f3f4\U000e0067\U000e0068\U000e0075\U000e0065\U000e007f"
- FLAG_FOR_KINDIA_REGION_GN_D = "\U0001f3f4\U000e0067\U000e006e\U000e0064\U000e007f"
- FLAG_FOR_CONAKRY_GN_C = "\U0001f3f4\U000e0067\U000e006e\U000e0063\U000e007f"
- FLAG_FOR_IONIAN_ISLANDS_GR_F = "\U0001f3f4\U000e0067\U000e0072\U000e0066\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f468\U0001f3ff\u200d\U0001f476\U0001f3ff"
- COUPLE_WITH_HEART_WOMAN_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_SINOE_LR_SI = "\U0001f3f4\U000e006c\U000e0072\U000e0073\U000e0069\U000e007f"
- FLAG_FOR_FARANAH_REGION_GN_F = "\U0001f3f4\U000e0067\U000e006e\U000e0066\U000e007f"
- COUPLE_WITH_HEART_WOMAN_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc"
- FLAG_FOR_HEILONGJIANG_CN_23 = "\U0001f3f4\U000e0063\U000e006e\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_RIO_MUNI_GQ_C = "\U0001f3f4\U000e0067\U000e0071\U000e0063\U000e007f"
- WHITE_DOWN_POINTING_LEFT_HAND_INDEX = "\U0001f597"
- FLAG_FOR_VOLTA_GH_TV = "\U0001f3f4\U000e0067\U000e0068\U000e0074\U000e0076\U000e007f"
- FLAG_FOR_QAASUITSUP_GL_QA = "\U0001f3f4\U000e0067\U000e006c\U000e0071\U000e0061\U000e007f"
- KISS_MAN_LIGHT_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff"
- FLAG_FOR_QUICHE_GT_QC = "\U0001f3f4\U000e0067\U000e0074\U000e0071\U000e0063\U000e007f"
- FLAG_FOR_HUNAN_CN_43 = "\U0001f3f4\U000e0063\U000e006e\U000e0034\U000e0033\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe"
- FLAG_FOR_QUETZALTENANGO_GT_QZ = "\U0001f3f4\U000e0067\U000e0074\U000e0071\U000e007a\U000e007f"
- FLAG_FOR_LESTE_GW_L = "\U0001f3f4\U000e0067\U000e0077\U000e006c\U000e007f"
- FLAG_FOR_CUYUNI_MAZARUNI_GY_CU = "\U0001f3f4\U000e0067\U000e0079\U000e0063\U000e0075\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f476\U0001f3ff"
- FLAG_FOR_PETEN_GT_PE = "\U0001f3f4\U000e0067\U000e0074\U000e0070\U000e0065\U000e007f"
- FLAG_FOR_ZACAPA_GT_ZA = "\U0001f3f4\U000e0067\U000e0074\U000e007a\U000e0061\U000e007f"
- FLAG_FOR_LIAONING_CN_21 = "\U0001f3f4\U000e0063\U000e006e\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_CHOLUTECA_HN_CH = "\U0001f3f4\U000e0068\U000e006e\U000e0063\U000e0068\U000e007f"
- FLAG_FOR_CHIMALTENANGO_GT_CM = "\U0001f3f4\U000e0067\U000e0074\U000e0063\U000e006d\U000e007f"
- FLAG_FOR_SOLOLA_GT_SO = "\U0001f3f4\U000e0067\U000e0074\U000e0073\U000e006f\U000e007f"
- FLAG_FOR_HUEHUETENANGO_GT_HU = "\U0001f3f4\U000e0067\U000e0074\U000e0068\U000e0075\U000e007f"
- KISS_MAN_MAN_LIGHT_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb"
- FLAG_FOR_ESCUINTLA_GT_ES = "\U0001f3f4\U000e0067\U000e0074\U000e0065\U000e0073\U000e007f"
- FLAG_FOR_CHIQUIMULA_GT_CQ = "\U0001f3f4\U000e0067\U000e0074\U000e0063\U000e0071\U000e007f"
- FLAG_FOR_IZABAL_GT_IZ = "\U0001f3f4\U000e0067\U000e0074\U000e0069\U000e007a\U000e007f"
- FLAG_FOR_ATLANTIDA_HN_AT = "\U0001f3f4\U000e0068\U000e006e\U000e0061\U000e0074\U000e007f"
- FLAG_FOR_NEW_JERSEY_US_NJ = "\U0001f3f4\U000e0075\U000e0073\U000e006e\U000e006a\U000e007f"
- FLAG_FOR_ESSEQUIBO_ISLANDS_WEST_DEMERARA_GY_ES = "\U0001f3f4\U000e0067\U000e0079\U000e0065\U000e0073\U000e007f"
- FLAG_FOR_POTARO_SIPARUNI_GY_PT = "\U0001f3f4\U000e0067\U000e0079\U000e0070\U000e0074\U000e007f"
- FLAG_FOR_BISSAU_GW_BS = "\U0001f3f4\U000e0067\U000e0077\U000e0062\U000e0073\U000e007f"
- FLAG_FOR_DEMERARA_MAHAICA_GY_DE = "\U0001f3f4\U000e0067\U000e0079\U000e0064\U000e0065\U000e007f"
- FLAG_FOR_IDA_VIRU_EE_44 = "\U0001f3f4\U000e0065\U000e0065\U000e0034\U000e0034\U000e007f"
- FLAG_FOR_LIKA_SENJ_HR_09 = "\U0001f3f4\U000e0068\U000e0072\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_KRAPINA_ZAGORJE_HR_02 = "\U0001f3f4\U000e0068\U000e0072\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_ARTIBONITE_HT_AR = "\U0001f3f4\U000e0068\U000e0074\U000e0061\U000e0072\U000e007f"
- FLAG_FOR_OCOTEPEQUE_HN_OC = "\U0001f3f4\U000e0068\U000e006e\U000e006f\U000e0063\U000e007f"
- FLAG_FOR_CENTRE_HT_CE = "\U0001f3f4\U000e0068\U000e0074\U000e0063\U000e0065\U000e007f"
- FLAG_FOR_SOLOTHURN_CH_SO = "\U0001f3f4\U000e0063\U000e0068\U000e0073\U000e006f\U000e007f"
- FLAG_FOR_JALAPA_GT_JA = "\U0001f3f4\U000e0067\U000e0074\U000e006a\U000e0061\U000e007f"
- FLAG_FOR_DUBROVNIK_NERETVA_HR_19 = "\U0001f3f4\U000e0068\U000e0072\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_VUKOVAR_SYRMIA_HR_16 = "\U0001f3f4\U000e0068\U000e0072\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_OSIJEK_BARANJA_HR_14 = "\U0001f3f4\U000e0068\U000e0072\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_KOPRIVNICA_KRIZEVCI_HR_06 = "\U0001f3f4\U000e0068\U000e0072\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_INTIBUCA_HN_IN = "\U0001f3f4\U000e0068\U000e006e\U000e0069\U000e006e\U000e007f"
- FLAG_FOR_POZEGA_SLAVONIA_HR_11 = "\U0001f3f4\U000e0068\U000e0072\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_BERAT_COUNTY_AL_01 = "\U0001f3f4\U000e0061\U000e006c\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_SAINT_LUKE_DM_07 = "\U0001f3f4\U000e0064\U000e006d\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_COMAYAGUA_HN_CM = "\U0001f3f4\U000e0068\U000e006e\U000e0063\U000e006d\U000e007f"
- FLAG_FOR_YORO_HN_YO = "\U0001f3f4\U000e0068\U000e006e\U000e0079\U000e006f\U000e007f"
- FLAG_FOR_COPAN_HN_CP = "\U0001f3f4\U000e0068\U000e006e\U000e0063\U000e0070\U000e007f"
- FLAG_FOR_VALLE_HN_VA = "\U0001f3f4\U000e0068\U000e006e\U000e0076\U000e0061\U000e007f"
- FLAG_FOR_LEMPIRA_HN_LE = "\U0001f3f4\U000e0068\U000e006e\U000e006c\U000e0065\U000e007f"
- FLAG_FOR_ME_IMURJE_HR_20 = "\U0001f3f4\U000e0068\U000e0072\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_SIBENIK_KNIN_HR_15 = "\U0001f3f4\U000e0068\U000e0072\U000e0031\U000e0035\U000e007f"
- MERCURY = "\u263f\ufe0f"
- FLAG_FOR_FRANCISCO_MORAZAN_HN_FM = "\U0001f3f4\U000e0068\U000e006e\U000e0066\U000e006d\U000e007f"
- FLAG_FOR_OLANCHO_HN_OL = "\U0001f3f4\U000e0068\U000e006e\U000e006f\U000e006c\U000e007f"
- FLAG_FOR_CORTES_HN_CR = "\U0001f3f4\U000e0068\U000e006e\U000e0063\U000e0072\U000e007f"
- FLAG_FOR_ZAGREB_COUNTY_HR_01 = "\U0001f3f4\U000e0068\U000e0072\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_ISTRIA_HR_18 = "\U0001f3f4\U000e0068\U000e0072\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_ZADAR_HR_13 = "\U0001f3f4\U000e0068\U000e0072\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_PEST_HU_PE = "\U0001f3f4\U000e0068\U000e0075\U000e0070\U000e0065\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_GIRL_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f467\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FLAG_FOR_HAJDU_BIHAR_HU_HB = "\U0001f3f4\U000e0068\U000e0075\U000e0068\U000e0062\U000e007f"
- COUPLE_WITH_HEART_MAN_DARK_SKIN_TONE_MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff"
- FLAG_FOR_OUEST_HT_OU = "\U0001f3f4\U000e0068\U000e0074\U000e006f\U000e0075\U000e007f"
- FLAG_FOR_SZOLNOK_HU_SK = "\U0001f3f4\U000e0068\U000e0075\U000e0073\U000e006b\U000e007f"
- FLAG_FOR_NOGRAD_HU_NO = "\U0001f3f4\U000e0068\U000e0075\U000e006e\U000e006f\U000e007f"
- FLAG_FOR_BORSOD_ABAUJ_ZEMPLEN_HU_BZ = "\U0001f3f4\U000e0068\U000e0075\U000e0062\U000e007a\U000e007f"
- FLAG_FOR_SOPRON_HU_SN = "\U0001f3f4\U000e0068\U000e0075\U000e0073\U000e006e\U000e007f"
- FLAG_FOR_JIJEL_DZ_18 = "\U0001f3f4\U000e0064\U000e007a\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_BEKESCSABA_HU_BC = "\U0001f3f4\U000e0068\U000e0075\U000e0062\U000e0063\U000e007f"
- FLAG_FOR_NYIREGYHAZA_HU_NY = "\U0001f3f4\U000e0068\U000e0075\U000e006e\U000e0079\U000e007f"
- FLAG_FOR_NORD_HT_ND = "\U0001f3f4\U000e0068\U000e0074\U000e006e\U000e0064\U000e007f"
- FLAG_FOR_FEJER_HU_FE = "\U0001f3f4\U000e0068\U000e0075\U000e0066\U000e0065\U000e007f"
- FLAG_FOR_NIPPES_HT_NI = "\U0001f3f4\U000e0068\U000e0074\U000e006e\U000e0069\U000e007f"
- FLAG_FOR_ERD_HU_ER = "\U0001f3f4\U000e0068\U000e0075\U000e0065\U000e0072\U000e007f"
- FLAG_FOR_SZOMBATHELY_HU_SH = "\U0001f3f4\U000e0068\U000e0075\U000e0073\U000e0068\U000e007f"
- FLAG_FOR_EASTERN_GH_EP = "\U0001f3f4\U000e0067\U000e0068\U000e0065\U000e0070\U000e007f"
- FLAG_FOR_DIRE_DAWA_ET_DD = "\U0001f3f4\U000e0065\U000e0074\U000e0064\U000e0064\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469"
- FLAG_FOR_SZEKESFEHERVAR_HU_SF = "\U0001f3f4\U000e0068\U000e0075\U000e0073\U000e0066\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb"
- FLAG_FOR_KOMAROM_ESZTERGOM_HU_KE = "\U0001f3f4\U000e0068\U000e0075\U000e006b\U000e0065\U000e007f"
- FLAG_FOR_MISKOLC_HU_MI = "\U0001f3f4\U000e0068\U000e0075\U000e006d\U000e0069\U000e007f"
- FLAG_FOR_DEBRECEN_HU_DE = "\U0001f3f4\U000e0068\U000e0075\U000e0064\U000e0065\U000e007f"
- FLAG_FOR_BACS_KISKUN_HU_BK = "\U0001f3f4\U000e0068\U000e0075\U000e0062\U000e006b\U000e007f"
- FLAG_FOR_GYOR_HU_GY = "\U0001f3f4\U000e0068\U000e0075\U000e0067\U000e0079\U000e007f"
- FLAG_FOR_DUNAUJVAROS_HU_DU = "\U0001f3f4\U000e0068\U000e0075\U000e0064\U000e0075\U000e007f"
- FLAG_FOR_HEVES_HU_HE = "\U0001f3f4\U000e0068\U000e0075\U000e0068\U000e0065\U000e007f"
- FLAG_FOR_BEKES_HU_BE = "\U0001f3f4\U000e0068\U000e0075\U000e0062\U000e0065\U000e007f"
- FLAG_FOR_JASZ_NAGYKUN_SZOLNOK_HU_JN = "\U0001f3f4\U000e0068\U000e0075\U000e006a\U000e006e\U000e007f"
- FLAG_FOR_RAPLA_EE_70 = "\U0001f3f4\U000e0065\U000e0065\U000e0037\U000e0030\U000e007f"
- FLAG_FOR_ZALAEGERSZEG_HU_ZE = "\U0001f3f4\U000e0068\U000e0075\U000e007a\U000e0065\U000e007f"
- FLAG_FOR_CONNACHT_IE_C = "\U0001f3f4\U000e0069\U000e0065\U000e0063\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd"
- FLAG_FOR_CENTRAL_DISTRICT_IL_M = "\U0001f3f4\U000e0069\U000e006c\U000e006d\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FLAG_FOR_GREATER_ACCRA_GH_AA = "\U0001f3f4\U000e0067\U000e0068\U000e0061\U000e0061\U000e007f"
- FLAG_FOR_HAIFA_DISTRICT_IL_HA = "\U0001f3f4\U000e0069\U000e006c\U000e0068\U000e0061\U000e007f"
- FLAG_FOR_BARANYA_HU_BA = "\U0001f3f4\U000e0068\U000e0075\U000e0062\U000e0061\U000e007f"
- FLAG_FOR_VESZPREM_HU_VM = "\U0001f3f4\U000e0068\U000e0075\U000e0076\U000e006d\U000e007f"
- FLAG_FOR_VESZPREM_COUNTY_HU_VE = "\U0001f3f4\U000e0068\U000e0075\U000e0076\U000e0065\U000e007f"
- FLAG_FOR_MAGDALENA_CO_MAG = "\U0001f3f4\U000e0063\U000e006f\U000e006d\U000e0061\U000e0067\U000e007f"
- FLAG_FOR_NAGYKANIZSA_HU_NK = "\U0001f3f4\U000e0068\U000e0075\U000e006e\U000e006b\U000e007f"
- FLAG_FOR_SOMOGY_HU_SO = "\U0001f3f4\U000e0068\U000e0075\U000e0073\U000e006f\U000e007f"
- FLAG_FOR_SOUTHERN_DISTRICT_IL_D = "\U0001f3f4\U000e0069\U000e006c\U000e0064\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_DARK_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_SAINT_PETER_DM_11 = "\U0001f3f4\U000e0064\U000e006d\U000e0031\U000e0031\U000e007f"
- KISS_WOMAN_MEDIUM_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb"
- FLAG_FOR_TOLNA_HU_TO = "\U0001f3f4\U000e0068\U000e0075\U000e0074\U000e006f\U000e007f"
- FLAG_FOR_ODISHA_IN_OR = "\U0001f3f4\U000e0069\U000e006e\U000e006f\U000e0072\U000e007f"
- FLAG_FOR_PUTUMAYO_CO_PUT = "\U0001f3f4\U000e0063\U000e006f\U000e0070\U000e0075\U000e0074\U000e007f"
- FLAG_FOR_DOHUK_IQ_DA = "\U0001f3f4\U000e0069\U000e0071\U000e0064\U000e0061\U000e007f"
- FLAG_FOR_AL_MUTHANNA_IQ_MU = "\U0001f3f4\U000e0069\U000e0071\U000e006d\U000e0075\U000e007f"
- WHITE_DIAMOND_SUIT = "\u2662"
- BLACK_CHESS_QUEEN = "\u265b"
- FLAG_FOR_SALADIN_IQ_SD = "\U0001f3f4\U000e0069\U000e0071\U000e0073\U000e0064\U000e007f"
- TAG_LATIN_SMALL_LETTER_V = "\U000e0076"
- FAMILY_WOMAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FLAG_FOR_SHANDONG_CN_37 = "\U0001f3f4\U000e0063\U000e006e\U000e0033\U000e0037\U000e007f"
- FLAG_FOR_AL_ANBAR_IQ_AN = "\U0001f3f4\U000e0069\U000e0071\U000e0061\U000e006e\U000e007f"
- FLAG_FOR_NAJAF_IQ_NA = "\U0001f3f4\U000e0069\U000e0071\U000e006e\U000e0061\U000e007f"
- FLAG_FOR_KARBALA_IQ_KA = "\U0001f3f4\U000e0069\U000e0071\U000e006b\U000e0061\U000e007f"
- FLAG_FOR_SULAWESI_ID_SL = "\U0001f3f4\U000e0069\U000e0064\U000e0073\U000e006c\U000e007f"
- FLAG_FOR_ATLANTICO_CO_ATL = "\U0001f3f4\U000e0063\U000e006f\U000e0061\U000e0074\U000e006c\U000e007f"
- FAMILY_MAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_DIYALA_IQ_DI = "\U0001f3f4\U000e0069\U000e0071\U000e0064\U000e0069\U000e007f"
- FLAG_FOR_AL_QADISIYYAH_IQ_QA = "\U0001f3f4\U000e0069\U000e0071\U000e0071\U000e0061\U000e007f"
- FLAG_FOR_NAGALAND_IN_NL = "\U0001f3f4\U000e0069\U000e006e\U000e006e\U000e006c\U000e007f"
- FLAG_FOR_SULAYMANIYAH_IQ_SU = "\U0001f3f4\U000e0069\U000e0071\U000e0073\U000e0075\U000e007f"
- FLAG_FOR_SUEZ_EG_SUZ = "\U0001f3f4\U000e0065\U000e0067\U000e0073\U000e0075\U000e007a\U000e007f"
- FLAG_FOR_MEGHALAYA_IN_ML = "\U0001f3f4\U000e0069\U000e006e\U000e006d\U000e006c\U000e007f"
- FLAG_FOR_NINEVEH_IQ_NI = "\U0001f3f4\U000e0069\U000e0071\U000e006e\U000e0069\U000e007f"
- FLAG_FOR_NEUCHATEL_CH_NE = "\U0001f3f4\U000e0063\U000e0068\U000e006e\U000e0065\U000e007f"
- FLAG_FOR_MIZORAM_IN_MZ = "\U0001f3f4\U000e0069\U000e006e\U000e006d\U000e007a\U000e007f"
- FLAG_FOR_OBWALDEN_CH_OW = "\U0001f3f4\U000e0063\U000e0068\U000e006f\U000e0077\U000e007f"
- FLAG_FOR_LAKSHADWEEP_IN_LD = "\U0001f3f4\U000e0069\U000e006e\U000e006c\U000e0064\U000e007f"
- FLAG_FOR_HORMOZGAN_IR_23 = "\U0001f3f4\U000e0069\U000e0072\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_QAZVIN_IR_28 = "\U0001f3f4\U000e0069\U000e0072\U000e0032\U000e0038\U000e007f"
- FLAG_FOR_MAYSAN_IQ_MA = "\U0001f3f4\U000e0069\U000e0071\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_SEMNAN_IR_12 = "\U0001f3f4\U000e0069\U000e0072\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_ALAJUELA_CR_A = "\U0001f3f4\U000e0063\U000e0072\U000e0061\U000e007f"
- FLAG_FOR_MARKAZI_IR_22 = "\U0001f3f4\U000e0069\U000e0072\U000e0032\U000e0032\U000e007f"
- COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe"
- FLAG_FOR_RHODE_ISLAND_US_RI = "\U0001f3f4\U000e0075\U000e0073\U000e0072\U000e0069\U000e007f"
- FLAG_FOR_PIRAN_SI_090 = "\U0001f3f4\U000e0073\U000e0069\U000e0030\U000e0039\U000e0030\U000e007f"
- FLAG_FOR_LEINSTER_IE_L = "\U0001f3f4\U000e0069\U000e0065\U000e006c\U000e007f"
- FLAG_FOR_BANJUL_GM_B = "\U0001f3f4\U000e0067\U000e006d\U000e0062\U000e007f"
- FLAG_FOR_NORTHWESTERN_IS_5 = "\U0001f3f4\U000e0069\U000e0073\U000e0035\U000e007f"
- FAMILY_WOMAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f467\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_MAHAICA_BERBICE_GY_MA = "\U0001f3f4\U000e0067\U000e0079\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_YAZD_IR_25 = "\U0001f3f4\U000e0069\U000e0072\U000e0032\U000e0035\U000e007f"
- FLAG_FOR_WASIT_IQ_WA = "\U0001f3f4\U000e0069\U000e0071\U000e0077\U000e0061\U000e007f"
- FLAG_FOR_SAINT_ANDREW_DM_02 = "\U0001f3f4\U000e0064\U000e006d\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_SUMATRA_ID_SM = "\U0001f3f4\U000e0069\U000e0064\U000e0073\U000e006d\U000e007f"
- FLAG_FOR_ZALA_HU_ZA = "\U0001f3f4\U000e0068\U000e0075\U000e007a\U000e0061\U000e007f"
- COUPLE_WITH_HEART_WOMAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe"
- FLAG_FOR_BOLIVAR_CO_BOL = "\U0001f3f4\U000e0063\U000e006f\U000e0062\U000e006f\U000e006c\U000e007f"
- FLAG_FOR_SAINT_ELIZABETH_JM_11 = "\U0001f3f4\U000e006a\U000e006d\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_WESTERN_GH_WP = "\U0001f3f4\U000e0067\U000e0068\U000e0077\U000e0070\U000e007f"
- FLAG_FOR_JERASH_JO_JA = "\U0001f3f4\U000e006a\U000e006f\U000e006a\U000e0061\U000e007f"
- FLAG_FOR_TRELAWNY_JM_07 = "\U0001f3f4\U000e006a\U000e006d\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_MOLISE_IT_67 = "\U0001f3f4\U000e0069\U000e0074\U000e0036\U000e0037\U000e007f"
- FLAG_FOR_NORTHEASTERN_IS_6 = "\U0001f3f4\U000e0069\U000e0073\U000e0036\U000e007f"
- FLAG_FOR_AMMAN_JO_AM = "\U0001f3f4\U000e006a\U000e006f\U000e0061\U000e006d\U000e007f"
- FLAG_FOR_UMM_AL_QUWAIN_AE_UQ = "\U0001f3f4\U000e0061\U000e0065\U000e0075\U000e0071\U000e007f"
- FLAG_FOR_GOLESTAN_IR_27 = "\U0001f3f4\U000e0069\U000e0072\U000e0032\U000e0037\U000e007f"
- FLAG_FOR_TAFILAH_JO_AT = "\U0001f3f4\U000e006a\U000e006f\U000e0061\U000e0074\U000e007f"
- FLAG_FOR_KECSKEMET_HU_KM = "\U0001f3f4\U000e0068\U000e0075\U000e006b\U000e006d\U000e007f"
- FLAG_FOR_UMBRIA_IT_55 = "\U0001f3f4\U000e0069\U000e0074\U000e0035\U000e0035\U000e007f"
- FLAG_FOR_SAINT_ANN_JM_06 = "\U0001f3f4\U000e006a\U000e006d\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_SUD_HT_SD = "\U0001f3f4\U000e0068\U000e0074\U000e0073\U000e0064\U000e007f"
- COUPLE_WITH_HEART_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469"
- FLAG_FOR_CHAHARMAHAL_AND_BAKHTIARI_IR_08 = "\U0001f3f4\U000e0069\U000e0072\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_WESTMORELAND_JM_10 = "\U0001f3f4\U000e006a\U000e006d\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_LIGURIA_IT_42 = "\U0001f3f4\U000e0069\U000e0074\U000e0034\U000e0032\U000e007f"
- FLAG_FOR_GRACIAS_A_DIOS_HN_GD = "\U0001f3f4\U000e0068\U000e006e\U000e0067\U000e0064\U000e007f"
- FLAG_FOR_CLARENDON_JM_13 = "\U0001f3f4\U000e006a\U000e006d\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_AQABA_JO_AQ = "\U0001f3f4\U000e006a\U000e006f\U000e0061\U000e0071\U000e007f"
- FLAG_FOR_IRBID_JO_IR = "\U0001f3f4\U000e006a\U000e006f\U000e0069\U000e0072\U000e007f"
- FLAG_FOR_BALQA_JO_BA = "\U0001f3f4\U000e006a\U000e006f\U000e0062\U000e0061\U000e007f"
- FLAG_FOR_ZARQA_JO_AZ = "\U0001f3f4\U000e006a\U000e006f\U000e0061\U000e007a\U000e007f"
- FLAG_FOR_OSTROBOTHNIA_FI_12 = "\U0001f3f4\U000e0066\U000e0069\U000e0031\U000e0032\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_MAFRAQ_JO_MA = "\U0001f3f4\U000e006a\U000e006f\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_ARAUCANIA_CL_AR = "\U0001f3f4\U000e0063\U000e006c\U000e0061\U000e0072\U000e007f"
- FLAG_FOR_EAST_CM_ES = "\U0001f3f4\U000e0063\U000e006d\U000e0065\U000e0073\U000e007f"
- FLAG_FOR_YAMAGUCHI_JP_35 = "\U0001f3f4\U000e006a\U000e0070\U000e0033\U000e0035\U000e007f"
- FLAG_FOR_NAGANO_JP_20 = "\U0001f3f4\U000e006a\U000e0070\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_TOCHIGI_JP_09 = "\U0001f3f4\U000e006a\U000e0070\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_SHIMANE_JP_32 = "\U0001f3f4\U000e006a\U000e0070\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_ILAM_IR_05 = "\U0001f3f4\U000e0069\U000e0072\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_NARA_JP_29 = "\U0001f3f4\U000e006a\U000e0070\U000e0032\U000e0039\U000e007f"
- FLAG_FOR_SPLIT_DALMATIA_HR_17 = "\U0001f3f4\U000e0068\U000e0072\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_EHIME_JP_38 = "\U0001f3f4\U000e006a\U000e0070\U000e0033\U000e0038\U000e007f"
- FLAG_FOR_ORELLANA_EC_D = "\U0001f3f4\U000e0065\U000e0063\U000e0064\U000e007f"
- FLAG_FOR_LA_RIOJA_ES_RI = "\U0001f3f4\U000e0065\U000e0073\U000e0072\U000e0069\U000e007f"
- FLAG_FOR_IBARAKI_JP_08 = "\U0001f3f4\U000e006a\U000e0070\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_GRANMA_CU_12 = "\U0001f3f4\U000e0063\U000e0075\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_SHIZUOKA_JP_22 = "\U0001f3f4\U000e006a\U000e0070\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_IWATE_JP_03 = "\U0001f3f4\U000e006a\U000e0070\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_TOYAMA_JP_16 = "\U0001f3f4\U000e006a\U000e0070\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_MADABA_JO_MD = "\U0001f3f4\U000e006a\U000e006f\U000e006d\U000e0064\U000e007f"
- FLAG_FOR_YAMANASHI_JP_19 = "\U0001f3f4\U000e006a\U000e0070\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_TOKUSHIMA_JP_36 = "\U0001f3f4\U000e006a\U000e0070\U000e0033\U000e0036\U000e007f"
- FLAG_FOR_ISHIKAWA_JP_17 = "\U0001f3f4\U000e006a\U000e0070\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_KANAGAWA_JP_14 = "\U0001f3f4\U000e006a\U000e0070\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_MIE_JP_24 = "\U0001f3f4\U000e006a\U000e0070\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_NIIGATA_JP_15 = "\U0001f3f4\U000e006a\U000e0070\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_HYOGO_JP_28 = "\U0001f3f4\U000e006a\U000e0070\U000e0032\U000e0038\U000e007f"
- FLAG_FOR_DHI_QAR_IQ_DQ = "\U0001f3f4\U000e0069\U000e0071\U000e0064\U000e0071\U000e007f"
- FLAG_FOR_SHIGA_JP_25 = "\U0001f3f4\U000e006a\U000e0070\U000e0032\U000e0035\U000e007f"
- FLAG_FOR_TOTTORI_JP_31 = "\U0001f3f4\U000e006a\U000e0070\U000e0033\U000e0031\U000e007f"
- FLAG_FOR_OKAYAMA_JP_33 = "\U0001f3f4\U000e006a\U000e0070\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_CHIBA_JP_12 = "\U0001f3f4\U000e006a\U000e0070\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_MURANG_A_KE_29 = "\U0001f3f4\U000e006b\U000e0065\U000e0032\U000e0039\U000e007f"
- FLAG_FOR_SOUTH_SINAI_EG_JS = "\U0001f3f4\U000e0065\U000e0067\U000e006a\U000e0073\U000e007f"
- FLAG_FOR_KAJIADO_KE_10 = "\U0001f3f4\U000e006b\U000e0065\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_KOCHI_JP_39 = "\U0001f3f4\U000e006a\U000e0070\U000e0033\U000e0039\U000e007f"
- FLAG_FOR_BASRA_IQ_BA = "\U0001f3f4\U000e0069\U000e0071\U000e0062\U000e0061\U000e007f"
- FLAG_FOR_NAROK_KE_33 = "\U0001f3f4\U000e006b\U000e0065\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_FUKUOKA_JP_40 = "\U0001f3f4\U000e006a\U000e0070\U000e0034\U000e0030\U000e007f"
- FLAG_FOR_BUNGOMA_KE_03 = "\U0001f3f4\U000e006b\U000e0065\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_GUNMA_JP_10 = "\U0001f3f4\U000e006a\U000e0070\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_MERU_KE_26 = "\U0001f3f4\U000e006b\U000e0065\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_ELGEYO_MARAKWET_KE_05 = "\U0001f3f4\U000e006b\U000e0065\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_LAIKIPIA_KE_20 = "\U0001f3f4\U000e006b\U000e0065\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_ISIOLO_KE_09 = "\U0001f3f4\U000e006b\U000e0065\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_KISII_KE_16 = "\U0001f3f4\U000e006b\U000e0065\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_SOUTHERN_PENINSULA_IS_2 = "\U0001f3f4\U000e0069\U000e0073\U000e0032\U000e007f"
- FLAG_FOR_KAKAMEGA_KE_11 = "\U0001f3f4\U000e006b\U000e0065\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_MAKUENI_KE_23 = "\U0001f3f4\U000e006b\U000e0065\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_BITOLA_MK_04 = "\U0001f3f4\U000e006d\U000e006b\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_MIGORI_KE_27 = "\U0001f3f4\U000e006b\U000e0065\U000e0032\U000e0037\U000e007f"
- FLAG_FOR_KILIFI_KE_14 = "\U0001f3f4\U000e006b\U000e0065\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_LAMU_KE_21 = "\U0001f3f4\U000e006b\U000e0065\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_MOMBASA_KE_28 = "\U0001f3f4\U000e006b\U000e0065\U000e0032\U000e0038\U000e007f"
- FLAG_FOR_TATABANYA_HU_TB = "\U0001f3f4\U000e0068\U000e0075\U000e0074\U000e0062\U000e007f"
- FLAG_FOR_BOMET_KE_02 = "\U0001f3f4\U000e006b\U000e0065\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_KUMAMOTO_JP_43 = "\U0001f3f4\U000e006a\U000e0070\U000e0034\U000e0033\U000e007f"
- FLAG_FOR_KIAMBU_KE_13 = "\U0001f3f4\U000e006b\U000e0065\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_NANDI_KE_32 = "\U0001f3f4\U000e006b\U000e0065\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_YAMAGATA_JP_06 = "\U0001f3f4\U000e006a\U000e0070\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_BUSIA_KE_04 = "\U0001f3f4\U000e006b\U000e0065\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_MANDERA_KE_24 = "\U0001f3f4\U000e006b\U000e0065\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_TURKANA_KE_43 = "\U0001f3f4\U000e006b\U000e0065\U000e0034\U000e0033\U000e007f"
- FLAG_FOR_NARYN_KG_N = "\U0001f3f4\U000e006b\U000e0067\U000e006e\U000e007f"
- FLAG_FOR_SIAYA_KE_38 = "\U0001f3f4\U000e006b\U000e0065\U000e0033\U000e0038\U000e007f"
- FLAG_FOR_UASIN_GISHU_KE_44 = "\U0001f3f4\U000e006b\U000e0065\U000e0034\U000e0034\U000e007f"
- FLAG_FOR_JALAL_ABAD_KG_J = "\U0001f3f4\U000e006b\U000e0067\U000e006a\U000e007f"
- FLAG_FOR_MONDULKIRI_KH_11 = "\U0001f3f4\U000e006b\U000e0068\U000e0031\U000e0031\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_VIHIGA_KE_45 = "\U0001f3f4\U000e006b\U000e0065\U000e0034\U000e0035\U000e007f"
- FLAG_FOR_WEST_POKOT_KE_47 = "\U0001f3f4\U000e006b\U000e0065\U000e0034\U000e0037\U000e007f"
- FLAG_FOR_PREY_VENG_KH_14 = "\U0001f3f4\U000e006b\U000e0068\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_TALAS_KG_T = "\U0001f3f4\U000e006b\U000e0067\U000e0074\U000e007f"
- FLAG_FOR_HOMA_BAY_KE_08 = "\U0001f3f4\U000e006b\U000e0065\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_KRATIE_KH_10 = "\U0001f3f4\U000e006b\U000e0068\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_TBONG_KHMUM_KH_25 = "\U0001f3f4\U000e006b\U000e0068\U000e0032\U000e0035\U000e007f"
- FLAG_FOR_BISHKEK_KG_GB = "\U0001f3f4\U000e006b\U000e0067\U000e0067\U000e0062\U000e007f"
- FLAG_FOR_ODDAR_MEANCHEY_KH_22 = "\U0001f3f4\U000e006b\U000e0068\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_PHNOM_PENH_KH_12 = "\U0001f3f4\U000e006b\U000e0068\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_NYERI_KE_36 = "\U0001f3f4\U000e006b\U000e0065\U000e0033\U000e0036\U000e007f"
- FLAG_FOR_STUNG_TRENG_KH_19 = "\U0001f3f4\U000e006b\U000e0068\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_PURSAT_KH_15 = "\U0001f3f4\U000e006b\U000e0068\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_NYANDARUA_KE_35 = "\U0001f3f4\U000e006b\U000e0065\U000e0033\U000e0035\U000e007f"
- FLAG_FOR_SAMBURU_KE_37 = "\U0001f3f4\U000e006b\U000e0065\U000e0033\U000e0037\U000e007f"
- FLAG_FOR_MACHAKOS_KE_22 = "\U0001f3f4\U000e006b\U000e0065\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_BATTAMBANG_KH_2 = "\U0001f3f4\U000e006b\U000e0068\U000e0032\U000e007f"
- FLAG_FOR_TAITA_TAVETA_KE_39 = "\U0001f3f4\U000e006b\U000e0065\U000e0033\U000e0039\U000e007f"
- FLAG_FOR_TAKEO_KH_21 = "\U0001f3f4\U000e006b\U000e0068\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_SIHANOUKVILLE_KH_18 = "\U0001f3f4\U000e006b\U000e0068\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_NYAMIRA_KE_34 = "\U0001f3f4\U000e006b\U000e0065\U000e0033\U000e0034\U000e007f"
- FLAG_FOR_KEP_KH_23 = "\U0001f3f4\U000e006b\U000e0068\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_THARAKA_NITHI_KE_41 = "\U0001f3f4\U000e006b\U000e0065\U000e0034\U000e0031\U000e007f"
- FAMILY_MAN_MEDIUM_DARK_SKIN_TONE_WOMAN_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE_BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f469\U0001f3fe\u200d\U0001f466\U0001f3fe\u200d\U0001f466\U0001f3fe"
- FLAG_FOR_SUCHITEPEQUEZ_GT_SU = "\U0001f3f4\U000e0067\U000e0074\U000e0073\U000e0075\U000e007f"
- FLAG_FOR_AGUASCALIENTES_MX_AGU = "\U0001f3f4\U000e006d\U000e0078\U000e0061\U000e0067\U000e0075\U000e007f"
- FLAG_FOR_COLON_HN_CL = "\U0001f3f4\U000e0068\U000e006e\U000e0063\U000e006c\U000e007f"
- FLAG_FOR_KAMPOT_KH_7 = "\U0001f3f4\U000e006b\U000e0068\U000e0037\U000e007f"
- FLAG_FOR_SIRNAK_TR_73 = "\U0001f3f4\U000e0074\U000e0072\U000e0037\U000e0033\U000e007f"
- FLAG_FOR_ZAGREB_HR_21 = "\U0001f3f4\U000e0068\U000e0072\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_GRAND_ANSE_HT_GA = "\U0001f3f4\U000e0068\U000e0074\U000e0067\U000e0061\U000e007f"
- FLAG_FOR_LISBON_PT_11 = "\U0001f3f4\U000e0070\U000e0074\U000e0031\U000e0031\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f468\U0001f3fc\u200d\U0001f476\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_CHAGANG_KP_04 = "\U0001f3f4\U000e006b\U000e0070\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_SOUTH_HAMGYONG_KP_08 = "\U0001f3f4\U000e006b\U000e0070\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_SOUTH_CHUNGCHEONG_KR_44 = "\U0001f3f4\U000e006b\U000e0072\U000e0034\U000e0034\U000e007f"
- FLAG_FOR_MOUNT_ATHOS_GR_69 = "\U0001f3f4\U000e0067\U000e0072\U000e0036\U000e0039\U000e007f"
- WOMAN_IN_BUSINESS_SUIT_LEVITATING_MEDIUM_SKIN_TONE = "\U0001f574\U0001f3fd\u200d\u2640\ufe0f"
- FLAG_FOR_RASON_KP_13 = "\U0001f3f4\U000e006b\U000e0070\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_INCHEON_KR_28 = "\U0001f3f4\U000e006b\U000e0072\U000e0032\U000e0038\U000e007f"
- FLAG_FOR_KAMPONG_THOM_KH_6 = "\U0001f3f4\U000e006b\U000e0068\U000e0036\U000e007f"
- FLAG_FOR_EAST_MACEDONIA_AND_THRACE_GR_A = "\U0001f3f4\U000e0067\U000e0072\U000e0061\U000e007f"
- FLAG_FOR_AIN_DEFLA_DZ_44 = "\U0001f3f4\U000e0064\U000e007a\U000e0034\U000e0034\U000e007f"
- FLAG_FOR_NORTH_PYONGAN_KP_03 = "\U0001f3f4\U000e006b\U000e0070\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_GANGWON_KR_42 = "\U0001f3f4\U000e006b\U000e0072\U000e0034\U000e0032\U000e007f"
- FLAG_FOR_KAMPONG_SPEU_KH_5 = "\U0001f3f4\U000e006b\U000e0068\U000e0035\U000e007f"
- FLAG_FOR_CENTRAL_OSTROBOTHNIA_FI_07 = "\U0001f3f4\U000e0066\U000e0069\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_SOUTH_HWANGHAE_KP_05 = "\U0001f3f4\U000e006b\U000e0070\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_ULSAN_KR_31 = "\U0001f3f4\U000e006b\U000e0072\U000e0033\U000e0031\U000e007f"
- FLAG_FOR_NORTH_BANK_DIVISION_GM_N = "\U0001f3f4\U000e0067\U000e006d\U000e006e\U000e007f"
- COUPLE_WITH_HEART_WOMAN_DARK_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_AL_FARWANIYAH_KW_FA = "\U0001f3f4\U000e006b\U000e0077\U000e0066\U000e0061\U000e007f"
- FLAG_FOR_KARAGANDY_KZ_KAR = "\U0001f3f4\U000e006b\U000e007a\U000e006b\U000e0061\U000e0072\U000e007f"
- FLAG_FOR_SERMERSOOQ_GL_SM = "\U0001f3f4\U000e0067\U000e006c\U000e0073\U000e006d\U000e007f"
- FLAG_FOR_PHONGSALY_LA_PH = "\U0001f3f4\U000e006c\U000e0061\U000e0070\U000e0068\U000e007f"
- FLAG_FOR_OUDOMXAY_LA_OU = "\U0001f3f4\U000e006c\U000e0061\U000e006f\U000e0075\U000e007f"
- FLAG_FOR_ATYRAU_KZ_ATY = "\U0001f3f4\U000e006b\U000e007a\U000e0061\U000e0074\U000e0079\U000e007f"
- FLAG_FOR_LUANG_NAMTHA_LA_LM = "\U0001f3f4\U000e006c\U000e0061\U000e006c\U000e006d\U000e007f"
- FLAG_FOR_LUANG_PRABANG_LA_LP = "\U0001f3f4\U000e006c\U000e0061\U000e006c\U000e0070\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_WOMAN_DARK_SKIN_TONE_BABY_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f469\U0001f3ff\u200d\U0001f476\U0001f3ff\u200d\U0001f466\U0001f3ff"
- FLAG_FOR_HONG_KONG_SAR_CHINA_CN_91 = "\U0001f3f4\U000e0063\U000e006e\U000e0039\U000e0031\U000e007f"
- FLAG_FOR_VIENTIANE_LA_VT = "\U0001f3f4\U000e006c\U000e0061\U000e0076\U000e0074\U000e007f"
- FLAG_FOR_NORTH_CHUNGCHEONG_KR_43 = "\U0001f3f4\U000e006b\U000e0072\U000e0034\U000e0033\U000e007f"
- FLAG_FOR_JAMBYL_KZ_ZHA = "\U0001f3f4\U000e006b\U000e007a\U000e007a\U000e0068\U000e0061\U000e007f"
- FLAG_FOR_QOM_IR_26 = "\U0001f3f4\U000e0069\U000e0072\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_MUBARAK_AL_KABEER_KW_MU = "\U0001f3f4\U000e006b\U000e0077\U000e006d\U000e0075\U000e007f"
- FLAG_FOR_KYZYLORDA_KZ_KZY = "\U0001f3f4\U000e006b\U000e007a\U000e006b\U000e007a\U000e0079\U000e007f"
- FLAG_FOR_AL_JAHRA_KW_JA = "\U0001f3f4\U000e006b\U000e0077\U000e006a\U000e0061\U000e007f"
- FLAG_FOR_AL_ASIMAH_KW_KU = "\U0001f3f4\U000e006b\U000e0077\U000e006b\U000e0075\U000e007f"
- FLAG_FOR_GYEONGGI_KR_41 = "\U0001f3f4\U000e006b\U000e0072\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_PAVLODAR_KZ_PAV = "\U0001f3f4\U000e006b\U000e007a\U000e0070\U000e0061\U000e0076\U000e007f"
- FLAG_FOR_ANJOUAN_KM_A = "\U0001f3f4\U000e006b\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_CHAMPASAK_LA_CH = "\U0001f3f4\U000e006c\U000e0061\U000e0063\U000e0068\U000e007f"
- FLAG_FOR_SEJONG_KR_50 = "\U0001f3f4\U000e006b\U000e0072\U000e0035\U000e0030\U000e007f"
- FLAG_FOR_NORTH_KAZAKHSTAN_KZ_SEV = "\U0001f3f4\U000e006b\U000e007a\U000e0073\U000e0065\U000e0076\U000e007f"
- FLAG_FOR_HANOVER_JM_09 = "\U0001f3f4\U000e006a\U000e006d\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_UPPER_RIVER_DIVISION_GM_U = "\U0001f3f4\U000e0067\U000e006d\U000e0075\U000e007f"
- FLAG_FOR_MAUREN_LI_04 = "\U0001f3f4\U000e006c\U000e0069\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_BAALBEK_HERMEL_LB_BH = "\U0001f3f4\U000e006c\U000e0062\U000e0062\U000e0068\U000e007f"
- FLAG_FOR_NORTH_CENTRAL_LK_7 = "\U0001f3f4\U000e006c\U000e006b\U000e0037\U000e007f"
- FLAG_FOR_SOUFRIERE_LC_10 = "\U0001f3f4\U000e006c\U000e0063\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_NORTHERN_LK_4 = "\U0001f3f4\U000e006c\U000e006b\U000e0034\U000e007f"
- FLAG_FOR_TRIESEN_LI_09 = "\U0001f3f4\U000e006c\U000e0069\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_BJELOVAR_BILOGORA_HR_07 = "\U0001f3f4\U000e0068\U000e0072\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_SAINYABULI_LA_XA = "\U0001f3f4\U000e006c\U000e0061\U000e0078\U000e0061\U000e007f"
- FLAG_FOR_SOUTHERN_SAVONIA_FI_04 = "\U0001f3f4\U000e0066\U000e0069\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_UVA_LK_8 = "\U0001f3f4\U000e006c\U000e006b\U000e0038\U000e007f"
- FLAG_FOR_GAMPRIN_LI_03 = "\U0001f3f4\U000e006c\U000e0069\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_ESCHEN_LI_02 = "\U0001f3f4\U000e006c\U000e0069\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_SOUTH_LB_JA = "\U0001f3f4\U000e006c\U000e0062\U000e006a\U000e0061\U000e007f"
- FLAG_FOR_NORTH_LB_AS = "\U0001f3f4\U000e006c\U000e0062\U000e0061\U000e0073\U000e007f"
- FLAG_FOR_RUGGELL_LI_06 = "\U0001f3f4\U000e006c\U000e0069\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_NORTH_WESTERN_LK_6 = "\U0001f3f4\U000e006c\U000e006b\U000e0036\U000e007f"
- FLAG_FOR_GROS_ISLET_LC_06 = "\U0001f3f4\U000e006c\U000e0063\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_NABATIEH_LB_NA = "\U0001f3f4\U000e006c\U000e0062\U000e006e\U000e0061\U000e007f"
- FLAG_FOR_GRANDE_COMORE_KM_G = "\U0001f3f4\U000e006b\U000e006d\U000e0067\U000e007f"
- FLAG_FOR_CASTRIES_LC_02 = "\U0001f3f4\U000e006c\U000e0063\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_VADUZ_LI_11 = "\U0001f3f4\U000e006c\U000e0069\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_KOSTANAY_KZ_KUS = "\U0001f3f4\U000e006b\U000e007a\U000e006b\U000e0075\U000e0073\U000e007f"
- FLAG_FOR_CHOISEUL_LC_03 = "\U0001f3f4\U000e006c\U000e0063\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_CENTRAL_LK_2 = "\U0001f3f4\U000e006c\U000e006b\U000e0032\U000e007f"
- FLAG_FOR_DENNERY_LC_05 = "\U0001f3f4\U000e006c\U000e0063\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_GARISSA_KE_07 = "\U0001f3f4\U000e006b\U000e0065\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_ANSE_LA_RAYE_LC_01 = "\U0001f3f4\U000e006c\U000e0063\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_RYANGGANG_KP_10 = "\U0001f3f4\U000e006b\U000e0070\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_JONAVA_LT_10 = "\U0001f3f4\U000e006c\U000e0074\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_MOHALE_S_HOEK_LS_F = "\U0001f3f4\U000e006c\U000e0073\U000e0066\U000e007f"
- FLAG_FOR_KALVARIJA_LT_14 = "\U0001f3f4\U000e006c\U000e0074\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_GBARPOLU_LR_GP = "\U0001f3f4\U000e006c\U000e0072\U000e0067\U000e0070\U000e007f"
- TAG_LATIN_CAPITAL_LETTER_F = "\U000e0046"
- FLAG_FOR_NORTH_KIVU_CD_NK = "\U0001f3f4\U000e0063\U000e0064\U000e006e\U000e006b\U000e007f"
- FLAG_FOR_IGNALINA_LT_09 = "\U0001f3f4\U000e006c\U000e0074\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_MAFETENG_LS_E = "\U0001f3f4\U000e006c\U000e0073\U000e0065\U000e007f"
- UNIVERSAL_RECYCLING_SYMBOL = "\u2672"
- FLAG_FOR_BIHAR_IN_BR = "\U0001f3f4\U000e0069\U000e006e\U000e0062\U000e0072\U000e007f"
- FLAG_FOR_THABA_TSEKA_LS_K = "\U0001f3f4\U000e006c\U000e0073\U000e006b\U000e007f"
- FLAG_FOR_ALYTUS_LT_03 = "\U0001f3f4\U000e006c\U000e0074\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_DRUSKININKAI_LT_07 = "\U0001f3f4\U000e006c\U000e0074\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_MOKHOTLONG_LS_J = "\U0001f3f4\U000e006c\U000e0073\U000e006a\U000e007f"
- FLAG_FOR_KAUNO_MUNICIPALITY_LT_15 = "\U0001f3f4\U000e006c\U000e0074\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_JONISKIS_LT_11 = "\U0001f3f4\U000e006c\U000e0074\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_QACHA_S_NEK_LS_H = "\U0001f3f4\U000e006c\U000e0073\U000e0068\U000e007f"
- FLAG_FOR_BEREA_LS_D = "\U0001f3f4\U000e006c\U000e0073\U000e0064\U000e007f"
- FLAG_FOR_NIMBA_LR_NI = "\U0001f3f4\U000e006c\U000e0072\U000e006e\U000e0069\U000e007f"
- FLAG_FOR_ELEKTRENAI_LT_08 = "\U0001f3f4\U000e006c\U000e0074\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_ERBIL_IQ_AR = "\U0001f3f4\U000e0069\U000e0071\U000e0061\U000e0072\U000e007f"
- FLAG_FOR_KANGWON_KP_07 = "\U0001f3f4\U000e006b\U000e0070\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_KAISIADORYS_LT_13 = "\U0001f3f4\U000e006c\U000e0074\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_BUTHA_BUTHE_LS_B = "\U0001f3f4\U000e006c\U000e0073\U000e0062\U000e007f"
- FLAG_FOR_BIRSTONAS_LT_05 = "\U0001f3f4\U000e006c\U000e0074\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_KIRINYAGA_KE_15 = "\U0001f3f4\U000e006b\U000e0065\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_ANYKSCIAI_LT_04 = "\U0001f3f4\U000e006c\U000e0074\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_JURBARKAS_LT_12 = "\U0001f3f4\U000e006c\U000e0074\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_UTENA_LT_54 = "\U0001f3f4\U000e006c\U000e0074\U000e0035\U000e0034\U000e007f"
- FLAG_FOR_PASVALYS_LT_34 = "\U0001f3f4\U000e006c\U000e0074\U000e0033\U000e0034\U000e007f"
- FLAG_FOR_PRIENAI_LT_36 = "\U0001f3f4\U000e006c\U000e0074\U000e0033\U000e0036\U000e007f"
- FLAG_FOR_KUPISKIS_LT_23 = "\U0001f3f4\U000e006c\U000e0074\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_ROKISKIS_LT_40 = "\U0001f3f4\U000e006c\U000e0074\U000e0034\U000e0030\U000e007f"
- FLAG_FOR_SIAULIU_MUNICIPALITY_LT_43 = "\U0001f3f4\U000e006c\U000e0074\U000e0034\U000e0033\U000e007f"
- FLAG_FOR_KAZLU_RUDA_LT_17 = "\U0001f3f4\U000e006c\U000e0074\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_TELSIAI_LT_51 = "\U0001f3f4\U000e006c\U000e0074\U000e0035\U000e0031\U000e007f"
- FLAG_FOR_KLAIPEDA_LT_21 = "\U0001f3f4\U000e006c\U000e0074\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_KEDAINIAI_LT_18 = "\U0001f3f4\U000e006c\U000e0074\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_SIAULIAI_LT_44 = "\U0001f3f4\U000e006c\U000e0074\U000e0034\U000e0034\U000e007f"
- FLAG_FOR_PALANGA_LT_31 = "\U0001f3f4\U000e006c\U000e0074\U000e0033\U000e0031\U000e007f"
- FLAG_FOR_PANEVEZYS_LT_33 = "\U0001f3f4\U000e006c\U000e0074\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_SILALE_LT_45 = "\U0001f3f4\U000e006c\U000e0074\U000e0034\U000e0035\U000e007f"
- FLAG_FOR_SAKIAI_LT_41 = "\U0001f3f4\U000e006c\U000e0074\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_TAURAGE_LT_50 = "\U0001f3f4\U000e006c\U000e0074\U000e0035\U000e0030\U000e007f"
- FLAG_FOR_MOLETAI_LT_27 = "\U0001f3f4\U000e006c\U000e0074\U000e0032\U000e0037\U000e007f"
- FLAG_FOR_SKUODAS_LT_48 = "\U0001f3f4\U000e006c\U000e0074\U000e0034\U000e0038\U000e007f"
- FLAG_FOR_UKMERGE_LT_53 = "\U0001f3f4\U000e006c\U000e0074\U000e0035\U000e0033\U000e007f"
- FLAG_FOR_VILKAVISKIS_LT_56 = "\U0001f3f4\U000e006c\U000e0074\U000e0035\U000e0036\U000e007f"
- FLAG_FOR_PAGEGIAI_LT_29 = "\U0001f3f4\U000e006c\U000e0074\U000e0032\U000e0039\U000e007f"
- FLAG_FOR_RIETAVAS_LT_39 = "\U0001f3f4\U000e006c\U000e0074\U000e0033\U000e0039\U000e007f"
- FLAG_FOR_SILUTE_LT_46 = "\U0001f3f4\U000e006c\U000e0074\U000e0034\U000e0036\U000e007f"
- FLAG_FOR_SVENCIONYS_LT_49 = "\U0001f3f4\U000e006c\U000e0074\U000e0034\U000e0039\U000e007f"
- FLAG_FOR_GRAND_BASSA_LR_GB = "\U0001f3f4\U000e006c\U000e0072\U000e0067\U000e0062\U000e007f"
- FLAG_FOR_TRAKAI_LT_52 = "\U0001f3f4\U000e006c\U000e0074\U000e0035\U000e0032\U000e007f"
- FLAG_FOR_LAZDIJAI_LT_24 = "\U0001f3f4\U000e006c\U000e0074\U000e0032\U000e0034\U000e007f"
- FLAG_FOR_MARIJAMPOLE_LT_25 = "\U0001f3f4\U000e006c\U000e0074\U000e0032\U000e0035\U000e007f"
- FLAG_FOR_VARENA_LT_55 = "\U0001f3f4\U000e006c\U000e0074\U000e0035\U000e0035\U000e007f"
- FLAG_FOR_MAZEIKIAI_LT_26 = "\U0001f3f4\U000e006c\U000e0074\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_PLUNGE_LT_35 = "\U0001f3f4\U000e006c\U000e0074\U000e0033\U000e0035\U000e007f"
- FLAG_FOR_RADVILISKIS_LT_37 = "\U0001f3f4\U000e006c\U000e0074\U000e0033\U000e0037\U000e007f"
- FLAG_FOR_KRETINGA_LT_22 = "\U0001f3f4\U000e006c\U000e0074\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_KELME_LT_19 = "\U0001f3f4\U000e006c\U000e0074\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_SIRVINTOS_LT_47 = "\U0001f3f4\U000e006c\U000e0074\U000e0034\U000e0037\U000e007f"
- FLAG_FOR_NERINGA_LT_28 = "\U0001f3f4\U000e006c\U000e0074\U000e0032\U000e0038\U000e007f"
- FLAG_FOR_AIZPUTE_LV_003 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_GREVENMACHER_LU_GR = "\U0001f3f4\U000e006c\U000e0075\U000e0067\U000e0072\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_MAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f468\U0001f3fd\u200d\U0001f476\U0001f3fd"
- FLAG_FOR_BALDONE_LV_013 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_AKNISTE_LV_004 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_UTENA_COUNTY_LT_UT = "\U0001f3f4\U000e006c\U000e0074\U000e0075\U000e0074\U000e007f"
- FLAG_FOR_ALYTUS_COUNTY_LT_AL = "\U0001f3f4\U000e006c\U000e0074\U000e0061\U000e006c\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f467\U0001f3fc"
- FLAG_FOR_VISAGINAS_LT_59 = "\U0001f3f4\U000e006c\U000e0074\U000e0035\U000e0039\U000e007f"
- KISS_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc"
- FLAG_FOR_KLAIPEDA_COUNTY_LT_KL = "\U0001f3f4\U000e006c\U000e0074\U000e006b\U000e006c\U000e007f"
- FLAG_FOR_REMICH_LU_RM = "\U0001f3f4\U000e006c\U000e0075\U000e0072\U000e006d\U000e007f"
- FLAG_FOR_RATANAKIRI_KH_16 = "\U0001f3f4\U000e006b\U000e0068\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_AMATA_LV_008 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_RASEINIAI_LT_38 = "\U0001f3f4\U000e006c\U000e0074\U000e0033\U000e0038\U000e007f"
- FLAG_FOR_MERSCH_LU_ME = "\U0001f3f4\U000e006c\U000e0075\U000e006d\U000e0065\U000e007f"
- FLAG_FOR_VIANDEN_LU_VD = "\U0001f3f4\U000e006c\U000e0075\U000e0076\U000e0064\U000e007f"
- FLAG_FOR_CLERVAUX_LU_CL = "\U0001f3f4\U000e006c\U000e0075\U000e0063\U000e006c\U000e007f"
- FLAG_FOR_VILNIUS_COUNTY_LT_VL = "\U0001f3f4\U000e006c\U000e0074\U000e0076\U000e006c\U000e007f"
- FLAG_FOR_ECHTERNACH_LU_EC = "\U0001f3f4\U000e006c\U000e0075\U000e0065\U000e0063\U000e007f"
- FLAG_FOR_DIEKIRCH_LU_DI = "\U0001f3f4\U000e006c\U000e0075\U000e0064\U000e0069\U000e007f"
- FLAG_FOR_SIAULIAI_COUNTY_LT_SA = "\U0001f3f4\U000e006c\U000e0074\U000e0073\U000e0061\U000e007f"
- FLAG_FOR_TAURAGE_COUNTY_LT_TA = "\U0001f3f4\U000e006c\U000e0074\U000e0074\U000e0061\U000e007f"
- FLAG_FOR_MARIJAMPOLE_COUNTY_LT_MR = "\U0001f3f4\U000e006c\U000e0074\U000e006d\U000e0072\U000e007f"
- FLAG_FOR_ADAZI_LV_011 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_ALUKSNE_LV_007 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_KULDIGA_LV_050 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0035\U000e0030\U000e007f"
- FLAG_FOR_BALVI_LV_015 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_LABORIE_LC_07 = "\U0001f3f4\U000e006c\U000e0063\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_KARSAVA_LV_044 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0034\U000e0034\U000e007f"
- FLAG_FOR_KEGUMS_LV_051 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0035\U000e0031\U000e007f"
- FLAG_FOR_BALTINAVA_LV_014 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_KRUSTPILS_LV_049 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0034\U000e0039\U000e007f"
- FLAG_FOR_GROBINA_LV_032 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_BAUSKA_LV_016 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_DOBELE_LV_026 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_BROCENI_LV_018 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_IECAVA_LV_034 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0033\U000e0034\U000e007f"
- FLAG_FOR_CESVAINE_LV_021 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_AJLOUN_JO_AJ = "\U0001f3f4\U000e006a\U000e006f\U000e0061\U000e006a\U000e007f"
- FLAG_FOR_JAUNJELGAVA_LV_038 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0033\U000e0038\U000e007f"
- FLAG_FOR_KOCENI_LV_045 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0034\U000e0035\U000e007f"
- FLAG_FOR_GARKALNE_LV_031 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0033\U000e0031\U000e007f"
- FLAG_FOR_AIZKRAUKLE_LV_002 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_CIBLA_LV_023 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_JAUNPIEBALGA_LV_039 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0033\U000e0039\U000e007f"
- FLAG_FOR_DUNDAGA_LV_027 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0032\U000e0037\U000e007f"
- FLAG_FOR_CESIS_LV_022 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_KRIMULDA_LV_048 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0034\U000e0038\U000e007f"
- FLAG_FOR_CARNIKAVA_LV_020 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_IKSKILE_LV_035 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0033\U000e0035\U000e007f"
- FLAG_FOR_GULBENE_LV_033 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_KRASLAVA_LV_047 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0034\U000e0037\U000e007f"
- FLAG_FOR_JAUNPILS_LV_040 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0034\U000e0030\U000e007f"
- FLAG_FOR_BURTNIEKI_LV_019 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_BEVERINA_LV_017 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0031\U000e0037\U000e007f"
- FLAG_FOR_KANDAVA_LV_043 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0034\U000e0033\U000e007f"
- FLAG_FOR_LIGATNE_LV_055 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0035\U000e0035\U000e007f"
- FLAG_FOR_SAULKRASTI_LV_089 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0038\U000e0039\U000e007f"
- FLAG_FOR_SALASPILS_LV_087 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0038\U000e0037\U000e007f"
- FLAG_FOR_PRIEKULI_LV_075 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0037\U000e0035\U000e007f"
- FLAG_FOR_RUCAVA_LV_081 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0038\U000e0031\U000e007f"
- FLAG_FOR_NAUKSENI_LV_064 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0036\U000e0034\U000e007f"
- FLAG_FOR_PRIEKULE_LV_074 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0037\U000e0034\U000e007f"
- FLAG_FOR_SEJA_LV_090 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0039\U000e0030\U000e007f"
- FLAG_FOR_NERETA_LV_065 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0036\U000e0035\U000e007f"
- FLAG_FOR_PARGAUJA_LV_070 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0037\U000e0030\U000e007f"
- FLAG_FOR_MARUPE_LV_062 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0036\U000e0032\U000e007f"
- FLAG_FOR_PAVILOSTA_LV_071 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0037\U000e0031\U000e007f"
- FLAG_FOR_OLAINE_LV_068 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0036\U000e0038\U000e007f"
- FLAG_FOR_LIMBAZI_LV_054 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0035\U000e0034\U000e007f"
- FLAG_FOR_RUJIENA_LV_084 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0038\U000e0034\U000e007f"
- FLAG_FOR_PLAVINAS_LV_072 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0037\U000e0032\U000e007f"
- FLAG_FOR_RUNDALE_LV_083 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0038\U000e0033\U000e007f"
- FLAG_FOR_PREILI_LV_073 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0037\U000e0033\U000e007f"
- FLAG_FOR_RUGAJI_LV_082 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0038\U000e0032\U000e007f"
- FLAG_FOR_MERSRAGS_LV_063 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0036\U000e0033\U000e007f"
- FLAG_FOR_SALDUS_LV_088 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0038\U000e0038\U000e007f"
- FLAG_FOR_LUDZA_LV_058 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0035\U000e0038\U000e007f"
- FLAG_FOR_LIVANI_LV_056 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0035\U000e0036\U000e007f"
- FLAG_FOR_ROPAZI_LV_080 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0038\U000e0030\U000e007f"
- FLAG_FOR_KOH_KONG_KH_9 = "\U0001f3f4\U000e006b\U000e0068\U000e0039\U000e007f"
- FLAG_FOR_RIEBINI_LV_078 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0037\U000e0038\U000e007f"
- FLAG_FOR_LIELVARDE_LV_053 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0035\U000e0033\U000e007f"
- FLAG_FOR_KEKAVA_LV_052 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0035\U000e0032\U000e007f"
- FLAG_FOR_NICA_LV_066 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0036\U000e0036\U000e007f"
- FLAG_FOR_LUBANA_LV_057 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0035\U000e0037\U000e007f"
- FLAG_FOR_GRAND_EST_FR_GES = "\U0001f3f4\U000e0066\U000e0072\U000e0067\U000e0065\U000e0073\U000e007f"
- FLAG_FOR_RAUNA_LV_076 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0037\U000e0036\U000e007f"
- FLAG_FOR_ROJA_LV_079 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0037\U000e0039\U000e007f"
- FLAG_FOR_MALPILS_LV_061 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0036\U000e0031\U000e007f"
- FLAG_FOR_SMILTENE_LV_094 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0039\U000e0034\U000e007f"
- FLAG_FOR_VARAKLANI_LV_102 = "\U0001f3f4\U000e006c\U000e0076\U000e0031\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_JABAL_AL_GHARBI_LY_JG = "\U0001f3f4\U000e006c\U000e0079\U000e006a\U000e0067\U000e007f"
- FLAG_FOR_VARKAVA_LV_103 = "\U0001f3f4\U000e006c\U000e0076\U000e0031\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_VIESITE_LV_107 = "\U0001f3f4\U000e006c\U000e0076\U000e0031\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_DAUGAVPILS_LV_DGV = "\U0001f3f4\U000e006c\U000e0076\U000e0064\U000e0067\U000e0076\U000e007f"
- FLAG_FOR_KUFRA_LY_KF = "\U0001f3f4\U000e006c\U000e0079\U000e006b\U000e0066\U000e007f"
- FLAG_FOR_VILANI_LV_109 = "\U0001f3f4\U000e006c\U000e0076\U000e0031\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_JURMALA_LV_JUR = "\U0001f3f4\U000e006c\U000e0076\U000e006a\U000e0075\U000e0072\U000e007f"
- FLAG_FOR_VILAKA_LV_108 = "\U0001f3f4\U000e006c\U000e0076\U000e0031\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_VENTSPILS_LV_VEN = "\U0001f3f4\U000e006c\U000e0076\U000e0076\U000e0065\U000e006e\U000e007f"
- FLAG_FOR_MURQUB_LY_MB = "\U0001f3f4\U000e006c\U000e0079\U000e006d\U000e0062\U000e007f"
- FLAG_FOR_VECPIEBALGA_LV_104 = "\U0001f3f4\U000e006c\U000e0076\U000e0031\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_TUKUMS_LV_099 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0039\U000e0039\U000e007f"
- FLAG_FOR_BENGHAZI_LY_BA = "\U0001f3f4\U000e006c\U000e0079\U000e0062\U000e0061\U000e007f"
- FLAG_FOR_LIEPAJA_LV_LPX = "\U0001f3f4\U000e006c\U000e0076\U000e006c\U000e0070\U000e0078\U000e007f"
- FLAG_FOR_JABAL_AL_AKHDAR_LY_JA = "\U0001f3f4\U000e006c\U000e0079\U000e006a\U000e0061\U000e007f"
- FLAG_FOR_ZARASAI_LT_60 = "\U0001f3f4\U000e006c\U000e0074\U000e0036\U000e0030\U000e007f"
- FLAG_FOR_VECUMNIEKI_LV_105 = "\U0001f3f4\U000e006c\U000e0076\U000e0031\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_GHAT_LY_GT = "\U0001f3f4\U000e006c\U000e0079\U000e0067\U000e0074\U000e007f"
- FLAG_FOR_TALSI_LV_097 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0039\U000e0037\U000e007f"
- FLAG_FOR_JELGAVA_LV_JEL = "\U0001f3f4\U000e006c\U000e0076\U000e006a\U000e0065\U000e006c\U000e007f"
- FLAG_FOR_STRENCI_LV_096 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0039\U000e0036\U000e007f"
- FLAG_FOR_NORTH_HAMGYONG_KP_09 = "\U0001f3f4\U000e006b\U000e0070\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_VALMIERA_LV_VMR = "\U0001f3f4\U000e006c\U000e0076\U000e0076\U000e006d\U000e0072\U000e007f"
- FLAG_FOR_TERVETE_LV_098 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0039\U000e0038\U000e007f"
- FLAG_FOR_REZEKNE_LV_REZ = "\U0001f3f4\U000e006c\U000e0076\U000e0072\U000e0065\U000e007a\U000e007f"
- FLAG_FOR_ZILUPE_LV_110 = "\U0001f3f4\U000e006c\U000e0076\U000e0031\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_JEKABPILS_LV_JKB = "\U0001f3f4\U000e006c\U000e0076\U000e006a\U000e006b\U000e0062\U000e007f"
- FLAG_FOR_SIGULDA_LV_091 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0039\U000e0031\U000e007f"
- FLAG_FOR_STOPINI_LV_095 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0039\U000e0035\U000e007f"
- FLAG_FOR_ENGURE_LV_029 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0032\U000e0039\U000e007f"
- FLAG_FOR_WADI_AL_HAYAA_LY_WD = "\U0001f3f4\U000e006c\U000e0079\U000e0077\U000e0064\U000e007f"
- FLAG_FOR_AL_WAHAT_LY_WA = "\U0001f3f4\U000e006c\U000e0079\U000e0077\U000e0061\U000e007f"
- FLAG_FOR_LABE_REGION_GN_L = "\U0001f3f4\U000e0067\U000e006e\U000e006c\U000e007f"
- FLAG_FOR_NALUT_LY_NL = "\U0001f3f4\U000e006c\U000e0079\U000e006e\U000e006c\U000e007f"
- FLAG_FOR_MONEGHETTI_MC_MG = "\U0001f3f4\U000e006d\U000e0063\U000e006d\U000e0067\U000e007f"
- FLAG_FOR_MARRAKESH_TENSIFT_EL_HAOUZ_MA_11 = "\U0001f3f4\U000e006d\U000e0061\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_LA_COLLE_MC_CL = "\U0001f3f4\U000e006d\U000e0063\U000e0063\U000e006c\U000e007f"
- FLAG_FOR_ZAWIYA_LY_ZA = "\U0001f3f4\U000e006c\U000e0079\U000e007a\U000e0061\U000e007f"
- FLAG_FOR_EL_TARF_DZ_36 = "\U0001f3f4\U000e0064\U000e007a\U000e0033\U000e0036\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_MURZUQ_LY_MQ = "\U0001f3f4\U000e006c\U000e0079\U000e006d\U000e0071\U000e007f"
- FLAG_FOR_CHAOUIA_OUARDIGHA_MA_09 = "\U0001f3f4\U000e006d\U000e0061\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_SIRTE_LY_SR = "\U0001f3f4\U000e006c\U000e0079\U000e0073\U000e0072\U000e007f"
- FLAG_FOR_NUQAT_AL_KHAMS_LY_NQ = "\U0001f3f4\U000e006c\U000e0079\U000e006e\U000e0071\U000e007f"
- FLAG_FOR_LA_CONDAMINE_MC_CO = "\U0001f3f4\U000e006d\U000e0063\U000e0063\U000e006f\U000e007f"
- FLAG_FOR_MEKNES_TAFILALET_MA_06 = "\U0001f3f4\U000e006d\U000e0061\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_LA_GARE_MC_GA = "\U0001f3f4\U000e006d\U000e0063\U000e0067\U000e0061\U000e007f"
- FLAG_FOR_GUELMIM_ES_SEMARA_MA_14 = "\U0001f3f4\U000e006d\U000e0061\U000e0031\U000e0034\U000e007f"
- COUPLE_WITH_HEART_WOMAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb"
- FLAG_FOR_GHARB_CHRARDA_BENI_HSSEN_MA_02 = "\U0001f3f4\U000e006d\U000e0061\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_FONTVIEILLE_MC_FO = "\U0001f3f4\U000e006d\U000e0063\U000e0066\U000e006f\U000e007f"
- FLAG_FOR_TADLA_AZILAL_MA_12 = "\U0001f3f4\U000e006d\U000e0061\U000e0031\U000e0032\U000e007f"
- FAMILY_MAN_DARK_SKIN_TONE_BOY_DARK_SKIN_TONE_GIRL_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f466\U0001f3ff\u200d\U0001f467\U0001f3ff"
- FLAG_FOR_RABAT_SALE_ZEMMOUR_ZAER_MA_07 = "\U0001f3f4\U000e006d\U000e0061\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_MALBOUSQUET_MC_MA = "\U0001f3f4\U000e006d\U000e0063\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_OUED_ED_DAHAB_LAGOUIRA_MA_16 = "\U0001f3f4\U000e006d\U000e0061\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_CALARASI_MD_CL = "\U0001f3f4\U000e006d\U000e0064\U000e0063\U000e006c\U000e007f"
- FLAG_FOR_SOLDANESTI_MD_SD = "\U0001f3f4\U000e006d\U000e0064\U000e0073\U000e0064\U000e007f"
- FLAG_FOR_IALOVENI_MD_IA = "\U0001f3f4\U000e006d\U000e0064\U000e0069\U000e0061\U000e007f"
- FLAG_FOR_LEOVA_MD_LE = "\U0001f3f4\U000e006d\U000e0064\U000e006c\U000e0065\U000e007f"
- FLAG_FOR_BALTI_MD_BA = "\U0001f3f4\U000e006d\U000e0064\U000e0062\U000e0061\U000e007f"
- FLAG_FOR_CRIULENI_MD_CR = "\U0001f3f4\U000e006d\U000e0064\U000e0063\U000e0072\U000e007f"
- FLAG_FOR_CENTRE_VAL_DE_LOIRE_FR_CVL = "\U0001f3f4\U000e0066\U000e0072\U000e0063\U000e0076\U000e006c\U000e007f"
- FLAG_FOR_CANTEMIR_MD_CT = "\U0001f3f4\U000e006d\U000e0064\U000e0063\U000e0074\U000e007f"
- FLAG_FOR_CHISINAU_MD_CU = "\U0001f3f4\U000e006d\U000e0064\U000e0063\U000e0075\U000e007f"
- FLAG_FOR_FALESTI_MD_FA = "\U0001f3f4\U000e006d\U000e0064\U000e0066\U000e0061\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_GIRL_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f467\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_DONDUSENI_MD_DO = "\U0001f3f4\U000e006d\U000e0064\U000e0064\U000e006f\U000e007f"
- FLAG_FOR_MELILLA_ES_ML = "\U0001f3f4\U000e0065\U000e0073\U000e006d\U000e006c\U000e007f"
- FLAG_FOR_OCNITA_MD_OC = "\U0001f3f4\U000e006d\U000e0064\U000e006f\U000e0063\U000e007f"
- FLAG_FOR_SOROCA_MD_SO = "\U0001f3f4\U000e006d\U000e0064\U000e0073\U000e006f\U000e007f"
- FLAG_FOR_DUBASARI_MD_DU = "\U0001f3f4\U000e006d\U000e0064\U000e0064\U000e0075\U000e007f"
- FLAG_FOR_SINGEREI_MD_SI = "\U0001f3f4\U000e006d\U000e0064\U000e0073\U000e0069\U000e007f"
- FLAG_FOR_EDINET_MD_ED = "\U0001f3f4\U000e006d\U000e0064\U000e0065\U000e0064\U000e007f"
- FLAG_FOR_SABHA_LY_SB = "\U0001f3f4\U000e006c\U000e0079\U000e0073\U000e0062\U000e007f"
- FLAG_FOR_NISPORENI_MD_NI = "\U0001f3f4\U000e006d\U000e0064\U000e006e\U000e0069\U000e007f"
- FLAG_FOR_BRICENI_MD_BR = "\U0001f3f4\U000e006d\U000e0064\U000e0062\U000e0072\U000e007f"
- FAMILY_WOMAN_MEDIUM_SKIN_TONE_BABY_MEDIUM_SKIN_TONE_BOY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f476\U0001f3fd\u200d\U0001f466\U0001f3fd"
- FLAG_FOR_ORHEI_MD_OR = "\U0001f3f4\U000e006d\U000e0064\U000e006f\U000e0072\U000e007f"
- FLAG_FOR_CIMISLIA_MD_CM = "\U0001f3f4\U000e006d\U000e0064\U000e0063\U000e006d\U000e007f"
- FLAG_FOR_GLODENI_MD_GL = "\U0001f3f4\U000e006d\U000e0064\U000e0067\U000e006c\U000e007f"
- FLAG_FOR_RISCANI_MD_RI = "\U0001f3f4\U000e006d\U000e0064\U000e0072\U000e0069\U000e007f"
- FLAG_FOR_BENDER_MD_BD = "\U0001f3f4\U000e006d\U000e0064\U000e0062\U000e0064\U000e007f"
- FLAG_FOR_BASARABEASCA_MD_BS = "\U0001f3f4\U000e006d\U000e0064\U000e0062\U000e0073\U000e007f"
- FLAG_FOR_JARDIN_EXOTIQUE_DE_MONACO_MC_JE = "\U0001f3f4\U000e006d\U000e0063\U000e006a\U000e0065\U000e007f"
- FLAG_FOR_ERGLI_LV_030 = "\U0001f3f4\U000e006c\U000e0076\U000e0030\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_CAHUL_MD_CA = "\U0001f3f4\U000e006d\U000e0064\U000e0063\U000e0061\U000e007f"
- FLAG_FOR_FLORESTI_MD_FL = "\U0001f3f4\U000e006d\U000e0064\U000e0066\U000e006c\U000e007f"
- FLAG_FOR_HINCESTI_MD_HI = "\U0001f3f4\U000e006d\U000e0064\U000e0068\U000e0069\U000e007f"
- FLAG_FOR_TOAMASINA_MG_A = "\U0001f3f4\U000e006d\U000e0067\U000e0061\U000e007f"
- TAG_APOSTROPHE = "\U000e0027"
- FLAG_FOR_TRIPOLI_LY_TB = "\U0001f3f4\U000e006c\U000e0079\U000e0074\U000e0062\U000e007f"
- FLAG_FOR_BOGOVINJE_MK_06 = "\U0001f3f4\U000e006d\U000e006b\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_MOJKOVAC_ME_11 = "\U0001f3f4\U000e006d\U000e0065\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_PLUZINE_ME_15 = "\U0001f3f4\U000e006d\U000e0065\U000e0031\U000e0035\U000e007f"
- FLAG_FOR_BOGDANCI_MK_05 = "\U0001f3f4\U000e006d\U000e006b\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_ISFAHAN_IR_04 = "\U0001f3f4\U000e0069\U000e0072\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_BUDVA_ME_05 = "\U0001f3f4\U000e006d\U000e0065\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_FIANARANTSOA_MG_F = "\U0001f3f4\U000e006d\U000e0067\U000e0066\U000e007f"
- FLAG_FOR_PLJEVLJA_ME_14 = "\U0001f3f4\U000e006d\U000e0065\U000e0031\U000e0034\U000e007f"
- FAMILY_MAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f476\U0001f3fc"
- FLAG_FOR_BIJELO_POLJE_ME_04 = "\U0001f3f4\U000e006d\U000e0065\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_ANTSIRANANA_MG_D = "\U0001f3f4\U000e006d\U000e0067\U000e0064\U000e007f"
- FLAG_FOR_SAVNIK_ME_18 = "\U0001f3f4\U000e006d\U000e0065\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_BEROVO_MK_03 = "\U0001f3f4\U000e006d\U000e006b\U000e0030\U000e0033\U000e007f"
- FLAG_FOR_TOLIARA_MG_U = "\U0001f3f4\U000e006d\U000e0067\U000e0075\U000e007f"
- FLAG_FOR_KOLASIN_ME_09 = "\U0001f3f4\U000e006d\U000e0065\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_ANDRIJEVICA_ME_01 = "\U0001f3f4\U000e006d\U000e0065\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_DERNA_LY_DR = "\U0001f3f4\U000e006c\U000e0079\U000e0064\U000e0072\U000e007f"
- FLAG_FOR_ANTANANARIVO_MG_T = "\U0001f3f4\U000e006d\U000e0067\U000e0074\U000e007f"
- FLAG_FOR_QEQQATA_GL_QE = "\U0001f3f4\U000e0067\U000e006c\U000e0071\U000e0065\U000e007f"
- FLAG_FOR_MAHAJANGA_MG_M = "\U0001f3f4\U000e006d\U000e0067\U000e006d\U000e007f"
- FLAG_FOR_NIKSIC_ME_12 = "\U0001f3f4\U000e006d\U000e0065\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_PETNJICA_ME_23 = "\U0001f3f4\U000e006d\U000e0065\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_BOSILOVO_MK_07 = "\U0001f3f4\U000e006d\U000e006b\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_FES_BOULEMANE_MA_05 = "\U0001f3f4\U000e006d\U000e0061\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_HOUAPHANH_LA_HO = "\U0001f3f4\U000e006c\U000e0061\U000e0068\U000e006f\U000e007f"
- FLAG_FOR_STEFAN_VODA_MD_SV = "\U0001f3f4\U000e006d\U000e0064\U000e0073\U000e0076\U000e007f"
- FAMILY_MAN_LIGHT_SKIN_TONE_MAN_LIGHT_SKIN_TONE_BABY_LIGHT_SKIN_TONE_GIRL_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f468\U0001f3fb\u200d\U0001f476\U0001f3fb\u200d\U0001f467\U0001f3fb"
- FLAG_FOR_WADI_AL_SHATII_LY_WS = "\U0001f3f4\U000e006c\U000e0079\U000e0077\U000e0073\U000e007f"
- FLAG_FOR_PODGORICA_ME_16 = "\U0001f3f4\U000e006d\U000e0065\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_KOTOR_ME_10 = "\U0001f3f4\U000e006d\U000e0065\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_MARANHAO_BR_MA = "\U0001f3f4\U000e0062\U000e0072\U000e006d\U000e0061\U000e007f"
- FLAG_FOR_KRIVOGASTANI_MK_45 = "\U0001f3f4\U000e006d\U000e006b\U000e0034\U000e0035\U000e007f"
- FLAG_FOR_KARBINCI_MK_37 = "\U0001f3f4\U000e006d\U000e006b\U000e0033\U000e0037\U000e007f"
- FLAG_FOR_KAVADARCI_MK_36 = "\U0001f3f4\U000e006d\U000e006b\U000e0033\U000e0036\U000e007f"
- FLAG_FOR_MAVROVO_AND_ROSTUSA_MK_50 = "\U0001f3f4\U000e006d\U000e006b\U000e0035\U000e0030\U000e007f"
- FLAG_FOR_ZELINO_MK_30 = "\U0001f3f4\U000e006d\U000e006b\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_DOJRAN_MK_26 = "\U0001f3f4\U000e006d\U000e006b\U000e0032\U000e0036\U000e007f"
- FLAG_FOR_KOCANI_MK_42 = "\U0001f3f4\U000e006d\U000e006b\U000e0034\U000e0032\U000e007f"
- FLAG_FOR_NEGOTINO_MK_54 = "\U0001f3f4\U000e006d\U000e006b\U000e0035\U000e0034\U000e007f"
- FLAG_FOR_ILINDEN_MK_34 = "\U0001f3f4\U000e006d\U000e006b\U000e0033\U000e0034\U000e007f"
- FLAG_FOR_DEBAR_MK_21 = "\U0001f3f4\U000e006d\U000e006b\U000e0032\U000e0031\U000e007f"
- FLAG_FOR_LOZOVO_MK_49 = "\U0001f3f4\U000e006d\U000e006b\U000e0034\U000e0039\U000e007f"
- FLAG_FOR_GEVGELIJA_MK_18 = "\U0001f3f4\U000e006d\U000e006b\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_NOVACI_MK_55 = "\U0001f3f4\U000e006d\U000e006b\U000e0035\U000e0035\U000e007f"
- FLAG_FOR_VINICA_MK_14 = "\U0001f3f4\U000e006d\U000e006b\U000e0031\U000e0034\U000e007f"
- FLAG_FOR_VASILEVO_MK_11 = "\U0001f3f4\U000e006d\U000e006b\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_NOVO_SELO_MK_56 = "\U0001f3f4\U000e006d\U000e006b\U000e0035\U000e0036\U000e007f"
- FLAG_FOR_KUMANOVO_MK_47 = "\U0001f3f4\U000e006d\U000e006b\U000e0034\U000e0037\U000e007f"
- FLAG_FOR_GRADSKO_MK_20 = "\U0001f3f4\U000e006d\U000e006b\U000e0032\U000e0030\U000e007f"
- FLAG_FOR_KONCE_MK_41 = "\U0001f3f4\U000e006d\U000e006b\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_ZELENIKOVO_MK_32 = "\U0001f3f4\U000e006d\U000e006b\U000e0033\U000e0032\U000e007f"
- FLAG_FOR_JEGUNOVCE_MK_35 = "\U0001f3f4\U000e006d\U000e006b\U000e0033\U000e0035\U000e007f"
- FLAG_FOR_MAKEDONSKA_KAMENICA_MK_51 = "\U0001f3f4\U000e006d\U000e006b\U000e0035\U000e0031\U000e007f"
- FLAG_FOR_VEVCANI_MK_12 = "\U0001f3f4\U000e006d\U000e006b\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_GOSTIVAR_MK_19 = "\U0001f3f4\U000e006d\U000e006b\U000e0031\U000e0039\U000e007f"
- FLAG_FOR_KRUSEVO_MK_46 = "\U0001f3f4\U000e006d\U000e006b\U000e0034\U000e0036\U000e007f"
- FLAG_FOR_BRVENICA_MK_08 = "\U0001f3f4\U000e006d\U000e006b\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_LIPKOVO_MK_48 = "\U0001f3f4\U000e006d\U000e006b\U000e0034\U000e0038\U000e007f"
- FLAG_FOR_VALANDOVO_MK_10 = "\U0001f3f4\U000e006d\U000e006b\U000e0031\U000e0030\U000e007f"
- FLAG_FOR_KRATOVO_MK_43 = "\U0001f3f4\U000e006d\U000e006b\U000e0034\U000e0033\U000e007f"
- FLAG_FOR_KRIVA_PALANKA_MK_44 = "\U0001f3f4\U000e006d\U000e006b\U000e0034\U000e0034\U000e007f"
- FLAG_FOR_ZRNOVCI_MK_33 = "\U0001f3f4\U000e006d\U000e006b\U000e0033\U000e0033\U000e007f"
- FLAG_FOR_TEL_AVIV_DISTRICT_IL_TA = "\U0001f3f4\U000e0069\U000e006c\U000e0074\U000e0061\U000e007f"
- FLAG_FOR_DANILOVGRAD_ME_07 = "\U0001f3f4\U000e006d\U000e0065\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_DEBARCA_MK_22 = "\U0001f3f4\U000e006d\U000e006b\U000e0032\U000e0032\U000e007f"
- FLAG_FOR_VRAPCISTE_MK_16 = "\U0001f3f4\U000e006d\U000e006b\U000e0031\U000e0036\U000e007f"
- FLAG_FOR_DELCEVO_MK_23 = "\U0001f3f4\U000e006d\U000e006b\U000e0032\U000e0033\U000e007f"
- FLAG_FOR_VELES_MK_13 = "\U0001f3f4\U000e006d\U000e006b\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_AYEYARWADY_MM_07 = "\U0001f3f4\U000e006d\U000e006d\U000e0030\U000e0037\U000e007f"
- FLAG_FOR_KAYAH_MM_12 = "\U0001f3f4\U000e006d\U000e006d\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_STARO_NAGORICANE_MK_71 = "\U0001f3f4\U000e006d\U000e006b\U000e0037\U000e0031\U000e007f"
- FLAG_FOR_STIP_MK_83 = "\U0001f3f4\U000e006d\U000e006b\U000e0038\U000e0033\U000e007f"
- FLAG_FOR_DAEJEON_KR_30 = "\U0001f3f4\U000e006b\U000e0072\U000e0033\U000e0030\U000e007f"
- FLAG_FOR_TETOVO_MK_76 = "\U0001f3f4\U000e006d\U000e006b\U000e0037\U000e0036\U000e007f"
- FLAG_FOR_SZEGED_HU_SD = "\U0001f3f4\U000e0068\U000e0075\U000e0073\U000e0064\U000e007f"
- FLAG_FOR_MOPTI_ML_5 = "\U0001f3f4\U000e006d\U000e006c\U000e0035\U000e007f"
- FLAG_FOR_SIKASSO_ML_3 = "\U0001f3f4\U000e006d\U000e006c\U000e0033\U000e007f"
- FLAG_FOR_U_S_OUTLYING_ISLANDS_US_UM = "\U0001f3f4\U000e0075\U000e0073\U000e0075\U000e006d\U000e007f"
- FLAG_FOR_CASKA_MK_80 = "\U0001f3f4\U000e006d\U000e006b\U000e0038\U000e0030\U000e007f"
- FLAG_FOR_STRUGA_MK_72 = "\U0001f3f4\U000e006d\U000e006b\U000e0037\U000e0032\U000e007f"
- FLAG_FOR_KOULIKORO_ML_2 = "\U0001f3f4\U000e006d\U000e006c\U000e0032\U000e007f"
- FLAG_FOR_PETROVEC_MK_59 = "\U0001f3f4\U000e006d\U000e006b\U000e0035\U000e0039\U000e007f"
- KISS_MAN_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe"
- FLAG_FOR_CUCER_SANDEVO_MK_82 = "\U0001f3f4\U000e006d\U000e006b\U000e0038\U000e0032\U000e007f"
- FLAG_FOR_SOPISTE_MK_70 = "\U0001f3f4\U000e006d\U000e006b\U000e0037\U000e0030\U000e007f"
- FLAG_FOR_MANDALAY_MM_04 = "\U0001f3f4\U000e006d\U000e006d\U000e0030\U000e0034\U000e007f"
- FLAG_FOR_GENEVA_CH_GE = "\U0001f3f4\U000e0063\U000e0068\U000e0067\U000e0065\U000e007f"
- FLAG_FOR_KACHIN_MM_11 = "\U0001f3f4\U000e006d\U000e006d\U000e0031\U000e0031\U000e007f"
- FLAG_FOR_PROBISTIP_MK_63 = "\U0001f3f4\U000e006d\U000e006b\U000e0036\U000e0033\U000e007f"
- FLAG_FOR_RESEN_MK_66 = "\U0001f3f4\U000e006d\U000e006b\U000e0036\U000e0036\U000e007f"
- FLAG_FOR_TANINTHARYI_MM_05 = "\U0001f3f4\U000e006d\U000e006d\U000e0030\U000e0035\U000e007f"
- FLAG_FOR_ROSOMAN_MK_67 = "\U0001f3f4\U000e006d\U000e006b\U000e0036\U000e0037\U000e007f"
- FLAG_FOR_CESINOVO_OBLESEVO_MK_81 = "\U0001f3f4\U000e006d\U000e006b\U000e0038\U000e0031\U000e007f"
- FLAG_FOR_PEHCEVO_MK_60 = "\U0001f3f4\U000e006d\U000e006b\U000e0036\U000e0030\U000e007f"
- FLAG_FOR_SAGAING_MM_01 = "\U0001f3f4\U000e006d\U000e006d\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_ZAVKHAN_MN_057 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0035\U000e0037\U000e007f"
- FLAG_FOR_TOV_MN_047 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0034\U000e0037\U000e007f"
- FLAG_FOR_INCHIRI_MR_12 = "\U0001f3f4\U000e006d\U000e0072\U000e0031\U000e0032\U000e007f"
- FLAG_FOR_TAGANT_MR_09 = "\U0001f3f4\U000e006d\U000e0072\U000e0030\U000e0039\U000e007f"
- FLAG_FOR_DAKHLET_NOUADHIBOU_MR_08 = "\U0001f3f4\U000e006d\U000e0072\U000e0030\U000e0038\U000e007f"
- FLAG_FOR_OVORKHANGAI_MN_055 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0035\U000e0035\U000e007f"
- TAG_DOLLAR_SIGN = "\U000e0024"
- FLAG_FOR_HODH_EL_GHARBI_MR_02 = "\U0001f3f4\U000e006d\U000e0072\U000e0030\U000e0032\U000e007f"
- FLAG_FOR_BAYAN_OLGII_MN_071 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0037\U000e0031\U000e007f"
- FLAG_FOR_DUNDGOVI_MN_059 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0035\U000e0039\U000e007f"
- FLAG_FOR_SCHWYZ_CH_SZ = "\U0001f3f4\U000e0063\U000e0068\U000e0073\U000e007a\U000e007f"
- FLAG_FOR_BULGAN_MN_067 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0036\U000e0037\U000e007f"
- TAG_TILDE = "\U000e007e"
- FLAG_FOR_KAYIN_MM_13 = "\U0001f3f4\U000e006d\U000e006d\U000e0031\U000e0033\U000e007f"
- FLAG_FOR_GAO_ML_7 = "\U0001f3f4\U000e006d\U000e006c\U000e0037\U000e007f"
- FLAG_FOR_DORNOD_MN_061 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0036\U000e0031\U000e007f"
- FLAG_FOR_TRARZA_MR_06 = "\U0001f3f4\U000e006d\U000e0072\U000e0030\U000e0036\U000e007f"
- FLAG_FOR_DARKHAN_UUL_MN_037 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0033\U000e0037\U000e007f"
- FLAG_FOR_UVS_MN_046 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0034\U000e0036\U000e007f"
- FLAG_FOR_KHOVSGOL_MN_041 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0034\U000e0031\U000e007f"
- FLAG_FOR_BAYANKHONGOR_MN_069 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0036\U000e0039\U000e007f"
- FLAG_FOR_HODH_ECH_CHARGUI_MR_01 = "\U0001f3f4\U000e006d\U000e0072\U000e0030\U000e0031\U000e007f"
- FLAG_FOR_NAYPYIDAW_MM_18 = "\U0001f3f4\U000e006d\U000e006d\U000e0031\U000e0038\U000e007f"
- FLAG_FOR_DORNOGOVI_MN_063 = "\U0001f3f4\U000e006d\U000e006e\U000e0030\U000e0036\U000e0033\U000e007f"
- FAMILY_WOMAN_MEDIUM_LIGHT_SKIN_TONE_WOMAN_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE_BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f469\U0001f3fc\u200d\U0001f466\U0001f3fc\u200d\U0001f466\U0001f3fc"
- FLAG_FOR_SAN_MIGUEL_SV_SM = "\U0001f3f4\U000e0073\U000e0076\U000e0073\U000e006d\U000e007f"
- FLAG_FOR_MANCHESTER_JM_12 = "\U0001f3f4\U000e006a\U000e006d\U000e0031\U000e0032\U000e007f"
- WHITE_RIGHT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_1_2 = "\u261e\U0001f3fb"
- REVERSED_THUMBS_DOWN_SIGN_EMOJI_MODIFIER_FITZPATRICK_TYPE_1_2 = "\U0001f593\U0001f3fb"
- BLACK_RIGHT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_1_2 = "\u261b\U0001f3fb"
- REVERSED_RAISED_HAND_WITH_FINGERS_SPLAYED_EMOJI_MODIFIER_FITZPATRICK_TYPE_1_2 = "\U0001f591\U0001f3fb"
- WHITE_DOWN_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_1_2 = "\u261f\U0001f3fb"
- BLACK_LEFT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_1_2 = "\u261a\U0001f3fb"
- REVERSED_VICTORY_HAND_EMOJI_MODIFIER_FITZPATRICK_TYPE_1_2 = "\U0001f594\U0001f3fb"
- WHITE_LEFT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_1_2 = "\u261c\U0001f3fb"
- REVERSED_THUMBS_UP_SIGN_EMOJI_MODIFIER_FITZPATRICK_TYPE_1_2 = "\U0001f592\U0001f3fb"
- LEFT_WRITING_HAND_EMOJI_MODIFIER_FITZPATRICK_TYPE_1_2 = "\U0001f58e\U0001f3fb"
- WHITE_LEFT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_3 = "\u261c\U0001f3fc"
- BLACK_RIGHT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_3 = "\u261b\U0001f3fc"
- REVERSED_THUMBS_UP_SIGN_EMOJI_MODIFIER_FITZPATRICK_TYPE_3 = "\U0001f592\U0001f3fc"
- WHITE_RIGHT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_3 = "\u261e\U0001f3fc"
- LEFT_WRITING_HAND_EMOJI_MODIFIER_FITZPATRICK_TYPE_3 = "\U0001f58e\U0001f3fc"
- REVERSED_VICTORY_HAND_EMOJI_MODIFIER_FITZPATRICK_TYPE_3 = "\U0001f594\U0001f3fc"
- WHITE_DOWN_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_3 = "\u261f\U0001f3fc"
- BLACK_LEFT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_3 = "\u261a\U0001f3fc"
- REVERSED_THUMBS_DOWN_SIGN_EMOJI_MODIFIER_FITZPATRICK_TYPE_3 = "\U0001f593\U0001f3fc"
- REVERSED_RAISED_HAND_WITH_FINGERS_SPLAYED_EMOJI_MODIFIER_FITZPATRICK_TYPE_3 = "\U0001f591\U0001f3fc"
- REVERSED_RAISED_HAND_WITH_FINGERS_SPLAYED_EMOJI_MODIFIER_FITZPATRICK_TYPE_4 = "\U0001f591\U0001f3fd"
- BLACK_LEFT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_4 = "\u261a\U0001f3fd"
- REVERSED_THUMBS_DOWN_SIGN_EMOJI_MODIFIER_FITZPATRICK_TYPE_4 = "\U0001f593\U0001f3fd"
- WHITE_DOWN_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_4 = "\u261f\U0001f3fd"
- REVERSED_THUMBS_UP_SIGN_EMOJI_MODIFIER_FITZPATRICK_TYPE_4 = "\U0001f592\U0001f3fd"
- BLACK_RIGHT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_4 = "\u261b\U0001f3fd"
- REVERSED_VICTORY_HAND_EMOJI_MODIFIER_FITZPATRICK_TYPE_4 = "\U0001f594\U0001f3fd"
- WHITE_LEFT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_4 = "\u261c\U0001f3fd"
- LEFT_WRITING_HAND_EMOJI_MODIFIER_FITZPATRICK_TYPE_4 = "\U0001f58e\U0001f3fd"
- WHITE_RIGHT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_4 = "\u261e\U0001f3fd"
- LEFT_WRITING_HAND_EMOJI_MODIFIER_FITZPATRICK_TYPE_5 = "\U0001f58e\U0001f3fe"
- WHITE_RIGHT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_5 = "\u261e\U0001f3fe"
- WHITE_LEFT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_5 = "\u261c\U0001f3fe"
- BLACK_LEFT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_5 = "\u261a\U0001f3fe"
- WHITE_DOWN_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_5 = "\u261f\U0001f3fe"
- REVERSED_THUMBS_DOWN_SIGN_EMOJI_MODIFIER_FITZPATRICK_TYPE_5 = "\U0001f593\U0001f3fe"
- REVERSED_RAISED_HAND_WITH_FINGERS_SPLAYED_EMOJI_MODIFIER_FITZPATRICK_TYPE_5 = "\U0001f591\U0001f3fe"
- REVERSED_VICTORY_HAND_EMOJI_MODIFIER_FITZPATRICK_TYPE_5 = "\U0001f594\U0001f3fe"
- BLACK_RIGHT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_5 = "\u261b\U0001f3fe"
- REVERSED_THUMBS_UP_SIGN_EMOJI_MODIFIER_FITZPATRICK_TYPE_5 = "\U0001f592\U0001f3fe"
- REVERSED_THUMBS_DOWN_SIGN_EMOJI_MODIFIER_FITZPATRICK_TYPE_6 = "\U0001f593\U0001f3ff"
- WHITE_LEFT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_6 = "\u261c\U0001f3ff"
- WHITE_RIGHT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_6 = "\u261e\U0001f3ff"
- BLACK_LEFT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_6 = "\u261a\U0001f3ff"
- BLACK_RIGHT_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_6 = "\u261b\U0001f3ff"
- REVERSED_RAISED_HAND_WITH_FINGERS_SPLAYED_EMOJI_MODIFIER_FITZPATRICK_TYPE_6 = "\U0001f591\U0001f3ff"
- WHITE_DOWN_POINTING_INDEX_EMOJI_MODIFIER_FITZPATRICK_TYPE_6 = "\u261f\U0001f3ff"
- REVERSED_THUMBS_UP_SIGN_EMOJI_MODIFIER_FITZPATRICK_TYPE_6 = "\U0001f592\U0001f3ff"
- LEFT_WRITING_HAND_EMOJI_MODIFIER_FITZPATRICK_TYPE_6 = "\U0001f58e\U0001f3ff"
- REVERSED_VICTORY_HAND_EMOJI_MODIFIER_FITZPATRICK_TYPE_6 = "\U0001f594\U0001f3ff"
diff --git a/pyrogram/client/ext/file_data.py b/pyrogram/client/ext/file_data.py
deleted file mode 100644
index ea9de6e1ba..0000000000
--- a/pyrogram/client/ext/file_data.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Pyrogram - Telegram MTProto API Client Library for Python
-# Copyright (C) 2017-2020 Dan
-#
-# This file is part of Pyrogram.
-#
-# Pyrogram is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Pyrogram is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with Pyrogram. If not, see .
-
-class FileData:
- def __init__(
- self, *, media_type: int = None, dc_id: int = None, document_id: int = None, access_hash: int = None,
- thumb_size: str = None, peer_id: int = None, peer_type: str = None, peer_access_hash: int = None,
- volume_id: int = None, local_id: int = None, is_big: bool = None, file_size: int = None, mime_type: str = None,
- file_name: str = None, date: int = None, file_ref: str = None
- ):
- self.media_type = media_type
- self.dc_id = dc_id
- self.document_id = document_id
- self.access_hash = access_hash
- self.thumb_size = thumb_size
- self.peer_id = peer_id
- self.peer_type = peer_type
- self.peer_access_hash = peer_access_hash
- self.volume_id = volume_id
- self.local_id = local_id
- self.is_big = is_big
- self.file_size = file_size
- self.mime_type = mime_type
- self.file_name = file_name
- self.date = date
- self.file_ref = file_ref
diff --git a/pyrogram/client/ext/link.py b/pyrogram/client/ext/link.py
deleted file mode 100644
index bd2d82cf9a..0000000000
--- a/pyrogram/client/ext/link.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Pyrogram - Telegram MTProto API Client Library for Python
-# Copyright (C) 2017-2020 Dan
-#
-# This file is part of Pyrogram.
-#
-# Pyrogram is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Pyrogram is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with Pyrogram. If not, see .
-
-import html
-
-
-class Link(str):
- HTML = "{text}"
- MD = "[{text}]({url})"
-
- def __init__(self, url: str, text: str, style: str):
- super().__init__()
-
- self.url = url
- self.text = text
- self.style = style
-
- @staticmethod
- def format(url: str, text: str, style: str):
- if style in ["md", "markdown"]:
- fmt = Link.MD
- elif style in ["combined", "html", None]:
- fmt = Link.HTML
- else:
- raise ValueError("{} is not a valid style/parse mode".format(style))
-
- return fmt.format(url=url, text=html.escape(text))
-
- # noinspection PyArgumentList
- def __new__(cls, url, text, style):
- return str.__new__(cls, Link.format(url, text, style))
-
- def __call__(self, other: str = None, *, style: str = None):
- return Link.format(self.url, other or self.text, style or self.style)
-
- def __str__(self):
- return Link.format(self.url, self.text, self.style)
diff --git a/pyrogram/client/filters/__init__.py b/pyrogram/client/filters/__init__.py
deleted file mode 100644
index bdb72abc79..0000000000
--- a/pyrogram/client/filters/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Pyrogram - Telegram MTProto API Client Library for Python
-# Copyright (C) 2017-2020 Dan
-#
-# This file is part of Pyrogram.
-#
-# Pyrogram is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Pyrogram is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with Pyrogram. If not, see .
-
-from .filters import Filters
diff --git a/pyrogram/client/filters/filter.py b/pyrogram/client/filters/filter.py
deleted file mode 100644
index 67067e0370..0000000000
--- a/pyrogram/client/filters/filter.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# Pyrogram - Telegram MTProto API Client Library for Python
-# Copyright (C) 2017-2020 Dan
-#
-# This file is part of Pyrogram.
-#
-# Pyrogram is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Pyrogram is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with Pyrogram. If not, see .
-
-import asyncio
-
-
-class Filter:
- def __call__(self, message):
- raise NotImplementedError
-
- def __invert__(self):
- return InvertFilter(self)
-
- def __and__(self, other):
- return AndFilter(self, other)
-
- def __or__(self, other):
- return OrFilter(self, other)
-
-
-class InvertFilter(Filter):
- def __init__(self, base):
- self.base = base
-
- async def __call__(self, message):
- if asyncio.iscoroutinefunction(self.base.__call__):
- x = await self.base(message)
- else:
- x = self.base(message)
-
- return not x
-
-
-class AndFilter(Filter):
- def __init__(self, base, other):
- self.base = base
- self.other = other
-
- async def __call__(self, message):
- if asyncio.iscoroutinefunction(self.base.__call__):
- x = await self.base(message)
- else:
- x = self.base(message)
-
- if asyncio.iscoroutinefunction(self.other.__call__):
- y = await self.other(message)
- else:
- y = self.other(message)
-
- return x and y
-
-
-class OrFilter(Filter):
- def __init__(self, base, other):
- self.base = base
- self.other = other
-
- async def __call__(self, message):
- if asyncio.iscoroutinefunction(self.base.__call__):
- x = await self.base(message)
- else:
- x = self.base(message)
-
- if asyncio.iscoroutinefunction(self.other.__call__):
- y = await self.other(message)
- else:
- y = self.other(message)
-
- return x or y
diff --git a/pyrogram/client/filters/filters.py b/pyrogram/client/filters/filters.py
deleted file mode 100644
index 3a798874ea..0000000000
--- a/pyrogram/client/filters/filters.py
+++ /dev/null
@@ -1,404 +0,0 @@
-# Pyrogram - Telegram MTProto API Client Library for Python
-# Copyright (C) 2017-2020 Dan
-#
-# This file is part of Pyrogram.
-#
-# Pyrogram is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Pyrogram is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with Pyrogram. If not, see .
-
-import re
-from typing import Callable, Union
-
-from .filter import Filter
-from ..types import Message, CallbackQuery, InlineQuery
-from ..types.bots_and_keyboards import InlineKeyboardMarkup, ReplyKeyboardMarkup
-
-CUSTOM_FILTER_NAME = "CustomFilter"
-
-
-def create(func: Callable, name: str = None, **kwargs) -> Filter:
- """Easily create a custom filter.
-
- Custom filters give you extra control over which updates are allowed or not to be processed by your handlers.
-
- Parameters:
- func (``callable``):
- A function that accepts two positional arguments *(filter, update)* and returns a boolean: True if the
- update should be handled, False otherwise. The *filter* argument refers to the filter itself and can be used
- to access keyword arguments (read below). The *update* argument type will vary depending on which
- `Handler `_ is coming from. For example, in a :obj:`MessageHandler` the *update* argument will be
- a :obj:`Message`; in a :obj:`CallbackQueryHandler` the *update* will be a :obj:`CallbackQuery`. Your
- function body can then access the incoming update attributes and decide whether to allow it or not.
-
- name (``str``, *optional*):
- Your filter's name. Can be anything you like.
- Defaults to "CustomFilter".
-
- **kwargs (``any``, *optional*):
- Any keyword argument you would like to pass. Useful when creating parameterized custom filters, such as
- :meth:`~Filters.command` or :meth:`~Filters.regex`.
- """
- # TODO: unpack kwargs using **kwargs into the dict itself. For Python 3.5+ only
- d = {"__call__": func}
- d.update(kwargs)
-
- return type(name or CUSTOM_FILTER_NAME, (Filter,), d)()
-
-
-class Filters:
- """This class provides access to all library-defined Filters available in Pyrogram.
-
- The Filters listed here are currently intended to be used with the :obj:`MessageHandler` only.
- At the moment, if you want to filter updates coming from different `Handlers `_ you have to create
- your own filters with :meth:`~Filters.create` and use them in the same way.
- """
-
- create = create
-
- all = create(lambda _, m: True, "AllFilter")
- """Filter all messages."""
-
- me = create(lambda _, m: bool(m.from_user and m.from_user.is_self), "MeFilter")
- """Filter messages generated by you yourself."""
-
- bot = create(lambda _, m: bool(m.from_user and m.from_user.is_bot), "BotFilter")
- """Filter messages coming from bots."""
-
- incoming = create(lambda _, m: not m.outgoing, "IncomingFilter")
- """Filter incoming messages. Messages sent to your own chat (Saved Messages) are also recognised as incoming."""
-
- outgoing = create(lambda _, m: m.outgoing, "OutgoingFilter")
- """Filter outgoing messages. Messages sent to your own chat (Saved Messages) are not recognized as outgoing."""
-
- text = create(lambda _, m: bool(m.text), "TextFilter")
- """Filter text messages."""
-
- reply = create(lambda _, m: bool(m.reply_to_message), "ReplyFilter")
- """Filter messages that are replies to other messages."""
-
- forwarded = create(lambda _, m: bool(m.forward_date), "ForwardedFilter")
- """Filter messages that are forwarded."""
-
- caption = create(lambda _, m: bool(m.caption), "CaptionFilter")
- """Filter media messages that contain captions."""
-
- edited = create(lambda _, m: bool(m.edit_date), "EditedFilter")
- """Filter edited messages."""
-
- audio = create(lambda _, m: bool(m.audio), "AudioFilter")
- """Filter messages that contain :obj:`Audio` objects."""
-
- document = create(lambda _, m: bool(m.document), "DocumentFilter")
- """Filter messages that contain :obj:`Document` objects."""
-
- photo = create(lambda _, m: bool(m.photo), "PhotoFilter")
- """Filter messages that contain :obj:`Photo` objects."""
-
- sticker = create(lambda _, m: bool(m.sticker), "StickerFilter")
- """Filter messages that contain :obj:`Sticker` objects."""
-
- animation = create(lambda _, m: bool(m.animation), "AnimationFilter")
- """Filter messages that contain :obj:`Animation` objects."""
-
- game = create(lambda _, m: bool(m.game), "GameFilter")
- """Filter messages that contain :obj:`Game` objects."""
-
- video = create(lambda _, m: bool(m.video), "VideoFilter")
- """Filter messages that contain :obj:`Video` objects."""
-
- media_group = create(lambda _, m: bool(m.media_group_id), "MediaGroupFilter")
- """Filter messages containing photos or videos being part of an album."""
-
- voice = create(lambda _, m: bool(m.voice), "VoiceFilter")
- """Filter messages that contain :obj:`Voice` note objects."""
-
- video_note = create(lambda _, m: bool(m.video_note), "VideoNoteFilter")
- """Filter messages that contain :obj:`VideoNote` objects."""
-
- contact = create(lambda _, m: bool(m.contact), "ContactFilter")
- """Filter messages that contain :obj:`Contact` objects."""
-
- location = create(lambda _, m: bool(m.location), "LocationFilter")
- """Filter messages that contain :obj:`Location` objects."""
-
- venue = create(lambda _, m: bool(m.venue), "VenueFilter")
- """Filter messages that contain :obj:`Venue` objects."""
-
- web_page = create(lambda _, m: m.web_page, "WebPageFilter")
- """Filter messages sent with a webpage preview."""
-
- poll = create(lambda _, m: m.poll, "PollFilter")
- """Filter messages that contain :obj:`Poll` objects."""
-
- private = create(lambda _, m: bool(m.chat and m.chat.type in {"private", "bot"}), "PrivateFilter")
- """Filter messages sent in private chats."""
-
- group = create(lambda _, m: bool(m.chat and m.chat.type in {"group", "supergroup"}), "GroupFilter")
- """Filter messages sent in group or supergroup chats."""
-
- channel = create(lambda _, m: bool(m.chat and m.chat.type == "channel"), "ChannelFilter")
- """Filter messages sent in channels."""
-
- new_chat_members = create(lambda _, m: bool(m.new_chat_members), "NewChatMembersFilter")
- """Filter service messages for new chat members."""
-
- left_chat_member = create(lambda _, m: bool(m.left_chat_member), "LeftChatMemberFilter")
- """Filter service messages for members that left the chat."""
-
- new_chat_title = create(lambda _, m: bool(m.new_chat_title), "NewChatTitleFilter")
- """Filter service messages for new chat titles."""
-
- new_chat_photo = create(lambda _, m: bool(m.new_chat_photo), "NewChatPhotoFilter")
- """Filter service messages for new chat photos."""
-
- delete_chat_photo = create(lambda _, m: bool(m.delete_chat_photo), "DeleteChatPhotoFilter")
- """Filter service messages for deleted photos."""
-
- group_chat_created = create(lambda _, m: bool(m.group_chat_created), "GroupChatCreatedFilter")
- """Filter service messages for group chat creations."""
-
- supergroup_chat_created = create(lambda _, m: bool(m.supergroup_chat_created), "SupergroupChatCreatedFilter")
- """Filter service messages for supergroup chat creations."""
-
- channel_chat_created = create(lambda _, m: bool(m.channel_chat_created), "ChannelChatCreatedFilter")
- """Filter service messages for channel chat creations."""
-
- migrate_to_chat_id = create(lambda _, m: bool(m.migrate_to_chat_id), "MigrateToChatIdFilter")
- """Filter service messages that contain migrate_to_chat_id."""
-
- migrate_from_chat_id = create(lambda _, m: bool(m.migrate_from_chat_id), "MigrateFromChatIdFilter")
- """Filter service messages that contain migrate_from_chat_id."""
-
- pinned_message = create(lambda _, m: bool(m.pinned_message), "PinnedMessageFilter")
- """Filter service messages for pinned messages."""
-
- game_high_score = create(lambda _, m: bool(m.game_high_score), "GameHighScoreFilter")
- """Filter service messages for game high scores."""
-
- reply_keyboard = create(lambda _, m: isinstance(m.reply_markup, ReplyKeyboardMarkup), "ReplyKeyboardFilter")
- """Filter messages containing reply keyboard markups"""
-
- inline_keyboard = create(lambda _, m: isinstance(m.reply_markup, InlineKeyboardMarkup), "InlineKeyboardFilter")
- """Filter messages containing inline keyboard markups"""
-
- mentioned = create(lambda _, m: bool(m.mentioned), "MentionedFilter")
- """Filter messages containing mentions"""
-
- via_bot = create(lambda _, m: bool(m.via_bot), "ViaBotFilter")
- """Filter messages sent via inline bots"""
-
- service = create(lambda _, m: bool(m.service), "ServiceFilter")
- """Filter service messages.
-
- A service message contains any of the following fields set: *left_chat_member*,
- *new_chat_title*, *new_chat_photo*, *delete_chat_photo*, *group_chat_created*, *supergroup_chat_created*,
- *channel_chat_created*, *migrate_to_chat_id*, *migrate_from_chat_id*, *pinned_message*, *game_score*.
- """
-
- media = create(lambda _, m: bool(m.media), "MediaFilter")
- """Filter media messages.
-
- A media message contains any of the following fields set: *audio*, *document*, *photo*, *sticker*, *video*,
- *animation*, *voice*, *video_note*, *contact*, *location*, *venue*, *poll*.
- """
-
- scheduled = create(lambda _, m: bool(m.scheduled), "ScheduledFilter")
- """Filter messages that have been scheduled (not yet sent)."""
-
- from_scheduled = create(lambda _, m: bool(m.from_scheduled), "FromScheduledFilter")
- """Filter new automatically sent messages that were previously scheduled."""
-
- # Messages from linked channels are forwarded automatically by Telegram and have no sender (from_user is None).
- linked_channel = create(lambda _, m: bool(m.forward_from_chat and not m.from_user), "LinkedChannelFilter")
- """Filter messages that are automatically forwarded from the linked channel to the group chat."""
-
- @staticmethod
- def command(
- commands: str or list,
- prefixes: str or list = "/",
- case_sensitive: bool = False
- ):
- """Filter commands, i.e.: text messages starting with "/" or any other custom prefix.
-
- Parameters:
- commands (``str`` | ``list``):
- The command or list of commands as string the filter should look for.
- Examples: "start", ["start", "help", "settings"]. When a message text containing
- a command arrives, the command itself and its arguments will be stored in the *command*
- field of the :obj:`Message`.
-
- prefixes (``str`` | ``list``, *optional*):
- A prefix or a list of prefixes as string the filter should look for.
- Defaults to "/" (slash). Examples: ".", "!", ["/", "!", "."], list(".:!").
- Pass None or "" (empty string) to allow commands with no prefix at all.
-
- case_sensitive (``bool``, *optional*):
- Pass True if you want your command(s) to be case sensitive. Defaults to False.
- Examples: when True, command="Start" would trigger /Start but not /start.
- """
- command_re = re.compile(r"([\"'])(.*?)(?`_ are
- stored in the ``matches`` field of the update object itself.
-
- Parameters:
- pattern (``str`` | ``Pattern``):
- The regex pattern as string or as pre-compiled pattern.
-
- flags (``int``, *optional*):
- Regex flags.
- """
-
- def func(flt, update):
- if isinstance(update, Message):
- value = update.text or update.caption
- elif isinstance(update, CallbackQuery):
- value = update.data
- elif isinstance(update, InlineQuery):
- value = update.query
- else:
- raise ValueError("Regex filter doesn't work with {}".format(type(update)))
-
- if value:
- update.matches = list(flt.p.finditer(value)) or None
-
- return bool(update.matches)
-
- return create(
- func,
- "RegexFilter",
- p=pattern if isinstance(pattern, re.Pattern) else re.compile(pattern, flags)
- )
-
- # noinspection PyPep8Naming
- class user(Filter, set):
- """Filter messages coming from one or more users.
-
- You can use `set bound methods `_ to manipulate the
- users container.
-
- Parameters:
- users (``int`` | ``str`` | ``list``):
- Pass one or more user ids/usernames to filter users.
- For you yourself, "me" or "self" can be used as well.
- Defaults to None (no users).
- """
-
- def __init__(self, users: int or str or list = None):
- users = [] if users is None else users if isinstance(users, list) else [users]
-
- super().__init__(
- "me" if u in ["me", "self"]
- else u.lower().strip("@") if isinstance(u, str)
- else u for u in users
- )
-
- def __call__(self, message):
- return (message.from_user
- and (message.from_user.id in self
- or (message.from_user.username
- and message.from_user.username.lower() in self)
- or ("me" in self
- and message.from_user.is_self)))
-
- # noinspection PyPep8Naming
- class chat(Filter, set):
- """Filter messages coming from one or more chats.
-
- You can use `set bound methods `_ to manipulate the
- chats container.
-
- Parameters:
- chats (``int`` | ``str`` | ``list``):
- Pass one or more chat ids/usernames to filter chats.
- For your personal cloud (Saved Messages) you can simply use "me" or "self".
- Defaults to None (no chats).
- """
-
- def __init__(self, chats: int or str or list = None):
- chats = [] if chats is None else chats if isinstance(chats, list) else [chats]
-
- super().__init__(
- "me" if c in ["me", "self"]
- else c.lower().strip("@") if isinstance(c, str)
- else c for c in chats
- )
-
- def __call__(self, message):
- return (message.chat
- and (message.chat.id in self
- or (message.chat.username
- and message.chat.username.lower() in self)
- or ("me" in self
- and message.from_user
- and message.from_user.is_self
- and not message.outgoing)))
-
- dan = create(lambda _, m: bool(m.from_user and m.from_user.id == 23122162), "DanFilter")
diff --git a/pyrogram/client/methods/password/utils.py b/pyrogram/client/methods/password/utils.py
deleted file mode 100644
index 30c3679684..0000000000
--- a/pyrogram/client/methods/password/utils.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# Pyrogram - Telegram MTProto API Client Library for Python
-# Copyright (C) 2017-2020 Dan
-#
-# This file is part of Pyrogram.
-#
-# Pyrogram is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Pyrogram is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with Pyrogram. If not, see .
-
-import hashlib
-import os
-
-from pyrogram.api import types
-
-
-def btoi(b: bytes) -> int:
- return int.from_bytes(b, "big")
-
-
-def itob(i: int) -> bytes:
- return i.to_bytes(256, "big")
-
-
-def sha256(data: bytes) -> bytes:
- return hashlib.sha256(data).digest()
-
-
-def xor(a: bytes, b: bytes) -> bytes:
- return bytes(i ^ j for i, j in zip(a, b))
-
-
-def compute_hash(algo: types.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow, password: str) -> bytes:
- hash1 = sha256(algo.salt1 + password.encode() + algo.salt1)
- hash2 = sha256(algo.salt2 + hash1 + algo.salt2)
- hash3 = hashlib.pbkdf2_hmac("sha512", hash2, algo.salt1, 100000)
-
- return sha256(algo.salt2 + hash3 + algo.salt2)
-
-
-# noinspection PyPep8Naming
-def compute_check(r: types.account.Password, password: str) -> types.InputCheckPasswordSRP:
- algo = r.current_algo
-
- p_bytes = algo.p
- p = btoi(algo.p)
-
- g_bytes = itob(algo.g)
- g = algo.g
-
- B_bytes = r.srp_B
- B = btoi(B_bytes)
-
- srp_id = r.srp_id
-
- x_bytes = compute_hash(algo, password)
- x = btoi(x_bytes)
-
- g_x = pow(g, x, p)
-
- k_bytes = sha256(p_bytes + g_bytes)
- k = btoi(k_bytes)
-
- kg_x = (k * g_x) % p
-
- while True:
- a_bytes = os.urandom(256)
- a = btoi(a_bytes)
-
- A = pow(g, a, p)
- A_bytes = itob(A)
-
- u = btoi(sha256(A_bytes + B_bytes))
-
- if u > 0:
- break
-
- g_b = (B - kg_x) % p
-
- ux = u * x
- a_ux = a + ux
- S = pow(g_b, a_ux, p)
- S_bytes = itob(S)
-
- K_bytes = sha256(S_bytes)
-
- M1_bytes = sha256(
- xor(sha256(p_bytes), sha256(g_bytes))
- + sha256(algo.salt1)
- + sha256(algo.salt2)
- + A_bytes
- + B_bytes
- + K_bytes
- )
-
- return types.InputCheckPasswordSRP(srp_id=srp_id, A=A_bytes, M1=M1_bytes)
diff --git a/pyrogram/client/types/inline_mode/inline_query_result.py b/pyrogram/client/types/inline_mode/inline_query_result.py
deleted file mode 100644
index 6525585bf4..0000000000
--- a/pyrogram/client/types/inline_mode/inline_query_result.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# Pyrogram - Telegram MTProto API Client Library for Python
-# Copyright (C) 2017-2020 Dan
-#
-# This file is part of Pyrogram.
-#
-# Pyrogram is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Pyrogram is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with Pyrogram. If not, see .
-
-from uuid import uuid4
-
-from ..bots_and_keyboards import InlineKeyboardMarkup
-from ..input_message_content import InputMessageContent
-from ..object import Object
-
-"""- :obj:`InlineQueryResultCachedAudio`
- - :obj:`InlineQueryResultCachedDocument`
- - :obj:`InlineQueryResultCachedGif`
- - :obj:`InlineQueryResultCachedMpeg4Gif`
- - :obj:`InlineQueryResultCachedPhoto`
- - :obj:`InlineQueryResultCachedSticker`
- - :obj:`InlineQueryResultCachedVideo`
- - :obj:`InlineQueryResultCachedVoice`
- - :obj:`InlineQueryResultAudio`
- - :obj:`InlineQueryResultContact`
- - :obj:`InlineQueryResultGame`
- - :obj:`InlineQueryResultDocument`
- - :obj:`InlineQueryResultGif`
- - :obj:`InlineQueryResultLocation`
- - :obj:`InlineQueryResultMpeg4Gif`
- - :obj:`InlineQueryResultPhoto`
- - :obj:`InlineQueryResultVenue`
- - :obj:`InlineQueryResultVideo`
- - :obj:`InlineQueryResultVoice`"""
-
-
-class InlineQueryResult(Object):
- """One result of an inline query.
-
- Pyrogram currently supports results of the following types:
-
- - :obj:`InlineQueryResultArticle`
- - :obj:`InlineQueryResultPhoto`
- - :obj:`InlineQueryResultAnimation`
- """
-
- def __init__(
- self,
- type: str,
- id: str,
- input_message_content: InputMessageContent,
- reply_markup: InlineKeyboardMarkup
- ):
- super().__init__()
-
- self.type = type
- self.id = str(uuid4()) if id is None else str(id)
- self.input_message_content = input_message_content
- self.reply_markup = reply_markup
-
- async def write(self):
- pass
diff --git a/pyrogram/connection/transport/tcp/tcp.py b/pyrogram/connection/transport/tcp/tcp.py
index 070907f469..b2ff539184 100644
--- a/pyrogram/connection/transport/tcp/tcp.py
+++ b/pyrogram/connection/transport/tcp/tcp.py
@@ -68,7 +68,7 @@ def __init__(self, ipv6: bool, proxy: dict):
password=proxy.get("password", None)
)
- log.info("Using proxy {}:{}".format(hostname, port))
+ log.info(f"Using proxy {hostname}:{port}")
else:
self.socket = socks.socksocket(
socket.AF_INET6 if ipv6
diff --git a/pyrogram/connection/transport/tcp/tcp_abridged_o.py b/pyrogram/connection/transport/tcp/tcp_abridged_o.py
index e8f8fba0d9..c7b241593f 100644
--- a/pyrogram/connection/transport/tcp/tcp_abridged_o.py
+++ b/pyrogram/connection/transport/tcp/tcp_abridged_o.py
@@ -19,8 +19,8 @@
import logging
import os
+from pyrogram.crypto import aes
from .tcp import TCP
-from ....crypto.aes import AES
log = logging.getLogger(__name__)
@@ -49,7 +49,7 @@ async def connect(self, address: tuple):
self.encrypt = (nonce[8:40], nonce[40:56], bytearray(1))
self.decrypt = (temp[0:32], temp[32:48], bytearray(1))
- nonce[56:64] = AES.ctr256_encrypt(nonce, *self.encrypt)[56:64]
+ nonce[56:64] = aes.ctr256_encrypt(nonce, *self.encrypt)[56:64]
await super().send(nonce)
@@ -57,7 +57,7 @@ async def send(self, data: bytes, *args):
length = len(data) // 4
await super().send(
- AES.ctr256_encrypt(
+ aes.ctr256_encrypt(
(bytes([length])
if length <= 126
else b"\x7f" + length.to_bytes(3, "little"))
@@ -72,7 +72,7 @@ async def recv(self, length: int = 0) -> bytes or None:
if length is None:
return None
- length = AES.ctr256_decrypt(length, *self.decrypt)
+ length = aes.ctr256_decrypt(length, *self.decrypt)
if length == b"\x7f":
length = await super().recv(3)
@@ -80,11 +80,11 @@ async def recv(self, length: int = 0) -> bytes or None:
if length is None:
return None
- length = AES.ctr256_decrypt(length, *self.decrypt)
+ length = aes.ctr256_decrypt(length, *self.decrypt)
data = await super().recv(int.from_bytes(length, "little") * 4)
if data is None:
return None
- return AES.ctr256_decrypt(data, *self.decrypt)
+ return aes.ctr256_decrypt(data, *self.decrypt)
diff --git a/pyrogram/connection/transport/tcp/tcp_intermediate_o.py b/pyrogram/connection/transport/tcp/tcp_intermediate_o.py
index 4b4f4610af..c0c1d915b8 100644
--- a/pyrogram/connection/transport/tcp/tcp_intermediate_o.py
+++ b/pyrogram/connection/transport/tcp/tcp_intermediate_o.py
@@ -20,8 +20,8 @@
import os
from struct import pack, unpack
+from pyrogram.crypto import aes
from .tcp import TCP
-from ....crypto.aes import AES
log = logging.getLogger(__name__)
@@ -50,13 +50,13 @@ async def connect(self, address: tuple):
self.encrypt = (nonce[8:40], nonce[40:56], bytearray(1))
self.decrypt = (temp[0:32], temp[32:48], bytearray(1))
- nonce[56:64] = AES.ctr256_encrypt(nonce, *self.encrypt)[56:64]
+ nonce[56:64] = aes.ctr256_encrypt(nonce, *self.encrypt)[56:64]
await super().send(nonce)
async def send(self, data: bytes, *args):
await super().send(
- AES.ctr256_encrypt(
+ aes.ctr256_encrypt(
pack(" bytes or None:
if length is None:
return None
- length = AES.ctr256_decrypt(length, *self.decrypt)
+ length = aes.ctr256_decrypt(length, *self.decrypt)
data = await super().recv(unpack(".
-
-from .aes import AES
-from .kdf import KDF
-from .mtproto import MTProto
-from .prime import Prime
-from .rsa import RSA
diff --git a/pyrogram/crypto/aes.py b/pyrogram/crypto/aes.py
index 47c9c0949c..c094fd2214 100644
--- a/pyrogram/crypto/aes.py
+++ b/pyrogram/crypto/aes.py
@@ -26,30 +26,28 @@
log.info("Using TgCrypto")
- class AES:
- @classmethod
- def ige256_encrypt(cls, data: bytes, key: bytes, iv: bytes) -> bytes:
- return tgcrypto.ige256_encrypt(data, key, iv)
-
- @classmethod
- def ige256_decrypt(cls, data: bytes, key: bytes, iv: bytes) -> bytes:
- return tgcrypto.ige256_decrypt(data, key, iv)
-
- @staticmethod
- def ctr256_encrypt(data: bytes, key: bytes, iv: bytearray, state: bytearray = None) -> bytes:
- return tgcrypto.ctr256_encrypt(data, key, iv, state or bytearray(1))
-
- @staticmethod
- def ctr256_decrypt(data: bytes, key: bytes, iv: bytearray, state: bytearray = None) -> bytes:
- return tgcrypto.ctr256_decrypt(data, key, iv, state or bytearray(1))
-
- @staticmethod
- def xor(a: bytes, b: bytes) -> bytes:
- return int.to_bytes(
- int.from_bytes(a, "big") ^ int.from_bytes(b, "big"),
- len(a),
- "big",
- )
+ def ige256_encrypt(data: bytes, key: bytes, iv: bytes) -> bytes:
+ return tgcrypto.ige256_encrypt(data, key, iv)
+
+
+ def ige256_decrypt(data: bytes, key: bytes, iv: bytes) -> bytes:
+ return tgcrypto.ige256_decrypt(data, key, iv)
+
+
+ def ctr256_encrypt(data: bytes, key: bytes, iv: bytearray, state: bytearray = None) -> bytes:
+ return tgcrypto.ctr256_encrypt(data, key, iv, state or bytearray(1))
+
+
+ def ctr256_decrypt(data: bytes, key: bytes, iv: bytearray, state: bytearray = None) -> bytes:
+ return tgcrypto.ctr256_decrypt(data, key, iv, state or bytearray(1))
+
+
+ def xor(a: bytes, b: bytes) -> bytes:
+ return int.to_bytes(
+ int.from_bytes(a, "big") ^ int.from_bytes(b, "big"),
+ len(a),
+ "big",
+ )
except ImportError:
import pyaes
@@ -60,75 +58,73 @@ def xor(a: bytes, b: bytes) -> bytes:
)
- class AES:
- @classmethod
- def ige256_encrypt(cls, data: bytes, key: bytes, iv: bytes) -> bytes:
- return cls.ige(data, key, iv, True)
+ def ige256_encrypt(data: bytes, key: bytes, iv: bytes) -> bytes:
+ return ige(data, key, iv, True)
+
+
+ def ige256_decrypt(data: bytes, key: bytes, iv: bytes) -> bytes:
+ return ige(data, key, iv, False)
+
+
+ def ctr256_encrypt(data: bytes, key: bytes, iv: bytearray, state: bytearray = None) -> bytes:
+ return ctr(data, key, iv, state or bytearray(1))
+
+
+ def ctr256_decrypt(data: bytes, key: bytes, iv: bytearray, state: bytearray = None) -> bytes:
+ return ctr(data, key, iv, state or bytearray(1))
- @classmethod
- def ige256_decrypt(cls, data: bytes, key: bytes, iv: bytes) -> bytes:
- return cls.ige(data, key, iv, False)
- @classmethod
- def ctr256_encrypt(cls, data: bytes, key: bytes, iv: bytearray, state: bytearray = None) -> bytes:
- return cls.ctr(data, key, iv, state or bytearray(1))
+ def xor(a: bytes, b: bytes) -> bytes:
+ return int.to_bytes(
+ int.from_bytes(a, "big") ^ int.from_bytes(b, "big"),
+ len(a),
+ "big",
+ )
- @classmethod
- def ctr256_decrypt(cls, data: bytes, key: bytes, iv: bytearray, state: bytearray = None) -> bytes:
- return cls.ctr(data, key, iv, state or bytearray(1))
- @staticmethod
- def xor(a: bytes, b: bytes) -> bytes:
- return int.to_bytes(
- int.from_bytes(a, "big") ^ int.from_bytes(b, "big"),
- len(a),
- "big",
- )
+ def ige(data: bytes, key: bytes, iv: bytes, encrypt: bool) -> bytes:
+ cipher = pyaes.AES(key)
- @classmethod
- def ige(cls, data: bytes, key: bytes, iv: bytes, encrypt: bool) -> bytes:
- cipher = pyaes.AES(key)
+ iv_1 = iv[:16]
+ iv_2 = iv[16:]
- iv_1 = iv[:16]
- iv_2 = iv[16:]
+ data = [data[i: i + 16] for i in range(0, len(data), 16)]
- data = [data[i: i + 16] for i in range(0, len(data), 16)]
+ if encrypt:
+ for i, chunk in enumerate(data):
+ iv_1 = data[i] = xor(cipher.encrypt(xor(chunk, iv_1)), iv_2)
+ iv_2 = chunk
+ else:
+ for i, chunk in enumerate(data):
+ iv_2 = data[i] = xor(cipher.decrypt(xor(chunk, iv_2)), iv_1)
+ iv_1 = chunk
- if encrypt:
- for i, chunk in enumerate(data):
- iv_1 = data[i] = cls.xor(cipher.encrypt(cls.xor(chunk, iv_1)), iv_2)
- iv_2 = chunk
- else:
- for i, chunk in enumerate(data):
- iv_2 = data[i] = cls.xor(cipher.decrypt(cls.xor(chunk, iv_2)), iv_1)
- iv_1 = chunk
+ return b"".join(data)
- return b"".join(data)
- @classmethod
- def ctr(cls, data: bytes, key: bytes, iv: bytearray, state: bytearray) -> bytes:
- cipher = pyaes.AES(key)
+ def ctr(data: bytes, key: bytes, iv: bytearray, state: bytearray) -> bytes:
+ cipher = pyaes.AES(key)
- out = bytearray(data)
- chunk = cipher.encrypt(iv)
+ out = bytearray(data)
+ chunk = cipher.encrypt(iv)
- for i in range(0, len(data), 16):
- for j in range(0, min(len(data) - i, 16)):
- out[i + j] ^= chunk[state[0]]
+ for i in range(0, len(data), 16):
+ for j in range(0, min(len(data) - i, 16)):
+ out[i + j] ^= chunk[state[0]]
- state[0] += 1
+ state[0] += 1
- if state[0] >= 16:
- state[0] = 0
+ if state[0] >= 16:
+ state[0] = 0
- if state[0] == 0:
- for k in range(15, -1, -1):
- try:
- iv[k] += 1
- break
- except ValueError:
- iv[k] = 0
+ if state[0] == 0:
+ for k in range(15, -1, -1):
+ try:
+ iv[k] += 1
+ break
+ except ValueError:
+ iv[k] = 0
- chunk = cipher.encrypt(iv)
+ chunk = cipher.encrypt(iv)
- return out
+ return out
diff --git a/pyrogram/crypto/mtproto.py b/pyrogram/crypto/mtproto.py
index 539976d66e..b67b49f128 100644
--- a/pyrogram/crypto/mtproto.py
+++ b/pyrogram/crypto/mtproto.py
@@ -20,43 +20,54 @@
from io import BytesIO
from os import urandom
-from pyrogram.api.core import Message, Long
-from . import AES, KDF
+from pyrogram.raw.core import Message, Long
+from . import aes
-class MTProto:
- @staticmethod
- def pack(message: Message, salt: int, session_id: bytes, auth_key: bytes, auth_key_id: bytes) -> bytes:
- data = Long(salt) + session_id + message.write()
- padding = urandom(-(len(data) + 12) % 16 + 12)
+def kdf(auth_key: bytes, msg_key: bytes, outgoing: bool) -> tuple:
+ # https://core.telegram.org/mtproto/description#defining-aes-key-and-initialization-vector
+ x = 0 if outgoing else 8
- # 88 = 88 + 0 (outgoing message)
- msg_key_large = sha256(auth_key[88: 88 + 32] + data + padding).digest()
- msg_key = msg_key_large[8:24]
- aes_key, aes_iv = KDF(auth_key, msg_key, True)
+ sha256_a = sha256(msg_key + auth_key[x: x + 36]).digest()
+ sha256_b = sha256(auth_key[x + 40:x + 76] + msg_key).digest() # 76 = 40 + 36
- return auth_key_id + msg_key + AES.ige256_encrypt(data + padding, aes_key, aes_iv)
+ aes_key = sha256_a[:8] + sha256_b[8:24] + sha256_a[24:32]
+ aes_iv = sha256_b[:8] + sha256_a[8:24] + sha256_b[24:32]
- @staticmethod
- def unpack(b: BytesIO, session_id: bytes, auth_key: bytes, auth_key_id: bytes) -> Message:
- assert b.read(8) == auth_key_id, b.getvalue()
+ return aes_key, aes_iv
- msg_key = b.read(16)
- aes_key, aes_iv = KDF(auth_key, msg_key, False)
- data = BytesIO(AES.ige256_decrypt(b.read(), aes_key, aes_iv))
- data.read(8)
- # https://core.telegram.org/mtproto/security_guidelines#checking-session-id
- assert data.read(8) == session_id
+def pack(message: Message, salt: int, session_id: bytes, auth_key: bytes, auth_key_id: bytes) -> bytes:
+ data = Long(salt) + session_id + message.write()
+ padding = urandom(-(len(data) + 12) % 16 + 12)
- message = Message.read(data)
+ # 88 = 88 + 0 (outgoing message)
+ msg_key_large = sha256(auth_key[88: 88 + 32] + data + padding).digest()
+ msg_key = msg_key_large[8:24]
+ aes_key, aes_iv = kdf(auth_key, msg_key, True)
- # https://core.telegram.org/mtproto/security_guidelines#checking-sha256-hash-value-of-msg-key
- # https://core.telegram.org/mtproto/security_guidelines#checking-message-length
- # 96 = 88 + 8 (incoming message)
- assert msg_key == sha256(auth_key[96:96 + 32] + data.getvalue()).digest()[8:24]
+ return auth_key_id + msg_key + aes.ige256_encrypt(data + padding, aes_key, aes_iv)
- # https://core.telegram.org/mtproto/security_guidelines#checking-msg-id
- assert message.msg_id % 2 != 0
- return message
+def unpack(b: BytesIO, session_id: bytes, auth_key: bytes, auth_key_id: bytes) -> Message:
+ assert b.read(8) == auth_key_id, b.getvalue()
+
+ msg_key = b.read(16)
+ aes_key, aes_iv = kdf(auth_key, msg_key, False)
+ data = BytesIO(aes.ige256_decrypt(b.read(), aes_key, aes_iv))
+ data.read(8)
+
+ # https://core.telegram.org/mtproto/security_guidelines#checking-session-id
+ assert data.read(8) == session_id
+
+ message = Message.read(data)
+
+ # https://core.telegram.org/mtproto/security_guidelines#checking-sha256-hash-value-of-msg-key
+ # https://core.telegram.org/mtproto/security_guidelines#checking-message-length
+ # 96 = 88 + 8 (incoming message)
+ assert msg_key == sha256(auth_key[96:96 + 32] + data.getvalue()).digest()[8:24]
+
+ # https://core.telegram.org/mtproto/security_guidelines#checking-msg-id
+ assert message.msg_id % 2 != 0
+
+ return message
diff --git a/pyrogram/crypto/prime.py b/pyrogram/crypto/prime.py
index 0ca59ea75d..22210726af 100644
--- a/pyrogram/crypto/prime.py
+++ b/pyrogram/crypto/prime.py
@@ -18,68 +18,65 @@
from random import randint
+CURRENT_DH_PRIME = int(
+ "C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F"
+ "48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C37"
+ "20FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F64"
+ "2477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4"
+ "A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754"
+ "FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4"
+ "E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F"
+ "0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5B",
+ 16
+)
+
+
+# Recursive variant
+# def gcd(cls, a: int, b: int) -> int:
+# return cls.gcd(b, a % b) if b else a
+
+def gcd(a: int, b: int) -> int:
+ while b:
+ a, b = b, a % b
+
+ return a
-class Prime:
- CURRENT_DH_PRIME = int(
- "C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F"
- "48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C37"
- "20FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F64"
- "2477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4"
- "A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754"
- "FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4"
- "E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F"
- "0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5B",
- 16
- )
-
- # Recursive variant
- # @classmethod
- # def gcd(cls, a: int, b: int) -> int:
- # return cls.gcd(b, a % b) if b else a
-
- @staticmethod
- def gcd(a: int, b: int) -> int:
- while b:
- a, b = b, a % b
-
- return a
-
- @classmethod
- def decompose(cls, pq: int) -> int:
- # https://comeoncodeon.wordpress.com/2010/09/18/pollard-rho-brent-integer-factorization/
- if pq % 2 == 0:
- return 2
-
- y, c, m = randint(1, pq - 1), randint(1, pq - 1), randint(1, pq - 1)
- g = r = q = 1
- x = ys = 0
-
- while g == 1:
- x = y
-
- for i in range(r):
- y = (pow(y, 2, pq) + c) % pq
- k = 0
+def decompose(pq: int) -> int:
+ # https://comeoncodeon.wordpress.com/2010/09/18/pollard-rho-brent-integer-factorization/
+ if pq % 2 == 0:
+ return 2
- while k < r and g == 1:
- ys = y
+ y, c, m = randint(1, pq - 1), randint(1, pq - 1), randint(1, pq - 1)
+ g = r = q = 1
+ x = ys = 0
- for i in range(min(m, r - k)):
- y = (pow(y, 2, pq) + c) % pq
- q = q * (abs(x - y)) % pq
+ while g == 1:
+ x = y
+
+ for i in range(r):
+ y = (pow(y, 2, pq) + c) % pq
+
+ k = 0
+
+ while k < r and g == 1:
+ ys = y
+
+ for i in range(min(m, r - k)):
+ y = (pow(y, 2, pq) + c) % pq
+ q = q * (abs(x - y)) % pq
- g = cls.gcd(q, pq)
- k += m
+ g = gcd(q, pq)
+ k += m
- r *= 2
+ r *= 2
- if g == pq:
- while True:
- ys = (pow(ys, 2, pq) + c) % pq
- g = cls.gcd(abs(x - ys), pq)
+ if g == pq:
+ while True:
+ ys = (pow(ys, 2, pq) + c) % pq
+ g = gcd(abs(x - ys), pq)
- if g > 1:
- break
+ if g > 1:
+ break
- return g
+ return g
diff --git a/pyrogram/crypto/rsa.py b/pyrogram/crypto/rsa.py
index 268a91e476..aaec8df6ca 100644
--- a/pyrogram/crypto/rsa.py
+++ b/pyrogram/crypto/rsa.py
@@ -20,194 +20,192 @@
PublicKey = namedtuple("PublicKey", ["m", "e"])
+# To get modulus and exponent:
+#
+# [RSA PUBLIC KEY]:
+# grep -v -- - public.key | tr -d \\n | base64 -d | openssl asn1parse -inform DER -i
+#
+# [PUBLIC KEY]:
+# openssl rsa -pubin -in key -text -noout
-class RSA:
- # To get modulus and exponent:
- #
- # [RSA PUBLIC KEY]:
- # grep -v -- - public.key | tr -d \\n | base64 -d | openssl asn1parse -inform DER -i
- #
- # [PUBLIC KEY]:
- # openssl rsa -pubin -in key -text -noout
+server_public_keys = {
+ # -4344800451088585951
+ 0xc3b42b026ce86b21 - (1 << 64): PublicKey( # Telegram servers #1
+ # -----BEGIN RSA PUBLIC KEY-----
+ # MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
+ # lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
+ # an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw
+ # Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+
+ # 8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n
+ # Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
+ # -----END RSA PUBLIC KEY-----
+ int(
+ "C150023E2F70DB7985DED064759CFECF0AF328E69A41DAF4D6F01B538135A6F9"
+ "1F8F8B2A0EC9BA9720CE352EFCF6C5680FFC424BD634864902DE0B4BD6D49F4E"
+ "580230E3AE97D95C8B19442B3C0A10D8F5633FECEDD6926A7F6DAB0DDB7D457F"
+ "9EA81B8465FCD6FFFEED114011DF91C059CAEDAF97625F6C96ECC74725556934"
+ "EF781D866B34F011FCE4D835A090196E9A5F0E4449AF7EB697DDB9076494CA5F"
+ "81104A305B6DD27665722C46B60E5DF680FB16B210607EF217652E60236C255F"
+ "6A28315F4083A96791D7214BF64C1DF4FD0DB1944FB26A2A57031B32EEE64AD1"
+ "5A8BA68885CDE74A5BFC920F6ABF59BA5C75506373E7130F9042DA922179251F",
+ 16
+ ), # Modulus
+ int("010001", 16) # Exponent
+ ),
- server_public_keys = {
- # -4344800451088585951
- 0xc3b42b026ce86b21 - (1 << 64): PublicKey( # Telegram servers #1
- # -----BEGIN RSA PUBLIC KEY-----
- # MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
- # lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
- # an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw
- # Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+
- # 8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n
- # Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
- # -----END RSA PUBLIC KEY-----
- int(
- "C150023E2F70DB7985DED064759CFECF0AF328E69A41DAF4D6F01B538135A6F9"
- "1F8F8B2A0EC9BA9720CE352EFCF6C5680FFC424BD634864902DE0B4BD6D49F4E"
- "580230E3AE97D95C8B19442B3C0A10D8F5633FECEDD6926A7F6DAB0DDB7D457F"
- "9EA81B8465FCD6FFFEED114011DF91C059CAEDAF97625F6C96ECC74725556934"
- "EF781D866B34F011FCE4D835A090196E9A5F0E4449AF7EB697DDB9076494CA5F"
- "81104A305B6DD27665722C46B60E5DF680FB16B210607EF217652E60236C255F"
- "6A28315F4083A96791D7214BF64C1DF4FD0DB1944FB26A2A57031B32EEE64AD1"
- "5A8BA68885CDE74A5BFC920F6ABF59BA5C75506373E7130F9042DA922179251F",
- 16
- ), # Modulus
- int("010001", 16) # Exponent
- ),
+ # 847625836280919973
+ 0x10bc35f3509f7b7a5 - (1 << 64): PublicKey( # Telegram servers #2
+ # -----BEGIN PUBLIC KEY-----
+ # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAruw2yP/BCcsJliRoW5eB
+ # VBVle9dtjJw+OYED160Wybum9SXtBBLXriwt4rROd9csv0t0OHCaTmRqBcQ0J8fx
+ # hN6/cpR1GWgOZRUAiQxoMnlt0R93LCX/j1dnVa/gVbCjdSxpbrfY2g2L4frzjJvd
+ # l84Kd9ORYjDEAyFnEA7dD556OptgLQQ2e2iVNq8NZLYTzLp5YpOdO1doK+ttrltg
+ # gTCy5SrKeLoCPPbOgGsdxJxyz5KKcZnSLj16yE5HvJQn0CNpRdENvRUXe6tBP78O
+ # 39oJ8BTHp9oIjd6XWXAsp2CvK45Ol8wFXGF710w9lwCGNbmNxNYhtIkdqfsEcwR5
+ # JwIDAQAB
+ # -----END PUBLIC KEY-----
+ int(
+ "AEEC36C8FFC109CB099624685B97815415657BD76D8C9C3E398103D7AD16C9BB"
+ "A6F525ED0412D7AE2C2DE2B44E77D72CBF4B7438709A4E646A05C43427C7F184"
+ "DEBF72947519680E651500890C6832796DD11F772C25FF8F576755AFE055B0A3"
+ "752C696EB7D8DA0D8BE1FAF38C9BDD97CE0A77D3916230C4032167100EDD0F9E"
+ "7A3A9B602D04367B689536AF0D64B613CCBA7962939D3B57682BEB6DAE5B6081"
+ "30B2E52ACA78BA023CF6CE806B1DC49C72CF928A7199D22E3D7AC84E47BC9427"
+ "D0236945D10DBD15177BAB413FBF0EDFDA09F014C7A7DA088DDE9759702CA760"
+ "AF2B8E4E97CC055C617BD74C3D97008635B98DC4D621B4891DA9FB0473047927",
+ 16
+ ), # Modulus
+ int("010001", 16) # Exponent
+ ),
- # 847625836280919973
- 0x10bc35f3509f7b7a5 - (1 << 64): PublicKey( # Telegram servers #2
- # -----BEGIN PUBLIC KEY-----
- # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAruw2yP/BCcsJliRoW5eB
- # VBVle9dtjJw+OYED160Wybum9SXtBBLXriwt4rROd9csv0t0OHCaTmRqBcQ0J8fx
- # hN6/cpR1GWgOZRUAiQxoMnlt0R93LCX/j1dnVa/gVbCjdSxpbrfY2g2L4frzjJvd
- # l84Kd9ORYjDEAyFnEA7dD556OptgLQQ2e2iVNq8NZLYTzLp5YpOdO1doK+ttrltg
- # gTCy5SrKeLoCPPbOgGsdxJxyz5KKcZnSLj16yE5HvJQn0CNpRdENvRUXe6tBP78O
- # 39oJ8BTHp9oIjd6XWXAsp2CvK45Ol8wFXGF710w9lwCGNbmNxNYhtIkdqfsEcwR5
- # JwIDAQAB
- # -----END PUBLIC KEY-----
- int(
- "AEEC36C8FFC109CB099624685B97815415657BD76D8C9C3E398103D7AD16C9BB"
- "A6F525ED0412D7AE2C2DE2B44E77D72CBF4B7438709A4E646A05C43427C7F184"
- "DEBF72947519680E651500890C6832796DD11F772C25FF8F576755AFE055B0A3"
- "752C696EB7D8DA0D8BE1FAF38C9BDD97CE0A77D3916230C4032167100EDD0F9E"
- "7A3A9B602D04367B689536AF0D64B613CCBA7962939D3B57682BEB6DAE5B6081"
- "30B2E52ACA78BA023CF6CE806B1DC49C72CF928A7199D22E3D7AC84E47BC9427"
- "D0236945D10DBD15177BAB413FBF0EDFDA09F014C7A7DA088DDE9759702CA760"
- "AF2B8E4E97CC055C617BD74C3D97008635B98DC4D621B4891DA9FB0473047927",
- 16
- ), # Modulus
- int("010001", 16) # Exponent
- ),
+ # 1562291298945373506
+ 0x115ae5fa8b5529542 - (1 << 64): PublicKey( # Telegram servers #3
+ # -----BEGIN PUBLIC KEY-----
+ # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvfLHfYH2r9R70w8prHbl
+ # Wt/nDkh+XkgpflqQVcnAfSuTtO05lNPspQmL8Y2XjVT4t8cT6xAkdgfmmvnvRPOO
+ # KPi0OfJXoRVylFzAQG/j83u5K3kRLbae7fLccVhKZhY46lvsueI1hQdLgNV9n1cQ
+ # 3TDS2pQOCtovG4eDl9wacrXOJTG2990VjgnIKNA0UMoP+KF03qzryqIt3oTvZq03
+ # DyWdGK+AZjgBLaDKSnC6qD2cFY81UryRWOab8zKkWAnhw2kFpcqhI0jdV5QaSCEx
+ # vnsjVaX0Y1N0870931/5Jb9ICe4nweZ9kSDF/gip3kWLG0o8XQpChDfyvsqB9OLV
+ # /wIDAQAB
+ # -----END PUBLIC KEY-----
+ int(
+ "BDF2C77D81F6AFD47BD30F29AC76E55ADFE70E487E5E48297E5A9055C9C07D2B"
+ "93B4ED3994D3ECA5098BF18D978D54F8B7C713EB10247607E69AF9EF44F38E28"
+ "F8B439F257A11572945CC0406FE3F37BB92B79112DB69EEDF2DC71584A661638"
+ "EA5BECB9E23585074B80D57D9F5710DD30D2DA940E0ADA2F1B878397DC1A72B5"
+ "CE2531B6F7DD158E09C828D03450CA0FF8A174DEACEBCAA22DDE84EF66AD370F"
+ "259D18AF806638012DA0CA4A70BAA83D9C158F3552BC9158E69BF332A45809E1"
+ "C36905A5CAA12348DD57941A482131BE7B2355A5F4635374F3BD3DDF5FF925BF"
+ "4809EE27C1E67D9120C5FE08A9DE458B1B4A3C5D0A428437F2BECA81F4E2D5FF",
+ 16
+ ), # Modulus
+ int("010001", 16) # Exponent
+ ),
- # 1562291298945373506
- 0x115ae5fa8b5529542 - (1 << 64): PublicKey( # Telegram servers #3
- # -----BEGIN PUBLIC KEY-----
- # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvfLHfYH2r9R70w8prHbl
- # Wt/nDkh+XkgpflqQVcnAfSuTtO05lNPspQmL8Y2XjVT4t8cT6xAkdgfmmvnvRPOO
- # KPi0OfJXoRVylFzAQG/j83u5K3kRLbae7fLccVhKZhY46lvsueI1hQdLgNV9n1cQ
- # 3TDS2pQOCtovG4eDl9wacrXOJTG2990VjgnIKNA0UMoP+KF03qzryqIt3oTvZq03
- # DyWdGK+AZjgBLaDKSnC6qD2cFY81UryRWOab8zKkWAnhw2kFpcqhI0jdV5QaSCEx
- # vnsjVaX0Y1N0870931/5Jb9ICe4nweZ9kSDF/gip3kWLG0o8XQpChDfyvsqB9OLV
- # /wIDAQAB
- # -----END PUBLIC KEY-----
- int(
- "BDF2C77D81F6AFD47BD30F29AC76E55ADFE70E487E5E48297E5A9055C9C07D2B"
- "93B4ED3994D3ECA5098BF18D978D54F8B7C713EB10247607E69AF9EF44F38E28"
- "F8B439F257A11572945CC0406FE3F37BB92B79112DB69EEDF2DC71584A661638"
- "EA5BECB9E23585074B80D57D9F5710DD30D2DA940E0ADA2F1B878397DC1A72B5"
- "CE2531B6F7DD158E09C828D03450CA0FF8A174DEACEBCAA22DDE84EF66AD370F"
- "259D18AF806638012DA0CA4A70BAA83D9C158F3552BC9158E69BF332A45809E1"
- "C36905A5CAA12348DD57941A482131BE7B2355A5F4635374F3BD3DDF5FF925BF"
- "4809EE27C1E67D9120C5FE08A9DE458B1B4A3C5D0A428437F2BECA81F4E2D5FF",
- 16
- ), # Modulus
- int("010001", 16) # Exponent
- ),
+ # -5859577972006586033
+ 0xaeae98e13cd7f94f - (1 << 64): PublicKey( # Telegram servers #4
+ # -----BEGIN PUBLIC KEY-----
+ # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs/ditzm+mPND6xkhzwFI
+ # z6J/968CtkcSE/7Z2qAJiXbmZ3UDJPGrzqTDHkO30R8VeRM/Kz2f4nR05GIFiITl
+ # 4bEjvpy7xqRDspJcCFIOcyXm8abVDhF+th6knSU0yLtNKuQVP6voMrnt9MV1X92L
+ # GZQLgdHZbPQz0Z5qIpaKhdyA8DEvWWvSUwwc+yi1/gGaybwlzZwqXYoPOhwMebzK
+ # Uk0xW14htcJrRrq+PXXQbRzTMynseCoPIoke0dtCodbA3qQxQovE16q9zz4Otv2k
+ # 4j63cz53J+mhkVWAeWxVGI0lltJmWtEYK6er8VqqWot3nqmWMXogrgRLggv/Nbbo
+ # oQIDAQAB
+ # -----END PUBLIC KEY-----
+ int(
+ "B3F762B739BE98F343EB1921CF0148CFA27FF7AF02B6471213FED9DAA0098976"
+ "E667750324F1ABCEA4C31E43B7D11F1579133F2B3D9FE27474E462058884E5E1"
+ "B123BE9CBBC6A443B2925C08520E7325E6F1A6D50E117EB61EA49D2534C8BB4D"
+ "2AE4153FABE832B9EDF4C5755FDD8B19940B81D1D96CF433D19E6A22968A85DC"
+ "80F0312F596BD2530C1CFB28B5FE019AC9BC25CD9C2A5D8A0F3A1C0C79BCCA52"
+ "4D315B5E21B5C26B46BABE3D75D06D1CD33329EC782A0F22891ED1DB42A1D6C0"
+ "DEA431428BC4D7AABDCF3E0EB6FDA4E23EB7733E7727E9A1915580796C55188D"
+ "2596D2665AD1182BA7ABF15AAA5A8B779EA996317A20AE044B820BFF35B6E8A1",
+ 16
+ ), # Modulus
+ int("010001", 16) # Exponent
+ ),
- # -5859577972006586033
- 0xaeae98e13cd7f94f - (1 << 64): PublicKey( # Telegram servers #4
- # -----BEGIN PUBLIC KEY-----
- # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs/ditzm+mPND6xkhzwFI
- # z6J/968CtkcSE/7Z2qAJiXbmZ3UDJPGrzqTDHkO30R8VeRM/Kz2f4nR05GIFiITl
- # 4bEjvpy7xqRDspJcCFIOcyXm8abVDhF+th6knSU0yLtNKuQVP6voMrnt9MV1X92L
- # GZQLgdHZbPQz0Z5qIpaKhdyA8DEvWWvSUwwc+yi1/gGaybwlzZwqXYoPOhwMebzK
- # Uk0xW14htcJrRrq+PXXQbRzTMynseCoPIoke0dtCodbA3qQxQovE16q9zz4Otv2k
- # 4j63cz53J+mhkVWAeWxVGI0lltJmWtEYK6er8VqqWot3nqmWMXogrgRLggv/Nbbo
- # oQIDAQAB
- # -----END PUBLIC KEY-----
- int(
- "B3F762B739BE98F343EB1921CF0148CFA27FF7AF02B6471213FED9DAA0098976"
- "E667750324F1ABCEA4C31E43B7D11F1579133F2B3D9FE27474E462058884E5E1"
- "B123BE9CBBC6A443B2925C08520E7325E6F1A6D50E117EB61EA49D2534C8BB4D"
- "2AE4153FABE832B9EDF4C5755FDD8B19940B81D1D96CF433D19E6A22968A85DC"
- "80F0312F596BD2530C1CFB28B5FE019AC9BC25CD9C2A5D8A0F3A1C0C79BCCA52"
- "4D315B5E21B5C26B46BABE3D75D06D1CD33329EC782A0F22891ED1DB42A1D6C0"
- "DEA431428BC4D7AABDCF3E0EB6FDA4E23EB7733E7727E9A1915580796C55188D"
- "2596D2665AD1182BA7ABF15AAA5A8B779EA996317A20AE044B820BFF35B6E8A1",
- 16
- ), # Modulus
- int("010001", 16) # Exponent
- ),
+ # 6491968696586960280
+ 0x15a181b2235057d98 - (1 << 64): PublicKey( # Telegram servers #5
+ # -----BEGIN PUBLIC KEY-----
+ # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvmpxVY7ld/8DAjz6F6q0
+ # 5shjg8/4p6047bn6/m8yPy1RBsvIyvuDuGnP/RzPEhzXQ9UJ5Ynmh2XJZgHoE9xb
+ # nfxL5BXHplJhMtADXKM9bWB11PU1Eioc3+AXBB8QiNFBn2XI5UkO5hPhbb9mJpjA
+ # 9Uhw8EdfqJP8QetVsI/xrCEbwEXe0xvifRLJbY08/Gp66KpQvy7g8w7VB8wlgePe
+ # xW3pT13Ap6vuC+mQuJPyiHvSxjEKHgqePji9NP3tJUFQjcECqcm0yV7/2d0t/pbC
+ # m+ZH1sadZspQCEPPrtbkQBlvHb4OLiIWPGHKSMeRFvp3IWcmdJqXahxLCUS1Eh6M
+ # AQIDAQAB
+ # -----END PUBLIC KEY-----
+ int(
+ "BE6A71558EE577FF03023CFA17AAB4E6C86383CFF8A7AD38EDB9FAFE6F323F2D"
+ "5106CBC8CAFB83B869CFFD1CCF121CD743D509E589E68765C96601E813DC5B9D"
+ "FC4BE415C7A6526132D0035CA33D6D6075D4F535122A1CDFE017041F1088D141"
+ "9F65C8E5490EE613E16DBF662698C0F54870F0475FA893FC41EB55B08FF1AC21"
+ "1BC045DED31BE27D12C96D8D3CFC6A7AE8AA50BF2EE0F30ED507CC2581E3DEC5"
+ "6DE94F5DC0A7ABEE0BE990B893F2887BD2C6310A1E0A9E3E38BD34FDED254150"
+ "8DC102A9C9B4C95EFFD9DD2DFE96C29BE647D6C69D66CA500843CFAED6E44019"
+ "6F1DBE0E2E22163C61CA48C79116FA77216726749A976A1C4B0944B5121E8C01",
+ 16
+ ), # Modulus
+ int("010001", 16) # Exponent
+ ),
- # 6491968696586960280
- 0x15a181b2235057d98 - (1 << 64): PublicKey( # Telegram servers #5
- # -----BEGIN PUBLIC KEY-----
- # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvmpxVY7ld/8DAjz6F6q0
- # 5shjg8/4p6047bn6/m8yPy1RBsvIyvuDuGnP/RzPEhzXQ9UJ5Ynmh2XJZgHoE9xb
- # nfxL5BXHplJhMtADXKM9bWB11PU1Eioc3+AXBB8QiNFBn2XI5UkO5hPhbb9mJpjA
- # 9Uhw8EdfqJP8QetVsI/xrCEbwEXe0xvifRLJbY08/Gp66KpQvy7g8w7VB8wlgePe
- # xW3pT13Ap6vuC+mQuJPyiHvSxjEKHgqePji9NP3tJUFQjcECqcm0yV7/2d0t/pbC
- # m+ZH1sadZspQCEPPrtbkQBlvHb4OLiIWPGHKSMeRFvp3IWcmdJqXahxLCUS1Eh6M
- # AQIDAQAB
- # -----END PUBLIC KEY-----
- int(
- "BE6A71558EE577FF03023CFA17AAB4E6C86383CFF8A7AD38EDB9FAFE6F323F2D"
- "5106CBC8CAFB83B869CFFD1CCF121CD743D509E589E68765C96601E813DC5B9D"
- "FC4BE415C7A6526132D0035CA33D6D6075D4F535122A1CDFE017041F1088D141"
- "9F65C8E5490EE613E16DBF662698C0F54870F0475FA893FC41EB55B08FF1AC21"
- "1BC045DED31BE27D12C96D8D3CFC6A7AE8AA50BF2EE0F30ED507CC2581E3DEC5"
- "6DE94F5DC0A7ABEE0BE990B893F2887BD2C6310A1E0A9E3E38BD34FDED254150"
- "8DC102A9C9B4C95EFFD9DD2DFE96C29BE647D6C69D66CA500843CFAED6E44019"
- "6F1DBE0E2E22163C61CA48C79116FA77216726749A976A1C4B0944B5121E8C01",
- 16
- ), # Modulus
- int("010001", 16) # Exponent
- ),
+ # 6427105915145367799
+ 0x15931aac70e0d30f7 - (1 << 64): PublicKey( # CDN DC-121
+ # -----BEGIN RSA PUBLIC KEY-----
+ # MIIBCgKCAQEA+Lf3PvgE1yxbJUCMaEAkV0QySTVpnaDjiednB5RbtNWjCeqSVakY
+ # HbqqGMIIv5WCGdFdrqOfMNcNSstPtSU6R9UmRw6tquOIykpSuUOje9H+4XVIKquj
+ # yL2ISdK+4ZOMl4hCMkqauw4bP1Sbr03vZRQbU6qEA04V4j879BAyBVhr3WG9+Zi+
+ # t5XfGSTgSExPYEl8rZNHYNV5RB+BuroVH2HLTOpT/mJVfikYpgjfWF5ldezV4Wo9
+ # LSH0cZGSFIaeJl8d0A8Eiy5B9gtBO8mL+XfQRKOOmr7a4BM4Ro2de5rr2i2od7hY
+ # Xd3DO9FRSl4y1zA8Am48Rfd95WHF3N/OmQIDAQAB
+ # -----END RSA PUBLIC KEY-----
+ int(
+ "F8B7F73EF804D72C5B25408C6840245744324935699DA0E389E76707945BB4D5"
+ "A309EA9255A9181DBAAA18C208BF958219D15DAEA39F30D70D4ACB4FB5253A47"
+ "D526470EADAAE388CA4A52B943A37BD1FEE175482AABA3C8BD8849D2BEE1938C"
+ "978842324A9ABB0E1B3F549BAF4DEF65141B53AA84034E15E23F3BF410320558"
+ "6BDD61BDF998BEB795DF1924E0484C4F60497CAD934760D579441F81BABA151F"
+ "61CB4CEA53FE62557E2918A608DF585E6575ECD5E16A3D2D21F471919214869E"
+ "265F1DD00F048B2E41F60B413BC98BF977D044A38E9ABEDAE01338468D9D7B9A"
+ "EBDA2DA877B8585DDDC33BD1514A5E32D7303C026E3C45F77DE561C5DCDFCE99",
+ 16
+ ), # Modulus
+ int("010001", 16) # Exponent
+ ),
- # 6427105915145367799
- 0x15931aac70e0d30f7 - (1 << 64): PublicKey( # CDN DC-121
- # -----BEGIN RSA PUBLIC KEY-----
- # MIIBCgKCAQEA+Lf3PvgE1yxbJUCMaEAkV0QySTVpnaDjiednB5RbtNWjCeqSVakY
- # HbqqGMIIv5WCGdFdrqOfMNcNSstPtSU6R9UmRw6tquOIykpSuUOje9H+4XVIKquj
- # yL2ISdK+4ZOMl4hCMkqauw4bP1Sbr03vZRQbU6qEA04V4j879BAyBVhr3WG9+Zi+
- # t5XfGSTgSExPYEl8rZNHYNV5RB+BuroVH2HLTOpT/mJVfikYpgjfWF5ldezV4Wo9
- # LSH0cZGSFIaeJl8d0A8Eiy5B9gtBO8mL+XfQRKOOmr7a4BM4Ro2de5rr2i2od7hY
- # Xd3DO9FRSl4y1zA8Am48Rfd95WHF3N/OmQIDAQAB
- # -----END RSA PUBLIC KEY-----
- int(
- "F8B7F73EF804D72C5B25408C6840245744324935699DA0E389E76707945BB4D5"
- "A309EA9255A9181DBAAA18C208BF958219D15DAEA39F30D70D4ACB4FB5253A47"
- "D526470EADAAE388CA4A52B943A37BD1FEE175482AABA3C8BD8849D2BEE1938C"
- "978842324A9ABB0E1B3F549BAF4DEF65141B53AA84034E15E23F3BF410320558"
- "6BDD61BDF998BEB795DF1924E0484C4F60497CAD934760D579441F81BABA151F"
- "61CB4CEA53FE62557E2918A608DF585E6575ECD5E16A3D2D21F471919214869E"
- "265F1DD00F048B2E41F60B413BC98BF977D044A38E9ABEDAE01338468D9D7B9A"
- "EBDA2DA877B8585DDDC33BD1514A5E32D7303C026E3C45F77DE561C5DCDFCE99",
- 16
- ), # Modulus
- int("010001", 16) # Exponent
- ),
+ # 2685959930972952888
+ 0x1254672538e935938 - (1 << 64): PublicKey( # CDN DC-140
+ # -----BEGIN RSA PUBLIC KEY-----
+ # MIIBCgKCAQEAzuHVC7sE50Kho/yDVZtWnlmA5Bf/aM8KZY3WzS16w6w1sBqipj8o
+ # gMGG7ULbGBtYmKEaI7IIJO6WM2m1MaXVnsqS8d7PaGAZiy8rSN3S7S2a8wp4RXZe
+ # hs0JAXvZeIz45iByCMBfycbJKmSweYkesRUI7hUO8eQhmm/UYUEpJY7VOt0Iemiu
+ # URSpqlRQ2FlcyHahYUNcvbICb4+/AP7coKBn6cB5FyzM7MCcKxbEKOx3Y3MUnbZq
+ # q5pN6/eRazkegyrlp4kuJ94KsbRFHFX5Dx8uzjrO9wi8LF7gIgZu5DRMcmjXJKq6
+ # rGZ2Z9cnrD8pVu1L2vcInd4K6ximZS2hbwIDAQAB
+ # -----END RSA PUBLIC KEY-----
+ int(
+ "CEE1D50BBB04E742A1A3FC83559B569E5980E417FF68CF0A658DD6CD2D7AC3AC"
+ "35B01AA2A63F2880C186ED42DB181B5898A11A23B20824EE963369B531A5D59E"
+ "CA92F1DECF6860198B2F2B48DDD2ED2D9AF30A7845765E86CD09017BD9788CF8"
+ "E6207208C05FC9C6C92A64B079891EB11508EE150EF1E4219A6FD4614129258E"
+ "D53ADD087A68AE5114A9AA5450D8595CC876A161435CBDB2026F8FBF00FEDCA0"
+ "A067E9C079172CCCECC09C2B16C428EC776373149DB66AAB9A4DEBF7916B391E"
+ "832AE5A7892E27DE0AB1B4451C55F90F1F2ECE3ACEF708BC2C5EE022066EE434"
+ "4C7268D724AABAAC667667D727AC3F2956ED4BDAF7089DDE0AEB18A6652DA16F",
+ 16
+ ), # Modulus
+ int("010001", 16) # Exponent
+ )
+}
- # 2685959930972952888
- 0x1254672538e935938 - (1 << 64): PublicKey( # CDN DC-140
- # -----BEGIN RSA PUBLIC KEY-----
- # MIIBCgKCAQEAzuHVC7sE50Kho/yDVZtWnlmA5Bf/aM8KZY3WzS16w6w1sBqipj8o
- # gMGG7ULbGBtYmKEaI7IIJO6WM2m1MaXVnsqS8d7PaGAZiy8rSN3S7S2a8wp4RXZe
- # hs0JAXvZeIz45iByCMBfycbJKmSweYkesRUI7hUO8eQhmm/UYUEpJY7VOt0Iemiu
- # URSpqlRQ2FlcyHahYUNcvbICb4+/AP7coKBn6cB5FyzM7MCcKxbEKOx3Y3MUnbZq
- # q5pN6/eRazkegyrlp4kuJ94KsbRFHFX5Dx8uzjrO9wi8LF7gIgZu5DRMcmjXJKq6
- # rGZ2Z9cnrD8pVu1L2vcInd4K6ximZS2hbwIDAQAB
- # -----END RSA PUBLIC KEY-----
- int(
- "CEE1D50BBB04E742A1A3FC83559B569E5980E417FF68CF0A658DD6CD2D7AC3AC"
- "35B01AA2A63F2880C186ED42DB181B5898A11A23B20824EE963369B531A5D59E"
- "CA92F1DECF6860198B2F2B48DDD2ED2D9AF30A7845765E86CD09017BD9788CF8"
- "E6207208C05FC9C6C92A64B079891EB11508EE150EF1E4219A6FD4614129258E"
- "D53ADD087A68AE5114A9AA5450D8595CC876A161435CBDB2026F8FBF00FEDCA0"
- "A067E9C079172CCCECC09C2B16C428EC776373149DB66AAB9A4DEBF7916B391E"
- "832AE5A7892E27DE0AB1B4451C55F90F1F2ECE3ACEF708BC2C5EE022066EE434"
- "4C7268D724AABAAC667667D727AC3F2956ED4BDAF7089DDE0AEB18A6652DA16F",
- 16
- ), # Modulus
- int("010001", 16) # Exponent
- )
- }
- @classmethod
- def encrypt(cls, data: bytes, fingerprint: int) -> bytes:
- return pow(
- int.from_bytes(data, "big"),
- cls.server_public_keys[fingerprint].e,
- cls.server_public_keys[fingerprint].m
- ).to_bytes(256, "big")
+def encrypt(data: bytes, fingerprint: int) -> bytes:
+ return pow(
+ int.from_bytes(data, "big"),
+ server_public_keys[fingerprint].e,
+ server_public_keys[fingerprint].m
+ ).to_bytes(256, "big")
diff --git a/pyrogram/client/ext/dispatcher.py b/pyrogram/dispatcher.py
similarity index 72%
rename from pyrogram/client/ext/dispatcher.py
rename to pyrogram/dispatcher.py
index d8308944db..40a6dcf48f 100644
--- a/pyrogram/client/ext/dispatcher.py
+++ b/pyrogram/dispatcher.py
@@ -21,7 +21,13 @@
from collections import OrderedDict
import pyrogram
-from pyrogram.api.types import (
+from pyrogram import utils
+from pyrogram.handlers import (
+ CallbackQueryHandler, MessageHandler, DeletedMessagesHandler,
+ UserStatusHandler, RawUpdateHandler, InlineQueryHandler, PollHandler,
+ ChosenInlineResultHandler
+)
+from pyrogram.raw.types import (
UpdateNewMessage, UpdateNewChannelMessage, UpdateNewScheduledMessage,
UpdateEditMessage, UpdateEditChannelMessage,
UpdateDeleteMessages, UpdateDeleteChannelMessages,
@@ -29,12 +35,6 @@
UpdateUserStatus, UpdateBotInlineQuery, UpdateMessagePoll,
UpdateBotInlineSend
)
-from . import utils
-from ..handlers import (
- CallbackQueryHandler, MessageHandler, DeletedMessagesHandler,
- UserStatusHandler, RawUpdateHandler, InlineQueryHandler, PollHandler,
- ChosenInlineResultHandler
-)
log = logging.getLogger(__name__)
@@ -63,18 +63,18 @@ class Dispatcher:
MESSAGE_UPDATES = NEW_MESSAGE_UPDATES + EDIT_MESSAGE_UPDATES
- def __init__(self, client, workers: int):
+ def __init__(self, client: "pyrogram.Client"):
self.client = client
- self.workers = workers
+ self.loop = asyncio.get_event_loop()
- self.update_worker_tasks = []
+ self.handler_worker_tasks = []
self.locks_list = []
self.updates_queue = asyncio.Queue()
self.groups = OrderedDict()
async def message_parser(update, users, chats):
- return await pyrogram.Message._parse(
+ return await pyrogram.types.Message._parse(
self.client, update.message, users, chats,
isinstance(update, UpdateNewScheduledMessage)
), MessageHandler
@@ -83,19 +83,19 @@ async def deleted_messages_parser(update, users, chats):
return utils.parse_deleted_messages(self.client, update), DeletedMessagesHandler
async def callback_query_parser(update, users, chats):
- return await pyrogram.CallbackQuery._parse(self.client, update, users), CallbackQueryHandler
+ return await pyrogram.types.CallbackQuery._parse(self.client, update, users), CallbackQueryHandler
async def user_status_parser(update, users, chats):
- return pyrogram.User._parse_user_status(self.client, update), UserStatusHandler
+ return pyrogram.types.User._parse_user_status(self.client, update), UserStatusHandler
async def inline_query_parser(update, users, chats):
- return pyrogram.InlineQuery._parse(self.client, update, users), InlineQueryHandler
+ return pyrogram.types.InlineQuery._parse(self.client, update, users), InlineQueryHandler
async def poll_parser(update, users, chats):
- return pyrogram.Poll._parse_update(self.client, update), PollHandler
+ return pyrogram.types.Poll._parse_update(self.client, update), PollHandler
async def chosen_inline_result_parser(update, users, chats):
- return pyrogram.ChosenInlineResult._parse(self.client, update, users), ChosenInlineResultHandler
+ return pyrogram.types.ChosenInlineResult._parse(self.client, update, users), ChosenInlineResultHandler
self.update_parsers = {
Dispatcher.MESSAGE_UPDATES: message_parser,
@@ -110,26 +110,28 @@ async def chosen_inline_result_parser(update, users, chats):
self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple}
async def start(self):
- for i in range(self.workers):
- self.locks_list.append(asyncio.Lock())
+ if not self.client.no_updates:
+ for i in range(self.client.workers):
+ self.locks_list.append(asyncio.Lock())
- self.update_worker_tasks.append(
- asyncio.ensure_future(self.update_worker(self.locks_list[-1]))
- )
+ self.handler_worker_tasks.append(
+ asyncio.ensure_future(self.handler_worker(self.locks_list[-1]))
+ )
- logging.info("Started {} UpdateWorkerTasks".format(self.workers))
+ logging.info(f"Started {self.client.workers} HandlerTasks")
async def stop(self):
- for i in range(self.workers):
- self.updates_queue.put_nowait(None)
+ if not self.client.no_updates:
+ for i in range(self.client.workers):
+ self.updates_queue.put_nowait(None)
- for i in self.update_worker_tasks:
- await i
+ for i in self.handler_worker_tasks:
+ await i
- self.update_worker_tasks.clear()
- self.groups.clear()
+ self.handler_worker_tasks.clear()
+ self.groups.clear()
- logging.info("Stopped {} UpdateWorkerTasks".format(self.workers))
+ logging.info(f"Stopped {self.client.workers} HandlerTasks")
def add_handler(self, handler, group: int):
async def fn():
@@ -155,7 +157,7 @@ async def fn():
try:
if group not in self.groups:
- raise ValueError("Group {} does not exist. Handler was not removed.".format(group))
+ raise ValueError(f"Group {group} does not exist. Handler was not removed.")
self.groups[group].remove(handler)
finally:
@@ -164,7 +166,7 @@ async def fn():
asyncio.ensure_future(fn())
- async def update_worker(self, lock):
+ async def handler_worker(self, lock):
while True:
packet = await self.updates_queue.get()
@@ -188,9 +190,8 @@ async def update_worker(self, lock):
if isinstance(handler, handler_type):
try:
- if (await handler.check(parsed_update)):
+ if await handler.check(self.client, parsed_update):
args = (parsed_update,)
-
except Exception as e:
log.error(e, exc_info=True)
continue
@@ -202,7 +203,15 @@ async def update_worker(self, lock):
continue
try:
- await handler.callback(self.client, *args)
+ if asyncio.iscoroutinefunction(handler.callback):
+ await handler.callback(self.client, *args)
+ else:
+ await self.loop.run_in_executor(
+ self.client.executor,
+ handler.callback,
+ self.client,
+ *args
+ )
except pyrogram.StopPropagation:
raise
except pyrogram.ContinuePropagation:
diff --git a/pyrogram/emoji.py b/pyrogram/emoji.py
new file mode 100644
index 0000000000..7c55df601f
--- /dev/null
+++ b/pyrogram/emoji.py
@@ -0,0 +1,3521 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+GRINNING_FACE = "\U0001f600"
+GRINNING_FACE_WITH_BIG_EYES = "\U0001f603"
+GRINNING_FACE_WITH_SMILING_EYES = "\U0001f604"
+BEAMING_FACE_WITH_SMILING_EYES = "\U0001f601"
+GRINNING_SQUINTING_FACE = "\U0001f606"
+GRINNING_FACE_WITH_SWEAT = "\U0001f605"
+ROLLING_ON_THE_FLOOR_LAUGHING = "\U0001f923"
+FACE_WITH_TEARS_OF_JOY = "\U0001f602"
+SLIGHTLY_SMILING_FACE = "\U0001f642"
+UPSIDE_DOWN_FACE = "\U0001f643"
+WINKING_FACE = "\U0001f609"
+SMILING_FACE_WITH_SMILING_EYES = "\U0001f60a"
+SMILING_FACE_WITH_HALO = "\U0001f607"
+SMILING_FACE_WITH_HEARTS = "\U0001f970"
+SMILING_FACE_WITH_HEART_EYES = "\U0001f60d"
+STAR_STRUCK = "\U0001f929"
+FACE_BLOWING_A_KISS = "\U0001f618"
+KISSING_FACE = "\U0001f617"
+SMILING_FACE = "\u263a\ufe0f"
+KISSING_FACE_WITH_CLOSED_EYES = "\U0001f61a"
+KISSING_FACE_WITH_SMILING_EYES = "\U0001f619"
+SMILING_FACE_WITH_TEAR = "\U0001f972"
+FACE_SAVORING_FOOD = "\U0001f60b"
+FACE_WITH_TONGUE = "\U0001f61b"
+WINKING_FACE_WITH_TONGUE = "\U0001f61c"
+ZANY_FACE = "\U0001f92a"
+SQUINTING_FACE_WITH_TONGUE = "\U0001f61d"
+MONEY_MOUTH_FACE = "\U0001f911"
+HUGGING_FACE = "\U0001f917"
+FACE_WITH_HAND_OVER_MOUTH = "\U0001f92d"
+SHUSHING_FACE = "\U0001f92b"
+THINKING_FACE = "\U0001f914"
+ZIPPER_MOUTH_FACE = "\U0001f910"
+FACE_WITH_RAISED_EYEBROW = "\U0001f928"
+NEUTRAL_FACE = "\U0001f610"
+EXPRESSIONLESS_FACE = "\U0001f611"
+FACE_WITHOUT_MOUTH = "\U0001f636"
+SMIRKING_FACE = "\U0001f60f"
+UNAMUSED_FACE = "\U0001f612"
+FACE_WITH_ROLLING_EYES = "\U0001f644"
+GRIMACING_FACE = "\U0001f62c"
+LYING_FACE = "\U0001f925"
+RELIEVED_FACE = "\U0001f60c"
+PENSIVE_FACE = "\U0001f614"
+SLEEPY_FACE = "\U0001f62a"
+DROOLING_FACE = "\U0001f924"
+SLEEPING_FACE = "\U0001f634"
+FACE_WITH_MEDICAL_MASK = "\U0001f637"
+FACE_WITH_THERMOMETER = "\U0001f912"
+FACE_WITH_HEAD_BANDAGE = "\U0001f915"
+NAUSEATED_FACE = "\U0001f922"
+FACE_VOMITING = "\U0001f92e"
+SNEEZING_FACE = "\U0001f927"
+HOT_FACE = "\U0001f975"
+COLD_FACE = "\U0001f976"
+WOOZY_FACE = "\U0001f974"
+DIZZY_FACE = "\U0001f635"
+EXPLODING_HEAD = "\U0001f92f"
+COWBOY_HAT_FACE = "\U0001f920"
+PARTYING_FACE = "\U0001f973"
+DISGUISED_FACE = "\U0001f978"
+SMILING_FACE_WITH_SUNGLASSES = "\U0001f60e"
+NERD_FACE = "\U0001f913"
+FACE_WITH_MONOCLE = "\U0001f9d0"
+CONFUSED_FACE = "\U0001f615"
+WORRIED_FACE = "\U0001f61f"
+SLIGHTLY_FROWNING_FACE = "\U0001f641"
+FROWNING_FACE = "\u2639\ufe0f"
+FACE_WITH_OPEN_MOUTH = "\U0001f62e"
+HUSHED_FACE = "\U0001f62f"
+ASTONISHED_FACE = "\U0001f632"
+FLUSHED_FACE = "\U0001f633"
+PLEADING_FACE = "\U0001f97a"
+FROWNING_FACE_WITH_OPEN_MOUTH = "\U0001f626"
+ANGUISHED_FACE = "\U0001f627"
+FEARFUL_FACE = "\U0001f628"
+ANXIOUS_FACE_WITH_SWEAT = "\U0001f630"
+SAD_BUT_RELIEVED_FACE = "\U0001f625"
+CRYING_FACE = "\U0001f622"
+LOUDLY_CRYING_FACE = "\U0001f62d"
+FACE_SCREAMING_IN_FEAR = "\U0001f631"
+CONFOUNDED_FACE = "\U0001f616"
+PERSEVERING_FACE = "\U0001f623"
+DISAPPOINTED_FACE = "\U0001f61e"
+DOWNCAST_FACE_WITH_SWEAT = "\U0001f613"
+WEARY_FACE = "\U0001f629"
+TIRED_FACE = "\U0001f62b"
+YAWNING_FACE = "\U0001f971"
+FACE_WITH_STEAM_FROM_NOSE = "\U0001f624"
+POUTING_FACE = "\U0001f621"
+ANGRY_FACE = "\U0001f620"
+FACE_WITH_SYMBOLS_ON_MOUTH = "\U0001f92c"
+SMILING_FACE_WITH_HORNS = "\U0001f608"
+ANGRY_FACE_WITH_HORNS = "\U0001f47f"
+SKULL = "\U0001f480"
+SKULL_AND_CROSSBONES = "\u2620\ufe0f"
+PILE_OF_POO = "\U0001f4a9"
+CLOWN_FACE = "\U0001f921"
+OGRE = "\U0001f479"
+GOBLIN = "\U0001f47a"
+GHOST = "\U0001f47b"
+ALIEN = "\U0001f47d"
+ALIEN_MONSTER = "\U0001f47e"
+ROBOT = "\U0001f916"
+GRINNING_CAT = "\U0001f63a"
+GRINNING_CAT_WITH_SMILING_EYES = "\U0001f638"
+CAT_WITH_TEARS_OF_JOY = "\U0001f639"
+SMILING_CAT_WITH_HEART_EYES = "\U0001f63b"
+CAT_WITH_WRY_SMILE = "\U0001f63c"
+KISSING_CAT = "\U0001f63d"
+WEARY_CAT = "\U0001f640"
+CRYING_CAT = "\U0001f63f"
+POUTING_CAT = "\U0001f63e"
+SEE_NO_EVIL_MONKEY = "\U0001f648"
+HEAR_NO_EVIL_MONKEY = "\U0001f649"
+SPEAK_NO_EVIL_MONKEY = "\U0001f64a"
+KISS_MARK = "\U0001f48b"
+LOVE_LETTER = "\U0001f48c"
+HEART_WITH_ARROW = "\U0001f498"
+HEART_WITH_RIBBON = "\U0001f49d"
+SPARKLING_HEART = "\U0001f496"
+GROWING_HEART = "\U0001f497"
+BEATING_HEART = "\U0001f493"
+REVOLVING_HEARTS = "\U0001f49e"
+TWO_HEARTS = "\U0001f495"
+HEART_DECORATION = "\U0001f49f"
+HEART_EXCLAMATION = "\u2763\ufe0f"
+BROKEN_HEART = "\U0001f494"
+RED_HEART = "\u2764\ufe0f"
+ORANGE_HEART = "\U0001f9e1"
+YELLOW_HEART = "\U0001f49b"
+GREEN_HEART = "\U0001f49a"
+BLUE_HEART = "\U0001f499"
+PURPLE_HEART = "\U0001f49c"
+BROWN_HEART = "\U0001f90e"
+BLACK_HEART = "\U0001f5a4"
+WHITE_HEART = "\U0001f90d"
+HUNDRED_POINTS = "\U0001f4af"
+ANGER_SYMBOL = "\U0001f4a2"
+COLLISION = "\U0001f4a5"
+DIZZY = "\U0001f4ab"
+SWEAT_DROPLETS = "\U0001f4a6"
+DASHING_AWAY = "\U0001f4a8"
+HOLE = "\U0001f573\ufe0f"
+BOMB = "\U0001f4a3"
+SPEECH_BALLOON = "\U0001f4ac"
+EYE_IN_SPEECH_BUBBLE = "\U0001f441\ufe0f\u200d\U0001f5e8\ufe0f"
+LEFT_SPEECH_BUBBLE = "\U0001f5e8\ufe0f"
+RIGHT_ANGER_BUBBLE = "\U0001f5ef\ufe0f"
+THOUGHT_BALLOON = "\U0001f4ad"
+ZZZ = "\U0001f4a4"
+WAVING_HAND = "\U0001f44b"
+WAVING_HAND_LIGHT_SKIN_TONE = "\U0001f44b\U0001f3fb"
+WAVING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f44b\U0001f3fc"
+WAVING_HAND_MEDIUM_SKIN_TONE = "\U0001f44b\U0001f3fd"
+WAVING_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f44b\U0001f3fe"
+WAVING_HAND_DARK_SKIN_TONE = "\U0001f44b\U0001f3ff"
+RAISED_BACK_OF_HAND = "\U0001f91a"
+RAISED_BACK_OF_HAND_LIGHT_SKIN_TONE = "\U0001f91a\U0001f3fb"
+RAISED_BACK_OF_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f91a\U0001f3fc"
+RAISED_BACK_OF_HAND_MEDIUM_SKIN_TONE = "\U0001f91a\U0001f3fd"
+RAISED_BACK_OF_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f91a\U0001f3fe"
+RAISED_BACK_OF_HAND_DARK_SKIN_TONE = "\U0001f91a\U0001f3ff"
+HAND_WITH_FINGERS_SPLAYED = "\U0001f590\ufe0f"
+HAND_WITH_FINGERS_SPLAYED_LIGHT_SKIN_TONE = "\U0001f590\U0001f3fb"
+HAND_WITH_FINGERS_SPLAYED_MEDIUM_LIGHT_SKIN_TONE = "\U0001f590\U0001f3fc"
+HAND_WITH_FINGERS_SPLAYED_MEDIUM_SKIN_TONE = "\U0001f590\U0001f3fd"
+HAND_WITH_FINGERS_SPLAYED_MEDIUM_DARK_SKIN_TONE = "\U0001f590\U0001f3fe"
+HAND_WITH_FINGERS_SPLAYED_DARK_SKIN_TONE = "\U0001f590\U0001f3ff"
+RAISED_HAND = "\u270b"
+RAISED_HAND_LIGHT_SKIN_TONE = "\u270b\U0001f3fb"
+RAISED_HAND_MEDIUM_LIGHT_SKIN_TONE = "\u270b\U0001f3fc"
+RAISED_HAND_MEDIUM_SKIN_TONE = "\u270b\U0001f3fd"
+RAISED_HAND_MEDIUM_DARK_SKIN_TONE = "\u270b\U0001f3fe"
+RAISED_HAND_DARK_SKIN_TONE = "\u270b\U0001f3ff"
+VULCAN_SALUTE = "\U0001f596"
+VULCAN_SALUTE_LIGHT_SKIN_TONE = "\U0001f596\U0001f3fb"
+VULCAN_SALUTE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f596\U0001f3fc"
+VULCAN_SALUTE_MEDIUM_SKIN_TONE = "\U0001f596\U0001f3fd"
+VULCAN_SALUTE_MEDIUM_DARK_SKIN_TONE = "\U0001f596\U0001f3fe"
+VULCAN_SALUTE_DARK_SKIN_TONE = "\U0001f596\U0001f3ff"
+OK_HAND = "\U0001f44c"
+OK_HAND_LIGHT_SKIN_TONE = "\U0001f44c\U0001f3fb"
+OK_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f44c\U0001f3fc"
+OK_HAND_MEDIUM_SKIN_TONE = "\U0001f44c\U0001f3fd"
+OK_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f44c\U0001f3fe"
+OK_HAND_DARK_SKIN_TONE = "\U0001f44c\U0001f3ff"
+PINCHED_FINGERS = "\U0001f90c"
+PINCHED_FINGERS_LIGHT_SKIN_TONE = "\U0001f90c\U0001f3fb"
+PINCHED_FINGERS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f90c\U0001f3fc"
+PINCHED_FINGERS_MEDIUM_SKIN_TONE = "\U0001f90c\U0001f3fd"
+PINCHED_FINGERS_MEDIUM_DARK_SKIN_TONE = "\U0001f90c\U0001f3fe"
+PINCHED_FINGERS_DARK_SKIN_TONE = "\U0001f90c\U0001f3ff"
+PINCHING_HAND = "\U0001f90f"
+PINCHING_HAND_LIGHT_SKIN_TONE = "\U0001f90f\U0001f3fb"
+PINCHING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f90f\U0001f3fc"
+PINCHING_HAND_MEDIUM_SKIN_TONE = "\U0001f90f\U0001f3fd"
+PINCHING_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f90f\U0001f3fe"
+PINCHING_HAND_DARK_SKIN_TONE = "\U0001f90f\U0001f3ff"
+VICTORY_HAND = "\u270c\ufe0f"
+VICTORY_HAND_LIGHT_SKIN_TONE = "\u270c\U0001f3fb"
+VICTORY_HAND_MEDIUM_LIGHT_SKIN_TONE = "\u270c\U0001f3fc"
+VICTORY_HAND_MEDIUM_SKIN_TONE = "\u270c\U0001f3fd"
+VICTORY_HAND_MEDIUM_DARK_SKIN_TONE = "\u270c\U0001f3fe"
+VICTORY_HAND_DARK_SKIN_TONE = "\u270c\U0001f3ff"
+CROSSED_FINGERS = "\U0001f91e"
+CROSSED_FINGERS_LIGHT_SKIN_TONE = "\U0001f91e\U0001f3fb"
+CROSSED_FINGERS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f91e\U0001f3fc"
+CROSSED_FINGERS_MEDIUM_SKIN_TONE = "\U0001f91e\U0001f3fd"
+CROSSED_FINGERS_MEDIUM_DARK_SKIN_TONE = "\U0001f91e\U0001f3fe"
+CROSSED_FINGERS_DARK_SKIN_TONE = "\U0001f91e\U0001f3ff"
+LOVE_YOU_GESTURE = "\U0001f91f"
+LOVE_YOU_GESTURE_LIGHT_SKIN_TONE = "\U0001f91f\U0001f3fb"
+LOVE_YOU_GESTURE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f91f\U0001f3fc"
+LOVE_YOU_GESTURE_MEDIUM_SKIN_TONE = "\U0001f91f\U0001f3fd"
+LOVE_YOU_GESTURE_MEDIUM_DARK_SKIN_TONE = "\U0001f91f\U0001f3fe"
+LOVE_YOU_GESTURE_DARK_SKIN_TONE = "\U0001f91f\U0001f3ff"
+SIGN_OF_THE_HORNS = "\U0001f918"
+SIGN_OF_THE_HORNS_LIGHT_SKIN_TONE = "\U0001f918\U0001f3fb"
+SIGN_OF_THE_HORNS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f918\U0001f3fc"
+SIGN_OF_THE_HORNS_MEDIUM_SKIN_TONE = "\U0001f918\U0001f3fd"
+SIGN_OF_THE_HORNS_MEDIUM_DARK_SKIN_TONE = "\U0001f918\U0001f3fe"
+SIGN_OF_THE_HORNS_DARK_SKIN_TONE = "\U0001f918\U0001f3ff"
+CALL_ME_HAND = "\U0001f919"
+CALL_ME_HAND_LIGHT_SKIN_TONE = "\U0001f919\U0001f3fb"
+CALL_ME_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f919\U0001f3fc"
+CALL_ME_HAND_MEDIUM_SKIN_TONE = "\U0001f919\U0001f3fd"
+CALL_ME_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f919\U0001f3fe"
+CALL_ME_HAND_DARK_SKIN_TONE = "\U0001f919\U0001f3ff"
+BACKHAND_INDEX_POINTING_LEFT = "\U0001f448"
+BACKHAND_INDEX_POINTING_LEFT_LIGHT_SKIN_TONE = "\U0001f448\U0001f3fb"
+BACKHAND_INDEX_POINTING_LEFT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f448\U0001f3fc"
+BACKHAND_INDEX_POINTING_LEFT_MEDIUM_SKIN_TONE = "\U0001f448\U0001f3fd"
+BACKHAND_INDEX_POINTING_LEFT_MEDIUM_DARK_SKIN_TONE = "\U0001f448\U0001f3fe"
+BACKHAND_INDEX_POINTING_LEFT_DARK_SKIN_TONE = "\U0001f448\U0001f3ff"
+BACKHAND_INDEX_POINTING_RIGHT = "\U0001f449"
+BACKHAND_INDEX_POINTING_RIGHT_LIGHT_SKIN_TONE = "\U0001f449\U0001f3fb"
+BACKHAND_INDEX_POINTING_RIGHT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f449\U0001f3fc"
+BACKHAND_INDEX_POINTING_RIGHT_MEDIUM_SKIN_TONE = "\U0001f449\U0001f3fd"
+BACKHAND_INDEX_POINTING_RIGHT_MEDIUM_DARK_SKIN_TONE = "\U0001f449\U0001f3fe"
+BACKHAND_INDEX_POINTING_RIGHT_DARK_SKIN_TONE = "\U0001f449\U0001f3ff"
+BACKHAND_INDEX_POINTING_UP = "\U0001f446"
+BACKHAND_INDEX_POINTING_UP_LIGHT_SKIN_TONE = "\U0001f446\U0001f3fb"
+BACKHAND_INDEX_POINTING_UP_MEDIUM_LIGHT_SKIN_TONE = "\U0001f446\U0001f3fc"
+BACKHAND_INDEX_POINTING_UP_MEDIUM_SKIN_TONE = "\U0001f446\U0001f3fd"
+BACKHAND_INDEX_POINTING_UP_MEDIUM_DARK_SKIN_TONE = "\U0001f446\U0001f3fe"
+BACKHAND_INDEX_POINTING_UP_DARK_SKIN_TONE = "\U0001f446\U0001f3ff"
+MIDDLE_FINGER = "\U0001f595"
+MIDDLE_FINGER_LIGHT_SKIN_TONE = "\U0001f595\U0001f3fb"
+MIDDLE_FINGER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f595\U0001f3fc"
+MIDDLE_FINGER_MEDIUM_SKIN_TONE = "\U0001f595\U0001f3fd"
+MIDDLE_FINGER_MEDIUM_DARK_SKIN_TONE = "\U0001f595\U0001f3fe"
+MIDDLE_FINGER_DARK_SKIN_TONE = "\U0001f595\U0001f3ff"
+BACKHAND_INDEX_POINTING_DOWN = "\U0001f447"
+BACKHAND_INDEX_POINTING_DOWN_LIGHT_SKIN_TONE = "\U0001f447\U0001f3fb"
+BACKHAND_INDEX_POINTING_DOWN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f447\U0001f3fc"
+BACKHAND_INDEX_POINTING_DOWN_MEDIUM_SKIN_TONE = "\U0001f447\U0001f3fd"
+BACKHAND_INDEX_POINTING_DOWN_MEDIUM_DARK_SKIN_TONE = "\U0001f447\U0001f3fe"
+BACKHAND_INDEX_POINTING_DOWN_DARK_SKIN_TONE = "\U0001f447\U0001f3ff"
+INDEX_POINTING_UP = "\u261d\ufe0f"
+INDEX_POINTING_UP_LIGHT_SKIN_TONE = "\u261d\U0001f3fb"
+INDEX_POINTING_UP_MEDIUM_LIGHT_SKIN_TONE = "\u261d\U0001f3fc"
+INDEX_POINTING_UP_MEDIUM_SKIN_TONE = "\u261d\U0001f3fd"
+INDEX_POINTING_UP_MEDIUM_DARK_SKIN_TONE = "\u261d\U0001f3fe"
+INDEX_POINTING_UP_DARK_SKIN_TONE = "\u261d\U0001f3ff"
+THUMBS_UP = "\U0001f44d"
+THUMBS_UP_LIGHT_SKIN_TONE = "\U0001f44d\U0001f3fb"
+THUMBS_UP_MEDIUM_LIGHT_SKIN_TONE = "\U0001f44d\U0001f3fc"
+THUMBS_UP_MEDIUM_SKIN_TONE = "\U0001f44d\U0001f3fd"
+THUMBS_UP_MEDIUM_DARK_SKIN_TONE = "\U0001f44d\U0001f3fe"
+THUMBS_UP_DARK_SKIN_TONE = "\U0001f44d\U0001f3ff"
+THUMBS_DOWN = "\U0001f44e"
+THUMBS_DOWN_LIGHT_SKIN_TONE = "\U0001f44e\U0001f3fb"
+THUMBS_DOWN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f44e\U0001f3fc"
+THUMBS_DOWN_MEDIUM_SKIN_TONE = "\U0001f44e\U0001f3fd"
+THUMBS_DOWN_MEDIUM_DARK_SKIN_TONE = "\U0001f44e\U0001f3fe"
+THUMBS_DOWN_DARK_SKIN_TONE = "\U0001f44e\U0001f3ff"
+RAISED_FIST = "\u270a"
+RAISED_FIST_LIGHT_SKIN_TONE = "\u270a\U0001f3fb"
+RAISED_FIST_MEDIUM_LIGHT_SKIN_TONE = "\u270a\U0001f3fc"
+RAISED_FIST_MEDIUM_SKIN_TONE = "\u270a\U0001f3fd"
+RAISED_FIST_MEDIUM_DARK_SKIN_TONE = "\u270a\U0001f3fe"
+RAISED_FIST_DARK_SKIN_TONE = "\u270a\U0001f3ff"
+ONCOMING_FIST = "\U0001f44a"
+ONCOMING_FIST_LIGHT_SKIN_TONE = "\U0001f44a\U0001f3fb"
+ONCOMING_FIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f44a\U0001f3fc"
+ONCOMING_FIST_MEDIUM_SKIN_TONE = "\U0001f44a\U0001f3fd"
+ONCOMING_FIST_MEDIUM_DARK_SKIN_TONE = "\U0001f44a\U0001f3fe"
+ONCOMING_FIST_DARK_SKIN_TONE = "\U0001f44a\U0001f3ff"
+LEFT_FACING_FIST = "\U0001f91b"
+LEFT_FACING_FIST_LIGHT_SKIN_TONE = "\U0001f91b\U0001f3fb"
+LEFT_FACING_FIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f91b\U0001f3fc"
+LEFT_FACING_FIST_MEDIUM_SKIN_TONE = "\U0001f91b\U0001f3fd"
+LEFT_FACING_FIST_MEDIUM_DARK_SKIN_TONE = "\U0001f91b\U0001f3fe"
+LEFT_FACING_FIST_DARK_SKIN_TONE = "\U0001f91b\U0001f3ff"
+RIGHT_FACING_FIST = "\U0001f91c"
+RIGHT_FACING_FIST_LIGHT_SKIN_TONE = "\U0001f91c\U0001f3fb"
+RIGHT_FACING_FIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f91c\U0001f3fc"
+RIGHT_FACING_FIST_MEDIUM_SKIN_TONE = "\U0001f91c\U0001f3fd"
+RIGHT_FACING_FIST_MEDIUM_DARK_SKIN_TONE = "\U0001f91c\U0001f3fe"
+RIGHT_FACING_FIST_DARK_SKIN_TONE = "\U0001f91c\U0001f3ff"
+CLAPPING_HANDS = "\U0001f44f"
+CLAPPING_HANDS_LIGHT_SKIN_TONE = "\U0001f44f\U0001f3fb"
+CLAPPING_HANDS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f44f\U0001f3fc"
+CLAPPING_HANDS_MEDIUM_SKIN_TONE = "\U0001f44f\U0001f3fd"
+CLAPPING_HANDS_MEDIUM_DARK_SKIN_TONE = "\U0001f44f\U0001f3fe"
+CLAPPING_HANDS_DARK_SKIN_TONE = "\U0001f44f\U0001f3ff"
+RAISING_HANDS = "\U0001f64c"
+RAISING_HANDS_LIGHT_SKIN_TONE = "\U0001f64c\U0001f3fb"
+RAISING_HANDS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64c\U0001f3fc"
+RAISING_HANDS_MEDIUM_SKIN_TONE = "\U0001f64c\U0001f3fd"
+RAISING_HANDS_MEDIUM_DARK_SKIN_TONE = "\U0001f64c\U0001f3fe"
+RAISING_HANDS_DARK_SKIN_TONE = "\U0001f64c\U0001f3ff"
+OPEN_HANDS = "\U0001f450"
+OPEN_HANDS_LIGHT_SKIN_TONE = "\U0001f450\U0001f3fb"
+OPEN_HANDS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f450\U0001f3fc"
+OPEN_HANDS_MEDIUM_SKIN_TONE = "\U0001f450\U0001f3fd"
+OPEN_HANDS_MEDIUM_DARK_SKIN_TONE = "\U0001f450\U0001f3fe"
+OPEN_HANDS_DARK_SKIN_TONE = "\U0001f450\U0001f3ff"
+PALMS_UP_TOGETHER = "\U0001f932"
+PALMS_UP_TOGETHER_LIGHT_SKIN_TONE = "\U0001f932\U0001f3fb"
+PALMS_UP_TOGETHER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f932\U0001f3fc"
+PALMS_UP_TOGETHER_MEDIUM_SKIN_TONE = "\U0001f932\U0001f3fd"
+PALMS_UP_TOGETHER_MEDIUM_DARK_SKIN_TONE = "\U0001f932\U0001f3fe"
+PALMS_UP_TOGETHER_DARK_SKIN_TONE = "\U0001f932\U0001f3ff"
+HANDSHAKE = "\U0001f91d"
+FOLDED_HANDS = "\U0001f64f"
+FOLDED_HANDS_LIGHT_SKIN_TONE = "\U0001f64f\U0001f3fb"
+FOLDED_HANDS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64f\U0001f3fc"
+FOLDED_HANDS_MEDIUM_SKIN_TONE = "\U0001f64f\U0001f3fd"
+FOLDED_HANDS_MEDIUM_DARK_SKIN_TONE = "\U0001f64f\U0001f3fe"
+FOLDED_HANDS_DARK_SKIN_TONE = "\U0001f64f\U0001f3ff"
+WRITING_HAND = "\u270d\ufe0f"
+WRITING_HAND_LIGHT_SKIN_TONE = "\u270d\U0001f3fb"
+WRITING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\u270d\U0001f3fc"
+WRITING_HAND_MEDIUM_SKIN_TONE = "\u270d\U0001f3fd"
+WRITING_HAND_MEDIUM_DARK_SKIN_TONE = "\u270d\U0001f3fe"
+WRITING_HAND_DARK_SKIN_TONE = "\u270d\U0001f3ff"
+NAIL_POLISH = "\U0001f485"
+NAIL_POLISH_LIGHT_SKIN_TONE = "\U0001f485\U0001f3fb"
+NAIL_POLISH_MEDIUM_LIGHT_SKIN_TONE = "\U0001f485\U0001f3fc"
+NAIL_POLISH_MEDIUM_SKIN_TONE = "\U0001f485\U0001f3fd"
+NAIL_POLISH_MEDIUM_DARK_SKIN_TONE = "\U0001f485\U0001f3fe"
+NAIL_POLISH_DARK_SKIN_TONE = "\U0001f485\U0001f3ff"
+SELFIE = "\U0001f933"
+SELFIE_LIGHT_SKIN_TONE = "\U0001f933\U0001f3fb"
+SELFIE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f933\U0001f3fc"
+SELFIE_MEDIUM_SKIN_TONE = "\U0001f933\U0001f3fd"
+SELFIE_MEDIUM_DARK_SKIN_TONE = "\U0001f933\U0001f3fe"
+SELFIE_DARK_SKIN_TONE = "\U0001f933\U0001f3ff"
+FLEXED_BICEPS = "\U0001f4aa"
+FLEXED_BICEPS_LIGHT_SKIN_TONE = "\U0001f4aa\U0001f3fb"
+FLEXED_BICEPS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f4aa\U0001f3fc"
+FLEXED_BICEPS_MEDIUM_SKIN_TONE = "\U0001f4aa\U0001f3fd"
+FLEXED_BICEPS_MEDIUM_DARK_SKIN_TONE = "\U0001f4aa\U0001f3fe"
+FLEXED_BICEPS_DARK_SKIN_TONE = "\U0001f4aa\U0001f3ff"
+MECHANICAL_ARM = "\U0001f9be"
+MECHANICAL_LEG = "\U0001f9bf"
+LEG = "\U0001f9b5"
+LEG_LIGHT_SKIN_TONE = "\U0001f9b5\U0001f3fb"
+LEG_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b5\U0001f3fc"
+LEG_MEDIUM_SKIN_TONE = "\U0001f9b5\U0001f3fd"
+LEG_MEDIUM_DARK_SKIN_TONE = "\U0001f9b5\U0001f3fe"
+LEG_DARK_SKIN_TONE = "\U0001f9b5\U0001f3ff"
+FOOT = "\U0001f9b6"
+FOOT_LIGHT_SKIN_TONE = "\U0001f9b6\U0001f3fb"
+FOOT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b6\U0001f3fc"
+FOOT_MEDIUM_SKIN_TONE = "\U0001f9b6\U0001f3fd"
+FOOT_MEDIUM_DARK_SKIN_TONE = "\U0001f9b6\U0001f3fe"
+FOOT_DARK_SKIN_TONE = "\U0001f9b6\U0001f3ff"
+EAR = "\U0001f442"
+EAR_LIGHT_SKIN_TONE = "\U0001f442\U0001f3fb"
+EAR_MEDIUM_LIGHT_SKIN_TONE = "\U0001f442\U0001f3fc"
+EAR_MEDIUM_SKIN_TONE = "\U0001f442\U0001f3fd"
+EAR_MEDIUM_DARK_SKIN_TONE = "\U0001f442\U0001f3fe"
+EAR_DARK_SKIN_TONE = "\U0001f442\U0001f3ff"
+EAR_WITH_HEARING_AID = "\U0001f9bb"
+EAR_WITH_HEARING_AID_LIGHT_SKIN_TONE = "\U0001f9bb\U0001f3fb"
+EAR_WITH_HEARING_AID_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9bb\U0001f3fc"
+EAR_WITH_HEARING_AID_MEDIUM_SKIN_TONE = "\U0001f9bb\U0001f3fd"
+EAR_WITH_HEARING_AID_MEDIUM_DARK_SKIN_TONE = "\U0001f9bb\U0001f3fe"
+EAR_WITH_HEARING_AID_DARK_SKIN_TONE = "\U0001f9bb\U0001f3ff"
+NOSE = "\U0001f443"
+NOSE_LIGHT_SKIN_TONE = "\U0001f443\U0001f3fb"
+NOSE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f443\U0001f3fc"
+NOSE_MEDIUM_SKIN_TONE = "\U0001f443\U0001f3fd"
+NOSE_MEDIUM_DARK_SKIN_TONE = "\U0001f443\U0001f3fe"
+NOSE_DARK_SKIN_TONE = "\U0001f443\U0001f3ff"
+BRAIN = "\U0001f9e0"
+ANATOMICAL_HEART = "\U0001fac0"
+LUNGS = "\U0001fac1"
+TOOTH = "\U0001f9b7"
+BONE = "\U0001f9b4"
+EYES = "\U0001f440"
+EYE = "\U0001f441\ufe0f"
+TONGUE = "\U0001f445"
+MOUTH = "\U0001f444"
+BABY = "\U0001f476"
+BABY_LIGHT_SKIN_TONE = "\U0001f476\U0001f3fb"
+BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f476\U0001f3fc"
+BABY_MEDIUM_SKIN_TONE = "\U0001f476\U0001f3fd"
+BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f476\U0001f3fe"
+BABY_DARK_SKIN_TONE = "\U0001f476\U0001f3ff"
+CHILD = "\U0001f9d2"
+CHILD_LIGHT_SKIN_TONE = "\U0001f9d2\U0001f3fb"
+CHILD_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d2\U0001f3fc"
+CHILD_MEDIUM_SKIN_TONE = "\U0001f9d2\U0001f3fd"
+CHILD_MEDIUM_DARK_SKIN_TONE = "\U0001f9d2\U0001f3fe"
+CHILD_DARK_SKIN_TONE = "\U0001f9d2\U0001f3ff"
+BOY = "\U0001f466"
+BOY_LIGHT_SKIN_TONE = "\U0001f466\U0001f3fb"
+BOY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f466\U0001f3fc"
+BOY_MEDIUM_SKIN_TONE = "\U0001f466\U0001f3fd"
+BOY_MEDIUM_DARK_SKIN_TONE = "\U0001f466\U0001f3fe"
+BOY_DARK_SKIN_TONE = "\U0001f466\U0001f3ff"
+GIRL = "\U0001f467"
+GIRL_LIGHT_SKIN_TONE = "\U0001f467\U0001f3fb"
+GIRL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f467\U0001f3fc"
+GIRL_MEDIUM_SKIN_TONE = "\U0001f467\U0001f3fd"
+GIRL_MEDIUM_DARK_SKIN_TONE = "\U0001f467\U0001f3fe"
+GIRL_DARK_SKIN_TONE = "\U0001f467\U0001f3ff"
+PERSON = "\U0001f9d1"
+PERSON_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb"
+PERSON_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc"
+PERSON_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd"
+PERSON_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe"
+PERSON_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff"
+PERSON_BLOND_HAIR = "\U0001f471"
+PERSON_LIGHT_SKIN_TONE_BLOND_HAIR = "\U0001f471\U0001f3fb"
+PERSON_MEDIUM_LIGHT_SKIN_TONE_BLOND_HAIR = "\U0001f471\U0001f3fc"
+PERSON_MEDIUM_SKIN_TONE_BLOND_HAIR = "\U0001f471\U0001f3fd"
+PERSON_MEDIUM_DARK_SKIN_TONE_BLOND_HAIR = "\U0001f471\U0001f3fe"
+PERSON_DARK_SKIN_TONE_BLOND_HAIR = "\U0001f471\U0001f3ff"
+MAN = "\U0001f468"
+MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb"
+MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc"
+MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd"
+MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe"
+MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3ff"
+MAN_BEARD = "\U0001f9d4"
+MAN_LIGHT_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fb"
+MAN_MEDIUM_LIGHT_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fc"
+MAN_MEDIUM_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fd"
+MAN_MEDIUM_DARK_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fe"
+MAN_DARK_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3ff"
+MAN_RED_HAIR = "\U0001f468\u200d\U0001f9b0"
+MAN_LIGHT_SKIN_TONE_RED_HAIR = "\U0001f468\U0001f3fb\u200d\U0001f9b0"
+MAN_MEDIUM_LIGHT_SKIN_TONE_RED_HAIR = "\U0001f468\U0001f3fc\u200d\U0001f9b0"
+MAN_MEDIUM_SKIN_TONE_RED_HAIR = "\U0001f468\U0001f3fd\u200d\U0001f9b0"
+MAN_MEDIUM_DARK_SKIN_TONE_RED_HAIR = "\U0001f468\U0001f3fe\u200d\U0001f9b0"
+MAN_DARK_SKIN_TONE_RED_HAIR = "\U0001f468\U0001f3ff\u200d\U0001f9b0"
+MAN_CURLY_HAIR = "\U0001f468\u200d\U0001f9b1"
+MAN_LIGHT_SKIN_TONE_CURLY_HAIR = "\U0001f468\U0001f3fb\u200d\U0001f9b1"
+MAN_MEDIUM_LIGHT_SKIN_TONE_CURLY_HAIR = "\U0001f468\U0001f3fc\u200d\U0001f9b1"
+MAN_MEDIUM_SKIN_TONE_CURLY_HAIR = "\U0001f468\U0001f3fd\u200d\U0001f9b1"
+MAN_MEDIUM_DARK_SKIN_TONE_CURLY_HAIR = "\U0001f468\U0001f3fe\u200d\U0001f9b1"
+MAN_DARK_SKIN_TONE_CURLY_HAIR = "\U0001f468\U0001f3ff\u200d\U0001f9b1"
+MAN_WHITE_HAIR = "\U0001f468\u200d\U0001f9b3"
+MAN_LIGHT_SKIN_TONE_WHITE_HAIR = "\U0001f468\U0001f3fb\u200d\U0001f9b3"
+MAN_MEDIUM_LIGHT_SKIN_TONE_WHITE_HAIR = "\U0001f468\U0001f3fc\u200d\U0001f9b3"
+MAN_MEDIUM_SKIN_TONE_WHITE_HAIR = "\U0001f468\U0001f3fd\u200d\U0001f9b3"
+MAN_MEDIUM_DARK_SKIN_TONE_WHITE_HAIR = "\U0001f468\U0001f3fe\u200d\U0001f9b3"
+MAN_DARK_SKIN_TONE_WHITE_HAIR = "\U0001f468\U0001f3ff\u200d\U0001f9b3"
+MAN_BALD = "\U0001f468\u200d\U0001f9b2"
+MAN_LIGHT_SKIN_TONE_BALD = "\U0001f468\U0001f3fb\u200d\U0001f9b2"
+MAN_MEDIUM_LIGHT_SKIN_TONE_BALD = "\U0001f468\U0001f3fc\u200d\U0001f9b2"
+MAN_MEDIUM_SKIN_TONE_BALD = "\U0001f468\U0001f3fd\u200d\U0001f9b2"
+MAN_MEDIUM_DARK_SKIN_TONE_BALD = "\U0001f468\U0001f3fe\u200d\U0001f9b2"
+MAN_DARK_SKIN_TONE_BALD = "\U0001f468\U0001f3ff\u200d\U0001f9b2"
+WOMAN = "\U0001f469"
+WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb"
+WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc"
+WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd"
+WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe"
+WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3ff"
+WOMAN_RED_HAIR = "\U0001f469\u200d\U0001f9b0"
+WOMAN_LIGHT_SKIN_TONE_RED_HAIR = "\U0001f469\U0001f3fb\u200d\U0001f9b0"
+WOMAN_MEDIUM_LIGHT_SKIN_TONE_RED_HAIR = "\U0001f469\U0001f3fc\u200d\U0001f9b0"
+WOMAN_MEDIUM_SKIN_TONE_RED_HAIR = "\U0001f469\U0001f3fd\u200d\U0001f9b0"
+WOMAN_MEDIUM_DARK_SKIN_TONE_RED_HAIR = "\U0001f469\U0001f3fe\u200d\U0001f9b0"
+WOMAN_DARK_SKIN_TONE_RED_HAIR = "\U0001f469\U0001f3ff\u200d\U0001f9b0"
+PERSON_RED_HAIR = "\U0001f9d1\u200d\U0001f9b0"
+PERSON_LIGHT_SKIN_TONE_RED_HAIR = "\U0001f9d1\U0001f3fb\u200d\U0001f9b0"
+PERSON_MEDIUM_LIGHT_SKIN_TONE_RED_HAIR = "\U0001f9d1\U0001f3fc\u200d\U0001f9b0"
+PERSON_MEDIUM_SKIN_TONE_RED_HAIR = "\U0001f9d1\U0001f3fd\u200d\U0001f9b0"
+PERSON_MEDIUM_DARK_SKIN_TONE_RED_HAIR = "\U0001f9d1\U0001f3fe\u200d\U0001f9b0"
+PERSON_DARK_SKIN_TONE_RED_HAIR = "\U0001f9d1\U0001f3ff\u200d\U0001f9b0"
+WOMAN_CURLY_HAIR = "\U0001f469\u200d\U0001f9b1"
+WOMAN_LIGHT_SKIN_TONE_CURLY_HAIR = "\U0001f469\U0001f3fb\u200d\U0001f9b1"
+WOMAN_MEDIUM_LIGHT_SKIN_TONE_CURLY_HAIR = "\U0001f469\U0001f3fc\u200d\U0001f9b1"
+WOMAN_MEDIUM_SKIN_TONE_CURLY_HAIR = "\U0001f469\U0001f3fd\u200d\U0001f9b1"
+WOMAN_MEDIUM_DARK_SKIN_TONE_CURLY_HAIR = "\U0001f469\U0001f3fe\u200d\U0001f9b1"
+WOMAN_DARK_SKIN_TONE_CURLY_HAIR = "\U0001f469\U0001f3ff\u200d\U0001f9b1"
+PERSON_CURLY_HAIR = "\U0001f9d1\u200d\U0001f9b1"
+PERSON_LIGHT_SKIN_TONE_CURLY_HAIR = "\U0001f9d1\U0001f3fb\u200d\U0001f9b1"
+PERSON_MEDIUM_LIGHT_SKIN_TONE_CURLY_HAIR = "\U0001f9d1\U0001f3fc\u200d\U0001f9b1"
+PERSON_MEDIUM_SKIN_TONE_CURLY_HAIR = "\U0001f9d1\U0001f3fd\u200d\U0001f9b1"
+PERSON_MEDIUM_DARK_SKIN_TONE_CURLY_HAIR = "\U0001f9d1\U0001f3fe\u200d\U0001f9b1"
+PERSON_DARK_SKIN_TONE_CURLY_HAIR = "\U0001f9d1\U0001f3ff\u200d\U0001f9b1"
+WOMAN_WHITE_HAIR = "\U0001f469\u200d\U0001f9b3"
+WOMAN_LIGHT_SKIN_TONE_WHITE_HAIR = "\U0001f469\U0001f3fb\u200d\U0001f9b3"
+WOMAN_MEDIUM_LIGHT_SKIN_TONE_WHITE_HAIR = "\U0001f469\U0001f3fc\u200d\U0001f9b3"
+WOMAN_MEDIUM_SKIN_TONE_WHITE_HAIR = "\U0001f469\U0001f3fd\u200d\U0001f9b3"
+WOMAN_MEDIUM_DARK_SKIN_TONE_WHITE_HAIR = "\U0001f469\U0001f3fe\u200d\U0001f9b3"
+WOMAN_DARK_SKIN_TONE_WHITE_HAIR = "\U0001f469\U0001f3ff\u200d\U0001f9b3"
+PERSON_WHITE_HAIR = "\U0001f9d1\u200d\U0001f9b3"
+PERSON_LIGHT_SKIN_TONE_WHITE_HAIR = "\U0001f9d1\U0001f3fb\u200d\U0001f9b3"
+PERSON_MEDIUM_LIGHT_SKIN_TONE_WHITE_HAIR = "\U0001f9d1\U0001f3fc\u200d\U0001f9b3"
+PERSON_MEDIUM_SKIN_TONE_WHITE_HAIR = "\U0001f9d1\U0001f3fd\u200d\U0001f9b3"
+PERSON_MEDIUM_DARK_SKIN_TONE_WHITE_HAIR = "\U0001f9d1\U0001f3fe\u200d\U0001f9b3"
+PERSON_DARK_SKIN_TONE_WHITE_HAIR = "\U0001f9d1\U0001f3ff\u200d\U0001f9b3"
+WOMAN_BALD = "\U0001f469\u200d\U0001f9b2"
+WOMAN_LIGHT_SKIN_TONE_BALD = "\U0001f469\U0001f3fb\u200d\U0001f9b2"
+WOMAN_MEDIUM_LIGHT_SKIN_TONE_BALD = "\U0001f469\U0001f3fc\u200d\U0001f9b2"
+WOMAN_MEDIUM_SKIN_TONE_BALD = "\U0001f469\U0001f3fd\u200d\U0001f9b2"
+WOMAN_MEDIUM_DARK_SKIN_TONE_BALD = "\U0001f469\U0001f3fe\u200d\U0001f9b2"
+WOMAN_DARK_SKIN_TONE_BALD = "\U0001f469\U0001f3ff\u200d\U0001f9b2"
+PERSON_BALD = "\U0001f9d1\u200d\U0001f9b2"
+PERSON_LIGHT_SKIN_TONE_BALD = "\U0001f9d1\U0001f3fb\u200d\U0001f9b2"
+PERSON_MEDIUM_LIGHT_SKIN_TONE_BALD = "\U0001f9d1\U0001f3fc\u200d\U0001f9b2"
+PERSON_MEDIUM_SKIN_TONE_BALD = "\U0001f9d1\U0001f3fd\u200d\U0001f9b2"
+PERSON_MEDIUM_DARK_SKIN_TONE_BALD = "\U0001f9d1\U0001f3fe\u200d\U0001f9b2"
+PERSON_DARK_SKIN_TONE_BALD = "\U0001f9d1\U0001f3ff\u200d\U0001f9b2"
+WOMAN_BLOND_HAIR = "\U0001f471\u200d\u2640\ufe0f"
+WOMAN_LIGHT_SKIN_TONE_BLOND_HAIR = "\U0001f471\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_MEDIUM_LIGHT_SKIN_TONE_BLOND_HAIR = "\U0001f471\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_MEDIUM_SKIN_TONE_BLOND_HAIR = "\U0001f471\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_MEDIUM_DARK_SKIN_TONE_BLOND_HAIR = "\U0001f471\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_DARK_SKIN_TONE_BLOND_HAIR = "\U0001f471\U0001f3ff\u200d\u2640\ufe0f"
+MAN_BLOND_HAIR = "\U0001f471\u200d\u2642\ufe0f"
+MAN_LIGHT_SKIN_TONE_BLOND_HAIR = "\U0001f471\U0001f3fb\u200d\u2642\ufe0f"
+MAN_MEDIUM_LIGHT_SKIN_TONE_BLOND_HAIR = "\U0001f471\U0001f3fc\u200d\u2642\ufe0f"
+MAN_MEDIUM_SKIN_TONE_BLOND_HAIR = "\U0001f471\U0001f3fd\u200d\u2642\ufe0f"
+MAN_MEDIUM_DARK_SKIN_TONE_BLOND_HAIR = "\U0001f471\U0001f3fe\u200d\u2642\ufe0f"
+MAN_DARK_SKIN_TONE_BLOND_HAIR = "\U0001f471\U0001f3ff\u200d\u2642\ufe0f"
+OLDER_PERSON = "\U0001f9d3"
+OLDER_PERSON_LIGHT_SKIN_TONE = "\U0001f9d3\U0001f3fb"
+OLDER_PERSON_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d3\U0001f3fc"
+OLDER_PERSON_MEDIUM_SKIN_TONE = "\U0001f9d3\U0001f3fd"
+OLDER_PERSON_MEDIUM_DARK_SKIN_TONE = "\U0001f9d3\U0001f3fe"
+OLDER_PERSON_DARK_SKIN_TONE = "\U0001f9d3\U0001f3ff"
+OLD_MAN = "\U0001f474"
+OLD_MAN_LIGHT_SKIN_TONE = "\U0001f474\U0001f3fb"
+OLD_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f474\U0001f3fc"
+OLD_MAN_MEDIUM_SKIN_TONE = "\U0001f474\U0001f3fd"
+OLD_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f474\U0001f3fe"
+OLD_MAN_DARK_SKIN_TONE = "\U0001f474\U0001f3ff"
+OLD_WOMAN = "\U0001f475"
+OLD_WOMAN_LIGHT_SKIN_TONE = "\U0001f475\U0001f3fb"
+OLD_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f475\U0001f3fc"
+OLD_WOMAN_MEDIUM_SKIN_TONE = "\U0001f475\U0001f3fd"
+OLD_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f475\U0001f3fe"
+OLD_WOMAN_DARK_SKIN_TONE = "\U0001f475\U0001f3ff"
+PERSON_FROWNING = "\U0001f64d"
+PERSON_FROWNING_LIGHT_SKIN_TONE = "\U0001f64d\U0001f3fb"
+PERSON_FROWNING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64d\U0001f3fc"
+PERSON_FROWNING_MEDIUM_SKIN_TONE = "\U0001f64d\U0001f3fd"
+PERSON_FROWNING_MEDIUM_DARK_SKIN_TONE = "\U0001f64d\U0001f3fe"
+PERSON_FROWNING_DARK_SKIN_TONE = "\U0001f64d\U0001f3ff"
+MAN_FROWNING = "\U0001f64d\u200d\u2642\ufe0f"
+MAN_FROWNING_LIGHT_SKIN_TONE = "\U0001f64d\U0001f3fb\u200d\u2642\ufe0f"
+MAN_FROWNING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64d\U0001f3fc\u200d\u2642\ufe0f"
+MAN_FROWNING_MEDIUM_SKIN_TONE = "\U0001f64d\U0001f3fd\u200d\u2642\ufe0f"
+MAN_FROWNING_MEDIUM_DARK_SKIN_TONE = "\U0001f64d\U0001f3fe\u200d\u2642\ufe0f"
+MAN_FROWNING_DARK_SKIN_TONE = "\U0001f64d\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_FROWNING = "\U0001f64d\u200d\u2640\ufe0f"
+WOMAN_FROWNING_LIGHT_SKIN_TONE = "\U0001f64d\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_FROWNING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64d\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_FROWNING_MEDIUM_SKIN_TONE = "\U0001f64d\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_FROWNING_MEDIUM_DARK_SKIN_TONE = "\U0001f64d\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_FROWNING_DARK_SKIN_TONE = "\U0001f64d\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_POUTING = "\U0001f64e"
+PERSON_POUTING_LIGHT_SKIN_TONE = "\U0001f64e\U0001f3fb"
+PERSON_POUTING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64e\U0001f3fc"
+PERSON_POUTING_MEDIUM_SKIN_TONE = "\U0001f64e\U0001f3fd"
+PERSON_POUTING_MEDIUM_DARK_SKIN_TONE = "\U0001f64e\U0001f3fe"
+PERSON_POUTING_DARK_SKIN_TONE = "\U0001f64e\U0001f3ff"
+MAN_POUTING = "\U0001f64e\u200d\u2642\ufe0f"
+MAN_POUTING_LIGHT_SKIN_TONE = "\U0001f64e\U0001f3fb\u200d\u2642\ufe0f"
+MAN_POUTING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64e\U0001f3fc\u200d\u2642\ufe0f"
+MAN_POUTING_MEDIUM_SKIN_TONE = "\U0001f64e\U0001f3fd\u200d\u2642\ufe0f"
+MAN_POUTING_MEDIUM_DARK_SKIN_TONE = "\U0001f64e\U0001f3fe\u200d\u2642\ufe0f"
+MAN_POUTING_DARK_SKIN_TONE = "\U0001f64e\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_POUTING = "\U0001f64e\u200d\u2640\ufe0f"
+WOMAN_POUTING_LIGHT_SKIN_TONE = "\U0001f64e\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_POUTING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64e\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_POUTING_MEDIUM_SKIN_TONE = "\U0001f64e\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_POUTING_MEDIUM_DARK_SKIN_TONE = "\U0001f64e\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_POUTING_DARK_SKIN_TONE = "\U0001f64e\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_GESTURING_NO = "\U0001f645"
+PERSON_GESTURING_NO_LIGHT_SKIN_TONE = "\U0001f645\U0001f3fb"
+PERSON_GESTURING_NO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f645\U0001f3fc"
+PERSON_GESTURING_NO_MEDIUM_SKIN_TONE = "\U0001f645\U0001f3fd"
+PERSON_GESTURING_NO_MEDIUM_DARK_SKIN_TONE = "\U0001f645\U0001f3fe"
+PERSON_GESTURING_NO_DARK_SKIN_TONE = "\U0001f645\U0001f3ff"
+MAN_GESTURING_NO = "\U0001f645\u200d\u2642\ufe0f"
+MAN_GESTURING_NO_LIGHT_SKIN_TONE = "\U0001f645\U0001f3fb\u200d\u2642\ufe0f"
+MAN_GESTURING_NO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f645\U0001f3fc\u200d\u2642\ufe0f"
+MAN_GESTURING_NO_MEDIUM_SKIN_TONE = "\U0001f645\U0001f3fd\u200d\u2642\ufe0f"
+MAN_GESTURING_NO_MEDIUM_DARK_SKIN_TONE = "\U0001f645\U0001f3fe\u200d\u2642\ufe0f"
+MAN_GESTURING_NO_DARK_SKIN_TONE = "\U0001f645\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_GESTURING_NO = "\U0001f645\u200d\u2640\ufe0f"
+WOMAN_GESTURING_NO_LIGHT_SKIN_TONE = "\U0001f645\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_GESTURING_NO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f645\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_GESTURING_NO_MEDIUM_SKIN_TONE = "\U0001f645\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_GESTURING_NO_MEDIUM_DARK_SKIN_TONE = "\U0001f645\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_GESTURING_NO_DARK_SKIN_TONE = "\U0001f645\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_GESTURING_OK = "\U0001f646"
+PERSON_GESTURING_OK_LIGHT_SKIN_TONE = "\U0001f646\U0001f3fb"
+PERSON_GESTURING_OK_MEDIUM_LIGHT_SKIN_TONE = "\U0001f646\U0001f3fc"
+PERSON_GESTURING_OK_MEDIUM_SKIN_TONE = "\U0001f646\U0001f3fd"
+PERSON_GESTURING_OK_MEDIUM_DARK_SKIN_TONE = "\U0001f646\U0001f3fe"
+PERSON_GESTURING_OK_DARK_SKIN_TONE = "\U0001f646\U0001f3ff"
+MAN_GESTURING_OK = "\U0001f646\u200d\u2642\ufe0f"
+MAN_GESTURING_OK_LIGHT_SKIN_TONE = "\U0001f646\U0001f3fb\u200d\u2642\ufe0f"
+MAN_GESTURING_OK_MEDIUM_LIGHT_SKIN_TONE = "\U0001f646\U0001f3fc\u200d\u2642\ufe0f"
+MAN_GESTURING_OK_MEDIUM_SKIN_TONE = "\U0001f646\U0001f3fd\u200d\u2642\ufe0f"
+MAN_GESTURING_OK_MEDIUM_DARK_SKIN_TONE = "\U0001f646\U0001f3fe\u200d\u2642\ufe0f"
+MAN_GESTURING_OK_DARK_SKIN_TONE = "\U0001f646\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_GESTURING_OK = "\U0001f646\u200d\u2640\ufe0f"
+WOMAN_GESTURING_OK_LIGHT_SKIN_TONE = "\U0001f646\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_GESTURING_OK_MEDIUM_LIGHT_SKIN_TONE = "\U0001f646\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_GESTURING_OK_MEDIUM_SKIN_TONE = "\U0001f646\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_GESTURING_OK_MEDIUM_DARK_SKIN_TONE = "\U0001f646\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_GESTURING_OK_DARK_SKIN_TONE = "\U0001f646\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_TIPPING_HAND = "\U0001f481"
+PERSON_TIPPING_HAND_LIGHT_SKIN_TONE = "\U0001f481\U0001f3fb"
+PERSON_TIPPING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f481\U0001f3fc"
+PERSON_TIPPING_HAND_MEDIUM_SKIN_TONE = "\U0001f481\U0001f3fd"
+PERSON_TIPPING_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f481\U0001f3fe"
+PERSON_TIPPING_HAND_DARK_SKIN_TONE = "\U0001f481\U0001f3ff"
+MAN_TIPPING_HAND = "\U0001f481\u200d\u2642\ufe0f"
+MAN_TIPPING_HAND_LIGHT_SKIN_TONE = "\U0001f481\U0001f3fb\u200d\u2642\ufe0f"
+MAN_TIPPING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f481\U0001f3fc\u200d\u2642\ufe0f"
+MAN_TIPPING_HAND_MEDIUM_SKIN_TONE = "\U0001f481\U0001f3fd\u200d\u2642\ufe0f"
+MAN_TIPPING_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f481\U0001f3fe\u200d\u2642\ufe0f"
+MAN_TIPPING_HAND_DARK_SKIN_TONE = "\U0001f481\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_TIPPING_HAND = "\U0001f481\u200d\u2640\ufe0f"
+WOMAN_TIPPING_HAND_LIGHT_SKIN_TONE = "\U0001f481\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_TIPPING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f481\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_TIPPING_HAND_MEDIUM_SKIN_TONE = "\U0001f481\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_TIPPING_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f481\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_TIPPING_HAND_DARK_SKIN_TONE = "\U0001f481\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_RAISING_HAND = "\U0001f64b"
+PERSON_RAISING_HAND_LIGHT_SKIN_TONE = "\U0001f64b\U0001f3fb"
+PERSON_RAISING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64b\U0001f3fc"
+PERSON_RAISING_HAND_MEDIUM_SKIN_TONE = "\U0001f64b\U0001f3fd"
+PERSON_RAISING_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f64b\U0001f3fe"
+PERSON_RAISING_HAND_DARK_SKIN_TONE = "\U0001f64b\U0001f3ff"
+MAN_RAISING_HAND = "\U0001f64b\u200d\u2642\ufe0f"
+MAN_RAISING_HAND_LIGHT_SKIN_TONE = "\U0001f64b\U0001f3fb\u200d\u2642\ufe0f"
+MAN_RAISING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64b\U0001f3fc\u200d\u2642\ufe0f"
+MAN_RAISING_HAND_MEDIUM_SKIN_TONE = "\U0001f64b\U0001f3fd\u200d\u2642\ufe0f"
+MAN_RAISING_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f64b\U0001f3fe\u200d\u2642\ufe0f"
+MAN_RAISING_HAND_DARK_SKIN_TONE = "\U0001f64b\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_RAISING_HAND = "\U0001f64b\u200d\u2640\ufe0f"
+WOMAN_RAISING_HAND_LIGHT_SKIN_TONE = "\U0001f64b\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_RAISING_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001f64b\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_RAISING_HAND_MEDIUM_SKIN_TONE = "\U0001f64b\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_RAISING_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001f64b\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_RAISING_HAND_DARK_SKIN_TONE = "\U0001f64b\U0001f3ff\u200d\u2640\ufe0f"
+DEAF_PERSON = "\U0001f9cf"
+DEAF_PERSON_LIGHT_SKIN_TONE = "\U0001f9cf\U0001f3fb"
+DEAF_PERSON_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9cf\U0001f3fc"
+DEAF_PERSON_MEDIUM_SKIN_TONE = "\U0001f9cf\U0001f3fd"
+DEAF_PERSON_MEDIUM_DARK_SKIN_TONE = "\U0001f9cf\U0001f3fe"
+DEAF_PERSON_DARK_SKIN_TONE = "\U0001f9cf\U0001f3ff"
+DEAF_MAN = "\U0001f9cf\u200d\u2642\ufe0f"
+DEAF_MAN_LIGHT_SKIN_TONE = "\U0001f9cf\U0001f3fb\u200d\u2642\ufe0f"
+DEAF_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9cf\U0001f3fc\u200d\u2642\ufe0f"
+DEAF_MAN_MEDIUM_SKIN_TONE = "\U0001f9cf\U0001f3fd\u200d\u2642\ufe0f"
+DEAF_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f9cf\U0001f3fe\u200d\u2642\ufe0f"
+DEAF_MAN_DARK_SKIN_TONE = "\U0001f9cf\U0001f3ff\u200d\u2642\ufe0f"
+DEAF_WOMAN = "\U0001f9cf\u200d\u2640\ufe0f"
+DEAF_WOMAN_LIGHT_SKIN_TONE = "\U0001f9cf\U0001f3fb\u200d\u2640\ufe0f"
+DEAF_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9cf\U0001f3fc\u200d\u2640\ufe0f"
+DEAF_WOMAN_MEDIUM_SKIN_TONE = "\U0001f9cf\U0001f3fd\u200d\u2640\ufe0f"
+DEAF_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f9cf\U0001f3fe\u200d\u2640\ufe0f"
+DEAF_WOMAN_DARK_SKIN_TONE = "\U0001f9cf\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_BOWING = "\U0001f647"
+PERSON_BOWING_LIGHT_SKIN_TONE = "\U0001f647\U0001f3fb"
+PERSON_BOWING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f647\U0001f3fc"
+PERSON_BOWING_MEDIUM_SKIN_TONE = "\U0001f647\U0001f3fd"
+PERSON_BOWING_MEDIUM_DARK_SKIN_TONE = "\U0001f647\U0001f3fe"
+PERSON_BOWING_DARK_SKIN_TONE = "\U0001f647\U0001f3ff"
+MAN_BOWING = "\U0001f647\u200d\u2642\ufe0f"
+MAN_BOWING_LIGHT_SKIN_TONE = "\U0001f647\U0001f3fb\u200d\u2642\ufe0f"
+MAN_BOWING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f647\U0001f3fc\u200d\u2642\ufe0f"
+MAN_BOWING_MEDIUM_SKIN_TONE = "\U0001f647\U0001f3fd\u200d\u2642\ufe0f"
+MAN_BOWING_MEDIUM_DARK_SKIN_TONE = "\U0001f647\U0001f3fe\u200d\u2642\ufe0f"
+MAN_BOWING_DARK_SKIN_TONE = "\U0001f647\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_BOWING = "\U0001f647\u200d\u2640\ufe0f"
+WOMAN_BOWING_LIGHT_SKIN_TONE = "\U0001f647\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_BOWING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f647\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_BOWING_MEDIUM_SKIN_TONE = "\U0001f647\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_BOWING_MEDIUM_DARK_SKIN_TONE = "\U0001f647\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_BOWING_DARK_SKIN_TONE = "\U0001f647\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_FACEPALMING = "\U0001f926"
+PERSON_FACEPALMING_LIGHT_SKIN_TONE = "\U0001f926\U0001f3fb"
+PERSON_FACEPALMING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f926\U0001f3fc"
+PERSON_FACEPALMING_MEDIUM_SKIN_TONE = "\U0001f926\U0001f3fd"
+PERSON_FACEPALMING_MEDIUM_DARK_SKIN_TONE = "\U0001f926\U0001f3fe"
+PERSON_FACEPALMING_DARK_SKIN_TONE = "\U0001f926\U0001f3ff"
+MAN_FACEPALMING = "\U0001f926\u200d\u2642\ufe0f"
+MAN_FACEPALMING_LIGHT_SKIN_TONE = "\U0001f926\U0001f3fb\u200d\u2642\ufe0f"
+MAN_FACEPALMING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f926\U0001f3fc\u200d\u2642\ufe0f"
+MAN_FACEPALMING_MEDIUM_SKIN_TONE = "\U0001f926\U0001f3fd\u200d\u2642\ufe0f"
+MAN_FACEPALMING_MEDIUM_DARK_SKIN_TONE = "\U0001f926\U0001f3fe\u200d\u2642\ufe0f"
+MAN_FACEPALMING_DARK_SKIN_TONE = "\U0001f926\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_FACEPALMING = "\U0001f926\u200d\u2640\ufe0f"
+WOMAN_FACEPALMING_LIGHT_SKIN_TONE = "\U0001f926\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_FACEPALMING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f926\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_FACEPALMING_MEDIUM_SKIN_TONE = "\U0001f926\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_FACEPALMING_MEDIUM_DARK_SKIN_TONE = "\U0001f926\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_FACEPALMING_DARK_SKIN_TONE = "\U0001f926\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_SHRUGGING = "\U0001f937"
+PERSON_SHRUGGING_LIGHT_SKIN_TONE = "\U0001f937\U0001f3fb"
+PERSON_SHRUGGING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f937\U0001f3fc"
+PERSON_SHRUGGING_MEDIUM_SKIN_TONE = "\U0001f937\U0001f3fd"
+PERSON_SHRUGGING_MEDIUM_DARK_SKIN_TONE = "\U0001f937\U0001f3fe"
+PERSON_SHRUGGING_DARK_SKIN_TONE = "\U0001f937\U0001f3ff"
+MAN_SHRUGGING = "\U0001f937\u200d\u2642\ufe0f"
+MAN_SHRUGGING_LIGHT_SKIN_TONE = "\U0001f937\U0001f3fb\u200d\u2642\ufe0f"
+MAN_SHRUGGING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f937\U0001f3fc\u200d\u2642\ufe0f"
+MAN_SHRUGGING_MEDIUM_SKIN_TONE = "\U0001f937\U0001f3fd\u200d\u2642\ufe0f"
+MAN_SHRUGGING_MEDIUM_DARK_SKIN_TONE = "\U0001f937\U0001f3fe\u200d\u2642\ufe0f"
+MAN_SHRUGGING_DARK_SKIN_TONE = "\U0001f937\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_SHRUGGING = "\U0001f937\u200d\u2640\ufe0f"
+WOMAN_SHRUGGING_LIGHT_SKIN_TONE = "\U0001f937\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_SHRUGGING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f937\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_SHRUGGING_MEDIUM_SKIN_TONE = "\U0001f937\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_SHRUGGING_MEDIUM_DARK_SKIN_TONE = "\U0001f937\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_SHRUGGING_DARK_SKIN_TONE = "\U0001f937\U0001f3ff\u200d\u2640\ufe0f"
+HEALTH_WORKER = "\U0001f9d1\u200d\u2695\ufe0f"
+HEALTH_WORKER_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\u2695\ufe0f"
+HEALTH_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\u2695\ufe0f"
+HEALTH_WORKER_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\u2695\ufe0f"
+HEALTH_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\u2695\ufe0f"
+HEALTH_WORKER_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\u2695\ufe0f"
+MAN_HEALTH_WORKER = "\U0001f468\u200d\u2695\ufe0f"
+MAN_HEALTH_WORKER_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2695\ufe0f"
+MAN_HEALTH_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2695\ufe0f"
+MAN_HEALTH_WORKER_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2695\ufe0f"
+MAN_HEALTH_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2695\ufe0f"
+MAN_HEALTH_WORKER_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2695\ufe0f"
+WOMAN_HEALTH_WORKER = "\U0001f469\u200d\u2695\ufe0f"
+WOMAN_HEALTH_WORKER_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2695\ufe0f"
+WOMAN_HEALTH_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2695\ufe0f"
+WOMAN_HEALTH_WORKER_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2695\ufe0f"
+WOMAN_HEALTH_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2695\ufe0f"
+WOMAN_HEALTH_WORKER_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2695\ufe0f"
+STUDENT = "\U0001f9d1\u200d\U0001f393"
+STUDENT_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f393"
+STUDENT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f393"
+STUDENT_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f393"
+STUDENT_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f393"
+STUDENT_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f393"
+MAN_STUDENT = "\U0001f468\u200d\U0001f393"
+MAN_STUDENT_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f393"
+MAN_STUDENT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f393"
+MAN_STUDENT_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f393"
+MAN_STUDENT_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f393"
+MAN_STUDENT_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f393"
+WOMAN_STUDENT = "\U0001f469\u200d\U0001f393"
+WOMAN_STUDENT_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f393"
+WOMAN_STUDENT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f393"
+WOMAN_STUDENT_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f393"
+WOMAN_STUDENT_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f393"
+WOMAN_STUDENT_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f393"
+TEACHER = "\U0001f9d1\u200d\U0001f3eb"
+TEACHER_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f3eb"
+TEACHER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f3eb"
+TEACHER_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f3eb"
+TEACHER_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f3eb"
+TEACHER_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f3eb"
+MAN_TEACHER = "\U0001f468\u200d\U0001f3eb"
+MAN_TEACHER_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f3eb"
+MAN_TEACHER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f3eb"
+MAN_TEACHER_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f3eb"
+MAN_TEACHER_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f3eb"
+MAN_TEACHER_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f3eb"
+WOMAN_TEACHER = "\U0001f469\u200d\U0001f3eb"
+WOMAN_TEACHER_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f3eb"
+WOMAN_TEACHER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f3eb"
+WOMAN_TEACHER_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f3eb"
+WOMAN_TEACHER_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f3eb"
+WOMAN_TEACHER_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f3eb"
+JUDGE = "\U0001f9d1\u200d\u2696\ufe0f"
+JUDGE_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\u2696\ufe0f"
+JUDGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\u2696\ufe0f"
+JUDGE_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\u2696\ufe0f"
+JUDGE_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\u2696\ufe0f"
+JUDGE_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\u2696\ufe0f"
+MAN_JUDGE = "\U0001f468\u200d\u2696\ufe0f"
+MAN_JUDGE_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2696\ufe0f"
+MAN_JUDGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2696\ufe0f"
+MAN_JUDGE_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2696\ufe0f"
+MAN_JUDGE_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2696\ufe0f"
+MAN_JUDGE_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2696\ufe0f"
+WOMAN_JUDGE = "\U0001f469\u200d\u2696\ufe0f"
+WOMAN_JUDGE_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2696\ufe0f"
+WOMAN_JUDGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2696\ufe0f"
+WOMAN_JUDGE_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2696\ufe0f"
+WOMAN_JUDGE_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2696\ufe0f"
+WOMAN_JUDGE_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2696\ufe0f"
+FARMER = "\U0001f9d1\u200d\U0001f33e"
+FARMER_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f33e"
+FARMER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f33e"
+FARMER_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f33e"
+FARMER_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f33e"
+FARMER_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f33e"
+MAN_FARMER = "\U0001f468\u200d\U0001f33e"
+MAN_FARMER_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f33e"
+MAN_FARMER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f33e"
+MAN_FARMER_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f33e"
+MAN_FARMER_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f33e"
+MAN_FARMER_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f33e"
+WOMAN_FARMER = "\U0001f469\u200d\U0001f33e"
+WOMAN_FARMER_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f33e"
+WOMAN_FARMER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f33e"
+WOMAN_FARMER_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f33e"
+WOMAN_FARMER_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f33e"
+WOMAN_FARMER_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f33e"
+COOK = "\U0001f9d1\u200d\U0001f373"
+COOK_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f373"
+COOK_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f373"
+COOK_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f373"
+COOK_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f373"
+COOK_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f373"
+MAN_COOK = "\U0001f468\u200d\U0001f373"
+MAN_COOK_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f373"
+MAN_COOK_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f373"
+MAN_COOK_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f373"
+MAN_COOK_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f373"
+MAN_COOK_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f373"
+WOMAN_COOK = "\U0001f469\u200d\U0001f373"
+WOMAN_COOK_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f373"
+WOMAN_COOK_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f373"
+WOMAN_COOK_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f373"
+WOMAN_COOK_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f373"
+WOMAN_COOK_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f373"
+MECHANIC = "\U0001f9d1\u200d\U0001f527"
+MECHANIC_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f527"
+MECHANIC_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f527"
+MECHANIC_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f527"
+MECHANIC_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f527"
+MECHANIC_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f527"
+MAN_MECHANIC = "\U0001f468\u200d\U0001f527"
+MAN_MECHANIC_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f527"
+MAN_MECHANIC_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f527"
+MAN_MECHANIC_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f527"
+MAN_MECHANIC_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f527"
+MAN_MECHANIC_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f527"
+WOMAN_MECHANIC = "\U0001f469\u200d\U0001f527"
+WOMAN_MECHANIC_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f527"
+WOMAN_MECHANIC_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f527"
+WOMAN_MECHANIC_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f527"
+WOMAN_MECHANIC_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f527"
+WOMAN_MECHANIC_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f527"
+FACTORY_WORKER = "\U0001f9d1\u200d\U0001f3ed"
+FACTORY_WORKER_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f3ed"
+FACTORY_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f3ed"
+FACTORY_WORKER_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f3ed"
+FACTORY_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f3ed"
+FACTORY_WORKER_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f3ed"
+MAN_FACTORY_WORKER = "\U0001f468\u200d\U0001f3ed"
+MAN_FACTORY_WORKER_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f3ed"
+MAN_FACTORY_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f3ed"
+MAN_FACTORY_WORKER_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f3ed"
+MAN_FACTORY_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f3ed"
+MAN_FACTORY_WORKER_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f3ed"
+WOMAN_FACTORY_WORKER = "\U0001f469\u200d\U0001f3ed"
+WOMAN_FACTORY_WORKER_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f3ed"
+WOMAN_FACTORY_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f3ed"
+WOMAN_FACTORY_WORKER_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f3ed"
+WOMAN_FACTORY_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f3ed"
+WOMAN_FACTORY_WORKER_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f3ed"
+OFFICE_WORKER = "\U0001f9d1\u200d\U0001f4bc"
+OFFICE_WORKER_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f4bc"
+OFFICE_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f4bc"
+OFFICE_WORKER_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f4bc"
+OFFICE_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f4bc"
+OFFICE_WORKER_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f4bc"
+MAN_OFFICE_WORKER = "\U0001f468\u200d\U0001f4bc"
+MAN_OFFICE_WORKER_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f4bc"
+MAN_OFFICE_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f4bc"
+MAN_OFFICE_WORKER_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f4bc"
+MAN_OFFICE_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f4bc"
+MAN_OFFICE_WORKER_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f4bc"
+WOMAN_OFFICE_WORKER = "\U0001f469\u200d\U0001f4bc"
+WOMAN_OFFICE_WORKER_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f4bc"
+WOMAN_OFFICE_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f4bc"
+WOMAN_OFFICE_WORKER_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f4bc"
+WOMAN_OFFICE_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f4bc"
+WOMAN_OFFICE_WORKER_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f4bc"
+SCIENTIST = "\U0001f9d1\u200d\U0001f52c"
+SCIENTIST_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f52c"
+SCIENTIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f52c"
+SCIENTIST_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f52c"
+SCIENTIST_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f52c"
+SCIENTIST_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f52c"
+MAN_SCIENTIST = "\U0001f468\u200d\U0001f52c"
+MAN_SCIENTIST_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f52c"
+MAN_SCIENTIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f52c"
+MAN_SCIENTIST_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f52c"
+MAN_SCIENTIST_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f52c"
+MAN_SCIENTIST_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f52c"
+WOMAN_SCIENTIST = "\U0001f469\u200d\U0001f52c"
+WOMAN_SCIENTIST_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f52c"
+WOMAN_SCIENTIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f52c"
+WOMAN_SCIENTIST_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f52c"
+WOMAN_SCIENTIST_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f52c"
+WOMAN_SCIENTIST_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f52c"
+TECHNOLOGIST = "\U0001f9d1\u200d\U0001f4bb"
+TECHNOLOGIST_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f4bb"
+TECHNOLOGIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f4bb"
+TECHNOLOGIST_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f4bb"
+TECHNOLOGIST_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f4bb"
+TECHNOLOGIST_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f4bb"
+MAN_TECHNOLOGIST = "\U0001f468\u200d\U0001f4bb"
+MAN_TECHNOLOGIST_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f4bb"
+MAN_TECHNOLOGIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f4bb"
+MAN_TECHNOLOGIST_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f4bb"
+MAN_TECHNOLOGIST_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f4bb"
+MAN_TECHNOLOGIST_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f4bb"
+WOMAN_TECHNOLOGIST = "\U0001f469\u200d\U0001f4bb"
+WOMAN_TECHNOLOGIST_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f4bb"
+WOMAN_TECHNOLOGIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f4bb"
+WOMAN_TECHNOLOGIST_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f4bb"
+WOMAN_TECHNOLOGIST_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f4bb"
+WOMAN_TECHNOLOGIST_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f4bb"
+SINGER = "\U0001f9d1\u200d\U0001f3a4"
+SINGER_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f3a4"
+SINGER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f3a4"
+SINGER_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f3a4"
+SINGER_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f3a4"
+SINGER_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f3a4"
+MAN_SINGER = "\U0001f468\u200d\U0001f3a4"
+MAN_SINGER_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f3a4"
+MAN_SINGER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f3a4"
+MAN_SINGER_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f3a4"
+MAN_SINGER_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f3a4"
+MAN_SINGER_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f3a4"
+WOMAN_SINGER = "\U0001f469\u200d\U0001f3a4"
+WOMAN_SINGER_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f3a4"
+WOMAN_SINGER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f3a4"
+WOMAN_SINGER_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f3a4"
+WOMAN_SINGER_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f3a4"
+WOMAN_SINGER_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f3a4"
+ARTIST = "\U0001f9d1\u200d\U0001f3a8"
+ARTIST_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f3a8"
+ARTIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f3a8"
+ARTIST_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f3a8"
+ARTIST_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f3a8"
+ARTIST_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f3a8"
+MAN_ARTIST = "\U0001f468\u200d\U0001f3a8"
+MAN_ARTIST_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f3a8"
+MAN_ARTIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f3a8"
+MAN_ARTIST_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f3a8"
+MAN_ARTIST_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f3a8"
+MAN_ARTIST_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f3a8"
+WOMAN_ARTIST = "\U0001f469\u200d\U0001f3a8"
+WOMAN_ARTIST_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f3a8"
+WOMAN_ARTIST_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f3a8"
+WOMAN_ARTIST_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f3a8"
+WOMAN_ARTIST_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f3a8"
+WOMAN_ARTIST_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f3a8"
+PILOT = "\U0001f9d1\u200d\u2708\ufe0f"
+PILOT_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\u2708\ufe0f"
+PILOT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\u2708\ufe0f"
+PILOT_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\u2708\ufe0f"
+PILOT_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\u2708\ufe0f"
+PILOT_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\u2708\ufe0f"
+MAN_PILOT = "\U0001f468\u200d\u2708\ufe0f"
+MAN_PILOT_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2708\ufe0f"
+MAN_PILOT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2708\ufe0f"
+MAN_PILOT_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2708\ufe0f"
+MAN_PILOT_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2708\ufe0f"
+MAN_PILOT_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2708\ufe0f"
+WOMAN_PILOT = "\U0001f469\u200d\u2708\ufe0f"
+WOMAN_PILOT_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2708\ufe0f"
+WOMAN_PILOT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2708\ufe0f"
+WOMAN_PILOT_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2708\ufe0f"
+WOMAN_PILOT_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2708\ufe0f"
+WOMAN_PILOT_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2708\ufe0f"
+ASTRONAUT = "\U0001f9d1\u200d\U0001f680"
+ASTRONAUT_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f680"
+ASTRONAUT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f680"
+ASTRONAUT_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f680"
+ASTRONAUT_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f680"
+ASTRONAUT_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f680"
+MAN_ASTRONAUT = "\U0001f468\u200d\U0001f680"
+MAN_ASTRONAUT_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f680"
+MAN_ASTRONAUT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f680"
+MAN_ASTRONAUT_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f680"
+MAN_ASTRONAUT_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f680"
+MAN_ASTRONAUT_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f680"
+WOMAN_ASTRONAUT = "\U0001f469\u200d\U0001f680"
+WOMAN_ASTRONAUT_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f680"
+WOMAN_ASTRONAUT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f680"
+WOMAN_ASTRONAUT_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f680"
+WOMAN_ASTRONAUT_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f680"
+WOMAN_ASTRONAUT_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f680"
+FIREFIGHTER = "\U0001f9d1\u200d\U0001f692"
+FIREFIGHTER_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f692"
+FIREFIGHTER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f692"
+FIREFIGHTER_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f692"
+FIREFIGHTER_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f692"
+FIREFIGHTER_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f692"
+MAN_FIREFIGHTER = "\U0001f468\u200d\U0001f692"
+MAN_FIREFIGHTER_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f692"
+MAN_FIREFIGHTER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f692"
+MAN_FIREFIGHTER_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f692"
+MAN_FIREFIGHTER_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f692"
+MAN_FIREFIGHTER_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f692"
+WOMAN_FIREFIGHTER = "\U0001f469\u200d\U0001f692"
+WOMAN_FIREFIGHTER_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f692"
+WOMAN_FIREFIGHTER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f692"
+WOMAN_FIREFIGHTER_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f692"
+WOMAN_FIREFIGHTER_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f692"
+WOMAN_FIREFIGHTER_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f692"
+POLICE_OFFICER = "\U0001f46e"
+POLICE_OFFICER_LIGHT_SKIN_TONE = "\U0001f46e\U0001f3fb"
+POLICE_OFFICER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f46e\U0001f3fc"
+POLICE_OFFICER_MEDIUM_SKIN_TONE = "\U0001f46e\U0001f3fd"
+POLICE_OFFICER_MEDIUM_DARK_SKIN_TONE = "\U0001f46e\U0001f3fe"
+POLICE_OFFICER_DARK_SKIN_TONE = "\U0001f46e\U0001f3ff"
+MAN_POLICE_OFFICER = "\U0001f46e\u200d\u2642\ufe0f"
+MAN_POLICE_OFFICER_LIGHT_SKIN_TONE = "\U0001f46e\U0001f3fb\u200d\u2642\ufe0f"
+MAN_POLICE_OFFICER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f46e\U0001f3fc\u200d\u2642\ufe0f"
+MAN_POLICE_OFFICER_MEDIUM_SKIN_TONE = "\U0001f46e\U0001f3fd\u200d\u2642\ufe0f"
+MAN_POLICE_OFFICER_MEDIUM_DARK_SKIN_TONE = "\U0001f46e\U0001f3fe\u200d\u2642\ufe0f"
+MAN_POLICE_OFFICER_DARK_SKIN_TONE = "\U0001f46e\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_POLICE_OFFICER = "\U0001f46e\u200d\u2640\ufe0f"
+WOMAN_POLICE_OFFICER_LIGHT_SKIN_TONE = "\U0001f46e\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_POLICE_OFFICER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f46e\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_POLICE_OFFICER_MEDIUM_SKIN_TONE = "\U0001f46e\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_POLICE_OFFICER_MEDIUM_DARK_SKIN_TONE = "\U0001f46e\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_POLICE_OFFICER_DARK_SKIN_TONE = "\U0001f46e\U0001f3ff\u200d\u2640\ufe0f"
+DETECTIVE = "\U0001f575\ufe0f"
+DETECTIVE_LIGHT_SKIN_TONE = "\U0001f575\U0001f3fb"
+DETECTIVE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f575\U0001f3fc"
+DETECTIVE_MEDIUM_SKIN_TONE = "\U0001f575\U0001f3fd"
+DETECTIVE_MEDIUM_DARK_SKIN_TONE = "\U0001f575\U0001f3fe"
+DETECTIVE_DARK_SKIN_TONE = "\U0001f575\U0001f3ff"
+MAN_DETECTIVE = "\U0001f575\ufe0f\u200d\u2642\ufe0f"
+MAN_DETECTIVE_LIGHT_SKIN_TONE = "\U0001f575\U0001f3fb\u200d\u2642\ufe0f"
+MAN_DETECTIVE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f575\U0001f3fc\u200d\u2642\ufe0f"
+MAN_DETECTIVE_MEDIUM_SKIN_TONE = "\U0001f575\U0001f3fd\u200d\u2642\ufe0f"
+MAN_DETECTIVE_MEDIUM_DARK_SKIN_TONE = "\U0001f575\U0001f3fe\u200d\u2642\ufe0f"
+MAN_DETECTIVE_DARK_SKIN_TONE = "\U0001f575\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_DETECTIVE = "\U0001f575\ufe0f\u200d\u2640\ufe0f"
+WOMAN_DETECTIVE_LIGHT_SKIN_TONE = "\U0001f575\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_DETECTIVE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f575\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_DETECTIVE_MEDIUM_SKIN_TONE = "\U0001f575\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_DETECTIVE_MEDIUM_DARK_SKIN_TONE = "\U0001f575\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_DETECTIVE_DARK_SKIN_TONE = "\U0001f575\U0001f3ff\u200d\u2640\ufe0f"
+GUARD = "\U0001f482"
+GUARD_LIGHT_SKIN_TONE = "\U0001f482\U0001f3fb"
+GUARD_MEDIUM_LIGHT_SKIN_TONE = "\U0001f482\U0001f3fc"
+GUARD_MEDIUM_SKIN_TONE = "\U0001f482\U0001f3fd"
+GUARD_MEDIUM_DARK_SKIN_TONE = "\U0001f482\U0001f3fe"
+GUARD_DARK_SKIN_TONE = "\U0001f482\U0001f3ff"
+MAN_GUARD = "\U0001f482\u200d\u2642\ufe0f"
+MAN_GUARD_LIGHT_SKIN_TONE = "\U0001f482\U0001f3fb\u200d\u2642\ufe0f"
+MAN_GUARD_MEDIUM_LIGHT_SKIN_TONE = "\U0001f482\U0001f3fc\u200d\u2642\ufe0f"
+MAN_GUARD_MEDIUM_SKIN_TONE = "\U0001f482\U0001f3fd\u200d\u2642\ufe0f"
+MAN_GUARD_MEDIUM_DARK_SKIN_TONE = "\U0001f482\U0001f3fe\u200d\u2642\ufe0f"
+MAN_GUARD_DARK_SKIN_TONE = "\U0001f482\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_GUARD = "\U0001f482\u200d\u2640\ufe0f"
+WOMAN_GUARD_LIGHT_SKIN_TONE = "\U0001f482\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_GUARD_MEDIUM_LIGHT_SKIN_TONE = "\U0001f482\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_GUARD_MEDIUM_SKIN_TONE = "\U0001f482\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_GUARD_MEDIUM_DARK_SKIN_TONE = "\U0001f482\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_GUARD_DARK_SKIN_TONE = "\U0001f482\U0001f3ff\u200d\u2640\ufe0f"
+NINJA = "\U0001f977"
+NINJA_LIGHT_SKIN_TONE = "\U0001f977\U0001f3fb"
+NINJA_MEDIUM_LIGHT_SKIN_TONE = "\U0001f977\U0001f3fc"
+NINJA_MEDIUM_SKIN_TONE = "\U0001f977\U0001f3fd"
+NINJA_MEDIUM_DARK_SKIN_TONE = "\U0001f977\U0001f3fe"
+NINJA_DARK_SKIN_TONE = "\U0001f977\U0001f3ff"
+CONSTRUCTION_WORKER = "\U0001f477"
+CONSTRUCTION_WORKER_LIGHT_SKIN_TONE = "\U0001f477\U0001f3fb"
+CONSTRUCTION_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f477\U0001f3fc"
+CONSTRUCTION_WORKER_MEDIUM_SKIN_TONE = "\U0001f477\U0001f3fd"
+CONSTRUCTION_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f477\U0001f3fe"
+CONSTRUCTION_WORKER_DARK_SKIN_TONE = "\U0001f477\U0001f3ff"
+MAN_CONSTRUCTION_WORKER = "\U0001f477\u200d\u2642\ufe0f"
+MAN_CONSTRUCTION_WORKER_LIGHT_SKIN_TONE = "\U0001f477\U0001f3fb\u200d\u2642\ufe0f"
+MAN_CONSTRUCTION_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f477\U0001f3fc\u200d\u2642\ufe0f"
+MAN_CONSTRUCTION_WORKER_MEDIUM_SKIN_TONE = "\U0001f477\U0001f3fd\u200d\u2642\ufe0f"
+MAN_CONSTRUCTION_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f477\U0001f3fe\u200d\u2642\ufe0f"
+MAN_CONSTRUCTION_WORKER_DARK_SKIN_TONE = "\U0001f477\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_CONSTRUCTION_WORKER = "\U0001f477\u200d\u2640\ufe0f"
+WOMAN_CONSTRUCTION_WORKER_LIGHT_SKIN_TONE = "\U0001f477\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_CONSTRUCTION_WORKER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f477\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_CONSTRUCTION_WORKER_MEDIUM_SKIN_TONE = "\U0001f477\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_CONSTRUCTION_WORKER_MEDIUM_DARK_SKIN_TONE = "\U0001f477\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_CONSTRUCTION_WORKER_DARK_SKIN_TONE = "\U0001f477\U0001f3ff\u200d\u2640\ufe0f"
+PRINCE = "\U0001f934"
+PRINCE_LIGHT_SKIN_TONE = "\U0001f934\U0001f3fb"
+PRINCE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f934\U0001f3fc"
+PRINCE_MEDIUM_SKIN_TONE = "\U0001f934\U0001f3fd"
+PRINCE_MEDIUM_DARK_SKIN_TONE = "\U0001f934\U0001f3fe"
+PRINCE_DARK_SKIN_TONE = "\U0001f934\U0001f3ff"
+PRINCESS = "\U0001f478"
+PRINCESS_LIGHT_SKIN_TONE = "\U0001f478\U0001f3fb"
+PRINCESS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f478\U0001f3fc"
+PRINCESS_MEDIUM_SKIN_TONE = "\U0001f478\U0001f3fd"
+PRINCESS_MEDIUM_DARK_SKIN_TONE = "\U0001f478\U0001f3fe"
+PRINCESS_DARK_SKIN_TONE = "\U0001f478\U0001f3ff"
+PERSON_WEARING_TURBAN = "\U0001f473"
+PERSON_WEARING_TURBAN_LIGHT_SKIN_TONE = "\U0001f473\U0001f3fb"
+PERSON_WEARING_TURBAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f473\U0001f3fc"
+PERSON_WEARING_TURBAN_MEDIUM_SKIN_TONE = "\U0001f473\U0001f3fd"
+PERSON_WEARING_TURBAN_MEDIUM_DARK_SKIN_TONE = "\U0001f473\U0001f3fe"
+PERSON_WEARING_TURBAN_DARK_SKIN_TONE = "\U0001f473\U0001f3ff"
+MAN_WEARING_TURBAN = "\U0001f473\u200d\u2642\ufe0f"
+MAN_WEARING_TURBAN_LIGHT_SKIN_TONE = "\U0001f473\U0001f3fb\u200d\u2642\ufe0f"
+MAN_WEARING_TURBAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f473\U0001f3fc\u200d\u2642\ufe0f"
+MAN_WEARING_TURBAN_MEDIUM_SKIN_TONE = "\U0001f473\U0001f3fd\u200d\u2642\ufe0f"
+MAN_WEARING_TURBAN_MEDIUM_DARK_SKIN_TONE = "\U0001f473\U0001f3fe\u200d\u2642\ufe0f"
+MAN_WEARING_TURBAN_DARK_SKIN_TONE = "\U0001f473\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_WEARING_TURBAN = "\U0001f473\u200d\u2640\ufe0f"
+WOMAN_WEARING_TURBAN_LIGHT_SKIN_TONE = "\U0001f473\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_WEARING_TURBAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f473\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_WEARING_TURBAN_MEDIUM_SKIN_TONE = "\U0001f473\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_WEARING_TURBAN_MEDIUM_DARK_SKIN_TONE = "\U0001f473\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_WEARING_TURBAN_DARK_SKIN_TONE = "\U0001f473\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_WITH_SKULLCAP = "\U0001f472"
+PERSON_WITH_SKULLCAP_LIGHT_SKIN_TONE = "\U0001f472\U0001f3fb"
+PERSON_WITH_SKULLCAP_MEDIUM_LIGHT_SKIN_TONE = "\U0001f472\U0001f3fc"
+PERSON_WITH_SKULLCAP_MEDIUM_SKIN_TONE = "\U0001f472\U0001f3fd"
+PERSON_WITH_SKULLCAP_MEDIUM_DARK_SKIN_TONE = "\U0001f472\U0001f3fe"
+PERSON_WITH_SKULLCAP_DARK_SKIN_TONE = "\U0001f472\U0001f3ff"
+WOMAN_WITH_HEADSCARF = "\U0001f9d5"
+WOMAN_WITH_HEADSCARF_LIGHT_SKIN_TONE = "\U0001f9d5\U0001f3fb"
+WOMAN_WITH_HEADSCARF_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d5\U0001f3fc"
+WOMAN_WITH_HEADSCARF_MEDIUM_SKIN_TONE = "\U0001f9d5\U0001f3fd"
+WOMAN_WITH_HEADSCARF_MEDIUM_DARK_SKIN_TONE = "\U0001f9d5\U0001f3fe"
+WOMAN_WITH_HEADSCARF_DARK_SKIN_TONE = "\U0001f9d5\U0001f3ff"
+PERSON_IN_TUXEDO = "\U0001f935"
+PERSON_IN_TUXEDO_LIGHT_SKIN_TONE = "\U0001f935\U0001f3fb"
+PERSON_IN_TUXEDO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f935\U0001f3fc"
+PERSON_IN_TUXEDO_MEDIUM_SKIN_TONE = "\U0001f935\U0001f3fd"
+PERSON_IN_TUXEDO_MEDIUM_DARK_SKIN_TONE = "\U0001f935\U0001f3fe"
+PERSON_IN_TUXEDO_DARK_SKIN_TONE = "\U0001f935\U0001f3ff"
+MAN_IN_TUXEDO = "\U0001f935\u200d\u2642\ufe0f"
+MAN_IN_TUXEDO_LIGHT_SKIN_TONE = "\U0001f935\U0001f3fb\u200d\u2642\ufe0f"
+MAN_IN_TUXEDO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f935\U0001f3fc\u200d\u2642\ufe0f"
+MAN_IN_TUXEDO_MEDIUM_SKIN_TONE = "\U0001f935\U0001f3fd\u200d\u2642\ufe0f"
+MAN_IN_TUXEDO_MEDIUM_DARK_SKIN_TONE = "\U0001f935\U0001f3fe\u200d\u2642\ufe0f"
+MAN_IN_TUXEDO_DARK_SKIN_TONE = "\U0001f935\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_IN_TUXEDO = "\U0001f935\u200d\u2640\ufe0f"
+WOMAN_IN_TUXEDO_LIGHT_SKIN_TONE = "\U0001f935\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_IN_TUXEDO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f935\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_IN_TUXEDO_MEDIUM_SKIN_TONE = "\U0001f935\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_IN_TUXEDO_MEDIUM_DARK_SKIN_TONE = "\U0001f935\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_IN_TUXEDO_DARK_SKIN_TONE = "\U0001f935\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_WITH_VEIL = "\U0001f470"
+PERSON_WITH_VEIL_LIGHT_SKIN_TONE = "\U0001f470\U0001f3fb"
+PERSON_WITH_VEIL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f470\U0001f3fc"
+PERSON_WITH_VEIL_MEDIUM_SKIN_TONE = "\U0001f470\U0001f3fd"
+PERSON_WITH_VEIL_MEDIUM_DARK_SKIN_TONE = "\U0001f470\U0001f3fe"
+PERSON_WITH_VEIL_DARK_SKIN_TONE = "\U0001f470\U0001f3ff"
+MAN_WITH_VEIL = "\U0001f470\u200d\u2642\ufe0f"
+MAN_WITH_VEIL_LIGHT_SKIN_TONE = "\U0001f470\U0001f3fb\u200d\u2642\ufe0f"
+MAN_WITH_VEIL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f470\U0001f3fc\u200d\u2642\ufe0f"
+MAN_WITH_VEIL_MEDIUM_SKIN_TONE = "\U0001f470\U0001f3fd\u200d\u2642\ufe0f"
+MAN_WITH_VEIL_MEDIUM_DARK_SKIN_TONE = "\U0001f470\U0001f3fe\u200d\u2642\ufe0f"
+MAN_WITH_VEIL_DARK_SKIN_TONE = "\U0001f470\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_WITH_VEIL = "\U0001f470\u200d\u2640\ufe0f"
+WOMAN_WITH_VEIL_LIGHT_SKIN_TONE = "\U0001f470\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_WITH_VEIL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f470\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_WITH_VEIL_MEDIUM_SKIN_TONE = "\U0001f470\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_WITH_VEIL_MEDIUM_DARK_SKIN_TONE = "\U0001f470\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_WITH_VEIL_DARK_SKIN_TONE = "\U0001f470\U0001f3ff\u200d\u2640\ufe0f"
+PREGNANT_WOMAN = "\U0001f930"
+PREGNANT_WOMAN_LIGHT_SKIN_TONE = "\U0001f930\U0001f3fb"
+PREGNANT_WOMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f930\U0001f3fc"
+PREGNANT_WOMAN_MEDIUM_SKIN_TONE = "\U0001f930\U0001f3fd"
+PREGNANT_WOMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f930\U0001f3fe"
+PREGNANT_WOMAN_DARK_SKIN_TONE = "\U0001f930\U0001f3ff"
+BREAST_FEEDING = "\U0001f931"
+BREAST_FEEDING_LIGHT_SKIN_TONE = "\U0001f931\U0001f3fb"
+BREAST_FEEDING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f931\U0001f3fc"
+BREAST_FEEDING_MEDIUM_SKIN_TONE = "\U0001f931\U0001f3fd"
+BREAST_FEEDING_MEDIUM_DARK_SKIN_TONE = "\U0001f931\U0001f3fe"
+BREAST_FEEDING_DARK_SKIN_TONE = "\U0001f931\U0001f3ff"
+WOMAN_FEEDING_BABY = "\U0001f469\u200d\U0001f37c"
+WOMAN_FEEDING_BABY_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f37c"
+WOMAN_FEEDING_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f37c"
+WOMAN_FEEDING_BABY_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f37c"
+WOMAN_FEEDING_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f37c"
+WOMAN_FEEDING_BABY_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f37c"
+MAN_FEEDING_BABY = "\U0001f468\u200d\U0001f37c"
+MAN_FEEDING_BABY_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f37c"
+MAN_FEEDING_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f37c"
+MAN_FEEDING_BABY_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f37c"
+MAN_FEEDING_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f37c"
+MAN_FEEDING_BABY_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f37c"
+PERSON_FEEDING_BABY = "\U0001f9d1\u200d\U0001f37c"
+PERSON_FEEDING_BABY_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f37c"
+PERSON_FEEDING_BABY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f37c"
+PERSON_FEEDING_BABY_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f37c"
+PERSON_FEEDING_BABY_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f37c"
+PERSON_FEEDING_BABY_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f37c"
+BABY_ANGEL = "\U0001f47c"
+BABY_ANGEL_LIGHT_SKIN_TONE = "\U0001f47c\U0001f3fb"
+BABY_ANGEL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f47c\U0001f3fc"
+BABY_ANGEL_MEDIUM_SKIN_TONE = "\U0001f47c\U0001f3fd"
+BABY_ANGEL_MEDIUM_DARK_SKIN_TONE = "\U0001f47c\U0001f3fe"
+BABY_ANGEL_DARK_SKIN_TONE = "\U0001f47c\U0001f3ff"
+SANTA_CLAUS = "\U0001f385"
+SANTA_CLAUS_LIGHT_SKIN_TONE = "\U0001f385\U0001f3fb"
+SANTA_CLAUS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f385\U0001f3fc"
+SANTA_CLAUS_MEDIUM_SKIN_TONE = "\U0001f385\U0001f3fd"
+SANTA_CLAUS_MEDIUM_DARK_SKIN_TONE = "\U0001f385\U0001f3fe"
+SANTA_CLAUS_DARK_SKIN_TONE = "\U0001f385\U0001f3ff"
+MRS_CLAUS = "\U0001f936"
+MRS_CLAUS_LIGHT_SKIN_TONE = "\U0001f936\U0001f3fb"
+MRS_CLAUS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f936\U0001f3fc"
+MRS_CLAUS_MEDIUM_SKIN_TONE = "\U0001f936\U0001f3fd"
+MRS_CLAUS_MEDIUM_DARK_SKIN_TONE = "\U0001f936\U0001f3fe"
+MRS_CLAUS_DARK_SKIN_TONE = "\U0001f936\U0001f3ff"
+MX_CLAUS = "\U0001f9d1\u200d\U0001f384"
+MX_CLAUS_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f384"
+MX_CLAUS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f384"
+MX_CLAUS_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f384"
+MX_CLAUS_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f384"
+MX_CLAUS_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f384"
+SUPERHERO = "\U0001f9b8"
+SUPERHERO_LIGHT_SKIN_TONE = "\U0001f9b8\U0001f3fb"
+SUPERHERO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b8\U0001f3fc"
+SUPERHERO_MEDIUM_SKIN_TONE = "\U0001f9b8\U0001f3fd"
+SUPERHERO_MEDIUM_DARK_SKIN_TONE = "\U0001f9b8\U0001f3fe"
+SUPERHERO_DARK_SKIN_TONE = "\U0001f9b8\U0001f3ff"
+MAN_SUPERHERO = "\U0001f9b8\u200d\u2642\ufe0f"
+MAN_SUPERHERO_LIGHT_SKIN_TONE = "\U0001f9b8\U0001f3fb\u200d\u2642\ufe0f"
+MAN_SUPERHERO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b8\U0001f3fc\u200d\u2642\ufe0f"
+MAN_SUPERHERO_MEDIUM_SKIN_TONE = "\U0001f9b8\U0001f3fd\u200d\u2642\ufe0f"
+MAN_SUPERHERO_MEDIUM_DARK_SKIN_TONE = "\U0001f9b8\U0001f3fe\u200d\u2642\ufe0f"
+MAN_SUPERHERO_DARK_SKIN_TONE = "\U0001f9b8\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_SUPERHERO = "\U0001f9b8\u200d\u2640\ufe0f"
+WOMAN_SUPERHERO_LIGHT_SKIN_TONE = "\U0001f9b8\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_SUPERHERO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b8\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_SUPERHERO_MEDIUM_SKIN_TONE = "\U0001f9b8\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_SUPERHERO_MEDIUM_DARK_SKIN_TONE = "\U0001f9b8\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_SUPERHERO_DARK_SKIN_TONE = "\U0001f9b8\U0001f3ff\u200d\u2640\ufe0f"
+SUPERVILLAIN = "\U0001f9b9"
+SUPERVILLAIN_LIGHT_SKIN_TONE = "\U0001f9b9\U0001f3fb"
+SUPERVILLAIN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b9\U0001f3fc"
+SUPERVILLAIN_MEDIUM_SKIN_TONE = "\U0001f9b9\U0001f3fd"
+SUPERVILLAIN_MEDIUM_DARK_SKIN_TONE = "\U0001f9b9\U0001f3fe"
+SUPERVILLAIN_DARK_SKIN_TONE = "\U0001f9b9\U0001f3ff"
+MAN_SUPERVILLAIN = "\U0001f9b9\u200d\u2642\ufe0f"
+MAN_SUPERVILLAIN_LIGHT_SKIN_TONE = "\U0001f9b9\U0001f3fb\u200d\u2642\ufe0f"
+MAN_SUPERVILLAIN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b9\U0001f3fc\u200d\u2642\ufe0f"
+MAN_SUPERVILLAIN_MEDIUM_SKIN_TONE = "\U0001f9b9\U0001f3fd\u200d\u2642\ufe0f"
+MAN_SUPERVILLAIN_MEDIUM_DARK_SKIN_TONE = "\U0001f9b9\U0001f3fe\u200d\u2642\ufe0f"
+MAN_SUPERVILLAIN_DARK_SKIN_TONE = "\U0001f9b9\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_SUPERVILLAIN = "\U0001f9b9\u200d\u2640\ufe0f"
+WOMAN_SUPERVILLAIN_LIGHT_SKIN_TONE = "\U0001f9b9\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_SUPERVILLAIN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9b9\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_SUPERVILLAIN_MEDIUM_SKIN_TONE = "\U0001f9b9\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_SUPERVILLAIN_MEDIUM_DARK_SKIN_TONE = "\U0001f9b9\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_SUPERVILLAIN_DARK_SKIN_TONE = "\U0001f9b9\U0001f3ff\u200d\u2640\ufe0f"
+MAGE = "\U0001f9d9"
+MAGE_LIGHT_SKIN_TONE = "\U0001f9d9\U0001f3fb"
+MAGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d9\U0001f3fc"
+MAGE_MEDIUM_SKIN_TONE = "\U0001f9d9\U0001f3fd"
+MAGE_MEDIUM_DARK_SKIN_TONE = "\U0001f9d9\U0001f3fe"
+MAGE_DARK_SKIN_TONE = "\U0001f9d9\U0001f3ff"
+MAN_MAGE = "\U0001f9d9\u200d\u2642\ufe0f"
+MAN_MAGE_LIGHT_SKIN_TONE = "\U0001f9d9\U0001f3fb\u200d\u2642\ufe0f"
+MAN_MAGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d9\U0001f3fc\u200d\u2642\ufe0f"
+MAN_MAGE_MEDIUM_SKIN_TONE = "\U0001f9d9\U0001f3fd\u200d\u2642\ufe0f"
+MAN_MAGE_MEDIUM_DARK_SKIN_TONE = "\U0001f9d9\U0001f3fe\u200d\u2642\ufe0f"
+MAN_MAGE_DARK_SKIN_TONE = "\U0001f9d9\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_MAGE = "\U0001f9d9\u200d\u2640\ufe0f"
+WOMAN_MAGE_LIGHT_SKIN_TONE = "\U0001f9d9\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_MAGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d9\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_MAGE_MEDIUM_SKIN_TONE = "\U0001f9d9\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_MAGE_MEDIUM_DARK_SKIN_TONE = "\U0001f9d9\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_MAGE_DARK_SKIN_TONE = "\U0001f9d9\U0001f3ff\u200d\u2640\ufe0f"
+FAIRY = "\U0001f9da"
+FAIRY_LIGHT_SKIN_TONE = "\U0001f9da\U0001f3fb"
+FAIRY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9da\U0001f3fc"
+FAIRY_MEDIUM_SKIN_TONE = "\U0001f9da\U0001f3fd"
+FAIRY_MEDIUM_DARK_SKIN_TONE = "\U0001f9da\U0001f3fe"
+FAIRY_DARK_SKIN_TONE = "\U0001f9da\U0001f3ff"
+MAN_FAIRY = "\U0001f9da\u200d\u2642\ufe0f"
+MAN_FAIRY_LIGHT_SKIN_TONE = "\U0001f9da\U0001f3fb\u200d\u2642\ufe0f"
+MAN_FAIRY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9da\U0001f3fc\u200d\u2642\ufe0f"
+MAN_FAIRY_MEDIUM_SKIN_TONE = "\U0001f9da\U0001f3fd\u200d\u2642\ufe0f"
+MAN_FAIRY_MEDIUM_DARK_SKIN_TONE = "\U0001f9da\U0001f3fe\u200d\u2642\ufe0f"
+MAN_FAIRY_DARK_SKIN_TONE = "\U0001f9da\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_FAIRY = "\U0001f9da\u200d\u2640\ufe0f"
+WOMAN_FAIRY_LIGHT_SKIN_TONE = "\U0001f9da\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_FAIRY_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9da\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_FAIRY_MEDIUM_SKIN_TONE = "\U0001f9da\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_FAIRY_MEDIUM_DARK_SKIN_TONE = "\U0001f9da\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_FAIRY_DARK_SKIN_TONE = "\U0001f9da\U0001f3ff\u200d\u2640\ufe0f"
+VAMPIRE = "\U0001f9db"
+VAMPIRE_LIGHT_SKIN_TONE = "\U0001f9db\U0001f3fb"
+VAMPIRE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9db\U0001f3fc"
+VAMPIRE_MEDIUM_SKIN_TONE = "\U0001f9db\U0001f3fd"
+VAMPIRE_MEDIUM_DARK_SKIN_TONE = "\U0001f9db\U0001f3fe"
+VAMPIRE_DARK_SKIN_TONE = "\U0001f9db\U0001f3ff"
+MAN_VAMPIRE = "\U0001f9db\u200d\u2642\ufe0f"
+MAN_VAMPIRE_LIGHT_SKIN_TONE = "\U0001f9db\U0001f3fb\u200d\u2642\ufe0f"
+MAN_VAMPIRE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9db\U0001f3fc\u200d\u2642\ufe0f"
+MAN_VAMPIRE_MEDIUM_SKIN_TONE = "\U0001f9db\U0001f3fd\u200d\u2642\ufe0f"
+MAN_VAMPIRE_MEDIUM_DARK_SKIN_TONE = "\U0001f9db\U0001f3fe\u200d\u2642\ufe0f"
+MAN_VAMPIRE_DARK_SKIN_TONE = "\U0001f9db\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_VAMPIRE = "\U0001f9db\u200d\u2640\ufe0f"
+WOMAN_VAMPIRE_LIGHT_SKIN_TONE = "\U0001f9db\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_VAMPIRE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9db\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_VAMPIRE_MEDIUM_SKIN_TONE = "\U0001f9db\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_VAMPIRE_MEDIUM_DARK_SKIN_TONE = "\U0001f9db\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_VAMPIRE_DARK_SKIN_TONE = "\U0001f9db\U0001f3ff\u200d\u2640\ufe0f"
+MERPERSON = "\U0001f9dc"
+MERPERSON_LIGHT_SKIN_TONE = "\U0001f9dc\U0001f3fb"
+MERPERSON_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9dc\U0001f3fc"
+MERPERSON_MEDIUM_SKIN_TONE = "\U0001f9dc\U0001f3fd"
+MERPERSON_MEDIUM_DARK_SKIN_TONE = "\U0001f9dc\U0001f3fe"
+MERPERSON_DARK_SKIN_TONE = "\U0001f9dc\U0001f3ff"
+MERMAN = "\U0001f9dc\u200d\u2642\ufe0f"
+MERMAN_LIGHT_SKIN_TONE = "\U0001f9dc\U0001f3fb\u200d\u2642\ufe0f"
+MERMAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9dc\U0001f3fc\u200d\u2642\ufe0f"
+MERMAN_MEDIUM_SKIN_TONE = "\U0001f9dc\U0001f3fd\u200d\u2642\ufe0f"
+MERMAN_MEDIUM_DARK_SKIN_TONE = "\U0001f9dc\U0001f3fe\u200d\u2642\ufe0f"
+MERMAN_DARK_SKIN_TONE = "\U0001f9dc\U0001f3ff\u200d\u2642\ufe0f"
+MERMAID = "\U0001f9dc\u200d\u2640\ufe0f"
+MERMAID_LIGHT_SKIN_TONE = "\U0001f9dc\U0001f3fb\u200d\u2640\ufe0f"
+MERMAID_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9dc\U0001f3fc\u200d\u2640\ufe0f"
+MERMAID_MEDIUM_SKIN_TONE = "\U0001f9dc\U0001f3fd\u200d\u2640\ufe0f"
+MERMAID_MEDIUM_DARK_SKIN_TONE = "\U0001f9dc\U0001f3fe\u200d\u2640\ufe0f"
+MERMAID_DARK_SKIN_TONE = "\U0001f9dc\U0001f3ff\u200d\u2640\ufe0f"
+ELF = "\U0001f9dd"
+ELF_LIGHT_SKIN_TONE = "\U0001f9dd\U0001f3fb"
+ELF_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9dd\U0001f3fc"
+ELF_MEDIUM_SKIN_TONE = "\U0001f9dd\U0001f3fd"
+ELF_MEDIUM_DARK_SKIN_TONE = "\U0001f9dd\U0001f3fe"
+ELF_DARK_SKIN_TONE = "\U0001f9dd\U0001f3ff"
+MAN_ELF = "\U0001f9dd\u200d\u2642\ufe0f"
+MAN_ELF_LIGHT_SKIN_TONE = "\U0001f9dd\U0001f3fb\u200d\u2642\ufe0f"
+MAN_ELF_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9dd\U0001f3fc\u200d\u2642\ufe0f"
+MAN_ELF_MEDIUM_SKIN_TONE = "\U0001f9dd\U0001f3fd\u200d\u2642\ufe0f"
+MAN_ELF_MEDIUM_DARK_SKIN_TONE = "\U0001f9dd\U0001f3fe\u200d\u2642\ufe0f"
+MAN_ELF_DARK_SKIN_TONE = "\U0001f9dd\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_ELF = "\U0001f9dd\u200d\u2640\ufe0f"
+WOMAN_ELF_LIGHT_SKIN_TONE = "\U0001f9dd\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_ELF_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9dd\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_ELF_MEDIUM_SKIN_TONE = "\U0001f9dd\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_ELF_MEDIUM_DARK_SKIN_TONE = "\U0001f9dd\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_ELF_DARK_SKIN_TONE = "\U0001f9dd\U0001f3ff\u200d\u2640\ufe0f"
+GENIE = "\U0001f9de"
+MAN_GENIE = "\U0001f9de\u200d\u2642\ufe0f"
+WOMAN_GENIE = "\U0001f9de\u200d\u2640\ufe0f"
+ZOMBIE = "\U0001f9df"
+MAN_ZOMBIE = "\U0001f9df\u200d\u2642\ufe0f"
+WOMAN_ZOMBIE = "\U0001f9df\u200d\u2640\ufe0f"
+PERSON_GETTING_MASSAGE = "\U0001f486"
+PERSON_GETTING_MASSAGE_LIGHT_SKIN_TONE = "\U0001f486\U0001f3fb"
+PERSON_GETTING_MASSAGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f486\U0001f3fc"
+PERSON_GETTING_MASSAGE_MEDIUM_SKIN_TONE = "\U0001f486\U0001f3fd"
+PERSON_GETTING_MASSAGE_MEDIUM_DARK_SKIN_TONE = "\U0001f486\U0001f3fe"
+PERSON_GETTING_MASSAGE_DARK_SKIN_TONE = "\U0001f486\U0001f3ff"
+MAN_GETTING_MASSAGE = "\U0001f486\u200d\u2642\ufe0f"
+MAN_GETTING_MASSAGE_LIGHT_SKIN_TONE = "\U0001f486\U0001f3fb\u200d\u2642\ufe0f"
+MAN_GETTING_MASSAGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f486\U0001f3fc\u200d\u2642\ufe0f"
+MAN_GETTING_MASSAGE_MEDIUM_SKIN_TONE = "\U0001f486\U0001f3fd\u200d\u2642\ufe0f"
+MAN_GETTING_MASSAGE_MEDIUM_DARK_SKIN_TONE = "\U0001f486\U0001f3fe\u200d\u2642\ufe0f"
+MAN_GETTING_MASSAGE_DARK_SKIN_TONE = "\U0001f486\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_GETTING_MASSAGE = "\U0001f486\u200d\u2640\ufe0f"
+WOMAN_GETTING_MASSAGE_LIGHT_SKIN_TONE = "\U0001f486\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_GETTING_MASSAGE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f486\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_GETTING_MASSAGE_MEDIUM_SKIN_TONE = "\U0001f486\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_GETTING_MASSAGE_MEDIUM_DARK_SKIN_TONE = "\U0001f486\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_GETTING_MASSAGE_DARK_SKIN_TONE = "\U0001f486\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_GETTING_HAIRCUT = "\U0001f487"
+PERSON_GETTING_HAIRCUT_LIGHT_SKIN_TONE = "\U0001f487\U0001f3fb"
+PERSON_GETTING_HAIRCUT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f487\U0001f3fc"
+PERSON_GETTING_HAIRCUT_MEDIUM_SKIN_TONE = "\U0001f487\U0001f3fd"
+PERSON_GETTING_HAIRCUT_MEDIUM_DARK_SKIN_TONE = "\U0001f487\U0001f3fe"
+PERSON_GETTING_HAIRCUT_DARK_SKIN_TONE = "\U0001f487\U0001f3ff"
+MAN_GETTING_HAIRCUT = "\U0001f487\u200d\u2642\ufe0f"
+MAN_GETTING_HAIRCUT_LIGHT_SKIN_TONE = "\U0001f487\U0001f3fb\u200d\u2642\ufe0f"
+MAN_GETTING_HAIRCUT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f487\U0001f3fc\u200d\u2642\ufe0f"
+MAN_GETTING_HAIRCUT_MEDIUM_SKIN_TONE = "\U0001f487\U0001f3fd\u200d\u2642\ufe0f"
+MAN_GETTING_HAIRCUT_MEDIUM_DARK_SKIN_TONE = "\U0001f487\U0001f3fe\u200d\u2642\ufe0f"
+MAN_GETTING_HAIRCUT_DARK_SKIN_TONE = "\U0001f487\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_GETTING_HAIRCUT = "\U0001f487\u200d\u2640\ufe0f"
+WOMAN_GETTING_HAIRCUT_LIGHT_SKIN_TONE = "\U0001f487\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_GETTING_HAIRCUT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f487\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_GETTING_HAIRCUT_MEDIUM_SKIN_TONE = "\U0001f487\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_GETTING_HAIRCUT_MEDIUM_DARK_SKIN_TONE = "\U0001f487\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_GETTING_HAIRCUT_DARK_SKIN_TONE = "\U0001f487\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_WALKING = "\U0001f6b6"
+PERSON_WALKING_LIGHT_SKIN_TONE = "\U0001f6b6\U0001f3fb"
+PERSON_WALKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b6\U0001f3fc"
+PERSON_WALKING_MEDIUM_SKIN_TONE = "\U0001f6b6\U0001f3fd"
+PERSON_WALKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b6\U0001f3fe"
+PERSON_WALKING_DARK_SKIN_TONE = "\U0001f6b6\U0001f3ff"
+MAN_WALKING = "\U0001f6b6\u200d\u2642\ufe0f"
+MAN_WALKING_LIGHT_SKIN_TONE = "\U0001f6b6\U0001f3fb\u200d\u2642\ufe0f"
+MAN_WALKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b6\U0001f3fc\u200d\u2642\ufe0f"
+MAN_WALKING_MEDIUM_SKIN_TONE = "\U0001f6b6\U0001f3fd\u200d\u2642\ufe0f"
+MAN_WALKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b6\U0001f3fe\u200d\u2642\ufe0f"
+MAN_WALKING_DARK_SKIN_TONE = "\U0001f6b6\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_WALKING = "\U0001f6b6\u200d\u2640\ufe0f"
+WOMAN_WALKING_LIGHT_SKIN_TONE = "\U0001f6b6\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_WALKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b6\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_WALKING_MEDIUM_SKIN_TONE = "\U0001f6b6\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_WALKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b6\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_WALKING_DARK_SKIN_TONE = "\U0001f6b6\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_STANDING = "\U0001f9cd"
+PERSON_STANDING_LIGHT_SKIN_TONE = "\U0001f9cd\U0001f3fb"
+PERSON_STANDING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9cd\U0001f3fc"
+PERSON_STANDING_MEDIUM_SKIN_TONE = "\U0001f9cd\U0001f3fd"
+PERSON_STANDING_MEDIUM_DARK_SKIN_TONE = "\U0001f9cd\U0001f3fe"
+PERSON_STANDING_DARK_SKIN_TONE = "\U0001f9cd\U0001f3ff"
+MAN_STANDING = "\U0001f9cd\u200d\u2642\ufe0f"
+MAN_STANDING_LIGHT_SKIN_TONE = "\U0001f9cd\U0001f3fb\u200d\u2642\ufe0f"
+MAN_STANDING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9cd\U0001f3fc\u200d\u2642\ufe0f"
+MAN_STANDING_MEDIUM_SKIN_TONE = "\U0001f9cd\U0001f3fd\u200d\u2642\ufe0f"
+MAN_STANDING_MEDIUM_DARK_SKIN_TONE = "\U0001f9cd\U0001f3fe\u200d\u2642\ufe0f"
+MAN_STANDING_DARK_SKIN_TONE = "\U0001f9cd\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_STANDING = "\U0001f9cd\u200d\u2640\ufe0f"
+WOMAN_STANDING_LIGHT_SKIN_TONE = "\U0001f9cd\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_STANDING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9cd\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_STANDING_MEDIUM_SKIN_TONE = "\U0001f9cd\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_STANDING_MEDIUM_DARK_SKIN_TONE = "\U0001f9cd\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_STANDING_DARK_SKIN_TONE = "\U0001f9cd\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_KNEELING = "\U0001f9ce"
+PERSON_KNEELING_LIGHT_SKIN_TONE = "\U0001f9ce\U0001f3fb"
+PERSON_KNEELING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9ce\U0001f3fc"
+PERSON_KNEELING_MEDIUM_SKIN_TONE = "\U0001f9ce\U0001f3fd"
+PERSON_KNEELING_MEDIUM_DARK_SKIN_TONE = "\U0001f9ce\U0001f3fe"
+PERSON_KNEELING_DARK_SKIN_TONE = "\U0001f9ce\U0001f3ff"
+MAN_KNEELING = "\U0001f9ce\u200d\u2642\ufe0f"
+MAN_KNEELING_LIGHT_SKIN_TONE = "\U0001f9ce\U0001f3fb\u200d\u2642\ufe0f"
+MAN_KNEELING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9ce\U0001f3fc\u200d\u2642\ufe0f"
+MAN_KNEELING_MEDIUM_SKIN_TONE = "\U0001f9ce\U0001f3fd\u200d\u2642\ufe0f"
+MAN_KNEELING_MEDIUM_DARK_SKIN_TONE = "\U0001f9ce\U0001f3fe\u200d\u2642\ufe0f"
+MAN_KNEELING_DARK_SKIN_TONE = "\U0001f9ce\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_KNEELING = "\U0001f9ce\u200d\u2640\ufe0f"
+WOMAN_KNEELING_LIGHT_SKIN_TONE = "\U0001f9ce\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_KNEELING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9ce\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_KNEELING_MEDIUM_SKIN_TONE = "\U0001f9ce\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_KNEELING_MEDIUM_DARK_SKIN_TONE = "\U0001f9ce\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_KNEELING_DARK_SKIN_TONE = "\U0001f9ce\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_WITH_WHITE_CANE = "\U0001f9d1\u200d\U0001f9af"
+PERSON_WITH_WHITE_CANE_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f9af"
+PERSON_WITH_WHITE_CANE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f9af"
+PERSON_WITH_WHITE_CANE_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f9af"
+PERSON_WITH_WHITE_CANE_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f9af"
+PERSON_WITH_WHITE_CANE_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f9af"
+MAN_WITH_WHITE_CANE = "\U0001f468\u200d\U0001f9af"
+MAN_WITH_WHITE_CANE_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f9af"
+MAN_WITH_WHITE_CANE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f9af"
+MAN_WITH_WHITE_CANE_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f9af"
+MAN_WITH_WHITE_CANE_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f9af"
+MAN_WITH_WHITE_CANE_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f9af"
+WOMAN_WITH_WHITE_CANE = "\U0001f469\u200d\U0001f9af"
+WOMAN_WITH_WHITE_CANE_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f9af"
+WOMAN_WITH_WHITE_CANE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f9af"
+WOMAN_WITH_WHITE_CANE_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f9af"
+WOMAN_WITH_WHITE_CANE_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f9af"
+WOMAN_WITH_WHITE_CANE_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f9af"
+PERSON_IN_MOTORIZED_WHEELCHAIR = "\U0001f9d1\u200d\U0001f9bc"
+PERSON_IN_MOTORIZED_WHEELCHAIR_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f9bc"
+PERSON_IN_MOTORIZED_WHEELCHAIR_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f9bc"
+PERSON_IN_MOTORIZED_WHEELCHAIR_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f9bc"
+PERSON_IN_MOTORIZED_WHEELCHAIR_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f9bc"
+PERSON_IN_MOTORIZED_WHEELCHAIR_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f9bc"
+MAN_IN_MOTORIZED_WHEELCHAIR = "\U0001f468\u200d\U0001f9bc"
+MAN_IN_MOTORIZED_WHEELCHAIR_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f9bc"
+MAN_IN_MOTORIZED_WHEELCHAIR_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f9bc"
+MAN_IN_MOTORIZED_WHEELCHAIR_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f9bc"
+MAN_IN_MOTORIZED_WHEELCHAIR_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f9bc"
+MAN_IN_MOTORIZED_WHEELCHAIR_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f9bc"
+WOMAN_IN_MOTORIZED_WHEELCHAIR = "\U0001f469\u200d\U0001f9bc"
+WOMAN_IN_MOTORIZED_WHEELCHAIR_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f9bc"
+WOMAN_IN_MOTORIZED_WHEELCHAIR_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f9bc"
+WOMAN_IN_MOTORIZED_WHEELCHAIR_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f9bc"
+WOMAN_IN_MOTORIZED_WHEELCHAIR_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f9bc"
+WOMAN_IN_MOTORIZED_WHEELCHAIR_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f9bc"
+PERSON_IN_MANUAL_WHEELCHAIR = "\U0001f9d1\u200d\U0001f9bd"
+PERSON_IN_MANUAL_WHEELCHAIR_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f9bd"
+PERSON_IN_MANUAL_WHEELCHAIR_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f9bd"
+PERSON_IN_MANUAL_WHEELCHAIR_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f9bd"
+PERSON_IN_MANUAL_WHEELCHAIR_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f9bd"
+PERSON_IN_MANUAL_WHEELCHAIR_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f9bd"
+MAN_IN_MANUAL_WHEELCHAIR = "\U0001f468\u200d\U0001f9bd"
+MAN_IN_MANUAL_WHEELCHAIR_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f9bd"
+MAN_IN_MANUAL_WHEELCHAIR_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\U0001f9bd"
+MAN_IN_MANUAL_WHEELCHAIR_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f9bd"
+MAN_IN_MANUAL_WHEELCHAIR_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\U0001f9bd"
+MAN_IN_MANUAL_WHEELCHAIR_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f9bd"
+WOMAN_IN_MANUAL_WHEELCHAIR = "\U0001f469\u200d\U0001f9bd"
+WOMAN_IN_MANUAL_WHEELCHAIR_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f9bd"
+WOMAN_IN_MANUAL_WHEELCHAIR_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\U0001f9bd"
+WOMAN_IN_MANUAL_WHEELCHAIR_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f9bd"
+WOMAN_IN_MANUAL_WHEELCHAIR_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\U0001f9bd"
+WOMAN_IN_MANUAL_WHEELCHAIR_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f9bd"
+PERSON_RUNNING = "\U0001f3c3"
+PERSON_RUNNING_LIGHT_SKIN_TONE = "\U0001f3c3\U0001f3fb"
+PERSON_RUNNING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c3\U0001f3fc"
+PERSON_RUNNING_MEDIUM_SKIN_TONE = "\U0001f3c3\U0001f3fd"
+PERSON_RUNNING_MEDIUM_DARK_SKIN_TONE = "\U0001f3c3\U0001f3fe"
+PERSON_RUNNING_DARK_SKIN_TONE = "\U0001f3c3\U0001f3ff"
+MAN_RUNNING = "\U0001f3c3\u200d\u2642\ufe0f"
+MAN_RUNNING_LIGHT_SKIN_TONE = "\U0001f3c3\U0001f3fb\u200d\u2642\ufe0f"
+MAN_RUNNING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c3\U0001f3fc\u200d\u2642\ufe0f"
+MAN_RUNNING_MEDIUM_SKIN_TONE = "\U0001f3c3\U0001f3fd\u200d\u2642\ufe0f"
+MAN_RUNNING_MEDIUM_DARK_SKIN_TONE = "\U0001f3c3\U0001f3fe\u200d\u2642\ufe0f"
+MAN_RUNNING_DARK_SKIN_TONE = "\U0001f3c3\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_RUNNING = "\U0001f3c3\u200d\u2640\ufe0f"
+WOMAN_RUNNING_LIGHT_SKIN_TONE = "\U0001f3c3\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_RUNNING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c3\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_RUNNING_MEDIUM_SKIN_TONE = "\U0001f3c3\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_RUNNING_MEDIUM_DARK_SKIN_TONE = "\U0001f3c3\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_RUNNING_DARK_SKIN_TONE = "\U0001f3c3\U0001f3ff\u200d\u2640\ufe0f"
+WOMAN_DANCING = "\U0001f483"
+WOMAN_DANCING_LIGHT_SKIN_TONE = "\U0001f483\U0001f3fb"
+WOMAN_DANCING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f483\U0001f3fc"
+WOMAN_DANCING_MEDIUM_SKIN_TONE = "\U0001f483\U0001f3fd"
+WOMAN_DANCING_MEDIUM_DARK_SKIN_TONE = "\U0001f483\U0001f3fe"
+WOMAN_DANCING_DARK_SKIN_TONE = "\U0001f483\U0001f3ff"
+MAN_DANCING = "\U0001f57a"
+MAN_DANCING_LIGHT_SKIN_TONE = "\U0001f57a\U0001f3fb"
+MAN_DANCING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f57a\U0001f3fc"
+MAN_DANCING_MEDIUM_SKIN_TONE = "\U0001f57a\U0001f3fd"
+MAN_DANCING_MEDIUM_DARK_SKIN_TONE = "\U0001f57a\U0001f3fe"
+MAN_DANCING_DARK_SKIN_TONE = "\U0001f57a\U0001f3ff"
+PERSON_IN_SUIT_LEVITATING = "\U0001f574\ufe0f"
+PERSON_IN_SUIT_LEVITATING_LIGHT_SKIN_TONE = "\U0001f574\U0001f3fb"
+PERSON_IN_SUIT_LEVITATING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f574\U0001f3fc"
+PERSON_IN_SUIT_LEVITATING_MEDIUM_SKIN_TONE = "\U0001f574\U0001f3fd"
+PERSON_IN_SUIT_LEVITATING_MEDIUM_DARK_SKIN_TONE = "\U0001f574\U0001f3fe"
+PERSON_IN_SUIT_LEVITATING_DARK_SKIN_TONE = "\U0001f574\U0001f3ff"
+PEOPLE_WITH_BUNNY_EARS = "\U0001f46f"
+MEN_WITH_BUNNY_EARS = "\U0001f46f\u200d\u2642\ufe0f"
+WOMEN_WITH_BUNNY_EARS = "\U0001f46f\u200d\u2640\ufe0f"
+PERSON_IN_STEAMY_ROOM = "\U0001f9d6"
+PERSON_IN_STEAMY_ROOM_LIGHT_SKIN_TONE = "\U0001f9d6\U0001f3fb"
+PERSON_IN_STEAMY_ROOM_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d6\U0001f3fc"
+PERSON_IN_STEAMY_ROOM_MEDIUM_SKIN_TONE = "\U0001f9d6\U0001f3fd"
+PERSON_IN_STEAMY_ROOM_MEDIUM_DARK_SKIN_TONE = "\U0001f9d6\U0001f3fe"
+PERSON_IN_STEAMY_ROOM_DARK_SKIN_TONE = "\U0001f9d6\U0001f3ff"
+MAN_IN_STEAMY_ROOM = "\U0001f9d6\u200d\u2642\ufe0f"
+MAN_IN_STEAMY_ROOM_LIGHT_SKIN_TONE = "\U0001f9d6\U0001f3fb\u200d\u2642\ufe0f"
+MAN_IN_STEAMY_ROOM_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d6\U0001f3fc\u200d\u2642\ufe0f"
+MAN_IN_STEAMY_ROOM_MEDIUM_SKIN_TONE = "\U0001f9d6\U0001f3fd\u200d\u2642\ufe0f"
+MAN_IN_STEAMY_ROOM_MEDIUM_DARK_SKIN_TONE = "\U0001f9d6\U0001f3fe\u200d\u2642\ufe0f"
+MAN_IN_STEAMY_ROOM_DARK_SKIN_TONE = "\U0001f9d6\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_IN_STEAMY_ROOM = "\U0001f9d6\u200d\u2640\ufe0f"
+WOMAN_IN_STEAMY_ROOM_LIGHT_SKIN_TONE = "\U0001f9d6\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_IN_STEAMY_ROOM_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d6\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_IN_STEAMY_ROOM_MEDIUM_SKIN_TONE = "\U0001f9d6\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_IN_STEAMY_ROOM_MEDIUM_DARK_SKIN_TONE = "\U0001f9d6\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_IN_STEAMY_ROOM_DARK_SKIN_TONE = "\U0001f9d6\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_CLIMBING = "\U0001f9d7"
+PERSON_CLIMBING_LIGHT_SKIN_TONE = "\U0001f9d7\U0001f3fb"
+PERSON_CLIMBING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d7\U0001f3fc"
+PERSON_CLIMBING_MEDIUM_SKIN_TONE = "\U0001f9d7\U0001f3fd"
+PERSON_CLIMBING_MEDIUM_DARK_SKIN_TONE = "\U0001f9d7\U0001f3fe"
+PERSON_CLIMBING_DARK_SKIN_TONE = "\U0001f9d7\U0001f3ff"
+MAN_CLIMBING = "\U0001f9d7\u200d\u2642\ufe0f"
+MAN_CLIMBING_LIGHT_SKIN_TONE = "\U0001f9d7\U0001f3fb\u200d\u2642\ufe0f"
+MAN_CLIMBING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d7\U0001f3fc\u200d\u2642\ufe0f"
+MAN_CLIMBING_MEDIUM_SKIN_TONE = "\U0001f9d7\U0001f3fd\u200d\u2642\ufe0f"
+MAN_CLIMBING_MEDIUM_DARK_SKIN_TONE = "\U0001f9d7\U0001f3fe\u200d\u2642\ufe0f"
+MAN_CLIMBING_DARK_SKIN_TONE = "\U0001f9d7\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_CLIMBING = "\U0001f9d7\u200d\u2640\ufe0f"
+WOMAN_CLIMBING_LIGHT_SKIN_TONE = "\U0001f9d7\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_CLIMBING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d7\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_CLIMBING_MEDIUM_SKIN_TONE = "\U0001f9d7\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_CLIMBING_MEDIUM_DARK_SKIN_TONE = "\U0001f9d7\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_CLIMBING_DARK_SKIN_TONE = "\U0001f9d7\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_FENCING = "\U0001f93a"
+HORSE_RACING = "\U0001f3c7"
+HORSE_RACING_LIGHT_SKIN_TONE = "\U0001f3c7\U0001f3fb"
+HORSE_RACING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c7\U0001f3fc"
+HORSE_RACING_MEDIUM_SKIN_TONE = "\U0001f3c7\U0001f3fd"
+HORSE_RACING_MEDIUM_DARK_SKIN_TONE = "\U0001f3c7\U0001f3fe"
+HORSE_RACING_DARK_SKIN_TONE = "\U0001f3c7\U0001f3ff"
+SKIER = "\u26f7\ufe0f"
+SNOWBOARDER = "\U0001f3c2"
+SNOWBOARDER_LIGHT_SKIN_TONE = "\U0001f3c2\U0001f3fb"
+SNOWBOARDER_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c2\U0001f3fc"
+SNOWBOARDER_MEDIUM_SKIN_TONE = "\U0001f3c2\U0001f3fd"
+SNOWBOARDER_MEDIUM_DARK_SKIN_TONE = "\U0001f3c2\U0001f3fe"
+SNOWBOARDER_DARK_SKIN_TONE = "\U0001f3c2\U0001f3ff"
+PERSON_GOLFING = "\U0001f3cc\ufe0f"
+PERSON_GOLFING_LIGHT_SKIN_TONE = "\U0001f3cc\U0001f3fb"
+PERSON_GOLFING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3cc\U0001f3fc"
+PERSON_GOLFING_MEDIUM_SKIN_TONE = "\U0001f3cc\U0001f3fd"
+PERSON_GOLFING_MEDIUM_DARK_SKIN_TONE = "\U0001f3cc\U0001f3fe"
+PERSON_GOLFING_DARK_SKIN_TONE = "\U0001f3cc\U0001f3ff"
+MAN_GOLFING = "\U0001f3cc\ufe0f\u200d\u2642\ufe0f"
+MAN_GOLFING_LIGHT_SKIN_TONE = "\U0001f3cc\U0001f3fb\u200d\u2642\ufe0f"
+MAN_GOLFING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3cc\U0001f3fc\u200d\u2642\ufe0f"
+MAN_GOLFING_MEDIUM_SKIN_TONE = "\U0001f3cc\U0001f3fd\u200d\u2642\ufe0f"
+MAN_GOLFING_MEDIUM_DARK_SKIN_TONE = "\U0001f3cc\U0001f3fe\u200d\u2642\ufe0f"
+MAN_GOLFING_DARK_SKIN_TONE = "\U0001f3cc\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_GOLFING = "\U0001f3cc\ufe0f\u200d\u2640\ufe0f"
+WOMAN_GOLFING_LIGHT_SKIN_TONE = "\U0001f3cc\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_GOLFING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3cc\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_GOLFING_MEDIUM_SKIN_TONE = "\U0001f3cc\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_GOLFING_MEDIUM_DARK_SKIN_TONE = "\U0001f3cc\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_GOLFING_DARK_SKIN_TONE = "\U0001f3cc\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_SURFING = "\U0001f3c4"
+PERSON_SURFING_LIGHT_SKIN_TONE = "\U0001f3c4\U0001f3fb"
+PERSON_SURFING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c4\U0001f3fc"
+PERSON_SURFING_MEDIUM_SKIN_TONE = "\U0001f3c4\U0001f3fd"
+PERSON_SURFING_MEDIUM_DARK_SKIN_TONE = "\U0001f3c4\U0001f3fe"
+PERSON_SURFING_DARK_SKIN_TONE = "\U0001f3c4\U0001f3ff"
+MAN_SURFING = "\U0001f3c4\u200d\u2642\ufe0f"
+MAN_SURFING_LIGHT_SKIN_TONE = "\U0001f3c4\U0001f3fb\u200d\u2642\ufe0f"
+MAN_SURFING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c4\U0001f3fc\u200d\u2642\ufe0f"
+MAN_SURFING_MEDIUM_SKIN_TONE = "\U0001f3c4\U0001f3fd\u200d\u2642\ufe0f"
+MAN_SURFING_MEDIUM_DARK_SKIN_TONE = "\U0001f3c4\U0001f3fe\u200d\u2642\ufe0f"
+MAN_SURFING_DARK_SKIN_TONE = "\U0001f3c4\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_SURFING = "\U0001f3c4\u200d\u2640\ufe0f"
+WOMAN_SURFING_LIGHT_SKIN_TONE = "\U0001f3c4\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_SURFING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3c4\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_SURFING_MEDIUM_SKIN_TONE = "\U0001f3c4\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_SURFING_MEDIUM_DARK_SKIN_TONE = "\U0001f3c4\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_SURFING_DARK_SKIN_TONE = "\U0001f3c4\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_ROWING_BOAT = "\U0001f6a3"
+PERSON_ROWING_BOAT_LIGHT_SKIN_TONE = "\U0001f6a3\U0001f3fb"
+PERSON_ROWING_BOAT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6a3\U0001f3fc"
+PERSON_ROWING_BOAT_MEDIUM_SKIN_TONE = "\U0001f6a3\U0001f3fd"
+PERSON_ROWING_BOAT_MEDIUM_DARK_SKIN_TONE = "\U0001f6a3\U0001f3fe"
+PERSON_ROWING_BOAT_DARK_SKIN_TONE = "\U0001f6a3\U0001f3ff"
+MAN_ROWING_BOAT = "\U0001f6a3\u200d\u2642\ufe0f"
+MAN_ROWING_BOAT_LIGHT_SKIN_TONE = "\U0001f6a3\U0001f3fb\u200d\u2642\ufe0f"
+MAN_ROWING_BOAT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6a3\U0001f3fc\u200d\u2642\ufe0f"
+MAN_ROWING_BOAT_MEDIUM_SKIN_TONE = "\U0001f6a3\U0001f3fd\u200d\u2642\ufe0f"
+MAN_ROWING_BOAT_MEDIUM_DARK_SKIN_TONE = "\U0001f6a3\U0001f3fe\u200d\u2642\ufe0f"
+MAN_ROWING_BOAT_DARK_SKIN_TONE = "\U0001f6a3\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_ROWING_BOAT = "\U0001f6a3\u200d\u2640\ufe0f"
+WOMAN_ROWING_BOAT_LIGHT_SKIN_TONE = "\U0001f6a3\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_ROWING_BOAT_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6a3\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_ROWING_BOAT_MEDIUM_SKIN_TONE = "\U0001f6a3\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_ROWING_BOAT_MEDIUM_DARK_SKIN_TONE = "\U0001f6a3\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_ROWING_BOAT_DARK_SKIN_TONE = "\U0001f6a3\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_SWIMMING = "\U0001f3ca"
+PERSON_SWIMMING_LIGHT_SKIN_TONE = "\U0001f3ca\U0001f3fb"
+PERSON_SWIMMING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3ca\U0001f3fc"
+PERSON_SWIMMING_MEDIUM_SKIN_TONE = "\U0001f3ca\U0001f3fd"
+PERSON_SWIMMING_MEDIUM_DARK_SKIN_TONE = "\U0001f3ca\U0001f3fe"
+PERSON_SWIMMING_DARK_SKIN_TONE = "\U0001f3ca\U0001f3ff"
+MAN_SWIMMING = "\U0001f3ca\u200d\u2642\ufe0f"
+MAN_SWIMMING_LIGHT_SKIN_TONE = "\U0001f3ca\U0001f3fb\u200d\u2642\ufe0f"
+MAN_SWIMMING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3ca\U0001f3fc\u200d\u2642\ufe0f"
+MAN_SWIMMING_MEDIUM_SKIN_TONE = "\U0001f3ca\U0001f3fd\u200d\u2642\ufe0f"
+MAN_SWIMMING_MEDIUM_DARK_SKIN_TONE = "\U0001f3ca\U0001f3fe\u200d\u2642\ufe0f"
+MAN_SWIMMING_DARK_SKIN_TONE = "\U0001f3ca\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_SWIMMING = "\U0001f3ca\u200d\u2640\ufe0f"
+WOMAN_SWIMMING_LIGHT_SKIN_TONE = "\U0001f3ca\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_SWIMMING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3ca\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_SWIMMING_MEDIUM_SKIN_TONE = "\U0001f3ca\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_SWIMMING_MEDIUM_DARK_SKIN_TONE = "\U0001f3ca\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_SWIMMING_DARK_SKIN_TONE = "\U0001f3ca\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_BOUNCING_BALL = "\u26f9\ufe0f"
+PERSON_BOUNCING_BALL_LIGHT_SKIN_TONE = "\u26f9\U0001f3fb"
+PERSON_BOUNCING_BALL_MEDIUM_LIGHT_SKIN_TONE = "\u26f9\U0001f3fc"
+PERSON_BOUNCING_BALL_MEDIUM_SKIN_TONE = "\u26f9\U0001f3fd"
+PERSON_BOUNCING_BALL_MEDIUM_DARK_SKIN_TONE = "\u26f9\U0001f3fe"
+PERSON_BOUNCING_BALL_DARK_SKIN_TONE = "\u26f9\U0001f3ff"
+MAN_BOUNCING_BALL = "\u26f9\ufe0f\u200d\u2642\ufe0f"
+MAN_BOUNCING_BALL_LIGHT_SKIN_TONE = "\u26f9\U0001f3fb\u200d\u2642\ufe0f"
+MAN_BOUNCING_BALL_MEDIUM_LIGHT_SKIN_TONE = "\u26f9\U0001f3fc\u200d\u2642\ufe0f"
+MAN_BOUNCING_BALL_MEDIUM_SKIN_TONE = "\u26f9\U0001f3fd\u200d\u2642\ufe0f"
+MAN_BOUNCING_BALL_MEDIUM_DARK_SKIN_TONE = "\u26f9\U0001f3fe\u200d\u2642\ufe0f"
+MAN_BOUNCING_BALL_DARK_SKIN_TONE = "\u26f9\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_BOUNCING_BALL = "\u26f9\ufe0f\u200d\u2640\ufe0f"
+WOMAN_BOUNCING_BALL_LIGHT_SKIN_TONE = "\u26f9\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_BOUNCING_BALL_MEDIUM_LIGHT_SKIN_TONE = "\u26f9\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_BOUNCING_BALL_MEDIUM_SKIN_TONE = "\u26f9\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_BOUNCING_BALL_MEDIUM_DARK_SKIN_TONE = "\u26f9\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_BOUNCING_BALL_DARK_SKIN_TONE = "\u26f9\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_LIFTING_WEIGHTS = "\U0001f3cb\ufe0f"
+PERSON_LIFTING_WEIGHTS_LIGHT_SKIN_TONE = "\U0001f3cb\U0001f3fb"
+PERSON_LIFTING_WEIGHTS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3cb\U0001f3fc"
+PERSON_LIFTING_WEIGHTS_MEDIUM_SKIN_TONE = "\U0001f3cb\U0001f3fd"
+PERSON_LIFTING_WEIGHTS_MEDIUM_DARK_SKIN_TONE = "\U0001f3cb\U0001f3fe"
+PERSON_LIFTING_WEIGHTS_DARK_SKIN_TONE = "\U0001f3cb\U0001f3ff"
+MAN_LIFTING_WEIGHTS = "\U0001f3cb\ufe0f\u200d\u2642\ufe0f"
+MAN_LIFTING_WEIGHTS_LIGHT_SKIN_TONE = "\U0001f3cb\U0001f3fb\u200d\u2642\ufe0f"
+MAN_LIFTING_WEIGHTS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3cb\U0001f3fc\u200d\u2642\ufe0f"
+MAN_LIFTING_WEIGHTS_MEDIUM_SKIN_TONE = "\U0001f3cb\U0001f3fd\u200d\u2642\ufe0f"
+MAN_LIFTING_WEIGHTS_MEDIUM_DARK_SKIN_TONE = "\U0001f3cb\U0001f3fe\u200d\u2642\ufe0f"
+MAN_LIFTING_WEIGHTS_DARK_SKIN_TONE = "\U0001f3cb\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_LIFTING_WEIGHTS = "\U0001f3cb\ufe0f\u200d\u2640\ufe0f"
+WOMAN_LIFTING_WEIGHTS_LIGHT_SKIN_TONE = "\U0001f3cb\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_LIFTING_WEIGHTS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f3cb\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_LIFTING_WEIGHTS_MEDIUM_SKIN_TONE = "\U0001f3cb\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_LIFTING_WEIGHTS_MEDIUM_DARK_SKIN_TONE = "\U0001f3cb\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_LIFTING_WEIGHTS_DARK_SKIN_TONE = "\U0001f3cb\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_BIKING = "\U0001f6b4"
+PERSON_BIKING_LIGHT_SKIN_TONE = "\U0001f6b4\U0001f3fb"
+PERSON_BIKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b4\U0001f3fc"
+PERSON_BIKING_MEDIUM_SKIN_TONE = "\U0001f6b4\U0001f3fd"
+PERSON_BIKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b4\U0001f3fe"
+PERSON_BIKING_DARK_SKIN_TONE = "\U0001f6b4\U0001f3ff"
+MAN_BIKING = "\U0001f6b4\u200d\u2642\ufe0f"
+MAN_BIKING_LIGHT_SKIN_TONE = "\U0001f6b4\U0001f3fb\u200d\u2642\ufe0f"
+MAN_BIKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b4\U0001f3fc\u200d\u2642\ufe0f"
+MAN_BIKING_MEDIUM_SKIN_TONE = "\U0001f6b4\U0001f3fd\u200d\u2642\ufe0f"
+MAN_BIKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b4\U0001f3fe\u200d\u2642\ufe0f"
+MAN_BIKING_DARK_SKIN_TONE = "\U0001f6b4\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_BIKING = "\U0001f6b4\u200d\u2640\ufe0f"
+WOMAN_BIKING_LIGHT_SKIN_TONE = "\U0001f6b4\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_BIKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b4\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_BIKING_MEDIUM_SKIN_TONE = "\U0001f6b4\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_BIKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b4\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_BIKING_DARK_SKIN_TONE = "\U0001f6b4\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_MOUNTAIN_BIKING = "\U0001f6b5"
+PERSON_MOUNTAIN_BIKING_LIGHT_SKIN_TONE = "\U0001f6b5\U0001f3fb"
+PERSON_MOUNTAIN_BIKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b5\U0001f3fc"
+PERSON_MOUNTAIN_BIKING_MEDIUM_SKIN_TONE = "\U0001f6b5\U0001f3fd"
+PERSON_MOUNTAIN_BIKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b5\U0001f3fe"
+PERSON_MOUNTAIN_BIKING_DARK_SKIN_TONE = "\U0001f6b5\U0001f3ff"
+MAN_MOUNTAIN_BIKING = "\U0001f6b5\u200d\u2642\ufe0f"
+MAN_MOUNTAIN_BIKING_LIGHT_SKIN_TONE = "\U0001f6b5\U0001f3fb\u200d\u2642\ufe0f"
+MAN_MOUNTAIN_BIKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b5\U0001f3fc\u200d\u2642\ufe0f"
+MAN_MOUNTAIN_BIKING_MEDIUM_SKIN_TONE = "\U0001f6b5\U0001f3fd\u200d\u2642\ufe0f"
+MAN_MOUNTAIN_BIKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b5\U0001f3fe\u200d\u2642\ufe0f"
+MAN_MOUNTAIN_BIKING_DARK_SKIN_TONE = "\U0001f6b5\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_MOUNTAIN_BIKING = "\U0001f6b5\u200d\u2640\ufe0f"
+WOMAN_MOUNTAIN_BIKING_LIGHT_SKIN_TONE = "\U0001f6b5\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_MOUNTAIN_BIKING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6b5\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_MOUNTAIN_BIKING_MEDIUM_SKIN_TONE = "\U0001f6b5\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_MOUNTAIN_BIKING_MEDIUM_DARK_SKIN_TONE = "\U0001f6b5\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_MOUNTAIN_BIKING_DARK_SKIN_TONE = "\U0001f6b5\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_CARTWHEELING = "\U0001f938"
+PERSON_CARTWHEELING_LIGHT_SKIN_TONE = "\U0001f938\U0001f3fb"
+PERSON_CARTWHEELING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f938\U0001f3fc"
+PERSON_CARTWHEELING_MEDIUM_SKIN_TONE = "\U0001f938\U0001f3fd"
+PERSON_CARTWHEELING_MEDIUM_DARK_SKIN_TONE = "\U0001f938\U0001f3fe"
+PERSON_CARTWHEELING_DARK_SKIN_TONE = "\U0001f938\U0001f3ff"
+MAN_CARTWHEELING = "\U0001f938\u200d\u2642\ufe0f"
+MAN_CARTWHEELING_LIGHT_SKIN_TONE = "\U0001f938\U0001f3fb\u200d\u2642\ufe0f"
+MAN_CARTWHEELING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f938\U0001f3fc\u200d\u2642\ufe0f"
+MAN_CARTWHEELING_MEDIUM_SKIN_TONE = "\U0001f938\U0001f3fd\u200d\u2642\ufe0f"
+MAN_CARTWHEELING_MEDIUM_DARK_SKIN_TONE = "\U0001f938\U0001f3fe\u200d\u2642\ufe0f"
+MAN_CARTWHEELING_DARK_SKIN_TONE = "\U0001f938\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_CARTWHEELING = "\U0001f938\u200d\u2640\ufe0f"
+WOMAN_CARTWHEELING_LIGHT_SKIN_TONE = "\U0001f938\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_CARTWHEELING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f938\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_CARTWHEELING_MEDIUM_SKIN_TONE = "\U0001f938\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_CARTWHEELING_MEDIUM_DARK_SKIN_TONE = "\U0001f938\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_CARTWHEELING_DARK_SKIN_TONE = "\U0001f938\U0001f3ff\u200d\u2640\ufe0f"
+PEOPLE_WRESTLING = "\U0001f93c"
+PERSON_PLAYING_WATER_POLO = "\U0001f93d"
+PERSON_PLAYING_WATER_POLO_LIGHT_SKIN_TONE = "\U0001f93d\U0001f3fb"
+PERSON_PLAYING_WATER_POLO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f93d\U0001f3fc"
+PERSON_PLAYING_WATER_POLO_MEDIUM_SKIN_TONE = "\U0001f93d\U0001f3fd"
+PERSON_PLAYING_WATER_POLO_MEDIUM_DARK_SKIN_TONE = "\U0001f93d\U0001f3fe"
+PERSON_PLAYING_WATER_POLO_DARK_SKIN_TONE = "\U0001f93d\U0001f3ff"
+MAN_PLAYING_WATER_POLO = "\U0001f93d\u200d\u2642\ufe0f"
+MAN_PLAYING_WATER_POLO_LIGHT_SKIN_TONE = "\U0001f93d\U0001f3fb\u200d\u2642\ufe0f"
+MAN_PLAYING_WATER_POLO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f93d\U0001f3fc\u200d\u2642\ufe0f"
+MAN_PLAYING_WATER_POLO_MEDIUM_SKIN_TONE = "\U0001f93d\U0001f3fd\u200d\u2642\ufe0f"
+MAN_PLAYING_WATER_POLO_MEDIUM_DARK_SKIN_TONE = "\U0001f93d\U0001f3fe\u200d\u2642\ufe0f"
+MAN_PLAYING_WATER_POLO_DARK_SKIN_TONE = "\U0001f93d\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_PLAYING_WATER_POLO = "\U0001f93d\u200d\u2640\ufe0f"
+WOMAN_PLAYING_WATER_POLO_LIGHT_SKIN_TONE = "\U0001f93d\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_PLAYING_WATER_POLO_MEDIUM_LIGHT_SKIN_TONE = "\U0001f93d\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_PLAYING_WATER_POLO_MEDIUM_SKIN_TONE = "\U0001f93d\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_PLAYING_WATER_POLO_MEDIUM_DARK_SKIN_TONE = "\U0001f93d\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_PLAYING_WATER_POLO_DARK_SKIN_TONE = "\U0001f93d\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_PLAYING_HANDBALL = "\U0001f93e"
+PERSON_PLAYING_HANDBALL_LIGHT_SKIN_TONE = "\U0001f93e\U0001f3fb"
+PERSON_PLAYING_HANDBALL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f93e\U0001f3fc"
+PERSON_PLAYING_HANDBALL_MEDIUM_SKIN_TONE = "\U0001f93e\U0001f3fd"
+PERSON_PLAYING_HANDBALL_MEDIUM_DARK_SKIN_TONE = "\U0001f93e\U0001f3fe"
+PERSON_PLAYING_HANDBALL_DARK_SKIN_TONE = "\U0001f93e\U0001f3ff"
+MAN_PLAYING_HANDBALL = "\U0001f93e\u200d\u2642\ufe0f"
+MAN_PLAYING_HANDBALL_LIGHT_SKIN_TONE = "\U0001f93e\U0001f3fb\u200d\u2642\ufe0f"
+MAN_PLAYING_HANDBALL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f93e\U0001f3fc\u200d\u2642\ufe0f"
+MAN_PLAYING_HANDBALL_MEDIUM_SKIN_TONE = "\U0001f93e\U0001f3fd\u200d\u2642\ufe0f"
+MAN_PLAYING_HANDBALL_MEDIUM_DARK_SKIN_TONE = "\U0001f93e\U0001f3fe\u200d\u2642\ufe0f"
+MAN_PLAYING_HANDBALL_DARK_SKIN_TONE = "\U0001f93e\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_PLAYING_HANDBALL = "\U0001f93e\u200d\u2640\ufe0f"
+WOMAN_PLAYING_HANDBALL_LIGHT_SKIN_TONE = "\U0001f93e\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_PLAYING_HANDBALL_MEDIUM_LIGHT_SKIN_TONE = "\U0001f93e\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_PLAYING_HANDBALL_MEDIUM_SKIN_TONE = "\U0001f93e\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_PLAYING_HANDBALL_MEDIUM_DARK_SKIN_TONE = "\U0001f93e\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_PLAYING_HANDBALL_DARK_SKIN_TONE = "\U0001f93e\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_JUGGLING = "\U0001f939"
+PERSON_JUGGLING_LIGHT_SKIN_TONE = "\U0001f939\U0001f3fb"
+PERSON_JUGGLING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f939\U0001f3fc"
+PERSON_JUGGLING_MEDIUM_SKIN_TONE = "\U0001f939\U0001f3fd"
+PERSON_JUGGLING_MEDIUM_DARK_SKIN_TONE = "\U0001f939\U0001f3fe"
+PERSON_JUGGLING_DARK_SKIN_TONE = "\U0001f939\U0001f3ff"
+MAN_JUGGLING = "\U0001f939\u200d\u2642\ufe0f"
+MAN_JUGGLING_LIGHT_SKIN_TONE = "\U0001f939\U0001f3fb\u200d\u2642\ufe0f"
+MAN_JUGGLING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f939\U0001f3fc\u200d\u2642\ufe0f"
+MAN_JUGGLING_MEDIUM_SKIN_TONE = "\U0001f939\U0001f3fd\u200d\u2642\ufe0f"
+MAN_JUGGLING_MEDIUM_DARK_SKIN_TONE = "\U0001f939\U0001f3fe\u200d\u2642\ufe0f"
+MAN_JUGGLING_DARK_SKIN_TONE = "\U0001f939\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_JUGGLING = "\U0001f939\u200d\u2640\ufe0f"
+WOMAN_JUGGLING_LIGHT_SKIN_TONE = "\U0001f939\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_JUGGLING_MEDIUM_LIGHT_SKIN_TONE = "\U0001f939\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_JUGGLING_MEDIUM_SKIN_TONE = "\U0001f939\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_JUGGLING_MEDIUM_DARK_SKIN_TONE = "\U0001f939\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_JUGGLING_DARK_SKIN_TONE = "\U0001f939\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_IN_LOTUS_POSITION = "\U0001f9d8"
+PERSON_IN_LOTUS_POSITION_LIGHT_SKIN_TONE = "\U0001f9d8\U0001f3fb"
+PERSON_IN_LOTUS_POSITION_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d8\U0001f3fc"
+PERSON_IN_LOTUS_POSITION_MEDIUM_SKIN_TONE = "\U0001f9d8\U0001f3fd"
+PERSON_IN_LOTUS_POSITION_MEDIUM_DARK_SKIN_TONE = "\U0001f9d8\U0001f3fe"
+PERSON_IN_LOTUS_POSITION_DARK_SKIN_TONE = "\U0001f9d8\U0001f3ff"
+MAN_IN_LOTUS_POSITION = "\U0001f9d8\u200d\u2642\ufe0f"
+MAN_IN_LOTUS_POSITION_LIGHT_SKIN_TONE = "\U0001f9d8\U0001f3fb\u200d\u2642\ufe0f"
+MAN_IN_LOTUS_POSITION_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d8\U0001f3fc\u200d\u2642\ufe0f"
+MAN_IN_LOTUS_POSITION_MEDIUM_SKIN_TONE = "\U0001f9d8\U0001f3fd\u200d\u2642\ufe0f"
+MAN_IN_LOTUS_POSITION_MEDIUM_DARK_SKIN_TONE = "\U0001f9d8\U0001f3fe\u200d\u2642\ufe0f"
+MAN_IN_LOTUS_POSITION_DARK_SKIN_TONE = "\U0001f9d8\U0001f3ff\u200d\u2642\ufe0f"
+WOMAN_IN_LOTUS_POSITION = "\U0001f9d8\u200d\u2640\ufe0f"
+WOMAN_IN_LOTUS_POSITION_LIGHT_SKIN_TONE = "\U0001f9d8\U0001f3fb\u200d\u2640\ufe0f"
+WOMAN_IN_LOTUS_POSITION_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d8\U0001f3fc\u200d\u2640\ufe0f"
+WOMAN_IN_LOTUS_POSITION_MEDIUM_SKIN_TONE = "\U0001f9d8\U0001f3fd\u200d\u2640\ufe0f"
+WOMAN_IN_LOTUS_POSITION_MEDIUM_DARK_SKIN_TONE = "\U0001f9d8\U0001f3fe\u200d\u2640\ufe0f"
+WOMAN_IN_LOTUS_POSITION_DARK_SKIN_TONE = "\U0001f9d8\U0001f3ff\u200d\u2640\ufe0f"
+PERSON_TAKING_BATH = "\U0001f6c0"
+PERSON_TAKING_BATH_LIGHT_SKIN_TONE = "\U0001f6c0\U0001f3fb"
+PERSON_TAKING_BATH_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6c0\U0001f3fc"
+PERSON_TAKING_BATH_MEDIUM_SKIN_TONE = "\U0001f6c0\U0001f3fd"
+PERSON_TAKING_BATH_MEDIUM_DARK_SKIN_TONE = "\U0001f6c0\U0001f3fe"
+PERSON_TAKING_BATH_DARK_SKIN_TONE = "\U0001f6c0\U0001f3ff"
+PERSON_IN_BED = "\U0001f6cc"
+PERSON_IN_BED_LIGHT_SKIN_TONE = "\U0001f6cc\U0001f3fb"
+PERSON_IN_BED_MEDIUM_LIGHT_SKIN_TONE = "\U0001f6cc\U0001f3fc"
+PERSON_IN_BED_MEDIUM_SKIN_TONE = "\U0001f6cc\U0001f3fd"
+PERSON_IN_BED_MEDIUM_DARK_SKIN_TONE = "\U0001f6cc\U0001f3fe"
+PERSON_IN_BED_DARK_SKIN_TONE = "\U0001f6cc\U0001f3ff"
+PEOPLE_HOLDING_HANDS = "\U0001f9d1\u200d\U0001f91d\u200d\U0001f9d1"
+PEOPLE_HOLDING_HANDS_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fb"
+PEOPLE_HOLDING_HANDS_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f9d1\U0001f3fb\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fc"
+PEOPLE_HOLDING_HANDS_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \
+ "\U0001f9d1\U0001f3fb\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fd"
+PEOPLE_HOLDING_HANDS_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f9d1\U0001f3fb\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fe"
+PEOPLE_HOLDING_HANDS_LIGHT_SKIN_TONE_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fb\u200d\U0001f91d\u200d\U0001f9d1\U0001f3ff"
+PEOPLE_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \
+ "\U0001f9d1\U0001f3fc\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fb"
+PEOPLE_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3fc\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fc"
+PEOPLE_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \
+ "\U0001f9d1\U0001f3fc\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fd"
+PEOPLE_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f9d1\U0001f3fc\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fe"
+PEOPLE_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \
+ "\U0001f9d1\U0001f3fc\u200d\U0001f91d\u200d\U0001f9d1\U0001f3ff"
+PEOPLE_HOLDING_HANDS_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \
+ "\U0001f9d1\U0001f3fd\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fb"
+PEOPLE_HOLDING_HANDS_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f9d1\U0001f3fd\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fc"
+PEOPLE_HOLDING_HANDS_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fd"
+PEOPLE_HOLDING_HANDS_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f9d1\U0001f3fd\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fe"
+PEOPLE_HOLDING_HANDS_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fd\u200d\U0001f91d\u200d\U0001f9d1\U0001f3ff"
+PEOPLE_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \
+ "\U0001f9d1\U0001f3fe\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fb"
+PEOPLE_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f9d1\U0001f3fe\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fc"
+PEOPLE_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \
+ "\U0001f9d1\U0001f3fe\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fd"
+PEOPLE_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE = "\U0001f9d1\U0001f3fe\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fe"
+PEOPLE_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \
+ "\U0001f9d1\U0001f3fe\u200d\U0001f91d\u200d\U0001f9d1\U0001f3ff"
+PEOPLE_HOLDING_HANDS_DARK_SKIN_TONE_LIGHT_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fb"
+PEOPLE_HOLDING_HANDS_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f9d1\U0001f3ff\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fc"
+PEOPLE_HOLDING_HANDS_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fd"
+PEOPLE_HOLDING_HANDS_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f9d1\U0001f3ff\u200d\U0001f91d\u200d\U0001f9d1\U0001f3fe"
+PEOPLE_HOLDING_HANDS_DARK_SKIN_TONE = "\U0001f9d1\U0001f3ff\u200d\U0001f91d\u200d\U0001f9d1\U0001f3ff"
+WOMEN_HOLDING_HANDS = "\U0001f46d"
+WOMEN_HOLDING_HANDS_LIGHT_SKIN_TONE = "\U0001f46d\U0001f3fb"
+WOMEN_HOLDING_HANDS_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f469\U0001f3fb\u200d\U0001f91d\u200d\U0001f469\U0001f3fc"
+WOMEN_HOLDING_HANDS_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f91d\u200d\U0001f469\U0001f3fd"
+WOMEN_HOLDING_HANDS_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f469\U0001f3fb\u200d\U0001f91d\u200d\U0001f469\U0001f3fe"
+WOMEN_HOLDING_HANDS_LIGHT_SKIN_TONE_DARK_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\U0001f91d\u200d\U0001f469\U0001f3ff"
+WOMEN_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \
+ "\U0001f469\U0001f3fc\u200d\U0001f91d\u200d\U0001f469\U0001f3fb"
+WOMEN_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f46d\U0001f3fc"
+WOMEN_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \
+ "\U0001f469\U0001f3fc\u200d\U0001f91d\u200d\U0001f469\U0001f3fd"
+WOMEN_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f469\U0001f3fc\u200d\U0001f91d\u200d\U0001f469\U0001f3fe"
+WOMEN_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \
+ "\U0001f469\U0001f3fc\u200d\U0001f91d\u200d\U0001f469\U0001f3ff"
+WOMEN_HOLDING_HANDS_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f91d\u200d\U0001f469\U0001f3fb"
+WOMEN_HOLDING_HANDS_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f469\U0001f3fd\u200d\U0001f91d\u200d\U0001f469\U0001f3fc"
+WOMEN_HOLDING_HANDS_MEDIUM_SKIN_TONE = "\U0001f46d\U0001f3fd"
+WOMEN_HOLDING_HANDS_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f469\U0001f3fd\u200d\U0001f91d\u200d\U0001f469\U0001f3fe"
+WOMEN_HOLDING_HANDS_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\U0001f91d\u200d\U0001f469\U0001f3ff"
+WOMEN_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \
+ "\U0001f469\U0001f3fe\u200d\U0001f91d\u200d\U0001f469\U0001f3fb"
+WOMEN_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f469\U0001f3fe\u200d\U0001f91d\u200d\U0001f469\U0001f3fc"
+WOMEN_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \
+ "\U0001f469\U0001f3fe\u200d\U0001f91d\u200d\U0001f469\U0001f3fd"
+WOMEN_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE = "\U0001f46d\U0001f3fe"
+WOMEN_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \
+ "\U0001f469\U0001f3fe\u200d\U0001f91d\u200d\U0001f469\U0001f3ff"
+WOMEN_HOLDING_HANDS_DARK_SKIN_TONE_LIGHT_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f91d\u200d\U0001f469\U0001f3fb"
+WOMEN_HOLDING_HANDS_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f469\U0001f3ff\u200d\U0001f91d\u200d\U0001f469\U0001f3fc"
+WOMEN_HOLDING_HANDS_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\U0001f91d\u200d\U0001f469\U0001f3fd"
+WOMEN_HOLDING_HANDS_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f469\U0001f3ff\u200d\U0001f91d\u200d\U0001f469\U0001f3fe"
+WOMEN_HOLDING_HANDS_DARK_SKIN_TONE = "\U0001f46d\U0001f3ff"
+WOMAN_AND_MAN_HOLDING_HANDS = "\U0001f46b"
+WOMAN_AND_MAN_HOLDING_HANDS_LIGHT_SKIN_TONE = "\U0001f46b\U0001f3fb"
+WOMAN_AND_MAN_HOLDING_HANDS_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f469\U0001f3fb\u200d\U0001f91d\u200d\U0001f468\U0001f3fc"
+WOMAN_AND_MAN_HOLDING_HANDS_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \
+ "\U0001f469\U0001f3fb\u200d\U0001f91d\u200d\U0001f468\U0001f3fd"
+WOMAN_AND_MAN_HOLDING_HANDS_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f469\U0001f3fb\u200d\U0001f91d\u200d\U0001f468\U0001f3fe"
+WOMAN_AND_MAN_HOLDING_HANDS_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \
+ "\U0001f469\U0001f3fb\u200d\U0001f91d\u200d\U0001f468\U0001f3ff"
+WOMAN_AND_MAN_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \
+ "\U0001f469\U0001f3fc\u200d\U0001f91d\u200d\U0001f468\U0001f3fb"
+WOMAN_AND_MAN_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f46b\U0001f3fc"
+WOMAN_AND_MAN_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \
+ "\U0001f469\U0001f3fc\u200d\U0001f91d\u200d\U0001f468\U0001f3fd"
+WOMAN_AND_MAN_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f469\U0001f3fc\u200d\U0001f91d\u200d\U0001f468\U0001f3fe"
+WOMAN_AND_MAN_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \
+ "\U0001f469\U0001f3fc\u200d\U0001f91d\u200d\U0001f468\U0001f3ff"
+WOMAN_AND_MAN_HOLDING_HANDS_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \
+ "\U0001f469\U0001f3fd\u200d\U0001f91d\u200d\U0001f468\U0001f3fb"
+WOMAN_AND_MAN_HOLDING_HANDS_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f469\U0001f3fd\u200d\U0001f91d\u200d\U0001f468\U0001f3fc"
+WOMAN_AND_MAN_HOLDING_HANDS_MEDIUM_SKIN_TONE = "\U0001f46b\U0001f3fd"
+WOMAN_AND_MAN_HOLDING_HANDS_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f469\U0001f3fd\u200d\U0001f91d\u200d\U0001f468\U0001f3fe"
+WOMAN_AND_MAN_HOLDING_HANDS_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \
+ "\U0001f469\U0001f3fd\u200d\U0001f91d\u200d\U0001f468\U0001f3ff"
+WOMAN_AND_MAN_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \
+ "\U0001f469\U0001f3fe\u200d\U0001f91d\u200d\U0001f468\U0001f3fb"
+WOMAN_AND_MAN_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f469\U0001f3fe\u200d\U0001f91d\u200d\U0001f468\U0001f3fc"
+WOMAN_AND_MAN_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \
+ "\U0001f469\U0001f3fe\u200d\U0001f91d\u200d\U0001f468\U0001f3fd"
+WOMAN_AND_MAN_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE = "\U0001f46b\U0001f3fe"
+WOMAN_AND_MAN_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \
+ "\U0001f469\U0001f3fe\u200d\U0001f91d\u200d\U0001f468\U0001f3ff"
+WOMAN_AND_MAN_HOLDING_HANDS_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \
+ "\U0001f469\U0001f3ff\u200d\U0001f91d\u200d\U0001f468\U0001f3fb"
+WOMAN_AND_MAN_HOLDING_HANDS_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f469\U0001f3ff\u200d\U0001f91d\u200d\U0001f468\U0001f3fc"
+WOMAN_AND_MAN_HOLDING_HANDS_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \
+ "\U0001f469\U0001f3ff\u200d\U0001f91d\u200d\U0001f468\U0001f3fd"
+WOMAN_AND_MAN_HOLDING_HANDS_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f469\U0001f3ff\u200d\U0001f91d\u200d\U0001f468\U0001f3fe"
+WOMAN_AND_MAN_HOLDING_HANDS_DARK_SKIN_TONE = "\U0001f46b\U0001f3ff"
+MEN_HOLDING_HANDS = "\U0001f46c"
+MEN_HOLDING_HANDS_LIGHT_SKIN_TONE = "\U0001f46c\U0001f3fb"
+MEN_HOLDING_HANDS_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f468\U0001f3fb\u200d\U0001f91d\u200d\U0001f468\U0001f3fc"
+MEN_HOLDING_HANDS_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f91d\u200d\U0001f468\U0001f3fd"
+MEN_HOLDING_HANDS_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f468\U0001f3fb\u200d\U0001f91d\u200d\U0001f468\U0001f3fe"
+MEN_HOLDING_HANDS_LIGHT_SKIN_TONE_DARK_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\U0001f91d\u200d\U0001f468\U0001f3ff"
+MEN_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \
+ "\U0001f468\U0001f3fc\u200d\U0001f91d\u200d\U0001f468\U0001f3fb"
+MEN_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f46c\U0001f3fc"
+MEN_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \
+ "\U0001f468\U0001f3fc\u200d\U0001f91d\u200d\U0001f468\U0001f3fd"
+MEN_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f468\U0001f3fc\u200d\U0001f91d\u200d\U0001f468\U0001f3fe"
+MEN_HOLDING_HANDS_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \
+ "\U0001f468\U0001f3fc\u200d\U0001f91d\u200d\U0001f468\U0001f3ff"
+MEN_HOLDING_HANDS_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f91d\u200d\U0001f468\U0001f3fb"
+MEN_HOLDING_HANDS_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f468\U0001f3fd\u200d\U0001f91d\u200d\U0001f468\U0001f3fc"
+MEN_HOLDING_HANDS_MEDIUM_SKIN_TONE = "\U0001f46c\U0001f3fd"
+MEN_HOLDING_HANDS_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f468\U0001f3fd\u200d\U0001f91d\u200d\U0001f468\U0001f3fe"
+MEN_HOLDING_HANDS_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\U0001f91d\u200d\U0001f468\U0001f3ff"
+MEN_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \
+ "\U0001f468\U0001f3fe\u200d\U0001f91d\u200d\U0001f468\U0001f3fb"
+MEN_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f468\U0001f3fe\u200d\U0001f91d\u200d\U0001f468\U0001f3fc"
+MEN_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \
+ "\U0001f468\U0001f3fe\u200d\U0001f91d\u200d\U0001f468\U0001f3fd"
+MEN_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE = "\U0001f46c\U0001f3fe"
+MEN_HOLDING_HANDS_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \
+ "\U0001f468\U0001f3fe\u200d\U0001f91d\u200d\U0001f468\U0001f3ff"
+MEN_HOLDING_HANDS_DARK_SKIN_TONE_LIGHT_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f91d\u200d\U0001f468\U0001f3fb"
+MEN_HOLDING_HANDS_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \
+ "\U0001f468\U0001f3ff\u200d\U0001f91d\u200d\U0001f468\U0001f3fc"
+MEN_HOLDING_HANDS_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\U0001f91d\u200d\U0001f468\U0001f3fd"
+MEN_HOLDING_HANDS_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \
+ "\U0001f468\U0001f3ff\u200d\U0001f91d\u200d\U0001f468\U0001f3fe"
+MEN_HOLDING_HANDS_DARK_SKIN_TONE = "\U0001f46c\U0001f3ff"
+KISS = "\U0001f48f"
+KISS_WOMAN_MAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468"
+KISS_MAN_MAN = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468"
+KISS_WOMAN_WOMAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469"
+COUPLE_WITH_HEART = "\U0001f491"
+COUPLE_WITH_HEART_WOMAN_MAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f468"
+COUPLE_WITH_HEART_MAN_MAN = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f468"
+COUPLE_WITH_HEART_WOMAN_WOMAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f469"
+FAMILY = "\U0001f46a"
+FAMILY_MAN_WOMAN_BOY = "\U0001f468\u200d\U0001f469\u200d\U0001f466"
+FAMILY_MAN_WOMAN_GIRL = "\U0001f468\u200d\U0001f469\u200d\U0001f467"
+FAMILY_MAN_WOMAN_GIRL_BOY = "\U0001f468\u200d\U0001f469\u200d\U0001f467\u200d\U0001f466"
+FAMILY_MAN_WOMAN_BOY_BOY = "\U0001f468\u200d\U0001f469\u200d\U0001f466\u200d\U0001f466"
+FAMILY_MAN_WOMAN_GIRL_GIRL = "\U0001f468\u200d\U0001f469\u200d\U0001f467\u200d\U0001f467"
+FAMILY_MAN_MAN_BOY = "\U0001f468\u200d\U0001f468\u200d\U0001f466"
+FAMILY_MAN_MAN_GIRL = "\U0001f468\u200d\U0001f468\u200d\U0001f467"
+FAMILY_MAN_MAN_GIRL_BOY = "\U0001f468\u200d\U0001f468\u200d\U0001f467\u200d\U0001f466"
+FAMILY_MAN_MAN_BOY_BOY = "\U0001f468\u200d\U0001f468\u200d\U0001f466\u200d\U0001f466"
+FAMILY_MAN_MAN_GIRL_GIRL = "\U0001f468\u200d\U0001f468\u200d\U0001f467\u200d\U0001f467"
+FAMILY_WOMAN_WOMAN_BOY = "\U0001f469\u200d\U0001f469\u200d\U0001f466"
+FAMILY_WOMAN_WOMAN_GIRL = "\U0001f469\u200d\U0001f469\u200d\U0001f467"
+FAMILY_WOMAN_WOMAN_GIRL_BOY = "\U0001f469\u200d\U0001f469\u200d\U0001f467\u200d\U0001f466"
+FAMILY_WOMAN_WOMAN_BOY_BOY = "\U0001f469\u200d\U0001f469\u200d\U0001f466\u200d\U0001f466"
+FAMILY_WOMAN_WOMAN_GIRL_GIRL = "\U0001f469\u200d\U0001f469\u200d\U0001f467\u200d\U0001f467"
+FAMILY_MAN_BOY = "\U0001f468\u200d\U0001f466"
+FAMILY_MAN_BOY_BOY = "\U0001f468\u200d\U0001f466\u200d\U0001f466"
+FAMILY_MAN_GIRL = "\U0001f468\u200d\U0001f467"
+FAMILY_MAN_GIRL_BOY = "\U0001f468\u200d\U0001f467\u200d\U0001f466"
+FAMILY_MAN_GIRL_GIRL = "\U0001f468\u200d\U0001f467\u200d\U0001f467"
+FAMILY_WOMAN_BOY = "\U0001f469\u200d\U0001f466"
+FAMILY_WOMAN_BOY_BOY = "\U0001f469\u200d\U0001f466\u200d\U0001f466"
+FAMILY_WOMAN_GIRL = "\U0001f469\u200d\U0001f467"
+FAMILY_WOMAN_GIRL_BOY = "\U0001f469\u200d\U0001f467\u200d\U0001f466"
+FAMILY_WOMAN_GIRL_GIRL = "\U0001f469\u200d\U0001f467\u200d\U0001f467"
+SPEAKING_HEAD = "\U0001f5e3\ufe0f"
+BUST_IN_SILHOUETTE = "\U0001f464"
+BUSTS_IN_SILHOUETTE = "\U0001f465"
+PEOPLE_HUGGING = "\U0001fac2"
+FOOTPRINTS = "\U0001f463"
+LIGHT_SKIN_TONE = "\U0001f3fb"
+MEDIUM_LIGHT_SKIN_TONE = "\U0001f3fc"
+MEDIUM_SKIN_TONE = "\U0001f3fd"
+MEDIUM_DARK_SKIN_TONE = "\U0001f3fe"
+DARK_SKIN_TONE = "\U0001f3ff"
+RED_HAIR = "\U0001f9b0"
+CURLY_HAIR = "\U0001f9b1"
+WHITE_HAIR = "\U0001f9b3"
+BALD = "\U0001f9b2"
+MONKEY_FACE = "\U0001f435"
+MONKEY = "\U0001f412"
+GORILLA = "\U0001f98d"
+ORANGUTAN = "\U0001f9a7"
+DOG_FACE = "\U0001f436"
+DOG = "\U0001f415"
+GUIDE_DOG = "\U0001f9ae"
+SERVICE_DOG = "\U0001f415\u200d\U0001f9ba"
+POODLE = "\U0001f429"
+WOLF = "\U0001f43a"
+FOX = "\U0001f98a"
+RACCOON = "\U0001f99d"
+CAT_FACE = "\U0001f431"
+CAT = "\U0001f408"
+BLACK_CAT = "\U0001f408\u200d\u2b1b"
+LION = "\U0001f981"
+TIGER_FACE = "\U0001f42f"
+TIGER = "\U0001f405"
+LEOPARD = "\U0001f406"
+HORSE_FACE = "\U0001f434"
+HORSE = "\U0001f40e"
+UNICORN = "\U0001f984"
+ZEBRA = "\U0001f993"
+DEER = "\U0001f98c"
+BISON = "\U0001f9ac"
+COW_FACE = "\U0001f42e"
+OX = "\U0001f402"
+WATER_BUFFALO = "\U0001f403"
+COW = "\U0001f404"
+PIG_FACE = "\U0001f437"
+PIG = "\U0001f416"
+BOAR = "\U0001f417"
+PIG_NOSE = "\U0001f43d"
+RAM = "\U0001f40f"
+EWE = "\U0001f411"
+GOAT = "\U0001f410"
+CAMEL = "\U0001f42a"
+TWO_HUMP_CAMEL = "\U0001f42b"
+LLAMA = "\U0001f999"
+GIRAFFE = "\U0001f992"
+ELEPHANT = "\U0001f418"
+MAMMOTH = "\U0001f9a3"
+RHINOCEROS = "\U0001f98f"
+HIPPOPOTAMUS = "\U0001f99b"
+MOUSE_FACE = "\U0001f42d"
+MOUSE = "\U0001f401"
+RAT = "\U0001f400"
+HAMSTER = "\U0001f439"
+RABBIT_FACE = "\U0001f430"
+RABBIT = "\U0001f407"
+CHIPMUNK = "\U0001f43f\ufe0f"
+BEAVER = "\U0001f9ab"
+HEDGEHOG = "\U0001f994"
+BAT = "\U0001f987"
+BEAR = "\U0001f43b"
+POLAR_BEAR = "\U0001f43b\u200d\u2744\ufe0f"
+KOALA = "\U0001f428"
+PANDA = "\U0001f43c"
+SLOTH = "\U0001f9a5"
+OTTER = "\U0001f9a6"
+SKUNK = "\U0001f9a8"
+KANGAROO = "\U0001f998"
+BADGER = "\U0001f9a1"
+PAW_PRINTS = "\U0001f43e"
+TURKEY = "\U0001f983"
+CHICKEN = "\U0001f414"
+ROOSTER = "\U0001f413"
+HATCHING_CHICK = "\U0001f423"
+BABY_CHICK = "\U0001f424"
+FRONT_FACING_BABY_CHICK = "\U0001f425"
+BIRD = "\U0001f426"
+PENGUIN = "\U0001f427"
+DOVE = "\U0001f54a\ufe0f"
+EAGLE = "\U0001f985"
+DUCK = "\U0001f986"
+SWAN = "\U0001f9a2"
+OWL = "\U0001f989"
+DODO = "\U0001f9a4"
+FEATHER = "\U0001fab6"
+FLAMINGO = "\U0001f9a9"
+PEACOCK = "\U0001f99a"
+PARROT = "\U0001f99c"
+FROG = "\U0001f438"
+CROCODILE = "\U0001f40a"
+TURTLE = "\U0001f422"
+LIZARD = "\U0001f98e"
+SNAKE = "\U0001f40d"
+DRAGON_FACE = "\U0001f432"
+DRAGON = "\U0001f409"
+SAUROPOD = "\U0001f995"
+T_REX = "\U0001f996"
+SPOUTING_WHALE = "\U0001f433"
+WHALE = "\U0001f40b"
+DOLPHIN = "\U0001f42c"
+SEAL = "\U0001f9ad"
+FISH = "\U0001f41f"
+TROPICAL_FISH = "\U0001f420"
+BLOWFISH = "\U0001f421"
+SHARK = "\U0001f988"
+OCTOPUS = "\U0001f419"
+SPIRAL_SHELL = "\U0001f41a"
+SNAIL = "\U0001f40c"
+BUTTERFLY = "\U0001f98b"
+BUG = "\U0001f41b"
+ANT = "\U0001f41c"
+HONEYBEE = "\U0001f41d"
+BEETLE = "\U0001fab2"
+LADY_BEETLE = "\U0001f41e"
+CRICKET = "\U0001f997"
+COCKROACH = "\U0001fab3"
+SPIDER = "\U0001f577\ufe0f"
+SPIDER_WEB = "\U0001f578\ufe0f"
+SCORPION = "\U0001f982"
+MOSQUITO = "\U0001f99f"
+FLY = "\U0001fab0"
+WORM = "\U0001fab1"
+MICROBE = "\U0001f9a0"
+BOUQUET = "\U0001f490"
+CHERRY_BLOSSOM = "\U0001f338"
+WHITE_FLOWER = "\U0001f4ae"
+ROSETTE = "\U0001f3f5\ufe0f"
+ROSE = "\U0001f339"
+WILTED_FLOWER = "\U0001f940"
+HIBISCUS = "\U0001f33a"
+SUNFLOWER = "\U0001f33b"
+BLOSSOM = "\U0001f33c"
+TULIP = "\U0001f337"
+SEEDLING = "\U0001f331"
+POTTED_PLANT = "\U0001fab4"
+EVERGREEN_TREE = "\U0001f332"
+DECIDUOUS_TREE = "\U0001f333"
+PALM_TREE = "\U0001f334"
+CACTUS = "\U0001f335"
+SHEAF_OF_RICE = "\U0001f33e"
+HERB = "\U0001f33f"
+SHAMROCK = "\u2618\ufe0f"
+FOUR_LEAF_CLOVER = "\U0001f340"
+MAPLE_LEAF = "\U0001f341"
+FALLEN_LEAF = "\U0001f342"
+LEAF_FLUTTERING_IN_WIND = "\U0001f343"
+GRAPES = "\U0001f347"
+MELON = "\U0001f348"
+WATERMELON = "\U0001f349"
+TANGERINE = "\U0001f34a"
+LEMON = "\U0001f34b"
+BANANA = "\U0001f34c"
+PINEAPPLE = "\U0001f34d"
+MANGO = "\U0001f96d"
+RED_APPLE = "\U0001f34e"
+GREEN_APPLE = "\U0001f34f"
+PEAR = "\U0001f350"
+PEACH = "\U0001f351"
+CHERRIES = "\U0001f352"
+STRAWBERRY = "\U0001f353"
+BLUEBERRIES = "\U0001fad0"
+KIWI_FRUIT = "\U0001f95d"
+TOMATO = "\U0001f345"
+OLIVE = "\U0001fad2"
+COCONUT = "\U0001f965"
+AVOCADO = "\U0001f951"
+EGGPLANT = "\U0001f346"
+POTATO = "\U0001f954"
+CARROT = "\U0001f955"
+EAR_OF_CORN = "\U0001f33d"
+HOT_PEPPER = "\U0001f336\ufe0f"
+BELL_PEPPER = "\U0001fad1"
+CUCUMBER = "\U0001f952"
+LEAFY_GREEN = "\U0001f96c"
+BROCCOLI = "\U0001f966"
+GARLIC = "\U0001f9c4"
+ONION = "\U0001f9c5"
+MUSHROOM = "\U0001f344"
+PEANUTS = "\U0001f95c"
+CHESTNUT = "\U0001f330"
+BREAD = "\U0001f35e"
+CROISSANT = "\U0001f950"
+BAGUETTE_BREAD = "\U0001f956"
+FLATBREAD = "\U0001fad3"
+PRETZEL = "\U0001f968"
+BAGEL = "\U0001f96f"
+PANCAKES = "\U0001f95e"
+WAFFLE = "\U0001f9c7"
+CHEESE_WEDGE = "\U0001f9c0"
+MEAT_ON_BONE = "\U0001f356"
+POULTRY_LEG = "\U0001f357"
+CUT_OF_MEAT = "\U0001f969"
+BACON = "\U0001f953"
+HAMBURGER = "\U0001f354"
+FRENCH_FRIES = "\U0001f35f"
+PIZZA = "\U0001f355"
+HOT_DOG = "\U0001f32d"
+SANDWICH = "\U0001f96a"
+TACO = "\U0001f32e"
+BURRITO = "\U0001f32f"
+TAMALE = "\U0001fad4"
+STUFFED_FLATBREAD = "\U0001f959"
+FALAFEL = "\U0001f9c6"
+EGG = "\U0001f95a"
+COOKING = "\U0001f373"
+SHALLOW_PAN_OF_FOOD = "\U0001f958"
+POT_OF_FOOD = "\U0001f372"
+FONDUE = "\U0001fad5"
+BOWL_WITH_SPOON = "\U0001f963"
+GREEN_SALAD = "\U0001f957"
+POPCORN = "\U0001f37f"
+BUTTER = "\U0001f9c8"
+SALT = "\U0001f9c2"
+CANNED_FOOD = "\U0001f96b"
+BENTO_BOX = "\U0001f371"
+RICE_CRACKER = "\U0001f358"
+RICE_BALL = "\U0001f359"
+COOKED_RICE = "\U0001f35a"
+CURRY_RICE = "\U0001f35b"
+STEAMING_BOWL = "\U0001f35c"
+SPAGHETTI = "\U0001f35d"
+ROASTED_SWEET_POTATO = "\U0001f360"
+ODEN = "\U0001f362"
+SUSHI = "\U0001f363"
+FRIED_SHRIMP = "\U0001f364"
+FISH_CAKE_WITH_SWIRL = "\U0001f365"
+MOON_CAKE = "\U0001f96e"
+DANGO = "\U0001f361"
+DUMPLING = "\U0001f95f"
+FORTUNE_COOKIE = "\U0001f960"
+TAKEOUT_BOX = "\U0001f961"
+CRAB = "\U0001f980"
+LOBSTER = "\U0001f99e"
+SHRIMP = "\U0001f990"
+SQUID = "\U0001f991"
+OYSTER = "\U0001f9aa"
+SOFT_ICE_CREAM = "\U0001f366"
+SHAVED_ICE = "\U0001f367"
+ICE_CREAM = "\U0001f368"
+DOUGHNUT = "\U0001f369"
+COOKIE = "\U0001f36a"
+BIRTHDAY_CAKE = "\U0001f382"
+SHORTCAKE = "\U0001f370"
+CUPCAKE = "\U0001f9c1"
+PIE = "\U0001f967"
+CHOCOLATE_BAR = "\U0001f36b"
+CANDY = "\U0001f36c"
+LOLLIPOP = "\U0001f36d"
+CUSTARD = "\U0001f36e"
+HONEY_POT = "\U0001f36f"
+BABY_BOTTLE = "\U0001f37c"
+GLASS_OF_MILK = "\U0001f95b"
+HOT_BEVERAGE = "\u2615"
+TEAPOT = "\U0001fad6"
+TEACUP_WITHOUT_HANDLE = "\U0001f375"
+SAKE = "\U0001f376"
+BOTTLE_WITH_POPPING_CORK = "\U0001f37e"
+WINE_GLASS = "\U0001f377"
+COCKTAIL_GLASS = "\U0001f378"
+TROPICAL_DRINK = "\U0001f379"
+BEER_MUG = "\U0001f37a"
+CLINKING_BEER_MUGS = "\U0001f37b"
+CLINKING_GLASSES = "\U0001f942"
+TUMBLER_GLASS = "\U0001f943"
+CUP_WITH_STRAW = "\U0001f964"
+BUBBLE_TEA = "\U0001f9cb"
+BEVERAGE_BOX = "\U0001f9c3"
+MATE = "\U0001f9c9"
+ICE = "\U0001f9ca"
+CHOPSTICKS = "\U0001f962"
+FORK_AND_KNIFE_WITH_PLATE = "\U0001f37d\ufe0f"
+FORK_AND_KNIFE = "\U0001f374"
+SPOON = "\U0001f944"
+KITCHEN_KNIFE = "\U0001f52a"
+AMPHORA = "\U0001f3fa"
+GLOBE_SHOWING_EUROPE_AFRICA = "\U0001f30d"
+GLOBE_SHOWING_AMERICAS = "\U0001f30e"
+GLOBE_SHOWING_ASIA_AUSTRALIA = "\U0001f30f"
+GLOBE_WITH_MERIDIANS = "\U0001f310"
+WORLD_MAP = "\U0001f5fa\ufe0f"
+MAP_OF_JAPAN = "\U0001f5fe"
+COMPASS = "\U0001f9ed"
+SNOW_CAPPED_MOUNTAIN = "\U0001f3d4\ufe0f"
+MOUNTAIN = "\u26f0\ufe0f"
+VOLCANO = "\U0001f30b"
+MOUNT_FUJI = "\U0001f5fb"
+CAMPING = "\U0001f3d5\ufe0f"
+BEACH_WITH_UMBRELLA = "\U0001f3d6\ufe0f"
+DESERT = "\U0001f3dc\ufe0f"
+DESERT_ISLAND = "\U0001f3dd\ufe0f"
+NATIONAL_PARK = "\U0001f3de\ufe0f"
+STADIUM = "\U0001f3df\ufe0f"
+CLASSICAL_BUILDING = "\U0001f3db\ufe0f"
+BUILDING_CONSTRUCTION = "\U0001f3d7\ufe0f"
+BRICK = "\U0001f9f1"
+ROCK = "\U0001faa8"
+WOOD = "\U0001fab5"
+HUT = "\U0001f6d6"
+HOUSES = "\U0001f3d8\ufe0f"
+DERELICT_HOUSE = "\U0001f3da\ufe0f"
+HOUSE = "\U0001f3e0"
+HOUSE_WITH_GARDEN = "\U0001f3e1"
+OFFICE_BUILDING = "\U0001f3e2"
+JAPANESE_POST_OFFICE = "\U0001f3e3"
+POST_OFFICE = "\U0001f3e4"
+HOSPITAL = "\U0001f3e5"
+BANK = "\U0001f3e6"
+HOTEL = "\U0001f3e8"
+LOVE_HOTEL = "\U0001f3e9"
+CONVENIENCE_STORE = "\U0001f3ea"
+SCHOOL = "\U0001f3eb"
+DEPARTMENT_STORE = "\U0001f3ec"
+FACTORY = "\U0001f3ed"
+JAPANESE_CASTLE = "\U0001f3ef"
+CASTLE = "\U0001f3f0"
+WEDDING = "\U0001f492"
+TOKYO_TOWER = "\U0001f5fc"
+STATUE_OF_LIBERTY = "\U0001f5fd"
+CHURCH = "\u26ea"
+MOSQUE = "\U0001f54c"
+HINDU_TEMPLE = "\U0001f6d5"
+SYNAGOGUE = "\U0001f54d"
+SHINTO_SHRINE = "\u26e9\ufe0f"
+KAABA = "\U0001f54b"
+FOUNTAIN = "\u26f2"
+TENT = "\u26fa"
+FOGGY = "\U0001f301"
+NIGHT_WITH_STARS = "\U0001f303"
+CITYSCAPE = "\U0001f3d9\ufe0f"
+SUNRISE_OVER_MOUNTAINS = "\U0001f304"
+SUNRISE = "\U0001f305"
+CITYSCAPE_AT_DUSK = "\U0001f306"
+SUNSET = "\U0001f307"
+BRIDGE_AT_NIGHT = "\U0001f309"
+HOT_SPRINGS = "\u2668\ufe0f"
+CAROUSEL_HORSE = "\U0001f3a0"
+FERRIS_WHEEL = "\U0001f3a1"
+ROLLER_COASTER = "\U0001f3a2"
+BARBER_POLE = "\U0001f488"
+CIRCUS_TENT = "\U0001f3aa"
+LOCOMOTIVE = "\U0001f682"
+RAILWAY_CAR = "\U0001f683"
+HIGH_SPEED_TRAIN = "\U0001f684"
+BULLET_TRAIN = "\U0001f685"
+TRAIN = "\U0001f686"
+METRO = "\U0001f687"
+LIGHT_RAIL = "\U0001f688"
+STATION = "\U0001f689"
+TRAM = "\U0001f68a"
+MONORAIL = "\U0001f69d"
+MOUNTAIN_RAILWAY = "\U0001f69e"
+TRAM_CAR = "\U0001f68b"
+BUS = "\U0001f68c"
+ONCOMING_BUS = "\U0001f68d"
+TROLLEYBUS = "\U0001f68e"
+MINIBUS = "\U0001f690"
+AMBULANCE = "\U0001f691"
+FIRE_ENGINE = "\U0001f692"
+POLICE_CAR = "\U0001f693"
+ONCOMING_POLICE_CAR = "\U0001f694"
+TAXI = "\U0001f695"
+ONCOMING_TAXI = "\U0001f696"
+AUTOMOBILE = "\U0001f697"
+ONCOMING_AUTOMOBILE = "\U0001f698"
+SPORT_UTILITY_VEHICLE = "\U0001f699"
+PICKUP_TRUCK = "\U0001f6fb"
+DELIVERY_TRUCK = "\U0001f69a"
+ARTICULATED_LORRY = "\U0001f69b"
+TRACTOR = "\U0001f69c"
+RACING_CAR = "\U0001f3ce\ufe0f"
+MOTORCYCLE = "\U0001f3cd\ufe0f"
+MOTOR_SCOOTER = "\U0001f6f5"
+MANUAL_WHEELCHAIR = "\U0001f9bd"
+MOTORIZED_WHEELCHAIR = "\U0001f9bc"
+AUTO_RICKSHAW = "\U0001f6fa"
+BICYCLE = "\U0001f6b2"
+KICK_SCOOTER = "\U0001f6f4"
+SKATEBOARD = "\U0001f6f9"
+ROLLER_SKATE = "\U0001f6fc"
+BUS_STOP = "\U0001f68f"
+MOTORWAY = "\U0001f6e3\ufe0f"
+RAILWAY_TRACK = "\U0001f6e4\ufe0f"
+OIL_DRUM = "\U0001f6e2\ufe0f"
+FUEL_PUMP = "\u26fd"
+POLICE_CAR_LIGHT = "\U0001f6a8"
+HORIZONTAL_TRAFFIC_LIGHT = "\U0001f6a5"
+VERTICAL_TRAFFIC_LIGHT = "\U0001f6a6"
+STOP_SIGN = "\U0001f6d1"
+CONSTRUCTION = "\U0001f6a7"
+ANCHOR = "\u2693"
+SAILBOAT = "\u26f5"
+CANOE = "\U0001f6f6"
+SPEEDBOAT = "\U0001f6a4"
+PASSENGER_SHIP = "\U0001f6f3\ufe0f"
+FERRY = "\u26f4\ufe0f"
+MOTOR_BOAT = "\U0001f6e5\ufe0f"
+SHIP = "\U0001f6a2"
+AIRPLANE = "\u2708\ufe0f"
+SMALL_AIRPLANE = "\U0001f6e9\ufe0f"
+AIRPLANE_DEPARTURE = "\U0001f6eb"
+AIRPLANE_ARRIVAL = "\U0001f6ec"
+PARACHUTE = "\U0001fa82"
+SEAT = "\U0001f4ba"
+HELICOPTER = "\U0001f681"
+SUSPENSION_RAILWAY = "\U0001f69f"
+MOUNTAIN_CABLEWAY = "\U0001f6a0"
+AERIAL_TRAMWAY = "\U0001f6a1"
+SATELLITE = "\U0001f6f0\ufe0f"
+ROCKET = "\U0001f680"
+FLYING_SAUCER = "\U0001f6f8"
+BELLHOP_BELL = "\U0001f6ce\ufe0f"
+LUGGAGE = "\U0001f9f3"
+HOURGLASS_DONE = "\u231b"
+HOURGLASS_NOT_DONE = "\u23f3"
+WATCH = "\u231a"
+ALARM_CLOCK = "\u23f0"
+STOPWATCH = "\u23f1\ufe0f"
+TIMER_CLOCK = "\u23f2\ufe0f"
+MANTELPIECE_CLOCK = "\U0001f570\ufe0f"
+TWELVE_O_CLOCK = "\U0001f55b"
+TWELVE_THIRTY = "\U0001f567"
+ONE_O_CLOCK = "\U0001f550"
+ONE_THIRTY = "\U0001f55c"
+TWO_O_CLOCK = "\U0001f551"
+TWO_THIRTY = "\U0001f55d"
+THREE_O_CLOCK = "\U0001f552"
+THREE_THIRTY = "\U0001f55e"
+FOUR_O_CLOCK = "\U0001f553"
+FOUR_THIRTY = "\U0001f55f"
+FIVE_O_CLOCK = "\U0001f554"
+FIVE_THIRTY = "\U0001f560"
+SIX_O_CLOCK = "\U0001f555"
+SIX_THIRTY = "\U0001f561"
+SEVEN_O_CLOCK = "\U0001f556"
+SEVEN_THIRTY = "\U0001f562"
+EIGHT_O_CLOCK = "\U0001f557"
+EIGHT_THIRTY = "\U0001f563"
+NINE_O_CLOCK = "\U0001f558"
+NINE_THIRTY = "\U0001f564"
+TEN_O_CLOCK = "\U0001f559"
+TEN_THIRTY = "\U0001f565"
+ELEVEN_O_CLOCK = "\U0001f55a"
+ELEVEN_THIRTY = "\U0001f566"
+NEW_MOON = "\U0001f311"
+WAXING_CRESCENT_MOON = "\U0001f312"
+FIRST_QUARTER_MOON = "\U0001f313"
+WAXING_GIBBOUS_MOON = "\U0001f314"
+FULL_MOON = "\U0001f315"
+WANING_GIBBOUS_MOON = "\U0001f316"
+LAST_QUARTER_MOON = "\U0001f317"
+WANING_CRESCENT_MOON = "\U0001f318"
+CRESCENT_MOON = "\U0001f319"
+NEW_MOON_FACE = "\U0001f31a"
+FIRST_QUARTER_MOON_FACE = "\U0001f31b"
+LAST_QUARTER_MOON_FACE = "\U0001f31c"
+THERMOMETER = "\U0001f321\ufe0f"
+SUN = "\u2600\ufe0f"
+FULL_MOON_FACE = "\U0001f31d"
+SUN_WITH_FACE = "\U0001f31e"
+RINGED_PLANET = "\U0001fa90"
+STAR = "\u2b50"
+GLOWING_STAR = "\U0001f31f"
+SHOOTING_STAR = "\U0001f320"
+MILKY_WAY = "\U0001f30c"
+CLOUD = "\u2601\ufe0f"
+SUN_BEHIND_CLOUD = "\u26c5"
+CLOUD_WITH_LIGHTNING_AND_RAIN = "\u26c8\ufe0f"
+SUN_BEHIND_SMALL_CLOUD = "\U0001f324\ufe0f"
+SUN_BEHIND_LARGE_CLOUD = "\U0001f325\ufe0f"
+SUN_BEHIND_RAIN_CLOUD = "\U0001f326\ufe0f"
+CLOUD_WITH_RAIN = "\U0001f327\ufe0f"
+CLOUD_WITH_SNOW = "\U0001f328\ufe0f"
+CLOUD_WITH_LIGHTNING = "\U0001f329\ufe0f"
+TORNADO = "\U0001f32a\ufe0f"
+FOG = "\U0001f32b\ufe0f"
+WIND_FACE = "\U0001f32c\ufe0f"
+CYCLONE = "\U0001f300"
+RAINBOW = "\U0001f308"
+CLOSED_UMBRELLA = "\U0001f302"
+UMBRELLA = "\u2602\ufe0f"
+UMBRELLA_WITH_RAIN_DROPS = "\u2614"
+UMBRELLA_ON_GROUND = "\u26f1\ufe0f"
+HIGH_VOLTAGE = "\u26a1"
+SNOWFLAKE = "\u2744\ufe0f"
+SNOWMAN = "\u2603\ufe0f"
+SNOWMAN_WITHOUT_SNOW = "\u26c4"
+COMET = "\u2604\ufe0f"
+FIRE = "\U0001f525"
+DROPLET = "\U0001f4a7"
+WATER_WAVE = "\U0001f30a"
+JACK_O_LANTERN = "\U0001f383"
+CHRISTMAS_TREE = "\U0001f384"
+FIREWORKS = "\U0001f386"
+SPARKLER = "\U0001f387"
+FIRECRACKER = "\U0001f9e8"
+SPARKLES = "\u2728"
+BALLOON = "\U0001f388"
+PARTY_POPPER = "\U0001f389"
+CONFETTI_BALL = "\U0001f38a"
+TANABATA_TREE = "\U0001f38b"
+PINE_DECORATION = "\U0001f38d"
+JAPANESE_DOLLS = "\U0001f38e"
+CARP_STREAMER = "\U0001f38f"
+WIND_CHIME = "\U0001f390"
+MOON_VIEWING_CEREMONY = "\U0001f391"
+RED_ENVELOPE = "\U0001f9e7"
+RIBBON = "\U0001f380"
+WRAPPED_GIFT = "\U0001f381"
+REMINDER_RIBBON = "\U0001f397\ufe0f"
+ADMISSION_TICKETS = "\U0001f39f\ufe0f"
+TICKET = "\U0001f3ab"
+MILITARY_MEDAL = "\U0001f396\ufe0f"
+TROPHY = "\U0001f3c6"
+SPORTS_MEDAL = "\U0001f3c5"
+FIRST_PLACE_MEDAL = "\U0001f947"
+SECOND_PLACE_MEDAL = "\U0001f948"
+THIRD_PLACE_MEDAL = "\U0001f949"
+SOCCER_BALL = "\u26bd"
+BASEBALL = "\u26be"
+SOFTBALL = "\U0001f94e"
+BASKETBALL = "\U0001f3c0"
+VOLLEYBALL = "\U0001f3d0"
+AMERICAN_FOOTBALL = "\U0001f3c8"
+RUGBY_FOOTBALL = "\U0001f3c9"
+TENNIS = "\U0001f3be"
+FLYING_DISC = "\U0001f94f"
+BOWLING = "\U0001f3b3"
+CRICKET_GAME = "\U0001f3cf"
+FIELD_HOCKEY = "\U0001f3d1"
+ICE_HOCKEY = "\U0001f3d2"
+LACROSSE = "\U0001f94d"
+PING_PONG = "\U0001f3d3"
+BADMINTON = "\U0001f3f8"
+BOXING_GLOVE = "\U0001f94a"
+MARTIAL_ARTS_UNIFORM = "\U0001f94b"
+GOAL_NET = "\U0001f945"
+FLAG_IN_HOLE = "\u26f3"
+ICE_SKATE = "\u26f8\ufe0f"
+FISHING_POLE = "\U0001f3a3"
+DIVING_MASK = "\U0001f93f"
+RUNNING_SHIRT = "\U0001f3bd"
+SKIS = "\U0001f3bf"
+SLED = "\U0001f6f7"
+CURLING_STONE = "\U0001f94c"
+DIRECT_HIT = "\U0001f3af"
+YO_YO = "\U0001fa80"
+KITE = "\U0001fa81"
+POOL_8_BALL = "\U0001f3b1"
+CRYSTAL_BALL = "\U0001f52e"
+MAGIC_WAND = "\U0001fa84"
+NAZAR_AMULET = "\U0001f9ff"
+VIDEO_GAME = "\U0001f3ae"
+JOYSTICK = "\U0001f579\ufe0f"
+SLOT_MACHINE = "\U0001f3b0"
+GAME_DIE = "\U0001f3b2"
+PUZZLE_PIECE = "\U0001f9e9"
+TEDDY_BEAR = "\U0001f9f8"
+PINATA = "\U0001fa85"
+NESTING_DOLLS = "\U0001fa86"
+SPADE_SUIT = "\u2660\ufe0f"
+HEART_SUIT = "\u2665\ufe0f"
+DIAMOND_SUIT = "\u2666\ufe0f"
+CLUB_SUIT = "\u2663\ufe0f"
+CHESS_PAWN = "\u265f\ufe0f"
+JOKER = "\U0001f0cf"
+MAHJONG_RED_DRAGON = "\U0001f004"
+FLOWER_PLAYING_CARDS = "\U0001f3b4"
+PERFORMING_ARTS = "\U0001f3ad"
+FRAMED_PICTURE = "\U0001f5bc\ufe0f"
+ARTIST_PALETTE = "\U0001f3a8"
+THREAD = "\U0001f9f5"
+SEWING_NEEDLE = "\U0001faa1"
+YARN = "\U0001f9f6"
+KNOT = "\U0001faa2"
+GLASSES = "\U0001f453"
+SUNGLASSES = "\U0001f576\ufe0f"
+GOGGLES = "\U0001f97d"
+LAB_COAT = "\U0001f97c"
+SAFETY_VEST = "\U0001f9ba"
+NECKTIE = "\U0001f454"
+T_SHIRT = "\U0001f455"
+JEANS = "\U0001f456"
+SCARF = "\U0001f9e3"
+GLOVES = "\U0001f9e4"
+COAT = "\U0001f9e5"
+SOCKS = "\U0001f9e6"
+DRESS = "\U0001f457"
+KIMONO = "\U0001f458"
+SARI = "\U0001f97b"
+ONE_PIECE_SWIMSUIT = "\U0001fa71"
+BRIEFS = "\U0001fa72"
+SHORTS = "\U0001fa73"
+BIKINI = "\U0001f459"
+WOMAN_S_CLOTHES = "\U0001f45a"
+PURSE = "\U0001f45b"
+HANDBAG = "\U0001f45c"
+CLUTCH_BAG = "\U0001f45d"
+SHOPPING_BAGS = "\U0001f6cd\ufe0f"
+BACKPACK = "\U0001f392"
+THONG_SANDAL = "\U0001fa74"
+MAN_S_SHOE = "\U0001f45e"
+RUNNING_SHOE = "\U0001f45f"
+HIKING_BOOT = "\U0001f97e"
+FLAT_SHOE = "\U0001f97f"
+HIGH_HEELED_SHOE = "\U0001f460"
+WOMAN_S_SANDAL = "\U0001f461"
+BALLET_SHOES = "\U0001fa70"
+WOMAN_S_BOOT = "\U0001f462"
+CROWN = "\U0001f451"
+WOMAN_S_HAT = "\U0001f452"
+TOP_HAT = "\U0001f3a9"
+GRADUATION_CAP = "\U0001f393"
+BILLED_CAP = "\U0001f9e2"
+MILITARY_HELMET = "\U0001fa96"
+RESCUE_WORKER_S_HELMET = "\u26d1\ufe0f"
+PRAYER_BEADS = "\U0001f4ff"
+LIPSTICK = "\U0001f484"
+RING = "\U0001f48d"
+GEM_STONE = "\U0001f48e"
+MUTED_SPEAKER = "\U0001f507"
+SPEAKER_LOW_VOLUME = "\U0001f508"
+SPEAKER_MEDIUM_VOLUME = "\U0001f509"
+SPEAKER_HIGH_VOLUME = "\U0001f50a"
+LOUDSPEAKER = "\U0001f4e2"
+MEGAPHONE = "\U0001f4e3"
+POSTAL_HORN = "\U0001f4ef"
+BELL = "\U0001f514"
+BELL_WITH_SLASH = "\U0001f515"
+MUSICAL_SCORE = "\U0001f3bc"
+MUSICAL_NOTE = "\U0001f3b5"
+MUSICAL_NOTES = "\U0001f3b6"
+STUDIO_MICROPHONE = "\U0001f399\ufe0f"
+LEVEL_SLIDER = "\U0001f39a\ufe0f"
+CONTROL_KNOBS = "\U0001f39b\ufe0f"
+MICROPHONE = "\U0001f3a4"
+HEADPHONE = "\U0001f3a7"
+RADIO = "\U0001f4fb"
+SAXOPHONE = "\U0001f3b7"
+ACCORDION = "\U0001fa97"
+GUITAR = "\U0001f3b8"
+MUSICAL_KEYBOARD = "\U0001f3b9"
+TRUMPET = "\U0001f3ba"
+VIOLIN = "\U0001f3bb"
+BANJO = "\U0001fa95"
+DRUM = "\U0001f941"
+LONG_DRUM = "\U0001fa98"
+MOBILE_PHONE = "\U0001f4f1"
+MOBILE_PHONE_WITH_ARROW = "\U0001f4f2"
+TELEPHONE = "\u260e\ufe0f"
+TELEPHONE_RECEIVER = "\U0001f4de"
+PAGER = "\U0001f4df"
+FAX_MACHINE = "\U0001f4e0"
+BATTERY = "\U0001f50b"
+ELECTRIC_PLUG = "\U0001f50c"
+LAPTOP = "\U0001f4bb"
+DESKTOP_COMPUTER = "\U0001f5a5\ufe0f"
+PRINTER = "\U0001f5a8\ufe0f"
+KEYBOARD = "\u2328\ufe0f"
+COMPUTER_MOUSE = "\U0001f5b1\ufe0f"
+TRACKBALL = "\U0001f5b2\ufe0f"
+COMPUTER_DISK = "\U0001f4bd"
+FLOPPY_DISK = "\U0001f4be"
+OPTICAL_DISK = "\U0001f4bf"
+DVD = "\U0001f4c0"
+ABACUS = "\U0001f9ee"
+MOVIE_CAMERA = "\U0001f3a5"
+FILM_FRAMES = "\U0001f39e\ufe0f"
+FILM_PROJECTOR = "\U0001f4fd\ufe0f"
+CLAPPER_BOARD = "\U0001f3ac"
+TELEVISION = "\U0001f4fa"
+CAMERA = "\U0001f4f7"
+CAMERA_WITH_FLASH = "\U0001f4f8"
+VIDEO_CAMERA = "\U0001f4f9"
+VIDEOCASSETTE = "\U0001f4fc"
+MAGNIFYING_GLASS_TILTED_LEFT = "\U0001f50d"
+MAGNIFYING_GLASS_TILTED_RIGHT = "\U0001f50e"
+CANDLE = "\U0001f56f\ufe0f"
+LIGHT_BULB = "\U0001f4a1"
+FLASHLIGHT = "\U0001f526"
+RED_PAPER_LANTERN = "\U0001f3ee"
+DIYA_LAMP = "\U0001fa94"
+NOTEBOOK_WITH_DECORATIVE_COVER = "\U0001f4d4"
+CLOSED_BOOK = "\U0001f4d5"
+OPEN_BOOK = "\U0001f4d6"
+GREEN_BOOK = "\U0001f4d7"
+BLUE_BOOK = "\U0001f4d8"
+ORANGE_BOOK = "\U0001f4d9"
+BOOKS = "\U0001f4da"
+NOTEBOOK = "\U0001f4d3"
+LEDGER = "\U0001f4d2"
+PAGE_WITH_CURL = "\U0001f4c3"
+SCROLL = "\U0001f4dc"
+PAGE_FACING_UP = "\U0001f4c4"
+NEWSPAPER = "\U0001f4f0"
+ROLLED_UP_NEWSPAPER = "\U0001f5de\ufe0f"
+BOOKMARK_TABS = "\U0001f4d1"
+BOOKMARK = "\U0001f516"
+LABEL = "\U0001f3f7\ufe0f"
+MONEY_BAG = "\U0001f4b0"
+COIN = "\U0001fa99"
+YEN_BANKNOTE = "\U0001f4b4"
+DOLLAR_BANKNOTE = "\U0001f4b5"
+EURO_BANKNOTE = "\U0001f4b6"
+POUND_BANKNOTE = "\U0001f4b7"
+MONEY_WITH_WINGS = "\U0001f4b8"
+CREDIT_CARD = "\U0001f4b3"
+RECEIPT = "\U0001f9fe"
+CHART_INCREASING_WITH_YEN = "\U0001f4b9"
+ENVELOPE = "\u2709\ufe0f"
+E_MAIL = "\U0001f4e7"
+INCOMING_ENVELOPE = "\U0001f4e8"
+ENVELOPE_WITH_ARROW = "\U0001f4e9"
+OUTBOX_TRAY = "\U0001f4e4"
+INBOX_TRAY = "\U0001f4e5"
+PACKAGE = "\U0001f4e6"
+CLOSED_MAILBOX_WITH_RAISED_FLAG = "\U0001f4eb"
+CLOSED_MAILBOX_WITH_LOWERED_FLAG = "\U0001f4ea"
+OPEN_MAILBOX_WITH_RAISED_FLAG = "\U0001f4ec"
+OPEN_MAILBOX_WITH_LOWERED_FLAG = "\U0001f4ed"
+POSTBOX = "\U0001f4ee"
+BALLOT_BOX_WITH_BALLOT = "\U0001f5f3\ufe0f"
+PENCIL = "\u270f\ufe0f"
+BLACK_NIB = "\u2712\ufe0f"
+FOUNTAIN_PEN = "\U0001f58b\ufe0f"
+PEN = "\U0001f58a\ufe0f"
+PAINTBRUSH = "\U0001f58c\ufe0f"
+CRAYON = "\U0001f58d\ufe0f"
+MEMO = "\U0001f4dd"
+BRIEFCASE = "\U0001f4bc"
+FILE_FOLDER = "\U0001f4c1"
+OPEN_FILE_FOLDER = "\U0001f4c2"
+CARD_INDEX_DIVIDERS = "\U0001f5c2\ufe0f"
+CALENDAR = "\U0001f4c5"
+TEAR_OFF_CALENDAR = "\U0001f4c6"
+SPIRAL_NOTEPAD = "\U0001f5d2\ufe0f"
+SPIRAL_CALENDAR = "\U0001f5d3\ufe0f"
+CARD_INDEX = "\U0001f4c7"
+CHART_INCREASING = "\U0001f4c8"
+CHART_DECREASING = "\U0001f4c9"
+BAR_CHART = "\U0001f4ca"
+CLIPBOARD = "\U0001f4cb"
+PUSHPIN = "\U0001f4cc"
+ROUND_PUSHPIN = "\U0001f4cd"
+PAPERCLIP = "\U0001f4ce"
+LINKED_PAPERCLIPS = "\U0001f587\ufe0f"
+STRAIGHT_RULER = "\U0001f4cf"
+TRIANGULAR_RULER = "\U0001f4d0"
+SCISSORS = "\u2702\ufe0f"
+CARD_FILE_BOX = "\U0001f5c3\ufe0f"
+FILE_CABINET = "\U0001f5c4\ufe0f"
+WASTEBASKET = "\U0001f5d1\ufe0f"
+LOCKED = "\U0001f512"
+UNLOCKED = "\U0001f513"
+LOCKED_WITH_PEN = "\U0001f50f"
+LOCKED_WITH_KEY = "\U0001f510"
+KEY = "\U0001f511"
+OLD_KEY = "\U0001f5dd\ufe0f"
+HAMMER = "\U0001f528"
+AXE = "\U0001fa93"
+PICK = "\u26cf\ufe0f"
+HAMMER_AND_PICK = "\u2692\ufe0f"
+HAMMER_AND_WRENCH = "\U0001f6e0\ufe0f"
+DAGGER = "\U0001f5e1\ufe0f"
+CROSSED_SWORDS = "\u2694\ufe0f"
+PISTOL = "\U0001f52b"
+BOOMERANG = "\U0001fa83"
+BOW_AND_ARROW = "\U0001f3f9"
+SHIELD = "\U0001f6e1\ufe0f"
+CARPENTRY_SAW = "\U0001fa9a"
+WRENCH = "\U0001f527"
+SCREWDRIVER = "\U0001fa9b"
+NUT_AND_BOLT = "\U0001f529"
+GEAR = "\u2699\ufe0f"
+CLAMP = "\U0001f5dc\ufe0f"
+BALANCE_SCALE = "\u2696\ufe0f"
+WHITE_CANE = "\U0001f9af"
+LINK = "\U0001f517"
+CHAINS = "\u26d3\ufe0f"
+HOOK = "\U0001fa9d"
+TOOLBOX = "\U0001f9f0"
+MAGNET = "\U0001f9f2"
+LADDER = "\U0001fa9c"
+ALEMBIC = "\u2697\ufe0f"
+TEST_TUBE = "\U0001f9ea"
+PETRI_DISH = "\U0001f9eb"
+DNA = "\U0001f9ec"
+MICROSCOPE = "\U0001f52c"
+TELESCOPE = "\U0001f52d"
+SATELLITE_ANTENNA = "\U0001f4e1"
+SYRINGE = "\U0001f489"
+DROP_OF_BLOOD = "\U0001fa78"
+PILL = "\U0001f48a"
+ADHESIVE_BANDAGE = "\U0001fa79"
+STETHOSCOPE = "\U0001fa7a"
+DOOR = "\U0001f6aa"
+ELEVATOR = "\U0001f6d7"
+MIRROR = "\U0001fa9e"
+WINDOW = "\U0001fa9f"
+BED = "\U0001f6cf\ufe0f"
+COUCH_AND_LAMP = "\U0001f6cb\ufe0f"
+CHAIR = "\U0001fa91"
+TOILET = "\U0001f6bd"
+PLUNGER = "\U0001faa0"
+SHOWER = "\U0001f6bf"
+BATHTUB = "\U0001f6c1"
+MOUSE_TRAP = "\U0001faa4"
+RAZOR = "\U0001fa92"
+LOTION_BOTTLE = "\U0001f9f4"
+SAFETY_PIN = "\U0001f9f7"
+BROOM = "\U0001f9f9"
+BASKET = "\U0001f9fa"
+ROLL_OF_PAPER = "\U0001f9fb"
+BUCKET = "\U0001faa3"
+SOAP = "\U0001f9fc"
+TOOTHBRUSH = "\U0001faa5"
+SPONGE = "\U0001f9fd"
+FIRE_EXTINGUISHER = "\U0001f9ef"
+SHOPPING_CART = "\U0001f6d2"
+CIGARETTE = "\U0001f6ac"
+COFFIN = "\u26b0\ufe0f"
+HEADSTONE = "\U0001faa6"
+FUNERAL_URN = "\u26b1\ufe0f"
+MOAI = "\U0001f5ff"
+PLACARD = "\U0001faa7"
+ATM_SIGN = "\U0001f3e7"
+LITTER_IN_BIN_SIGN = "\U0001f6ae"
+POTABLE_WATER = "\U0001f6b0"
+WHEELCHAIR_SYMBOL = "\u267f"
+MEN_S_ROOM = "\U0001f6b9"
+WOMEN_S_ROOM = "\U0001f6ba"
+RESTROOM = "\U0001f6bb"
+BABY_SYMBOL = "\U0001f6bc"
+WATER_CLOSET = "\U0001f6be"
+PASSPORT_CONTROL = "\U0001f6c2"
+CUSTOMS = "\U0001f6c3"
+BAGGAGE_CLAIM = "\U0001f6c4"
+LEFT_LUGGAGE = "\U0001f6c5"
+WARNING = "\u26a0\ufe0f"
+CHILDREN_CROSSING = "\U0001f6b8"
+NO_ENTRY = "\u26d4"
+PROHIBITED = "\U0001f6ab"
+NO_BICYCLES = "\U0001f6b3"
+NO_SMOKING = "\U0001f6ad"
+NO_LITTERING = "\U0001f6af"
+NON_POTABLE_WATER = "\U0001f6b1"
+NO_PEDESTRIANS = "\U0001f6b7"
+NO_MOBILE_PHONES = "\U0001f4f5"
+NO_ONE_UNDER_EIGHTEEN = "\U0001f51e"
+RADIOACTIVE = "\u2622\ufe0f"
+BIOHAZARD = "\u2623\ufe0f"
+UP_ARROW = "\u2b06\ufe0f"
+UP_RIGHT_ARROW = "\u2197\ufe0f"
+RIGHT_ARROW = "\u27a1\ufe0f"
+DOWN_RIGHT_ARROW = "\u2198\ufe0f"
+DOWN_ARROW = "\u2b07\ufe0f"
+DOWN_LEFT_ARROW = "\u2199\ufe0f"
+LEFT_ARROW = "\u2b05\ufe0f"
+UP_LEFT_ARROW = "\u2196\ufe0f"
+UP_DOWN_ARROW = "\u2195\ufe0f"
+LEFT_RIGHT_ARROW = "\u2194\ufe0f"
+RIGHT_ARROW_CURVING_LEFT = "\u21a9\ufe0f"
+LEFT_ARROW_CURVING_RIGHT = "\u21aa\ufe0f"
+RIGHT_ARROW_CURVING_UP = "\u2934\ufe0f"
+RIGHT_ARROW_CURVING_DOWN = "\u2935\ufe0f"
+CLOCKWISE_VERTICAL_ARROWS = "\U0001f503"
+COUNTERCLOCKWISE_ARROWS_BUTTON = "\U0001f504"
+BACK_ARROW = "\U0001f519"
+END_ARROW = "\U0001f51a"
+ON_ARROW = "\U0001f51b"
+SOON_ARROW = "\U0001f51c"
+TOP_ARROW = "\U0001f51d"
+PLACE_OF_WORSHIP = "\U0001f6d0"
+ATOM_SYMBOL = "\u269b\ufe0f"
+OM = "\U0001f549\ufe0f"
+STAR_OF_DAVID = "\u2721\ufe0f"
+WHEEL_OF_DHARMA = "\u2638\ufe0f"
+YIN_YANG = "\u262f\ufe0f"
+LATIN_CROSS = "\u271d\ufe0f"
+ORTHODOX_CROSS = "\u2626\ufe0f"
+STAR_AND_CRESCENT = "\u262a\ufe0f"
+PEACE_SYMBOL = "\u262e\ufe0f"
+MENORAH = "\U0001f54e"
+DOTTED_SIX_POINTED_STAR = "\U0001f52f"
+ARIES = "\u2648"
+TAURUS = "\u2649"
+GEMINI = "\u264a"
+CANCER = "\u264b"
+LEO = "\u264c"
+VIRGO = "\u264d"
+LIBRA = "\u264e"
+SCORPIO = "\u264f"
+SAGITTARIUS = "\u2650"
+CAPRICORN = "\u2651"
+AQUARIUS = "\u2652"
+PISCES = "\u2653"
+OPHIUCHUS = "\u26ce"
+SHUFFLE_TRACKS_BUTTON = "\U0001f500"
+REPEAT_BUTTON = "\U0001f501"
+REPEAT_SINGLE_BUTTON = "\U0001f502"
+PLAY_BUTTON = "\u25b6\ufe0f"
+FAST_FORWARD_BUTTON = "\u23e9"
+NEXT_TRACK_BUTTON = "\u23ed\ufe0f"
+PLAY_OR_PAUSE_BUTTON = "\u23ef\ufe0f"
+REVERSE_BUTTON = "\u25c0\ufe0f"
+FAST_REVERSE_BUTTON = "\u23ea"
+LAST_TRACK_BUTTON = "\u23ee\ufe0f"
+UPWARDS_BUTTON = "\U0001f53c"
+FAST_UP_BUTTON = "\u23eb"
+DOWNWARDS_BUTTON = "\U0001f53d"
+FAST_DOWN_BUTTON = "\u23ec"
+PAUSE_BUTTON = "\u23f8\ufe0f"
+STOP_BUTTON = "\u23f9\ufe0f"
+RECORD_BUTTON = "\u23fa\ufe0f"
+EJECT_BUTTON = "\u23cf\ufe0f"
+CINEMA = "\U0001f3a6"
+DIM_BUTTON = "\U0001f505"
+BRIGHT_BUTTON = "\U0001f506"
+ANTENNA_BARS = "\U0001f4f6"
+VIBRATION_MODE = "\U0001f4f3"
+MOBILE_PHONE_OFF = "\U0001f4f4"
+FEMALE_SIGN = "\u2640\ufe0f"
+MALE_SIGN = "\u2642\ufe0f"
+TRANSGENDER_SYMBOL = "\u26a7\ufe0f"
+MULTIPLY = "\u2716\ufe0f"
+PLUS = "\u2795"
+MINUS = "\u2796"
+DIVIDE = "\u2797"
+INFINITY = "\u267e\ufe0f"
+DOUBLE_EXCLAMATION_MARK = "\u203c\ufe0f"
+EXCLAMATION_QUESTION_MARK = "\u2049\ufe0f"
+QUESTION_MARK = "\u2753"
+WHITE_QUESTION_MARK = "\u2754"
+WHITE_EXCLAMATION_MARK = "\u2755"
+EXCLAMATION_MARK = "\u2757"
+WAVY_DASH = "\u3030\ufe0f"
+CURRENCY_EXCHANGE = "\U0001f4b1"
+HEAVY_DOLLAR_SIGN = "\U0001f4b2"
+MEDICAL_SYMBOL = "\u2695\ufe0f"
+RECYCLING_SYMBOL = "\u267b\ufe0f"
+FLEUR_DE_LIS = "\u269c\ufe0f"
+TRIDENT_EMBLEM = "\U0001f531"
+NAME_BADGE = "\U0001f4db"
+JAPANESE_SYMBOL_FOR_BEGINNER = "\U0001f530"
+HOLLOW_RED_CIRCLE = "\u2b55"
+CHECK_MARK_BUTTON = "\u2705"
+CHECK_BOX_WITH_CHECK = "\u2611\ufe0f"
+CHECK_MARK = "\u2714\ufe0f"
+CROSS_MARK = "\u274c"
+CROSS_MARK_BUTTON = "\u274e"
+CURLY_LOOP = "\u27b0"
+DOUBLE_CURLY_LOOP = "\u27bf"
+PART_ALTERNATION_MARK = "\u303d\ufe0f"
+EIGHT_SPOKED_ASTERISK = "\u2733\ufe0f"
+EIGHT_POINTED_STAR = "\u2734\ufe0f"
+SPARKLE = "\u2747\ufe0f"
+COPYRIGHT = "\xa9\ufe0f"
+REGISTERED = "\xae\ufe0f"
+TRADE_MARK = "\u2122\ufe0f"
+KEYCAP_NUMBER_SIGN = "#\ufe0f\u20e3"
+KEYCAP_ASTERISK = "*\ufe0f\u20e3"
+KEYCAP_DIGIT_ZERO = "0\ufe0f\u20e3"
+KEYCAP_DIGIT_ONE = "1\ufe0f\u20e3"
+KEYCAP_DIGIT_TWO = "2\ufe0f\u20e3"
+KEYCAP_DIGIT_THREE = "3\ufe0f\u20e3"
+KEYCAP_DIGIT_FOUR = "4\ufe0f\u20e3"
+KEYCAP_DIGIT_FIVE = "5\ufe0f\u20e3"
+KEYCAP_DIGIT_SIX = "6\ufe0f\u20e3"
+KEYCAP_DIGIT_SEVEN = "7\ufe0f\u20e3"
+KEYCAP_DIGIT_EIGHT = "8\ufe0f\u20e3"
+KEYCAP_DIGIT_NINE = "9\ufe0f\u20e3"
+KEYCAP_10 = "\U0001f51f"
+INPUT_LATIN_UPPERCASE = "\U0001f520"
+INPUT_LATIN_LOWERCASE = "\U0001f521"
+INPUT_NUMBERS = "\U0001f522"
+INPUT_SYMBOLS = "\U0001f523"
+INPUT_LATIN_LETTERS = "\U0001f524"
+A_BUTTON_BLOOD_TYPE = "\U0001f170\ufe0f"
+AB_BUTTON_BLOOD_TYPE = "\U0001f18e"
+B_BUTTON_BLOOD_TYPE = "\U0001f171\ufe0f"
+CL_BUTTON = "\U0001f191"
+COOL_BUTTON = "\U0001f192"
+FREE_BUTTON = "\U0001f193"
+INFORMATION = "\u2139\ufe0f"
+ID_BUTTON = "\U0001f194"
+CIRCLED_M = "\u24c2\ufe0f"
+NEW_BUTTON = "\U0001f195"
+NG_BUTTON = "\U0001f196"
+O_BUTTON_BLOOD_TYPE = "\U0001f17e\ufe0f"
+OK_BUTTON = "\U0001f197"
+P_BUTTON = "\U0001f17f\ufe0f"
+SOS_BUTTON = "\U0001f198"
+UP_BUTTON = "\U0001f199"
+VS_BUTTON = "\U0001f19a"
+JAPANESE_HERE_BUTTON = "\U0001f201"
+JAPANESE_SERVICE_CHARGE_BUTTON = "\U0001f202\ufe0f"
+JAPANESE_MONTHLY_AMOUNT_BUTTON = "\U0001f237\ufe0f"
+JAPANESE_NOT_FREE_OF_CHARGE_BUTTON = "\U0001f236"
+JAPANESE_RESERVED_BUTTON = "\U0001f22f"
+JAPANESE_BARGAIN_BUTTON = "\U0001f250"
+JAPANESE_DISCOUNT_BUTTON = "\U0001f239"
+JAPANESE_FREE_OF_CHARGE_BUTTON = "\U0001f21a"
+JAPANESE_PROHIBITED_BUTTON = "\U0001f232"
+JAPANESE_ACCEPTABLE_BUTTON = "\U0001f251"
+JAPANESE_APPLICATION_BUTTON = "\U0001f238"
+JAPANESE_PASSING_GRADE_BUTTON = "\U0001f234"
+JAPANESE_VACANCY_BUTTON = "\U0001f233"
+JAPANESE_CONGRATULATIONS_BUTTON = "\u3297\ufe0f"
+JAPANESE_SECRET_BUTTON = "\u3299\ufe0f"
+JAPANESE_OPEN_FOR_BUSINESS_BUTTON = "\U0001f23a"
+JAPANESE_NO_VACANCY_BUTTON = "\U0001f235"
+RED_CIRCLE = "\U0001f534"
+ORANGE_CIRCLE = "\U0001f7e0"
+YELLOW_CIRCLE = "\U0001f7e1"
+GREEN_CIRCLE = "\U0001f7e2"
+BLUE_CIRCLE = "\U0001f535"
+PURPLE_CIRCLE = "\U0001f7e3"
+BROWN_CIRCLE = "\U0001f7e4"
+BLACK_CIRCLE = "\u26ab"
+WHITE_CIRCLE = "\u26aa"
+RED_SQUARE = "\U0001f7e5"
+ORANGE_SQUARE = "\U0001f7e7"
+YELLOW_SQUARE = "\U0001f7e8"
+GREEN_SQUARE = "\U0001f7e9"
+BLUE_SQUARE = "\U0001f7e6"
+PURPLE_SQUARE = "\U0001f7ea"
+BROWN_SQUARE = "\U0001f7eb"
+BLACK_LARGE_SQUARE = "\u2b1b"
+WHITE_LARGE_SQUARE = "\u2b1c"
+BLACK_MEDIUM_SQUARE = "\u25fc\ufe0f"
+WHITE_MEDIUM_SQUARE = "\u25fb\ufe0f"
+BLACK_MEDIUM_SMALL_SQUARE = "\u25fe"
+WHITE_MEDIUM_SMALL_SQUARE = "\u25fd"
+BLACK_SMALL_SQUARE = "\u25aa\ufe0f"
+WHITE_SMALL_SQUARE = "\u25ab\ufe0f"
+LARGE_ORANGE_DIAMOND = "\U0001f536"
+LARGE_BLUE_DIAMOND = "\U0001f537"
+SMALL_ORANGE_DIAMOND = "\U0001f538"
+SMALL_BLUE_DIAMOND = "\U0001f539"
+RED_TRIANGLE_POINTED_UP = "\U0001f53a"
+RED_TRIANGLE_POINTED_DOWN = "\U0001f53b"
+DIAMOND_WITH_A_DOT = "\U0001f4a0"
+RADIO_BUTTON = "\U0001f518"
+WHITE_SQUARE_BUTTON = "\U0001f533"
+BLACK_SQUARE_BUTTON = "\U0001f532"
+CHEQUERED_FLAG = "\U0001f3c1"
+TRIANGULAR_FLAG = "\U0001f6a9"
+CROSSED_FLAGS = "\U0001f38c"
+BLACK_FLAG = "\U0001f3f4"
+WHITE_FLAG = "\U0001f3f3\ufe0f"
+RAINBOW_FLAG = "\U0001f3f3\ufe0f\u200d\U0001f308"
+TRANSGENDER_FLAG = "\U0001f3f3\ufe0f\u200d\u26a7\ufe0f"
+PIRATE_FLAG = "\U0001f3f4\u200d\u2620\ufe0f"
+FLAG_ASCENSION_ISLAND = "\U0001f1e6\U0001f1e8"
+FLAG_ANDORRA = "\U0001f1e6\U0001f1e9"
+FLAG_UNITED_ARAB_EMIRATES = "\U0001f1e6\U0001f1ea"
+FLAG_AFGHANISTAN = "\U0001f1e6\U0001f1eb"
+FLAG_ANTIGUA_ANDAMP_BARBUDA = "\U0001f1e6\U0001f1ec"
+FLAG_ANGUILLA = "\U0001f1e6\U0001f1ee"
+FLAG_ALBANIA = "\U0001f1e6\U0001f1f1"
+FLAG_ARMENIA = "\U0001f1e6\U0001f1f2"
+FLAG_ANGOLA = "\U0001f1e6\U0001f1f4"
+FLAG_ANTARCTICA = "\U0001f1e6\U0001f1f6"
+FLAG_ARGENTINA = "\U0001f1e6\U0001f1f7"
+FLAG_AMERICAN_SAMOA = "\U0001f1e6\U0001f1f8"
+FLAG_AUSTRIA = "\U0001f1e6\U0001f1f9"
+FLAG_AUSTRALIA = "\U0001f1e6\U0001f1fa"
+FLAG_ARUBA = "\U0001f1e6\U0001f1fc"
+FLAG_ALAND_ISLANDS = "\U0001f1e6\U0001f1fd"
+FLAG_AZERBAIJAN = "\U0001f1e6\U0001f1ff"
+FLAG_BOSNIA_ANDAMP_HERZEGOVINA = "\U0001f1e7\U0001f1e6"
+FLAG_BARBADOS = "\U0001f1e7\U0001f1e7"
+FLAG_BANGLADESH = "\U0001f1e7\U0001f1e9"
+FLAG_BELGIUM = "\U0001f1e7\U0001f1ea"
+FLAG_BURKINA_FASO = "\U0001f1e7\U0001f1eb"
+FLAG_BULGARIA = "\U0001f1e7\U0001f1ec"
+FLAG_BAHRAIN = "\U0001f1e7\U0001f1ed"
+FLAG_BURUNDI = "\U0001f1e7\U0001f1ee"
+FLAG_BENIN = "\U0001f1e7\U0001f1ef"
+FLAG_ST_BARTHELEMY = "\U0001f1e7\U0001f1f1"
+FLAG_BERMUDA = "\U0001f1e7\U0001f1f2"
+FLAG_BRUNEI = "\U0001f1e7\U0001f1f3"
+FLAG_BOLIVIA = "\U0001f1e7\U0001f1f4"
+FLAG_CARIBBEAN_NETHERLANDS = "\U0001f1e7\U0001f1f6"
+FLAG_BRAZIL = "\U0001f1e7\U0001f1f7"
+FLAG_BAHAMAS = "\U0001f1e7\U0001f1f8"
+FLAG_BHUTAN = "\U0001f1e7\U0001f1f9"
+FLAG_BOUVET_ISLAND = "\U0001f1e7\U0001f1fb"
+FLAG_BOTSWANA = "\U0001f1e7\U0001f1fc"
+FLAG_BELARUS = "\U0001f1e7\U0001f1fe"
+FLAG_BELIZE = "\U0001f1e7\U0001f1ff"
+FLAG_CANADA = "\U0001f1e8\U0001f1e6"
+FLAG_COCOS_KEELING_ISLANDS = "\U0001f1e8\U0001f1e8"
+FLAG_CONGO_KINSHASA = "\U0001f1e8\U0001f1e9"
+FLAG_CENTRAL_AFRICAN_REPUBLIC = "\U0001f1e8\U0001f1eb"
+FLAG_CONGO_BRAZZAVILLE = "\U0001f1e8\U0001f1ec"
+FLAG_SWITZERLAND = "\U0001f1e8\U0001f1ed"
+FLAG_COTE_D_IVOIRE = "\U0001f1e8\U0001f1ee"
+FLAG_COOK_ISLANDS = "\U0001f1e8\U0001f1f0"
+FLAG_CHILE = "\U0001f1e8\U0001f1f1"
+FLAG_CAMEROON = "\U0001f1e8\U0001f1f2"
+FLAG_CHINA = "\U0001f1e8\U0001f1f3"
+FLAG_COLOMBIA = "\U0001f1e8\U0001f1f4"
+FLAG_CLIPPERTON_ISLAND = "\U0001f1e8\U0001f1f5"
+FLAG_COSTA_RICA = "\U0001f1e8\U0001f1f7"
+FLAG_CUBA = "\U0001f1e8\U0001f1fa"
+FLAG_CAPE_VERDE = "\U0001f1e8\U0001f1fb"
+FLAG_CURACAO = "\U0001f1e8\U0001f1fc"
+FLAG_CHRISTMAS_ISLAND = "\U0001f1e8\U0001f1fd"
+FLAG_CYPRUS = "\U0001f1e8\U0001f1fe"
+FLAG_CZECHIA = "\U0001f1e8\U0001f1ff"
+FLAG_GERMANY = "\U0001f1e9\U0001f1ea"
+FLAG_DIEGO_GARCIA = "\U0001f1e9\U0001f1ec"
+FLAG_DJIBOUTI = "\U0001f1e9\U0001f1ef"
+FLAG_DENMARK = "\U0001f1e9\U0001f1f0"
+FLAG_DOMINICA = "\U0001f1e9\U0001f1f2"
+FLAG_DOMINICAN_REPUBLIC = "\U0001f1e9\U0001f1f4"
+FLAG_ALGERIA = "\U0001f1e9\U0001f1ff"
+FLAG_CEUTA_ANDAMP_MELILLA = "\U0001f1ea\U0001f1e6"
+FLAG_ECUADOR = "\U0001f1ea\U0001f1e8"
+FLAG_ESTONIA = "\U0001f1ea\U0001f1ea"
+FLAG_EGYPT = "\U0001f1ea\U0001f1ec"
+FLAG_WESTERN_SAHARA = "\U0001f1ea\U0001f1ed"
+FLAG_ERITREA = "\U0001f1ea\U0001f1f7"
+FLAG_SPAIN = "\U0001f1ea\U0001f1f8"
+FLAG_ETHIOPIA = "\U0001f1ea\U0001f1f9"
+FLAG_EUROPEAN_UNION = "\U0001f1ea\U0001f1fa"
+FLAG_FINLAND = "\U0001f1eb\U0001f1ee"
+FLAG_FIJI = "\U0001f1eb\U0001f1ef"
+FLAG_FALKLAND_ISLANDS = "\U0001f1eb\U0001f1f0"
+FLAG_MICRONESIA = "\U0001f1eb\U0001f1f2"
+FLAG_FAROE_ISLANDS = "\U0001f1eb\U0001f1f4"
+FLAG_FRANCE = "\U0001f1eb\U0001f1f7"
+FLAG_GABON = "\U0001f1ec\U0001f1e6"
+FLAG_UNITED_KINGDOM = "\U0001f1ec\U0001f1e7"
+FLAG_GRENADA = "\U0001f1ec\U0001f1e9"
+FLAG_GEORGIA = "\U0001f1ec\U0001f1ea"
+FLAG_FRENCH_GUIANA = "\U0001f1ec\U0001f1eb"
+FLAG_GUERNSEY = "\U0001f1ec\U0001f1ec"
+FLAG_GHANA = "\U0001f1ec\U0001f1ed"
+FLAG_GIBRALTAR = "\U0001f1ec\U0001f1ee"
+FLAG_GREENLAND = "\U0001f1ec\U0001f1f1"
+FLAG_GAMBIA = "\U0001f1ec\U0001f1f2"
+FLAG_GUINEA = "\U0001f1ec\U0001f1f3"
+FLAG_GUADELOUPE = "\U0001f1ec\U0001f1f5"
+FLAG_EQUATORIAL_GUINEA = "\U0001f1ec\U0001f1f6"
+FLAG_GREECE = "\U0001f1ec\U0001f1f7"
+FLAG_SOUTH_GEORGIA_ANDAMP_SOUTH_SANDWICH_ISLANDS = "\U0001f1ec\U0001f1f8"
+FLAG_GUATEMALA = "\U0001f1ec\U0001f1f9"
+FLAG_GUAM = "\U0001f1ec\U0001f1fa"
+FLAG_GUINEA_BISSAU = "\U0001f1ec\U0001f1fc"
+FLAG_GUYANA = "\U0001f1ec\U0001f1fe"
+FLAG_HONG_KONG_SAR_CHINA = "\U0001f1ed\U0001f1f0"
+FLAG_HEARD_ANDAMP_MCDONALD_ISLANDS = "\U0001f1ed\U0001f1f2"
+FLAG_HONDURAS = "\U0001f1ed\U0001f1f3"
+FLAG_CROATIA = "\U0001f1ed\U0001f1f7"
+FLAG_HAITI = "\U0001f1ed\U0001f1f9"
+FLAG_HUNGARY = "\U0001f1ed\U0001f1fa"
+FLAG_CANARY_ISLANDS = "\U0001f1ee\U0001f1e8"
+FLAG_INDONESIA = "\U0001f1ee\U0001f1e9"
+FLAG_IRELAND = "\U0001f1ee\U0001f1ea"
+FLAG_ISRAEL = "\U0001f1ee\U0001f1f1"
+FLAG_ISLE_OF_MAN = "\U0001f1ee\U0001f1f2"
+FLAG_INDIA = "\U0001f1ee\U0001f1f3"
+FLAG_BRITISH_INDIAN_OCEAN_TERRITORY = "\U0001f1ee\U0001f1f4"
+FLAG_IRAQ = "\U0001f1ee\U0001f1f6"
+FLAG_IRAN = "\U0001f1ee\U0001f1f7"
+FLAG_ICELAND = "\U0001f1ee\U0001f1f8"
+FLAG_ITALY = "\U0001f1ee\U0001f1f9"
+FLAG_JERSEY = "\U0001f1ef\U0001f1ea"
+FLAG_JAMAICA = "\U0001f1ef\U0001f1f2"
+FLAG_JORDAN = "\U0001f1ef\U0001f1f4"
+FLAG_JAPAN = "\U0001f1ef\U0001f1f5"
+FLAG_KENYA = "\U0001f1f0\U0001f1ea"
+FLAG_KYRGYZSTAN = "\U0001f1f0\U0001f1ec"
+FLAG_CAMBODIA = "\U0001f1f0\U0001f1ed"
+FLAG_KIRIBATI = "\U0001f1f0\U0001f1ee"
+FLAG_COMOROS = "\U0001f1f0\U0001f1f2"
+FLAG_ST_KITTS_ANDAMP_NEVIS = "\U0001f1f0\U0001f1f3"
+FLAG_NORTH_KOREA = "\U0001f1f0\U0001f1f5"
+FLAG_SOUTH_KOREA = "\U0001f1f0\U0001f1f7"
+FLAG_KUWAIT = "\U0001f1f0\U0001f1fc"
+FLAG_CAYMAN_ISLANDS = "\U0001f1f0\U0001f1fe"
+FLAG_KAZAKHSTAN = "\U0001f1f0\U0001f1ff"
+FLAG_LAOS = "\U0001f1f1\U0001f1e6"
+FLAG_LEBANON = "\U0001f1f1\U0001f1e7"
+FLAG_ST_LUCIA = "\U0001f1f1\U0001f1e8"
+FLAG_LIECHTENSTEIN = "\U0001f1f1\U0001f1ee"
+FLAG_SRI_LANKA = "\U0001f1f1\U0001f1f0"
+FLAG_LIBERIA = "\U0001f1f1\U0001f1f7"
+FLAG_LESOTHO = "\U0001f1f1\U0001f1f8"
+FLAG_LITHUANIA = "\U0001f1f1\U0001f1f9"
+FLAG_LUXEMBOURG = "\U0001f1f1\U0001f1fa"
+FLAG_LATVIA = "\U0001f1f1\U0001f1fb"
+FLAG_LIBYA = "\U0001f1f1\U0001f1fe"
+FLAG_MOROCCO = "\U0001f1f2\U0001f1e6"
+FLAG_MONACO = "\U0001f1f2\U0001f1e8"
+FLAG_MOLDOVA = "\U0001f1f2\U0001f1e9"
+FLAG_MONTENEGRO = "\U0001f1f2\U0001f1ea"
+FLAG_ST_MARTIN = "\U0001f1f2\U0001f1eb"
+FLAG_MADAGASCAR = "\U0001f1f2\U0001f1ec"
+FLAG_MARSHALL_ISLANDS = "\U0001f1f2\U0001f1ed"
+FLAG_NORTH_MACEDONIA = "\U0001f1f2\U0001f1f0"
+FLAG_MALI = "\U0001f1f2\U0001f1f1"
+FLAG_MYANMAR_BURMA = "\U0001f1f2\U0001f1f2"
+FLAG_MONGOLIA = "\U0001f1f2\U0001f1f3"
+FLAG_MACAO_SAR_CHINA = "\U0001f1f2\U0001f1f4"
+FLAG_NORTHERN_MARIANA_ISLANDS = "\U0001f1f2\U0001f1f5"
+FLAG_MARTINIQUE = "\U0001f1f2\U0001f1f6"
+FLAG_MAURITANIA = "\U0001f1f2\U0001f1f7"
+FLAG_MONTSERRAT = "\U0001f1f2\U0001f1f8"
+FLAG_MALTA = "\U0001f1f2\U0001f1f9"
+FLAG_MAURITIUS = "\U0001f1f2\U0001f1fa"
+FLAG_MALDIVES = "\U0001f1f2\U0001f1fb"
+FLAG_MALAWI = "\U0001f1f2\U0001f1fc"
+FLAG_MEXICO = "\U0001f1f2\U0001f1fd"
+FLAG_MALAYSIA = "\U0001f1f2\U0001f1fe"
+FLAG_MOZAMBIQUE = "\U0001f1f2\U0001f1ff"
+FLAG_NAMIBIA = "\U0001f1f3\U0001f1e6"
+FLAG_NEW_CALEDONIA = "\U0001f1f3\U0001f1e8"
+FLAG_NIGER = "\U0001f1f3\U0001f1ea"
+FLAG_NORFOLK_ISLAND = "\U0001f1f3\U0001f1eb"
+FLAG_NIGERIA = "\U0001f1f3\U0001f1ec"
+FLAG_NICARAGUA = "\U0001f1f3\U0001f1ee"
+FLAG_NETHERLANDS = "\U0001f1f3\U0001f1f1"
+FLAG_NORWAY = "\U0001f1f3\U0001f1f4"
+FLAG_NEPAL = "\U0001f1f3\U0001f1f5"
+FLAG_NAURU = "\U0001f1f3\U0001f1f7"
+FLAG_NIUE = "\U0001f1f3\U0001f1fa"
+FLAG_NEW_ZEALAND = "\U0001f1f3\U0001f1ff"
+FLAG_OMAN = "\U0001f1f4\U0001f1f2"
+FLAG_PANAMA = "\U0001f1f5\U0001f1e6"
+FLAG_PERU = "\U0001f1f5\U0001f1ea"
+FLAG_FRENCH_POLYNESIA = "\U0001f1f5\U0001f1eb"
+FLAG_PAPUA_NEW_GUINEA = "\U0001f1f5\U0001f1ec"
+FLAG_PHILIPPINES = "\U0001f1f5\U0001f1ed"
+FLAG_PAKISTAN = "\U0001f1f5\U0001f1f0"
+FLAG_POLAND = "\U0001f1f5\U0001f1f1"
+FLAG_ST_PIERRE_ANDAMP_MIQUELON = "\U0001f1f5\U0001f1f2"
+FLAG_PITCAIRN_ISLANDS = "\U0001f1f5\U0001f1f3"
+FLAG_PUERTO_RICO = "\U0001f1f5\U0001f1f7"
+FLAG_PALESTINIAN_TERRITORIES = "\U0001f1f5\U0001f1f8"
+FLAG_PORTUGAL = "\U0001f1f5\U0001f1f9"
+FLAG_PALAU = "\U0001f1f5\U0001f1fc"
+FLAG_PARAGUAY = "\U0001f1f5\U0001f1fe"
+FLAG_QATAR = "\U0001f1f6\U0001f1e6"
+FLAG_REUNION = "\U0001f1f7\U0001f1ea"
+FLAG_ROMANIA = "\U0001f1f7\U0001f1f4"
+FLAG_SERBIA = "\U0001f1f7\U0001f1f8"
+FLAG_RUSSIA = "\U0001f1f7\U0001f1fa"
+FLAG_RWANDA = "\U0001f1f7\U0001f1fc"
+FLAG_SAUDI_ARABIA = "\U0001f1f8\U0001f1e6"
+FLAG_SOLOMON_ISLANDS = "\U0001f1f8\U0001f1e7"
+FLAG_SEYCHELLES = "\U0001f1f8\U0001f1e8"
+FLAG_SUDAN = "\U0001f1f8\U0001f1e9"
+FLAG_SWEDEN = "\U0001f1f8\U0001f1ea"
+FLAG_SINGAPORE = "\U0001f1f8\U0001f1ec"
+FLAG_ST_HELENA = "\U0001f1f8\U0001f1ed"
+FLAG_SLOVENIA = "\U0001f1f8\U0001f1ee"
+FLAG_SVALBARD_ANDAMP_JAN_MAYEN = "\U0001f1f8\U0001f1ef"
+FLAG_SLOVAKIA = "\U0001f1f8\U0001f1f0"
+FLAG_SIERRA_LEONE = "\U0001f1f8\U0001f1f1"
+FLAG_SAN_MARINO = "\U0001f1f8\U0001f1f2"
+FLAG_SENEGAL = "\U0001f1f8\U0001f1f3"
+FLAG_SOMALIA = "\U0001f1f8\U0001f1f4"
+FLAG_SURINAME = "\U0001f1f8\U0001f1f7"
+FLAG_SOUTH_SUDAN = "\U0001f1f8\U0001f1f8"
+FLAG_SAO_TOME_ANDAMP_PRINCIPE = "\U0001f1f8\U0001f1f9"
+FLAG_EL_SALVADOR = "\U0001f1f8\U0001f1fb"
+FLAG_SINT_MAARTEN = "\U0001f1f8\U0001f1fd"
+FLAG_SYRIA = "\U0001f1f8\U0001f1fe"
+FLAG_ESWATINI = "\U0001f1f8\U0001f1ff"
+FLAG_TRISTAN_DA_CUNHA = "\U0001f1f9\U0001f1e6"
+FLAG_TURKS_ANDAMP_CAICOS_ISLANDS = "\U0001f1f9\U0001f1e8"
+FLAG_CHAD = "\U0001f1f9\U0001f1e9"
+FLAG_FRENCH_SOUTHERN_TERRITORIES = "\U0001f1f9\U0001f1eb"
+FLAG_TOGO = "\U0001f1f9\U0001f1ec"
+FLAG_THAILAND = "\U0001f1f9\U0001f1ed"
+FLAG_TAJIKISTAN = "\U0001f1f9\U0001f1ef"
+FLAG_TOKELAU = "\U0001f1f9\U0001f1f0"
+FLAG_TIMOR_LESTE = "\U0001f1f9\U0001f1f1"
+FLAG_TURKMENISTAN = "\U0001f1f9\U0001f1f2"
+FLAG_TUNISIA = "\U0001f1f9\U0001f1f3"
+FLAG_TONGA = "\U0001f1f9\U0001f1f4"
+FLAG_TURKEY = "\U0001f1f9\U0001f1f7"
+FLAG_TRINIDAD_ANDAMP_TOBAGO = "\U0001f1f9\U0001f1f9"
+FLAG_TUVALU = "\U0001f1f9\U0001f1fb"
+FLAG_TAIWAN = "\U0001f1f9\U0001f1fc"
+FLAG_TANZANIA = "\U0001f1f9\U0001f1ff"
+FLAG_UKRAINE = "\U0001f1fa\U0001f1e6"
+FLAG_UGANDA = "\U0001f1fa\U0001f1ec"
+FLAG_U_S_OUTLYING_ISLANDS = "\U0001f1fa\U0001f1f2"
+FLAG_UNITED_NATIONS = "\U0001f1fa\U0001f1f3"
+FLAG_UNITED_STATES = "\U0001f1fa\U0001f1f8"
+FLAG_URUGUAY = "\U0001f1fa\U0001f1fe"
+FLAG_UZBEKISTAN = "\U0001f1fa\U0001f1ff"
+FLAG_VATICAN_CITY = "\U0001f1fb\U0001f1e6"
+FLAG_ST_VINCENT_ANDAMP_GRENADINES = "\U0001f1fb\U0001f1e8"
+FLAG_VENEZUELA = "\U0001f1fb\U0001f1ea"
+FLAG_BRITISH_VIRGIN_ISLANDS = "\U0001f1fb\U0001f1ec"
+FLAG_U_S_VIRGIN_ISLANDS = "\U0001f1fb\U0001f1ee"
+FLAG_VIETNAM = "\U0001f1fb\U0001f1f3"
+FLAG_VANUATU = "\U0001f1fb\U0001f1fa"
+FLAG_WALLIS_ANDAMP_FUTUNA = "\U0001f1fc\U0001f1eb"
+FLAG_SAMOA = "\U0001f1fc\U0001f1f8"
+FLAG_KOSOVO = "\U0001f1fd\U0001f1f0"
+FLAG_YEMEN = "\U0001f1fe\U0001f1ea"
+FLAG_MAYOTTE = "\U0001f1fe\U0001f1f9"
+FLAG_SOUTH_AFRICA = "\U0001f1ff\U0001f1e6"
+FLAG_ZAMBIA = "\U0001f1ff\U0001f1f2"
+FLAG_ZIMBABWE = "\U0001f1ff\U0001f1fc"
+FLAG_ENGLAND = "\U0001f3f4\U000e0067\U000e0062\U000e0065\U000e006e\U000e0067\U000e007f"
+FLAG_SCOTLAND = "\U0001f3f4\U000e0067\U000e0062\U000e0073\U000e0063\U000e0074\U000e007f"
+FLAG_WALES = "\U0001f3f4\U000e0067\U000e0062\U000e0077\U000e006c\U000e0073\U000e007f"
+REGIONAL_INDICATOR_SYMBOL_LETTER_A = "\U0001f1e6"
+REGIONAL_INDICATOR_SYMBOL_LETTER_B = "\U0001f1e7"
+REGIONAL_INDICATOR_SYMBOL_LETTER_C = "\U0001f1e8"
+REGIONAL_INDICATOR_SYMBOL_LETTER_D = "\U0001f1e9"
+REGIONAL_INDICATOR_SYMBOL_LETTER_E = "\U0001f1ea"
+REGIONAL_INDICATOR_SYMBOL_LETTER_F = "\U0001f1eb"
+REGIONAL_INDICATOR_SYMBOL_LETTER_G = "\U0001f1ec"
+REGIONAL_INDICATOR_SYMBOL_LETTER_H = "\U0001f1ed"
+REGIONAL_INDICATOR_SYMBOL_LETTER_I = "\U0001f1ee"
+REGIONAL_INDICATOR_SYMBOL_LETTER_J = "\U0001f1ef"
+REGIONAL_INDICATOR_SYMBOL_LETTER_K = "\U0001f1f0"
+REGIONAL_INDICATOR_SYMBOL_LETTER_L = "\U0001f1f1"
+REGIONAL_INDICATOR_SYMBOL_LETTER_M = "\U0001f1f2"
+REGIONAL_INDICATOR_SYMBOL_LETTER_N = "\U0001f1f3"
+REGIONAL_INDICATOR_SYMBOL_LETTER_O = "\U0001f1f4"
+REGIONAL_INDICATOR_SYMBOL_LETTER_P = "\U0001f1f5"
+REGIONAL_INDICATOR_SYMBOL_LETTER_Q = "\U0001f1f6"
+REGIONAL_INDICATOR_SYMBOL_LETTER_R = "\U0001f1f7"
+REGIONAL_INDICATOR_SYMBOL_LETTER_S = "\U0001f1f8"
+REGIONAL_INDICATOR_SYMBOL_LETTER_T = "\U0001f1f9"
+REGIONAL_INDICATOR_SYMBOL_LETTER_U = "\U0001f1fa"
+REGIONAL_INDICATOR_SYMBOL_LETTER_V = "\U0001f1fb"
+REGIONAL_INDICATOR_SYMBOL_LETTER_W = "\U0001f1fc"
+REGIONAL_INDICATOR_SYMBOL_LETTER_X = "\U0001f1fd"
+REGIONAL_INDICATOR_SYMBOL_LETTER_Y = "\U0001f1fe"
+REGIONAL_INDICATOR_SYMBOL_LETTER_Z = "\U0001f1ff"
+TAG_VERTICAL_LINE = "\U000e007c"
+TAG_LATIN_CAPITAL_LETTER_O = "\U000e004f"
+TAG_LOW_LINE = "\U000e005f"
+TAG_LATIN_SMALL_LETTER_E = "\U000e0065"
+TAG_PERCENT_SIGN = "\U000e0025"
+TAG_DIGIT_SEVEN = "\U000e0037"
+TAG_LATIN_SMALL_LETTER_W = "\U000e0077"
+TAG_DIGIT_ONE = "\U000e0031"
+TAG_LATIN_CAPITAL_LETTER_A = "\U000e0041"
+TAG_LATIN_CAPITAL_LETTER_Z = "\U000e005a"
+TAG_LATIN_CAPITAL_LETTER_M = "\U000e004d"
+TAG_QUESTION_MARK = "\U000e003f"
+TAG_LATIN_CAPITAL_LETTER_W = "\U000e0057"
+TAG_LATIN_SMALL_LETTER_D = "\U000e0064"
+TAG_LATIN_SMALL_LETTER_K = "\U000e006b"
+TAG_LATIN_SMALL_LETTER_V = "\U000e0076"
+DIGIT_ZERO = "0\ufe0f"
+TAG_DIGIT_SIX = "\U000e0036"
+TAG_LATIN_SMALL_LETTER_C = "\U000e0063"
+TAG_LATIN_SMALL_LETTER_X = "\U000e0078"
+TAG_LATIN_SMALL_LETTER_U = "\U000e0075"
+TAG_DIGIT_NINE = "\U000e0039"
+DIGIT_FOUR = "4\ufe0f"
+DIGIT_EIGHT = "8\ufe0f"
+TAG_RIGHT_CURLY_BRACKET = "\U000e007d"
+TAG_LATIN_CAPITAL_LETTER_S = "\U000e0053"
+TAG_DIGIT_FIVE = "\U000e0035"
+TAG_LATIN_CAPITAL_LETTER_V = "\U000e0056"
+TAG_LATIN_SMALL_LETTER_L = "\U000e006c"
+TAG_SOLIDUS = "\U000e002f"
+TAG_LATIN_SMALL_LETTER_B = "\U000e0062"
+TAG_SEMICOLON = "\U000e003b"
+TAG_LESS_THAN_SIGN = "\U000e003c"
+TAG_DIGIT_TWO = "\U000e0032"
+TAG_LATIN_SMALL_LETTER_M = "\U000e006d"
+TAG_LATIN_CAPITAL_LETTER_N = "\U000e004e"
+TAG_LATIN_SMALL_LETTER_P = "\U000e0070"
+TAG_LATIN_SMALL_LETTER_I = "\U000e0069"
+TAG_LATIN_SMALL_LETTER_A = "\U000e0061"
+TAG_NUMBER_SIGN = "\U000e0023"
+TAG_LATIN_CAPITAL_LETTER_K = "\U000e004b"
+TAG_LATIN_CAPITAL_LETTER_J = "\U000e004a"
+TAG_LATIN_CAPITAL_LETTER_T = "\U000e0054"
+TAG_LATIN_SMALL_LETTER_Y = "\U000e0079"
+TAG_QUOTATION_MARK = "\U000e0022"
+TAG_TILDE = "\U000e007e"
+TAG_FULL_STOP = "\U000e002e"
+TAG_LATIN_SMALL_LETTER_S = "\U000e0073"
+TAG_LATIN_SMALL_LETTER_F = "\U000e0066"
+TAG_LATIN_SMALL_LETTER_O = "\U000e006f"
+TAG_DIGIT_ZERO = "\U000e0030"
+DIGIT_FIVE = "5\ufe0f"
+DIGIT_ONE = "1\ufe0f"
+TAG_LATIN_CAPITAL_LETTER_B = "\U000e0042"
+DIGIT_NINE = "9\ufe0f"
+TAG_LATIN_CAPITAL_LETTER_F = "\U000e0046"
+TAG_LATIN_CAPITAL_LETTER_Y = "\U000e0059"
+TAG_GREATER_THAN_SIGN = "\U000e003e"
+TAG_HYPHEN_MINUS = "\U000e002d"
+TAG_LEFT_CURLY_BRACKET = "\U000e007b"
+TAG_DIGIT_THREE = "\U000e0033"
+TAG_EQUALS_SIGN = "\U000e003d"
+TAG_DIGIT_FOUR = "\U000e0034"
+TAG_LATIN_SMALL_LETTER_N = "\U000e006e"
+TAG_DOLLAR_SIGN = "\U000e0024"
+TAG_RIGHT_PARENTHESIS = "\U000e0029"
+TAG_LATIN_CAPITAL_LETTER_Q = "\U000e0051"
+TAG_CIRCUMFLEX_ACCENT = "\U000e005e"
+DIGIT_SEVEN = "7\ufe0f"
+VARIATION_SELECTOR_16 = "\ufe0f"
+NUMBER_SIGN = "#\ufe0f"
+DIGIT_TWO = "2\ufe0f"
+TAG_GRAVE_ACCENT = "\U000e0060"
+TAG_COLON = "\U000e003a"
+TAG_REVERSE_SOLIDUS = "\U000e005c"
+TAG_COMMERCIAL_AT = "\U000e0040"
+TAG_EXCLAMATION_MARK = "\U000e0021"
+TAG_APOSTROPHE = "\U000e0027"
+TAG_LATIN_SMALL_LETTER_Z = "\U000e007a"
+TAG_LATIN_CAPITAL_LETTER_X = "\U000e0058"
+TAG_LATIN_CAPITAL_LETTER_R = "\U000e0052"
+COMBINING_ENCLOSING_KEYCAP = "\u20e3"
+ZERO_WIDTH_JOINER = "\u200d"
+TAG_LATIN_SMALL_LETTER_G = "\U000e0067"
+TAG_LATIN_CAPITAL_LETTER_U = "\U000e0055"
+TAG_LATIN_CAPITAL_LETTER_D = "\U000e0044"
+TAG_LATIN_SMALL_LETTER_R = "\U000e0072"
+TAG_LATIN_CAPITAL_LETTER_P = "\U000e0050"
+TAG_LATIN_SMALL_LETTER_H = "\U000e0068"
+CANCEL_TAG = "\U000e007f"
+TAG_AMPERSAND = "\U000e0026"
+TAG_LEFT_PARENTHESIS = "\U000e0028"
+TAG_LATIN_SMALL_LETTER_Q = "\U000e0071"
+TAG_LATIN_CAPITAL_LETTER_C = "\U000e0043"
+TAG_ASTERISK = "\U000e002a"
+TAG_LATIN_SMALL_LETTER_T = "\U000e0074"
+TAG_LATIN_CAPITAL_LETTER_L = "\U000e004c"
+TAG_COMMA = "\U000e002c"
+TAG_RIGHT_SQUARE_BRACKET = "\U000e005d"
+DIGIT_THREE = "3\ufe0f"
+TAG_LATIN_CAPITAL_LETTER_H = "\U000e0048"
+TAG_LATIN_SMALL_LETTER_J = "\U000e006a"
+TAG_SPACE = "\U000e0020"
+TAG_PLUS_SIGN = "\U000e002b"
+TAG_LEFT_SQUARE_BRACKET = "\U000e005b"
+ASTERISK = "*\ufe0f"
+DIGIT_SIX = "6\ufe0f"
+TAG_DIGIT_EIGHT = "\U000e0038"
+TAG_LATIN_CAPITAL_LETTER_E = "\U000e0045"
+TAG_LATIN_CAPITAL_LETTER_G = "\U000e0047"
+TAG_LATIN_CAPITAL_LETTER_I = "\U000e0049"
diff --git a/pyrogram/errors/rpc_error.py b/pyrogram/errors/rpc_error.py
index 2586d8737e..d11467945b 100644
--- a/pyrogram/errors/rpc_error.py
+++ b/pyrogram/errors/rpc_error.py
@@ -21,9 +21,8 @@
from importlib import import_module
from typing import Type
-from pyrogram.api.types import RpcError as RawRPCError
-
-from pyrogram.api.core import TLObject
+from pyrogram import raw
+from pyrogram.raw.core import TLObject
from .exceptions.all import exceptions
@@ -33,12 +32,12 @@ class RPCError(Exception):
NAME = None
MESSAGE = "{x}"
- def __init__(self, x: int or RawRPCError = None, rpc_name: str = None, is_unknown: bool = False):
+ def __init__(self, x: int or raw.types.RpcError = None, rpc_name: str = None, is_unknown: bool = False):
super().__init__("[{} {}]: {} {}".format(
self.CODE,
self.ID or self.NAME,
self.MESSAGE.format(x=x),
- '(caused by "{}")'.format(rpc_name) if rpc_name else ""
+ f'(caused by "{rpc_name}")' if rpc_name else ""
))
try:
@@ -48,17 +47,17 @@ def __init__(self, x: int or RawRPCError = None, rpc_name: str = None, is_unknow
if is_unknown:
with open("unknown_errors.txt", "a", encoding="utf-8") as f:
- f.write("{}\t{}\t{}\n".format(datetime.now(), x, rpc_name))
+ f.write(f"{datetime.now()}\t{x}\t{rpc_name}\n")
@staticmethod
- def raise_it(rpc_error: RawRPCError, rpc_type: Type[TLObject]):
+ def raise_it(rpc_error: "raw.types.RpcError", rpc_type: Type[TLObject]):
error_code = rpc_error.error_code
error_message = rpc_error.error_message
rpc_name = ".".join(rpc_type.QUALNAME.split(".")[1:])
if error_code not in exceptions:
raise UnknownError(
- x="[{} {}]".format(error_code, error_message),
+ x=f"[{error_code} {error_message}]",
rpc_name=rpc_name,
is_unknown=True
)
@@ -69,7 +68,7 @@ def raise_it(rpc_error: RawRPCError, rpc_type: Type[TLObject]):
raise getattr(
import_module("pyrogram.errors"),
exceptions[error_code]["_"]
- )(x="[{} {}]".format(error_code, error_message),
+ )(x=f"[{error_code} {error_message}]",
rpc_name=rpc_name,
is_unknown=True)
diff --git a/pyrogram/filters.py b/pyrogram/filters.py
new file mode 100644
index 0000000000..45762aee7d
--- /dev/null
+++ b/pyrogram/filters.py
@@ -0,0 +1,877 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import inspect
+import re
+from typing import Callable, Union, List, Pattern
+
+import pyrogram
+from pyrogram.types import Message, CallbackQuery, InlineQuery, InlineKeyboardMarkup, ReplyKeyboardMarkup, Update
+
+
+class Filter:
+ async def __call__(self, client: "pyrogram.Client", update: Update):
+ raise NotImplementedError
+
+ def __invert__(self):
+ return InvertFilter(self)
+
+ def __and__(self, other):
+ return AndFilter(self, other)
+
+ def __or__(self, other):
+ return OrFilter(self, other)
+
+
+class InvertFilter(Filter):
+ def __init__(self, base):
+ self.base = base
+
+ async def __call__(self, client: "pyrogram.Client", update: Update):
+ if inspect.iscoroutinefunction(self.base.__call__):
+ x = await self.base(client, update)
+ else:
+ x = await client.loop.run_in_executor(
+ client.executor,
+ self.base,
+ client, update
+ )
+
+ return not x
+
+
+class AndFilter(Filter):
+ def __init__(self, base, other):
+ self.base = base
+ self.other = other
+
+ async def __call__(self, client: "pyrogram.Client", update: Update):
+ if inspect.iscoroutinefunction(self.base.__call__):
+ x = await self.base(client, update)
+ else:
+ x = await client.loop.run_in_executor(
+ client.executor,
+ self.base,
+ client, update
+ )
+
+ if inspect.iscoroutinefunction(self.other.__call__):
+ y = await self.other(client, update)
+ else:
+ y = await client.loop.run_in_executor(
+ client.executor,
+ self.other,
+ client, update
+ )
+
+ return x and y
+
+
+class OrFilter(Filter):
+ def __init__(self, base, other):
+ self.base = base
+ self.other = other
+
+ async def __call__(self, client: "pyrogram.Client", update: Update):
+ if inspect.iscoroutinefunction(self.base.__call__):
+ x = await self.base(client, update)
+ else:
+ x = await client.loop.run_in_executor(
+ client.executor,
+ self.base,
+ client, update
+ )
+
+ if inspect.iscoroutinefunction(self.other.__call__):
+ y = await self.other(client, update)
+ else:
+ y = await client.loop.run_in_executor(
+ client.executor,
+ self.other,
+ client, update
+ )
+
+ return x or y
+
+
+CUSTOM_FILTER_NAME = "CustomFilter"
+
+
+def create(func: Callable, name: str = None, **kwargs) -> Filter:
+ """Easily create a custom filter.
+
+ Custom filters give you extra control over which updates are allowed or not to be processed by your handlers.
+
+ Parameters:
+ func (``callable``):
+ A function that accepts two positional arguments *(filter, update)* and returns a boolean: True if the
+ update should be handled, False otherwise. The *filter* argument refers to the filter itself and can be used
+ to access keyword arguments (read below). The *update* argument type will vary depending on which
+ `Handler `_ is coming from. For example, in a :obj:`~pyrogram.handlers.MessageHandler` the
+ *update* argument will be a :obj:`~pyrogram.types.Message`; in a
+ :obj:`~pyrogram.handlers.CallbackQueryHandler` the *update* will be a :obj:`~pyrogram.types.CallbackQuery`.
+ Your function body can then access the incoming update attributes and decide whether to allow it or not.
+
+ name (``str``, *optional*):
+ Your filter's name. Can be anything you like.
+ Defaults to "CustomFilter".
+
+ **kwargs (``any``, *optional*):
+ Any keyword argument you would like to pass. Useful when creating parameterized custom filters, such as
+ :meth:`~Filters.command` or :meth:`~Filters.regex`.
+ """
+ return type(
+ name or func.__name__ or CUSTOM_FILTER_NAME,
+ (Filter,),
+ {"__call__": func, **kwargs}
+ )()
+
+
+# region all_filter
+async def all_filter(_, __, ___):
+ return True
+
+
+all = create(all_filter)
+"""Filter all messages."""
+
+
+# endregion
+
+# region me_filter
+async def me_filter(_, __, m: Message):
+ return bool(m.from_user and m.from_user.is_self)
+
+
+me = create(me_filter)
+"""Filter messages generated by you yourself."""
+
+
+# endregion
+
+# region bot_filter
+async def bot_filter(_, __, m: Message):
+ return bool(m.from_user and m.from_user.is_bot)
+
+
+bot = create(bot_filter)
+"""Filter messages coming from bots."""
+
+
+# endregion
+
+# region incoming_filter
+async def incoming_filter(_, __, m: Message):
+ return not m.outgoing
+
+
+incoming = create(incoming_filter)
+"""Filter incoming messages. Messages sent to your own chat (Saved Messages) are also recognised as incoming."""
+
+
+# endregion
+
+# region outgoing_filter
+async def outgoing_filter(_, __, m: Message):
+ return m.outgoing
+
+
+outgoing = create(outgoing_filter)
+"""Filter outgoing messages. Messages sent to your own chat (Saved Messages) are not recognized as outgoing."""
+
+
+# endregion
+
+# region text_filter
+async def text_filter(_, __, m: Message):
+ return bool(m.text)
+
+
+text = create(text_filter)
+"""Filter text messages."""
+
+
+# endregion
+
+# region reply_filter
+async def reply_filter(_, __, m: Message):
+ return bool(m.reply_to_message)
+
+
+reply = create(reply_filter)
+"""Filter messages that are replies to other messages."""
+
+
+# endregion
+
+# region forwarded_filter
+async def forwarded_filter(_, __, m: Message):
+ return bool(m.forward_date)
+
+
+forwarded = create(forwarded_filter)
+"""Filter messages that are forwarded."""
+
+
+# endregion
+
+# region caption_filter
+async def caption_filter(_, __, m: Message):
+ return bool(m.caption)
+
+
+caption = create(caption_filter)
+"""Filter media messages that contain captions."""
+
+
+# endregion
+
+# region edited_filter
+async def edited_filter(_, __, m: Message):
+ return bool(m.edit_date)
+
+
+edited = create(edited_filter)
+"""Filter edited messages."""
+
+
+# endregion
+
+# region audio_filter
+async def audio_filter(_, __, m: Message):
+ return bool(m.audio)
+
+
+audio = create(audio_filter)
+"""Filter messages that contain :obj:`~pyrogram.types.Audio` objects."""
+
+
+# endregion
+
+# region document_filter
+async def document_filter(_, __, m: Message):
+ return bool(m.document)
+
+
+document = create(document_filter)
+"""Filter messages that contain :obj:`~pyrogram.types.Document` objects."""
+
+
+# endregion
+
+# region photo_filter
+async def photo_filter(_, __, m: Message):
+ return bool(m.photo)
+
+
+photo = create(photo_filter)
+"""Filter messages that contain :obj:`~pyrogram.types.Photo` objects."""
+
+
+# endregion
+
+# region sticker_filter
+async def sticker_filter(_, __, m: Message):
+ return bool(m.sticker)
+
+
+sticker = create(sticker_filter)
+"""Filter messages that contain :obj:`~pyrogram.types.Sticker` objects."""
+
+
+# endregion
+
+# region animation_filter
+async def animation_filter(_, __, m: Message):
+ return bool(m.animation)
+
+
+animation = create(animation_filter)
+"""Filter messages that contain :obj:`~pyrogram.types.Animation` objects."""
+
+
+# endregion
+
+# region game_filter
+async def game_filter(_, __, m: Message):
+ return bool(m.game)
+
+
+game = create(game_filter)
+"""Filter messages that contain :obj:`~pyrogram.types.Game` objects."""
+
+
+# endregion
+
+# region video_filter
+async def video_filter(_, __, m: Message):
+ return bool(m.video)
+
+
+video = create(video_filter)
+"""Filter messages that contain :obj:`~pyrogram.types.Video` objects."""
+
+
+# endregion
+
+# region media_group_filter
+async def media_group_filter(_, __, m: Message):
+ return bool(m.media_group_id)
+
+
+media_group = create(media_group_filter)
+"""Filter messages containing photos or videos being part of an album."""
+
+
+# endregion
+
+# region voice_filter
+async def voice_filter(_, __, m: Message):
+ return bool(m.voice)
+
+
+voice = create(voice_filter)
+"""Filter messages that contain :obj:`~pyrogram.types.Voice` note objects."""
+
+
+# endregion
+
+# region video_note_filter
+async def video_note_filter(_, __, m: Message):
+ return bool(m.video_note)
+
+
+video_note = create(video_note_filter)
+"""Filter messages that contain :obj:`~pyrogram.types.VideoNote` objects."""
+
+
+# endregion
+
+# region contact_filter
+async def contact_filter(_, __, m: Message):
+ return bool(m.contact)
+
+
+contact = create(contact_filter)
+"""Filter messages that contain :obj:`~pyrogram.types.Contact` objects."""
+
+
+# endregion
+
+# region location_filter
+async def location_filter(_, __, m: Message):
+ return bool(m.location)
+
+
+location = create(location_filter)
+"""Filter messages that contain :obj:`~pyrogram.types.Location` objects."""
+
+
+# endregion
+
+# region venue_filter
+async def venue_filter(_, __, m: Message):
+ return bool(m.venue)
+
+
+venue = create(venue_filter)
+"""Filter messages that contain :obj:`~pyrogram.types.Venue` objects."""
+
+
+# endregion
+
+# region web_page_filter
+async def web_page_filter(_, __, m: Message):
+ return m.web_page
+
+
+web_page = create(web_page_filter)
+"""Filter messages sent with a webpage preview."""
+
+
+# endregion
+
+# region poll_filter
+async def poll_filter(_, __, m: Message):
+ return m.poll
+
+
+poll = create(poll_filter)
+"""Filter messages that contain :obj:`~pyrogram.types.Poll` objects."""
+
+
+# endregion
+
+# region private_filter
+async def private_filter(_, __, m: Message):
+ return bool(m.chat and m.chat.type in {"private", "bot"})
+
+
+private = create(private_filter)
+"""Filter messages sent in private chats."""
+
+
+# endregion
+
+# region group_filter
+async def group_filter(_, __, m: Message):
+ return bool(m.chat and m.chat.type in {"group", "supergroup"})
+
+
+group = create(group_filter)
+"""Filter messages sent in group or supergroup chats."""
+
+
+# endregion
+
+# region channel_filter
+async def channel_filter(_, __, m: Message):
+ return bool(m.chat and m.chat.type == "channel")
+
+
+channel = create(channel_filter)
+"""Filter messages sent in channels."""
+
+
+# endregion
+
+# region new_chat_members_filter
+async def new_chat_members_filter(_, __, m: Message):
+ return bool(m.new_chat_members)
+
+
+new_chat_members = create(new_chat_members_filter)
+"""Filter service messages for new chat members."""
+
+
+# endregion
+
+# region left_chat_member_filter
+async def left_chat_member_filter(_, __, m: Message):
+ return bool(m.left_chat_member)
+
+
+left_chat_member = create(left_chat_member_filter)
+"""Filter service messages for members that left the chat."""
+
+
+# endregion
+
+# region new_chat_title_filter
+async def new_chat_title_filter(_, __, m: Message):
+ return bool(m.new_chat_title)
+
+
+new_chat_title = create(new_chat_title_filter)
+"""Filter service messages for new chat titles."""
+
+
+# endregion
+
+# region new_chat_photo_filter
+async def new_chat_photo_filter(_, __, m: Message):
+ return bool(m.new_chat_photo)
+
+
+new_chat_photo = create(new_chat_photo_filter)
+"""Filter service messages for new chat photos."""
+
+
+# endregion
+
+# region delete_chat_photo_filter
+async def delete_chat_photo_filter(_, __, m: Message):
+ return bool(m.delete_chat_photo)
+
+
+delete_chat_photo = create(delete_chat_photo_filter)
+"""Filter service messages for deleted photos."""
+
+
+# endregion
+
+# region group_chat_created_filter
+async def group_chat_created_filter(_, __, m: Message):
+ return bool(m.group_chat_created)
+
+
+group_chat_created = create(group_chat_created_filter)
+"""Filter service messages for group chat creations."""
+
+
+# endregion
+
+# region supergroup_chat_created_filter
+async def supergroup_chat_created_filter(_, __, m: Message):
+ return bool(m.supergroup_chat_created)
+
+
+supergroup_chat_created = create(supergroup_chat_created_filter)
+"""Filter service messages for supergroup chat creations."""
+
+
+# endregion
+
+# region channel_chat_created_filter
+async def channel_chat_created_filter(_, __, m: Message):
+ return bool(m.channel_chat_created)
+
+
+channel_chat_created = create(channel_chat_created_filter)
+"""Filter service messages for channel chat creations."""
+
+
+# endregion
+
+# region migrate_to_chat_id_filter
+async def migrate_to_chat_id_filter(_, __, m: Message):
+ return bool(m.migrate_to_chat_id)
+
+
+migrate_to_chat_id = create(migrate_to_chat_id_filter)
+"""Filter service messages that contain migrate_to_chat_id."""
+
+
+# endregion
+
+# region migrate_from_chat_id_filter
+async def migrate_from_chat_id_filter(_, __, m: Message):
+ return bool(m.migrate_from_chat_id)
+
+
+migrate_from_chat_id = create(migrate_from_chat_id_filter)
+"""Filter service messages that contain migrate_from_chat_id."""
+
+
+# endregion
+
+# region pinned_message_filter
+async def pinned_message_filter(_, __, m: Message):
+ return bool(m.pinned_message)
+
+
+pinned_message = create(pinned_message_filter)
+"""Filter service messages for pinned messages."""
+
+
+# endregion
+
+# region game_high_score_filter
+async def game_high_score_filter(_, __, m: Message):
+ return bool(m.game_high_score)
+
+
+game_high_score = create(game_high_score_filter)
+"""Filter service messages for game high scores."""
+
+
+# endregion
+
+# region reply_keyboard_filter
+async def reply_keyboard_filter(_, __, m: Message):
+ return isinstance(m.reply_markup, ReplyKeyboardMarkup)
+
+
+reply_keyboard = create(reply_keyboard_filter)
+"""Filter messages containing reply keyboard markups"""
+
+
+# endregion
+
+# region inline_keyboard_filter
+async def inline_keyboard_filter(_, __, m: Message):
+ return isinstance(m.reply_markup, InlineKeyboardMarkup)
+
+
+inline_keyboard = create(inline_keyboard_filter)
+"""Filter messages containing inline keyboard markups"""
+
+
+# endregion
+
+# region mentioned_filter
+async def mentioned_filter(_, __, m: Message):
+ return bool(m.mentioned)
+
+
+mentioned = create(mentioned_filter)
+"""Filter messages containing mentions"""
+
+
+# endregion
+
+# region via_bot_filter
+async def via_bot_filter(_, __, m: Message):
+ return bool(m.via_bot)
+
+
+via_bot = create(via_bot_filter)
+"""Filter messages sent via inline bots"""
+
+
+# endregion
+
+# region service_filter
+async def service_filter(_, __, m: Message):
+ return bool(m.service)
+
+
+service = create(service_filter)
+"""Filter service messages.
+
+A service message contains any of the following fields set: *left_chat_member*,
+*new_chat_title*, *new_chat_photo*, *delete_chat_photo*, *group_chat_created*, *supergroup_chat_created*,
+*channel_chat_created*, *migrate_to_chat_id*, *migrate_from_chat_id*, *pinned_message*, *game_score*.
+"""
+
+
+# endregion
+
+# region media_filter
+async def media_filter(_, __, m: Message):
+ return bool(m.media)
+
+
+media = create(media_filter)
+"""Filter media messages.
+
+A media message contains any of the following fields set: *audio*, *document*, *photo*, *sticker*, *video*,
+*animation*, *voice*, *video_note*, *contact*, *location*, *venue*, *poll*.
+"""
+
+
+# endregion
+
+# region scheduled_filter
+async def scheduled_filter(_, __, m: Message):
+ return bool(m.scheduled)
+
+
+scheduled = create(scheduled_filter)
+"""Filter messages that have been scheduled (not yet sent)."""
+
+
+# endregion
+
+# region from_scheduled_filter
+async def from_scheduled_filter(_, __, m: Message):
+ return bool(m.from_scheduled)
+
+
+from_scheduled = create(from_scheduled_filter)
+"""Filter new automatically sent messages that were previously scheduled."""
+
+
+# endregion
+
+# region linked_channel_filter
+async def linked_channel_filter(_, __, m: Message):
+ return bool(m.forward_from_chat and not m.from_user)
+
+
+linked_channel = create(linked_channel_filter)
+"""Filter messages that are automatically forwarded from the linked channel to the group chat."""
+
+
+# endregion
+
+
+def command(commands: str or List[str], prefixes: str or List[str] = "/", case_sensitive: bool = False):
+ """Filter commands, i.e.: text messages starting with "/" or any other custom prefix.
+
+ Parameters:
+ commands (``str`` | ``list``):
+ The command or list of commands as string the filter should look for.
+ Examples: "start", ["start", "help", "settings"]. When a message text containing
+ a command arrives, the command itself and its arguments will be stored in the *command*
+ field of the :obj:`~pyrogram.types.Message`.
+
+ prefixes (``str`` | ``list``, *optional*):
+ A prefix or a list of prefixes as string the filter should look for.
+ Defaults to "/" (slash). Examples: ".", "!", ["/", "!", "."], list(".:!").
+ Pass None or "" (empty string) to allow commands with no prefix at all.
+
+ case_sensitive (``bool``, *optional*):
+ Pass True if you want your command(s) to be case sensitive. Defaults to False.
+ Examples: when True, command="Start" would trigger /Start but not /start.
+ """
+ command_re = re.compile(r"([\"'])(.*?)(?`_ are
+ stored in the ``matches`` field of the update object itself.
+
+ Parameters:
+ pattern (``str`` | ``Pattern``):
+ The regex pattern as string or as pre-compiled pattern.
+
+ flags (``int``, *optional*):
+ Regex flags.
+ """
+
+ async def func(flt, _, update: Update):
+ if isinstance(update, Message):
+ value = update.text or update.caption
+ elif isinstance(update, CallbackQuery):
+ value = update.data
+ elif isinstance(update, InlineQuery):
+ value = update.query
+ else:
+ raise ValueError(f"Regex filter doesn't work with {type(update)}")
+
+ if value:
+ update.matches = list(flt.p.finditer(value)) or None
+
+ return bool(update.matches)
+
+ return create(
+ func,
+ "RegexFilter",
+ p=pattern if isinstance(pattern, Pattern) else re.compile(pattern, flags)
+ )
+
+
+# noinspection PyPep8Naming
+class user(Filter, set):
+ """Filter messages coming from one or more users.
+
+ You can use `set bound methods `_ to manipulate the
+ users container.
+
+ Parameters:
+ users (``int`` | ``str`` | ``list``):
+ Pass one or more user ids/usernames to filter users.
+ For you yourself, "me" or "self" can be used as well.
+ Defaults to None (no users).
+ """
+
+ def __init__(self, users: int or str or list = None):
+ users = [] if users is None else users if isinstance(users, list) else [users]
+
+ super().__init__(
+ "me" if u in ["me", "self"]
+ else u.lower().strip("@") if isinstance(u, str)
+ else u for u in users
+ )
+
+ async def __call__(self, _, message: Message):
+ return (message.from_user
+ and (message.from_user.id in self
+ or (message.from_user.username
+ and message.from_user.username.lower() in self)
+ or ("me" in self
+ and message.from_user.is_self)))
+
+
+# noinspection PyPep8Naming
+class chat(Filter, set):
+ """Filter messages coming from one or more chats.
+
+ You can use `set bound methods `_ to manipulate the
+ chats container.
+
+ Parameters:
+ chats (``int`` | ``str`` | ``list``):
+ Pass one or more chat ids/usernames to filter chats.
+ For your personal cloud (Saved Messages) you can simply use "me" or "self".
+ Defaults to None (no chats).
+ """
+
+ def __init__(self, chats: int or str or list = None):
+ chats = [] if chats is None else chats if isinstance(chats, list) else [chats]
+
+ super().__init__(
+ "me" if c in ["me", "self"]
+ else c.lower().strip("@") if isinstance(c, str)
+ else c for c in chats
+ )
+
+ async def __call__(self, _, message: Message):
+ return (message.chat
+ and (message.chat.id in self
+ or (message.chat.username
+ and message.chat.username.lower() in self)
+ or ("me" in self
+ and message.from_user
+ and message.from_user.is_self
+ and not message.outgoing)))
+
+
+# region dan_filter
+async def dan_filter(_, __, m: Message):
+ return bool(m.from_user and m.from_user.id == 23122162)
+
+
+dan = create(dan_filter)
+# endregion
diff --git a/pyrogram/client/handlers/__init__.py b/pyrogram/handlers/__init__.py
similarity index 85%
rename from pyrogram/client/handlers/__init__.py
rename to pyrogram/handlers/__init__.py
index 87ef10c5bd..e0c37e87c3 100644
--- a/pyrogram/client/handlers/__init__.py
+++ b/pyrogram/handlers/__init__.py
@@ -17,6 +17,7 @@
# along with Pyrogram. If not, see .
from .callback_query_handler import CallbackQueryHandler
+from .chosen_inline_result_handler import ChosenInlineResultHandler
from .deleted_messages_handler import DeletedMessagesHandler
from .disconnect_handler import DisconnectHandler
from .inline_query_handler import InlineQueryHandler
@@ -24,9 +25,3 @@
from .poll_handler import PollHandler
from .raw_update_handler import RawUpdateHandler
from .user_status_handler import UserStatusHandler
-from .chosen_inline_result_handler import ChosenInlineResultHandler
-
-__all__ = [
- "MessageHandler", "DeletedMessagesHandler", "CallbackQueryHandler", "RawUpdateHandler", "DisconnectHandler",
- "UserStatusHandler", "InlineQueryHandler", "PollHandler", "ChosenInlineResultHandler"
-]
diff --git a/pyrogram/client/handlers/callback_query_handler.py b/pyrogram/handlers/callback_query_handler.py
similarity index 88%
rename from pyrogram/client/handlers/callback_query_handler.py
rename to pyrogram/handlers/callback_query_handler.py
index 99aa2e70b7..84e7ebede3 100644
--- a/pyrogram/client/handlers/callback_query_handler.py
+++ b/pyrogram/handlers/callback_query_handler.py
@@ -21,10 +21,10 @@
class CallbackQueryHandler(Handler):
"""The CallbackQuery handler class. Used to handle callback queries coming from inline buttons.
- It is intended to be used with :meth:`~Client.add_handler`
+ It is intended to be used with :meth:`~pyrogram.Client.add_handler`
For a nicer way to register this handler, have a look at the
- :meth:`~Client.on_callback_query` decorator.
+ :meth:`~pyrogram.Client.on_callback_query` decorator.
Parameters:
callback (``callable``):
@@ -36,10 +36,10 @@ class CallbackQueryHandler(Handler):
in your callback function.
Other parameters:
- client (:obj:`Client`):
+ client (:obj:`~pyrogram.Client`):
The Client itself, useful when you want to call other API methods inside the message handler.
- callback_query (:obj:`CallbackQuery `):
+ callback_query (:obj:`~pyrogram.types.CallbackQuery`):
The received callback query.
"""
diff --git a/pyrogram/client/handlers/chosen_inline_result_handler.py b/pyrogram/handlers/chosen_inline_result_handler.py
similarity index 87%
rename from pyrogram/client/handlers/chosen_inline_result_handler.py
rename to pyrogram/handlers/chosen_inline_result_handler.py
index f5014ab08e..428b153dd6 100644
--- a/pyrogram/client/handlers/chosen_inline_result_handler.py
+++ b/pyrogram/handlers/chosen_inline_result_handler.py
@@ -21,10 +21,10 @@
class ChosenInlineResultHandler(Handler):
"""The ChosenInlineResultHandler handler class. Used to handle chosen inline results coming from inline queries.
- It is intended to be used with :meth:`~Client.add_handler`
+ It is intended to be used with :meth:`~pyrogram.Client.add_handler`
For a nicer way to register this handler, have a look at the
- :meth:`~Client.on_chosen_inline_query` decorator.
+ :meth:`~pyrogram.Client.on_chosen_inline_query` decorator.
Parameters:
callback (``callable``):
@@ -37,10 +37,10 @@ class ChosenInlineResultHandler(Handler):
in your callback function.
Other parameters:
- client (:obj:`Client`):
+ client (:obj:`~pyrogram.Client`):
The Client itself, useful when you want to call other API methods inside the message handler.
- chosen_inline_result (:obj:`ChosenInlineResult`):
+ chosen_inline_result (:obj:`~pyrogram.types.ChosenInlineResult`):
The received chosen inline result.
"""
diff --git a/pyrogram/client/handlers/deleted_messages_handler.py b/pyrogram/handlers/deleted_messages_handler.py
similarity index 77%
rename from pyrogram/client/handlers/deleted_messages_handler.py
rename to pyrogram/handlers/deleted_messages_handler.py
index 0386354163..2073092ce0 100644
--- a/pyrogram/client/handlers/deleted_messages_handler.py
+++ b/pyrogram/handlers/deleted_messages_handler.py
@@ -16,15 +16,20 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import List, Callable
+
+import pyrogram
+from pyrogram.filters import Filter
+from pyrogram.types import Message
from .handler import Handler
class DeletedMessagesHandler(Handler):
"""The deleted messages handler class. Used to handle deleted messages coming from any chat
- (private, group, channel). It is intended to be used with :meth:`~Client.add_handler`
+ (private, group, channel). It is intended to be used with :meth:`~pyrogram.Client.add_handler`
For a nicer way to register this handler, have a look at the
- :meth:`~Client.on_deleted_messages` decorator.
+ :meth:`~pyrogram.Client.on_deleted_messages` decorator.
Parameters:
callback (``callable``):
@@ -36,15 +41,15 @@ class DeletedMessagesHandler(Handler):
in your callback function.
Other parameters:
- client (:obj:`Client`):
+ client (:obj:`~pyrogram.Client`):
The Client itself, useful when you want to call other API methods inside the message handler.
- messages (List of :obj:`Message`):
+ messages (List of :obj:`~pyrogram.types.Message`):
The deleted messages, as list.
"""
- def __init__(self, callback: callable, filters=None):
+ def __init__(self, callback: Callable, filters: Filter = None):
super().__init__(callback, filters)
- async def check(self, messages):
- return (await super().check(messages[0]))
+ async def check(self, client: "pyrogram.Client", messages: List[Message]):
+ return await super().check(client, messages[0])
diff --git a/pyrogram/client/handlers/disconnect_handler.py b/pyrogram/handlers/disconnect_handler.py
similarity index 91%
rename from pyrogram/client/handlers/disconnect_handler.py
rename to pyrogram/handlers/disconnect_handler.py
index f4aec6b22d..59ab401571 100644
--- a/pyrogram/client/handlers/disconnect_handler.py
+++ b/pyrogram/handlers/disconnect_handler.py
@@ -21,10 +21,10 @@
class DisconnectHandler(Handler):
"""The Disconnect handler class. Used to handle disconnections. It is intended to be used with
- :meth:`~Client.add_handler`
+ :meth:`~pyrogram.Client.add_handler`
For a nicer way to register this handler, have a look at the
- :meth:`~Client.on_disconnect` decorator.
+ :meth:`~pyrogram.Client.on_disconnect` decorator.
Parameters:
callback (``callable``):
@@ -32,7 +32,7 @@ class DisconnectHandler(Handler):
as positional argument (look at the section below for a detailed description).
Other parameters:
- client (:obj:`Client`):
+ client (:obj:`~pyrogram.Client`):
The Client itself. Useful, for example, when you want to change the proxy before a new connection
is established.
"""
diff --git a/pyrogram/client/handlers/handler.py b/pyrogram/handlers/handler.py
similarity index 59%
rename from pyrogram/client/handlers/handler.py
rename to pyrogram/handlers/handler.py
index d50b069b33..d4d41ea56c 100644
--- a/pyrogram/client/handlers/handler.py
+++ b/pyrogram/handlers/handler.py
@@ -16,22 +16,28 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-import asyncio
+import inspect
+from typing import Callable
+
+import pyrogram
+from pyrogram.filters import Filter
+from pyrogram.types import Update
class Handler:
- def __init__(self, callback: callable, filters=None):
+ def __init__(self, callback: Callable, filters: Filter = None):
self.callback = callback
self.filters = filters
- async def check(self, update):
-
- if callable(self.filters):
- if asyncio.iscoroutinefunction(self.filters.__call__):
- return (await self.filters(update))
-
+ async def check(self, client: "pyrogram.Client", update: Update):
+ if self.filters:
+ if inspect.iscoroutinefunction(self.filters.__call__):
+ return await self.filters(client, update)
else:
- return self.filters(update)
+ return await client.loop.run_in_executor(
+ client.executor,
+ self.filters,
+ client, update
+ )
- else:
- return True
+ return True
diff --git a/pyrogram/client/handlers/inline_query_handler.py b/pyrogram/handlers/inline_query_handler.py
similarity index 88%
rename from pyrogram/client/handlers/inline_query_handler.py
rename to pyrogram/handlers/inline_query_handler.py
index aaa63c351c..af7f9e3bad 100644
--- a/pyrogram/client/handlers/inline_query_handler.py
+++ b/pyrogram/handlers/inline_query_handler.py
@@ -21,10 +21,10 @@
class InlineQueryHandler(Handler):
"""The InlineQuery handler class. Used to handle inline queries.
- It is intended to be used with :meth:`~Client.add_handler`
+ It is intended to be used with :meth:`~pyrogram.Client.add_handler`
For a nicer way to register this handler, have a look at the
- :meth:`~Client.on_inline_query` decorator.
+ :meth:`~pyrogram.Client.on_inline_query` decorator.
Parameters:
callback (``callable``):
@@ -36,10 +36,10 @@ class InlineQueryHandler(Handler):
in your callback function.
Other parameters:
- client (:obj:`Client`):
+ client (:obj:`~pyrogram.Client`):
The Client itself, useful when you want to call other API methods inside the inline query handler.
- inline_query (:obj:`InlineQuery`):
+ inline_query (:obj:`~pyrogram.types.InlineQuery`):
The received inline query.
"""
diff --git a/pyrogram/client/handlers/message_handler.py b/pyrogram/handlers/message_handler.py
similarity index 90%
rename from pyrogram/client/handlers/message_handler.py
rename to pyrogram/handlers/message_handler.py
index f5a3b6e935..e9ef2aa53c 100644
--- a/pyrogram/client/handlers/message_handler.py
+++ b/pyrogram/handlers/message_handler.py
@@ -21,10 +21,10 @@
class MessageHandler(Handler):
"""The Message handler class. Used to handle text, media and service messages coming from
- any chat (private, group, channel). It is intended to be used with :meth:`~Client.add_handler`
+ any chat (private, group, channel). It is intended to be used with :meth:`~pyrogram.Client.add_handler`
For a nicer way to register this handler, have a look at the
- :meth:`~Client.on_message` decorator.
+ :meth:`~pyrogram.Client.on_message` decorator.
Parameters:
callback (``callable``):
@@ -36,10 +36,10 @@ class MessageHandler(Handler):
in your callback function.
Other parameters:
- client (:obj:`Client`):
+ client (:obj:`~pyrogram.Client`):
The Client itself, useful when you want to call other API methods inside the message handler.
- message (:obj:`Message`):
+ message (:obj:`~pyrogram.types.Message`):
The received message.
"""
diff --git a/pyrogram/client/handlers/poll_handler.py b/pyrogram/handlers/poll_handler.py
similarity index 89%
rename from pyrogram/client/handlers/poll_handler.py
rename to pyrogram/handlers/poll_handler.py
index 9dc90c4f56..3fe7c382af 100644
--- a/pyrogram/client/handlers/poll_handler.py
+++ b/pyrogram/handlers/poll_handler.py
@@ -22,10 +22,10 @@
class PollHandler(Handler):
"""The Poll handler class. Used to handle polls updates.
- It is intended to be used with :meth:`~Client.add_handler`
+ It is intended to be used with :meth:`~pyrogram.Client.add_handler`
For a nicer way to register this handler, have a look at the
- :meth:`~Client.on_poll` decorator.
+ :meth:`~pyrogram.Client.on_poll` decorator.
Parameters:
callback (``callable``):
@@ -37,10 +37,10 @@ class PollHandler(Handler):
in your callback function.
Other parameters:
- client (:obj:`Client`):
+ client (:obj:`~pyrogram.Client`):
The Client itself, useful when you want to call other API methods inside the poll handler.
- poll (:obj:`Poll`):
+ poll (:obj:`~pyrogram.types.Poll`):
The received poll.
"""
diff --git a/pyrogram/client/handlers/raw_update_handler.py b/pyrogram/handlers/raw_update_handler.py
similarity index 88%
rename from pyrogram/client/handlers/raw_update_handler.py
rename to pyrogram/handlers/raw_update_handler.py
index fa01ced53c..9376409b3e 100644
--- a/pyrogram/client/handlers/raw_update_handler.py
+++ b/pyrogram/handlers/raw_update_handler.py
@@ -21,10 +21,10 @@
class RawUpdateHandler(Handler):
"""The Raw Update handler class. Used to handle raw updates. It is intended to be used with
- :meth:`~Client.add_handler`
+ :meth:`~pyrogram.Client.add_handler`
For a nicer way to register this handler, have a look at the
- :meth:`~Client.on_raw_update` decorator.
+ :meth:`~pyrogram.Client.on_raw_update` decorator.
Parameters:
callback (``callable``):
@@ -33,20 +33,20 @@ class RawUpdateHandler(Handler):
a detailed description).
Other Parameters:
- client (:obj:`Client`):
+ client (:obj:`~pyrogram.Client`):
The Client itself, useful when you want to call other API methods inside the update handler.
update (``Update``):
The received update, which can be one of the many single Updates listed in the *updates*
- field you see in the :obj:`Update ` type.
+ field you see in the :obj:`~pyrogram.types.Update` type.
users (``dict``):
- Dictionary of all :obj:`User ` mentioned in the update.
+ Dictionary of all :obj:`~pyrogram.types.User` mentioned in the update.
You can access extra info about the user (such as *first_name*, *last_name*, etc...) by using
the IDs you find in the *update* argument (e.g.: *users[1768841572]*).
chats (``dict``):
- Dictionary of all :obj:`Chat ` and
+ Dictionary of all :obj:`~pyrogram.types.Chat` and
:obj:`Channel ` mentioned in the update.
You can access extra info about the chat (such as *title*, *participants_count*, etc...)
by using the IDs you find in the *update* argument (e.g.: *chats[1701277281]*).
diff --git a/pyrogram/client/handlers/user_status_handler.py b/pyrogram/handlers/user_status_handler.py
similarity index 89%
rename from pyrogram/client/handlers/user_status_handler.py
rename to pyrogram/handlers/user_status_handler.py
index 94404d69f2..50c5a89e5a 100644
--- a/pyrogram/client/handlers/user_status_handler.py
+++ b/pyrogram/handlers/user_status_handler.py
@@ -21,9 +21,9 @@
class UserStatusHandler(Handler):
"""The UserStatus handler class. Used to handle user status updates (user going online or offline).
- It is intended to be used with :meth:`~Client.add_handler`.
+ It is intended to be used with :meth:`~pyrogram.Client.add_handler`.
- For a nicer way to register this handler, have a look at the :meth:`~Client.on_user_status` decorator.
+ For a nicer way to register this handler, have a look at the :meth:`~pyrogram.Client.on_user_status` decorator.
Parameters:
callback (``callable``):
@@ -34,10 +34,10 @@ class UserStatusHandler(Handler):
Pass one or more filters to allow only a subset of users to be passed in your callback function.
Other parameters:
- client (:obj:`Client`):
+ client (:obj:`~pyrogram.Client`):
The Client itself, useful when you want to call other API methods inside the user status handler.
- user (:obj:`User`):
+ user (:obj:`~pyrogram.types.User`):
The user containing the updated status.
"""
diff --git a/pyrogram/client/methods/__init__.py b/pyrogram/methods/__init__.py
similarity index 88%
rename from pyrogram/client/methods/__init__.py
rename to pyrogram/methods/__init__.py
index 54516e98fd..30fe28a388 100644
--- a/pyrogram/client/methods/__init__.py
+++ b/pyrogram/methods/__init__.py
@@ -16,6 +16,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from .advanced import Advanced
+from .auth import Auth
from .bots import Bots
from .chats import Chats
from .contacts import Contacts
@@ -23,15 +25,19 @@
from .messages import Messages
from .password import Password
from .users import Users
+from .utilities import Utilities
class Methods(
+ Advanced,
+ Auth,
Bots,
Contacts,
Password,
Chats,
Users,
Messages,
- Decorators
+ Decorators,
+ Utilities
):
pass
diff --git a/pyrogram/methods/advanced/__init__.py b/pyrogram/methods/advanced/__init__.py
new file mode 100644
index 0000000000..318f40eef2
--- /dev/null
+++ b/pyrogram/methods/advanced/__init__.py
@@ -0,0 +1,29 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+from .resolve_peer import ResolvePeer
+from .save_file import SaveFile
+from .send import Send
+
+
+class Advanced(
+ ResolvePeer,
+ SaveFile,
+ Send
+):
+ pass
diff --git a/pyrogram/methods/advanced/resolve_peer.py b/pyrogram/methods/advanced/resolve_peer.py
new file mode 100644
index 0000000000..babc35d3a5
--- /dev/null
+++ b/pyrogram/methods/advanced/resolve_peer.py
@@ -0,0 +1,123 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import logging
+import re
+from typing import Union
+
+from pyrogram import raw
+from pyrogram import utils
+from pyrogram.errors import PeerIdInvalid
+from pyrogram.scaffold import Scaffold
+
+log = logging.getLogger(__name__)
+
+
+class ResolvePeer(Scaffold):
+ async def resolve_peer(
+ self,
+ peer_id: Union[int, str]
+ ) -> Union[raw.base.InputPeer, raw.base.InputUser, raw.base.InputChannel]:
+ """Get the InputPeer of a known peer id.
+ Useful whenever an InputPeer type is required.
+
+ .. note::
+
+ This is a utility method intended to be used **only** when working with raw
+ :obj:`functions ` (i.e: a Telegram API method you wish to use which is not
+ available yet in the Client class as an easy-to-use method).
+
+ Parameters:
+ peer_id (``int`` | ``str``):
+ The peer id you want to extract the InputPeer from.
+ Can be a direct id (int), a username (str) or a phone number (str).
+
+ Returns:
+ ``InputPeer``: On success, the resolved peer id is returned in form of an InputPeer object.
+
+ Raises:
+ KeyError: In case the peer doesn't exist in the internal database.
+ """
+ if not self.is_connected:
+ raise ConnectionError("Client has not been started yet")
+
+ try:
+ return await self.storage.get_peer_by_id(peer_id)
+ except KeyError:
+ if isinstance(peer_id, str):
+ if peer_id in ("self", "me"):
+ return raw.types.InputPeerSelf()
+
+ peer_id = re.sub(r"[@+\s]", "", peer_id.lower())
+
+ try:
+ int(peer_id)
+ except ValueError:
+ try:
+ return await self.storage.get_peer_by_username(peer_id)
+ except KeyError:
+ await self.send(
+ raw.functions.contacts.ResolveUsername(
+ username=peer_id
+ )
+ )
+
+ return await self.storage.get_peer_by_username(peer_id)
+ else:
+ try:
+ return await self.storage.get_peer_by_phone_number(peer_id)
+ except KeyError:
+ raise PeerIdInvalid
+
+ peer_type = utils.get_peer_type(peer_id)
+
+ if peer_type == "user":
+ await self.fetch_peers(
+ await self.send(
+ raw.functions.users.GetUsers(
+ id=[
+ raw.types.InputUser(
+ user_id=peer_id,
+ access_hash=0
+ )
+ ]
+ )
+ )
+ )
+ elif peer_type == "chat":
+ await self.send(
+ raw.functions.messages.GetChats(
+ id=[-peer_id]
+ )
+ )
+ else:
+ await self.send(
+ raw.functions.channels.GetChannels(
+ id=[
+ raw.types.InputChannel(
+ channel_id=utils.get_channel_id(peer_id),
+ access_hash=0
+ )
+ ]
+ )
+ )
+
+ try:
+ return await self.storage.get_peer_by_id(peer_id)
+ except KeyError:
+ raise PeerIdInvalid
diff --git a/pyrogram/methods/advanced/save_file.py b/pyrogram/methods/advanced/save_file.py
new file mode 100644
index 0000000000..4e594b6485
--- /dev/null
+++ b/pyrogram/methods/advanced/save_file.py
@@ -0,0 +1,222 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import asyncio
+import functools
+import io
+import logging
+import math
+import os
+from hashlib import md5
+from pathlib import PurePath
+from typing import Union, BinaryIO
+
+from pyrogram import StopTransmission
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
+from pyrogram.session import Session
+
+log = logging.getLogger(__name__)
+
+
+class SaveFile(Scaffold):
+ async def save_file(
+ self,
+ path: Union[str, BinaryIO],
+ file_id: int = None,
+ file_part: int = 0,
+ progress: callable = None,
+ progress_args: tuple = ()
+ ):
+ """Upload a file onto Telegram servers, without actually sending the message to anyone.
+ Useful whenever an InputFile type is required.
+
+ .. note::
+
+ This is a utility method intended to be used **only** when working with raw
+ :obj:`functions ` (i.e: a Telegram API method you wish to use which is not
+ available yet in the Client class as an easy-to-use method).
+
+ Parameters:
+ path (``str``):
+ The path of the file you want to upload that exists on your local machine.
+
+ file_id (``int``, *optional*):
+ In case a file part expired, pass the file_id and the file_part to retry uploading that specific chunk.
+
+ file_part (``int``, *optional*):
+ In case a file part expired, pass the file_id and the file_part to retry uploading that specific chunk.
+
+ progress (``callable``, *optional*):
+ Pass a callback function to view the file transmission progress.
+ The function must take *(current, total)* as positional arguments (look at Other Parameters below for a
+ detailed description) and will be called back each time a new file chunk has been successfully
+ transmitted.
+
+ progress_args (``tuple``, *optional*):
+ Extra custom arguments for the progress callback function.
+ You can pass anything you need to be available in the progress callback scope; for example, a Message
+ object or a Client instance in order to edit the message with the updated progress status.
+
+ Other Parameters:
+ current (``int``):
+ The amount of bytes transmitted so far.
+
+ total (``int``):
+ The total size of the file.
+
+ *args (``tuple``, *optional*):
+ Extra custom arguments as defined in the *progress_args* parameter.
+ You can either keep *\*args* or add every single extra argument in your function signature.
+
+ Returns:
+ ``InputFile``: On success, the uploaded file is returned in form of an InputFile object.
+
+ Raises:
+ RPCError: In case of a Telegram RPC error.
+ """
+ if path is None:
+ return None
+
+ async def worker(session):
+ while True:
+ data = await queue.get()
+
+ if data is None:
+ return
+
+ try:
+ await asyncio.ensure_future(session.send(data))
+ except Exception as e:
+ log.error(e)
+
+ part_size = 512 * 1024
+
+ if isinstance(path, (str, PurePath)):
+ fp = open(path, "rb")
+ elif isinstance(path, io.IOBase):
+ fp = path
+ else:
+ raise ValueError("Invalid file. Expected a file path as string or a binary (not text) file pointer")
+
+ file_name = fp.name
+
+ fp.seek(0, os.SEEK_END)
+ file_size = fp.tell()
+ fp.seek(0)
+
+ if file_size == 0:
+ raise ValueError("File size equals to 0 B")
+
+ if file_size > 2000 * 1024 * 1024:
+ raise ValueError("Telegram doesn't support uploading files bigger than 2000 MiB")
+
+ file_total_parts = int(math.ceil(file_size / part_size))
+ is_big = file_size > 10 * 1024 * 1024
+ pool_size = 3 if is_big else 1
+ workers_count = 4 if is_big else 1
+ is_missing_part = file_id is not None
+ file_id = file_id or self.rnd_id()
+ md5_sum = md5() if not is_big and not is_missing_part else None
+ pool = [
+ Session(
+ self, await self.storage.dc_id(), await self.storage.auth_key(),
+ await self.storage.test_mode(), is_media=True
+ ) for _ in range(pool_size)
+ ]
+ workers = [asyncio.ensure_future(worker(session)) for session in pool for _ in range(workers_count)]
+ queue = asyncio.Queue(16)
+
+ try:
+ for session in pool:
+ await session.start()
+
+ with fp:
+ fp.seek(part_size * file_part)
+
+ while True:
+ chunk = fp.read(part_size)
+
+ if not chunk:
+ if not is_big:
+ md5_sum = "".join([hex(i)[2:].zfill(2) for i in md5_sum.digest()])
+ break
+
+ if is_big:
+ rpc = raw.functions.upload.SaveBigFilePart(
+ file_id=file_id,
+ file_part=file_part,
+ file_total_parts=file_total_parts,
+ bytes=chunk
+ )
+ else:
+ rpc = raw.functions.upload.SaveFilePart(
+ file_id=file_id,
+ file_part=file_part,
+ bytes=chunk
+ )
+
+ await queue.put(rpc)
+
+ if is_missing_part:
+ return
+
+ if not is_big:
+ md5_sum.update(chunk)
+
+ file_part += 1
+
+ if progress:
+ if asyncio.iscoroutinefunction(progress):
+ await progress(min(file_part * part_size, file_size), file_size, *progress_args)
+ else:
+ func = functools.partial(
+ progress,
+ min(file_part * part_size, file_size),
+ file_size,
+ *progress_args
+ )
+
+ await self.loop.run_in_executor(self.executor, func)
+ except StopTransmission:
+ raise
+ except Exception as e:
+ log.error(e, exc_info=True)
+ else:
+ if is_big:
+ return raw.types.InputFileBig(
+ id=file_id,
+ parts=file_total_parts,
+ name=file_name,
+
+ )
+ else:
+ return raw.types.InputFile(
+ id=file_id,
+ parts=file_total_parts,
+ name=file_name,
+ md5_checksum=md5_sum
+ )
+ finally:
+ for _ in workers:
+ await queue.put(None)
+
+ await asyncio.gather(*workers)
+
+ for session in pool:
+ await session.stop()
diff --git a/pyrogram/methods/advanced/send.py b/pyrogram/methods/advanced/send.py
new file mode 100644
index 0000000000..fa6b9f44ce
--- /dev/null
+++ b/pyrogram/methods/advanced/send.py
@@ -0,0 +1,73 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import logging
+
+from pyrogram import raw
+from pyrogram.raw.core import TLObject
+from pyrogram.scaffold import Scaffold
+from pyrogram.session import Session
+
+log = logging.getLogger(__name__)
+
+
+class Send(Scaffold):
+ async def send(self, data: TLObject, retries: int = Session.MAX_RETRIES, timeout: float = Session.WAIT_TIMEOUT):
+ """Send raw Telegram queries.
+
+ This method makes it possible to manually call every single Telegram API method in a low-level manner.
+ Available functions are listed in the :obj:`functions ` package and may accept compound
+ data types from :obj:`types ` as well as bare types such as ``int``, ``str``, etc...
+
+ .. note::
+
+ This is a utility method intended to be used **only** when working with raw
+ :obj:`functions ` (i.e: a Telegram API method you wish to use which is not
+ available yet in the Client class as an easy-to-use method).
+
+ Parameters:
+ data (``RawFunction``):
+ The API Schema function filled with proper arguments.
+
+ retries (``int``):
+ Number of retries.
+
+ timeout (``float``):
+ Timeout in seconds.
+
+ Returns:
+ ``RawType``: The raw type response generated by the query.
+
+ Raises:
+ RPCError: In case of a Telegram RPC error.
+ """
+ if not self.is_connected:
+ raise ConnectionError("Client has not been started yet")
+
+ if self.no_updates:
+ data = raw.functions.InvokeWithoutUpdates(query=data)
+
+ if self.takeout_id:
+ data = raw.functions.InvokeWithTakeout(takeout_id=self.takeout_id, query=data)
+
+ r = await self.session.send(data, retries, timeout, self.sleep_threshold)
+
+ await self.fetch_peers(getattr(r, "users", []))
+ await self.fetch_peers(getattr(r, "chats", []))
+
+ return r
diff --git a/pyrogram/methods/auth/__init__.py b/pyrogram/methods/auth/__init__.py
new file mode 100644
index 0000000000..dca53a0854
--- /dev/null
+++ b/pyrogram/methods/auth/__init__.py
@@ -0,0 +1,53 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+from .accept_terms_of_service import AcceptTermsOfService
+from .check_password import CheckPassword
+from .connect import Connect
+from .disconnect import Disconnect
+from .get_password_hint import GetPasswordHint
+from .initialize import Initialize
+from .log_out import LogOut
+from .recover_password import RecoverPassword
+from .resend_code import ResendCode
+from .send_code import SendCode
+from .send_recovery_code import SendRecoveryCode
+from .sign_in import SignIn
+from .sign_in_bot import SignInBot
+from .sign_up import SignUp
+from .terminate import Terminate
+
+
+class Auth(
+ AcceptTermsOfService,
+ CheckPassword,
+ Connect,
+ Disconnect,
+ GetPasswordHint,
+ Initialize,
+ LogOut,
+ RecoverPassword,
+ ResendCode,
+ SendCode,
+ SendRecoveryCode,
+ SignIn,
+ SignInBot,
+ SignUp,
+ Terminate
+):
+ pass
diff --git a/pyrogram/methods/auth/accept_terms_of_service.py b/pyrogram/methods/auth/accept_terms_of_service.py
new file mode 100644
index 0000000000..33da88af12
--- /dev/null
+++ b/pyrogram/methods/auth/accept_terms_of_service.py
@@ -0,0 +1,41 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
+
+
+class AcceptTermsOfService(Scaffold):
+ async def accept_terms_of_service(self, terms_of_service_id: str) -> bool:
+ """Accept the given terms of service.
+
+ Parameters:
+ terms_of_service_id (``str``):
+ The terms of service identifier.
+ """
+ r = await self.send(
+ raw.functions.help.AcceptTermsOfService(
+ id=raw.types.DataJSON(
+ data=terms_of_service_id
+ )
+ )
+ )
+
+ assert r
+
+ return True
diff --git a/pyrogram/methods/auth/check_password.py b/pyrogram/methods/auth/check_password.py
new file mode 100644
index 0000000000..8942780a65
--- /dev/null
+++ b/pyrogram/methods/auth/check_password.py
@@ -0,0 +1,55 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import logging
+
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
+from pyrogram.utils import compute_password_check
+
+log = logging.getLogger(__name__)
+
+
+class CheckPassword(Scaffold):
+ async def check_password(self, password: str) -> "types.User":
+ """Check your Two-Step Verification password and log in.
+
+ Parameters:
+ password (``str``):
+ Your Two-Step Verification password.
+
+ Returns:
+ :obj:`~pyrogram.types.User`: On success, the authorized user is returned.
+
+ Raises:
+ BadRequest: In case the password is invalid.
+ """
+ r = await self.send(
+ raw.functions.auth.CheckPassword(
+ password=compute_password_check(
+ await self.send(raw.functions.account.GetPassword()),
+ password
+ )
+ )
+ )
+
+ await self.storage.user_id(r.user.id)
+ await self.storage.is_bot(False)
+
+ return types.User._parse(self, r.user)
diff --git a/pyrogram/methods/auth/connect.py b/pyrogram/methods/auth/connect.py
new file mode 100644
index 0000000000..cbb5bec898
--- /dev/null
+++ b/pyrogram/methods/auth/connect.py
@@ -0,0 +1,50 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+from pyrogram.scaffold import Scaffold
+from pyrogram.session import Session
+
+
+class Connect(Scaffold):
+ async def connect(self) -> bool:
+ """
+ Connect the client to Telegram servers.
+
+ Returns:
+ ``bool``: On success, in case the passed-in session is authorized, True is returned. Otherwise, in case
+ the session needs to be authorized, False is returned.
+
+ Raises:
+ ConnectionError: In case you try to connect an already connected client.
+ """
+ if self.is_connected:
+ raise ConnectionError("Client is already connected")
+
+ self.load_config()
+ await self.load_session()
+
+ self.session = Session(
+ self, await self.storage.dc_id(),
+ await self.storage.auth_key(), await self.storage.test_mode()
+ )
+
+ await self.session.start()
+
+ self.is_connected = True
+
+ return bool(await self.storage.user_id())
diff --git a/pyrogram/methods/auth/disconnect.py b/pyrogram/methods/auth/disconnect.py
new file mode 100644
index 0000000000..08b88e6239
--- /dev/null
+++ b/pyrogram/methods/auth/disconnect.py
@@ -0,0 +1,38 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+from pyrogram.scaffold import Scaffold
+
+
+class Disconnect(Scaffold):
+ async def disconnect(self):
+ """Disconnect the client from Telegram servers.
+
+ Raises:
+ ConnectionError: In case you try to disconnect an already disconnected client or in case you try to
+ disconnect a client that needs to be terminated first.
+ """
+ if not self.is_connected:
+ raise ConnectionError("Client is already disconnected")
+
+ if self.is_initialized:
+ raise ConnectionError("Can't disconnect an initialized client")
+
+ await self.session.stop()
+ await self.storage.close()
+ self.is_connected = False
diff --git a/pyrogram/methods/auth/get_password_hint.py b/pyrogram/methods/auth/get_password_hint.py
new file mode 100644
index 0000000000..ca1ad66244
--- /dev/null
+++ b/pyrogram/methods/auth/get_password_hint.py
@@ -0,0 +1,34 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import logging
+
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
+
+log = logging.getLogger(__name__)
+
+
+class GetPasswordHint(Scaffold):
+ async def get_password_hint(self) -> str:
+ """Get your Two-Step Verification password hint.
+
+ Returns:
+ ``str``: On success, the password hint as string is returned.
+ """
+ return (await self.send(raw.functions.account.GetPassword())).hint
diff --git a/pyrogram/methods/auth/initialize.py b/pyrogram/methods/auth/initialize.py
new file mode 100644
index 0000000000..1b50069274
--- /dev/null
+++ b/pyrogram/methods/auth/initialize.py
@@ -0,0 +1,49 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import logging
+
+from pyrogram.scaffold import Scaffold
+from pyrogram.syncer import Syncer
+
+log = logging.getLogger(__name__)
+
+
+class Initialize(Scaffold):
+ async def initialize(self):
+ """Initialize the client by starting up workers.
+
+ This method will start updates and download workers.
+ It will also load plugins and start the internal dispatcher.
+
+ Raises:
+ ConnectionError: In case you try to initialize a disconnected client or in case you try to initialize an
+ already initialized client.
+ """
+ if not self.is_connected:
+ raise ConnectionError("Can't initialize a disconnected client")
+
+ if self.is_initialized:
+ raise ConnectionError("Client is already initialized")
+
+ self.load_plugins()
+
+ await self.dispatcher.start()
+ await Syncer.add(self)
+
+ self.is_initialized = True
diff --git a/pyrogram/methods/auth/log_out.py b/pyrogram/methods/auth/log_out.py
new file mode 100644
index 0000000000..e554c37763
--- /dev/null
+++ b/pyrogram/methods/auth/log_out.py
@@ -0,0 +1,47 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import logging
+
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
+
+log = logging.getLogger(__name__)
+
+
+class LogOut(Scaffold):
+ async def log_out(self):
+ """Log out from Telegram and delete the *\\*.session* file.
+
+ When you log out, the current client is stopped and the storage session deleted.
+ No more API calls can be made until you start the client and re-authorize again.
+
+ Returns:
+ ``bool``: On success, True is returned.
+
+ Example:
+ .. code-block:: python
+
+ # Log out.
+ app.log_out()
+ """
+ await self.send(raw.functions.auth.LogOut())
+ await self.stop()
+ await self.storage.delete()
+
+ return True
diff --git a/pyrogram/methods/auth/recover_password.py b/pyrogram/methods/auth/recover_password.py
new file mode 100644
index 0000000000..f49e4a28a7
--- /dev/null
+++ b/pyrogram/methods/auth/recover_password.py
@@ -0,0 +1,52 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import logging
+
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
+
+log = logging.getLogger(__name__)
+
+
+class RecoverPassword(Scaffold):
+ async def recover_password(self, recovery_code: str) -> "types.User":
+ """Recover your password with a recovery code and log in.
+
+ Parameters:
+ recovery_code (``str``):
+ The recovery code sent via email.
+
+ Returns:
+ :obj:`~pyrogram.types.User`: On success, the authorized user is returned and the Two-Step Verification
+ password reset.
+
+ Raises:
+ BadRequest: In case the recovery code is invalid.
+ """
+ r = await self.send(
+ raw.functions.auth.RecoverPassword(
+ code=recovery_code
+ )
+ )
+
+ await self.storage.user_id(r.user.id)
+ await self.storage.is_bot(False)
+
+ return types.User._parse(self, r.user)
diff --git a/pyrogram/methods/auth/resend_code.py b/pyrogram/methods/auth/resend_code.py
new file mode 100644
index 0000000000..870876a876
--- /dev/null
+++ b/pyrogram/methods/auth/resend_code.py
@@ -0,0 +1,58 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import logging
+
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
+
+log = logging.getLogger(__name__)
+
+
+class ResendCode(Scaffold):
+ async def resend_code(self, phone_number: str, phone_code_hash: str) -> "types.SentCode":
+ """Re-send the confirmation code using a different type.
+
+ The type of the code to be re-sent is specified in the *next_type* attribute of the
+ :obj:`~pyrogram.types.SentCode` object returned by :meth:`send_code`.
+
+ Parameters:
+ phone_number (``str``):
+ Phone number in international format (includes the country prefix).
+
+ phone_code_hash (``str``):
+ Confirmation code identifier.
+
+ Returns:
+ :obj:`~pyrogram.types.SentCode`: On success, an object containing information on the re-sent confirmation
+ code is returned.
+
+ Raises:
+ BadRequest: In case the arguments are invalid.
+ """
+ phone_number = phone_number.strip(" +")
+
+ r = await self.send(
+ raw.functions.auth.ResendCode(
+ phone_number=phone_number,
+ phone_code_hash=phone_code_hash
+ )
+ )
+
+ return types.SentCode._parse(r)
diff --git a/pyrogram/methods/auth/send_code.py b/pyrogram/methods/auth/send_code.py
new file mode 100644
index 0000000000..5f0232f252
--- /dev/null
+++ b/pyrogram/methods/auth/send_code.py
@@ -0,0 +1,74 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import logging
+
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.errors import PhoneMigrate, NetworkMigrate
+from pyrogram.scaffold import Scaffold
+from pyrogram.session import Session, Auth
+
+log = logging.getLogger(__name__)
+
+
+class SendCode(Scaffold):
+ async def send_code(self, phone_number: str) -> "types.SentCode":
+ """Send the confirmation code to the given phone number.
+
+ Parameters:
+ phone_number (``str``):
+ Phone number in international format (includes the country prefix).
+
+ Returns:
+ :obj:`~pyrogram.types.SentCode`: On success, an object containing information on the sent confirmation code
+ is returned.
+
+ Raises:
+ BadRequest: In case the phone number is invalid.
+ """
+ phone_number = phone_number.strip(" +")
+
+ while True:
+ try:
+ r = await self.send(
+ raw.functions.auth.SendCode(
+ phone_number=phone_number,
+ api_id=self.api_id,
+ api_hash=self.api_hash,
+ settings=raw.types.CodeSettings()
+ )
+ )
+ except (PhoneMigrate, NetworkMigrate) as e:
+ await self.session.stop()
+
+ await self.storage.dc_id(e.x)
+ await self.storage.auth_key(
+ await Auth(
+ self, await self.storage.dc_id(),
+ await self.storage.test_mode()
+ ).create()
+ )
+ self.session = Session(
+ self, await self.storage.dc_id(),
+ await self.storage.auth_key(), await self.storage.test_mode()
+ )
+
+ await self.session.start()
+ else:
+ return types.SentCode._parse(r)
diff --git a/pyrogram/crypto/kdf.py b/pyrogram/methods/auth/send_recovery_code.py
similarity index 58%
rename from pyrogram/crypto/kdf.py
rename to pyrogram/methods/auth/send_recovery_code.py
index cb4ee96388..1a128b467d 100644
--- a/pyrogram/crypto/kdf.py
+++ b/pyrogram/methods/auth/send_recovery_code.py
@@ -16,18 +16,24 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from hashlib import sha256
+import logging
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class KDF:
- def __new__(cls, auth_key: bytes, msg_key: bytes, outgoing: bool) -> tuple:
- # https://core.telegram.org/mtproto/description#defining-aes-key-and-initialization-vector
- x = 0 if outgoing else 8
+log = logging.getLogger(__name__)
- sha256_a = sha256(msg_key + auth_key[x: x + 36]).digest()
- sha256_b = sha256(auth_key[x + 40:x + 76] + msg_key).digest() # 76 = 40 + 36
- aes_key = sha256_a[:8] + sha256_b[8:24] + sha256_a[24:32]
- aes_iv = sha256_b[:8] + sha256_a[8:24] + sha256_b[24:32]
+class SendRecoveryCode(Scaffold):
+ async def send_recovery_code(self) -> str:
+ """Send a code to your email to recover your password.
- return aes_key, aes_iv
+ Returns:
+ ``str``: On success, the hidden email pattern is returned and a recovery code is sent to that email.
+
+ Raises:
+ BadRequest: In case no recovery email was set up.
+ """
+ return (await self.send(
+ raw.functions.auth.RequestPasswordRecovery()
+ )).email_pattern
diff --git a/pyrogram/methods/auth/sign_in.py b/pyrogram/methods/auth/sign_in.py
new file mode 100644
index 0000000000..ccd2dabe94
--- /dev/null
+++ b/pyrogram/methods/auth/sign_in.py
@@ -0,0 +1,78 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import logging
+from typing import Union
+
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
+
+log = logging.getLogger(__name__)
+
+
+class SignIn(Scaffold):
+ async def sign_in(
+ self,
+ phone_number: str,
+ phone_code_hash: str,
+ phone_code: str
+ ) -> Union["types.User", "types.TermsOfService", bool]:
+ """Authorize a user in Telegram with a valid confirmation code.
+
+ Parameters:
+ phone_number (``str``):
+ Phone number in international format (includes the country prefix).
+
+ phone_code_hash (``str``):
+ Code identifier taken from the result of :meth:`~pyrogram.Client.send_code`.
+
+ phone_code (``str``):
+ The valid confirmation code you received (either as Telegram message or as SMS in your phone number).
+
+ Returns:
+ :obj:`~pyrogram.types.User` | :obj:`~pyrogram.types.TermsOfService` | bool: On success, in case the
+ authorization completed, the user is returned. In case the phone number needs to be registered first AND the
+ terms of services accepted (with :meth:`~pyrogram.Client.accept_terms_of_service`), an object containing
+ them is returned. In case the phone number needs to be registered, but the terms of services don't need to
+ be accepted, False is returned instead.
+
+ Raises:
+ BadRequest: In case the arguments are invalid.
+ SessionPasswordNeeded: In case a password is needed to sign in.
+ """
+ phone_number = phone_number.strip(" +")
+
+ r = await self.send(
+ raw.functions.auth.SignIn(
+ phone_number=phone_number,
+ phone_code_hash=phone_code_hash,
+ phone_code=phone_code
+ )
+ )
+
+ if isinstance(r, raw.types.auth.AuthorizationSignUpRequired):
+ if r.terms_of_service:
+ return types.TermsOfService._parse(terms_of_service=r.terms_of_service)
+
+ return False
+ else:
+ await self.storage.user_id(r.user.id)
+ await self.storage.is_bot(False)
+
+ return types.User._parse(self, r.user)
diff --git a/pyrogram/methods/auth/sign_in_bot.py b/pyrogram/methods/auth/sign_in_bot.py
new file mode 100644
index 0000000000..c5ada72cdd
--- /dev/null
+++ b/pyrogram/methods/auth/sign_in_bot.py
@@ -0,0 +1,74 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import logging
+
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.errors import UserMigrate
+from pyrogram.scaffold import Scaffold
+from pyrogram.session import Session, Auth
+
+log = logging.getLogger(__name__)
+
+
+class SignInBot(Scaffold):
+ async def sign_in_bot(self, bot_token: str) -> "types.User":
+ """Authorize a bot using its bot token generated by BotFather.
+
+ Parameters:
+ bot_token (``str``):
+ The bot token generated by BotFather
+
+ Returns:
+ :obj:`~pyrogram.types.User`: On success, the bot identity is return in form of a user object.
+
+ Raises:
+ BadRequest: In case the bot token is invalid.
+ """
+ while True:
+ try:
+ r = await self.send(
+ raw.functions.auth.ImportBotAuthorization(
+ flags=0,
+ api_id=self.api_id,
+ api_hash=self.api_hash,
+ bot_auth_token=bot_token
+ )
+ )
+ except UserMigrate as e:
+ await self.session.stop()
+
+ await self.storage.dc_id(e.x)
+ await self.storage.auth_key(
+ await Auth(
+ self, await self.storage.dc_id(),
+ await self.storage.test_mode()
+ ).create()
+ )
+ self.session = Session(
+ self, await self.storage.dc_id(),
+ await self.storage.auth_key(), await self.storage.test_mode()
+ )
+
+ await self.session.start()
+ else:
+ await self.storage.user_id(r.user.id)
+ await self.storage.is_bot(True)
+
+ return types.User._parse(self, r.user)
diff --git a/pyrogram/methods/auth/sign_up.py b/pyrogram/methods/auth/sign_up.py
new file mode 100644
index 0000000000..b8d42916c3
--- /dev/null
+++ b/pyrogram/methods/auth/sign_up.py
@@ -0,0 +1,71 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import logging
+
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
+
+log = logging.getLogger(__name__)
+
+
+class SignUp(Scaffold):
+ async def sign_up(
+ self,
+ phone_number: str,
+ phone_code_hash: str,
+ first_name: str,
+ last_name: str = ""
+ ) -> "types.User":
+ """Register a new user in Telegram.
+
+ Parameters:
+ phone_number (``str``):
+ Phone number in international format (includes the country prefix).
+
+ phone_code_hash (``str``):
+ Code identifier taken from the result of :meth:`~pyrogram.Client.send_code`.
+
+ first_name (``str``):
+ New user first name.
+
+ last_name (``str``, *optional*):
+ New user last name. Defaults to "" (empty string, no last name).
+
+ Returns:
+ :obj:`~pyrogram.types.User`: On success, the new registered user is returned.
+
+ Raises:
+ BadRequest: In case the arguments are invalid.
+ """
+ phone_number = phone_number.strip(" +")
+
+ r = await self.send(
+ raw.functions.auth.SignUp(
+ phone_number=phone_number,
+ first_name=first_name,
+ last_name=last_name,
+ phone_code_hash=phone_code_hash
+ )
+ )
+
+ await self.storage.user_id(r.user.id)
+ await self.storage.is_bot(False)
+
+ return types.User._parse(self, r.user)
diff --git a/pyrogram/methods/auth/terminate.py b/pyrogram/methods/auth/terminate.py
new file mode 100644
index 0000000000..72d8038042
--- /dev/null
+++ b/pyrogram/methods/auth/terminate.py
@@ -0,0 +1,53 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import logging
+
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
+from pyrogram.syncer import Syncer
+
+log = logging.getLogger(__name__)
+
+
+class Terminate(Scaffold):
+ async def terminate(self):
+ """Terminate the client by shutting down workers.
+
+ This method does the opposite of :meth:`~pyrogram.Client.initialize`.
+ It will stop the dispatcher and shut down updates and download workers.
+
+ Raises:
+ ConnectionError: In case you try to terminate a client that is already terminated.
+ """
+ if not self.is_initialized:
+ raise ConnectionError("Client is already terminated")
+
+ if self.takeout_id:
+ await self.send(raw.functions.account.FinishTakeoutSession())
+ log.warning(f"Takeout session {self.takeout_id} finished")
+
+ await Syncer.remove(self)
+ await self.dispatcher.stop()
+
+ for media_session in self.media_sessions.values():
+ await media_session.stop()
+
+ self.media_sessions.clear()
+
+ self.is_initialized = False
diff --git a/pyrogram/client/methods/bots/__init__.py b/pyrogram/methods/bots/__init__.py
similarity index 100%
rename from pyrogram/client/methods/bots/__init__.py
rename to pyrogram/methods/bots/__init__.py
diff --git a/pyrogram/client/methods/bots/answer_callback_query.py b/pyrogram/methods/bots/answer_callback_query.py
similarity index 94%
rename from pyrogram/client/methods/bots/answer_callback_query.py
rename to pyrogram/methods/bots/answer_callback_query.py
index ff9a5b51fa..bbc7c72488 100644
--- a/pyrogram/client/methods/bots/answer_callback_query.py
+++ b/pyrogram/methods/bots/answer_callback_query.py
@@ -16,11 +16,11 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from pyrogram.api import functions
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class AnswerCallbackQuery(BaseClient):
+class AnswerCallbackQuery(Scaffold):
async def answer_callback_query(
self,
callback_query_id: str,
@@ -69,7 +69,7 @@ async def answer_callback_query(
app.answer_callback_query(query_id, text=text, show_alert=True)
"""
return await self.send(
- functions.messages.SetBotCallbackAnswer(
+ raw.functions.messages.SetBotCallbackAnswer(
query_id=int(callback_query_id),
cache_time=cache_time,
alert=show_alert or None,
diff --git a/pyrogram/client/methods/bots/answer_inline_query.py b/pyrogram/methods/bots/answer_inline_query.py
similarity index 88%
rename from pyrogram/client/methods/bots/answer_inline_query.py
rename to pyrogram/methods/bots/answer_inline_query.py
index 69b9184de6..e84491ee3a 100644
--- a/pyrogram/client/methods/bots/answer_inline_query.py
+++ b/pyrogram/methods/bots/answer_inline_query.py
@@ -18,16 +18,16 @@
from typing import List
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient
-from ...types.inline_mode import InlineQueryResult
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class AnswerInlineQuery(BaseClient):
+class AnswerInlineQuery(Scaffold):
async def answer_inline_query(
self,
inline_query_id: str,
- results: List[InlineQueryResult],
+ results: List["types.InlineQueryResult"],
cache_time: int = 300,
is_gallery: bool = False,
is_personal: bool = False,
@@ -43,7 +43,7 @@ async def answer_inline_query(
inline_query_id (``str``):
Unique identifier for the answered query.
- results (List of :obj:`InlineQueryResult`):
+ results (List of :obj:`~pyrogram.types.InlineQueryResult`):
A list of results for the inline query.
cache_time (``int``, *optional*):
@@ -93,20 +93,16 @@ async def answer_inline_query(
"Title",
InputTextMessageContent("Message content"))])
"""
- written_results = [] # Py 3.5 doesn't support await inside comprehensions
-
- for r in results:
- written_results.append(await r.write())
return await self.send(
- functions.messages.SetInlineBotResults(
+ raw.functions.messages.SetInlineBotResults(
query_id=int(inline_query_id),
- results=written_results,
+ results=[await r.write() for r in results],
cache_time=cache_time,
gallery=is_gallery or None,
private=is_personal or None,
next_offset=next_offset or None,
- switch_pm=types.InlineBotSwitchPM(
+ switch_pm=raw.types.InlineBotSwitchPM(
text=switch_pm_text,
start_param=switch_pm_parameter
) if switch_pm_text else None
diff --git a/pyrogram/client/methods/bots/get_game_high_scores.py b/pyrogram/methods/bots/get_game_high_scores.py
similarity index 85%
rename from pyrogram/client/methods/bots/get_game_high_scores.py
rename to pyrogram/methods/bots/get_game_high_scores.py
index c40350ad58..af2c6d7cbc 100644
--- a/pyrogram/client/methods/bots/get_game_high_scores.py
+++ b/pyrogram/methods/bots/get_game_high_scores.py
@@ -18,18 +18,18 @@
from typing import Union, List
-import pyrogram
-from pyrogram.api import functions
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class GetGameHighScores(BaseClient):
+class GetGameHighScores(Scaffold):
async def get_game_high_scores(
self,
user_id: Union[int, str],
chat_id: Union[int, str],
message_id: int = None
- ) -> List["pyrogram.GameHighScore"]:
+ ) -> List["types.GameHighScore"]:
"""Get data for high score tables.
Parameters:
@@ -49,7 +49,7 @@ async def get_game_high_scores(
Required if inline_message_id is not specified.
Returns:
- List of :obj:`GameHighScore`: On success.
+ List of :obj:`~pyrogram.types.GameHighScore`: On success.
Example:
.. code-block:: python
@@ -60,11 +60,11 @@ async def get_game_high_scores(
# TODO: inline_message_id
r = await self.send(
- functions.messages.GetGameHighScores(
+ raw.functions.messages.GetGameHighScores(
peer=await self.resolve_peer(chat_id),
id=message_id,
user_id=await self.resolve_peer(user_id)
)
)
- return pyrogram.List(pyrogram.GameHighScore._parse(self, score, r.users) for score in r.scores)
+ return types.List(types.GameHighScore._parse(self, score, r.users) for score in r.scores)
diff --git a/pyrogram/client/methods/bots/get_inline_bot_results.py b/pyrogram/methods/bots/get_inline_bot_results.py
similarity index 88%
rename from pyrogram/client/methods/bots/get_inline_bot_results.py
rename to pyrogram/methods/bots/get_inline_bot_results.py
index 366594fcb0..e507e313ac 100644
--- a/pyrogram/client/methods/bots/get_inline_bot_results.py
+++ b/pyrogram/methods/bots/get_inline_bot_results.py
@@ -18,12 +18,12 @@
from typing import Union
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
from pyrogram.errors import UnknownError
+from pyrogram.scaffold import Scaffold
-class GetInlineBotResults(BaseClient):
+class GetInlineBotResults(Scaffold):
async def get_inline_bot_results(
self,
bot: Union[int, str],
@@ -33,7 +33,7 @@ async def get_inline_bot_results(
longitude: float = None
):
"""Get bot results via inline queries.
- You can then send a result using :obj:`send_inline_bot_result `
+ You can then send a result using :meth:`~pyrogram.Client.send_inline_bot_result`
Parameters:
bot (``int`` | ``str``):
@@ -71,12 +71,12 @@ async def get_inline_bot_results(
try:
return await self.send(
- functions.messages.GetInlineBotResults(
+ raw.functions.messages.GetInlineBotResults(
bot=await self.resolve_peer(bot),
- peer=types.InputPeerSelf(),
+ peer=raw.types.InputPeerSelf(),
query=query,
offset=offset,
- geo_point=types.InputGeoPoint(
+ geo_point=raw.types.InputGeoPoint(
lat=latitude,
long=longitude
) if (latitude is not None and longitude is not None) else None
diff --git a/pyrogram/client/methods/bots/request_callback_answer.py b/pyrogram/methods/bots/request_callback_answer.py
similarity index 93%
rename from pyrogram/client/methods/bots/request_callback_answer.py
rename to pyrogram/methods/bots/request_callback_answer.py
index 97eacf0dbb..c42306ee1e 100644
--- a/pyrogram/client/methods/bots/request_callback_answer.py
+++ b/pyrogram/methods/bots/request_callback_answer.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class RequestCallbackAnswer(BaseClient):
+class RequestCallbackAnswer(Scaffold):
async def request_callback_answer(
self,
chat_id: Union[int, str],
@@ -65,7 +65,7 @@ async def request_callback_answer(
data = bytes(callback_data, "utf-8") if isinstance(callback_data, str) else callback_data
return await self.send(
- functions.messages.GetBotCallbackAnswer(
+ raw.functions.messages.GetBotCallbackAnswer(
peer=await self.resolve_peer(chat_id),
msg_id=message_id,
data=data
diff --git a/pyrogram/client/methods/bots/send_game.py b/pyrogram/methods/bots/send_game.py
similarity index 77%
rename from pyrogram/client/methods/bots/send_game.py
rename to pyrogram/methods/bots/send_game.py
index 4b4d2c02d2..3913946ae8 100644
--- a/pyrogram/client/methods/bots/send_game.py
+++ b/pyrogram/methods/bots/send_game.py
@@ -18,12 +18,12 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class SendGame(BaseClient):
+class SendGame(Scaffold):
async def send_game(
self,
chat_id: Union[int, str],
@@ -31,12 +31,12 @@ async def send_game(
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None
- ) -> "pyrogram.Message":
+ ) -> "types.Message":
"""Send a game.
Parameters:
@@ -55,12 +55,12 @@ async def send_game(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An object for an inline keyboard. If empty, one ‘Play game_title’ button will be shown automatically.
If not empty, the first button must launch the game.
Returns:
- :obj:`Message`: On success, the sent game message is returned.
+ :obj:`~pyrogram.types.Message`: On success, the sent game message is returned.
Example:
.. code-block:: python
@@ -68,11 +68,11 @@ async def send_game(
app.send_game(chat_id, "gamename")
"""
r = await self.send(
- functions.messages.SendMedia(
+ raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
- media=types.InputMediaGame(
- id=types.InputGameShortName(
- bot_id=types.InputUserSelf(),
+ media=raw.types.InputMediaGame(
+ id=raw.types.InputGameShortName(
+ bot_id=raw.types.InputUserSelf(),
short_name=game_short_name
),
),
@@ -85,8 +85,8 @@ async def send_game(
)
for i in r.updates:
- if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage, raw.types.UpdateNewChannelMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/bots/send_inline_bot_result.py b/pyrogram/methods/bots/send_inline_bot_result.py
similarity index 87%
rename from pyrogram/client/methods/bots/send_inline_bot_result.py
rename to pyrogram/methods/bots/send_inline_bot_result.py
index 8cc5bf115a..7d396a609f 100644
--- a/pyrogram/client/methods/bots/send_inline_bot_result.py
+++ b/pyrogram/methods/bots/send_inline_bot_result.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class SendInlineBotResult(BaseClient):
+class SendInlineBotResult(Scaffold):
async def send_inline_bot_result(
self,
chat_id: Union[int, str],
@@ -33,7 +33,7 @@ async def send_inline_bot_result(
hide_via: bool = None
):
"""Send an inline bot result.
- Bot results can be retrieved using :obj:`get_inline_bot_results `
+ Bot results can be retrieved using :meth:`~pyrogram.Client.get_inline_bot_results`
Parameters:
chat_id (``int`` | ``str``):
@@ -58,7 +58,7 @@ async def send_inline_bot_result(
Sends the message with *via @bot* hidden.
Returns:
- :obj:`Message`: On success, the sent inline result message is returned.
+ :obj:`~pyrogram.types.Message`: On success, the sent inline result message is returned.
Example:
.. code-block:: python
@@ -66,7 +66,7 @@ async def send_inline_bot_result(
app.send_inline_bot_result(chat_id, query_id, result_id)
"""
return await self.send(
- functions.messages.SendInlineBotResult(
+ raw.functions.messages.SendInlineBotResult(
peer=await self.resolve_peer(chat_id),
query_id=query_id,
id=result_id,
diff --git a/pyrogram/client/methods/bots/set_game_score.py b/pyrogram/methods/bots/set_game_score.py
similarity index 85%
rename from pyrogram/client/methods/bots/set_game_score.py
rename to pyrogram/methods/bots/set_game_score.py
index 3912d29492..b9c2fe0ebb 100644
--- a/pyrogram/client/methods/bots/set_game_score.py
+++ b/pyrogram/methods/bots/set_game_score.py
@@ -18,12 +18,12 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class SetGameScore(BaseClient):
+class SetGameScore(Scaffold):
async def set_game_score(
self,
user_id: Union[int, str],
@@ -32,7 +32,7 @@ async def set_game_score(
disable_edit_message: bool = None,
chat_id: Union[int, str] = None,
message_id: int = None
- ) -> Union["pyrogram.Message", bool]:
+ ) -> Union["types.Message", bool]:
# inline_message_id: str = None): TODO Add inline_message_id
"""Set the score of the specified user in a game.
@@ -63,8 +63,8 @@ async def set_game_score(
Required if inline_message_id is not specified.
Returns:
- :obj:`Message` | ``bool``: On success, if the message was sent by the bot, the edited message is returned,
- True otherwise.
+ :obj:`~pyrogram.types.Message` | ``bool``: On success, if the message was sent by the bot, the edited
+ message is returned, True otherwise.
Example:
.. code-block:: python
@@ -76,7 +76,7 @@ async def set_game_score(
app.set_game_score(user_id, 25, force=True)
"""
r = await self.send(
- functions.messages.SetGameScore(
+ raw.functions.messages.SetGameScore(
peer=await self.resolve_peer(chat_id),
score=score,
id=message_id,
@@ -87,8 +87,9 @@ async def set_game_score(
)
for i in r.updates:
- if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateEditMessage,
+ raw.types.UpdateEditChannelMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/chats/__init__.py b/pyrogram/methods/chats/__init__.py
similarity index 100%
rename from pyrogram/client/methods/chats/__init__.py
rename to pyrogram/methods/chats/__init__.py
diff --git a/pyrogram/client/methods/chats/add_chat_members.py b/pyrogram/methods/chats/add_chat_members.py
similarity index 92%
rename from pyrogram/client/methods/chats/add_chat_members.py
rename to pyrogram/methods/chats/add_chat_members.py
index 9a5f18eac8..6164f411bb 100644
--- a/pyrogram/client/methods/chats/add_chat_members.py
+++ b/pyrogram/methods/chats/add_chat_members.py
@@ -18,11 +18,11 @@
from typing import Union, List
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class AddChatMembers(BaseClient):
+class AddChatMembers(Scaffold):
async def add_chat_members(
self,
chat_id: Union[int, str],
@@ -65,10 +65,10 @@ async def add_chat_members(
if not isinstance(user_ids, list):
user_ids = [user_ids]
- if isinstance(peer, types.InputPeerChat):
+ if isinstance(peer, raw.types.InputPeerChat):
for user_id in user_ids:
await self.send(
- functions.messages.AddChatUser(
+ raw.functions.messages.AddChatUser(
chat_id=peer.chat_id,
user_id=await self.resolve_peer(user_id),
fwd_limit=forward_limit
@@ -76,7 +76,7 @@ async def add_chat_members(
)
else:
await self.send(
- functions.channels.InviteToChannel(
+ raw.functions.channels.InviteToChannel(
channel=peer,
users=[
await self.resolve_peer(user_id)
diff --git a/pyrogram/client/methods/chats/archive_chats.py b/pyrogram/methods/chats/archive_chats.py
similarity index 91%
rename from pyrogram/client/methods/chats/archive_chats.py
rename to pyrogram/methods/chats/archive_chats.py
index 54c452a2df..144a22718c 100644
--- a/pyrogram/client/methods/chats/archive_chats.py
+++ b/pyrogram/methods/chats/archive_chats.py
@@ -18,11 +18,11 @@
from typing import Union, List
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class ArchiveChats(BaseClient):
+class ArchiveChats(Scaffold):
async def archive_chats(
self,
chat_ids: Union[int, str, List[Union[int, str]]],
@@ -54,14 +54,14 @@ async def archive_chats(
for chat in chat_ids:
folder_peers.append(
- types.InputFolderPeer(
+ raw.types.InputFolderPeer(
peer=await self.resolve_peer(chat),
folder_id=1
)
)
await self.send(
- functions.folders.EditPeerFolders(
+ raw.functions.folders.EditPeerFolders(
folder_peers=folder_peers
)
)
diff --git a/pyrogram/client/methods/chats/create_channel.py b/pyrogram/methods/chats/create_channel.py
similarity index 81%
rename from pyrogram/client/methods/chats/create_channel.py
rename to pyrogram/methods/chats/create_channel.py
index 7885ed3ea9..6c2a597218 100644
--- a/pyrogram/client/methods/chats/create_channel.py
+++ b/pyrogram/methods/chats/create_channel.py
@@ -16,17 +16,17 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-import pyrogram
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class CreateChannel(BaseClient):
+class CreateChannel(Scaffold):
async def create_channel(
self,
title: str,
description: str = ""
- ) -> "pyrogram.Chat":
+ ) -> "types.Chat":
"""Create a new broadcast channel.
Parameters:
@@ -37,7 +37,7 @@ async def create_channel(
The channel description.
Returns:
- :obj:`Chat`: On success, a chat object is returned.
+ :obj:`~pyrogram.types.Chat`: On success, a chat object is returned.
Example:
.. code-block:: python
@@ -45,11 +45,11 @@ async def create_channel(
app.create_channel("Channel Title", "Channel Description")
"""
r = await self.send(
- functions.channels.CreateChannel(
+ raw.functions.channels.CreateChannel(
title=title,
about=description,
broadcast=True
)
)
- return pyrogram.Chat._parse_chat(self, r.chats[0])
+ return types.Chat._parse_chat(self, r.chats[0])
diff --git a/pyrogram/client/methods/chats/create_group.py b/pyrogram/methods/chats/create_group.py
similarity index 85%
rename from pyrogram/client/methods/chats/create_group.py
rename to pyrogram/methods/chats/create_group.py
index 631aa75a71..7c68f90c05 100644
--- a/pyrogram/client/methods/chats/create_group.py
+++ b/pyrogram/methods/chats/create_group.py
@@ -18,17 +18,17 @@
from typing import Union, List
-import pyrogram
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class CreateGroup(BaseClient):
+class CreateGroup(Scaffold):
async def create_group(
self,
title: str,
users: Union[Union[int, str], List[Union[int, str]]]
- ) -> "pyrogram.Chat":
+ ) -> "types.Chat":
"""Create a new basic group.
.. note::
@@ -45,7 +45,7 @@ async def create_group(
Multiple users can be invited by passing a list of IDs, usernames or phone numbers.
Returns:
- :obj:`Chat`: On success, a chat object is returned.
+ :obj:`~pyrogram.types.Chat`: On success, a chat object is returned.
Example:
.. code-block:: python
@@ -56,10 +56,10 @@ async def create_group(
users = [users]
r = await self.send(
- functions.messages.CreateChat(
+ raw.functions.messages.CreateChat(
title=title,
users=[await self.resolve_peer(u) for u in users]
)
)
- return pyrogram.Chat._parse_chat(self, r.chats[0])
+ return types.Chat._parse_chat(self, r.chats[0])
diff --git a/pyrogram/client/methods/chats/create_supergroup.py b/pyrogram/methods/chats/create_supergroup.py
similarity index 82%
rename from pyrogram/client/methods/chats/create_supergroup.py
rename to pyrogram/methods/chats/create_supergroup.py
index 1310d65ec2..07b5adca21 100644
--- a/pyrogram/client/methods/chats/create_supergroup.py
+++ b/pyrogram/methods/chats/create_supergroup.py
@@ -16,17 +16,17 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-import pyrogram
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class CreateSupergroup(BaseClient):
+class CreateSupergroup(Scaffold):
async def create_supergroup(
self,
title: str,
description: str = ""
- ) -> "pyrogram.Chat":
+ ) -> "types.Chat":
"""Create a new supergroup.
.. note::
@@ -41,7 +41,7 @@ async def create_supergroup(
The supergroup description.
Returns:
- :obj:`Chat`: On success, a chat object is returned.
+ :obj:`~pyrogram.types.Chat`: On success, a chat object is returned.
Example:
.. code-block:: python
@@ -49,11 +49,11 @@ async def create_supergroup(
app.create_supergroup("Supergroup Title", "Supergroup Description")
"""
r = await self.send(
- functions.channels.CreateChannel(
+ raw.functions.channels.CreateChannel(
title=title,
about=description,
megagroup=True
)
)
- return pyrogram.Chat._parse_chat(self, r.chats[0])
+ return types.Chat._parse_chat(self, r.chats[0])
diff --git a/pyrogram/client/methods/chats/delete_channel.py b/pyrogram/methods/chats/delete_channel.py
similarity index 90%
rename from pyrogram/client/methods/chats/delete_channel.py
rename to pyrogram/methods/chats/delete_channel.py
index ff62e8d62f..7d884bb726 100644
--- a/pyrogram/client/methods/chats/delete_channel.py
+++ b/pyrogram/methods/chats/delete_channel.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class DeleteChannel(BaseClient):
+class DeleteChannel(Scaffold):
async def delete_channel(self, chat_id: Union[int, str]) -> bool:
"""Delete a channel.
@@ -39,7 +39,7 @@ async def delete_channel(self, chat_id: Union[int, str]) -> bool:
app.delete_channel(channel_id)
"""
await self.send(
- functions.channels.DeleteChannel(
+ raw.functions.channels.DeleteChannel(
channel=await self.resolve_peer(chat_id)
)
)
diff --git a/pyrogram/client/methods/chats/delete_chat_photo.py b/pyrogram/methods/chats/delete_chat_photo.py
similarity index 77%
rename from pyrogram/client/methods/chats/delete_chat_photo.py
rename to pyrogram/methods/chats/delete_chat_photo.py
index cc2e06dd37..de9f707c01 100644
--- a/pyrogram/client/methods/chats/delete_chat_photo.py
+++ b/pyrogram/methods/chats/delete_chat_photo.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class DeleteChatPhoto(BaseClient):
+class DeleteChatPhoto(Scaffold):
async def delete_chat_photo(
self,
chat_id: Union[int, str]
@@ -48,21 +48,21 @@ async def delete_chat_photo(
"""
peer = await self.resolve_peer(chat_id)
- if isinstance(peer, types.InputPeerChat):
+ if isinstance(peer, raw.types.InputPeerChat):
await self.send(
- functions.messages.EditChatPhoto(
+ raw.functions.messages.EditChatPhoto(
chat_id=peer.chat_id,
- photo=types.InputChatPhotoEmpty()
+ photo=raw.types.InputChatPhotoEmpty()
)
)
- elif isinstance(peer, types.InputPeerChannel):
+ elif isinstance(peer, raw.types.InputPeerChannel):
await self.send(
- functions.channels.EditPhoto(
+ raw.functions.channels.EditPhoto(
channel=peer,
- photo=types.InputChatPhotoEmpty()
+ photo=raw.types.InputChatPhotoEmpty()
)
)
else:
- raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
+ raise ValueError(f'The chat_id "{chat_id}" belongs to a user')
return True
diff --git a/pyrogram/client/methods/chats/delete_supergroup.py b/pyrogram/methods/chats/delete_supergroup.py
similarity index 90%
rename from pyrogram/client/methods/chats/delete_supergroup.py
rename to pyrogram/methods/chats/delete_supergroup.py
index f24c55a131..d4abba8c43 100644
--- a/pyrogram/client/methods/chats/delete_supergroup.py
+++ b/pyrogram/methods/chats/delete_supergroup.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class DeleteSupergroup(BaseClient):
+class DeleteSupergroup(Scaffold):
async def delete_supergroup(self, chat_id: Union[int, str]) -> bool:
"""Delete a supergroup.
@@ -39,7 +39,7 @@ async def delete_supergroup(self, chat_id: Union[int, str]) -> bool:
app.delete_supergroup(supergroup_id)
"""
await self.send(
- functions.channels.DeleteChannel(
+ raw.functions.channels.DeleteChannel(
channel=await self.resolve_peer(chat_id)
)
)
diff --git a/pyrogram/client/methods/chats/delete_user_history.py b/pyrogram/methods/chats/delete_user_history.py
similarity index 82%
rename from pyrogram/client/methods/chats/delete_user_history.py
rename to pyrogram/methods/chats/delete_user_history.py
index a35bf10c93..d2c1797905 100644
--- a/pyrogram/client/methods/chats/delete_user_history.py
+++ b/pyrogram/methods/chats/delete_user_history.py
@@ -18,12 +18,12 @@
from typing import Union
-from pyrogram.api import functions
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class DeleteUserHistory(BaseClient):
- def delete_user_history(
+class DeleteUserHistory(Scaffold):
+ async def delete_user_history(
self,
chat_id: Union[int, str],
user_id: Union[int, str],
@@ -41,12 +41,12 @@ def delete_user_history(
``bool``: True on success, False otherwise.
"""
- r = self.send(
- functions.channels.DeleteUserHistory(
- channel=self.resolve_peer(chat_id),
- user_id=self.resolve_peer(user_id)
- )
+ r = await self.send(
+ raw.functions.channels.DeleteUserHistory(
+ channel=await self.resolve_peer(chat_id),
+ user_id=await self.resolve_peer(user_id)
)
+ )
# Deleting messages you don't have right onto won't raise any error.
# Check for pts_count, which is 0 in case deletes fail.
diff --git a/pyrogram/client/methods/chats/export_chat_invite_link.py b/pyrogram/methods/chats/export_chat_invite_link.py
similarity index 80%
rename from pyrogram/client/methods/chats/export_chat_invite_link.py
rename to pyrogram/methods/chats/export_chat_invite_link.py
index ac0d3b9102..7b3121cae3 100644
--- a/pyrogram/client/methods/chats/export_chat_invite_link.py
+++ b/pyrogram/methods/chats/export_chat_invite_link.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class ExportChatInviteLink(BaseClient):
+class ExportChatInviteLink(Scaffold):
async def export_chat_invite_link(
self,
chat_id: Union[int, str]
@@ -35,8 +35,9 @@ async def export_chat_invite_link(
Each administrator in a chat generates their own invite links. Bots can't use invite links generated by
other administrators. If you want your bot to work with invite links, it will need to generate its own link
- using this method – after this the link will become available to the bot via the :meth:`~Client.get_chat`
- method. If your bot needs to generate a new invite link replacing its previous one, use this method again.
+ using this method – after this the link will become available to the bot via the
+ :meth:`~pyrogram.Client.get_chat` method. If your bot needs to generate a new invite link replacing its
+ previous one, use this method again.
Parameters:
chat_id (``int`` | ``str``):
@@ -57,11 +58,11 @@ async def export_chat_invite_link(
"""
peer = await self.resolve_peer(chat_id)
- if isinstance(peer, (types.InputPeerChat, types.InputPeerChannel)):
+ if isinstance(peer, (raw.types.InputPeerChat, raw.types.InputPeerChannel)):
return (await self.send(
- functions.messages.ExportChatInvite(
+ raw.functions.messages.ExportChatInvite(
peer=peer
)
)).link
else:
- raise ValueError('The chat_id "{}" belongs to a user'.format(chat_id))
+ raise ValueError(f'The chat_id "{chat_id}" belongs to a user')
diff --git a/pyrogram/client/methods/chats/get_chat.py b/pyrogram/methods/chats/get_chat.py
similarity index 67%
rename from pyrogram/client/methods/chats/get_chat.py
rename to pyrogram/methods/chats/get_chat.py
index 3c94507073..4e9a5428fa 100644
--- a/pyrogram/client/methods/chats/get_chat.py
+++ b/pyrogram/methods/chats/get_chat.py
@@ -18,16 +18,17 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from ...ext import BaseClient, utils
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
-class GetChat(BaseClient):
+class GetChat(Scaffold):
async def get_chat(
self,
chat_id: Union[int, str]
- ) -> Union["pyrogram.Chat", "pyrogram.ChatPreview"]:
+ ) -> Union["types.Chat", "types.ChatPreview"]:
"""Get up to date information about a chat.
Information include current name of the user for one-on-one conversations, current username of a user, group or
@@ -40,7 +41,7 @@ async def get_chat(
of the target channel/supergroup (in the format @username).
Returns:
- :obj:`Chat` | :obj:`ChatPreview`: On success, if you've already joined the chat, a chat object is returned,
+ :obj:`~pyrogram.types.Chat` | :obj:`~pyrogram.types.ChatPreview`: On success, if you've already joined the chat, a chat object is returned,
otherwise, a chat preview object is returned.
Raises:
@@ -56,29 +57,29 @@ async def get_chat(
if match:
r = await self.send(
- functions.messages.CheckChatInvite(
+ raw.functions.messages.CheckChatInvite(
hash=match.group(1)
)
)
- if isinstance(r, types.ChatInvite):
- return pyrogram.ChatPreview._parse(self, r)
+ if isinstance(r, raw.types.ChatInvite):
+ return types.ChatPreview._parse(self, r)
- self.fetch_peers([r.chat])
+ await self.fetch_peers([r.chat])
if isinstance(r.chat, types.Chat):
chat_id = -r.chat.id
- if isinstance(r.chat, types.Channel):
+ if isinstance(r.chat, raw.types.Channel):
chat_id = utils.get_channel_id(r.chat.id)
peer = await self.resolve_peer(chat_id)
- if isinstance(peer, types.InputPeerChannel):
- r = await self.send(functions.channels.GetFullChannel(channel=peer))
- elif isinstance(peer, (types.InputPeerUser, types.InputPeerSelf)):
- r = await self.send(functions.users.GetFullUser(id=peer))
+ if isinstance(peer, raw.types.InputPeerChannel):
+ r = await self.send(raw.functions.channels.GetFullChannel(channel=peer))
+ elif isinstance(peer, (raw.types.InputPeerUser, raw.types.InputPeerSelf)):
+ r = await self.send(raw.functions.users.GetFullUser(id=peer))
else:
- r = await self.send(functions.messages.GetFullChat(chat_id=peer.chat_id))
+ r = await self.send(raw.functions.messages.GetFullChat(chat_id=peer.chat_id))
- return await pyrogram.Chat._parse_full(self, r)
+ return await types.Chat._parse_full(self, r)
diff --git a/pyrogram/client/methods/chats/get_chat_member.py b/pyrogram/methods/chats/get_chat_member.py
similarity index 77%
rename from pyrogram/client/methods/chats/get_chat_member.py
rename to pyrogram/methods/chats/get_chat_member.py
index b77bca8553..c4555c2bbd 100644
--- a/pyrogram/client/methods/chats/get_chat_member.py
+++ b/pyrogram/methods/chats/get_chat_member.py
@@ -18,19 +18,18 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
+from pyrogram import raw
+from pyrogram import types
from pyrogram.errors import UserNotParticipant
+from pyrogram.scaffold import Scaffold
-from ...ext import BaseClient
-
-class GetChatMember(BaseClient):
+class GetChatMember(Scaffold):
async def get_chat_member(
self,
chat_id: Union[int, str],
user_id: Union[int, str]
- ) -> "pyrogram.ChatMember":
+ ) -> "types.ChatMember":
"""Get information about one member of a chat.
Parameters:
@@ -43,7 +42,7 @@ async def get_chat_member(
For a contact that exists in your Telegram address book you can use his phone number (str).
Returns:
- :obj:`ChatMember`: On success, a chat member is returned.
+ :obj:`~pyrogram.types.ChatMember`: On success, a chat member is returned.
Example:
.. code-block:: python
@@ -54,9 +53,9 @@ async def get_chat_member(
chat = await self.resolve_peer(chat_id)
user = await self.resolve_peer(user_id)
- if isinstance(chat, types.InputPeerChat):
+ if isinstance(chat, raw.types.InputPeerChat):
r = await self.send(
- functions.messages.GetFullChat(
+ raw.functions.messages.GetFullChat(
chat_id=chat.chat_id
)
)
@@ -65,9 +64,9 @@ async def get_chat_member(
users = {i.id: i for i in r.users}
for member in members:
- member = pyrogram.ChatMember._parse(self, member, users)
+ member = types.ChatMember._parse(self, member, users)
- if isinstance(user, types.InputPeerSelf):
+ if isinstance(user, raw.types.InputPeerSelf):
if member.user.is_self:
return member
else:
@@ -75,9 +74,9 @@ async def get_chat_member(
return member
else:
raise UserNotParticipant
- elif isinstance(chat, types.InputPeerChannel):
+ elif isinstance(chat, raw.types.InputPeerChannel):
r = await self.send(
- functions.channels.GetParticipant(
+ raw.functions.channels.GetParticipant(
channel=chat,
user_id=user
)
@@ -85,6 +84,6 @@ async def get_chat_member(
users = {i.id: i for i in r.users}
- return pyrogram.ChatMember._parse(self, r.participant, users)
+ return types.ChatMember._parse(self, r.participant, users)
else:
- raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
+ raise ValueError(f'The chat_id "{chat_id}" belongs to a user')
diff --git a/pyrogram/client/methods/chats/get_chat_members.py b/pyrogram/methods/chats/get_chat_members.py
similarity index 79%
rename from pyrogram/client/methods/chats/get_chat_members.py
rename to pyrogram/methods/chats/get_chat_members.py
index 4f7613ce35..e5a25f4191 100644
--- a/pyrogram/client/methods/chats/get_chat_members.py
+++ b/pyrogram/methods/chats/get_chat_members.py
@@ -19,9 +19,9 @@
import logging
from typing import Union, List
-import pyrogram
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
log = logging.getLogger(__name__)
@@ -35,7 +35,7 @@ class Filters:
ADMINISTRATORS = "administrators"
-class GetChatMembers(BaseClient):
+class GetChatMembers(Scaffold):
async def get_chat_members(
self,
chat_id: Union[int, str],
@@ -43,13 +43,13 @@ async def get_chat_members(
limit: int = 200,
query: str = "",
filter: str = Filters.ALL
- ) -> List["pyrogram.ChatMember"]:
+ ) -> List["types.ChatMember"]:
"""Get a chunk of the members list of a chat.
You can get up to 200 chat members at once.
A chat can be either a basic group, a supergroup or a channel.
You must be admin to retrieve the members list of a channel (also known as "subscribers").
- For a more convenient way of getting chat members see :meth:`~Client.iter_chat_members`.
+ For a more convenient way of getting chat members see :meth:`~pyrogram.Client.iter_chat_members`.
Parameters:
chat_id (``int`` | ``str``):
@@ -86,7 +86,7 @@ async def get_chat_members(
.. [2] A query string is applicable only for *"all"*, *"kicked"* and *"restricted"* filters only.
Returns:
- List of :obj:`ChatMember`: On success, a list of chat members is returned.
+ List of :obj:`~pyrogram.types.ChatMember`: On success, a list of chat members is returned.
Raises:
ValueError: In case you used an invalid filter or a chat id that belongs to a user.
@@ -105,9 +105,9 @@ async def get_chat_members(
"""
peer = await self.resolve_peer(chat_id)
- if isinstance(peer, types.InputPeerChat):
+ if isinstance(peer, raw.types.InputPeerChat):
r = await self.send(
- functions.messages.GetFullChat(
+ raw.functions.messages.GetFullChat(
chat_id=peer.chat_id
)
)
@@ -115,27 +115,27 @@ async def get_chat_members(
members = r.full_chat.participants.participants
users = {i.id: i for i in r.users}
- return pyrogram.List(pyrogram.ChatMember._parse(self, member, users) for member in members)
- elif isinstance(peer, types.InputPeerChannel):
+ return types.List(types.ChatMember._parse(self, member, users) for member in members)
+ elif isinstance(peer, raw.types.InputPeerChannel):
filter = filter.lower()
if filter == Filters.ALL:
- filter = types.ChannelParticipantsSearch(q=query)
+ filter = raw.types.ChannelParticipantsSearch(q=query)
elif filter == Filters.KICKED:
- filter = types.ChannelParticipantsKicked(q=query)
+ filter = raw.types.ChannelParticipantsKicked(q=query)
elif filter == Filters.RESTRICTED:
- filter = types.ChannelParticipantsBanned(q=query)
+ filter = raw.types.ChannelParticipantsBanned(q=query)
elif filter == Filters.BOTS:
- filter = types.ChannelParticipantsBots()
+ filter = raw.types.ChannelParticipantsBots()
elif filter == Filters.RECENT:
- filter = types.ChannelParticipantsRecent()
+ filter = raw.types.ChannelParticipantsRecent()
elif filter == Filters.ADMINISTRATORS:
- filter = types.ChannelParticipantsAdmins()
+ filter = raw.types.ChannelParticipantsAdmins()
else:
- raise ValueError("Invalid filter \"{}\"".format(filter))
+ raise ValueError(f'Invalid filter "{filter}"')
r = await self.send(
- functions.channels.GetParticipants(
+ raw.functions.channels.GetParticipants(
channel=peer,
filter=filter,
offset=offset,
@@ -147,6 +147,6 @@ async def get_chat_members(
members = r.participants
users = {i.id: i for i in r.users}
- return pyrogram.List(pyrogram.ChatMember._parse(self, member, users) for member in members)
+ return types.List(types.ChatMember._parse(self, member, users) for member in members)
else:
- raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
+ raise ValueError(f'The chat_id "{chat_id}" belongs to a user')
diff --git a/pyrogram/client/methods/chats/get_chat_members_count.py b/pyrogram/methods/chats/get_chat_members_count.py
similarity index 82%
rename from pyrogram/client/methods/chats/get_chat_members_count.py
rename to pyrogram/methods/chats/get_chat_members_count.py
index 88c126690f..8bb1b7bec7 100644
--- a/pyrogram/client/methods/chats/get_chat_members_count.py
+++ b/pyrogram/methods/chats/get_chat_members_count.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class GetChatMembersCount(BaseClient):
+class GetChatMembersCount(Scaffold):
async def get_chat_members_count(
self,
chat_id: Union[int, str]
@@ -47,21 +47,21 @@ async def get_chat_members_count(
"""
peer = await self.resolve_peer(chat_id)
- if isinstance(peer, types.InputPeerChat):
+ if isinstance(peer, raw.types.InputPeerChat):
r = await self.send(
- functions.messages.GetChats(
+ raw.functions.messages.GetChats(
id=[peer.chat_id]
)
)
return r.chats[0].participants_count
- elif isinstance(peer, types.InputPeerChannel):
+ elif isinstance(peer, raw.types.InputPeerChannel):
r = await self.send(
- functions.channels.GetFullChannel(
+ raw.functions.channels.GetFullChannel(
channel=peer
)
)
return r.full_chat.participants_count
else:
- raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
+ raise ValueError(f'The chat_id "{chat_id}" belongs to a user')
diff --git a/pyrogram/client/methods/chats/get_dialogs.py b/pyrogram/methods/chats/get_dialogs.py
similarity index 75%
rename from pyrogram/client/methods/chats/get_dialogs.py
rename to pyrogram/methods/chats/get_dialogs.py
index d52bd2cedd..8549fb139f 100644
--- a/pyrogram/client/methods/chats/get_dialogs.py
+++ b/pyrogram/methods/chats/get_dialogs.py
@@ -19,28 +19,29 @@
import logging
from typing import List
-import pyrogram
-from pyrogram.api import functions, types
-from ...ext import BaseClient, utils
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
log = logging.getLogger(__name__)
-class GetDialogs(BaseClient):
+class GetDialogs(Scaffold):
async def get_dialogs(
self,
offset_date: int = 0,
limit: int = 100,
pinned_only: bool = False
- ) -> List["pyrogram.Dialog"]:
+ ) -> List["types.Dialog"]:
"""Get a chunk of the user's dialogs.
You can get up to 100 dialogs at once.
- For a more convenient way of getting a user's dialogs see :meth:`~Client.iter_dialogs`.
+ For a more convenient way of getting a user's dialogs see :meth:`~pyrogram.Client.iter_dialogs`.
Parameters:
offset_date (``int``):
- The offset date in Unix time taken from the top message of a :obj:`Dialog`.
+ The offset date in Unix time taken from the top message of a :obj:`~pyrogram.types.Dialog`.
Defaults to 0. Valid for non-pinned dialogs only.
limit (``str``, *optional*):
@@ -52,7 +53,7 @@ async def get_dialogs(
Defaults to False.
Returns:
- List of :obj:`Dialog`: On success, a list of dialogs is returned.
+ List of :obj:`~pyrogram.types.Dialog`: On success, a list of dialogs is returned.
Example:
.. code-block:: python
@@ -65,13 +66,13 @@ async def get_dialogs(
"""
if pinned_only:
- r = await self.send(functions.messages.GetPinnedDialogs(folder_id=0))
+ r = await self.send(raw.functions.messages.GetPinnedDialogs(folder_id=0))
else:
r = await self.send(
- functions.messages.GetDialogs(
+ raw.functions.messages.GetDialogs(
offset_date=offset_date,
offset_id=0,
- offset_peer=types.InputPeerEmpty(),
+ offset_peer=raw.types.InputPeerEmpty(),
limit=limit,
hash=0,
exclude_pinned=True
@@ -86,7 +87,7 @@ async def get_dialogs(
for message in r.messages:
to_id = message.to_id
- if isinstance(to_id, types.PeerUser):
+ if isinstance(to_id, raw.types.PeerUser):
if message.out:
chat_id = to_id.user_id
else:
@@ -94,14 +95,14 @@ async def get_dialogs(
else:
chat_id = utils.get_peer_id(to_id)
- messages[chat_id] = await pyrogram.Message._parse(self, message, users, chats)
+ messages[chat_id] = await types.Message._parse(self, message, users, chats)
parsed_dialogs = []
for dialog in r.dialogs:
- if not isinstance(dialog, types.Dialog):
+ if not isinstance(dialog, raw.types.Dialog):
continue
- parsed_dialogs.append(pyrogram.Dialog._parse(self, dialog, messages, users, chats))
+ parsed_dialogs.append(types.Dialog._parse(self, dialog, messages, users, chats))
- return pyrogram.List(parsed_dialogs)
+ return types.List(parsed_dialogs)
diff --git a/pyrogram/client/methods/chats/get_dialogs_count.py b/pyrogram/methods/chats/get_dialogs_count.py
similarity index 81%
rename from pyrogram/client/methods/chats/get_dialogs_count.py
rename to pyrogram/methods/chats/get_dialogs_count.py
index da4c60cee7..4eef96ad7b 100644
--- a/pyrogram/client/methods/chats/get_dialogs_count.py
+++ b/pyrogram/methods/chats/get_dialogs_count.py
@@ -16,11 +16,11 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class GetDialogsCount(BaseClient):
+class GetDialogsCount(Scaffold):
async def get_dialogs_count(self, pinned_only: bool = False) -> int:
"""Get the total count of your dialogs.
@@ -39,19 +39,19 @@ async def get_dialogs_count(self, pinned_only: bool = False) -> int:
"""
if pinned_only:
- return len((await self.send(functions.messages.GetPinnedDialogs(folder_id=0))).dialogs)
+ return len((await self.send(raw.functions.messages.GetPinnedDialogs(folder_id=0))).dialogs)
else:
r = await self.send(
- functions.messages.GetDialogs(
+ raw.functions.messages.GetDialogs(
offset_date=0,
offset_id=0,
- offset_peer=types.InputPeerEmpty(),
+ offset_peer=raw.types.InputPeerEmpty(),
limit=1,
hash=0
)
)
- if isinstance(r, types.messages.Dialogs):
+ if isinstance(r, raw.types.messages.Dialogs):
return len(r.dialogs)
else:
return r.count
diff --git a/pyrogram/client/methods/chats/get_nearby_chats.py b/pyrogram/methods/chats/get_nearby_chats.py
similarity index 77%
rename from pyrogram/client/methods/chats/get_nearby_chats.py
rename to pyrogram/methods/chats/get_nearby_chats.py
index 4e76b7e6f7..697465035e 100644
--- a/pyrogram/client/methods/chats/get_nearby_chats.py
+++ b/pyrogram/methods/chats/get_nearby_chats.py
@@ -18,17 +18,18 @@
from typing import List
-import pyrogram
-from pyrogram.api import functions, types
-from ...ext import BaseClient, utils
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
-class GetNearbyChats(BaseClient):
+class GetNearbyChats(Scaffold):
async def get_nearby_chats(
self,
latitude: float,
longitude: float
- ) -> List["pyrogram.Chat"]:
+ ) -> List["types.Chat"]:
"""Get nearby chats.
Parameters:
@@ -39,7 +40,7 @@ async def get_nearby_chats(
Longitude of the location.
Returns:
- List of :obj:`Chat`: On success, a list of nearby chats is returned.
+ List of :obj:`~pyrogram.types.Chat`: On success, a list of nearby chats is returned.
Example:
.. code-block:: python
@@ -49,8 +50,8 @@ async def get_nearby_chats(
"""
r = await self.send(
- functions.contacts.GetLocated(
- geo_point=types.InputGeoPoint(
+ raw.functions.contacts.GetLocated(
+ geo_point=raw.types.InputGeoPoint(
lat=latitude,
long=longitude
)
@@ -60,11 +61,11 @@ async def get_nearby_chats(
if not r.updates:
return []
- chats = pyrogram.List([pyrogram.Chat._parse_chat(self, chat) for chat in r.chats])
+ chats = types.List([types.Chat._parse_chat(self, chat) for chat in r.chats])
peers = r.updates[0].peers
for peer in peers:
- if isinstance(peer.peer, types.PeerChannel):
+ if isinstance(peer.peer, raw.types.PeerChannel):
chat_id = utils.get_channel_id(peer.peer.channel_id)
for chat in chats:
diff --git a/pyrogram/client/methods/chats/iter_chat_members.py b/pyrogram/methods/chats/iter_chat_members.py
similarity index 85%
rename from pyrogram/client/methods/chats/iter_chat_members.py
rename to pyrogram/methods/chats/iter_chat_members.py
index b5ded4dce4..2954bcdba4 100644
--- a/pyrogram/client/methods/chats/iter_chat_members.py
+++ b/pyrogram/methods/chats/iter_chat_members.py
@@ -17,13 +17,11 @@
# along with Pyrogram. If not, see .
from string import ascii_lowercase
-from typing import Union, Generator, Optional
+from typing import Union, AsyncGenerator, Optional
-import pyrogram
-from async_generator import async_generator, yield_
-from pyrogram.api import types
-
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
class Filters:
@@ -39,20 +37,19 @@ class Filters:
QUERYABLE_FILTERS = (Filters.ALL, Filters.KICKED, Filters.RESTRICTED)
-class IterChatMembers(BaseClient):
- @async_generator
+class IterChatMembers(Scaffold):
async def iter_chat_members(
self,
chat_id: Union[int, str],
limit: int = 0,
query: str = "",
filter: str = Filters.ALL
- ) -> Optional[Generator["pyrogram.ChatMember", None, None]]:
+ ) -> Optional[AsyncGenerator["types.ChatMember", None]]:
"""Iterate through the members of a chat sequentially.
- This convenience method does the same as repeatedly calling :meth:`~Client.get_chat_members` in a loop, thus saving you
- from the hassle of setting up boilerplate code. It is useful for getting the whole members list of a chat with
- a single call.
+ This convenience method does the same as repeatedly calling :meth:`~pyrogram.Client.get_chat_members` in a loop,
+ thus saving you from the hassle of setting up boilerplate code. It is useful for getting the whole members list
+ of a chat with a single call.
Parameters:
chat_id (``int`` | ``str``):
@@ -78,7 +75,7 @@ async def iter_chat_members(
Defaults to *"all"*.
Returns:
- ``Generator``: A generator yielding :obj:`ChatMember` objects.
+ ``Generator``: A generator yielding :obj:`~pyrogram.types.ChatMember` objects.
Example:
.. code-block:: python
@@ -120,7 +117,7 @@ async def iter_chat_members(
if not chat_members:
break
- if isinstance(resolved_chat_id, types.InputPeerChat):
+ if isinstance(resolved_chat_id, raw.types.InputPeerChat):
total = len(chat_members)
offset += len(chat_members)
@@ -131,7 +128,7 @@ async def iter_chat_members(
if user_id in yielded:
continue
- await yield_(chat_member)
+ yield chat_member
yielded.add(chat_member.user.id)
diff --git a/pyrogram/client/methods/chats/iter_dialogs.py b/pyrogram/methods/chats/iter_dialogs.py
similarity index 79%
rename from pyrogram/client/methods/chats/iter_dialogs.py
rename to pyrogram/methods/chats/iter_dialogs.py
index a1933a7e20..0c878f0ef4 100644
--- a/pyrogram/client/methods/chats/iter_dialogs.py
+++ b/pyrogram/methods/chats/iter_dialogs.py
@@ -16,26 +16,23 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from typing import Generator, Optional
+from typing import AsyncGenerator, Optional
-from async_generator import async_generator, yield_
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-import pyrogram
-from ...ext import BaseClient
-
-class IterDialogs(BaseClient):
- @async_generator
+class IterDialogs(Scaffold):
async def iter_dialogs(
self,
limit: int = 0,
offset_date: int = 0
- ) -> Optional[Generator["pyrogram.Dialog", None, None]]:
+ ) -> Optional[AsyncGenerator["types.Dialog", None]]:
"""Iterate through a user's dialogs sequentially.
- This convenience method does the same as repeatedly calling :meth:`~Client.get_dialogs` in a loop, thus saving
- you from the hassle of setting up boilerplate code. It is useful for getting the whole dialogs list with a
- single call.
+ This convenience method does the same as repeatedly calling :meth:`~pyrogram.Client.get_dialogs` in a loop,
+ thus saving you from the hassle of setting up boilerplate code. It is useful for getting the whole dialogs list
+ with a single call.
Parameters:
limit (``int``, *optional*):
@@ -43,11 +40,11 @@ async def iter_dialogs(
By default, no limit is applied and all dialogs are returned.
offset_date (``int``):
- The offset date in Unix time taken from the top message of a :obj:`Dialog`.
+ The offset date in Unix time taken from the top message of a :obj:`~pyrogram.types.Dialog`.
Defaults to 0 (most recent dialog).
Returns:
- ``Generator``: A generator yielding :obj:`Dialog` objects.
+ ``Generator``: A generator yielding :obj:`~pyrogram.types.Dialog` objects.
Example:
.. code-block:: python
@@ -65,7 +62,7 @@ async def iter_dialogs(
)
for dialog in pinned_dialogs:
- await yield_(dialog)
+ yield dialog
current += 1
@@ -84,7 +81,7 @@ async def iter_dialogs(
offset_date = dialogs[-1].top_message.date
for dialog in dialogs:
- await yield_(dialog)
+ yield dialog
current += 1
diff --git a/pyrogram/client/methods/chats/join_chat.py b/pyrogram/methods/chats/join_chat.py
similarity index 75%
rename from pyrogram/client/methods/chats/join_chat.py
rename to pyrogram/methods/chats/join_chat.py
index 05bde18643..88adc4ed58 100644
--- a/pyrogram/client/methods/chats/join_chat.py
+++ b/pyrogram/methods/chats/join_chat.py
@@ -18,12 +18,12 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class JoinChat(BaseClient):
+class JoinChat(Scaffold):
async def join_chat(
self,
chat_id: Union[int, str]
@@ -36,7 +36,7 @@ async def join_chat(
channel/supergroup (in the format @username) or a chat id of a linked chat (channel or supergroup).
Returns:
- :obj:`Chat`: On success, a chat object is returned.
+ :obj:`~pyrogram.types.Chat`: On success, a chat object is returned.
Example:
.. code-block:: python
@@ -54,19 +54,19 @@ async def join_chat(
if match:
chat = await self.send(
- functions.messages.ImportChatInvite(
+ raw.functions.messages.ImportChatInvite(
hash=match.group(1)
)
)
- if isinstance(chat.chats[0], types.Chat):
- return pyrogram.Chat._parse_chat_chat(self, chat.chats[0])
- elif isinstance(chat.chats[0], types.Channel):
- return pyrogram.Chat._parse_channel_chat(self, chat.chats[0])
+ if isinstance(chat.chats[0], raw.types.Chat):
+ return types.Chat._parse_chat_chat(self, chat.chats[0])
+ elif isinstance(chat.chats[0], raw.types.Channel):
+ return types.Chat._parse_channel_chat(self, chat.chats[0])
else:
chat = await self.send(
- functions.channels.JoinChannel(
+ raw.functions.channels.JoinChannel(
channel=await self.resolve_peer(chat_id)
)
)
- return pyrogram.Chat._parse_channel_chat(self, chat.chats[0])
+ return types.Chat._parse_channel_chat(self, chat.chats[0])
diff --git a/pyrogram/client/methods/chats/kick_chat_member.py b/pyrogram/methods/chats/kick_chat_member.py
similarity index 83%
rename from pyrogram/client/methods/chats/kick_chat_member.py
rename to pyrogram/methods/chats/kick_chat_member.py
index d72da5ab22..ce814f25c1 100644
--- a/pyrogram/client/methods/chats/kick_chat_member.py
+++ b/pyrogram/methods/chats/kick_chat_member.py
@@ -18,18 +18,18 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class KickChatMember(BaseClient):
+class KickChatMember(Scaffold):
async def kick_chat_member(
self,
chat_id: Union[int, str],
user_id: Union[int, str],
until_date: int = 0
- ) -> Union["pyrogram.Message", bool]:
+ ) -> Union["types.Message", bool]:
"""Kick a user from a group, a supergroup or a channel.
In the case of supergroups and channels, the user will not be able to return to the group on their own using
invite links, etc., unless unbanned first. You must be an administrator in the chat for this to work and must
@@ -54,8 +54,8 @@ async def kick_chat_member(
considered to be banned forever. Defaults to 0 (ban forever).
Returns:
- :obj:`Message` | ``bool``: On success, a service message will be returned (when applicable), otherwise, in
- case a message object couldn't be returned, True is returned.
+ :obj:`~pyrogram.types.Message` | ``bool``: On success, a service message will be returned (when applicable),
+ otherwise, in case a message object couldn't be returned, True is returned.
Example:
.. code-block:: python
@@ -71,12 +71,12 @@ async def kick_chat_member(
chat_peer = await self.resolve_peer(chat_id)
user_peer = await self.resolve_peer(user_id)
- if isinstance(chat_peer, types.InputPeerChannel):
+ if isinstance(chat_peer, raw.types.InputPeerChannel):
r = await self.send(
- functions.channels.EditBanned(
+ raw.functions.channels.EditBanned(
channel=chat_peer,
user_id=user_peer,
- banned_rights=types.ChatBannedRights(
+ banned_rights=raw.types.ChatBannedRights(
until_date=until_date,
view_messages=True,
send_messages=True,
@@ -91,15 +91,15 @@ async def kick_chat_member(
)
else:
r = await self.send(
- functions.messages.DeleteChatUser(
+ raw.functions.messages.DeleteChatUser(
chat_id=abs(chat_id),
user_id=user_peer
)
)
for i in r.updates:
- if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage, raw.types.UpdateNewChannelMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/chats/leave_chat.py b/pyrogram/methods/chats/leave_chat.py
similarity index 83%
rename from pyrogram/client/methods/chats/leave_chat.py
rename to pyrogram/methods/chats/leave_chat.py
index 31b7cc78cd..5c60e6581c 100644
--- a/pyrogram/client/methods/chats/leave_chat.py
+++ b/pyrogram/methods/chats/leave_chat.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class LeaveChat(BaseClient):
+class LeaveChat(Scaffold):
async def leave_chat(
self,
chat_id: Union[int, str],
@@ -50,23 +50,23 @@ async def leave_chat(
"""
peer = await self.resolve_peer(chat_id)
- if isinstance(peer, types.InputPeerChannel):
+ if isinstance(peer, raw.types.InputPeerChannel):
return await self.send(
- functions.channels.LeaveChannel(
+ raw.functions.channels.LeaveChannel(
channel=await self.resolve_peer(chat_id)
)
)
- elif isinstance(peer, types.InputPeerChat):
+ elif isinstance(peer, raw.types.InputPeerChat):
r = await self.send(
- functions.messages.DeleteChatUser(
+ raw.functions.messages.DeleteChatUser(
chat_id=peer.chat_id,
- user_id=types.InputPeerSelf()
+ user_id=raw.types.InputUserSelf()
)
)
if delete:
await self.send(
- functions.messages.DeleteHistory(
+ raw.functions.messages.DeleteHistory(
peer=peer,
max_id=0
)
diff --git a/pyrogram/client/methods/chats/pin_chat_message.py b/pyrogram/methods/chats/pin_chat_message.py
similarity index 93%
rename from pyrogram/client/methods/chats/pin_chat_message.py
rename to pyrogram/methods/chats/pin_chat_message.py
index 6adaa2e84c..a357aab9ec 100644
--- a/pyrogram/client/methods/chats/pin_chat_message.py
+++ b/pyrogram/methods/chats/pin_chat_message.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class PinChatMessage(BaseClient):
+class PinChatMessage(Scaffold):
async def pin_chat_message(
self,
chat_id: Union[int, str],
@@ -57,7 +57,7 @@ async def pin_chat_message(
app.pin_chat_message(chat_id, message_id, disable_notification=True)
"""
await self.send(
- functions.messages.UpdatePinnedMessage(
+ raw.functions.messages.UpdatePinnedMessage(
peer=await self.resolve_peer(chat_id),
id=message_id,
silent=disable_notification or None
diff --git a/pyrogram/client/methods/chats/promote_chat_member.py b/pyrogram/methods/chats/promote_chat_member.py
similarity index 95%
rename from pyrogram/client/methods/chats/promote_chat_member.py
rename to pyrogram/methods/chats/promote_chat_member.py
index c6912031f7..eb49bce05b 100644
--- a/pyrogram/client/methods/chats/promote_chat_member.py
+++ b/pyrogram/methods/chats/promote_chat_member.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class PromoteChatMember(BaseClient):
+class PromoteChatMember(Scaffold):
async def promote_chat_member(
self,
chat_id: Union[int, str],
@@ -85,10 +85,10 @@ async def promote_chat_member(
app.promote_chat_member(chat_id, user_id)
"""
await self.send(
- functions.channels.EditAdmin(
+ raw.functions.channels.EditAdmin(
channel=await self.resolve_peer(chat_id),
user_id=await self.resolve_peer(user_id),
- admin_rights=types.ChatAdminRights(
+ admin_rights=raw.types.ChatAdminRights(
change_info=can_change_info or None,
post_messages=can_post_messages or None,
edit_messages=can_edit_messages or None,
diff --git a/pyrogram/client/methods/chats/restrict_chat_member.py b/pyrogram/methods/chats/restrict_chat_member.py
similarity index 88%
rename from pyrogram/client/methods/chats/restrict_chat_member.py
rename to pyrogram/methods/chats/restrict_chat_member.py
index 500482a1fd..af760feb74 100644
--- a/pyrogram/client/methods/chats/restrict_chat_member.py
+++ b/pyrogram/methods/chats/restrict_chat_member.py
@@ -18,19 +18,19 @@
from typing import Union
-from pyrogram.api import functions, types
-from ...ext import BaseClient
-from ...types.user_and_chats import Chat, ChatPermissions
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class RestrictChatMember(BaseClient):
+class RestrictChatMember(Scaffold):
async def restrict_chat_member(
self,
chat_id: Union[int, str],
user_id: Union[int, str],
- permissions: ChatPermissions,
+ permissions: "types.ChatPermissions",
until_date: int = 0
- ) -> Chat:
+ ) -> "types.Chat":
"""Restrict a user in a supergroup.
You must be an administrator in the supergroup for this to work and must have the appropriate admin rights.
@@ -44,7 +44,7 @@ async def restrict_chat_member(
Unique identifier (int) or username (str) of the target user.
For a contact that exists in your Telegram address book you can use his phone number (str).
- permissions (:obj:`ChatPermissions`):
+ permissions (:obj:`~pyrogram.types.ChatPermissions`):
New user permissions.
until_date (``int``, *optional*):
@@ -53,7 +53,7 @@ async def restrict_chat_member(
considered to be banned forever. Defaults to 0 (ban forever).
Returns:
- :obj:`Chat`: On success, a chat object is returned.
+ :obj:`~pyrogram.types.Chat`: On success, a chat object is returned.
Example:
.. code-block:: python
@@ -72,10 +72,10 @@ async def restrict_chat_member(
app.restrict_chat_member(chat_id, user_id, ChatPermissions(can_send_messages=True))
"""
r = await self.send(
- functions.channels.EditBanned(
+ raw.functions.channels.EditBanned(
channel=await self.resolve_peer(chat_id),
user_id=await self.resolve_peer(user_id),
- banned_rights=types.ChatBannedRights(
+ banned_rights=raw.types.ChatBannedRights(
until_date=until_date,
send_messages=True if not permissions.can_send_messages else None,
send_media=True if not permissions.can_send_media_messages else None,
@@ -92,4 +92,4 @@ async def restrict_chat_member(
)
)
- return Chat._parse_chat(self, r.chats[0])
+ return types.Chat._parse_chat(self, r.chats[0])
diff --git a/pyrogram/client/methods/chats/set_administrator_title.py b/pyrogram/methods/chats/set_administrator_title.py
similarity index 90%
rename from pyrogram/client/methods/chats/set_administrator_title.py
rename to pyrogram/methods/chats/set_administrator_title.py
index 0cbc937a33..e354fd5b72 100644
--- a/pyrogram/client/methods/chats/set_administrator_title.py
+++ b/pyrogram/methods/chats/set_administrator_title.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class SetAdministratorTitle(BaseClient):
+class SetAdministratorTitle(Scaffold):
async def set_administrator_title(
self,
chat_id: Union[int, str],
@@ -58,14 +58,14 @@ async def set_administrator_title(
user_id = await self.resolve_peer(user_id)
r = (await self.send(
- functions.channels.GetParticipant(
+ raw.functions.channels.GetParticipant(
channel=chat_id,
user_id=user_id
)
)).participant
- if isinstance(r, types.ChannelParticipantCreator):
- admin_rights = types.ChatAdminRights(
+ if isinstance(r, raw.types.ChannelParticipantCreator):
+ admin_rights = raw.types.ChatAdminRights(
change_info=True,
post_messages=True,
edit_messages=True,
@@ -75,7 +75,7 @@ async def set_administrator_title(
pin_messages=True,
add_admins=True,
)
- elif isinstance(r, types.ChannelParticipantAdmin):
+ elif isinstance(r, raw.types.ChannelParticipantAdmin):
admin_rights = r.admin_rights
else:
raise ValueError("Custom titles can only be applied to owners or administrators of supergroups")
@@ -105,7 +105,7 @@ async def set_administrator_title(
admin_rights.add_admins = None
await self.send(
- functions.channels.EditAdmin(
+ raw.functions.channels.EditAdmin(
channel=chat_id,
user_id=user_id,
admin_rights=admin_rights,
diff --git a/pyrogram/client/methods/chats/set_chat_description.py b/pyrogram/methods/chats/set_chat_description.py
similarity index 85%
rename from pyrogram/client/methods/chats/set_chat_description.py
rename to pyrogram/methods/chats/set_chat_description.py
index e296040894..0dc87c4837 100644
--- a/pyrogram/client/methods/chats/set_chat_description.py
+++ b/pyrogram/methods/chats/set_chat_description.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class SetChatDescription(BaseClient):
+class SetChatDescription(Scaffold):
async def set_chat_description(
self,
chat_id: Union[int, str],
@@ -51,14 +51,14 @@ async def set_chat_description(
"""
peer = await self.resolve_peer(chat_id)
- if isinstance(peer, (types.InputPeerChannel, types.InputPeerChat)):
+ if isinstance(peer, (raw.types.InputPeerChannel, raw.types.InputPeerChat)):
await self.send(
- functions.messages.EditChatAbout(
+ raw.functions.messages.EditChatAbout(
peer=peer,
about=description
)
)
else:
- raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
+ raise ValueError(f'The chat_id "{chat_id}" belongs to a user')
return True
diff --git a/pyrogram/client/methods/chats/set_chat_permissions.py b/pyrogram/methods/chats/set_chat_permissions.py
similarity index 85%
rename from pyrogram/client/methods/chats/set_chat_permissions.py
rename to pyrogram/methods/chats/set_chat_permissions.py
index 3509baf4ac..028f0eb167 100644
--- a/pyrogram/client/methods/chats/set_chat_permissions.py
+++ b/pyrogram/methods/chats/set_chat_permissions.py
@@ -18,17 +18,17 @@
from typing import Union
-from pyrogram.api import functions, types
-from ...ext import BaseClient
-from ...types.user_and_chats import Chat, ChatPermissions
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class SetChatPermissions(BaseClient):
+class SetChatPermissions(Scaffold):
async def set_chat_permissions(
self,
chat_id: Union[int, str],
- permissions: ChatPermissions,
- ) -> Chat:
+ permissions: "types.ChatPermissions",
+ ) -> "types.Chat":
"""Set default chat permissions for all members.
You must be an administrator in the group or a supergroup for this to work and must have the
@@ -38,11 +38,11 @@ async def set_chat_permissions(
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
- permissions (:obj:`ChatPermissions`):
+ permissions (:obj:`~pyrogram.types.ChatPermissions`):
New default chat permissions.
Returns:
- :obj:`Chat`: On success, a chat object is returned.
+ :obj:`~pyrogram.types.Chat`: On success, a chat object is returned.
Example:
.. code-block:: python
@@ -64,9 +64,9 @@ async def set_chat_permissions(
)
"""
r = await self.send(
- functions.messages.EditChatDefaultBannedRights(
+ raw.functions.messages.EditChatDefaultBannedRights(
peer=await self.resolve_peer(chat_id),
- banned_rights=types.ChatBannedRights(
+ banned_rights=raw.types.ChatBannedRights(
until_date=0,
send_messages=True if not permissions.can_send_messages else None,
send_media=True if not permissions.can_send_media_messages else None,
@@ -83,4 +83,4 @@ async def set_chat_permissions(
)
)
- return Chat._parse_chat(self, r.chats[0])
+ return types.Chat._parse_chat(self, r.chats[0])
diff --git a/pyrogram/client/methods/chats/set_chat_photo.py b/pyrogram/methods/chats/set_chat_photo.py
similarity index 74%
rename from pyrogram/client/methods/chats/set_chat_photo.py
rename to pyrogram/methods/chats/set_chat_photo.py
index e6d3544871..8ccb123cd3 100644
--- a/pyrogram/client/methods/chats/set_chat_photo.py
+++ b/pyrogram/methods/chats/set_chat_photo.py
@@ -19,11 +19,12 @@
import os
from typing import Union, BinaryIO
-from pyrogram.api import functions, types
-from ...ext import BaseClient, utils
+from pyrogram import raw
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
-class SetChatPhoto(BaseClient):
+class SetChatPhoto(Scaffold):
async def set_chat_photo(
self,
chat_id: Union[int, str],
@@ -44,14 +45,14 @@ async def set_chat_photo(
Unique identifier (int) or username (str) of the target chat.
photo (``str`` | ``BinaryIO``, *optional*):
- New chat photo. You can pass a :obj:`Photo` file_id (in pair with a valid file_ref), a file path to
- upload a new photo from your local machine or a binary file-like object with its attribute ".name"
- set for in-memory uploads.
+ New chat photo. You can pass a :obj:`~pyrogram.types.Photo` file_id (in pair with a valid file_ref), a
+ file path to upload a new photo from your local machine or a binary file-like object with its attribute
+ ".name" set for in-memory uploads.
video (``str`` | ``BinaryIO``, *optional*):
- New chat video. You can pass a :obj:`Video` file_id (in pair with a valid file_ref), a file path to
- upload a new video from your local machine or a binary file-like object with its attribute ".name"
- set for in-memory uploads.
+ New chat video. You can pass a :obj:`~pyrogram.types.Video` file_id (in pair with a valid file_ref), a
+ file path to upload a new video from your local machine or a binary file-like object with its attribute
+ ".name" set for in-memory uploads.
file_ref (``str``, *optional*):
A valid file reference obtained by a recently fetched media message.
@@ -83,34 +84,34 @@ async def set_chat_photo(
if isinstance(photo, str):
if os.path.isfile(photo):
- photo = types.InputChatUploadedPhoto(
+ photo = raw.types.InputChatUploadedPhoto(
file=await self.save_file(photo),
video=await self.save_file(video)
)
else:
photo = utils.get_input_media_from_file_id(photo, file_ref, 2)
- photo = types.InputChatPhoto(id=photo.id)
+ photo = raw.types.InputChatPhoto(id=photo.id)
else:
- photo = types.InputChatUploadedPhoto(
+ photo = raw.types.InputChatUploadedPhoto(
file=await self.save_file(photo),
video=await self.save_file(video)
)
- if isinstance(peer, types.InputPeerChat):
+ if isinstance(peer, raw.types.InputPeerChat):
await self.send(
- functions.messages.EditChatPhoto(
+ raw.functions.messages.EditChatPhoto(
chat_id=peer.chat_id,
photo=photo
)
)
- elif isinstance(peer, types.InputPeerChannel):
+ elif isinstance(peer, raw.types.InputPeerChannel):
await self.send(
- functions.channels.EditPhoto(
+ raw.functions.channels.EditPhoto(
channel=peer,
photo=photo
)
)
else:
- raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
+ raise ValueError(f'The chat_id "{chat_id}" belongs to a user')
return True
diff --git a/pyrogram/client/methods/chats/set_chat_title.py b/pyrogram/methods/chats/set_chat_title.py
similarity index 84%
rename from pyrogram/client/methods/chats/set_chat_title.py
rename to pyrogram/methods/chats/set_chat_title.py
index a6b9bc71e3..2ed7d2e836 100644
--- a/pyrogram/client/methods/chats/set_chat_title.py
+++ b/pyrogram/methods/chats/set_chat_title.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class SetChatTitle(BaseClient):
+class SetChatTitle(Scaffold):
async def set_chat_title(
self,
chat_id: Union[int, str],
@@ -56,21 +56,21 @@ async def set_chat_title(
"""
peer = await self.resolve_peer(chat_id)
- if isinstance(peer, types.InputPeerChat):
+ if isinstance(peer, raw.types.InputPeerChat):
await self.send(
- functions.messages.EditChatTitle(
+ raw.functions.messages.EditChatTitle(
chat_id=peer.chat_id,
title=title
)
)
- elif isinstance(peer, types.InputPeerChannel):
+ elif isinstance(peer, raw.types.InputPeerChannel):
await self.send(
- functions.channels.EditTitle(
+ raw.functions.channels.EditTitle(
channel=peer,
title=title
)
)
else:
- raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
+ raise ValueError(f'The chat_id "{chat_id}" belongs to a user')
return True
diff --git a/pyrogram/client/methods/chats/set_slow_mode.py b/pyrogram/methods/chats/set_slow_mode.py
similarity index 92%
rename from pyrogram/client/methods/chats/set_slow_mode.py
rename to pyrogram/methods/chats/set_slow_mode.py
index 185a3824eb..e2db5a85dd 100644
--- a/pyrogram/client/methods/chats/set_slow_mode.py
+++ b/pyrogram/methods/chats/set_slow_mode.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class SetSlowMode(BaseClient):
+class SetSlowMode(Scaffold):
async def set_slow_mode(
self,
chat_id: Union[int, str],
@@ -52,7 +52,7 @@ async def set_slow_mode(
"""
await self.send(
- functions.channels.ToggleSlowMode(
+ raw.functions.channels.ToggleSlowMode(
channel=await self.resolve_peer(chat_id),
seconds=0 if seconds is None else seconds
)
diff --git a/pyrogram/client/methods/chats/unarchive_chats.py b/pyrogram/methods/chats/unarchive_chats.py
similarity index 91%
rename from pyrogram/client/methods/chats/unarchive_chats.py
rename to pyrogram/methods/chats/unarchive_chats.py
index dfba70a7fa..af62d9a730 100644
--- a/pyrogram/client/methods/chats/unarchive_chats.py
+++ b/pyrogram/methods/chats/unarchive_chats.py
@@ -18,11 +18,11 @@
from typing import Union, List
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class UnarchiveChats(BaseClient):
+class UnarchiveChats(Scaffold):
async def unarchive_chats(
self,
chat_ids: Union[int, str, List[Union[int, str]]],
@@ -54,14 +54,14 @@ async def unarchive_chats(
for chat in chat_ids:
folder_peers.append(
- types.InputFolderPeer(
+ raw.types.InputFolderPeer(
peer=await self.resolve_peer(chat),
folder_id=0
)
)
await self.send(
- functions.folders.EditPeerFolders(
+ raw.functions.folders.EditPeerFolders(
folder_peers=folder_peers
)
)
diff --git a/pyrogram/client/methods/chats/unban_chat_member.py b/pyrogram/methods/chats/unban_chat_member.py
similarity index 90%
rename from pyrogram/client/methods/chats/unban_chat_member.py
rename to pyrogram/methods/chats/unban_chat_member.py
index 4a7b3940cf..e6f0b7b0b0 100644
--- a/pyrogram/client/methods/chats/unban_chat_member.py
+++ b/pyrogram/methods/chats/unban_chat_member.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class UnbanChatMember(BaseClient):
+class UnbanChatMember(Scaffold):
async def unban_chat_member(
self,
chat_id: Union[int, str],
@@ -50,10 +50,10 @@ async def unban_chat_member(
app.unban_chat_member(chat_id, user_id)
"""
await self.send(
- functions.channels.EditBanned(
+ raw.functions.channels.EditBanned(
channel=await self.resolve_peer(chat_id),
user_id=await self.resolve_peer(user_id),
- banned_rights=types.ChatBannedRights(
+ banned_rights=raw.types.ChatBannedRights(
until_date=0
)
)
diff --git a/pyrogram/client/methods/chats/unpin_chat_message.py b/pyrogram/methods/chats/unpin_chat_message.py
similarity index 91%
rename from pyrogram/client/methods/chats/unpin_chat_message.py
rename to pyrogram/methods/chats/unpin_chat_message.py
index 0ca8254aec..3ee7814dbd 100644
--- a/pyrogram/client/methods/chats/unpin_chat_message.py
+++ b/pyrogram/methods/chats/unpin_chat_message.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class UnpinChatMessage(BaseClient):
+class UnpinChatMessage(Scaffold):
async def unpin_chat_message(
self,
chat_id: Union[int, str]
@@ -44,7 +44,7 @@ async def unpin_chat_message(
app.unpin_chat_message(chat_id)
"""
await self.send(
- functions.messages.UpdatePinnedMessage(
+ raw.functions.messages.UpdatePinnedMessage(
peer=await self.resolve_peer(chat_id),
id=0
)
diff --git a/pyrogram/client/methods/chats/update_chat_username.py b/pyrogram/methods/chats/update_chat_username.py
similarity index 84%
rename from pyrogram/client/methods/chats/update_chat_username.py
rename to pyrogram/methods/chats/update_chat_username.py
index b1c57f1ed3..876115a4bc 100644
--- a/pyrogram/client/methods/chats/update_chat_username.py
+++ b/pyrogram/methods/chats/update_chat_username.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class UpdateChatUsername(BaseClient):
+class UpdateChatUsername(Scaffold):
async def update_chat_username(
self,
chat_id: Union[int, str],
@@ -30,7 +30,7 @@ async def update_chat_username(
) -> bool:
"""Update a channel or a supergroup username.
- To update your own username (for users only, not bots) you can use :meth:`~Client.update_username`.
+ To update your own username (for users only, not bots) you can use :meth:`~pyrogram.Client.update_username`.
Parameters:
chat_id (``int`` | ``str``)
@@ -52,14 +52,14 @@ async def update_chat_username(
peer = await self.resolve_peer(chat_id)
- if isinstance(peer, types.InputPeerChannel):
+ if isinstance(peer, raw.types.InputPeerChannel):
return bool(
await self.send(
- functions.channels.UpdateUsername(
+ raw.functions.channels.UpdateUsername(
channel=peer,
username=username or ""
)
)
)
else:
- raise ValueError("The chat_id \"{}\" belongs to a user or chat".format(chat_id))
+ raise ValueError(f'The chat_id "{chat_id}" belongs to a user or chat')
diff --git a/pyrogram/client/methods/contacts/__init__.py b/pyrogram/methods/contacts/__init__.py
similarity index 100%
rename from pyrogram/client/methods/contacts/__init__.py
rename to pyrogram/methods/contacts/__init__.py
diff --git a/pyrogram/client/methods/contacts/add_contacts.py b/pyrogram/methods/contacts/add_contacts.py
similarity index 84%
rename from pyrogram/client/methods/contacts/add_contacts.py
rename to pyrogram/methods/contacts/add_contacts.py
index 7226d60b19..b786991cc7 100644
--- a/pyrogram/client/methods/contacts/add_contacts.py
+++ b/pyrogram/methods/contacts/add_contacts.py
@@ -18,20 +18,20 @@
from typing import List
-import pyrogram
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class AddContacts(BaseClient):
+class AddContacts(Scaffold):
async def add_contacts(
self,
- contacts: List["pyrogram.InputPhoneContact"]
+ contacts: List["types.InputPhoneContact"]
):
"""Add contacts to your Telegram address book.
Parameters:
- contacts (List of :obj:`InputPhoneContact`):
+ contacts (List of :obj:`~pyrogram.types.InputPhoneContact`):
The contact list to be added
Returns:
@@ -48,7 +48,7 @@ async def add_contacts(
InputPhoneContact("01234567891", "Baz")])
"""
imported_contacts = await self.send(
- functions.contacts.ImportContacts(
+ raw.functions.contacts.ImportContacts(
contacts=contacts
)
)
diff --git a/pyrogram/client/methods/contacts/delete_contacts.py b/pyrogram/methods/contacts/delete_contacts.py
similarity index 88%
rename from pyrogram/client/methods/contacts/delete_contacts.py
rename to pyrogram/methods/contacts/delete_contacts.py
index 777d8b39d0..2f576a5e2f 100644
--- a/pyrogram/client/methods/contacts/delete_contacts.py
+++ b/pyrogram/methods/contacts/delete_contacts.py
@@ -18,12 +18,12 @@
from typing import List
-from pyrogram.api import functions, types
+from pyrogram import raw
from pyrogram.errors import PeerIdInvalid
-from ...ext import BaseClient
+from pyrogram.scaffold import Scaffold
-class DeleteContacts(BaseClient):
+class DeleteContacts(Scaffold):
async def delete_contacts(
self,
ids: List[int]
@@ -51,11 +51,11 @@ async def delete_contacts(
except PeerIdInvalid:
continue
else:
- if isinstance(input_user, types.InputPeerUser):
+ if isinstance(input_user, raw.types.InputPeerUser):
contacts.append(input_user)
return await self.send(
- functions.contacts.DeleteContacts(
+ raw.functions.contacts.DeleteContacts(
id=contacts
)
)
diff --git a/pyrogram/client/methods/contacts/get_contacts.py b/pyrogram/methods/contacts/get_contacts.py
similarity index 72%
rename from pyrogram/client/methods/contacts/get_contacts.py
rename to pyrogram/methods/contacts/get_contacts.py
index 8f8392d68a..d4f08168e8 100644
--- a/pyrogram/client/methods/contacts/get_contacts.py
+++ b/pyrogram/methods/contacts/get_contacts.py
@@ -16,23 +16,22 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-import asyncio
import logging
from typing import List
-import pyrogram
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
log = logging.getLogger(__name__)
-class GetContacts(BaseClient):
- async def get_contacts(self) -> List["pyrogram.User"]:
+class GetContacts(Scaffold):
+ async def get_contacts(self) -> List["types.User"]:
"""Get contacts from your Telegram address book.
Returns:
- List of :obj:`User`: On success, a list of users is returned.
+ List of :obj:`~pyrogram.types.User`: On success, a list of users is returned.
Example:
.. code-block:: python
@@ -40,5 +39,5 @@ async def get_contacts(self) -> List["pyrogram.User"]:
contacts = app.get_contacts()
print(contacts)
"""
- contacts = await self.send(functions.contacts.GetContacts(hash=0))
- return pyrogram.List(pyrogram.User._parse(self, user) for user in contacts.users)
+ contacts = await self.send(raw.functions.contacts.GetContacts(hash=0))
+ return types.List(types.User._parse(self, user) for user in contacts.users)
diff --git a/pyrogram/client/methods/contacts/get_contacts_count.py b/pyrogram/methods/contacts/get_contacts_count.py
similarity index 86%
rename from pyrogram/client/methods/contacts/get_contacts_count.py
rename to pyrogram/methods/contacts/get_contacts_count.py
index 8435557a9e..3a16c9050e 100644
--- a/pyrogram/client/methods/contacts/get_contacts_count.py
+++ b/pyrogram/methods/contacts/get_contacts_count.py
@@ -16,11 +16,11 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class GetContactsCount(BaseClient):
+class GetContactsCount(Scaffold):
async def get_contacts_count(self) -> int:
"""Get the total count of contacts from your Telegram address book.
@@ -34,4 +34,4 @@ async def get_contacts_count(self) -> int:
print(count)
"""
- return len((await self.send(functions.contacts.GetContacts(hash=0))).contacts)
+ return len((await self.send(raw.functions.contacts.GetContacts(hash=0))).contacts)
diff --git a/pyrogram/client/methods/decorators/__init__.py b/pyrogram/methods/decorators/__init__.py
similarity index 100%
rename from pyrogram/client/methods/decorators/__init__.py
rename to pyrogram/methods/decorators/__init__.py
index 5a60ff9b20..fbc4fac690 100644
--- a/pyrogram/client/methods/decorators/__init__.py
+++ b/pyrogram/methods/decorators/__init__.py
@@ -17,6 +17,7 @@
# along with Pyrogram. If not, see .
from .on_callback_query import OnCallbackQuery
+from .on_chosen_inline_result import OnChosenInlineResult
from .on_deleted_messages import OnDeletedMessages
from .on_disconnect import OnDisconnect
from .on_inline_query import OnInlineQuery
@@ -24,7 +25,6 @@
from .on_poll import OnPoll
from .on_raw_update import OnRawUpdate
from .on_user_status import OnUserStatus
-from .on_chosen_inline_result import OnChosenInlineResult
class Decorators(
diff --git a/pyrogram/client/methods/decorators/on_callback_query.py b/pyrogram/methods/decorators/on_callback_query.py
similarity index 84%
rename from pyrogram/client/methods/decorators/on_callback_query.py
rename to pyrogram/methods/decorators/on_callback_query.py
index c7bcae2676..f681eee70b 100644
--- a/pyrogram/client/methods/decorators/on_callback_query.py
+++ b/pyrogram/methods/decorators/on_callback_query.py
@@ -19,11 +19,11 @@
from typing import Callable
import pyrogram
-from pyrogram.client.filters.filter import Filter
-from ...ext import BaseClient
+from pyrogram.filters import Filter
+from pyrogram.scaffold import Scaffold
-class OnCallbackQuery(BaseClient):
+class OnCallbackQuery(Scaffold):
def on_callback_query(
self=None,
filters=None,
@@ -32,7 +32,7 @@ def on_callback_query(
"""Decorator for handling callback queries.
This does the same thing as :meth:`~pyrogram.Client.add_handler` using the
- :obj:`~pyrogram.CallbackQueryHandler`.
+ :obj:`~pyrogram.handlers.CallbackQueryHandler`.
Parameters:
filters (:obj:`~pyrogram.Filters`, *optional*):
@@ -45,10 +45,10 @@ def on_callback_query(
def decorator(func: Callable) -> Callable:
if isinstance(self, pyrogram.Client):
- self.add_handler(pyrogram.CallbackQueryHandler(func, filters), group)
+ self.add_handler(pyrogram.handlers.CallbackQueryHandler(func, filters), group)
elif isinstance(self, Filter) or self is None:
func.handler = (
- pyrogram.CallbackQueryHandler(func, self),
+ pyrogram.handlers.CallbackQueryHandler(func, self),
group if filters is None else filters
)
diff --git a/pyrogram/client/methods/decorators/on_chosen_inline_result.py b/pyrogram/methods/decorators/on_chosen_inline_result.py
similarity index 82%
rename from pyrogram/client/methods/decorators/on_chosen_inline_result.py
rename to pyrogram/methods/decorators/on_chosen_inline_result.py
index 40446eb2ff..3163ccb388 100644
--- a/pyrogram/client/methods/decorators/on_chosen_inline_result.py
+++ b/pyrogram/methods/decorators/on_chosen_inline_result.py
@@ -19,11 +19,11 @@
from typing import Callable
import pyrogram
-from pyrogram.client.filters.filter import Filter
-from ...ext import BaseClient
+from pyrogram.filters import Filter
+from pyrogram.scaffold import Scaffold
-class OnChosenInlineResult(BaseClient):
+class OnChosenInlineResult(Scaffold):
def on_chosen_inline_result(
self=None,
filters=None,
@@ -31,7 +31,8 @@ def on_chosen_inline_result(
) -> callable:
"""Decorator for handling chosen inline results.
- This does the same thing as :meth:`~pyrogram.Client.add_handler` using the :obj:`~pyrogram.ChosenInlineResult`.
+ This does the same thing as :meth:`~pyrogram.Client.add_handler` using the
+ :obj:`~pyrogram.handlers.ChosenInlineResult`.
Parameters:
filters (:obj:`~pyrogram.Filters`, *optional*):
@@ -44,10 +45,10 @@ def on_chosen_inline_result(
def decorator(func: Callable) -> Callable:
if isinstance(self, pyrogram.Client):
- self.add_handler(pyrogram.ChosenInlineResultHandler(func, filters), group)
+ self.add_handler(pyrogram.handlers.ChosenInlineResultHandler(func, filters), group)
elif isinstance(self, Filter) or self is None:
func.handler = (
- pyrogram.ChosenInlineResultHandler(func, self),
+ pyrogram.handlers.ChosenInlineResultHandler(func, self),
group if filters is None else filters
)
diff --git a/pyrogram/client/methods/decorators/on_deleted_messages.py b/pyrogram/methods/decorators/on_deleted_messages.py
similarity index 83%
rename from pyrogram/client/methods/decorators/on_deleted_messages.py
rename to pyrogram/methods/decorators/on_deleted_messages.py
index 8a7e1e55ec..adb4d87914 100644
--- a/pyrogram/client/methods/decorators/on_deleted_messages.py
+++ b/pyrogram/methods/decorators/on_deleted_messages.py
@@ -19,11 +19,11 @@
from typing import Callable
import pyrogram
-from pyrogram.client.filters.filter import Filter
-from ...ext import BaseClient
+from pyrogram.filters import Filter
+from pyrogram.scaffold import Scaffold
-class OnDeletedMessages(BaseClient):
+class OnDeletedMessages(Scaffold):
def on_deleted_messages(
self=None,
filters=None,
@@ -32,7 +32,7 @@ def on_deleted_messages(
"""Decorator for handling deleted messages.
This does the same thing as :meth:`~pyrogram.Client.add_handler` using the
- :obj:`~pyrogram.DeletedMessagesHandler`.
+ :obj:`~pyrogram.handlers.DeletedMessagesHandler`.
Parameters:
filters (:obj:`~pyrogram.Filters`, *optional*):
@@ -45,10 +45,10 @@ def on_deleted_messages(
def decorator(func: Callable) -> Callable:
if isinstance(self, pyrogram.Client):
- self.add_handler(pyrogram.DeletedMessagesHandler(func, filters), group)
+ self.add_handler(pyrogram.handlers.DeletedMessagesHandler(func, filters), group)
elif isinstance(self, Filter) or self is None:
func.handler = (
- pyrogram.DeletedMessagesHandler(func, self),
+ pyrogram.handlers.DeletedMessagesHandler(func, self),
group if filters is None else filters
)
diff --git a/pyrogram/client/methods/decorators/on_disconnect.py b/pyrogram/methods/decorators/on_disconnect.py
similarity index 84%
rename from pyrogram/client/methods/decorators/on_disconnect.py
rename to pyrogram/methods/decorators/on_disconnect.py
index 0df6584837..6e7b1522ff 100644
--- a/pyrogram/client/methods/decorators/on_disconnect.py
+++ b/pyrogram/methods/decorators/on_disconnect.py
@@ -19,19 +19,20 @@
from typing import Callable
import pyrogram
-from ...ext import BaseClient
+from pyrogram.scaffold import Scaffold
-class OnDisconnect(BaseClient):
+class OnDisconnect(Scaffold):
def on_disconnect(self=None) -> callable:
"""Decorator for handling disconnections.
- This does the same thing as :meth:`~pyrogram.Client.add_handler` using the :obj:`~pyrogram.DisconnectHandler`.
+ This does the same thing as :meth:`~pyrogram.Client.add_handler` using the
+ :obj:`~pyrogram.handlers.DisconnectHandler`.
"""
def decorator(func: Callable) -> Callable:
if isinstance(self, pyrogram.Client):
- self.add_handler(pyrogram.DisconnectHandler(func))
+ self.add_handler(pyrogram.handlers.DisconnectHandler(func))
return func
diff --git a/pyrogram/client/methods/decorators/on_inline_query.py b/pyrogram/methods/decorators/on_inline_query.py
similarity index 83%
rename from pyrogram/client/methods/decorators/on_inline_query.py
rename to pyrogram/methods/decorators/on_inline_query.py
index 4a9b1128ea..fdc287ecfe 100644
--- a/pyrogram/client/methods/decorators/on_inline_query.py
+++ b/pyrogram/methods/decorators/on_inline_query.py
@@ -19,11 +19,11 @@
from typing import Callable
import pyrogram
-from pyrogram.client.filters.filter import Filter
-from ...ext import BaseClient
+from pyrogram.filters import Filter
+from pyrogram.scaffold import Scaffold
-class OnInlineQuery(BaseClient):
+class OnInlineQuery(Scaffold):
def on_inline_query(
self=None,
filters=None,
@@ -31,7 +31,8 @@ def on_inline_query(
) -> callable:
"""Decorator for handling inline queries.
- This does the same thing as :meth:`~pyrogram.Client.add_handler` using the :obj:`~pyrogram.InlineQueryHandler`.
+ This does the same thing as :meth:`~pyrogram.Client.add_handler` using the
+ :obj:`~pyrogram.handlers.InlineQueryHandler`.
Parameters:
filters (:obj:`~pyrogram.Filters`, *optional*):
@@ -44,10 +45,10 @@ def on_inline_query(
def decorator(func: Callable) -> Callable:
if isinstance(self, pyrogram.Client):
- self.add_handler(pyrogram.InlineQueryHandler(func, filters), group)
+ self.add_handler(pyrogram.handlers.InlineQueryHandler(func, filters), group)
elif isinstance(self, Filter) or self is None:
func.handler = (
- pyrogram.InlineQueryHandler(func, self),
+ pyrogram.handlers.InlineQueryHandler(func, self),
group if filters is None else filters
)
diff --git a/pyrogram/client/methods/decorators/on_message.py b/pyrogram/methods/decorators/on_message.py
similarity index 83%
rename from pyrogram/client/methods/decorators/on_message.py
rename to pyrogram/methods/decorators/on_message.py
index 9d2791c279..6316def640 100644
--- a/pyrogram/client/methods/decorators/on_message.py
+++ b/pyrogram/methods/decorators/on_message.py
@@ -19,11 +19,11 @@
from typing import Callable
import pyrogram
-from pyrogram.client.filters.filter import Filter
-from ...ext import BaseClient
+from pyrogram.filters import Filter
+from pyrogram.scaffold import Scaffold
-class OnMessage(BaseClient):
+class OnMessage(Scaffold):
def on_message(
self=None,
filters=None,
@@ -31,7 +31,8 @@ def on_message(
) -> callable:
"""Decorator for handling messages.
- This does the same thing as :meth:`~pyrogram.Client.add_handler` using the :obj:`~pyrogram.MessageHandler`.
+ This does the same thing as :meth:`~pyrogram.Client.add_handler` using the
+ :obj:`~pyrogram.handlers.MessageHandler`.
Parameters:
filters (:obj:`~pyrogram.Filters`, *optional*):
@@ -44,10 +45,10 @@ def on_message(
def decorator(func: Callable) -> Callable:
if isinstance(self, pyrogram.Client):
- self.add_handler(pyrogram.MessageHandler(func, filters), group)
+ self.add_handler(pyrogram.handlers.MessageHandler(func, filters), group)
elif isinstance(self, Filter) or self is None:
func.handler = (
- pyrogram.MessageHandler(func, self),
+ pyrogram.handlers.MessageHandler(func, self),
group if filters is None else filters
)
diff --git a/pyrogram/client/methods/decorators/on_poll.py b/pyrogram/methods/decorators/on_poll.py
similarity index 84%
rename from pyrogram/client/methods/decorators/on_poll.py
rename to pyrogram/methods/decorators/on_poll.py
index 2326b3e558..7506c21828 100644
--- a/pyrogram/client/methods/decorators/on_poll.py
+++ b/pyrogram/methods/decorators/on_poll.py
@@ -19,11 +19,11 @@
from typing import Callable
import pyrogram
-from pyrogram.client.filters.filter import Filter
-from ...ext import BaseClient
+from pyrogram.filters import Filter
+from pyrogram.scaffold import Scaffold
-class OnPoll(BaseClient):
+class OnPoll(Scaffold):
def on_poll(
self=None,
filters=None,
@@ -31,7 +31,8 @@ def on_poll(
) -> callable:
"""Decorator for handling poll updates.
- This does the same thing as :meth:`~pyrogram.Client.add_handler` using the :obj:`~pyrogram.PollHandler`.
+ This does the same thing as :meth:`~pyrogram.Client.add_handler` using the
+ :obj:`~pyrogram.handlers.PollHandler`.
Parameters:
filters (:obj:`~pyrogram.Filters`, *optional*):
@@ -44,10 +45,10 @@ def on_poll(
def decorator(func: Callable) -> Callable:
if isinstance(self, pyrogram.Client):
- self.add_handler(pyrogram.PollHandler(func, filters), group)
+ self.add_handler(pyrogram.handlers.PollHandler(func, filters), group)
elif isinstance(self, Filter) or self is None:
func.handler = (
- pyrogram.PollHandler(func, self),
+ pyrogram.handlers.PollHandler(func, self),
group if filters is None else filters
)
diff --git a/pyrogram/client/methods/decorators/on_raw_update.py b/pyrogram/methods/decorators/on_raw_update.py
similarity index 83%
rename from pyrogram/client/methods/decorators/on_raw_update.py
rename to pyrogram/methods/decorators/on_raw_update.py
index 749b9b5401..9e3a7cd847 100644
--- a/pyrogram/client/methods/decorators/on_raw_update.py
+++ b/pyrogram/methods/decorators/on_raw_update.py
@@ -19,17 +19,18 @@
from typing import Callable
import pyrogram
-from ...ext import BaseClient
+from pyrogram.scaffold import Scaffold
-class OnRawUpdate(BaseClient):
+class OnRawUpdate(Scaffold):
def on_raw_update(
self=None,
group: int = 0
) -> callable:
"""Decorator for handling raw updates.
- This does the same thing as :meth:`~pyrogram.Client.add_handler` using the :obj:`~pyrogram.RawUpdateHandler`.
+ This does the same thing as :meth:`~pyrogram.Client.add_handler` using the
+ :obj:`~pyrogram.handlers.RawUpdateHandler`.
Parameters:
group (``int``, *optional*):
@@ -38,10 +39,10 @@ def on_raw_update(
def decorator(func: Callable) -> Callable:
if isinstance(self, pyrogram.Client):
- self.add_handler(pyrogram.RawUpdateHandler(func), group)
+ self.add_handler(pyrogram.handlers.RawUpdateHandler(func), group)
else:
func.handler = (
- pyrogram.RawUpdateHandler(func),
+ pyrogram.handlers.RawUpdateHandler(func),
group if self is None else group
)
diff --git a/pyrogram/client/methods/decorators/on_user_status.py b/pyrogram/methods/decorators/on_user_status.py
similarity index 83%
rename from pyrogram/client/methods/decorators/on_user_status.py
rename to pyrogram/methods/decorators/on_user_status.py
index ea09c8a495..3063ad3d48 100644
--- a/pyrogram/client/methods/decorators/on_user_status.py
+++ b/pyrogram/methods/decorators/on_user_status.py
@@ -19,18 +19,19 @@
from typing import Callable
import pyrogram
-from pyrogram.client.filters.filter import Filter
-from ...ext import BaseClient
+from pyrogram.filters import Filter
+from pyrogram.scaffold import Scaffold
-class OnUserStatus(BaseClient):
+class OnUserStatus(Scaffold):
def on_user_status(
self=None,
filters=None,
group: int = 0
) -> callable:
"""Decorator for handling user status updates.
- This does the same thing as :meth:`~pyrogram.Client.add_handler` using the :obj:`~pyrogram.UserStatusHandler`.
+ This does the same thing as :meth:`~pyrogram.Client.add_handler` using the
+ :obj:`~pyrogram.handlers.UserStatusHandler`.
Parameters:
filters (:obj:`~pyrogram.Filters`, *optional*):
@@ -42,10 +43,10 @@ def on_user_status(
def decorator(func: Callable) -> Callable:
if isinstance(self, pyrogram.Client):
- self.add_handler(pyrogram.UserStatusHandler(func, filters), group)
+ self.add_handler(pyrogram.handlers.UserStatusHandler(func, filters), group)
elif isinstance(self, Filter) or self is None:
func.handler = (
- pyrogram.UserStatusHandler(func, self),
+ pyrogram.handlers.UserStatusHandler(func, self),
group if filters is None else filters
)
diff --git a/pyrogram/client/methods/messages/__init__.py b/pyrogram/methods/messages/__init__.py
similarity index 100%
rename from pyrogram/client/methods/messages/__init__.py
rename to pyrogram/methods/messages/__init__.py
diff --git a/pyrogram/client/methods/messages/delete_messages.py b/pyrogram/methods/messages/delete_messages.py
similarity index 86%
rename from pyrogram/client/methods/messages/delete_messages.py
rename to pyrogram/methods/messages/delete_messages.py
index 5deb6d5aa8..1855ce9bc7 100644
--- a/pyrogram/client/methods/messages/delete_messages.py
+++ b/pyrogram/methods/messages/delete_messages.py
@@ -18,15 +18,15 @@
from typing import Union, Iterable
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class DeleteMessages(BaseClient):
+class DeleteMessages(Scaffold):
async def delete_messages(
self,
chat_id: Union[int, str],
- message_ids: Iterable[int],
+ message_ids: Union[int, Iterable[int]],
revoke: bool = True
) -> bool:
"""Delete messages, including service messages.
@@ -37,8 +37,8 @@ async def delete_messages(
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
- message_ids (``iterable``):
- A list of Message identifiers to delete or a single message id.
+ message_ids (``int`` | ``Iterable[int]``):
+ A list of Message identifiers to delete (integers) or a single message id.
Iterators and Generators are also accepted.
revoke (``bool``, *optional*):
@@ -65,16 +65,16 @@ async def delete_messages(
peer = await self.resolve_peer(chat_id)
message_ids = list(message_ids) if not isinstance(message_ids, int) else [message_ids]
- if isinstance(peer, types.InputPeerChannel):
+ if isinstance(peer, raw.types.InputPeerChannel):
r = await self.send(
- functions.channels.DeleteMessages(
+ raw.functions.channels.DeleteMessages(
channel=peer,
id=message_ids
)
)
else:
r = await self.send(
- functions.messages.DeleteMessages(
+ raw.functions.messages.DeleteMessages(
id=message_ids,
revoke=revoke or None
)
diff --git a/pyrogram/client/methods/messages/download_media.py b/pyrogram/methods/messages/download_media.py
similarity index 84%
rename from pyrogram/client/methods/messages/download_media.py
rename to pyrogram/methods/messages/download_media.py
index 3c1a8cbeb3..24092caca7 100644
--- a/pyrogram/client/methods/messages/download_media.py
+++ b/pyrogram/methods/messages/download_media.py
@@ -22,20 +22,45 @@
import struct
import time
from datetime import datetime
-from threading import Event
from typing import Union
-import pyrogram
-from pyrogram.client.ext import BaseClient, FileData, utils
+from pyrogram import types
+from pyrogram import utils
from pyrogram.errors import FileIdInvalid
+from pyrogram.scaffold import Scaffold
DEFAULT_DOWNLOAD_DIR = "downloads/"
-class DownloadMedia(BaseClient):
+class FileData:
+ def __init__(
+ self, *, media_type: int = None, dc_id: int = None, document_id: int = None, access_hash: int = None,
+ thumb_size: str = None, peer_id: int = None, peer_type: str = None, peer_access_hash: int = None,
+ volume_id: int = None, local_id: int = None, is_big: bool = None, file_size: int = None, mime_type: str = None,
+ file_name: str = None, date: int = None, file_ref: str = None
+ ):
+ self.media_type = media_type
+ self.dc_id = dc_id
+ self.document_id = document_id
+ self.access_hash = access_hash
+ self.thumb_size = thumb_size
+ self.peer_id = peer_id
+ self.peer_type = peer_type
+ self.peer_access_hash = peer_access_hash
+ self.volume_id = volume_id
+ self.local_id = local_id
+ self.is_big = is_big
+ self.file_size = file_size
+ self.mime_type = mime_type
+ self.file_name = file_name
+ self.date = date
+ self.file_ref = file_ref
+
+
+class DownloadMedia(Scaffold):
async def download_media(
self,
- message: Union["pyrogram.Message", str],
+ message: Union["types.Message", str],
file_ref: str = None,
file_name: str = DEFAULT_DOWNLOAD_DIR,
block: bool = True,
@@ -45,7 +70,7 @@ async def download_media(
"""Download the media from a message.
Parameters:
- message (:obj:`Message` | ``str``):
+ message (:obj:`~pyrogram.types.Message` | ``str``):
Pass a Message containing the media, the media itself (message.audio, message.video, ...) or
the file id as string.
@@ -87,7 +112,8 @@ async def download_media(
Returns:
``str`` | ``None``: On success, the absolute path of the downloaded file is returned, otherwise, in case
- the download failed or was deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
+ the download failed or was deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is
+ returned.
Raises:
ValueError: if the message doesn't contain any downloadable media
@@ -103,7 +129,7 @@ async def download_media(
# Keep track of the progress while downloading
def progress(current, total):
- print("{:.1f}%".format(current * 100 / total))
+ print(f"{current * 100 / total:.1f}%")
app.download_media(message, progress=progress)
"""
@@ -115,7 +141,7 @@ def progress(current, total):
mime_type = None
date = None
- if isinstance(message, pyrogram.Message):
+ if isinstance(message, types.Message):
for kind in available_media:
media = getattr(message, kind, None)
@@ -199,13 +225,10 @@ def get_existing_attributes() -> dict:
access_hash=access_hash
)
else:
- raise ValueError("Unknown media type: {}".format(file_id_str))
+ raise ValueError(f"Unknown media type: {file_id_str}")
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
- done = asyncio.Event()
- path = [None]
-
directory, file_name = os.path.split(file_name)
file_name = file_name or data.file_name or ""
@@ -239,10 +262,9 @@ def get_existing_attributes() -> dict:
extension
)
- # Cast to string because Path objects aren't supported by Python 3.5
- self.download_queue.put_nowait((data, str(directory), str(file_name), done, progress, progress_args, path))
+ downloader = self.handle_download((data, directory, file_name, progress, progress_args))
if block:
- await done.wait()
-
- return path[0]
+ return await downloader
+ else:
+ asyncio.get_event_loop().create_task(downloader)
diff --git a/pyrogram/client/methods/messages/edit_inline_caption.py b/pyrogram/methods/messages/edit_inline_caption.py
similarity index 89%
rename from pyrogram/client/methods/messages/edit_inline_caption.py
rename to pyrogram/methods/messages/edit_inline_caption.py
index 335f878eb7..055303b41e 100644
--- a/pyrogram/client/methods/messages/edit_inline_caption.py
+++ b/pyrogram/methods/messages/edit_inline_caption.py
@@ -18,17 +18,17 @@
from typing import Union
-import pyrogram
-from pyrogram.client.ext import BaseClient
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class EditInlineCaption(BaseClient):
+class EditInlineCaption(Scaffold):
async def edit_inline_caption(
self,
inline_message_id: str,
caption: str,
parse_mode: Union[str, None] = object,
- reply_markup: "pyrogram.InlineKeyboardMarkup" = None
+ reply_markup: "types.InlineKeyboardMarkup" = None
) -> bool:
"""Edit the caption of inline media messages.
@@ -46,7 +46,7 @@ async def edit_inline_caption(
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
diff --git a/pyrogram/client/methods/messages/edit_inline_media.py b/pyrogram/methods/messages/edit_inline_media.py
similarity index 76%
rename from pyrogram/client/methods/messages/edit_inline_media.py
rename to pyrogram/methods/messages/edit_inline_media.py
index 74cb29108b..76b716f1ab 100644
--- a/pyrogram/client/methods/messages/edit_inline_media.py
+++ b/pyrogram/methods/messages/edit_inline_media.py
@@ -18,22 +18,18 @@
import re
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
-from pyrogram.client.types import (
- InputMediaPhoto, InputMediaVideo, InputMediaAudio,
- InputMediaAnimation, InputMediaDocument
-)
-from pyrogram.client.types.input_media import InputMedia
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
-class EditInlineMedia(BaseClient):
+class EditInlineMedia(Scaffold):
async def edit_inline_media(
self,
inline_message_id: str,
- media: InputMedia,
- reply_markup: "pyrogram.InlineKeyboardMarkup" = None
+ media: "types.InputMedia",
+ reply_markup: "types.InlineKeyboardMarkup" = None
) -> bool:
"""Edit inline animation, audio, document, photo or video messages.
@@ -45,10 +41,10 @@ async def edit_inline_media(
Required if *chat_id* and *message_id* are not specified.
Identifier of the inline message.
- media (:obj:`InputMedia`):
+ media (:obj:`~pyrogram.types.InputMedia`):
One of the InputMedia objects describing an animation, audio, document, photo or video.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
@@ -73,44 +69,44 @@ async def edit_inline_media(
caption = media.caption
parse_mode = media.parse_mode
- if isinstance(media, InputMediaPhoto):
+ if isinstance(media, types.InputMediaPhoto):
if re.match("^https?://", media.media):
- media = types.InputMediaPhotoExternal(
+ media = raw.types.InputMediaPhotoExternal(
url=media.media
)
else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 2)
- elif isinstance(media, InputMediaVideo):
+ elif isinstance(media, types.InputMediaVideo):
if re.match("^https?://", media.media):
- media = types.InputMediaDocumentExternal(
+ media = raw.types.InputMediaDocumentExternal(
url=media.media
)
else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 4)
- elif isinstance(media, InputMediaAudio):
+ elif isinstance(media, types.InputMediaAudio):
if re.match("^https?://", media.media):
- media = types.InputMediaDocumentExternal(
+ media = raw.types.InputMediaDocumentExternal(
url=media.media
)
else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 9)
- elif isinstance(media, InputMediaAnimation):
+ elif isinstance(media, types.InputMediaAnimation):
if re.match("^https?://", media.media):
- media = types.InputMediaDocumentExternal(
+ media = raw.types.InputMediaDocumentExternal(
url=media.media
)
else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 10)
- elif isinstance(media, InputMediaDocument):
+ elif isinstance(media, types.InputMediaDocument):
if re.match("^https?://", media.media):
- media = types.InputMediaDocumentExternal(
+ media = raw.types.InputMediaDocumentExternal(
url=media.media
)
else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 5)
return await self.send(
- functions.messages.EditInlineBotMessage(
+ raw.functions.messages.EditInlineBotMessage(
id=utils.unpack_inline_message_id(inline_message_id),
media=media,
reply_markup=reply_markup.write() if reply_markup else None,
diff --git a/pyrogram/client/methods/messages/edit_inline_reply_markup.py b/pyrogram/methods/messages/edit_inline_reply_markup.py
similarity index 83%
rename from pyrogram/client/methods/messages/edit_inline_reply_markup.py
rename to pyrogram/methods/messages/edit_inline_reply_markup.py
index f538180641..5d1b24635b 100644
--- a/pyrogram/client/methods/messages/edit_inline_reply_markup.py
+++ b/pyrogram/methods/messages/edit_inline_reply_markup.py
@@ -16,16 +16,17 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-import pyrogram
-from pyrogram.api import functions
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
-class EditInlineReplyMarkup(BaseClient):
+class EditInlineReplyMarkup(Scaffold):
async def edit_inline_reply_markup(
self,
inline_message_id: str,
- reply_markup: "pyrogram.InlineKeyboardMarkup" = None
+ reply_markup: "types.InlineKeyboardMarkup" = None
) -> bool:
"""Edit only the reply markup of inline messages sent via the bot (for inline bots).
@@ -33,7 +34,7 @@ async def edit_inline_reply_markup(
inline_message_id (``str``):
Identifier of the inline message.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
@@ -51,7 +52,7 @@ async def edit_inline_reply_markup(
InlineKeyboardButton("New button", callback_data="new_data")]]))
"""
return await self.send(
- functions.messages.EditInlineBotMessage(
+ raw.functions.messages.EditInlineBotMessage(
id=utils.unpack_inline_message_id(inline_message_id),
reply_markup=reply_markup.write() if reply_markup else None,
)
diff --git a/pyrogram/client/methods/messages/edit_inline_text.py b/pyrogram/methods/messages/edit_inline_text.py
similarity index 88%
rename from pyrogram/client/methods/messages/edit_inline_text.py
rename to pyrogram/methods/messages/edit_inline_text.py
index cfdd232ba9..ebb2f91a81 100644
--- a/pyrogram/client/methods/messages/edit_inline_text.py
+++ b/pyrogram/methods/messages/edit_inline_text.py
@@ -18,19 +18,20 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
-class EditInlineText(BaseClient):
+class EditInlineText(Scaffold):
async def edit_inline_text(
self,
inline_message_id: str,
text: str,
parse_mode: Union[str, None] = object,
disable_web_page_preview: bool = None,
- reply_markup: "pyrogram.InlineKeyboardMarkup" = None
+ reply_markup: "types.InlineKeyboardMarkup" = None
) -> bool:
"""Edit the text of inline messages.
@@ -51,7 +52,7 @@ async def edit_inline_text(
disable_web_page_preview (``bool``, *optional*):
Disables link previews for links in this message.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
@@ -72,7 +73,7 @@ async def edit_inline_text(
"""
return await self.send(
- functions.messages.EditInlineBotMessage(
+ raw.functions.messages.EditInlineBotMessage(
id=utils.unpack_inline_message_id(inline_message_id),
no_webpage=disable_web_page_preview or None,
reply_markup=reply_markup.write() if reply_markup else None,
diff --git a/pyrogram/client/methods/messages/edit_message_caption.py b/pyrogram/methods/messages/edit_message_caption.py
similarity index 87%
rename from pyrogram/client/methods/messages/edit_message_caption.py
rename to pyrogram/methods/messages/edit_message_caption.py
index 01bd81474a..76b6cc483d 100644
--- a/pyrogram/client/methods/messages/edit_message_caption.py
+++ b/pyrogram/methods/messages/edit_message_caption.py
@@ -18,19 +18,19 @@
from typing import Union
-import pyrogram
-from pyrogram.client.ext import BaseClient
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class EditMessageCaption(BaseClient):
+class EditMessageCaption(Scaffold):
async def edit_message_caption(
self,
chat_id: Union[int, str],
message_id: int,
caption: str,
parse_mode: Union[str, None] = object,
- reply_markup: "pyrogram.InlineKeyboardMarkup" = None
- ) -> "pyrogram.Message":
+ reply_markup: "types.InlineKeyboardMarkup" = None
+ ) -> "types.Message":
"""Edit the caption of media messages.
Parameters:
@@ -52,11 +52,11 @@ async def edit_message_caption(
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
- :obj:`Message`: On success, the edited message is returned.
+ :obj:`~pyrogram.types.Message`: On success, the edited message is returned.
Example:
.. code-block:: python
diff --git a/pyrogram/client/methods/messages/edit_message_media.py b/pyrogram/methods/messages/edit_message_media.py
similarity index 74%
rename from pyrogram/client/methods/messages/edit_message_media.py
rename to pyrogram/methods/messages/edit_message_media.py
index 765c159842..5733c5bda6 100644
--- a/pyrogram/client/methods/messages/edit_message_media.py
+++ b/pyrogram/methods/messages/edit_message_media.py
@@ -20,25 +20,21 @@
import re
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
-from pyrogram.client.types import (
- InputMediaPhoto, InputMediaVideo, InputMediaAudio,
- InputMediaAnimation, InputMediaDocument
-)
-from pyrogram.client.types.input_media import InputMedia
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
-class EditMessageMedia(BaseClient):
+class EditMessageMedia(Scaffold):
async def edit_message_media(
self,
chat_id: Union[int, str],
message_id: int,
- media: InputMedia,
- reply_markup: "pyrogram.InlineKeyboardMarkup" = None,
+ media: "types.InputMedia",
+ reply_markup: "types.InlineKeyboardMarkup" = None,
file_name: str = None
- ) -> "pyrogram.Message":
+ ) -> "types.Message":
"""Edit animation, audio, document, photo or video messages.
If a message is a part of a message album, then it can be edited only to a photo or a video. Otherwise, the
@@ -53,10 +49,10 @@ async def edit_message_media(
message_id (``int``):
Message identifier in the chat specified in chat_id.
- media (:obj:`InputMedia`):
+ media (:obj:`~pyrogram.types.InputMedia`):
One of the InputMedia objects describing an animation, audio, document, photo or video.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
file_name (``str``, *optional*):
@@ -64,7 +60,7 @@ async def edit_message_media(
Defaults to file's path basename.
Returns:
- :obj:`Message`: On success, the edited message is returned.
+ :obj:`~pyrogram.types.Message`: On success, the edited message is returned.
Example:
.. code-block:: python
@@ -83,47 +79,47 @@ async def edit_message_media(
caption = media.caption
parse_mode = media.parse_mode
- if isinstance(media, InputMediaPhoto):
+ if isinstance(media, types.InputMediaPhoto):
if os.path.isfile(media.media):
media = await self.send(
- functions.messages.UploadMedia(
+ raw.functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id),
- media=types.InputMediaUploadedPhoto(
+ media=raw.types.InputMediaUploadedPhoto(
file=await self.save_file(media.media)
)
)
)
- media = types.InputMediaPhoto(
- id=types.InputPhoto(
+ media = raw.types.InputMediaPhoto(
+ id=raw.types.InputPhoto(
id=media.photo.id,
access_hash=media.photo.access_hash,
file_reference=media.photo.file_reference
)
)
elif re.match("^https?://", media.media):
- media = types.InputMediaPhotoExternal(
+ media = raw.types.InputMediaPhotoExternal(
url=media.media
)
else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 2)
- elif isinstance(media, InputMediaVideo):
+ elif isinstance(media, types.InputMediaVideo):
if os.path.isfile(media.media):
media = await self.send(
- functions.messages.UploadMedia(
+ raw.functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id),
- media=types.InputMediaUploadedDocument(
+ media=raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(media.media) or "video/mp4",
thumb=await self.save_file(media.thumb),
file=await self.save_file(media.media),
attributes=[
- types.DocumentAttributeVideo(
+ raw.types.DocumentAttributeVideo(
supports_streaming=media.supports_streaming or None,
duration=media.duration,
w=media.width,
h=media.height
),
- types.DocumentAttributeFilename(
+ raw.types.DocumentAttributeFilename(
file_name=file_name or os.path.basename(media.media)
)
]
@@ -131,35 +127,35 @@ async def edit_message_media(
)
)
- media = types.InputMediaDocument(
- id=types.InputDocument(
+ media = raw.types.InputMediaDocument(
+ id=raw.types.InputDocument(
id=media.document.id,
access_hash=media.document.access_hash,
file_reference=media.document.file_reference
)
)
elif re.match("^https?://", media.media):
- media = types.InputMediaDocumentExternal(
+ media = raw.types.InputMediaDocumentExternal(
url=media.media
)
else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 4)
- elif isinstance(media, InputMediaAudio):
+ elif isinstance(media, types.InputMediaAudio):
if os.path.isfile(media.media):
media = await self.send(
- functions.messages.UploadMedia(
+ raw.functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id),
- media=types.InputMediaUploadedDocument(
+ media=raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(media.media) or "audio/mpeg",
thumb=await self.save_file(media.thumb),
file=await self.save_file(media.media),
attributes=[
- types.DocumentAttributeAudio(
+ raw.types.DocumentAttributeAudio(
duration=media.duration,
performer=media.performer,
title=media.title
),
- types.DocumentAttributeFilename(
+ raw.types.DocumentAttributeFilename(
file_name=file_name or os.path.basename(media.media)
)
]
@@ -167,68 +163,68 @@ async def edit_message_media(
)
)
- media = types.InputMediaDocument(
- id=types.InputDocument(
+ media = raw.types.InputMediaDocument(
+ id=raw.types.InputDocument(
id=media.document.id,
access_hash=media.document.access_hash,
file_reference=media.document.file_reference
)
)
elif re.match("^https?://", media.media):
- media = types.InputMediaDocumentExternal(
+ media = raw.types.InputMediaDocumentExternal(
url=media.media
)
else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 9)
- elif isinstance(media, InputMediaAnimation):
+ elif isinstance(media, types.InputMediaAnimation):
if os.path.isfile(media.media):
media = await self.send(
- functions.messages.UploadMedia(
+ raw.functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id),
- media=types.InputMediaUploadedDocument(
+ media=raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(media.media) or "video/mp4",
- thumb=self.save_file(media.thumb),
+ thumb=await self.save_file(media.thumb),
file=await self.save_file(media.media),
attributes=[
- types.DocumentAttributeVideo(
+ raw.types.DocumentAttributeVideo(
supports_streaming=True,
duration=media.duration,
w=media.width,
h=media.height
),
- types.DocumentAttributeFilename(
+ raw.types.DocumentAttributeFilename(
file_name=file_name or os.path.basename(media.media)
),
- types.DocumentAttributeAnimated()
+ raw.types.DocumentAttributeAnimated()
]
)
)
)
- media = types.InputMediaDocument(
- id=types.InputDocument(
+ media = raw.types.InputMediaDocument(
+ id=raw.types.InputDocument(
id=media.document.id,
access_hash=media.document.access_hash,
file_reference=media.document.file_reference
)
)
elif re.match("^https?://", media.media):
- media = types.InputMediaDocumentExternal(
+ media = raw.types.InputMediaDocumentExternal(
url=media.media
)
else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 10)
- elif isinstance(media, InputMediaDocument):
+ elif isinstance(media, types.InputMediaDocument):
if os.path.isfile(media.media):
media = await self.send(
- functions.messages.UploadMedia(
+ raw.functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id),
- media=types.InputMediaUploadedDocument(
+ media=raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(media.media) or "application/zip",
thumb=await self.save_file(media.thumb),
file=await self.save_file(media.media),
attributes=[
- types.DocumentAttributeFilename(
+ raw.types.DocumentAttributeFilename(
file_name=file_name or os.path.basename(media.media)
)
]
@@ -236,22 +232,22 @@ async def edit_message_media(
)
)
- media = types.InputMediaDocument(
- id=types.InputDocument(
+ media = raw.types.InputMediaDocument(
+ id=raw.types.InputDocument(
id=media.document.id,
access_hash=media.document.access_hash,
file_reference=media.document.file_reference
)
)
elif re.match("^https?://", media.media):
- media = types.InputMediaDocumentExternal(
+ media = raw.types.InputMediaDocumentExternal(
url=media.media
)
else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 5)
r = await self.send(
- functions.messages.EditMessage(
+ raw.functions.messages.EditMessage(
peer=await self.resolve_peer(chat_id),
id=message_id,
media=media,
@@ -261,8 +257,8 @@ async def edit_message_media(
)
for i in r.updates:
- if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateEditMessage, raw.types.UpdateEditChannelMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/edit_message_reply_markup.py b/pyrogram/methods/messages/edit_message_reply_markup.py
similarity index 79%
rename from pyrogram/client/methods/messages/edit_message_reply_markup.py
rename to pyrogram/methods/messages/edit_message_reply_markup.py
index 65fa26e221..43d870adcc 100644
--- a/pyrogram/client/methods/messages/edit_message_reply_markup.py
+++ b/pyrogram/methods/messages/edit_message_reply_markup.py
@@ -18,18 +18,18 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class EditMessageReplyMarkup(BaseClient):
+class EditMessageReplyMarkup(Scaffold):
async def edit_message_reply_markup(
self,
chat_id: Union[int, str],
message_id: int,
- reply_markup: "pyrogram.InlineKeyboardMarkup" = None,
- ) -> "pyrogram.Message":
+ reply_markup: "types.InlineKeyboardMarkup" = None,
+ ) -> "types.Message":
"""Edit only the reply markup of messages sent by the bot.
Parameters:
@@ -41,11 +41,11 @@ async def edit_message_reply_markup(
message_id (``int``):
Message identifier in the chat specified in chat_id.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
- :obj:`Message`: On success, the edited message is returned.
+ :obj:`~pyrogram.types.Message`: On success, the edited message is returned.
Example:
.. code-block:: python
@@ -59,7 +59,7 @@ async def edit_message_reply_markup(
InlineKeyboardButton("New button", callback_data="new_data")]]))
"""
r = await self.send(
- functions.messages.EditMessage(
+ raw.functions.messages.EditMessage(
peer=await self.resolve_peer(chat_id),
id=message_id,
reply_markup=reply_markup.write() if reply_markup else None,
@@ -67,8 +67,8 @@ async def edit_message_reply_markup(
)
for i in r.updates:
- if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateEditMessage, raw.types.UpdateEditChannelMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/edit_message_text.py b/pyrogram/methods/messages/edit_message_text.py
similarity index 84%
rename from pyrogram/client/methods/messages/edit_message_text.py
rename to pyrogram/methods/messages/edit_message_text.py
index a2b43f1681..b7d8483054 100644
--- a/pyrogram/client/methods/messages/edit_message_text.py
+++ b/pyrogram/methods/messages/edit_message_text.py
@@ -18,12 +18,12 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class EditMessageText(BaseClient):
+class EditMessageText(Scaffold):
async def edit_message_text(
self,
chat_id: Union[int, str],
@@ -31,8 +31,8 @@ async def edit_message_text(
text: str,
parse_mode: Union[str, None] = object,
disable_web_page_preview: bool = None,
- reply_markup: "pyrogram.InlineKeyboardMarkup" = None
- ) -> "pyrogram.Message":
+ reply_markup: "types.InlineKeyboardMarkup" = None
+ ) -> "types.Message":
"""Edit the text of messages.
Parameters:
@@ -57,11 +57,11 @@ async def edit_message_text(
disable_web_page_preview (``bool``, *optional*):
Disables link previews for links in this message.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
- :obj:`Message`: On success, the edited message is returned.
+ :obj:`~pyrogram.types.Message`: On success, the edited message is returned.
Example:
.. code-block:: python
@@ -76,7 +76,7 @@ async def edit_message_text(
"""
r = await self.send(
- functions.messages.EditMessage(
+ raw.functions.messages.EditMessage(
peer=await self.resolve_peer(chat_id),
id=message_id,
no_webpage=disable_web_page_preview or None,
@@ -86,8 +86,8 @@ async def edit_message_text(
)
for i in r.updates:
- if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateEditMessage, raw.types.UpdateEditChannelMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
diff --git a/pyrogram/client/methods/messages/forward_messages.py b/pyrogram/methods/messages/forward_messages.py
similarity index 83%
rename from pyrogram/client/methods/messages/forward_messages.py
rename to pyrogram/methods/messages/forward_messages.py
index c7f47a5248..5287a4ced9 100644
--- a/pyrogram/client/methods/messages/forward_messages.py
+++ b/pyrogram/methods/messages/forward_messages.py
@@ -18,13 +18,12 @@
from typing import Union, Iterable, List
-import pyrogram
-from pyrogram.api import functions, types
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-from ...ext import BaseClient
-
-class ForwardMessages(BaseClient):
+class ForwardMessages(Scaffold):
async def forward_messages(
self,
chat_id: Union[int, str],
@@ -34,7 +33,7 @@ async def forward_messages(
as_copy: bool = False,
remove_caption: bool = False,
schedule_date: int = None
- ) -> List["pyrogram.Message"]:
+ ) -> List["types.Message"]:
"""Forward messages of any kind.
Parameters:
@@ -70,9 +69,9 @@ async def forward_messages(
Date when the message will be automatically sent. Unix time.
Returns:
- :obj:`Message` | List of :obj:`Message`: In case *message_ids* was an integer, the single forwarded message
- is returned, otherwise, in case *message_ids* was an iterable, the returned value will be a list of
- messages, even if such iterable contained just a single element.
+ :obj:`~pyrogram.types.Message` | List of :obj:`~pyrogram.types.Message`: In case *message_ids* was an
+ integer, the single forwarded message is returned, otherwise, in case *message_ids* was an iterable,
+ the returned value will be a list of messages, even if such iterable contained just a single element.
Example:
.. code-block:: python
@@ -108,10 +107,10 @@ async def forward_messages(
)
)
- return pyrogram.List(forwarded_messages) if is_iterable else forwarded_messages[0]
+ return types.List(forwarded_messages) if is_iterable else forwarded_messages[0]
else:
r = await self.send(
- functions.messages.ForwardMessages(
+ raw.functions.messages.ForwardMessages(
to_peer=await self.resolve_peer(chat_id),
from_peer=await self.resolve_peer(from_chat_id),
id=message_ids,
@@ -127,12 +126,14 @@ async def forward_messages(
chats = {i.id: i for i in r.chats}
for i in r.updates:
- if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)):
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
forwarded_messages.append(
- await pyrogram.Message._parse(
+ await types.Message._parse(
self, i.message,
users, chats
)
)
- return pyrogram.List(forwarded_messages) if is_iterable else forwarded_messages[0]
+ return types.List(forwarded_messages) if is_iterable else forwarded_messages[0]
diff --git a/pyrogram/client/methods/messages/get_history.py b/pyrogram/methods/messages/get_history.py
similarity index 90%
rename from pyrogram/client/methods/messages/get_history.py
rename to pyrogram/methods/messages/get_history.py
index 92a84d9bf5..00c9f435df 100644
--- a/pyrogram/client/methods/messages/get_history.py
+++ b/pyrogram/methods/messages/get_history.py
@@ -16,19 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-import asyncio
import logging
from typing import Union, List
-import pyrogram
-from pyrogram.api import functions
-from pyrogram.client.ext import utils
-from ...ext import BaseClient
+from pyrogram import raw
+# from pyrogram import types
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
log = logging.getLogger(__name__)
-class GetHistory(BaseClient):
+class GetHistory(Scaffold):
async def get_history(
self,
chat_id: Union[int, str],
@@ -37,11 +36,11 @@ async def get_history(
offset_id: int = 0,
offset_date: int = 0,
reverse: bool = False
- ) -> List["pyrogram.Message"]:
+ ) -> List["types.Message"]:
"""Retrieve a chunk of the history of a chat.
You can get up to 100 messages at once.
- For a more convenient way of getting a chat history see :meth:`~Client.iter_history`.
+ For a more convenient way of getting a chat history see :meth:`~pyrogram.Client.iter_history`.
Parameters:
chat_id (``int`` | ``str``):
@@ -67,7 +66,7 @@ async def get_history(
Pass True to retrieve the messages in reversed order (from older to most recent).
Returns:
- List of :obj:`Message` - On success, a list of the retrieved messages is returned.
+ List of :obj:`~pyrogram.types.Message` - On success, a list of the retrieved messages is returned.
Example:
.. code-block:: python
@@ -87,7 +86,7 @@ async def get_history(
messages = await utils.parse_messages(
self,
await self.send(
- functions.messages.GetHistory(
+ raw.functions.messages.GetHistory(
peer=await self.resolve_peer(chat_id),
offset_id=offset_id,
offset_date=offset_date,
diff --git a/pyrogram/client/methods/messages/get_history_count.py b/pyrogram/methods/messages/get_history_count.py
similarity index 90%
rename from pyrogram/client/methods/messages/get_history_count.py
rename to pyrogram/methods/messages/get_history_count.py
index d7476f95c2..e08bf027fc 100644
--- a/pyrogram/client/methods/messages/get_history_count.py
+++ b/pyrogram/methods/messages/get_history_count.py
@@ -19,13 +19,13 @@
import logging
from typing import Union
-from pyrogram.api import types, functions
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
log = logging.getLogger(__name__)
-class GetHistoryCount(BaseClient):
+class GetHistoryCount(Scaffold):
async def get_history_count(
self,
chat_id: Union[int, str]
@@ -52,7 +52,7 @@ async def get_history_count(
"""
r = await self.send(
- functions.messages.GetHistory(
+ raw.functions.messages.GetHistory(
peer=await self.resolve_peer(chat_id),
offset_id=0,
offset_date=0,
@@ -64,7 +64,7 @@ async def get_history_count(
)
)
- if isinstance(r, types.messages.Messages):
+ if isinstance(r, raw.types.messages.Messages):
return len(r.messages)
else:
return r.count
diff --git a/pyrogram/client/methods/messages/get_messages.py b/pyrogram/methods/messages/get_messages.py
similarity index 81%
rename from pyrogram/client/methods/messages/get_messages.py
rename to pyrogram/methods/messages/get_messages.py
index b4199b3070..d99bcb2f95 100644
--- a/pyrogram/client/methods/messages/get_messages.py
+++ b/pyrogram/methods/messages/get_messages.py
@@ -16,13 +16,13 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-import asyncio
import logging
from typing import Union, Iterable, List
-import pyrogram
-from pyrogram.api import functions, types
-from ...ext import BaseClient, utils
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
log = logging.getLogger(__name__)
@@ -30,14 +30,14 @@
# TODO: Rewrite using a flag for replied messages and have message_ids non-optional
-class GetMessages(BaseClient):
+class GetMessages(Scaffold):
async def get_messages(
self,
chat_id: Union[int, str],
message_ids: Union[int, Iterable[int]] = None,
reply_to_message_ids: Union[int, Iterable[int]] = None,
replies: int = 1
- ) -> Union["pyrogram.Message", List["pyrogram.Message"]]:
+ ) -> Union["types.Message", List["types.Message"]]:
"""Get one or more messages from a chat by using message identifiers.
You can retrieve up to 200 messages at once.
@@ -63,9 +63,9 @@ async def get_messages(
Defaults to 1.
Returns:
- :obj:`Message` | List of :obj:`Message`: In case *message_ids* was an integer, the single requested message is
- returned, otherwise, in case *message_ids* was an iterable, the returned value will be a list of messages,
- even if such iterable contained just a single element.
+ :obj:`~pyrogram.types.Message` | List of :obj:`~pyrogram.types.Message`: In case *message_ids* was an
+ integer, the single requested message is returned, otherwise, in case *message_ids* was an iterable, the
+ returned value will be a list of messages, even if such iterable contained just a single element.
Example:
.. code-block:: python
@@ -89,8 +89,8 @@ async def get_messages(
ValueError: In case of invalid arguments.
"""
ids, ids_type = (
- (message_ids, types.InputMessageID) if message_ids
- else (reply_to_message_ids, types.InputMessageReplyTo) if reply_to_message_ids
+ (message_ids, raw.types.InputMessageID) if message_ids
+ else (reply_to_message_ids, raw.types.InputMessageReplyTo) if reply_to_message_ids
else (None, None)
)
@@ -106,10 +106,10 @@ async def get_messages(
if replies < 0:
replies = (1 << 31) - 1
- if isinstance(peer, types.InputPeerChannel):
- rpc = functions.channels.GetMessages(channel=peer, id=ids)
+ if isinstance(peer, raw.types.InputPeerChannel):
+ rpc = raw.functions.channels.GetMessages(channel=peer, id=ids)
else:
- rpc = functions.messages.GetMessages(id=ids)
+ rpc = raw.functions.messages.GetMessages(id=ids)
r = await self.send(rpc)
diff --git a/pyrogram/client/methods/messages/iter_history.py b/pyrogram/methods/messages/iter_history.py
similarity index 88%
rename from pyrogram/client/methods/messages/iter_history.py
rename to pyrogram/methods/messages/iter_history.py
index 04c7dc1a77..6bd3d5815e 100644
--- a/pyrogram/client/methods/messages/iter_history.py
+++ b/pyrogram/methods/messages/iter_history.py
@@ -16,16 +16,13 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from typing import Union, Optional, Generator
+from typing import Union, Optional, AsyncGenerator
-import pyrogram
-from async_generator import async_generator, yield_
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-from ...ext import BaseClient
-
-class IterHistory(BaseClient):
- @async_generator
+class IterHistory(Scaffold):
async def iter_history(
self,
chat_id: Union[int, str],
@@ -34,10 +31,10 @@ async def iter_history(
offset_id: int = 0,
offset_date: int = 0,
reverse: bool = False
- ) -> Optional[Generator["pyrogram.Message", None, None]]:
+ ) -> Optional[AsyncGenerator["types.Message", None]]:
"""Iterate through a chat history sequentially.
- This convenience method does the same as repeatedly calling :meth:`~Client.get_history` in a loop, thus saving
+ This convenience method does the same as repeatedly calling :meth:`~pyrogram.Client.get_history` in a loop, thus saving
you from the hassle of setting up boilerplate code. It is useful for getting the whole chat history with a
single call.
@@ -65,7 +62,7 @@ async def iter_history(
Pass True to retrieve the messages in reversed order (from older to most recent).
Returns:
- ``Generator``: A generator yielding :obj:`Message` objects.
+ ``Generator``: A generator yielding :obj:`~pyrogram.types.Message` objects.
Example:
.. code-block:: python
@@ -94,7 +91,7 @@ async def iter_history(
offset_id = messages[-1].message_id + (1 if reverse else 0)
for message in messages:
- await yield_(message)
+ yield message
current += 1
diff --git a/pyrogram/client/methods/messages/read_history.py b/pyrogram/methods/messages/read_history.py
similarity index 89%
rename from pyrogram/client/methods/messages/read_history.py
rename to pyrogram/methods/messages/read_history.py
index 5e1e265bb3..15f0912870 100644
--- a/pyrogram/client/methods/messages/read_history.py
+++ b/pyrogram/methods/messages/read_history.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class ReadHistory(BaseClient):
+class ReadHistory(Scaffold):
async def read_history(
self,
chat_id: Union[int, str],
@@ -55,13 +55,13 @@ async def read_history(
peer = await self.resolve_peer(chat_id)
- if isinstance(peer, types.InputPeerChannel):
- q = functions.channels.ReadHistory(
+ if isinstance(peer, raw.types.InputPeerChannel):
+ q = raw.functions.channels.ReadHistory(
channel=peer,
max_id=max_id
)
else:
- q = functions.messages.ReadHistory(
+ q = raw.functions.messages.ReadHistory(
peer=peer,
max_id=max_id
)
diff --git a/pyrogram/client/methods/messages/retract_vote.py b/pyrogram/methods/messages/retract_vote.py
similarity index 83%
rename from pyrogram/client/methods/messages/retract_vote.py
rename to pyrogram/methods/messages/retract_vote.py
index 191c8c7539..add319c72b 100644
--- a/pyrogram/client/methods/messages/retract_vote.py
+++ b/pyrogram/methods/messages/retract_vote.py
@@ -18,17 +18,17 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class RetractVote(BaseClient):
+class RetractVote(Scaffold):
async def retract_vote(
self,
chat_id: Union[int, str],
message_id: int
- ) -> "pyrogram.Poll":
+ ) -> "types.Poll":
"""Retract your vote in a poll.
Parameters:
@@ -41,7 +41,7 @@ async def retract_vote(
Identifier of the original message with the poll.
Returns:
- :obj:`Poll`: On success, the poll with the retracted vote is returned.
+ :obj:`~pyrogram.types.Poll`: On success, the poll with the retracted vote is returned.
Example:
.. code-block:: python
@@ -49,11 +49,11 @@ async def retract_vote(
app.retract_vote(chat_id, message_id)
"""
r = await self.send(
- functions.messages.SendVote(
+ raw.functions.messages.SendVote(
peer=await self.resolve_peer(chat_id),
msg_id=message_id,
options=[]
)
)
- return pyrogram.Poll._parse(self, r.updates[0])
+ return types.Poll._parse(self, r.updates[0])
diff --git a/pyrogram/client/methods/messages/search_global.py b/pyrogram/methods/messages/search_global.py
similarity index 83%
rename from pyrogram/client/methods/messages/search_global.py
rename to pyrogram/methods/messages/search_global.py
index 2a889e312e..60c0c752ab 100644
--- a/pyrogram/client/methods/messages/search_global.py
+++ b/pyrogram/methods/messages/search_global.py
@@ -16,22 +16,20 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from typing import Generator, Optional
+from typing import AsyncGenerator, Optional
-from async_generator import async_generator, yield_
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
-
-class SearchGlobal(BaseClient):
- @async_generator
+class SearchGlobal(Scaffold):
async def search_global(
self,
query: str,
limit: int = 0,
- ) -> Optional[Generator["pyrogram.Message", None, None]]:
+ ) -> Optional[AsyncGenerator["types.Message", None]]:
"""Search messages globally from all of your chats.
.. note::
@@ -48,7 +46,7 @@ async def search_global(
By default, no limit is applied and all messages are returned.
Returns:
- ``Generator``: A generator yielding :obj:`Message` objects.
+ ``Generator``: A generator yielding :obj:`~pyrogram.types.Message` objects.
Example:
.. code-block:: python
@@ -63,14 +61,14 @@ async def search_global(
limit = min(100, total)
offset_date = 0
- offset_peer = types.InputPeerEmpty()
+ offset_peer = raw.types.InputPeerEmpty()
offset_id = 0
while True:
messages = await utils.parse_messages(
self,
await self.send(
- functions.messages.SearchGlobal(
+ raw.functions.messages.SearchGlobal(
q=query,
offset_rate=offset_date,
offset_peer=offset_peer,
@@ -91,7 +89,7 @@ async def search_global(
offset_id = last.message_id
for message in messages:
- await yield_(message)
+ yield message
current += 1
diff --git a/pyrogram/client/methods/messages/search_messages.py b/pyrogram/methods/messages/search_messages.py
similarity index 80%
rename from pyrogram/client/methods/messages/search_messages.py
rename to pyrogram/methods/messages/search_messages.py
index bfd56663db..44132dcef0 100644
--- a/pyrogram/client/methods/messages/search_messages.py
+++ b/pyrogram/methods/messages/search_messages.py
@@ -16,31 +16,31 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from typing import Union, List, Generator, Optional
+from typing import Union, List, AsyncGenerator, Optional
-import pyrogram
-from pyrogram.client.ext import BaseClient, utils
-from pyrogram.api import functions, types
-from async_generator import async_generator, yield_
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
class Filters:
- EMPTY = types.InputMessagesFilterEmpty()
- PHOTO = types.InputMessagesFilterPhotos()
- VIDEO = types.InputMessagesFilterVideo()
- PHOTO_VIDEO = types.InputMessagesFilterPhotoVideo()
- DOCUMENT = types.InputMessagesFilterDocument()
- URL = types.InputMessagesFilterUrl()
- ANIMATION = types.InputMessagesFilterGif()
- VOICE_NOTE = types.InputMessagesFilterVoice()
- AUDIO = types.InputMessagesFilterMusic()
- CHAT_PHOTO = types.InputMessagesFilterChatPhotos()
- PHONE_CALL = types.InputMessagesFilterPhoneCalls()
- AUDIO_VIDEO_NOTE = types.InputMessagesFilterRoundVideo()
- VIDEO_NOTE = types.InputMessagesFilterRoundVideo()
- MENTION = types.InputMessagesFilterMyMentions()
- LOCATION = types.InputMessagesFilterGeo()
- CONTACT = types.InputMessagesFilterContacts()
+ EMPTY = raw.types.InputMessagesFilterEmpty()
+ PHOTO = raw.types.InputMessagesFilterPhotos()
+ VIDEO = raw.types.InputMessagesFilterVideo()
+ PHOTO_VIDEO = raw.types.InputMessagesFilterPhotoVideo()
+ DOCUMENT = raw.types.InputMessagesFilterDocument()
+ URL = raw.types.InputMessagesFilterUrl()
+ ANIMATION = raw.types.InputMessagesFilterGif()
+ VOICE_NOTE = raw.types.InputMessagesFilterVoice()
+ AUDIO = raw.types.InputMessagesFilterMusic()
+ CHAT_PHOTO = raw.types.InputMessagesFilterChatPhotos()
+ PHONE_CALL = raw.types.InputMessagesFilterPhoneCalls()
+ AUDIO_VIDEO_NOTE = raw.types.InputMessagesFilterRoundVideo()
+ VIDEO_NOTE = raw.types.InputMessagesFilterRoundVideo()
+ MENTION = raw.types.InputMessagesFilterMyMentions()
+ LOCATION = raw.types.InputMessagesFilterGeo()
+ CONTACT = raw.types.InputMessagesFilterContacts()
POSSIBLE_VALUES = list(map(lambda x: x.lower(), filter(lambda x: not x.startswith("__"), Filters.__dict__.keys())))
@@ -48,22 +48,22 @@ class Filters:
# noinspection PyShadowingBuiltins
async def get_chunk(
- client: BaseClient,
+ client: Scaffold,
chat_id: Union[int, str],
query: str = "",
filter: str = "empty",
offset: int = 0,
limit: int = 100,
from_user: Union[int, str] = None
-) -> List["pyrogram.Message"]:
+) -> List["types.Message"]:
try:
filter = Filters.__dict__[filter.upper()]
except KeyError:
raise ValueError('Invalid filter "{}". Possible values are: {}'.format(
- filter, ", ".join('"{}"'.format(v) for v in POSSIBLE_VALUES))) from None
+ filter, ", ".join(f'"{v}"' for v in POSSIBLE_VALUES))) from None
r = await client.send(
- functions.messages.Search(
+ raw.functions.messages.Search(
peer=await client.resolve_peer(chat_id),
q=query,
filter=filter,
@@ -86,9 +86,8 @@ async def get_chunk(
return await utils.parse_messages(client, r)
-class SearchMessages(BaseClient):
+class SearchMessages(Scaffold):
# noinspection PyShadowingBuiltins
- @async_generator
async def search_messages(
self,
chat_id: Union[int, str],
@@ -97,7 +96,7 @@ async def search_messages(
filter: str = "empty",
limit: int = 0,
from_user: Union[int, str] = None
- ) -> Optional[Generator["pyrogram.Message", None, None]]:
+ ) -> Optional[AsyncGenerator["types.Message", None]]:
"""Search for text and media messages inside a specific chat.
Parameters:
@@ -144,7 +143,7 @@ async def search_messages(
Unique identifier (int) or username (str) of the target user you want to search for messages from.
Returns:
- ``Generator``: A generator yielding :obj:`Message` objects.
+ ``Generator``: A generator yielding :obj:`~pyrogram.types.Message` objects.
Example:
.. code-block:: python
@@ -178,7 +177,7 @@ async def search_messages(
offset += 100
for message in messages:
- await yield_(message)
+ yield message
current += 1
diff --git a/pyrogram/client/methods/messages/send_animation.py b/pyrogram/methods/messages/send_animation.py
similarity index 82%
rename from pyrogram/client/methods/messages/send_animation.py
rename to pyrogram/methods/messages/send_animation.py
index 465622140d..9851c11bef 100644
--- a/pyrogram/client/methods/messages/send_animation.py
+++ b/pyrogram/methods/messages/send_animation.py
@@ -20,13 +20,15 @@
import re
from typing import Union, BinaryIO
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram import StopTransmission
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
from pyrogram.errors import FilePartMissing
+from pyrogram.scaffold import Scaffold
-class SendAnimation(BaseClient):
+class SendAnimation(Scaffold):
async def send_animation(
self,
chat_id: Union[int, str],
@@ -44,14 +46,14 @@ async def send_animation(
reply_to_message_id: int = None,
schedule_date: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
progress: callable = None,
progress_args: tuple = ()
- ) -> Union["pyrogram.Message", None]:
+ ) -> Union["types.Message", None]:
"""Send animation files (animation or H.264/MPEG-4 AVC video without sound).
Parameters:
@@ -114,7 +116,7 @@ async def send_animation(
schedule_date (``int``, *optional*):
Date when the message will be automatically sent. Unix time.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -141,8 +143,9 @@ async def send_animation(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- :obj:`Message` | ``None``: On success, the sent animation message is returned, otherwise, in case the upload
- is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
+ :obj:`~pyrogram.types.Message` | ``None``: On success, the sent animation message is returned, otherwise,
+ in case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is
+ returned.
Example:
.. code-block:: python
@@ -158,7 +161,7 @@ async def send_animation(
# Keep track of the progress while uploading
def progress(current, total):
- print("{:.1f}%".format(current * 100 / total))
+ print(f"{current * 100 / total:.1f}%")
app.send_animation("me", "animation.gif", progress=progress)
"""
@@ -169,23 +172,23 @@ def progress(current, total):
if os.path.isfile(animation):
thumb = await self.save_file(thumb)
file = await self.save_file(animation, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedDocument(
+ media = raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(animation) or "video/mp4",
file=file,
thumb=thumb,
attributes=[
- types.DocumentAttributeVideo(
+ raw.types.DocumentAttributeVideo(
supports_streaming=True,
duration=duration,
w=width,
h=height
),
- types.DocumentAttributeFilename(file_name=file_name or os.path.basename(animation)),
- types.DocumentAttributeAnimated()
+ raw.types.DocumentAttributeFilename(file_name=file_name or os.path.basename(animation)),
+ raw.types.DocumentAttributeAnimated()
]
)
elif re.match("^https?://", animation):
- media = types.InputMediaDocumentExternal(
+ media = raw.types.InputMediaDocumentExternal(
url=animation
)
else:
@@ -193,26 +196,26 @@ def progress(current, total):
else:
thumb = await self.save_file(thumb)
file = await self.save_file(animation, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedDocument(
+ media = raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(animation.name) or "video/mp4",
file=file,
thumb=thumb,
attributes=[
- types.DocumentAttributeVideo(
+ raw.types.DocumentAttributeVideo(
supports_streaming=True,
duration=duration,
w=width,
h=height
),
- types.DocumentAttributeFilename(file_name=animation.name),
- types.DocumentAttributeAnimated()
+ raw.types.DocumentAttributeFilename(file_name=animation.name),
+ raw.types.DocumentAttributeAnimated()
]
)
while True:
try:
r = await self.send(
- functions.messages.SendMedia(
+ raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
media=media,
silent=disable_notification or None,
@@ -227,15 +230,14 @@ def progress(current, total):
await self.save_file(animation, file_id=file.id, file_part=e.x)
else:
for i in r.updates:
- if isinstance(
- i,
- (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)
- ):
- message = await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
+ message = await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
- is_scheduled=isinstance(i, types.UpdateNewScheduledMessage)
+ is_scheduled=isinstance(i, raw.types.UpdateNewScheduledMessage)
)
if unsave:
@@ -243,7 +245,7 @@ def progress(current, total):
document_id = utils.get_input_media_from_file_id(document.file_id, document.file_ref).id
await self.send(
- functions.messages.SaveGif(
+ raw.functions.messages.SaveGif(
id=document_id,
unsave=True
)
@@ -251,5 +253,5 @@ def progress(current, total):
return message
- except BaseClient.StopTransmission:
+ except StopTransmission:
return None
diff --git a/pyrogram/client/methods/messages/send_audio.py b/pyrogram/methods/messages/send_audio.py
similarity index 82%
rename from pyrogram/client/methods/messages/send_audio.py
rename to pyrogram/methods/messages/send_audio.py
index dc460e9744..fc5213cc9a 100644
--- a/pyrogram/client/methods/messages/send_audio.py
+++ b/pyrogram/methods/messages/send_audio.py
@@ -20,13 +20,15 @@
import re
from typing import Union, BinaryIO
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram import StopTransmission
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
from pyrogram.errors import FilePartMissing
+from pyrogram.scaffold import Scaffold
-class SendAudio(BaseClient):
+class SendAudio(Scaffold):
async def send_audio(
self,
chat_id: Union[int, str],
@@ -42,17 +44,17 @@ async def send_audio(
reply_to_message_id: int = None,
schedule_date: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
progress: callable = None,
progress_args: tuple = ()
- ) -> Union["pyrogram.Message", None]:
+ ) -> Union["types.Message", None]:
"""Send audio files.
- For sending voice messages, use the :obj:`send_voice()` method instead.
+ For sending voice messages, use the :meth:`~pyrogram.Client.send_voice` method instead.
Parameters:
chat_id (``int`` | ``str``):
@@ -110,7 +112,7 @@ async def send_audio(
schedule_date (``int``, *optional*):
Date when the message will be automatically sent. Unix time.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -137,8 +139,8 @@ async def send_audio(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- :obj:`Message` | ``None``: On success, the sent audio message is returned, otherwise, in case the upload
- is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
+ :obj:`~pyrogram.types.Message` | ``None``: On success, the sent audio message is returned, otherwise, in
+ case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned.
Example:
.. code-block:: python
@@ -157,7 +159,7 @@ async def send_audio(
# Keep track of the progress while uploading
def progress(current, total):
- print("{:.1f}%".format(current * 100 / total))
+ print(f"{current * 100 / total:.1f}%")
app.send_audio("me", "audio.mp3", progress=progress)
"""
@@ -168,21 +170,21 @@ def progress(current, total):
if os.path.isfile(audio):
thumb = await self.save_file(thumb)
file = await self.save_file(audio, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedDocument(
+ media = raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(audio) or "audio/mpeg",
file=file,
thumb=thumb,
attributes=[
- types.DocumentAttributeAudio(
+ raw.types.DocumentAttributeAudio(
duration=duration,
performer=performer,
title=title
),
- types.DocumentAttributeFilename(file_name=file_name or os.path.basename(audio))
+ raw.types.DocumentAttributeFilename(file_name=file_name or os.path.basename(audio))
]
)
elif re.match("^https?://", audio):
- media = types.InputMediaDocumentExternal(
+ media = raw.types.InputMediaDocumentExternal(
url=audio
)
else:
@@ -190,24 +192,24 @@ def progress(current, total):
else:
thumb = await self.save_file(thumb)
file = await self.save_file(audio, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedDocument(
+ media = raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(audio.name) or "audio/mpeg",
file=file,
thumb=thumb,
attributes=[
- types.DocumentAttributeAudio(
+ raw.types.DocumentAttributeAudio(
duration=duration,
performer=performer,
title=title
),
- types.DocumentAttributeFilename(file_name=audio.name)
+ raw.types.DocumentAttributeFilename(file_name=audio.name)
]
)
while True:
try:
r = await self.send(
- functions.messages.SendMedia(
+ raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
media=media,
silent=disable_notification or None,
@@ -222,15 +224,14 @@ def progress(current, total):
await self.save_file(audio, file_id=file.id, file_part=e.x)
else:
for i in r.updates:
- if isinstance(
- i,
- (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)
- ):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
- is_scheduled=isinstance(i, types.UpdateNewScheduledMessage)
+ is_scheduled=isinstance(i, raw.types.UpdateNewScheduledMessage)
)
- except BaseClient.StopTransmission:
+ except StopTransmission:
return None
diff --git a/pyrogram/client/methods/messages/send_cached_media.py b/pyrogram/methods/messages/send_cached_media.py
similarity index 80%
rename from pyrogram/client/methods/messages/send_cached_media.py
rename to pyrogram/methods/messages/send_cached_media.py
index d550cc279f..3d805c4dc4 100644
--- a/pyrogram/client/methods/messages/send_cached_media.py
+++ b/pyrogram/methods/messages/send_cached_media.py
@@ -18,12 +18,13 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
-class SendCachedMedia(BaseClient):
+class SendCachedMedia(Scaffold):
async def send_cached_media(
self,
chat_id: Union[int, str],
@@ -35,12 +36,12 @@ async def send_cached_media(
reply_to_message_id: int = None,
schedule_date: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None
- ) -> Union["pyrogram.Message", None]:
+ ) -> Union["types.Message", None]:
"""Send any media stored on the Telegram servers using a file_id.
This convenience method works with any valid file_id only.
@@ -81,12 +82,12 @@ async def send_cached_media(
schedule_date (``int``, *optional*):
Date when the message will be automatically sent. Unix time.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
Returns:
- :obj:`Message`: On success, the sent media message is returned.
+ :obj:`~pyrogram.types.Message`: On success, the sent media message is returned.
Example:
.. code-block:: python
@@ -95,7 +96,7 @@ async def send_cached_media(
"""
r = await self.send(
- functions.messages.SendMedia(
+ raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
media=utils.get_input_media_from_file_id(file_id, file_ref),
silent=disable_notification or None,
@@ -108,10 +109,12 @@ async def send_cached_media(
)
for i in r.updates:
- if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
- is_scheduled=isinstance(i, types.UpdateNewScheduledMessage)
+ is_scheduled=isinstance(i, raw.types.UpdateNewScheduledMessage)
)
diff --git a/pyrogram/client/methods/messages/send_chat_action.py b/pyrogram/methods/messages/send_chat_action.py
similarity index 78%
rename from pyrogram/client/methods/messages/send_chat_action.py
rename to pyrogram/methods/messages/send_chat_action.py
index 35a3d722af..c9c5d5692d 100644
--- a/pyrogram/client/methods/messages/send_chat_action.py
+++ b/pyrogram/methods/messages/send_chat_action.py
@@ -19,30 +19,30 @@
import json
from typing import Union
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
class ChatAction:
- TYPING = types.SendMessageTypingAction
- UPLOAD_PHOTO = types.SendMessageUploadPhotoAction
- RECORD_VIDEO = types.SendMessageRecordVideoAction
- UPLOAD_VIDEO = types.SendMessageUploadVideoAction
- RECORD_AUDIO = types.SendMessageRecordAudioAction
- UPLOAD_AUDIO = types.SendMessageUploadAudioAction
- UPLOAD_DOCUMENT = types.SendMessageUploadDocumentAction
- FIND_LOCATION = types.SendMessageGeoLocationAction
- RECORD_VIDEO_NOTE = types.SendMessageRecordRoundAction
- UPLOAD_VIDEO_NOTE = types.SendMessageUploadRoundAction
- PLAYING = types.SendMessageGamePlayAction
- CHOOSE_CONTACT = types.SendMessageChooseContactAction
- CANCEL = types.SendMessageCancelAction
+ TYPING = raw.types.SendMessageTypingAction
+ UPLOAD_PHOTO = raw.types.SendMessageUploadPhotoAction
+ RECORD_VIDEO = raw.types.SendMessageRecordVideoAction
+ UPLOAD_VIDEO = raw.types.SendMessageUploadVideoAction
+ RECORD_AUDIO = raw.types.SendMessageRecordAudioAction
+ UPLOAD_AUDIO = raw.types.SendMessageUploadAudioAction
+ UPLOAD_DOCUMENT = raw.types.SendMessageUploadDocumentAction
+ FIND_LOCATION = raw.types.SendMessageGeoLocationAction
+ RECORD_VIDEO_NOTE = raw.types.SendMessageRecordRoundAction
+ UPLOAD_VIDEO_NOTE = raw.types.SendMessageUploadRoundAction
+ PLAYING = raw.types.SendMessageGamePlayAction
+ CHOOSE_CONTACT = raw.types.SendMessageChooseContactAction
+ CANCEL = raw.types.SendMessageCancelAction
POSSIBLE_VALUES = list(map(lambda x: x.lower(), filter(lambda x: not x.startswith("__"), ChatAction.__dict__.keys())))
-class SendChatAction(BaseClient):
+class SendChatAction(Scaffold):
async def send_chat_action(self, chat_id: Union[int, str], action: str) -> bool:
"""Tell the other party that something is happening on your side.
@@ -94,7 +94,7 @@ async def send_chat_action(self, chat_id: Union[int, str], action: str) -> bool:
action = action()
return await self.send(
- functions.messages.SetTyping(
+ raw.functions.messages.SetTyping(
peer=await self.resolve_peer(chat_id),
action=action
)
diff --git a/pyrogram/client/methods/messages/send_contact.py b/pyrogram/methods/messages/send_contact.py
similarity index 77%
rename from pyrogram/client/methods/messages/send_contact.py
rename to pyrogram/methods/messages/send_contact.py
index 0eacd8fd4c..50909e7c95 100644
--- a/pyrogram/client/methods/messages/send_contact.py
+++ b/pyrogram/methods/messages/send_contact.py
@@ -18,12 +18,12 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class SendContact(BaseClient):
+class SendContact(Scaffold):
async def send_contact(
self,
chat_id: Union[int, str],
@@ -35,12 +35,12 @@ async def send_contact(
reply_to_message_id: int = None,
schedule_date: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None
- ) -> "pyrogram.Message":
+ ) -> "types.Message":
"""Send phone contacts.
Parameters:
@@ -71,12 +71,12 @@ async def send_contact(
schedule_date (``int``, *optional*):
Date when the message will be automatically sent. Unix time.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
Returns:
- :obj:`Message`: On success, the sent contact message is returned.
+ :obj:`~pyrogram.types.Message`: On success, the sent contact message is returned.
Example:
.. code-block:: python
@@ -84,9 +84,9 @@ async def send_contact(
app.send_contact("me", "+39 123 456 7890", "Dan")
"""
r = await self.send(
- functions.messages.SendMedia(
+ raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
- media=types.InputMediaContact(
+ media=raw.types.InputMediaContact(
phone_number=phone_number,
first_name=first_name,
last_name=last_name or "",
@@ -102,10 +102,12 @@ async def send_contact(
)
for i in r.updates:
- if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
- is_scheduled=isinstance(i, types.UpdateNewScheduledMessage)
+ is_scheduled=isinstance(i, raw.types.UpdateNewScheduledMessage)
)
diff --git a/pyrogram/client/methods/messages/send_dice.py b/pyrogram/methods/messages/send_dice.py
similarity index 76%
rename from pyrogram/client/methods/messages/send_dice.py
rename to pyrogram/methods/messages/send_dice.py
index 155185cd3e..f7734a4c59 100644
--- a/pyrogram/client/methods/messages/send_dice.py
+++ b/pyrogram/methods/messages/send_dice.py
@@ -18,12 +18,12 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class SendDice(BaseClient):
+class SendDice(Scaffold):
async def send_dice(
self,
chat_id: Union[int, str],
@@ -32,12 +32,12 @@ async def send_dice(
reply_to_message_id: int = None,
schedule_date: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None
- ) -> Union["pyrogram.Message", None]:
+ ) -> Union["types.Message", None]:
"""Send a dice with a random value from 1 to 6.
Parameters:
@@ -60,12 +60,12 @@ async def send_dice(
schedule_date (``int``, *optional*):
Date when the message will be automatically sent. Unix time.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
Returns:
- :obj:`Message`: On success, the sent dice message is returned.
+ :obj:`~pyrogram.types.Message`: On success, the sent dice message is returned.
Example:
.. code-block:: python
@@ -81,9 +81,9 @@ async def send_dice(
"""
r = await self.send(
- functions.messages.SendMedia(
+ raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
- media=types.InputMediaDice(emoticon=emoji),
+ media=raw.types.InputMediaDice(emoticon=emoji),
silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id,
random_id=self.rnd_id(),
@@ -94,10 +94,12 @@ async def send_dice(
)
for i in r.updates:
- if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
- is_scheduled=isinstance(i, types.UpdateNewScheduledMessage)
+ is_scheduled=isinstance(i, raw.types.UpdateNewScheduledMessage)
)
diff --git a/pyrogram/client/methods/messages/send_document.py b/pyrogram/methods/messages/send_document.py
similarity index 81%
rename from pyrogram/client/methods/messages/send_document.py
rename to pyrogram/methods/messages/send_document.py
index 7f93d6cba0..0c77a94086 100644
--- a/pyrogram/client/methods/messages/send_document.py
+++ b/pyrogram/methods/messages/send_document.py
@@ -20,13 +20,15 @@
import re
from typing import Union, BinaryIO
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram import StopTransmission
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
from pyrogram.errors import FilePartMissing
+from pyrogram.scaffold import Scaffold
-class SendDocument(BaseClient):
+class SendDocument(Scaffold):
async def send_document(
self,
chat_id: Union[int, str],
@@ -40,14 +42,14 @@ async def send_document(
reply_to_message_id: int = None,
schedule_date: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
progress: callable = None,
progress_args: tuple = ()
- ) -> Union["pyrogram.Message", None]:
+ ) -> Union["types.Message", None]:
"""Send generic files.
Parameters:
@@ -97,7 +99,7 @@ async def send_document(
schedule_date (``int``, *optional*):
Date when the message will be automatically sent. Unix time.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -124,8 +126,8 @@ async def send_document(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- :obj:`Message` | ``None``: On success, the sent document message is returned, otherwise, in case the upload
- is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
+ :obj:`~pyrogram.types.Message` | ``None``: On success, the sent document message is returned, otherwise, in
+ case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned.
Example:
.. code-block:: python
@@ -138,28 +140,31 @@ async def send_document(
# Keep track of the progress while uploading
def progress(current, total):
- print("{:.1f}%".format(current * 100 / total))
+ print(f"{current * 100 / total:.1f}%")
app.send_document("me", "document.zip", progress=progress)
"""
file = None
+ # if isinstance(document, PurePath):
+ # document = str(document)
+
try:
if isinstance(document, str):
if os.path.isfile(document):
thumb = await self.save_file(thumb)
file = await self.save_file(document, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedDocument(
+ media = raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(document) or "application/zip",
file=file,
force_file=True,
thumb=thumb,
attributes=[
- types.DocumentAttributeFilename(file_name=file_name or os.path.basename(document))
+ raw.types.DocumentAttributeFilename(file_name=file_name or os.path.basename(document))
]
)
elif re.match("^https?://", document):
- media = types.InputMediaDocumentExternal(
+ media = raw.types.InputMediaDocumentExternal(
url=document
)
else:
@@ -167,19 +172,19 @@ def progress(current, total):
else:
thumb = await self.save_file(thumb)
file = await self.save_file(document, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedDocument(
+ media = raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(document.name) or "application/zip",
file=file,
thumb=thumb,
attributes=[
- types.DocumentAttributeFilename(file_name=document.name)
+ raw.types.DocumentAttributeFilename(file_name=document.name)
]
)
while True:
try:
r = await self.send(
- functions.messages.SendMedia(
+ raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
media=media,
silent=disable_notification or None,
@@ -194,15 +199,14 @@ def progress(current, total):
await self.save_file(document, file_id=file.id, file_part=e.x)
else:
for i in r.updates:
- if isinstance(
- i,
- (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)
- ):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
- is_scheduled=isinstance(i, types.UpdateNewScheduledMessage)
+ is_scheduled=isinstance(i, raw.types.UpdateNewScheduledMessage)
)
- except BaseClient.StopTransmission:
+ except StopTransmission:
return None
diff --git a/pyrogram/client/methods/messages/send_location.py b/pyrogram/methods/messages/send_location.py
similarity index 74%
rename from pyrogram/client/methods/messages/send_location.py
rename to pyrogram/methods/messages/send_location.py
index b23d9b10ef..d144855027 100644
--- a/pyrogram/client/methods/messages/send_location.py
+++ b/pyrogram/methods/messages/send_location.py
@@ -18,12 +18,12 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class SendLocation(BaseClient):
+class SendLocation(Scaffold):
async def send_location(
self,
chat_id: Union[int, str],
@@ -33,12 +33,12 @@ async def send_location(
reply_to_message_id: int = None,
schedule_date: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None
- ) -> "pyrogram.Message":
+ ) -> "types.Message":
"""Send points on the map.
Parameters:
@@ -63,12 +63,12 @@ async def send_location(
schedule_date (``int``, *optional*):
Date when the message will be automatically sent. Unix time.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
Returns:
- :obj:`Message`: On success, the sent location message is returned.
+ :obj:`~pyrogram.types.Message`: On success, the sent location message is returned.
Example:
.. code-block:: python
@@ -76,10 +76,10 @@ async def send_location(
app.send_location("me", 51.500729, -0.124583)
"""
r = await self.send(
- functions.messages.SendMedia(
+ raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
- media=types.InputMediaGeoPoint(
- geo_point=types.InputGeoPoint(
+ media=raw.types.InputMediaGeoPoint(
+ geo_point=raw.types.InputGeoPoint(
lat=latitude,
long=longitude
)
@@ -94,10 +94,12 @@ async def send_location(
)
for i in r.updates:
- if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
- is_scheduled=isinstance(i, types.UpdateNewScheduledMessage)
+ is_scheduled=isinstance(i, raw.types.UpdateNewScheduledMessage)
)
diff --git a/pyrogram/client/methods/messages/send_media_group.py b/pyrogram/methods/messages/send_media_group.py
similarity index 74%
rename from pyrogram/client/methods/messages/send_media_group.py
rename to pyrogram/methods/messages/send_media_group.py
index 0fad6e91e5..6c9bd04d4f 100644
--- a/pyrogram/client/methods/messages/send_media_group.py
+++ b/pyrogram/methods/messages/send_media_group.py
@@ -21,22 +21,23 @@
import re
from typing import Union, List
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
log = logging.getLogger(__name__)
-class SendMediaGroup(BaseClient):
+class SendMediaGroup(Scaffold):
# TODO: Add progress parameter
async def send_media_group(
self,
chat_id: Union[int, str],
- media: List[Union["pyrogram.InputMediaPhoto", "pyrogram.InputMediaVideo"]],
+ media: List[Union["types.InputMediaPhoto", "types.InputMediaVideo"]],
disable_notification: bool = None,
reply_to_message_id: int = None
- ) -> List["pyrogram.Message"]:
+ ) -> List["types.Message"]:
"""Send a group of photos or videos as an album.
Parameters:
@@ -45,7 +46,7 @@ async def send_media_group(
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
- media (List of :obj:`InputMediaPhoto` and :obj:`InputMediaVideo`):
+ media (List of :obj:`~pyrogram.types.InputMediaPhoto` and :obj:`~pyrogram.types.InputMediaVideo`):
A list describing photos and videos to be sent, must include 2–10 items.
disable_notification (``bool``, *optional*):
@@ -56,7 +57,7 @@ async def send_media_group(
If the message is a reply, ID of the original message.
Returns:
- List of :obj:`Message`: On success, a list of the sent messages is returned.
+ List of :obj:`~pyrogram.types.Message`: On success, a list of the sent messages is returned.
Example:
.. code-block:: python
@@ -75,19 +76,19 @@ async def send_media_group(
multi_media = []
for i in media:
- if isinstance(i, pyrogram.InputMediaPhoto):
+ if isinstance(i, types.InputMediaPhoto):
if os.path.isfile(i.media):
media = await self.send(
- functions.messages.UploadMedia(
+ raw.functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id),
- media=types.InputMediaUploadedPhoto(
+ media=raw.types.InputMediaUploadedPhoto(
file=await self.save_file(i.media)
)
)
)
- media = types.InputMediaPhoto(
- id=types.InputPhoto(
+ media = raw.types.InputMediaPhoto(
+ id=raw.types.InputPhoto(
id=media.photo.id,
access_hash=media.photo.access_hash,
file_reference=media.photo.file_reference
@@ -95,16 +96,16 @@ async def send_media_group(
)
elif re.match("^https?://", i.media):
media = await self.send(
- functions.messages.UploadMedia(
+ raw.functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id),
- media=types.InputMediaPhotoExternal(
+ media=raw.types.InputMediaPhotoExternal(
url=i.media
)
)
)
- media = types.InputMediaPhoto(
- id=types.InputPhoto(
+ media = raw.types.InputMediaPhoto(
+ id=raw.types.InputPhoto(
id=media.photo.id,
access_hash=media.photo.access_hash,
file_reference=media.photo.file_reference
@@ -112,30 +113,30 @@ async def send_media_group(
)
else:
media = utils.get_input_media_from_file_id(i.media, i.file_ref, 2)
- elif isinstance(i, pyrogram.InputMediaVideo):
+ elif isinstance(i, types.InputMediaVideo):
if os.path.isfile(i.media):
media = await self.send(
- functions.messages.UploadMedia(
+ raw.functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id),
- media=types.InputMediaUploadedDocument(
+ media=raw.types.InputMediaUploadedDocument(
file=await self.save_file(i.media),
- thumb=self.save_file(i.thumb),
+ thumb=await self.save_file(i.thumb),
mime_type=self.guess_mime_type(i.media) or "video/mp4",
attributes=[
- types.DocumentAttributeVideo(
+ raw.types.DocumentAttributeVideo(
supports_streaming=i.supports_streaming or None,
duration=i.duration,
w=i.width,
h=i.height
),
- types.DocumentAttributeFilename(file_name=os.path.basename(i.media))
+ raw.types.DocumentAttributeFilename(file_name=os.path.basename(i.media))
]
)
)
)
- media = types.InputMediaDocument(
- id=types.InputDocument(
+ media = raw.types.InputMediaDocument(
+ id=raw.types.InputDocument(
id=media.document.id,
access_hash=media.document.access_hash,
file_reference=media.document.file_reference
@@ -143,16 +144,16 @@ async def send_media_group(
)
elif re.match("^https?://", i.media):
media = await self.send(
- functions.messages.UploadMedia(
+ raw.functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id),
- media=types.InputMediaDocumentExternal(
+ media=raw.types.InputMediaDocumentExternal(
url=i.media
)
)
)
- media = types.InputMediaDocument(
- id=types.InputDocument(
+ media = raw.types.InputMediaDocument(
+ id=raw.types.InputDocument(
id=media.document.id,
access_hash=media.document.access_hash,
file_reference=media.document.file_reference
@@ -162,7 +163,7 @@ async def send_media_group(
media = utils.get_input_media_from_file_id(i.media, i.file_ref, 4)
multi_media.append(
- types.InputSingleMedia(
+ raw.types.InputSingleMedia(
media=media,
random_id=self.rnd_id(),
**await self.parser.parse(i.caption, i.parse_mode)
@@ -170,7 +171,7 @@ async def send_media_group(
)
r = await self.send(
- functions.messages.SendMultiMedia(
+ raw.functions.messages.SendMultiMedia(
peer=await self.resolve_peer(chat_id),
multi_media=multi_media,
silent=disable_notification or None,
@@ -180,9 +181,9 @@ async def send_media_group(
return await utils.parse_messages(
self,
- types.messages.Messages(
+ raw.types.messages.Messages(
messages=[m.message for m in filter(
- lambda u: isinstance(u, (types.UpdateNewMessage, types.UpdateNewChannelMessage)),
+ lambda u: isinstance(u, (raw.types.UpdateNewMessage, raw.types.UpdateNewChannelMessage)),
r.updates
)],
users=r.users,
diff --git a/pyrogram/client/methods/messages/send_message.py b/pyrogram/methods/messages/send_message.py
similarity index 82%
rename from pyrogram/client/methods/messages/send_message.py
rename to pyrogram/methods/messages/send_message.py
index 58385bcf7e..e2ccc853cf 100644
--- a/pyrogram/client/methods/messages/send_message.py
+++ b/pyrogram/methods/messages/send_message.py
@@ -18,12 +18,12 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class SendMessage(BaseClient):
+class SendMessage(Scaffold):
async def send_message(
self,
chat_id: Union[int, str],
@@ -34,12 +34,12 @@ async def send_message(
reply_to_message_id: int = None,
schedule_date: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None
- ) -> "pyrogram.Message":
+ ) -> "types.Message":
"""Send text messages.
Parameters:
@@ -71,12 +71,12 @@ async def send_message(
schedule_date (``int``, *optional*):
Date when the message will be automatically sent. Unix time.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
Returns:
- :obj:`Message`: On success, the sent text message is returned.
+ :obj:`~pyrogram.types.Message`: On success, the sent text message is returned.
Example:
.. code-block:: python
@@ -119,7 +119,7 @@ async def send_message(
message, entities = (await self.parser.parse(text, parse_mode)).values()
r = await self.send(
- functions.messages.SendMessage(
+ raw.functions.messages.SendMessage(
peer=await self.resolve_peer(chat_id),
no_webpage=disable_web_page_preview or None,
silent=disable_notification or None,
@@ -132,18 +132,18 @@ async def send_message(
)
)
- if isinstance(r, types.UpdateShortSentMessage):
+ if isinstance(r, raw.types.UpdateShortSentMessage):
peer = await self.resolve_peer(chat_id)
peer_id = (
peer.user_id
- if isinstance(peer, types.InputPeerUser)
+ if isinstance(peer, raw.types.InputPeerUser)
else -peer.chat_id
)
- return pyrogram.Message(
+ return types.Message(
message_id=r.id,
- chat=pyrogram.Chat(
+ chat=types.Chat(
id=peer_id,
type="private",
client=self
@@ -152,17 +152,19 @@ async def send_message(
date=r.date,
outgoing=r.out,
entities=[
- pyrogram.MessageEntity._parse(None, entity, {})
+ types.MessageEntity._parse(None, entity, {})
for entity in entities
],
client=self
)
for i in r.updates:
- if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
- is_scheduled=isinstance(i, types.UpdateNewScheduledMessage)
+ is_scheduled=isinstance(i, raw.types.UpdateNewScheduledMessage)
)
diff --git a/pyrogram/client/methods/messages/send_photo.py b/pyrogram/methods/messages/send_photo.py
similarity index 83%
rename from pyrogram/client/methods/messages/send_photo.py
rename to pyrogram/methods/messages/send_photo.py
index 7c2c194c36..06a6688be1 100644
--- a/pyrogram/client/methods/messages/send_photo.py
+++ b/pyrogram/methods/messages/send_photo.py
@@ -21,12 +21,14 @@
from typing import Union, BinaryIO
import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
from pyrogram.errors import FilePartMissing
+from pyrogram.scaffold import Scaffold
-class SendPhoto(BaseClient):
+class SendPhoto(Scaffold):
async def send_photo(
self,
chat_id: Union[int, str],
@@ -39,14 +41,14 @@ async def send_photo(
reply_to_message_id: int = None,
schedule_date: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
progress: callable = None,
progress_args: tuple = ()
- ) -> Union["pyrogram.Message", None]:
+ ) -> Union["types.Message", None]:
"""Send photos.
Parameters:
@@ -91,7 +93,7 @@ async def send_photo(
schedule_date (``int``, *optional*):
Date when the message will be automatically sent. Unix time.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -118,8 +120,8 @@ async def send_photo(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- :obj:`Message` | ``None``: On success, the sent photo message is returned, otherwise, in case the upload
- is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
+ :obj:`~pyrogram.types.Message` | ``None``: On success, the sent photo message is returned, otherwise, in
+ case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned.
Example:
.. code-block:: python
@@ -142,12 +144,12 @@ async def send_photo(
if isinstance(photo, str):
if os.path.isfile(photo):
file = await self.save_file(photo, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedPhoto(
+ media = raw.types.InputMediaUploadedPhoto(
file=file,
ttl_seconds=ttl_seconds
)
elif re.match("^https?://", photo):
- media = types.InputMediaPhotoExternal(
+ media = raw.types.InputMediaPhotoExternal(
url=photo,
ttl_seconds=ttl_seconds
)
@@ -155,7 +157,7 @@ async def send_photo(
media = utils.get_input_media_from_file_id(photo, file_ref, 2)
else:
file = await self.save_file(photo, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedPhoto(
+ media = raw.types.InputMediaUploadedPhoto(
file=file,
ttl_seconds=ttl_seconds
)
@@ -163,7 +165,7 @@ async def send_photo(
while True:
try:
r = await self.send(
- functions.messages.SendMedia(
+ raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
media=media,
silent=disable_notification or None,
@@ -178,15 +180,14 @@ async def send_photo(
await self.save_file(photo, file_id=file.id, file_part=e.x)
else:
for i in r.updates:
- if isinstance(
- i,
- (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)
- ):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
- is_scheduled=isinstance(i, types.UpdateNewScheduledMessage)
+ is_scheduled=isinstance(i, raw.types.UpdateNewScheduledMessage)
)
- except BaseClient.StopTransmission:
+ except pyrogram.StopTransmission:
return None
diff --git a/pyrogram/client/methods/messages/send_poll.py b/pyrogram/methods/messages/send_poll.py
similarity index 79%
rename from pyrogram/client/methods/messages/send_poll.py
rename to pyrogram/methods/messages/send_poll.py
index 7607a54609..4758e83ed8 100644
--- a/pyrogram/client/methods/messages/send_poll.py
+++ b/pyrogram/methods/messages/send_poll.py
@@ -18,12 +18,12 @@
from typing import Union, List
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class SendPoll(BaseClient):
+class SendPoll(Scaffold):
async def send_poll(
self,
chat_id: Union[int, str],
@@ -37,12 +37,12 @@ async def send_poll(
reply_to_message_id: int = None,
schedule_date: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None
- ) -> "pyrogram.Message":
+ ) -> "types.Message":
"""Send a new poll.
Parameters:
@@ -83,12 +83,12 @@ async def send_poll(
schedule_date (``int``, *optional*):
Date when the message will be automatically sent. Unix time.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
Returns:
- :obj:`Message`: On success, the sent poll message is returned.
+ :obj:`~pyrogram.types.Message`: On success, the sent poll message is returned.
Example:
.. code-block:: python
@@ -96,14 +96,14 @@ async def send_poll(
app.send_poll(chat_id, "Is this a poll question?", ["Yes", "No", "Maybe"])
"""
r = await self.send(
- functions.messages.SendMedia(
+ raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
- media=types.InputMediaPoll(
- poll=types.Poll(
+ media=raw.types.InputMediaPoll(
+ poll=raw.types.Poll(
id=0,
question=question,
answers=[
- types.PollAnswer(text=o, option=bytes([i]))
+ raw.types.PollAnswer(text=o, option=bytes([i]))
for i, o in enumerate(options)
],
multiple_choice=allows_multiple_answers or None,
@@ -122,10 +122,12 @@ async def send_poll(
)
for i in r.updates:
- if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
- is_scheduled=isinstance(i, types.UpdateNewScheduledMessage)
+ is_scheduled=isinstance(i, raw.types.UpdateNewScheduledMessage)
)
diff --git a/pyrogram/client/methods/messages/send_sticker.py b/pyrogram/methods/messages/send_sticker.py
similarity index 79%
rename from pyrogram/client/methods/messages/send_sticker.py
rename to pyrogram/methods/messages/send_sticker.py
index 8025a0dd73..6ab211f894 100644
--- a/pyrogram/client/methods/messages/send_sticker.py
+++ b/pyrogram/methods/messages/send_sticker.py
@@ -20,13 +20,15 @@
import re
from typing import Union, BinaryIO
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram import StopTransmission
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
from pyrogram.errors import FilePartMissing
+from pyrogram.scaffold import Scaffold
-class SendSticker(BaseClient):
+class SendSticker(Scaffold):
async def send_sticker(
self,
chat_id: Union[int, str],
@@ -36,14 +38,14 @@ async def send_sticker(
reply_to_message_id: int = None,
schedule_date: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
progress: callable = None,
progress_args: tuple = ()
- ) -> Union["pyrogram.Message", None]:
+ ) -> Union["types.Message", None]:
"""Send static .webp or animated .tgs stickers.
Parameters:
@@ -73,7 +75,7 @@ async def send_sticker(
schedule_date (``int``, *optional*):
Date when the message will be automatically sent. Unix time.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -100,8 +102,9 @@ async def send_sticker(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- :obj:`Message` | ``None``: On success, the sent sticker message is returned, otherwise, in case the upload
- is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
+ :obj:`~pyrogram.types.Message` | ``None``: On success, the sent sticker message is returned, otherwise,
+ in case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is
+ returned.
Example:
.. code-block:: python
@@ -118,33 +121,33 @@ async def send_sticker(
if isinstance(sticker, str):
if os.path.isfile(sticker):
file = await self.save_file(sticker, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedDocument(
+ media = raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(sticker) or "image/webp",
file=file,
attributes=[
- types.DocumentAttributeFilename(file_name=os.path.basename(sticker))
+ raw.types.DocumentAttributeFilename(file_name=os.path.basename(sticker))
]
)
elif re.match("^https?://", sticker):
- media = types.InputMediaDocumentExternal(
+ media = raw.types.InputMediaDocumentExternal(
url=sticker
)
else:
media = utils.get_input_media_from_file_id(sticker, file_ref, 8)
else:
file = await self.save_file(sticker, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedDocument(
+ media = raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(sticker.name) or "image/webp",
file=file,
attributes=[
- types.DocumentAttributeFilename(file_name=sticker.name)
+ raw.types.DocumentAttributeFilename(file_name=sticker.name)
]
)
while True:
try:
r = await self.send(
- functions.messages.SendMedia(
+ raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
media=media,
silent=disable_notification or None,
@@ -159,15 +162,14 @@ async def send_sticker(
await self.save_file(sticker, file_id=file.id, file_part=e.x)
else:
for i in r.updates:
- if isinstance(
- i,
- (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)
- ):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
- is_scheduled=isinstance(i, types.UpdateNewScheduledMessage)
+ is_scheduled=isinstance(i, raw.types.UpdateNewScheduledMessage)
)
- except BaseClient.StopTransmission:
+ except StopTransmission:
return None
diff --git a/pyrogram/client/methods/messages/send_venue.py b/pyrogram/methods/messages/send_venue.py
similarity index 79%
rename from pyrogram/client/methods/messages/send_venue.py
rename to pyrogram/methods/messages/send_venue.py
index f6f09d5eca..e46119109d 100644
--- a/pyrogram/client/methods/messages/send_venue.py
+++ b/pyrogram/methods/messages/send_venue.py
@@ -18,12 +18,12 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class SendVenue(BaseClient):
+class SendVenue(Scaffold):
async def send_venue(
self,
chat_id: Union[int, str],
@@ -37,12 +37,12 @@ async def send_venue(
reply_to_message_id: int = None,
schedule_date: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None
- ) -> "pyrogram.Message":
+ ) -> "types.Message":
"""Send information about a venue.
Parameters:
@@ -80,12 +80,12 @@ async def send_venue(
schedule_date (``int``, *optional*):
Date when the message will be automatically sent. Unix time.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
Returns:
- :obj:`Message`: On success, the sent venue message is returned.
+ :obj:`~pyrogram.types.Message`: On success, the sent venue message is returned.
Example:
.. code-block:: python
@@ -95,10 +95,10 @@ async def send_venue(
"Elizabeth Tower", "Westminster, London SW1A 0AA, UK")
"""
r = await self.send(
- functions.messages.SendMedia(
+ raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
- media=types.InputMediaVenue(
- geo_point=types.InputGeoPoint(
+ media=raw.types.InputMediaVenue(
+ geo_point=raw.types.InputGeoPoint(
lat=latitude,
long=longitude
),
@@ -118,10 +118,12 @@ async def send_venue(
)
for i in r.updates:
- if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
- is_scheduled=isinstance(i, types.UpdateNewScheduledMessage)
+ is_scheduled=isinstance(i, raw.types.UpdateNewScheduledMessage)
)
diff --git a/pyrogram/client/methods/messages/send_video.py b/pyrogram/methods/messages/send_video.py
similarity index 82%
rename from pyrogram/client/methods/messages/send_video.py
rename to pyrogram/methods/messages/send_video.py
index 87cecf5a1f..3b2bc03eb2 100644
--- a/pyrogram/client/methods/messages/send_video.py
+++ b/pyrogram/methods/messages/send_video.py
@@ -20,13 +20,15 @@
import re
from typing import Union, BinaryIO
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram import StopTransmission
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
from pyrogram.errors import FilePartMissing
+from pyrogram.scaffold import Scaffold
-class SendVideo(BaseClient):
+class SendVideo(Scaffold):
async def send_video(
self,
chat_id: Union[int, str],
@@ -44,14 +46,14 @@ async def send_video(
reply_to_message_id: int = None,
schedule_date: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
progress: callable = None,
progress_args: tuple = ()
- ) -> Union["pyrogram.Message", None]:
+ ) -> Union["types.Message", None]:
"""Send video files.
Parameters:
@@ -114,7 +116,7 @@ async def send_video(
schedule_date (``int``, *optional*):
Date when the message will be automatically sent. Unix time.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -141,8 +143,8 @@ async def send_video(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- :obj:`Message` | ``None``: On success, the sent video message is returned, otherwise, in case the upload
- is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
+ :obj:`~pyrogram.types.Message` | ``None``: On success, the sent video message is returned, otherwise, in
+ case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned.
Example:
.. code-block:: python
@@ -155,7 +157,7 @@ async def send_video(
# Keep track of the progress while uploading
def progress(current, total):
- print("{:.1f}%".format(current * 100 / total))
+ print(f"{current * 100 / total:.1f}%")
app.send_video("me", "video.mp4", progress=progress)
"""
@@ -166,22 +168,22 @@ def progress(current, total):
if os.path.isfile(video):
thumb = await self.save_file(thumb)
file = await self.save_file(video, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedDocument(
+ media = raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(video) or "video/mp4",
file=file,
thumb=thumb,
attributes=[
- types.DocumentAttributeVideo(
+ raw.types.DocumentAttributeVideo(
supports_streaming=supports_streaming or None,
duration=duration,
w=width,
h=height
),
- types.DocumentAttributeFilename(file_name=file_name or os.path.basename(video))
+ raw.types.DocumentAttributeFilename(file_name=file_name or os.path.basename(video))
]
)
elif re.match("^https?://", video):
- media = types.InputMediaDocumentExternal(
+ media = raw.types.InputMediaDocumentExternal(
url=video
)
else:
@@ -189,25 +191,25 @@ def progress(current, total):
else:
thumb = await self.save_file(thumb)
file = await self.save_file(video, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedDocument(
+ media = raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(video.name) or "video/mp4",
file=file,
thumb=thumb,
attributes=[
- types.DocumentAttributeVideo(
+ raw.types.DocumentAttributeVideo(
supports_streaming=supports_streaming or None,
duration=duration,
w=width,
h=height
),
- types.DocumentAttributeFilename(file_name=video.name)
+ raw.types.DocumentAttributeFilename(file_name=video.name)
]
)
while True:
try:
r = await self.send(
- functions.messages.SendMedia(
+ raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
media=media,
silent=disable_notification or None,
@@ -222,15 +224,14 @@ def progress(current, total):
await self.save_file(video, file_id=file.id, file_part=e.x)
else:
for i in r.updates:
- if isinstance(
- i,
- (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)
- ):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
- is_scheduled=isinstance(i, types.UpdateNewScheduledMessage)
+ is_scheduled=isinstance(i, raw.types.UpdateNewScheduledMessage)
)
- except BaseClient.StopTransmission:
+ except StopTransmission:
return None
diff --git a/pyrogram/client/methods/messages/send_video_note.py b/pyrogram/methods/messages/send_video_note.py
similarity index 83%
rename from pyrogram/client/methods/messages/send_video_note.py
rename to pyrogram/methods/messages/send_video_note.py
index c204f6ca15..82a3688bd3 100644
--- a/pyrogram/client/methods/messages/send_video_note.py
+++ b/pyrogram/methods/messages/send_video_note.py
@@ -19,13 +19,15 @@
import os
from typing import Union, BinaryIO
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram import StopTransmission
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
from pyrogram.errors import FilePartMissing
+from pyrogram.scaffold import Scaffold
-class SendVideoNote(BaseClient):
+class SendVideoNote(Scaffold):
async def send_video_note(
self,
chat_id: Union[int, str],
@@ -38,14 +40,14 @@ async def send_video_note(
reply_to_message_id: int = None,
schedule_date: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
progress: callable = None,
progress_args: tuple = ()
- ) -> Union["pyrogram.Message", None]:
+ ) -> Union["types.Message", None]:
"""Send video messages.
Parameters:
@@ -87,7 +89,7 @@ async def send_video_note(
schedule_date (``int``, *optional*):
Date when the message will be automatically sent. Unix time.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -114,8 +116,9 @@ async def send_video_note(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- :obj:`Message` | ``None``: On success, the sent video note message is returned, otherwise, in case the
- upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
+ :obj:`~pyrogram.types.Message` | ``None``: On success, the sent video note message is returned, otherwise,
+ in case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is
+ returned.
Example:
.. code-block:: python
@@ -133,12 +136,12 @@ async def send_video_note(
if os.path.isfile(video_note):
thumb = await self.save_file(thumb)
file = await self.save_file(video_note, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedDocument(
+ media = raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(video_note) or "video/mp4",
file=file,
thumb=thumb,
attributes=[
- types.DocumentAttributeVideo(
+ raw.types.DocumentAttributeVideo(
round_message=True,
duration=duration,
w=length,
@@ -151,12 +154,12 @@ async def send_video_note(
else:
thumb = await self.save_file(thumb)
file = await self.save_file(video_note, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedDocument(
+ media = raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(video_note.name) or "video/mp4",
file=file,
thumb=thumb,
attributes=[
- types.DocumentAttributeVideo(
+ raw.types.DocumentAttributeVideo(
round_message=True,
duration=duration,
w=length,
@@ -168,7 +171,7 @@ async def send_video_note(
while True:
try:
r = await self.send(
- functions.messages.SendMedia(
+ raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
media=media,
silent=disable_notification or None,
@@ -183,15 +186,14 @@ async def send_video_note(
await self.save_file(video_note, file_id=file.id, file_part=e.x)
else:
for i in r.updates:
- if isinstance(
- i,
- (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)
- ):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
- is_scheduled=isinstance(i, types.UpdateNewScheduledMessage)
+ is_scheduled=isinstance(i, raw.types.UpdateNewScheduledMessage)
)
- except BaseClient.StopTransmission:
+ except StopTransmission:
return None
diff --git a/pyrogram/client/methods/messages/send_voice.py b/pyrogram/methods/messages/send_voice.py
similarity index 82%
rename from pyrogram/client/methods/messages/send_voice.py
rename to pyrogram/methods/messages/send_voice.py
index 98221e8dbd..58d401d79d 100644
--- a/pyrogram/client/methods/messages/send_voice.py
+++ b/pyrogram/methods/messages/send_voice.py
@@ -20,13 +20,15 @@
import re
from typing import Union, BinaryIO
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient, utils
+from pyrogram import StopTransmission
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
from pyrogram.errors import FilePartMissing
+from pyrogram.scaffold import Scaffold
-class SendVoice(BaseClient):
+class SendVoice(Scaffold):
async def send_voice(
self,
chat_id: Union[int, str],
@@ -39,14 +41,14 @@ async def send_voice(
reply_to_message_id: int = None,
schedule_date: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
progress: callable = None,
progress_args: tuple = ()
- ) -> Union["pyrogram.Message", None]:
+ ) -> Union["types.Message", None]:
"""Send audio files.
Parameters:
@@ -89,7 +91,7 @@ async def send_voice(
schedule_date (``int``, *optional*):
Date when the message will be automatically sent. Unix time.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -116,8 +118,8 @@ async def send_voice(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- :obj:`Message` | ``None``: On success, the sent voice message is returned, otherwise, in case the upload
- is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
+ :obj:`~pyrogram.types.Message` | ``None``: On success, the sent voice message is returned, otherwise, in
+ case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned.
Example:
.. code-block:: python
@@ -137,29 +139,29 @@ async def send_voice(
if isinstance(voice, str):
if os.path.isfile(voice):
file = await self.save_file(voice, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedDocument(
+ media = raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(voice) or "audio/mpeg",
file=file,
attributes=[
- types.DocumentAttributeAudio(
+ raw.types.DocumentAttributeAudio(
voice=True,
duration=duration
)
]
)
elif re.match("^https?://", voice):
- media = types.InputMediaDocumentExternal(
+ media = raw.types.InputMediaDocumentExternal(
url=voice
)
else:
media = utils.get_input_media_from_file_id(voice, file_ref, 3)
else:
file = await self.save_file(voice, progress=progress, progress_args=progress_args)
- media = types.InputMediaUploadedDocument(
+ media = raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(voice.name) or "audio/mpeg",
file=file,
attributes=[
- types.DocumentAttributeAudio(
+ raw.types.DocumentAttributeAudio(
voice=True,
duration=duration
)
@@ -169,7 +171,7 @@ async def send_voice(
while True:
try:
r = await self.send(
- functions.messages.SendMedia(
+ raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
media=media,
silent=disable_notification or None,
@@ -184,15 +186,14 @@ async def send_voice(
await self.save_file(voice, file_id=file.id, file_part=e.x)
else:
for i in r.updates:
- if isinstance(
- i,
- (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)
- ):
- return await pyrogram.Message._parse(
+ if isinstance(i, (raw.types.UpdateNewMessage,
+ raw.types.UpdateNewChannelMessage,
+ raw.types.UpdateNewScheduledMessage)):
+ return await types.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
- is_scheduled=isinstance(i, types.UpdateNewScheduledMessage)
+ is_scheduled=isinstance(i, raw.types.UpdateNewScheduledMessage)
)
- except BaseClient.StopTransmission:
+ except StopTransmission:
return None
diff --git a/pyrogram/client/methods/messages/stop_poll.py b/pyrogram/methods/messages/stop_poll.py
similarity index 79%
rename from pyrogram/client/methods/messages/stop_poll.py
rename to pyrogram/methods/messages/stop_poll.py
index 79498e45ed..c0b0754244 100644
--- a/pyrogram/client/methods/messages/stop_poll.py
+++ b/pyrogram/methods/messages/stop_poll.py
@@ -18,18 +18,18 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class StopPoll(BaseClient):
+class StopPoll(Scaffold):
async def stop_poll(
self,
chat_id: Union[int, str],
message_id: int,
- reply_markup: "pyrogram.InlineKeyboardMarkup" = None
- ) -> "pyrogram.Poll":
+ reply_markup: "types.InlineKeyboardMarkup" = None
+ ) -> "types.Poll":
"""Stop a poll which was sent by you.
Stopped polls can't be reopened and nobody will be able to vote in it anymore.
@@ -43,11 +43,11 @@ async def stop_poll(
message_id (``int``):
Identifier of the original message with the poll.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
- :obj:`Poll`: On success, the stopped poll with the final results is returned.
+ :obj:`~pyrogram.types.Poll`: On success, the stopped poll with the final results is returned.
Example:
.. code-block:: python
@@ -57,11 +57,11 @@ async def stop_poll(
poll = (await self.get_messages(chat_id, message_id)).poll
r = await self.send(
- functions.messages.EditMessage(
+ raw.functions.messages.EditMessage(
peer=await self.resolve_peer(chat_id),
id=message_id,
- media=types.InputMediaPoll(
- poll=types.Poll(
+ media=raw.types.InputMediaPoll(
+ poll=raw.types.Poll(
id=int(poll.id),
closed=True,
question="",
@@ -72,4 +72,4 @@ async def stop_poll(
)
)
- return pyrogram.Poll._parse(self, r.updates[0])
+ return types.Poll._parse(self, r.updates[0])
diff --git a/pyrogram/client/methods/messages/vote_poll.py b/pyrogram/methods/messages/vote_poll.py
similarity index 86%
rename from pyrogram/client/methods/messages/vote_poll.py
rename to pyrogram/methods/messages/vote_poll.py
index 667df0fb16..e764e0bbba 100644
--- a/pyrogram/client/methods/messages/vote_poll.py
+++ b/pyrogram/methods/messages/vote_poll.py
@@ -18,18 +18,18 @@
from typing import Union, List
-import pyrogram
-from pyrogram.api import functions
-from pyrogram.client.ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class VotePoll(BaseClient):
+class VotePoll(Scaffold):
async def vote_poll(
self,
chat_id: Union[int, str],
message_id: id,
options: Union[int, List[int]]
- ) -> "pyrogram.Poll":
+ ) -> "types.Poll":
"""Vote a poll.
Parameters:
@@ -45,7 +45,7 @@ async def vote_poll(
Index or list of indexes (for multiple answers) of the poll option(s) you want to vote for (0 to 9).
Returns:
- :obj:`Poll` - On success, the poll with the chosen option is returned.
+ :obj:`~pyrogram.types.Poll` - On success, the poll with the chosen option is returned.
Example:
.. code-block:: python
@@ -57,11 +57,11 @@ async def vote_poll(
options = [options] if not isinstance(options, list) else options
r = await self.send(
- functions.messages.SendVote(
+ raw.functions.messages.SendVote(
peer=await self.resolve_peer(chat_id),
msg_id=message_id,
options=[poll.options[option].data for option in options]
)
)
- return pyrogram.Poll._parse(self, r.updates[0])
+ return types.Poll._parse(self, r.updates[0])
diff --git a/pyrogram/client/methods/password/__init__.py b/pyrogram/methods/password/__init__.py
similarity index 100%
rename from pyrogram/client/methods/password/__init__.py
rename to pyrogram/methods/password/__init__.py
diff --git a/pyrogram/client/methods/password/change_cloud_password.py b/pyrogram/methods/password/change_cloud_password.py
similarity index 80%
rename from pyrogram/client/methods/password/change_cloud_password.py
rename to pyrogram/methods/password/change_cloud_password.py
index 54ec289193..4002ef1e36 100644
--- a/pyrogram/client/methods/password/change_cloud_password.py
+++ b/pyrogram/methods/password/change_cloud_password.py
@@ -18,12 +18,12 @@
import os
-from pyrogram.api import functions, types
-from .utils import compute_hash, compute_check, btoi, itob
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
+from pyrogram.utils import compute_password_hash, compute_password_check, btoi, itob
-class ChangeCloudPassword(BaseClient):
+class ChangeCloudPassword(Scaffold):
async def change_cloud_password(
self,
current_password: str,
@@ -57,19 +57,19 @@ async def change_cloud_password(
# Change password and hint
app.change_cloud_password("current_password", "new_password", new_hint="hint")
"""
- r = await self.send(functions.account.GetPassword())
+ r = await self.send(raw.functions.account.GetPassword())
if not r.has_password:
raise ValueError("There is no cloud password to change")
r.new_algo.salt1 += os.urandom(32)
- new_hash = btoi(compute_hash(r.new_algo, new_password))
+ new_hash = btoi(compute_password_hash(r.new_algo, new_password))
new_hash = itob(pow(r.new_algo.g, new_hash, btoi(r.new_algo.p)))
await self.send(
- functions.account.UpdatePasswordSettings(
- password=compute_check(r, current_password),
- new_settings=types.account.PasswordInputSettings(
+ raw.functions.account.UpdatePasswordSettings(
+ password=compute_password_check(r, current_password),
+ new_settings=raw.types.account.PasswordInputSettings(
new_algo=r.new_algo,
new_password_hash=new_hash,
hint=new_hint
diff --git a/pyrogram/client/methods/password/enable_cloud_password.py b/pyrogram/methods/password/enable_cloud_password.py
similarity index 83%
rename from pyrogram/client/methods/password/enable_cloud_password.py
rename to pyrogram/methods/password/enable_cloud_password.py
index b629194345..4fedca154b 100644
--- a/pyrogram/client/methods/password/enable_cloud_password.py
+++ b/pyrogram/methods/password/enable_cloud_password.py
@@ -18,12 +18,12 @@
import os
-from pyrogram.api import functions, types
-from .utils import compute_hash, btoi, itob
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
+from pyrogram.utils import compute_password_hash, btoi, itob
-class EnableCloudPassword(BaseClient):
+class EnableCloudPassword(Scaffold):
async def enable_cloud_password(
self,
password: str,
@@ -62,19 +62,19 @@ async def enable_cloud_password(
# Enable password with hint and email
app.enable_cloud_password("password", hint="hint", email="user@email.com")
"""
- r = await self.send(functions.account.GetPassword())
+ r = await self.send(raw.functions.account.GetPassword())
if r.has_password:
raise ValueError("There is already a cloud password enabled")
r.new_algo.salt1 += os.urandom(32)
- new_hash = btoi(compute_hash(r.new_algo, password))
+ new_hash = btoi(compute_password_hash(r.new_algo, password))
new_hash = itob(pow(r.new_algo.g, new_hash, btoi(r.new_algo.p)))
await self.send(
- functions.account.UpdatePasswordSettings(
- password=types.InputCheckPasswordEmpty(),
- new_settings=types.account.PasswordInputSettings(
+ raw.functions.account.UpdatePasswordSettings(
+ password=raw.types.InputCheckPasswordEmpty(),
+ new_settings=raw.types.account.PasswordInputSettings(
new_algo=r.new_algo,
new_password_hash=new_hash,
hint=hint,
diff --git a/pyrogram/client/methods/password/remove_cloud_password.py b/pyrogram/methods/password/remove_cloud_password.py
similarity index 77%
rename from pyrogram/client/methods/password/remove_cloud_password.py
rename to pyrogram/methods/password/remove_cloud_password.py
index 9d41a9db8b..ecebe226b5 100644
--- a/pyrogram/client/methods/password/remove_cloud_password.py
+++ b/pyrogram/methods/password/remove_cloud_password.py
@@ -16,12 +16,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from pyrogram.api import functions, types
-from .utils import compute_check
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
+from pyrogram.utils import compute_password_check
-class RemoveCloudPassword(BaseClient):
+class RemoveCloudPassword(Scaffold):
async def remove_cloud_password(
self,
password: str
@@ -43,16 +43,16 @@ async def remove_cloud_password(
app.remove_cloud_password("password")
"""
- r = await self.send(functions.account.GetPassword())
+ r = await self.send(raw.functions.account.GetPassword())
if not r.has_password:
raise ValueError("There is no cloud password to remove")
await self.send(
- functions.account.UpdatePasswordSettings(
- password=compute_check(r, password),
- new_settings=types.account.PasswordInputSettings(
- new_algo=types.PasswordKdfAlgoUnknown(),
+ raw.functions.account.UpdatePasswordSettings(
+ password=compute_password_check(r, password),
+ new_settings=raw.types.account.PasswordInputSettings(
+ new_algo=raw.types.PasswordKdfAlgoUnknown(),
new_password_hash=b"",
hint=""
)
diff --git a/pyrogram/client/methods/users/__init__.py b/pyrogram/methods/users/__init__.py
similarity index 100%
rename from pyrogram/client/methods/users/__init__.py
rename to pyrogram/methods/users/__init__.py
diff --git a/pyrogram/client/methods/users/block_user.py b/pyrogram/methods/users/block_user.py
similarity index 92%
rename from pyrogram/client/methods/users/block_user.py
rename to pyrogram/methods/users/block_user.py
index 8dd6e09dff..6464788901 100644
--- a/pyrogram/client/methods/users/block_user.py
+++ b/pyrogram/methods/users/block_user.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class BlockUser(BaseClient):
+class BlockUser(Scaffold):
async def block_user(
self,
user_id: Union[int, str]
@@ -45,7 +45,7 @@ async def block_user(
"""
return bool(
await self.send(
- functions.contacts.Block(
+ raw.functions.contacts.Block(
id=await self.resolve_peer(user_id)
)
)
diff --git a/pyrogram/client/methods/users/delete_profile_photos.py b/pyrogram/methods/users/delete_profile_photos.py
similarity index 86%
rename from pyrogram/client/methods/users/delete_profile_photos.py
rename to pyrogram/methods/users/delete_profile_photos.py
index ac184da5d9..c56621267b 100644
--- a/pyrogram/client/methods/users/delete_profile_photos.py
+++ b/pyrogram/methods/users/delete_profile_photos.py
@@ -18,12 +18,12 @@
from typing import List, Union
-from pyrogram.api import functions
-from pyrogram.client.ext import utils
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
-class DeleteProfilePhotos(BaseClient):
+class DeleteProfilePhotos(Scaffold):
async def delete_profile_photos(
self,
photo_ids: Union[str, List[str]]
@@ -32,7 +32,7 @@ async def delete_profile_photos(
Parameters:
photo_ids (``str`` | List of ``str``):
- A single :obj:`Photo` id as string or multiple ids as list of strings for deleting
+ A single :obj:`~pyrogram.types.Photo` id as string or multiple ids as list of strings for deleting
more than one photos at once.
Returns:
@@ -54,7 +54,7 @@ async def delete_profile_photos(
input_photos = [utils.get_input_media_from_file_id(i).id for i in photo_ids]
return bool(await self.send(
- functions.photos.DeletePhotos(
+ raw.functions.photos.DeletePhotos(
id=input_photos
)
))
diff --git a/pyrogram/client/methods/users/get_common_chats.py b/pyrogram/methods/users/get_common_chats.py
similarity index 78%
rename from pyrogram/client/methods/users/get_common_chats.py
rename to pyrogram/methods/users/get_common_chats.py
index fab202fd36..5b788877bc 100644
--- a/pyrogram/client/methods/users/get_common_chats.py
+++ b/pyrogram/methods/users/get_common_chats.py
@@ -18,12 +18,12 @@
from typing import Union
-import pyrogram
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class GetCommonChats(BaseClient):
+class GetCommonChats(Scaffold):
async def get_common_chats(self, user_id: Union[int, str]) -> list:
"""Get the common chats you have with a user.
@@ -34,7 +34,7 @@ async def get_common_chats(self, user_id: Union[int, str]) -> list:
For a contact that exists in your Telegram address book you can use his phone number (str).
Returns:
- List of :obj:`Chat`: On success, a list of the common chats is returned.
+ List of :obj:`~pyrogram.types.Chat`: On success, a list of the common chats is returned.
Raises:
ValueError: If the user_id doesn't belong to a user.
@@ -48,15 +48,15 @@ async def get_common_chats(self, user_id: Union[int, str]) -> list:
peer = await self.resolve_peer(user_id)
- if isinstance(peer, types.InputPeerUser):
+ if isinstance(peer, raw.types.InputPeerUser):
r = await self.send(
- functions.messages.GetCommonChats(
+ raw.functions.messages.GetCommonChats(
user_id=peer,
max_id=0,
limit=100,
)
)
- return pyrogram.List([pyrogram.Chat._parse_chat(self, x) for x in r.chats])
+ return types.List([types.Chat._parse_chat(self, x) for x in r.chats])
- raise ValueError('The user_id "{}" doesn\'t belong to a user'.format(user_id))
+ raise ValueError(f'The user_id "{user_id}" doesn\'t belong to a user')
diff --git a/pyrogram/client/methods/users/get_me.py b/pyrogram/methods/users/get_me.py
similarity index 74%
rename from pyrogram/client/methods/users/get_me.py
rename to pyrogram/methods/users/get_me.py
index 0efbddb2e5..385296717d 100644
--- a/pyrogram/client/methods/users/get_me.py
+++ b/pyrogram/methods/users/get_me.py
@@ -16,17 +16,17 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-import pyrogram
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class GetMe(BaseClient):
- async def get_me(self) -> "pyrogram.User":
+class GetMe(Scaffold):
+ async def get_me(self) -> "types.User":
"""Get your own user identity.
Returns:
- :obj:`User`: Information about the own logged in user/bot.
+ :obj:`~pyrogram.types.User`: Information about the own logged in user/bot.
Example:
.. code-block:: python
@@ -34,11 +34,11 @@ async def get_me(self) -> "pyrogram.User":
me = app.get_me()
print(me)
"""
- return pyrogram.User._parse(
+ return types.User._parse(
self,
(await self.send(
- functions.users.GetFullUser(
- id=types.InputPeerSelf()
+ raw.functions.users.GetFullUser(
+ id=raw.types.InputUserSelf()
)
)).user
)
diff --git a/pyrogram/client/methods/users/get_profile_photos.py b/pyrogram/methods/users/get_profile_photos.py
similarity index 81%
rename from pyrogram/client/methods/users/get_profile_photos.py
rename to pyrogram/methods/users/get_profile_photos.py
index fded8dcb98..b27687a14f 100644
--- a/pyrogram/client/methods/users/get_profile_photos.py
+++ b/pyrogram/methods/users/get_profile_photos.py
@@ -18,19 +18,19 @@
from typing import Union, List
-import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.client.ext import utils
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
+from pyrogram.scaffold import Scaffold
-class GetProfilePhotos(BaseClient):
+class GetProfilePhotos(Scaffold):
async def get_profile_photos(
self,
chat_id: Union[int, str],
offset: int = 0,
limit: int = 100
- ) -> List["pyrogram.Photo"]:
+ ) -> List["types.Photo"]:
"""Get a list of profile pictures for a user or a chat.
Parameters:
@@ -48,7 +48,7 @@ async def get_profile_photos(
Values between 1—100 are accepted. Defaults to 100.
Returns:
- List of :obj:`Photo`: On success, a list of profile photos is returned.
+ List of :obj:`~pyrogram.types.Photo`: On success, a list of profile photos is returned.
Example:
.. code-block:: python
@@ -64,14 +64,14 @@ async def get_profile_photos(
"""
peer_id = await self.resolve_peer(chat_id)
- if isinstance(peer_id, types.InputPeerChannel):
+ if isinstance(peer_id, raw.types.InputPeerChannel):
r = await utils.parse_messages(
self,
await self.send(
- functions.messages.Search(
+ raw.functions.messages.Search(
peer=peer_id,
q="",
- filter=types.InputMessagesFilterChatPhotos(),
+ filter=raw.types.InputMessagesFilterChatPhotos(),
min_date=0,
max_date=0,
offset_id=0,
@@ -84,10 +84,10 @@ async def get_profile_photos(
)
)
- return pyrogram.List([message.new_chat_photo for message in r][:limit])
+ return types.List([message.new_chat_photo for message in r][:limit])
else:
r = await self.send(
- functions.photos.GetUserPhotos(
+ raw.functions.photos.GetUserPhotos(
user_id=peer_id,
offset=offset,
max_id=0,
@@ -95,4 +95,4 @@ async def get_profile_photos(
)
)
- return pyrogram.List(pyrogram.Photo._parse(self, photo) for photo in r.photos)
+ return types.List(types.Photo._parse(self, photo) for photo in r.photos)
diff --git a/pyrogram/client/methods/users/get_profile_photos_count.py b/pyrogram/methods/users/get_profile_photos_count.py
similarity index 83%
rename from pyrogram/client/methods/users/get_profile_photos_count.py
rename to pyrogram/methods/users/get_profile_photos_count.py
index affc00e110..65b4e16849 100644
--- a/pyrogram/client/methods/users/get_profile_photos_count.py
+++ b/pyrogram/methods/users/get_profile_photos_count.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions, types
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class GetProfilePhotosCount(BaseClient):
+class GetProfilePhotosCount(Scaffold):
async def get_profile_photos_count(self, chat_id: Union[int, str]) -> int:
"""Get the total count of profile pictures for a user.
@@ -44,18 +44,18 @@ async def get_profile_photos_count(self, chat_id: Union[int, str]) -> int:
peer_id = await self.resolve_peer(chat_id)
- if isinstance(peer_id, types.InputPeerChannel):
+ if isinstance(peer_id, raw.types.InputPeerChannel):
r = await self.send(
- functions.messages.GetSearchCounters(
+ raw.functions.messages.GetSearchCounters(
peer=peer_id,
- filters=[types.InputMessagesFilterChatPhotos()],
+ filters=[raw.types.InputMessagesFilterChatPhotos()],
)
)
return r[0].count
else:
r = await self.send(
- functions.photos.GetUserPhotos(
+ raw.functions.photos.GetUserPhotos(
user_id=peer_id,
offset=0,
max_id=0,
@@ -63,7 +63,7 @@ async def get_profile_photos_count(self, chat_id: Union[int, str]) -> int:
)
)
- if isinstance(r, types.photos.Photos):
+ if isinstance(r, raw.types.photos.Photos):
return len(r.photos)
else:
return r.count
diff --git a/pyrogram/client/methods/users/get_users.py b/pyrogram/methods/users/get_users.py
similarity index 77%
rename from pyrogram/client/methods/users/get_users.py
rename to pyrogram/methods/users/get_users.py
index 05476bc453..cf591d2bb8 100644
--- a/pyrogram/client/methods/users/get_users.py
+++ b/pyrogram/methods/users/get_users.py
@@ -19,16 +19,16 @@
import asyncio
from typing import Iterable, Union, List
-import pyrogram
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-class GetUsers(BaseClient):
+class GetUsers(Scaffold):
async def get_users(
self,
user_ids: Union[Iterable[Union[int, str]], int, str]
- ) -> Union["pyrogram.User", List["pyrogram.User"]]:
+ ) -> Union["types.User", List["types.User"]]:
"""Get information about a user.
You can retrieve up to 200 users at once.
@@ -39,9 +39,9 @@ async def get_users(
Iterators and Generators are also accepted.
Returns:
- :obj:`User` | List of :obj:`User`: In case *user_ids* was an integer or string the single requested user is
- returned, otherwise, in case *user_ids* was an iterable a list of users is returned, even if the iterable
- contained one item only.
+ :obj:`~pyrogram.types.User` | List of :obj:`~pyrogram.types.User`: In case *user_ids* was an integer or
+ string the single requested user is returned, otherwise, in case *user_ids* was an iterable a list of users
+ is returned, even if the iterable contained one item only.
Example:
.. code-block:: python
@@ -57,14 +57,14 @@ async def get_users(
user_ids = await asyncio.gather(*[self.resolve_peer(i) for i in user_ids])
r = await self.send(
- functions.users.GetUsers(
+ raw.functions.users.GetUsers(
id=user_ids
)
)
- users = pyrogram.List()
+ users = types.List()
for i in r:
- users.append(pyrogram.User._parse(self, i))
+ users.append(types.User._parse(self, i))
return users if is_iterable else users[0]
diff --git a/pyrogram/client/methods/users/iter_profile_photos.py b/pyrogram/methods/users/iter_profile_photos.py
similarity index 80%
rename from pyrogram/client/methods/users/iter_profile_photos.py
rename to pyrogram/methods/users/iter_profile_photos.py
index bdd3d8b79e..ee196f6553 100644
--- a/pyrogram/client/methods/users/iter_profile_photos.py
+++ b/pyrogram/methods/users/iter_profile_photos.py
@@ -16,27 +16,24 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from typing import Union, Generator, Optional
+from typing import Union, AsyncGenerator, Optional
-import pyrogram
-from async_generator import async_generator, yield_
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
-from ...ext import BaseClient
-
-class IterProfilePhotos(BaseClient):
- @async_generator
+class IterProfilePhotos(Scaffold):
async def iter_profile_photos(
self,
chat_id: Union[int, str],
offset: int = 0,
limit: int = 0,
- ) -> Optional[Generator["pyrogram.Message", None, None]]:
+ ) -> Optional[AsyncGenerator["types.Message", None]]:
"""Iterate through a chat or a user profile photos sequentially.
- This convenience method does the same as repeatedly calling :meth:`~Client.get_profile_photos` in a loop, thus
- saving you from the hassle of setting up boilerplate code. It is useful for getting all the profile photos with
- a single call.
+ This convenience method does the same as repeatedly calling :meth:`~pyrogram.Client.get_profile_photos` in a
+ loop, thus saving you from the hassle of setting up boilerplate code. It is useful for getting all the profile
+ photos with a single call.
Parameters:
chat_id (``int`` | ``str``):
@@ -52,7 +49,7 @@ async def iter_profile_photos(
Sequential number of the first profile photo to be returned.
Returns:
- ``Generator``: A generator yielding :obj:`Photo` objects.
+ ``Generator``: A generator yielding :obj:`~pyrogram.types.Photo` objects.
Example:
.. code-block:: python
@@ -77,7 +74,7 @@ async def iter_profile_photos(
offset += len(photos)
for photo in photos:
- await yield_(photo)
+ yield photo
current += 1
diff --git a/pyrogram/client/methods/users/set_profile_photo.py b/pyrogram/methods/users/set_profile_photo.py
similarity index 94%
rename from pyrogram/client/methods/users/set_profile_photo.py
rename to pyrogram/methods/users/set_profile_photo.py
index b9dbbf1048..9d72c033b1 100644
--- a/pyrogram/client/methods/users/set_profile_photo.py
+++ b/pyrogram/methods/users/set_profile_photo.py
@@ -18,11 +18,11 @@
from typing import Union, BinaryIO
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class SetProfilePhoto(BaseClient):
+class SetProfilePhoto(Scaffold):
async def set_profile_photo(
self,
*,
@@ -65,7 +65,7 @@ async def set_profile_photo(
return bool(
await self.send(
- functions.photos.UploadProfilePhoto(
+ raw.functions.photos.UploadProfilePhoto(
file=await self.save_file(photo),
video=await self.save_file(video)
)
diff --git a/pyrogram/client/methods/users/unblock_user.py b/pyrogram/methods/users/unblock_user.py
similarity index 91%
rename from pyrogram/client/methods/users/unblock_user.py
rename to pyrogram/methods/users/unblock_user.py
index fddf9ff655..9f9e76bbc3 100644
--- a/pyrogram/client/methods/users/unblock_user.py
+++ b/pyrogram/methods/users/unblock_user.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class UnblockUser(BaseClient):
+class UnblockUser(Scaffold):
async def unblock_user(
self,
user_id: Union[int, str]
@@ -45,7 +45,7 @@ async def unblock_user(
"""
return bool(
await self.send(
- functions.contacts.Unblock(
+ raw.functions.contacts.Unblock(
id=await self.resolve_peer(user_id)
)
)
diff --git a/pyrogram/client/methods/users/update_profile.py b/pyrogram/methods/users/update_profile.py
similarity index 93%
rename from pyrogram/client/methods/users/update_profile.py
rename to pyrogram/methods/users/update_profile.py
index 145d503509..15c7079343 100644
--- a/pyrogram/client/methods/users/update_profile.py
+++ b/pyrogram/methods/users/update_profile.py
@@ -16,11 +16,11 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class UpdateProfile(BaseClient):
+class UpdateProfile(Scaffold):
async def update_profile(
self,
first_name: str = None,
@@ -61,7 +61,7 @@ async def update_profile(
return bool(
await self.send(
- functions.account.UpdateProfile(
+ raw.functions.account.UpdateProfile(
first_name=first_name,
last_name=last_name,
about=bio
diff --git a/pyrogram/client/methods/users/update_username.py b/pyrogram/methods/users/update_username.py
similarity index 88%
rename from pyrogram/client/methods/users/update_username.py
rename to pyrogram/methods/users/update_username.py
index 50e2388c7e..2689c59db6 100644
--- a/pyrogram/client/methods/users/update_username.py
+++ b/pyrogram/methods/users/update_username.py
@@ -18,11 +18,11 @@
from typing import Union
-from pyrogram.api import functions
-from ...ext import BaseClient
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
-class UpdateUsername(BaseClient):
+class UpdateUsername(Scaffold):
async def update_username(
self,
username: Union[str, None]
@@ -31,7 +31,7 @@ async def update_username(
This method only works for users, not bots. Bot usernames must be changed via Bot Support or by recreating
them from scratch using BotFather. To update a channel or supergroup username you can use
- :meth:`~Client.update_chat_username`.
+ :meth:`~pyrogram.Client.update_chat_username`.
Parameters:
username (``str`` | ``None``):
@@ -48,7 +48,7 @@ async def update_username(
return bool(
await self.send(
- functions.account.UpdateUsername(
+ raw.functions.account.UpdateUsername(
username=username or ""
)
)
diff --git a/pyrogram/methods/utilities/__init__.py b/pyrogram/methods/utilities/__init__.py
new file mode 100644
index 0000000000..d6ddcd3c1b
--- /dev/null
+++ b/pyrogram/methods/utilities/__init__.py
@@ -0,0 +1,39 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+from .add_handler import AddHandler
+from .export_session_string import ExportSessionString
+from .remove_handler import RemoveHandler
+from .restart import Restart
+from .run import Run
+from .start import Start
+from .stop import Stop
+from .stop_transmission import StopTransmission
+
+
+class Utilities(
+ AddHandler,
+ ExportSessionString,
+ RemoveHandler,
+ Restart,
+ Run,
+ Start,
+ Stop,
+ StopTransmission
+):
+ pass
diff --git a/pyrogram/methods/utilities/add_handler.py b/pyrogram/methods/utilities/add_handler.py
new file mode 100644
index 0000000000..f8d993cddb
--- /dev/null
+++ b/pyrogram/methods/utilities/add_handler.py
@@ -0,0 +1,63 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+from pyrogram.handlers import DisconnectHandler
+from pyrogram.handlers.handler import Handler
+from pyrogram.scaffold import Scaffold
+
+
+class AddHandler(Scaffold):
+ def add_handler(self, handler: "Handler", group: int = 0):
+ """Register an update handler.
+
+ You can register multiple handlers, but at most one handler within a group will be used for a single update.
+ To handle the same update more than once, register your handler using a different group id (lower group id
+ == higher priority). This mechanism is explained in greater details at
+ :doc:`More on Updates <../../topics/more-on-updates>`.
+
+ Parameters:
+ handler (``Handler``):
+ The handler to be registered.
+
+ group (``int``, *optional*):
+ The group identifier, defaults to 0.
+
+ Returns:
+ ``tuple``: A tuple consisting of *(handler, group)*.
+
+ Example:
+ .. code-block:: python
+ :emphasize-lines: 8
+
+ from pyrogram import Client, MessageHandler
+
+ def dump(client, message):
+ print(message)
+
+ app = Client("my_account")
+
+ app.add_handler(MessageHandler(dump))
+
+ app.run()
+ """
+ if isinstance(handler, DisconnectHandler):
+ self.disconnect_handler = handler.callback
+ else:
+ self.dispatcher.add_handler(handler, group)
+
+ return handler, group
diff --git a/pyrogram/methods/utilities/export_session_string.py b/pyrogram/methods/utilities/export_session_string.py
new file mode 100644
index 0000000000..4b9a4fce9b
--- /dev/null
+++ b/pyrogram/methods/utilities/export_session_string.py
@@ -0,0 +1,44 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+from pyrogram.scaffold import Scaffold
+
+
+class ExportSessionString(Scaffold):
+ async def export_session_string(self):
+ """Export the current authorized session as a serialized string.
+
+ Session strings are useful for storing in-memory authorized sessions in a portable, serialized string.
+ More detailed information about session strings can be found at the dedicated page of
+ :doc:`Storage Engines <../../topics/storage-engines>`.
+
+ Returns:
+ ``str``: The session serialized into a printable, url-safe string.
+
+ Example:
+ .. code-block:: python
+ :emphasize-lines: 6
+
+ from pyrogram import Client
+
+ app = Client("my_account")
+
+ with app:
+ print(app.export_session_string())
+ """
+ return await self.storage.export_session_string()
diff --git a/pyrogram/methods/utilities/idle.py b/pyrogram/methods/utilities/idle.py
new file mode 100644
index 0000000000..86131ea218
--- /dev/null
+++ b/pyrogram/methods/utilities/idle.py
@@ -0,0 +1,78 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import asyncio
+import logging
+import signal
+
+log = logging.getLogger(__name__)
+
+loop = asyncio.get_event_loop()
+event = asyncio.Event()
+
+
+async def idle():
+ """Block the main script execution until a signal is received.
+
+ This function will run indefinitely in order to block the main script execution and prevent it from
+ exiting while having client(s) that are still running in the background.
+
+ It is useful for event-driven application only, that are, applications which react upon incoming Telegram
+ updates through handlers, rather than executing a set of methods sequentially.
+
+ The way Pyrogram works, it will keep your handlers in a pool of worker threads, which are executed concurrently
+ outside the main thread; calling idle() will ensure the client(s) will be kept alive by not letting the main
+ script to end, until you decide to quit.
+
+ Once a signal is received (e.g.: from CTRL+C) the function will terminate and your main script will continue.
+ Don't forget to call :meth:`~pyrogram.Client.stop` for each running client before the script ends.
+
+ Example:
+ .. code-block:: python
+ :emphasize-lines: 13
+
+ from pyrogram import Client, idle
+
+ app1 = Client("account1")
+ app2 = Client("account2")
+ app3 = Client("account3")
+
+ ... # Set handlers up
+
+ app1.start()
+ app2.start()
+ app3.start()
+
+ idle()
+
+ app1.stop()
+ app2.stop()
+ app3.stop()
+ """
+
+ def handler():
+ log.info("Stop signal received")
+ event.set()
+
+ asyncio.get_event_loop().add_signal_handler(signal.SIGINT, handler)
+
+ log.info("Idle started")
+ await event.wait()
+
+ log.info("Idle stopped")
+ event.clear()
diff --git a/pyrogram/methods/utilities/remove_handler.py b/pyrogram/methods/utilities/remove_handler.py
new file mode 100644
index 0000000000..5a4de8c14f
--- /dev/null
+++ b/pyrogram/methods/utilities/remove_handler.py
@@ -0,0 +1,59 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+from pyrogram.handlers import DisconnectHandler
+from pyrogram.handlers.handler import Handler
+from pyrogram.scaffold import Scaffold
+
+
+class RemoveHandler(Scaffold):
+ def remove_handler(self, handler: "Handler", group: int = 0):
+ """Remove a previously-registered update handler.
+
+ Make sure to provide the right group where the handler was added in. You can use the return value of the
+ :meth:`~pyrogram.Client.add_handler` method, a tuple of *(handler, group)*, and pass it directly.
+
+ Parameters:
+ handler (``Handler``):
+ The handler to be removed.
+
+ group (``int``, *optional*):
+ The group identifier, defaults to 0.
+
+ Example:
+ .. code-block:: python
+ :emphasize-lines: 11
+
+ from pyrogram import Client, MessageHandler
+
+ def dump(client, message):
+ print(message)
+
+ app = Client("my_account")
+
+ handler = app.add_handler(MessageHandler(dump))
+
+ # Starred expression to unpack (handler, group)
+ app.remove_handler(*handler)
+
+ app.run()
+ """
+ if isinstance(handler, DisconnectHandler):
+ self.disconnect_handler = None
+ else:
+ self.dispatcher.remove_handler(handler, group)
diff --git a/pyrogram/methods/utilities/restart.py b/pyrogram/methods/utilities/restart.py
new file mode 100644
index 0000000000..ad842bc4b3
--- /dev/null
+++ b/pyrogram/methods/utilities/restart.py
@@ -0,0 +1,70 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import asyncio
+
+from pyrogram.scaffold import Scaffold
+
+
+class Restart(Scaffold):
+ async def restart(self, block: bool = True):
+ """Restart the Client.
+
+ This method will first call :meth:`~pyrogram.Client.stop` and then :meth:`~pyrogram.Client.start` in a row in
+ order to restart a client using a single method.
+
+ Parameters:
+ block (``bool``, *optional*):
+ Blocks the code execution until the client has been restarted. It is useful with ``block=False`` in case
+ you want to restart the own client *within* an handler in order not to cause a deadlock.
+ Defaults to True.
+
+ Returns:
+ :obj:`~pyrogram.Client`: The restarted client itself.
+
+ Raises:
+ ConnectionError: In case you try to restart a stopped Client.
+
+ Example:
+ .. code-block:: python
+ :emphasize-lines: 8
+
+ from pyrogram import Client
+
+ app = Client("my_account")
+ app.start()
+
+ ... # Call API methods
+
+ app.restart()
+
+ ... # Call other API methods
+
+ app.stop()
+ """
+
+ async def do_it():
+ await self.stop()
+ await self.start()
+
+ if block:
+ await do_it()
+ else:
+ asyncio.ensure_future(do_it())
+
+ return self
diff --git a/pyrogram/methods/utilities/run.py b/pyrogram/methods/utilities/run.py
new file mode 100644
index 0000000000..dc49a524a4
--- /dev/null
+++ b/pyrogram/methods/utilities/run.py
@@ -0,0 +1,57 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import asyncio
+
+from pyrogram.methods.utilities.idle import idle
+from pyrogram.scaffold import Scaffold
+
+
+class Run(Scaffold):
+ def run(self, coroutine=None):
+ """Start the client, idle the main script and finally stop the client.
+
+ This is a convenience method that calls :meth:`~pyrogram.Client.start`, :meth:`~pyrogram.idle` and
+ :meth:`~pyrogram.Client.stop` in sequence. It makes running a client less verbose, but is not suitable in case
+ you want to run more than one client in a single main script, since :meth:`~pyrogram.idle` will block after
+ starting the own client.
+
+ Raises:
+ ConnectionError: In case you try to run an already started client.
+
+ Example:
+ .. code-block:: python
+ :emphasize-lines: 7
+
+ from pyrogram import Client
+
+ app = Client("my_account")
+
+ ... # Set handlers up
+
+ app.run()
+ """
+ loop = asyncio.get_event_loop()
+ run = loop.run_until_complete
+
+ if coroutine is not None:
+ run(coroutine)
+ else:
+ self.start()
+ run(idle())
+ self.stop()
diff --git a/pyrogram/methods/utilities/start.py b/pyrogram/methods/utilities/start.py
new file mode 100644
index 0000000000..8a8862575e
--- /dev/null
+++ b/pyrogram/methods/utilities/start.py
@@ -0,0 +1,69 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import logging
+
+from pyrogram import raw
+from pyrogram.scaffold import Scaffold
+
+log = logging.getLogger(__name__)
+
+
+class Start(Scaffold):
+ async def start(self):
+ """Start the client.
+
+ This method connects the client to Telegram and, in case of new sessions, automatically manages the full
+ authorization process using an interactive prompt.
+
+ Returns:
+ :obj:`~pyrogram.Client`: The started client itself.
+
+ Raises:
+ ConnectionError: In case you try to start an already started client.
+
+ Example:
+ .. code-block:: python
+ :emphasize-lines: 4
+
+ from pyrogram import Client
+
+ app = Client("my_account")
+ app.start()
+
+ ... # Call API methods
+
+ app.stop()
+ """
+ is_authorized = await self.connect()
+
+ try:
+ if not is_authorized:
+ await self.authorize()
+
+ if not await self.storage.is_bot() and self.takeout:
+ self.takeout_id = (await self.send(raw.functions.account.InitTakeoutSession())).id
+ log.warning(f"Takeout session {self.takeout_id} initiated")
+
+ await self.send(raw.functions.updates.GetState())
+ except (Exception, KeyboardInterrupt):
+ await self.disconnect()
+ raise
+ else:
+ await self.initialize()
+ return self
diff --git a/pyrogram/methods/utilities/stop.py b/pyrogram/methods/utilities/stop.py
new file mode 100644
index 0000000000..b48a143142
--- /dev/null
+++ b/pyrogram/methods/utilities/stop.py
@@ -0,0 +1,65 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import asyncio
+
+from pyrogram.scaffold import Scaffold
+
+
+class Stop(Scaffold):
+ async def stop(self, block: bool = True):
+ """Stop the Client.
+
+ This method disconnects the client from Telegram and stops the underlying tasks.
+
+ Parameters:
+ block (``bool``, *optional*):
+ Blocks the code execution until the client has been stopped. It is useful with ``block=False`` in case
+ you want to stop the own client *within* a handler in order not to cause a deadlock.
+ Defaults to True.
+
+ Returns:
+ :obj:`~pyrogram.Client`: The stopped client itself.
+
+ Raises:
+ ConnectionError: In case you try to stop an already stopped client.
+
+ Example:
+ .. code-block:: python
+ :emphasize-lines: 8
+
+ from pyrogram import Client
+
+ app = Client("my_account")
+ app.start()
+
+ ... # Call API methods
+
+ app.stop()
+ """
+
+ async def do_it():
+ await self.terminate()
+ await self.disconnect()
+
+ if block:
+ await do_it()
+ else:
+ asyncio.ensure_future(do_it())
+
+ return self
diff --git a/pyrogram/methods/utilities/stop_transmission.py b/pyrogram/methods/utilities/stop_transmission.py
new file mode 100644
index 0000000000..6eaedf4d56
--- /dev/null
+++ b/pyrogram/methods/utilities/stop_transmission.py
@@ -0,0 +1,47 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import pyrogram
+from pyrogram.scaffold import Scaffold
+
+
+class StopTransmission(Scaffold):
+ def stop_transmission(self):
+ """Stop downloading or uploading a file.
+
+ This method must be called inside a progress callback function in order to stop the transmission at the
+ desired time. The progress callback is called every time a file chunk is uploaded/downloaded.
+
+ Example:
+ .. code-block:: python
+ :emphasize-lines: 9
+
+ from pyrogram import Client
+
+ app = Client("my_account")
+
+ # Example to stop transmission once the upload progress reaches 50%
+ # Useless in practice, but shows how to stop on command
+ def progress(current, total, client):
+ if (current * 100 / total) > 50:
+ client.stop_transmission()
+
+ with app:
+ app.send_document("me", "files.zip", progress=progress, progress_args=(app,))
+ """
+ raise pyrogram.StopTransmission
diff --git a/pyrogram/client/ext/mime.types b/pyrogram/mime.types
similarity index 100%
rename from pyrogram/client/ext/mime.types
rename to pyrogram/mime.types
diff --git a/pyrogram/client/parser/__init__.py b/pyrogram/parser/__init__.py
similarity index 100%
rename from pyrogram/client/parser/__init__.py
rename to pyrogram/parser/__init__.py
diff --git a/pyrogram/client/parser/html.py b/pyrogram/parser/html.py
similarity index 74%
rename from pyrogram/client/parser/html.py
rename to pyrogram/parser/html.py
index 3ce70d5101..7fa1d94d2e 100644
--- a/pyrogram/client/parser/html.py
+++ b/pyrogram/parser/html.py
@@ -19,12 +19,11 @@
import html
import logging
import re
-from collections import OrderedDict
from html.parser import HTMLParser
from typing import Union
import pyrogram
-from pyrogram.api import types
+from pyrogram import raw
from pyrogram.errors import PeerIdInvalid
from . import utils
@@ -34,7 +33,7 @@
class Parser(HTMLParser):
MENTION_RE = re.compile(r"tg://user\?id=(\d+)")
- def __init__(self, client: "pyrogram.BaseClient"):
+ def __init__(self, client: "pyrogram.Client"):
super().__init__()
self.client = client
@@ -48,19 +47,19 @@ def handle_starttag(self, tag, attrs):
extra = {}
if tag in ["b", "strong"]:
- entity = types.MessageEntityBold
+ entity = raw.types.MessageEntityBold
elif tag in ["i", "em"]:
- entity = types.MessageEntityItalic
+ entity = raw.types.MessageEntityItalic
elif tag == "u":
- entity = types.MessageEntityUnderline
+ entity = raw.types.MessageEntityUnderline
elif tag in ["s", "del", "strike"]:
- entity = types.MessageEntityStrike
+ entity = raw.types.MessageEntityStrike
elif tag == "blockquote":
- entity = types.MessageEntityBlockquote
+ entity = raw.types.MessageEntityBlockquote
elif tag == "code":
- entity = types.MessageEntityCode
+ entity = raw.types.MessageEntityCode
elif tag == "pre":
- entity = types.MessageEntityPre
+ entity = raw.types.MessageEntityPre
extra["language"] = ""
elif tag == "a":
url = attrs.get("href", "")
@@ -68,10 +67,10 @@ def handle_starttag(self, tag, attrs):
mention = Parser.MENTION_RE.match(url)
if mention:
- entity = types.InputMessageEntityMentionName
+ entity = raw.types.InputMessageEntityMentionName
extra["user_id"] = int(mention.group(1))
else:
- entity = types.MessageEntityTextUrl
+ entity = raw.types.MessageEntityTextUrl
extra["url"] = url
else:
return
@@ -97,7 +96,7 @@ def handle_endtag(self, tag):
line, offset = self.getpos()
offset += 1
- log.warning("Unmatched closing tag {}> at line {}:{}".format(tag, line, offset))
+ log.warning(f"Unmatched closing tag {tag}> at line {line}:{offset}")
else:
if not self.tag_entities[tag]:
self.tag_entities.pop(tag)
@@ -107,7 +106,7 @@ def error(self, message):
class HTML:
- def __init__(self, client: Union["pyrogram.BaseClient", None]):
+ def __init__(self, client: Union["pyrogram.Client", None]):
self.client = client
async def parse(self, text: str):
@@ -122,14 +121,14 @@ async def parse(self, text: str):
unclosed_tags = []
for tag, entities in parser.tag_entities.items():
- unclosed_tags.append("<{}> (x{})".format(tag, len(entities)))
+ unclosed_tags.append(f"<{tag}> (x{len(entities)})")
- log.warning("Unclosed tags: {}".format(", ".join(unclosed_tags)))
+ log.warning(f"Unclosed tags: {', '.join(unclosed_tags)}")
entities = []
for entity in parser.entities:
- if isinstance(entity, types.InputMessageEntityMentionName):
+ if isinstance(entity, raw.types.InputMessageEntityMentionName):
try:
if self.client is not None:
entity.user_id = await self.client.resolve_peer(entity.user_id)
@@ -138,11 +137,10 @@ async def parse(self, text: str):
entities.append(entity)
- # TODO: OrderedDict to be removed in Python 3.6
- return OrderedDict([
- ("message", utils.remove_surrogates(parser.text)),
- ("entities", sorted(entities, key=lambda e: e.offset))
- ])
+ return {
+ "message": utils.remove_surrogates(parser.text),
+ "entities": sorted(entities, key=lambda e: e.offset)
+ }
@staticmethod
def unparse(text: str, entities: list):
@@ -156,18 +154,18 @@ def unparse(text: str, entities: list):
end = start + entity.length
if entity_type in ("bold", "italic", "underline", "strike"):
- start_tag = "<{}>".format(entity_type[0])
- end_tag = "{}>".format(entity_type[0])
+ start_tag = f"<{entity_type[0]}>"
+ end_tag = "f{entity_type[0]}>"
elif entity_type in ("code", "pre", "blockquote"):
- start_tag = "<{}>".format(entity_type)
- end_tag = "{}>".format(entity_type)
+ start_tag = f"<{entity_type}>"
+ end_tag = f"{entity_type}>"
elif entity_type == "text_link":
url = entity.url
- start_tag = ''.format(url)
+ start_tag = f''
end_tag = ""
elif entity_type == "text_mention":
user = entity.user
- start_tag = ''.format(user.id)
+ start_tag = f''
end_tag = ""
else:
continue
diff --git a/pyrogram/client/parser/markdown.py b/pyrogram/parser/markdown.py
similarity index 95%
rename from pyrogram/client/parser/markdown.py
rename to pyrogram/parser/markdown.py
index 4c954efd63..e821dbd378 100644
--- a/pyrogram/client/parser/markdown.py
+++ b/pyrogram/parser/markdown.py
@@ -34,7 +34,7 @@
MARKDOWN_RE = re.compile(r"({d})|\[(.+?)\]\((.+?)\)".format(
d="|".join(
["".join(i) for i in [
- [r"\{}".format(j) for j in i]
+ [rf"\{j}" for j in i]
for i in [
PRE_DELIM,
CODE_DELIM,
@@ -53,7 +53,7 @@
class Markdown:
- def __init__(self, client: Union["pyrogram.BaseClient", None]):
+ def __init__(self, client: Union["pyrogram.Client", None]):
self.html = HTML(client)
async def parse(self, text: str, strict: bool = False):
@@ -130,11 +130,11 @@ def unparse(text: str, entities: list):
elif entity_type == "text_link":
url = entity.url
start_tag = "["
- end_tag = "]({})".format(url)
+ end_tag = f"]({url})"
elif entity_type == "text_mention":
user = entity.user
start_tag = "["
- end_tag = "](tg://user?id={})".format(user.id)
+ end_tag = f"](tg://user?id={user.id})"
else:
continue
diff --git a/pyrogram/client/parser/parser.py b/pyrogram/parser/parser.py
similarity index 93%
rename from pyrogram/client/parser/parser.py
rename to pyrogram/parser/parser.py
index eb4f2e19b9..64d172417c 100644
--- a/pyrogram/client/parser/parser.py
+++ b/pyrogram/parser/parser.py
@@ -25,7 +25,7 @@
class Parser:
- def __init__(self, client: Union["pyrogram.BaseClient", None]):
+ def __init__(self, client: Union["pyrogram.Client", None]):
self.client = client
self.html = HTML(client)
self.markdown = Markdown(client)
@@ -57,7 +57,7 @@ async def parse(self, text: str, mode: Union[str, None] = object):
return await self.html.parse(text)
raise ValueError('parse_mode must be one of {} or None. Not "{}"'.format(
- ", ".join('"{}"'.format(m) for m in pyrogram.Client.PARSE_MODES[:-1]),
+ ", ".join(f'"{m}"' for m in pyrogram.Client.PARSE_MODES[:-1]),
mode
))
diff --git a/pyrogram/client/parser/utils.py b/pyrogram/parser/utils.py
similarity index 100%
rename from pyrogram/client/parser/utils.py
rename to pyrogram/parser/utils.py
diff --git a/pyrogram/api/__init__.py b/pyrogram/raw/__init__.py
similarity index 95%
rename from pyrogram/api/__init__.py
rename to pyrogram/raw/__init__.py
index da5b075e7b..2bbf90d772 100644
--- a/pyrogram/api/__init__.py
+++ b/pyrogram/raw/__init__.py
@@ -18,6 +18,7 @@
from importlib import import_module
+from . import types, functions, base, core
from .all import objects
for k, v in objects.items():
diff --git a/pyrogram/api/core/__init__.py b/pyrogram/raw/core/__init__.py
similarity index 80%
rename from pyrogram/api/core/__init__.py
rename to pyrogram/raw/core/__init__.py
index 22484f6fb2..0a4b2a8297 100644
--- a/pyrogram/api/core/__init__.py
+++ b/pyrogram/raw/core/__init__.py
@@ -22,5 +22,10 @@
from .list import List
from .message import Message
from .msg_container import MsgContainer
-from .primitives import *
+from .primitives.bool import Bool, BoolFalse, BoolTrue
+from .primitives.bytes import Bytes
+from .primitives.double import Double
+from .primitives.int import Int, Long, Int128, Int256
+from .primitives.string import String
+from .primitives.vector import Vector
from .tl_object import TLObject
diff --git a/pyrogram/api/core/future_salt.py b/pyrogram/raw/core/future_salt.py
similarity index 83%
rename from pyrogram/api/core/future_salt.py
rename to pyrogram/raw/core/future_salt.py
index cc9f7bc0fa..7d163e6b4a 100644
--- a/pyrogram/api/core/future_salt.py
+++ b/pyrogram/raw/core/future_salt.py
@@ -17,13 +17,14 @@
# along with Pyrogram. If not, see .
from io import BytesIO
+from typing import Any
-from .primitives import Int, Long
+from .primitives.int import Int, Long
from .tl_object import TLObject
class FutureSalt(TLObject):
- ID = 0x0949d9dc
+ ID = 0x0949D9DC
__slots__ = ["valid_since", "valid_until", "salt"]
@@ -35,9 +36,9 @@ def __init__(self, valid_since: int, valid_until: int, salt: int):
self.salt = salt
@staticmethod
- def read(b: BytesIO, *args) -> "FutureSalt":
- valid_since = Int.read(b)
- valid_until = Int.read(b)
- salt = Long.read(b)
+ def read(data: BytesIO, *args: Any) -> "FutureSalt":
+ valid_since = Int.read(data)
+ valid_until = Int.read(data)
+ salt = Long.read(data)
return FutureSalt(valid_since, valid_until, salt)
diff --git a/pyrogram/api/core/future_salts.py b/pyrogram/raw/core/future_salts.py
similarity index 73%
rename from pyrogram/api/core/future_salts.py
rename to pyrogram/raw/core/future_salts.py
index f22b464301..f8a4835311 100644
--- a/pyrogram/api/core/future_salts.py
+++ b/pyrogram/raw/core/future_salts.py
@@ -17,30 +17,31 @@
# along with Pyrogram. If not, see .
from io import BytesIO
+from typing import Any, List
-from . import FutureSalt
-from .primitives import Int, Long
+from .future_salt import FutureSalt
+from .primitives.int import Int, Long
from .tl_object import TLObject
class FutureSalts(TLObject):
- ID = 0xae500895
+ ID = 0xAE500895
__slots__ = ["req_msg_id", "now", "salts"]
QUALNAME = "FutureSalts"
- def __init__(self, req_msg_id: int, now: int, salts: list):
+ def __init__(self, req_msg_id: int, now: int, salts: List[FutureSalt]):
self.req_msg_id = req_msg_id
self.now = now
self.salts = salts
@staticmethod
- def read(b: BytesIO, *args) -> "FutureSalts":
- req_msg_id = Long.read(b)
- now = Int.read(b)
+ def read(data: BytesIO, *args: Any) -> "FutureSalts":
+ req_msg_id = Long.read(data)
+ now = Int.read(data)
- count = Int.read(b)
- salts = [FutureSalt.read(b) for _ in range(count)]
+ count = Int.read(data)
+ salts = [FutureSalt.read(data) for _ in range(count)]
return FutureSalts(req_msg_id, now, salts)
diff --git a/pyrogram/api/core/gzip_packed.py b/pyrogram/raw/core/gzip_packed.py
similarity index 82%
rename from pyrogram/api/core/gzip_packed.py
rename to pyrogram/raw/core/gzip_packed.py
index 1920c67de7..094162d59d 100644
--- a/pyrogram/api/core/gzip_packed.py
+++ b/pyrogram/raw/core/gzip_packed.py
@@ -18,13 +18,15 @@
from gzip import compress, decompress
from io import BytesIO
+from typing import cast, Any
-from .primitives import Int, Bytes
+from .primitives.bytes import Bytes
+from .primitives.int import Int
from .tl_object import TLObject
class GzipPacked(TLObject):
- ID = 0x3072cfa1
+ ID = 0x3072CFA1
__slots__ = ["packed_data"]
@@ -34,17 +36,17 @@ def __init__(self, packed_data: TLObject):
self.packed_data = packed_data
@staticmethod
- def read(b: BytesIO, *args) -> "GzipPacked":
+ def read(data: BytesIO, *args: Any) -> "GzipPacked":
# Return the Object itself instead of a GzipPacked wrapping it
- return TLObject.read(
+ return cast(GzipPacked, TLObject.read(
BytesIO(
decompress(
- Bytes.read(b)
+ Bytes.read(data)
)
)
- )
+ ))
- def write(self) -> bytes:
+ def write(self, *args: Any) -> bytes:
b = BytesIO()
b.write(Int(self.ID, False))
diff --git a/pyrogram/api/core/list.py b/pyrogram/raw/core/list.py
similarity index 81%
rename from pyrogram/api/core/list.py
rename to pyrogram/raw/core/list.py
index 0e083f17a6..c0014b6841 100644
--- a/pyrogram/api/core/list.py
+++ b/pyrogram/raw/core/list.py
@@ -16,13 +16,11 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from .tl_object import TLObject
+from typing import List as TList, Any
+from .tl_object import TLObject
-class List(list, TLObject):
- __slots__ = []
- def __repr__(self):
- return "pyrogram.api.core.List([{}])".format(
- ",".join(TLObject.__repr__(i) for i in self)
- )
+class List(TList[Any], TLObject):
+ def __repr__(self) -> str:
+ return f"pyrogram.api.core.List([{','.join(TLObject.__repr__(i) for i in self)}])"
diff --git a/pyrogram/api/core/message.py b/pyrogram/raw/core/message.py
similarity index 81%
rename from pyrogram/api/core/message.py
rename to pyrogram/raw/core/message.py
index 787aa3785d..e1e595a042 100644
--- a/pyrogram/api/core/message.py
+++ b/pyrogram/raw/core/message.py
@@ -17,13 +17,14 @@
# along with Pyrogram. If not, see .
from io import BytesIO
+from typing import Any
-from .primitives import Int, Long
+from .primitives.int import Int, Long
from .tl_object import TLObject
class Message(TLObject):
- ID = 0x5bb8e511 # hex(crc32(b"message msg_id:long seqno:int bytes:int body:Object = Message"))
+ ID = 0x5BB8E511 # hex(crc32(b"message msg_id:long seqno:int bytes:int body:Object = Message"))
__slots__ = ["msg_id", "seq_no", "length", "body"]
@@ -36,15 +37,15 @@ def __init__(self, body: TLObject, msg_id: int, seq_no: int, length: int):
self.body = body
@staticmethod
- def read(b: BytesIO, *args) -> "Message":
- msg_id = Long.read(b)
- seq_no = Int.read(b)
- length = Int.read(b)
- body = b.read(length)
+ def read(data: BytesIO, *args: Any) -> "Message":
+ msg_id = Long.read(data)
+ seq_no = Int.read(data)
+ length = Int.read(data)
+ body = data.read(length)
return Message(TLObject.read(BytesIO(body)), msg_id, seq_no, length)
- def write(self) -> bytes:
+ def write(self, *args: Any) -> bytes:
b = BytesIO()
b.write(Long(self.msg_id))
diff --git a/pyrogram/api/core/msg_container.py b/pyrogram/raw/core/msg_container.py
similarity index 79%
rename from pyrogram/api/core/msg_container.py
rename to pyrogram/raw/core/msg_container.py
index dc6f755d74..aecf7dfc78 100644
--- a/pyrogram/api/core/msg_container.py
+++ b/pyrogram/raw/core/msg_container.py
@@ -17,28 +17,29 @@
# along with Pyrogram. If not, see .
from io import BytesIO
+from typing import List, Any
from .message import Message
-from .primitives import Int
+from .primitives.int import Int
from .tl_object import TLObject
class MsgContainer(TLObject):
- ID = 0x73f1f8dc
+ ID = 0x73F1F8DC
__slots__ = ["messages"]
QUALNAME = "MsgContainer"
- def __init__(self, messages: list):
+ def __init__(self, messages: List[Message]):
self.messages = messages
@staticmethod
- def read(b: BytesIO, *args) -> "MsgContainer":
- count = Int.read(b)
- return MsgContainer([Message.read(b) for _ in range(count)])
+ def read(data: BytesIO, *args: Any) -> "MsgContainer":
+ count = Int.read(data)
+ return MsgContainer([Message.read(data) for _ in range(count)])
- def write(self) -> bytes:
+ def write(self, *args: Any) -> bytes:
b = BytesIO()
b.write(Int(self.ID, False))
diff --git a/pyrogram/api/core/primitives/__init__.py b/pyrogram/raw/core/primitives/__init__.py
similarity index 89%
rename from pyrogram/api/core/primitives/__init__.py
rename to pyrogram/raw/core/primitives/__init__.py
index f7b1c89ec8..9f6de65a0d 100644
--- a/pyrogram/api/core/primitives/__init__.py
+++ b/pyrogram/raw/core/primitives/__init__.py
@@ -22,5 +22,3 @@
from .int import Int, Long, Int128, Int256
from .string import String
from .vector import Vector
-
-__all__ = ["Bool", "BoolFalse", "BoolTrue", "Bytes", "Double", "Int", "Long", "Int128", "Int256", "String", "Vector"]
diff --git a/pyrogram/api/core/primitives/bool.py b/pyrogram/raw/core/primitives/bool.py
similarity index 73%
rename from pyrogram/api/core/primitives/bool.py
rename to pyrogram/raw/core/primitives/bool.py
index 966372255f..a8fb5b4ec5 100644
--- a/pyrogram/api/core/primitives/bool.py
+++ b/pyrogram/raw/core/primitives/bool.py
@@ -17,31 +17,32 @@
# along with Pyrogram. If not, see .
from io import BytesIO
+from typing import Any
from ..tl_object import TLObject
-class BoolFalse(TLObject):
- ID = 0xbc799737
+class BoolFalse(bytes, TLObject):
+ ID = 0xBC799737
value = False
@classmethod
- def read(cls, *args) -> bool:
+ def read(cls, *args: Any) -> bool:
return cls.value
- def __new__(cls) -> bytes:
+ def __new__(cls) -> bytes: # type: ignore
return cls.ID.to_bytes(4, "little")
class BoolTrue(BoolFalse):
- ID = 0x997275b5
+ ID = 0x997275B5
value = True
-class Bool(TLObject):
+class Bool(bytes, TLObject):
@classmethod
- def read(cls, b: BytesIO) -> bool:
- return int.from_bytes(b.read(4), "little") == BoolTrue.ID
+ def read(cls, data: BytesIO, *args: Any) -> bool:
+ return int.from_bytes(data.read(4), "little") == BoolTrue.ID
- def __new__(cls, value: bool) -> BoolTrue or BoolFalse:
+ def __new__(cls, value: bool) -> bytes: # type: ignore
return BoolTrue() if value else BoolFalse()
diff --git a/pyrogram/api/core/primitives/bytes.py b/pyrogram/raw/core/primitives/bytes.py
similarity index 74%
rename from pyrogram/api/core/primitives/bytes.py
rename to pyrogram/raw/core/primitives/bytes.py
index 298ea5440a..8c95ebdec9 100644
--- a/pyrogram/api/core/primitives/bytes.py
+++ b/pyrogram/raw/core/primitives/bytes.py
@@ -17,26 +17,27 @@
# along with Pyrogram. If not, see .
from io import BytesIO
+from typing import Any
from ..tl_object import TLObject
-class Bytes(TLObject):
- @staticmethod
- def read(b: BytesIO, *args) -> bytes:
- length = int.from_bytes(b.read(1), "little")
+class Bytes(bytes, TLObject):
+ @classmethod
+ def read(cls, data: BytesIO, *args: Any) -> bytes:
+ length = int.from_bytes(data.read(1), "little")
if length <= 253:
- x = b.read(length)
- b.read(-(length + 1) % 4)
+ x = data.read(length)
+ data.read(-(length + 1) % 4)
else:
- length = int.from_bytes(b.read(3), "little")
- x = b.read(length)
- b.read(-length % 4)
+ length = int.from_bytes(data.read(3), "little")
+ x = data.read(length)
+ data.read(-length % 4)
return x
- def __new__(cls, value: bytes) -> bytes:
+ def __new__(cls, value: bytes) -> bytes: # type: ignore
length = len(value)
if length <= 253:
diff --git a/pyrogram/api/core/primitives/double.py b/pyrogram/raw/core/primitives/double.py
similarity index 78%
rename from pyrogram/api/core/primitives/double.py
rename to pyrogram/raw/core/primitives/double.py
index 42cf0031ee..43dd5d2c76 100644
--- a/pyrogram/api/core/primitives/double.py
+++ b/pyrogram/raw/core/primitives/double.py
@@ -18,14 +18,15 @@
from io import BytesIO
from struct import unpack, pack
+from typing import cast, Any
from ..tl_object import TLObject
-class Double(TLObject):
- @staticmethod
- def read(b: BytesIO, *args) -> float:
- return unpack("d", b.read(8))[0]
+class Double(bytes, TLObject):
+ @classmethod
+ def read(cls, data: BytesIO, *args: Any) -> float:
+ return cast(float, unpack("d", data.read(8))[0])
- def __new__(cls, value: float) -> bytes:
+ def __new__(cls, value: float) -> bytes: # type: ignore
return pack("d", value)
diff --git a/pyrogram/api/core/primitives/int.py b/pyrogram/raw/core/primitives/int.py
similarity index 79%
rename from pyrogram/api/core/primitives/int.py
rename to pyrogram/raw/core/primitives/int.py
index bbaf7f2fcf..7e6135d1db 100644
--- a/pyrogram/api/core/primitives/int.py
+++ b/pyrogram/raw/core/primitives/int.py
@@ -17,18 +17,19 @@
# along with Pyrogram. If not, see .
from io import BytesIO
+from typing import Any
from ..tl_object import TLObject
-class Int(TLObject):
+class Int(bytes, TLObject):
SIZE = 4
@classmethod
- def read(cls, b: BytesIO, signed: bool = True) -> int:
- return int.from_bytes(b.read(cls.SIZE), "little", signed=signed)
+ def read(cls, data: BytesIO, signed: bool = True, *args: Any) -> int:
+ return int.from_bytes(data.read(cls.SIZE), "little", signed=signed)
- def __new__(cls, value: int, signed: bool = True) -> bytes:
+ def __new__(cls, value: int, signed: bool = True) -> bytes: # type: ignore
return value.to_bytes(cls.SIZE, "little", signed=signed)
diff --git a/pyrogram/api/core/primitives/string.py b/pyrogram/raw/core/primitives/string.py
similarity index 76%
rename from pyrogram/api/core/primitives/string.py
rename to pyrogram/raw/core/primitives/string.py
index a0995c5b9a..dd25b5bfbb 100644
--- a/pyrogram/api/core/primitives/string.py
+++ b/pyrogram/raw/core/primitives/string.py
@@ -17,14 +17,15 @@
# along with Pyrogram. If not, see .
from io import BytesIO
+from typing import cast
-from . import Bytes
+from .bytes import Bytes
class String(Bytes):
- @staticmethod
- def read(b: BytesIO, *args) -> str:
- return super(String, String).read(b).decode(errors="replace")
+ @classmethod
+ def read(cls, data: BytesIO, *args) -> str: # type: ignore
+ return cast(bytes, super(String, String).read(data)).decode(errors="replace")
- def __new__(cls, value: str) -> bytes:
+ def __new__(cls, value: str) -> bytes: # type: ignore
return super().__new__(cls, value.encode())
diff --git a/pyrogram/api/core/primitives/vector.py b/pyrogram/raw/core/primitives/vector.py
similarity index 73%
rename from pyrogram/api/core/primitives/vector.py
rename to pyrogram/raw/core/primitives/vector.py
index 2c60f5766c..afb7d591eb 100644
--- a/pyrogram/api/core/primitives/vector.py
+++ b/pyrogram/raw/core/primitives/vector.py
@@ -17,39 +17,36 @@
# along with Pyrogram. If not, see .
from io import BytesIO
+from typing import cast, Union, Any
-from . import Int
+from .int import Int
from ..list import List
from ..tl_object import TLObject
-class Vector(TLObject):
- ID = 0x1cb5c415
+class Vector(bytes, TLObject):
+ ID = 0x1CB5C415
# Method added to handle the special case when a query returns a bare Vector (of Ints);
# i.e., RpcResult body starts with 0x1cb5c415 (Vector Id) - e.g., messages.GetMessagesViews.
@staticmethod
- def _read(b: BytesIO) -> TLObject or int:
+ def _read(b: BytesIO) -> Union[int, Any]:
try:
return TLObject.read(b)
except KeyError:
b.seek(-4, 1)
return Int.read(b)
- @staticmethod
- def read(b: BytesIO, t: TLObject = None) -> list:
+ @classmethod
+ def read(cls, data: BytesIO, t: Any = None, *args: Any) -> List:
return List(
- t.read(b) if t
- else Vector._read(b)
- for _ in range(Int.read(b))
+ t.read(data) if t
+ else Vector._read(data)
+ for _ in range(Int.read(data))
)
- def __new__(cls, value: list, t: TLObject = None) -> bytes:
+ def __new__(cls, value: list, t: Any = None) -> bytes: # type: ignore
return b"".join(
[Int(cls.ID, False), Int(len(value))]
- + [
- t(i) if t
- else i.write()
- for i in value
- ]
+ + [cast(bytes, t(i)) if t else i.write() for i in value]
)
diff --git a/pyrogram/api/core/tl_object.py b/pyrogram/raw/core/tl_object.py
similarity index 71%
rename from pyrogram/api/core/tl_object.py
rename to pyrogram/raw/core/tl_object.py
index d9d5722f1b..0391ab85f6 100644
--- a/pyrogram/api/core/tl_object.py
+++ b/pyrogram/raw/core/tl_object.py
@@ -16,38 +16,38 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from collections import OrderedDict
from io import BytesIO
from json import dumps
+from typing import cast, List, Any, Union, Dict
from ..all import objects
class TLObject:
- __slots__ = []
+ __slots__: List[str] = []
QUALNAME = "Base"
- @staticmethod
- def read(b: BytesIO, *args): # TODO: Rename b -> data
- return objects[int.from_bytes(b.read(4), "little")].read(b, *args)
+ @classmethod
+ def read(cls, data: BytesIO, *args: Any) -> Any:
+ return cast(TLObject, objects[int.from_bytes(data.read(4), "little")]).read(data, *args)
- def write(self, *args) -> bytes:
+ def write(self, *args: Any) -> bytes:
pass
@staticmethod
- def default(obj: "TLObject"):
+ def default(obj: "TLObject") -> Union[str, Dict[str, str]]:
if isinstance(obj, bytes):
return repr(obj)
- return OrderedDict(
- [("_", obj.QUALNAME)]
- + [
- (attr, getattr(obj, attr))
+ return {
+ "_": obj.QUALNAME,
+ **{
+ attr: getattr(obj, attr)
for attr in obj.__slots__
if getattr(obj, attr) is not None
- ]
- )
+ }
+ }
def __str__(self) -> str:
return dumps(self, indent=4, default=TLObject.default, ensure_ascii=False)
@@ -56,13 +56,13 @@ def __repr__(self) -> str:
return "pyrogram.api.{}({})".format(
self.QUALNAME,
", ".join(
- "{}={}".format(attr, repr(getattr(self, attr)))
+ f"{attr}={repr(getattr(self, attr))}"
for attr in self.__slots__
if getattr(self, attr) is not None
)
)
- def __eq__(self, other: "TLObject") -> bool:
+ def __eq__(self, other: Any) -> bool:
for attr in self.__slots__:
try:
if getattr(self, attr) != getattr(other, attr):
@@ -75,8 +75,11 @@ def __eq__(self, other: "TLObject") -> bool:
def __len__(self) -> int:
return len(self.write())
- def __getitem__(self, item):
+ def __getitem__(self, item: Any) -> Any:
return getattr(self, item)
- def __setitem__(self, key, value):
+ def __setitem__(self, key: Any, value: Any) -> Any:
setattr(self, key, value)
+
+ def __call__(self, *args: Any, **kwargs: Any) -> Any:
+ pass
diff --git a/pyrogram/client/ext/base_client.py b/pyrogram/scaffold.py
similarity index 65%
rename from pyrogram/client/ext/base_client.py
rename to pyrogram/scaffold.py
index ca4e8f5ba1..0b3bf02185 100644
--- a/pyrogram/client/ext/base_client.py
+++ b/pyrogram/scaffold.py
@@ -24,36 +24,21 @@
from pathlib import Path
from pyrogram import __version__
-from ..parser import Parser
-from ...session.internals import MsgId
+from pyrogram.parser import Parser
+from pyrogram.session.internals import MsgId
-class BaseClient:
- class StopTransmission(StopAsyncIteration):
- pass
-
- APP_VERSION = "Pyrogram {}".format(__version__)
-
- DEVICE_MODEL = "{} {}".format(
- platform.python_implementation(),
- platform.python_version()
- )
-
- SYSTEM_VERSION = "{} {}".format(
- platform.system(),
- platform.release()
- )
+class Scaffold:
+ APP_VERSION = f"Pyrogram {__version__}"
+ DEVICE_MODEL = f"{platform.python_implementation()} {platform.python_version()}"
+ SYSTEM_VERSION = f"{platform.system()} {platform.release()}"
LANG_CODE = "en"
PARENT_DIR = Path(sys.argv[0]).parent
INVITE_LINK_RE = re.compile(r"^(?:https?://)?(?:www\.)?(?:t(?:elegram)?\.(?:org|me|dog)/joinchat/)([\w-]+)$")
- DIALOGS_AT_ONCE = 100
- UPDATES_WORKERS = 4
- DOWNLOAD_WORKERS = 4
- OFFLINE_SLEEP = 900
- WORKERS = 4
+ WORKERS = min(32, os.cpu_count() + 4)
WORKDIR = PARENT_DIR
CONFIG_FILE = PARENT_DIR / "config.ini"
@@ -76,20 +61,44 @@ class StopTransmission(StopAsyncIteration):
mime_types_to_extensions = {}
extensions_to_mime_types = {}
- with open("{}/mime.types".format(os.path.dirname(__file__)), "r", encoding="UTF-8") as f:
+ with open(f"{os.path.dirname(__file__)}/mime.types", "r", encoding="UTF-8") as f:
for match in re.finditer(r"^([^#\s]+)\s+(.+)$", f.read(), flags=re.M):
mime_type, extensions = match.groups()
- extensions = [".{}".format(ext) for ext in extensions.split(" ")]
+ extensions = [f".{ext}" for ext in extensions.split(" ")]
for ext in extensions:
extensions_to_mime_types[ext] = mime_type
mime_types_to_extensions[mime_type] = " ".join(extensions)
- is_idling = False
-
def __init__(self):
+ self.session_name = None
+ self.api_id = None
+ self.api_hash = None
+ self.app_version = None
+ self.device_model = None
+ self.system_version = None
+ self.lang_code = None
+ self.ipv6 = None
+ self.proxy = None
+ self.test_mode = None
+ self.bot_token = None
+ self.phone_number = None
+ self.phone_code = None
+ self.password = None
+ self.force_sms = None
+ self.workers = None
+ self.workdir = None
+ self.config_file = None
+ self.plugins = None
+ self.parse_mode = None
+ self.no_updates = None
+ self.takeout = None
+ self.sleep_threshold = None
+
+ self.executor = None
+
self.storage = None
self.rnd_id = MsgId
@@ -98,21 +107,22 @@ def __init__(self):
self.parse_mode = "combined"
self.session = None
+
self.media_sessions = {}
self.media_sessions_lock = asyncio.Lock()
self.is_connected = None
self.is_initialized = None
+ self.no_updates = None
self.takeout_id = None
- self.updates_queue = asyncio.Queue()
- self.updates_worker_tasks = []
- self.download_queue = asyncio.Queue()
- self.download_worker_tasks = []
+ self.dispatcher = None
self.disconnect_handler = None
+ self.loop = None
+
async def send(self, *args, **kwargs):
pass
@@ -172,3 +182,36 @@ def guess_mime_type(self, *args, **kwargs):
def guess_extension(self, *args, **kwargs):
pass
+
+ def load_config(self, *args, **kwargs):
+ pass
+
+ def load_session(self, *args, **kwargs):
+ pass
+
+ def load_plugins(self, *args, **kwargs):
+ pass
+
+ async def handle_download(self, *args, **kwargs):
+ pass
+
+ async def start(self, *args, **kwargs):
+ pass
+
+ async def stop(self, *args, **kwargs):
+ pass
+
+ async def connect(self, *args, **kwargs):
+ pass
+
+ async def authorize(self, *args, **kwargs):
+ pass
+
+ async def disconnect(self, *args, **kwargs):
+ pass
+
+ async def initialize(self, *args, **kwargs):
+ pass
+
+ async def terminate(self, *args, **kwargs):
+ pass
diff --git a/pyrogram/session/auth.py b/pyrogram/session/auth.py
index 6795928a7b..2aa658216e 100644
--- a/pyrogram/session/auth.py
+++ b/pyrogram/session/auth.py
@@ -24,10 +24,10 @@
from os import urandom
import pyrogram
-from pyrogram.api import functions, types
-from pyrogram.api.core import TLObject, Long, Int
+from pyrogram import raw
from pyrogram.connection import Connection
-from pyrogram.crypto import AES, RSA, Prime
+from pyrogram.crypto import aes, rsa, prime
+from pyrogram.raw.core import TLObject, Long, Int
from .internals import MsgId
log = logging.getLogger(__name__)
@@ -36,9 +36,9 @@
class Auth:
MAX_RETRIES = 5
- def __init__(self, client: "pyrogram.Client", dc_id: int):
+ def __init__(self, client: "pyrogram.Client", dc_id: int, test_mode: bool):
self.dc_id = dc_id
- self.test_mode = client.storage.test_mode()
+ self.test_mode = test_mode
self.ipv6 = client.ipv6
self.proxy = client.proxy
@@ -78,40 +78,40 @@ async def create(self):
self.connection = Connection(self.dc_id, self.test_mode, self.ipv6, self.proxy)
try:
- log.info("Start creating a new auth key on DC{}".format(self.dc_id))
+ log.info(f"Start creating a new auth key on DC{self.dc_id}")
await self.connection.connect()
# Step 1; Step 2
nonce = int.from_bytes(urandom(16), "little", signed=True)
- log.debug("Send req_pq: {}".format(nonce))
- res_pq = await self.send(functions.ReqPqMulti(nonce=nonce))
- log.debug("Got ResPq: {}".format(res_pq.server_nonce))
- log.debug("Server public key fingerprints: {}".format(res_pq.server_public_key_fingerprints))
+ log.debug(f"Send req_pq: {nonce}")
+ res_pq = await self.send(raw.functions.ReqPqMulti(nonce=nonce))
+ log.debug(f"Got ResPq: {res_pq.server_nonce}")
+ log.debug(f"Server public key fingerprints: {res_pq.server_public_key_fingerprints}")
for i in res_pq.server_public_key_fingerprints:
- if i in RSA.server_public_keys:
- log.debug("Using fingerprint: {}".format(i))
+ if i in rsa.server_public_keys:
+ log.debug(f"Using fingerprint: {i}")
public_key_fingerprint = i
break
else:
- log.debug("Fingerprint unknown: {}".format(i))
+ log.debug(f"Fingerprint unknown: {i}")
else:
raise Exception("Public key not found")
# Step 3
pq = int.from_bytes(res_pq.pq, "big")
- log.debug("Start PQ factorization: {}".format(pq))
+ log.debug(f"Start PQ factorization: {pq}")
start = time.time()
- g = Prime.decompose(pq)
+ g = prime.decompose(pq)
p, q = sorted((g, pq // g)) # p < q
- log.debug("Done PQ factorization ({}s): {} {}".format(round(time.time() - start, 3), p, q))
+ log.debug(f"Done PQ factorization ({round(time.time() - start, 3)}s): {p} {q}")
# Step 4
server_nonce = res_pq.server_nonce
new_nonce = int.from_bytes(urandom(32), "little", signed=True)
- data = types.PQInnerData(
+ data = raw.types.PQInnerData(
pq=res_pq.pq,
p=p.to_bytes(4, "big"),
q=q.to_bytes(4, "big"),
@@ -123,14 +123,14 @@ async def create(self):
sha = sha1(data).digest()
padding = urandom(- (len(data) + len(sha)) % 255)
data_with_hash = sha + data + padding
- encrypted_data = RSA.encrypt(data_with_hash, public_key_fingerprint)
+ encrypted_data = rsa.encrypt(data_with_hash, public_key_fingerprint)
log.debug("Done encrypt data with RSA")
# Step 5. TODO: Handle "server_DH_params_fail". Code assumes response is ok
log.debug("Send req_DH_params")
server_dh_params = await self.send(
- functions.ReqDHParams(
+ raw.functions.ReqDHParams(
nonce=nonce,
server_nonce=server_nonce,
p=p.to_bytes(4, "big"),
@@ -157,7 +157,7 @@ async def create(self):
server_nonce = int.from_bytes(server_nonce, "little", signed=True)
- answer_with_hash = AES.ige256_decrypt(encrypted_answer, tmp_aes_key, tmp_aes_iv)
+ answer_with_hash = aes.ige256_decrypt(encrypted_answer, tmp_aes_key, tmp_aes_iv)
answer = answer_with_hash[20:]
server_dh_inner_data = TLObject.read(BytesIO(answer))
@@ -167,7 +167,7 @@ async def create(self):
dh_prime = int.from_bytes(server_dh_inner_data.dh_prime, "big")
delta_time = server_dh_inner_data.server_time - time.time()
- log.debug("Delta time: {}".format(round(delta_time, 3)))
+ log.debug(f"Delta time: {round(delta_time, 3)}")
# Step 6
g = server_dh_inner_data.g
@@ -176,7 +176,7 @@ async def create(self):
retry_id = 0
- data = types.ClientDHInnerData(
+ data = raw.types.ClientDHInnerData(
nonce=nonce,
server_nonce=server_nonce,
retry_id=retry_id,
@@ -186,11 +186,11 @@ async def create(self):
sha = sha1(data).digest()
padding = urandom(- (len(data) + len(sha)) % 16)
data_with_hash = sha + data + padding
- encrypted_data = AES.ige256_encrypt(data_with_hash, tmp_aes_key, tmp_aes_iv)
+ encrypted_data = aes.ige256_encrypt(data_with_hash, tmp_aes_key, tmp_aes_iv)
log.debug("Send set_client_DH_params")
set_client_dh_params_answer = await self.send(
- functions.SetClientDHParams(
+ raw.functions.SetClientDHParams(
nonce=nonce,
server_nonce=server_nonce,
encrypted_data=encrypted_data
@@ -210,7 +210,7 @@ async def create(self):
# Security checks
#######################
- assert dh_prime == Prime.CURRENT_DH_PRIME
+ assert dh_prime == prime.CURRENT_DH_PRIME
log.debug("DH parameters check: OK")
# https://core.telegram.org/mtproto/security_guidelines#g-a-and-g-b-validation
@@ -241,15 +241,11 @@ async def create(self):
log.debug("Nonce fields check: OK")
# Step 9
- server_salt = AES.xor(new_nonce[:8], server_nonce[:8])
+ server_salt = aes.xor(new_nonce[:8], server_nonce[:8])
- log.debug("Server salt: {}".format(int.from_bytes(server_salt, "little")))
+ log.debug(f"Server salt: {int.from_bytes(server_salt, 'little')}")
- log.info(
- "Done auth key exchange: {}".format(
- set_client_dh_params_answer.__class__.__name__
- )
- )
+ log.info(f"Done auth key exchange: {set_client_dh_params_answer.__class__.__name__}")
except Exception as e:
if retries_left:
retries_left -= 1
diff --git a/pyrogram/session/internals/msg_factory.py b/pyrogram/session/internals/msg_factory.py
index 3f4c302648..bf44b7d3c4 100644
--- a/pyrogram/session/internals/msg_factory.py
+++ b/pyrogram/session/internals/msg_factory.py
@@ -16,10 +16,9 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from pyrogram.api.functions import Ping
-from pyrogram.api.types import MsgsAck, HttpWait
-
-from pyrogram.api.core import Message, MsgContainer, TLObject
+from pyrogram.raw.core import Message, MsgContainer, TLObject
+from pyrogram.raw.functions import Ping
+from pyrogram.raw.types import MsgsAck, HttpWait
from .msg_id import MsgId
from .seq_no import SeqNo
@@ -27,13 +26,14 @@
class MsgFactory:
- def __init__(self):
+ def __init__(self, server_time: float = 0):
self.seq_no = SeqNo()
+ self.server_time = server_time
def __call__(self, body: TLObject) -> Message:
return Message(
body,
- MsgId(),
+ MsgId(self.server_time),
self.seq_no(not isinstance(body, not_content_related)),
len(body)
)
diff --git a/pyrogram/session/internals/msg_id.py b/pyrogram/session/internals/msg_id.py
index e52815e94d..58474222c7 100644
--- a/pyrogram/session/internals/msg_id.py
+++ b/pyrogram/session/internals/msg_id.py
@@ -16,20 +16,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from threading import Lock
-from time import time
+from time import monotonic
class MsgId:
+ reference_clock = monotonic()
last_time = 0
- offset = 0
- lock = Lock()
+ msg_id_offset = 0
- def __new__(cls) -> int:
- with cls.lock:
- now = time()
- cls.offset = cls.offset + 4 if now == cls.last_time else 0
- msg_id = int(now * 2 ** 32) + cls.offset
- cls.last_time = now
+ def __new__(cls, server_time: float = 0) -> int:
+ now = monotonic() - cls.reference_clock + server_time
+ cls.msg_id_offset = cls.msg_id_offset + 4 if now == cls.last_time else 0
+ msg_id = int(now * 2 ** 32) + cls.msg_id_offset
+ cls.last_time = now
- return msg_id
+ return msg_id
diff --git a/pyrogram/session/session.py b/pyrogram/session/session.py
index beb4affacf..6c385199b4 100644
--- a/pyrogram/session/session.py
+++ b/pyrogram/session/session.py
@@ -18,18 +18,20 @@
import asyncio
import logging
+import time
+from concurrent.futures.thread import ThreadPoolExecutor
from datetime import datetime, timedelta
from hashlib import sha1
from io import BytesIO
import pyrogram
from pyrogram import __copyright__, __license__, __version__
-from pyrogram.api import functions, types
-from pyrogram.api.all import layer
-from pyrogram.api.core import TLObject, MsgContainer, Int, Long, FutureSalt, FutureSalts
+from pyrogram import raw
from pyrogram.connection import Connection
-from pyrogram.crypto import MTProto
+from pyrogram.crypto import mtproto
from pyrogram.errors import RPCError, InternalServerError, AuthKeyDuplicated, FloodWait
+from pyrogram.raw.all import layer
+from pyrogram.raw.core import TLObject, MsgContainer, Int, Long, FutureSalt, FutureSalts
from .internals import MsgId, MsgFactory
log = logging.getLogger(__name__)
@@ -43,13 +45,13 @@ def __init__(self):
class Session:
INITIAL_SALT = 0x616e67656c696361
- NET_WORKERS = 1
START_TIMEOUT = 1
WAIT_TIMEOUT = 15
SLEEP_THRESHOLD = 60
MAX_RETRIES = 5
ACKS_THRESHOLD = 8
PING_INTERVAL = 5
+ EXECUTOR_SIZE_THRESHOLD = 512
notice_displayed = False
@@ -67,22 +69,26 @@ class Session:
64: "[64] invalid container"
}
+ executor = ThreadPoolExecutor(2, thread_name_prefix="CryptoWorker")
+
def __init__(
self,
- client: pyrogram,
+ client: "pyrogram.Client",
dc_id: int,
auth_key: bytes,
+ test_mode: bool,
is_media: bool = False,
is_cdn: bool = False
):
if not Session.notice_displayed:
- print("Pyrogram v{}, {}".format(__version__, __copyright__))
- print("Licensed under the terms of the " + __license__, end="\n\n")
+ print(f"Pyrogram v{__version__}, {__copyright__}")
+ print(f"Licensed under the terms of the {__license__}", end="\n\n")
Session.notice_displayed = True
self.client = client
self.dc_id = dc_id
self.auth_key = auth_key
+ self.test_mode = test_mode
self.is_media = is_media
self.is_cdn = is_cdn
@@ -90,14 +96,13 @@ def __init__(
self.auth_key_id = sha1(auth_key).digest()[-8:]
- self.session_id = Long(MsgId())
+ self.session_id = Long(MsgId(time.time()))
self.msg_factory = MsgFactory()
self.current_salt = None
self.pending_acks = set()
- self.recv_queue = asyncio.Queue()
self.results = {}
self.ping_task = None
@@ -106,16 +111,17 @@ def __init__(
self.next_salt_task = None
self.next_salt_task_event = asyncio.Event()
- self.net_worker_task = None
- self.recv_task = None
+ self.network_task = None
self.is_connected = asyncio.Event()
+ self.loop = asyncio.get_event_loop()
+
async def start(self):
while True:
self.connection = Connection(
self.dc_id,
- self.client.storage.test_mode(),
+ self.test_mode,
self.client.ipv6,
self.client.proxy
)
@@ -123,27 +129,27 @@ async def start(self):
try:
await self.connection.connect()
- self.net_worker_task = asyncio.ensure_future(self.net_worker())
- self.recv_task = asyncio.ensure_future(self.recv())
+ self.network_task = self.loop.create_task(self.network_worker())
self.current_salt = FutureSalt(0, 0, Session.INITIAL_SALT)
self.current_salt = FutureSalt(
0, 0,
(await self._send(
- functions.Ping(ping_id=0),
+ raw.functions.Ping(ping_id=0),
timeout=self.START_TIMEOUT
)).new_server_salt
)
- self.current_salt = \
- (await self._send(functions.GetFutureSalts(num=1), timeout=self.START_TIMEOUT)).salts[0]
+ self.current_salt = (await self._send(
+ raw.functions.GetFutureSalts(num=1),
+ timeout=self.START_TIMEOUT)).salts[0]
- self.next_salt_task = asyncio.ensure_future(self.next_salt())
+ self.next_salt_task = self.loop.create_task(self.next_salt_worker())
if not self.is_cdn:
await self._send(
- functions.InvokeWithLayer(
+ raw.functions.InvokeWithLayer(
layer=layer,
- query=functions.InitConnection(
+ query=raw.functions.InitConnection(
api_id=self.client.api_id,
app_version=self.client.app_version,
device_model=self.client.device_model,
@@ -151,17 +157,17 @@ async def start(self):
system_lang_code=self.client.lang_code,
lang_code=self.client.lang_code,
lang_pack="",
- query=functions.help.GetConfig(),
+ query=raw.functions.help.GetConfig(),
)
),
timeout=self.START_TIMEOUT
)
- self.ping_task = asyncio.ensure_future(self.ping())
+ self.ping_task = self.loop.create_task(self.ping_worker())
- log.info("Session initialized: Layer {}".format(layer))
- log.info("Device: {} - {}".format(self.client.device_model, self.client.app_version))
- log.info("System: {} ({})".format(self.client.system_version, self.client.lang_code.upper()))
+ log.info(f"Session initialized: Layer {layer}")
+ log.info(f"Device: {self.client.device_model} - {self.client.app_version}")
+ log.info(f"System: {self.client.system_version} ({self.client.lang_code.upper()})")
except AuthKeyDuplicated as e:
await self.stop()
@@ -195,11 +201,8 @@ async def stop(self):
self.connection.close()
- if self.recv_task:
- await self.recv_task
-
- if self.net_worker_task:
- await self.net_worker_task
+ if self.network_task:
+ await self.network_task
for i in self.results.values():
i.event.set()
@@ -216,76 +219,78 @@ async def restart(self):
await self.stop()
await self.start()
- async def net_worker(self):
- logging.info("NetWorkerTask started")
+ async def handle_packet(self, packet):
+ if len(packet) <= self.EXECUTOR_SIZE_THRESHOLD:
+ data = mtproto.unpack(
+ BytesIO(packet),
+ self.session_id,
+ self.auth_key,
+ self.auth_key_id
+ )
+ else:
+ data = await self.loop.run_in_executor(
+ self.executor,
+ mtproto.unpack,
+ BytesIO(packet),
+ self.session_id,
+ self.auth_key,
+ self.auth_key_id
+ )
- while True:
- packet = await self.recv_queue.get()
+ messages = (
+ data.body.messages
+ if isinstance(data.body, MsgContainer)
+ else [data]
+ )
- if packet is None:
- break
+ log.debug(f"Received:\n{data}")
- try:
- data = MTProto.unpack(
- BytesIO(packet),
- self.session_id,
- self.auth_key,
- self.auth_key_id
- )
+ for msg in messages:
+ if msg.seq_no == 0:
+ server_time = msg.msg_id / (2 ** 32)
+ self.msg_factory.server_time = server_time
+ log.info(f"Time synced: {datetime.utcfromtimestamp(server_time)} UTC")
- messages = (
- data.body.messages
- if isinstance(data.body, MsgContainer)
- else [data]
- )
+ if msg.seq_no % 2 != 0:
+ if msg.msg_id in self.pending_acks:
+ continue
+ else:
+ self.pending_acks.add(msg.msg_id)
- log.debug("Received:\n{}".format(data))
-
- for msg in messages:
- if msg.seq_no % 2 != 0:
- if msg.msg_id in self.pending_acks:
- continue
- else:
- self.pending_acks.add(msg.msg_id)
-
- if isinstance(msg.body, (types.MsgDetailedInfo, types.MsgNewDetailedInfo)):
- self.pending_acks.add(msg.body.answer_msg_id)
- continue
-
- if isinstance(msg.body, types.NewSessionCreated):
- continue
-
- msg_id = None
-
- if isinstance(msg.body, (types.BadMsgNotification, types.BadServerSalt)):
- msg_id = msg.body.bad_msg_id
- elif isinstance(msg.body, (FutureSalts, types.RpcResult)):
- msg_id = msg.body.req_msg_id
- elif isinstance(msg.body, types.Pong):
- msg_id = msg.body.msg_id
- else:
- if self.client is not None:
- self.client.updates_queue.put_nowait(msg.body)
-
- if msg_id in self.results:
- self.results[msg_id].value = getattr(msg.body, "result", msg.body)
- self.results[msg_id].event.set()
-
- if len(self.pending_acks) >= self.ACKS_THRESHOLD:
- log.info("Send {} acks".format(len(self.pending_acks)))
-
- try:
- await self._send(types.MsgsAck(msg_ids=list(self.pending_acks)), False)
- except (OSError, TimeoutError):
- pass
- else:
- self.pending_acks.clear()
- except Exception as e:
- log.error(e, exc_info=True)
+ if isinstance(msg.body, (raw.types.MsgDetailedInfo, raw.types.MsgNewDetailedInfo)):
+ self.pending_acks.add(msg.body.answer_msg_id)
+ continue
- log.info("NetWorkerTask stopped")
+ if isinstance(msg.body, raw.types.NewSessionCreated):
+ continue
- async def ping(self):
+ msg_id = None
+
+ if isinstance(msg.body, (raw.types.BadMsgNotification, raw.types.BadServerSalt)):
+ msg_id = msg.body.bad_msg_id
+ elif isinstance(msg.body, (FutureSalts, raw.types.RpcResult)):
+ msg_id = msg.body.req_msg_id
+ elif isinstance(msg.body, raw.types.Pong):
+ msg_id = msg.body.msg_id
+ else:
+ if self.client is not None:
+ self.loop.create_task(self.client.handle_updates(msg.body))
+
+ if msg_id in self.results:
+ self.results[msg_id].value = getattr(msg.body, "result", msg.body)
+ self.results[msg_id].event.set()
+
+ if len(self.pending_acks) >= self.ACKS_THRESHOLD:
+ log.debug(f"Send {len(self.pending_acks)} acks")
+
+ try:
+ await self._send(raw.types.MsgsAck(msg_ids=list(self.pending_acks)), False)
+ except (OSError, TimeoutError):
+ pass
+ else:
+ self.pending_acks.clear()
+
+ async def ping_worker(self):
log.info("PingTask started")
while True:
@@ -298,7 +303,7 @@ async def ping(self):
try:
await self._send(
- functions.PingDelayDisconnect(
+ raw.functions.PingDelayDisconnect(
ping_id=0, disconnect_delay=self.WAIT_TIMEOUT + 10
), False
)
@@ -307,7 +312,7 @@ async def ping(self):
log.info("PingTask stopped")
- async def next_salt(self):
+ async def next_salt_worker(self):
log.info("NextSaltTask started")
while True:
@@ -331,33 +336,31 @@ async def next_salt(self):
break
try:
- self.current_salt = (await self._send(functions.GetFutureSalts(num=1))).salts[0]
+ self.current_salt = (await self._send(raw.functions.GetFutureSalts(num=1))).salts[0]
except (OSError, TimeoutError, RPCError):
self.connection.close()
break
log.info("NextSaltTask stopped")
- async def recv(self):
- log.info("RecvTask started")
+ async def network_worker(self):
+ log.info("NetworkTask started")
while True:
packet = await self.connection.recv()
if packet is None or len(packet) == 4:
- self.recv_queue.put_nowait(None)
-
if packet:
- log.warning("Server sent \"{}\"".format(Int.read(BytesIO(packet))))
+ log.warning(f'Server sent "{Int.read(BytesIO(packet))}"')
if self.is_connected.is_set():
- asyncio.ensure_future(self.restart())
+ self.loop.create_task(self.restart())
break
- self.recv_queue.put_nowait(packet)
+ self.loop.create_task(self.handle_packet(packet))
- log.info("RecvTask stopped")
+ log.info("NetworkTask stopped")
async def _send(self, data: TLObject, wait_response: bool = True, timeout: float = WAIT_TIMEOUT):
message = self.msg_factory(data)
@@ -366,15 +369,26 @@ async def _send(self, data: TLObject, wait_response: bool = True, timeout: float
if wait_response:
self.results[msg_id] = Result()
- log.debug("Sent:\n{}".format(message))
+ log.debug(f"Sent:\n{message}")
- payload = MTProto.pack(
- message,
- self.current_salt.salt,
- self.session_id,
- self.auth_key,
- self.auth_key_id
- )
+ if len(message) <= self.EXECUTOR_SIZE_THRESHOLD:
+ payload = mtproto.pack(
+ message,
+ self.current_salt.salt,
+ self.session_id,
+ self.auth_key,
+ self.auth_key_id
+ )
+ else:
+ payload = await self.loop.run_in_executor(
+ self.executor,
+ mtproto.pack,
+ message,
+ self.current_salt.salt,
+ self.session_id,
+ self.auth_key,
+ self.auth_key_id
+ )
try:
await self.connection.send(payload)
@@ -392,15 +406,15 @@ async def _send(self, data: TLObject, wait_response: bool = True, timeout: float
if result is None:
raise TimeoutError
- elif isinstance(result, types.RpcError):
- if isinstance(data, (functions.InvokeWithoutUpdates, functions.InvokeWithTakeout)):
+ elif isinstance(result, raw.types.RpcError):
+ if isinstance(data, (raw.functions.InvokeWithoutUpdates, raw.functions.InvokeWithTakeout)):
data = data.query
RPCError.raise_it(result, type(data))
- elif isinstance(result, types.BadMsgNotification):
+ elif isinstance(result, raw.types.BadMsgNotification):
raise Exception(self.BAD_MSG_DESCRIPTION.get(
result.error_code,
- "Error code {}".format(result.error_code)
+ f"Error code {result.error_code}"
))
else:
return result
@@ -417,7 +431,7 @@ async def send(
except asyncio.TimeoutError:
pass
- if isinstance(data, (functions.InvokeWithoutUpdates, functions.InvokeWithTakeout)):
+ if isinstance(data, (raw.functions.InvokeWithoutUpdates, raw.functions.InvokeWithTakeout)):
query = data.query
else:
query = data
@@ -433,8 +447,7 @@ async def send(
if amount > sleep_threshold:
raise
- log.warning('[{}] Sleeping for {}s (required by "{}")'.format(
- self.client.session_name, amount, query))
+ log.warning(f'[{self.client.session_name}] Sleeping for {amount}s (required by "{query}")')
await asyncio.sleep(amount)
except (OSError, TimeoutError, InternalServerError) as e:
@@ -442,9 +455,7 @@ async def send(
raise e from None
(log.warning if retries < 2 else log.info)(
- '[{}] Retrying "{}" due to {}'.format(
- Session.MAX_RETRIES - retries + 1,
- query, e))
+ f'[{Session.MAX_RETRIES - retries + 1}] Retrying "{query}" due to {e}')
await asyncio.sleep(0.5)
diff --git a/pyrogram/client/storage/__init__.py b/pyrogram/storage/__init__.py
similarity index 100%
rename from pyrogram/client/storage/__init__.py
rename to pyrogram/storage/__init__.py
diff --git a/pyrogram/client/storage/file_storage.py b/pyrogram/storage/file_storage.py
similarity index 93%
rename from pyrogram/client/storage/file_storage.py
rename to pyrogram/storage/file_storage.py
index 07716ce5e5..a335761a0b 100644
--- a/pyrogram/client/storage/file_storage.py
+++ b/pyrogram/storage/file_storage.py
@@ -78,7 +78,7 @@ def update(self):
self.version(version)
- def open(self):
+ async def open(self):
path = self.database
file_exists = path.is_file()
@@ -93,7 +93,7 @@ def open(self):
path.rename(path.name + ".OLD")
- log.warning('The old session file has been renamed to "{}.OLD"'.format(path.name))
+ log.warning(f'The old session file has been renamed to "{path.name}.OLD"')
self.migrate_from_json(session_json)
@@ -102,7 +102,7 @@ def open(self):
return
if Path(path.name + ".OLD").is_file():
- log.warning('Old session file detected: "{}.OLD". You can remove this file now'.format(path.name))
+ log.warning(f'Old session file detected: "{path.name}.OLD". You can remove this file now')
self.conn = sqlite3.connect(str(path), timeout=1, check_same_thread=False)
@@ -117,5 +117,5 @@ def open(self):
except sqlite3.OperationalError:
pass
- def delete(self):
+ async def delete(self):
os.remove(self.database)
diff --git a/pyrogram/client/storage/memory_storage.py b/pyrogram/storage/memory_storage.py
similarity index 81%
rename from pyrogram/client/storage/memory_storage.py
rename to pyrogram/storage/memory_storage.py
index b698d2cef9..7e0094974c 100644
--- a/pyrogram/client/storage/memory_storage.py
+++ b/pyrogram/storage/memory_storage.py
@@ -30,7 +30,7 @@ class MemoryStorage(SQLiteStorage):
def __init__(self, name: str):
super().__init__(name)
- def open(self):
+ async def open(self):
self.conn = sqlite3.connect(":memory:", check_same_thread=False)
self.create()
@@ -42,12 +42,12 @@ def open(self):
)
)
- self.dc_id(dc_id)
- self.test_mode(test_mode)
- self.auth_key(auth_key)
- self.user_id(user_id)
- self.is_bot(is_bot)
- self.date(0)
+ await self.dc_id(dc_id)
+ await self.test_mode(test_mode)
+ await self.auth_key(auth_key)
+ await self.user_id(user_id)
+ await self.is_bot(is_bot)
+ await self.date(0)
- def delete(self):
- pass
+ async def delete(self):
+ raise NotImplementedError
diff --git a/pyrogram/client/storage/schema.sql b/pyrogram/storage/schema.sql
similarity index 95%
rename from pyrogram/client/storage/schema.sql
rename to pyrogram/storage/schema.sql
index aa76c4b021..39c986b5d3 100644
--- a/pyrogram/client/storage/schema.sql
+++ b/pyrogram/storage/schema.sql
@@ -18,7 +18,8 @@
* along with Pyrogram. If not, see .
*/
-CREATE TABLE sessions (
+CREATE TABLE sessions
+(
dc_id INTEGER PRIMARY KEY,
test_mode INTEGER,
auth_key BLOB,
@@ -27,7 +28,8 @@ CREATE TABLE sessions (
is_bot INTEGER
);
-CREATE TABLE peers (
+CREATE TABLE peers
+(
id INTEGER PRIMARY KEY,
access_hash INTEGER,
type INTEGER NOT NULL,
@@ -36,7 +38,8 @@ CREATE TABLE peers (
last_update_on INTEGER NOT NULL DEFAULT (CAST(STRFTIME('%s', 'now') AS INTEGER))
);
-CREATE TABLE version (
+CREATE TABLE version
+(
number INTEGER PRIMARY KEY
);
diff --git a/pyrogram/client/storage/sqlite_storage.py b/pyrogram/storage/sqlite_storage.py
similarity index 76%
rename from pyrogram/client/storage/sqlite_storage.py
rename to pyrogram/storage/sqlite_storage.py
index 14279b0a27..2f3768df2d 100644
--- a/pyrogram/client/storage/sqlite_storage.py
+++ b/pyrogram/storage/sqlite_storage.py
@@ -23,30 +23,30 @@
from threading import Lock
from typing import List, Tuple, Any
-from pyrogram.api import types
-from pyrogram.client.ext import utils
+from pyrogram import raw
from .storage import Storage
+from .. import utils
def get_input_peer(peer_id: int, access_hash: int, peer_type: str):
if peer_type in ["user", "bot"]:
- return types.InputPeerUser(
+ return raw.types.InputPeerUser(
user_id=peer_id,
access_hash=access_hash
)
if peer_type == "group":
- return types.InputPeerChat(
+ return raw.types.InputPeerChat(
chat_id=-peer_id
)
if peer_type in ["channel", "supergroup"]:
- return types.InputPeerChannel(
+ return raw.types.InputPeerChannel(
channel_id=utils.get_channel_id(peer_id),
access_hash=access_hash
)
- raise ValueError("Invalid peer type: {}".format(peer_type))
+ raise ValueError(f"Invalid peer type: {peer_type}")
class SQLiteStorage(Storage):
@@ -74,23 +74,23 @@ def create(self):
(2, None, None, 0, None, None)
)
- def open(self):
+ async def open(self):
raise NotImplementedError
- def save(self):
- self.date(int(time.time()))
+ async def save(self):
+ await self.date(int(time.time()))
with self.lock:
self.conn.commit()
- def close(self):
+ async def close(self):
with self.lock:
self.conn.close()
- def delete(self):
+ async def delete(self):
raise NotImplementedError
- def update_peers(self, peers: List[Tuple[int, int, str, str, str]]):
+ async def update_peers(self, peers: List[Tuple[int, int, str, str, str]]):
with self.lock:
self.conn.executemany(
"REPLACE INTO peers (id, access_hash, type, username, phone_number)"
@@ -98,39 +98,39 @@ def update_peers(self, peers: List[Tuple[int, int, str, str, str]]):
peers
)
- def get_peer_by_id(self, peer_id: int):
+ async def get_peer_by_id(self, peer_id: int):
r = self.conn.execute(
"SELECT id, access_hash, type FROM peers WHERE id = ?",
(peer_id,)
).fetchone()
if r is None:
- raise KeyError("ID not found: {}".format(peer_id))
+ raise KeyError(f"ID not found: {peer_id}")
return get_input_peer(*r)
- def get_peer_by_username(self, username: str):
+ async def get_peer_by_username(self, username: str):
r = self.conn.execute(
"SELECT id, access_hash, type, last_update_on FROM peers WHERE username = ?",
(username,)
).fetchone()
if r is None:
- raise KeyError("Username not found: {}".format(username))
+ raise KeyError(f"Username not found: {username}")
if abs(time.time() - r[3]) > self.USERNAME_TTL:
- raise KeyError("Username expired: {}".format(username))
+ raise KeyError(f"Username expired: {username}")
return get_input_peer(*r[:3])
- def get_peer_by_phone_number(self, phone_number: str):
+ async def get_peer_by_phone_number(self, phone_number: str):
r = self.conn.execute(
"SELECT id, access_hash, type FROM peers WHERE phone_number = ?",
(phone_number,)
).fetchone()
if r is None:
- raise KeyError("Phone number not found: {}".format(phone_number))
+ raise KeyError(f"Phone number not found: {phone_number}")
return get_input_peer(*r)
@@ -138,7 +138,7 @@ def _get(self):
attr = inspect.stack()[2].function
return self.conn.execute(
- "SELECT {} FROM sessions".format(attr)
+ f"SELECT {attr} FROM sessions"
).fetchone()[0]
def _set(self, value: Any):
@@ -146,29 +146,29 @@ def _set(self, value: Any):
with self.lock, self.conn:
self.conn.execute(
- "UPDATE sessions SET {} = ?".format(attr),
+ f"UPDATE sessions SET {attr} = ?",
(value,)
)
def _accessor(self, value: Any = object):
return self._get() if value == object else self._set(value)
- def dc_id(self, value: int = object):
+ async def dc_id(self, value: int = object):
return self._accessor(value)
- def test_mode(self, value: bool = object):
+ async def test_mode(self, value: bool = object):
return self._accessor(value)
- def auth_key(self, value: bytes = object):
+ async def auth_key(self, value: bytes = object):
return self._accessor(value)
- def date(self, value: int = object):
+ async def date(self, value: int = object):
return self._accessor(value)
- def user_id(self, value: int = object):
+ async def user_id(self, value: int = object):
return self._accessor(value)
- def is_bot(self, value: bool = object):
+ async def is_bot(self, value: bool = object):
return self._accessor(value)
def version(self, value: int = object):
diff --git a/pyrogram/client/storage/storage.py b/pyrogram/storage/storage.py
similarity index 65%
rename from pyrogram/client/storage/storage.py
rename to pyrogram/storage/storage.py
index 8cd7e6f39e..3ef83027a0 100644
--- a/pyrogram/client/storage/storage.py
+++ b/pyrogram/storage/storage.py
@@ -28,56 +28,56 @@ class Storage:
def __init__(self, name: str):
self.name = name
- def open(self):
+ async def open(self):
raise NotImplementedError
- def save(self):
+ async def save(self):
raise NotImplementedError
- def close(self):
+ async def close(self):
raise NotImplementedError
- def delete(self):
+ async def delete(self):
raise NotImplementedError
- def update_peers(self, peers: List[Tuple[int, int, str, str, str]]):
+ async def update_peers(self, peers: List[Tuple[int, int, str, str, str]]):
raise NotImplementedError
- def get_peer_by_id(self, peer_id: int):
+ async def get_peer_by_id(self, peer_id: int):
raise NotImplementedError
- def get_peer_by_username(self, username: str):
+ async def get_peer_by_username(self, username: str):
raise NotImplementedError
- def get_peer_by_phone_number(self, phone_number: str):
+ async def get_peer_by_phone_number(self, phone_number: str):
raise NotImplementedError
- def dc_id(self, value: int = object):
+ async def dc_id(self, value: int = object):
raise NotImplementedError
- def test_mode(self, value: bool = object):
+ async def test_mode(self, value: bool = object):
raise NotImplementedError
- def auth_key(self, value: bytes = object):
+ async def auth_key(self, value: bytes = object):
raise NotImplementedError
- def date(self, value: int = object):
+ async def date(self, value: int = object):
raise NotImplementedError
- def user_id(self, value: int = object):
+ async def user_id(self, value: int = object):
raise NotImplementedError
- def is_bot(self, value: bool = object):
+ async def is_bot(self, value: bool = object):
raise NotImplementedError
- def export_session_string(self):
+ async def export_session_string(self):
return base64.urlsafe_b64encode(
struct.pack(
self.SESSION_STRING_FORMAT,
- self.dc_id(),
- self.test_mode(),
- self.auth_key(),
- self.user_id(),
- self.is_bot()
+ await self.dc_id(),
+ await self.test_mode(),
+ await self.auth_key(),
+ await self.user_id(),
+ await self.is_bot()
)
).decode().rstrip("=")
diff --git a/pyrogram/sync.py b/pyrogram/sync.py
new file mode 100644
index 0000000000..80288e68d0
--- /dev/null
+++ b/pyrogram/sync.py
@@ -0,0 +1,80 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+import asyncio
+import functools
+import inspect
+import threading
+
+from pyrogram import types
+from pyrogram.methods import Methods
+from pyrogram.methods.utilities import idle as idle_module
+
+
+def async_to_sync(obj, name):
+ function = getattr(obj, name)
+ loop = asyncio.get_event_loop()
+
+ async def consume_generator(coroutine):
+ return [i async for i in coroutine]
+
+ @functools.wraps(function)
+ def async_to_sync_wrap(*args, **kwargs):
+ coroutine = function(*args, **kwargs)
+
+ if loop.is_running():
+ if threading.current_thread() is threading.main_thread():
+ return coroutine
+ else:
+ if inspect.iscoroutine(coroutine):
+ return asyncio.run_coroutine_threadsafe(coroutine, loop).result()
+
+ if inspect.isasyncgen(coroutine):
+ return asyncio.run_coroutine_threadsafe(consume_generator(coroutine), loop).result()
+
+ if inspect.iscoroutine(coroutine):
+ return loop.run_until_complete(coroutine)
+
+ if inspect.isasyncgen(coroutine):
+ return loop.run_until_complete(consume_generator(coroutine))
+
+ setattr(obj, name, async_to_sync_wrap)
+
+
+def wrap(source):
+ for name in dir(source):
+ method = getattr(source, name)
+
+ if not name.startswith("_"):
+ if inspect.iscoroutinefunction(method) or inspect.isasyncgenfunction(method):
+ async_to_sync(source, name)
+
+
+# Wrap all Client's relevant methods
+wrap(Methods)
+
+# Wrap types' bound methods
+for class_name in dir(types):
+ cls = getattr(types, class_name)
+
+ if inspect.isclass(cls):
+ wrap(cls)
+
+# Special case for idle, because it's not inside Methods
+async_to_sync(idle_module, "idle")
+idle = getattr(idle_module, "idle")
diff --git a/pyrogram/client/ext/syncer.py b/pyrogram/syncer.py
similarity index 87%
rename from pyrogram/client/ext/syncer.py
rename to pyrogram/syncer.py
index 65fb210453..1a9d77f30e 100644
--- a/pyrogram/client/ext/syncer.py
+++ b/pyrogram/syncer.py
@@ -39,7 +39,7 @@ async def add(cls, client):
cls.lock = asyncio.Lock()
async with cls.lock:
- cls.sync(client)
+ await cls.sync(client)
cls.clients[id(client)] = client
@@ -49,7 +49,7 @@ async def add(cls, client):
@classmethod
async def remove(cls, client):
async with cls.lock:
- cls.sync(client)
+ await cls.sync(client)
del cls.clients[id(client)]
@@ -73,19 +73,16 @@ async def worker(cls):
except asyncio.TimeoutError:
async with cls.lock:
for client in cls.clients.values():
- cls.sync(client)
+ await cls.sync(client)
else:
break
@classmethod
- def sync(cls, client):
+ async def sync(cls, client):
try:
start = time.time()
- client.storage.save()
+ await client.storage.save()
except Exception as e:
log.critical(e, exc_info=True)
else:
- log.info('Synced "{}" in {:.6} ms'.format(
- client.storage.name,
- (time.time() - start) * 1000
- ))
+ log.info(f'Synced "{client.storage.name}" in {(time.time() - start) * 1000:.6} ms')
diff --git a/pyrogram/client/types/__init__.py b/pyrogram/types/__init__.py
similarity index 100%
rename from pyrogram/client/types/__init__.py
rename to pyrogram/types/__init__.py
index 1fa7c9cecf..f0a0665f91 100644
--- a/pyrogram/client/types/__init__.py
+++ b/pyrogram/types/__init__.py
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from .authorization import *
from .bots_and_keyboards import *
from .inline_mode import *
from .input_media import *
@@ -23,6 +24,5 @@
from .list import List
from .messages_and_media import *
from .object import Object
-from .authorization import *
from .update import *
from .user_and_chats import *
diff --git a/pyrogram/client/types/authorization/__init__.py b/pyrogram/types/authorization/__init__.py
similarity index 100%
rename from pyrogram/client/types/authorization/__init__.py
rename to pyrogram/types/authorization/__init__.py
index 18d57c935b..2848034100 100644
--- a/pyrogram/client/types/authorization/__init__.py
+++ b/pyrogram/types/authorization/__init__.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from .terms_of_service import TermsOfService
from .sent_code import SentCode
+from .terms_of_service import TermsOfService
__all__ = ["TermsOfService", "SentCode"]
diff --git a/pyrogram/client/types/authorization/sent_code.py b/pyrogram/types/authorization/sent_code.py
similarity index 74%
rename from pyrogram/client/types/authorization/sent_code.py
rename to pyrogram/types/authorization/sent_code.py
index f1fd49da22..fcbfeace2b 100644
--- a/pyrogram/client/types/authorization/sent_code.py
+++ b/pyrogram/types/authorization/sent_code.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from pyrogram.api import types
+from pyrogram import raw
from ..object import Object
@@ -30,16 +30,16 @@ class SentCode(Object):
*"flash_call"* (code is in the last 5 digits of the caller's phone number).
phone_code_hash (``str``):
- Confirmation code identifier useful for the next authorization steps (either :meth:`~Client.sign_in` or
- :meth:`~Client.sign_up`).
+ Confirmation code identifier useful for the next authorization steps (either
+ :meth:`~pyrogram.Client.sign_in` or :meth:`~pyrogram.Client.sign_up`).
next_type (``str``):
- Type of the next code to be sent with :meth:`~Client.resend_code`.
+ Type of the next code to be sent with :meth:`~pyrogram.Client.resend_code`.
Can be *"sms"* (code will be sent via SMS), *"call"* (code will be sent via voice call) or *"flash_call"*
(code will be in the last 5 digits of caller's phone number).
timeout (``int``):
- Delay in seconds before calling :meth:`~Client.resend_code`.
+ Delay in seconds before calling :meth:`~pyrogram.Client.resend_code`.
"""
def __init__(
@@ -57,25 +57,25 @@ def __init__(
self.timeout = timeout
@staticmethod
- def _parse(sent_code: types.auth.SentCode) -> "SentCode":
+ def _parse(sent_code: raw.types.auth.SentCode) -> "SentCode":
type = sent_code.type
- if isinstance(type, types.auth.SentCodeTypeApp):
+ if isinstance(type, raw.types.auth.SentCodeTypeApp):
type = "app"
- elif isinstance(type, types.auth.SentCodeTypeSms):
+ elif isinstance(type, raw.types.auth.SentCodeTypeSms):
type = "sms"
- elif isinstance(type, types.auth.SentCodeTypeCall):
+ elif isinstance(type, raw.types.auth.SentCodeTypeCall):
type = "call"
- elif isinstance(type, types.auth.SentCodeTypeFlashCall):
+ elif isinstance(type, raw.types.auth.SentCodeTypeFlashCall):
type = "flash_call"
next_type = sent_code.next_type
- if isinstance(next_type, types.auth.CodeTypeSms):
+ if isinstance(next_type, raw.types.auth.CodeTypeSms):
next_type = "sms"
- elif isinstance(next_type, types.auth.CodeTypeCall):
+ elif isinstance(next_type, raw.types.auth.CodeTypeCall):
next_type = "call"
- elif isinstance(next_type, types.auth.CodeTypeFlashCall):
+ elif isinstance(next_type, raw.types.auth.CodeTypeFlashCall):
next_type = "flash_call"
return SentCode(
diff --git a/pyrogram/client/types/authorization/terms_of_service.py b/pyrogram/types/authorization/terms_of_service.py
similarity index 77%
rename from pyrogram/client/types/authorization/terms_of_service.py
rename to pyrogram/types/authorization/terms_of_service.py
index ab7e1348df..33a94d0a0b 100644
--- a/pyrogram/client/types/authorization/terms_of_service.py
+++ b/pyrogram/types/authorization/terms_of_service.py
@@ -18,13 +18,13 @@
from typing import List
-from pyrogram.api import types
-from ..messages_and_media import MessageEntity
+from pyrogram import raw
+from pyrogram import types
from ..object import Object
class TermsOfService(Object):
- """Telegram's Terms of Service returned by :meth:`~Client.sign_in`.
+ """Telegram's Terms of Service returned by :meth:`~pyrogram.Client.sign_in`.
Parameters:
id (``str``):
@@ -33,11 +33,11 @@ class TermsOfService(Object):
text (``str``):
Terms of Service text.
- entities (List of :obj:`MessageEntity`):
+ entities (List of :obj:`~pyrogram.types.MessageEntity`):
Special entities like URLs that appear in the text.
"""
- def __init__(self, *, id: str, text: str, entities: List[MessageEntity]):
+ def __init__(self, *, id: str, text: str, entities: List["types.MessageEntity"]):
super().__init__()
self.id = id
@@ -45,12 +45,12 @@ def __init__(self, *, id: str, text: str, entities: List[MessageEntity]):
self.entities = entities
@staticmethod
- def _parse(terms_of_service: types.help.TermsOfService) -> "TermsOfService":
+ def _parse(terms_of_service: "raw.types.help.TermsOfService") -> "TermsOfService":
return TermsOfService(
id=terms_of_service.id.data,
text=terms_of_service.text,
entities=[
- MessageEntity._parse(None, entity, {})
+ types.MessageEntity._parse(None, entity, {})
for entity in terms_of_service.entities
]
)
diff --git a/pyrogram/client/types/bots_and_keyboards/__init__.py b/pyrogram/types/bots_and_keyboards/__init__.py
similarity index 100%
rename from pyrogram/client/types/bots_and_keyboards/__init__.py
rename to pyrogram/types/bots_and_keyboards/__init__.py
diff --git a/pyrogram/client/types/bots_and_keyboards/callback_game.py b/pyrogram/types/bots_and_keyboards/callback_game.py
similarity index 100%
rename from pyrogram/client/types/bots_and_keyboards/callback_game.py
rename to pyrogram/types/bots_and_keyboards/callback_game.py
diff --git a/pyrogram/client/types/bots_and_keyboards/callback_query.py b/pyrogram/types/bots_and_keyboards/callback_query.py
similarity index 79%
rename from pyrogram/client/types/bots_and_keyboards/callback_query.py
rename to pyrogram/types/bots_and_keyboards/callback_query.py
index a15a7c35e3..326c78bb10 100644
--- a/pyrogram/client/types/bots_and_keyboards/callback_query.py
+++ b/pyrogram/types/bots_and_keyboards/callback_query.py
@@ -21,11 +21,11 @@
from typing import Union, List, Match
import pyrogram
-from pyrogram.api import types
+from pyrogram import raw
+from pyrogram import types
from ..object import Object
from ..update import Update
-from ..user_and_chats import User
-from ...ext import utils
+from ... import utils
class CallbackQuery(Object, Update):
@@ -39,14 +39,14 @@ class CallbackQuery(Object, Update):
id (``str``):
Unique identifier for this query.
- from_user (:obj:`User`):
+ from_user (:obj:`~pyrogram.types.User`):
Sender.
chat_instance (``str``, *optional*):
Global identifier, uniquely corresponding to the chat to which the message with the callback button was
sent. Useful for high scores in games.
- message (:obj:`Message`, *optional*):
+ message (:obj:`~pyrogram.types.Message`, *optional*):
Message with the callback button that originated the query. Note that message content and message date will
not be available if the message is too old.
@@ -67,11 +67,11 @@ class CallbackQuery(Object, Update):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
id: str,
- from_user: User,
+ from_user: "types.User",
chat_instance: str,
- message: "pyrogram.Message" = None,
+ message: "types.Message" = None,
inline_message_id: str = None,
data: Union[str, bytes] = None,
game_short_name: str = None,
@@ -93,9 +93,9 @@ async def _parse(client, callback_query, users) -> "CallbackQuery":
message = None
inline_message_id = None
- if isinstance(callback_query, types.UpdateBotCallbackQuery):
+ if isinstance(callback_query, raw.types.UpdateBotCallbackQuery):
message = await client.get_messages(utils.get_peer_id(callback_query.peer), callback_query.msg_id)
- elif isinstance(callback_query, types.UpdateInlineBotCallbackQuery):
+ elif isinstance(callback_query, raw.types.UpdateInlineBotCallbackQuery):
inline_message_id = b64encode(
pack(
" "CallbackQuery":
return CallbackQuery(
id=str(callback_query.query_id),
- from_user=User._parse(client, users[callback_query.user_id]),
+ from_user=types.User._parse(client, users[callback_query.user_id]),
message=message,
inline_message_id=inline_message_id,
chat_instance=str(callback_query.chat_instance),
@@ -125,7 +125,7 @@ async def _parse(client, callback_query, users) -> "CallbackQuery":
)
async def answer(self, text: str = None, show_alert: bool = None, url: str = None, cache_time: int = 0):
- """Bound method *answer* of :obj:`CallbackQuery`.
+ """Bound method *answer* of :obj:`~pyrogram.types.CallbackQuery`.
Use this method as a shortcut for:
@@ -173,11 +173,11 @@ async def edit_message_text(
text: str,
parse_mode: Union[str, None] = object,
disable_web_page_preview: bool = None,
- reply_markup: "pyrogram.InlineKeyboardMarkup" = None
- ) -> Union["pyrogram.Message", bool]:
+ reply_markup: "types.InlineKeyboardMarkup" = None
+ ) -> Union["types.Message", bool]:
"""Edit the text of messages attached to callback queries.
- Bound method *edit_message_text* of :obj:`CallbackQuery`.
+ Bound method *edit_message_text* of :obj:`~pyrogram.types.CallbackQuery`.
Parameters:
text (``str``):
@@ -193,12 +193,12 @@ async def edit_message_text(
disable_web_page_preview (``bool``, *optional*):
Disables link previews for links in this message.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
- :obj:`Message` | ``bool``: On success, if the edited message was sent by the bot, the edited message is
- returned, otherwise True is returned (message sent via the bot, as inline query result).
+ :obj:`~pyrogram.types.Message` | ``bool``: On success, if the edited message was sent by the bot, the edited
+ message is returned, otherwise True is returned (message sent via the bot, as inline query result).
Raises:
RPCError: In case of a Telegram RPC error.
@@ -225,11 +225,11 @@ async def edit_message_caption(
self,
caption: str,
parse_mode: Union[str, None] = object,
- reply_markup: "pyrogram.InlineKeyboardMarkup" = None
- ) -> Union["pyrogram.Message", bool]:
+ reply_markup: "types.InlineKeyboardMarkup" = None
+ ) -> Union["types.Message", bool]:
"""Edit the caption of media messages attached to callback queries.
- Bound method *edit_message_caption* of :obj:`CallbackQuery`.
+ Bound method *edit_message_caption* of :obj:`~pyrogram.types.CallbackQuery`.
Parameters:
caption (``str``):
@@ -242,12 +242,12 @@ async def edit_message_caption(
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
- :obj:`Message` | ``bool``: On success, if the edited message was sent by the bot, the edited message is
- returned, otherwise True is returned (message sent via the bot, as inline query result).
+ :obj:`~pyrogram.types.Message` | ``bool``: On success, if the edited message was sent by the bot, the edited
+ message is returned, otherwise True is returned (message sent via the bot, as inline query result).
Raises:
RPCError: In case of a Telegram RPC error.
@@ -256,23 +256,23 @@ async def edit_message_caption(
async def edit_message_media(
self,
- media: "pyrogram.InputMedia",
- reply_markup: "pyrogram.InlineKeyboardMarkup" = None
- ) -> Union["pyrogram.Message", bool]:
+ media: "types.InputMedia",
+ reply_markup: "types.InlineKeyboardMarkup" = None
+ ) -> Union["types.Message", bool]:
"""Edit animation, audio, document, photo or video messages attached to callback queries.
- Bound method *edit_message_media* of :obj:`CallbackQuery`.
+ Bound method *edit_message_media* of :obj:`~pyrogram.types.CallbackQuery`.
Parameters:
- media (:obj:`InputMedia`):
+ media (:obj:`~pyrogram.types.InputMedia`):
One of the InputMedia objects describing an animation, audio, document, photo or video.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
- :obj:`Message` | ``bool``: On success, if the edited message was sent by the bot, the edited message is
- returned, otherwise True is returned (message sent via the bot, as inline query result).
+ :obj:`~pyrogram.types.Message` | ``bool``: On success, if the edited message was sent by the bot, the edited
+ message is returned, otherwise True is returned (message sent via the bot, as inline query result).
Raises:
RPCError: In case of a Telegram RPC error.
@@ -293,19 +293,19 @@ async def edit_message_media(
async def edit_message_reply_markup(
self,
- reply_markup: "pyrogram.InlineKeyboardMarkup" = None
- ) -> Union["pyrogram.Message", bool]:
+ reply_markup: "types.InlineKeyboardMarkup" = None
+ ) -> Union["types.Message", bool]:
"""Edit only the reply markup of messages attached to callback queries.
- Bound method *edit_message_reply_markup* of :obj:`CallbackQuery`.
+ Bound method *edit_message_reply_markup* of :obj:`~pyrogram.types.CallbackQuery`.
Parameters:
- reply_markup (:obj:`InlineKeyboardMarkup`):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`):
An InlineKeyboardMarkup object.
Returns:
- :obj:`Message` | ``bool``: On success, if the edited message was sent by the bot, the edited message is
- returned, otherwise True is returned (message sent via the bot, as inline query result).
+ :obj:`~pyrogram.types.Message` | ``bool``: On success, if the edited message was sent by the bot, the edited
+ message is returned, otherwise True is returned (message sent via the bot, as inline query result).
Raises:
RPCError: In case of a Telegram RPC error.
diff --git a/pyrogram/client/types/bots_and_keyboards/force_reply.py b/pyrogram/types/bots_and_keyboards/force_reply.py
similarity index 95%
rename from pyrogram/client/types/bots_and_keyboards/force_reply.py
rename to pyrogram/types/bots_and_keyboards/force_reply.py
index 14870318f6..97c88db095 100644
--- a/pyrogram/client/types/bots_and_keyboards/force_reply.py
+++ b/pyrogram/types/bots_and_keyboards/force_reply.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from pyrogram.api.types import ReplyKeyboardForceReply
+from pyrogram import raw
from ..object import Object
@@ -52,7 +52,7 @@ def read(o):
)
def write(self):
- return ReplyKeyboardForceReply(
+ return raw.types.ReplyKeyboardForceReply(
single_use=True,
selective=self.selective or None
)
diff --git a/pyrogram/client/types/bots_and_keyboards/game_high_score.py b/pyrogram/types/bots_and_keyboards/game_high_score.py
similarity index 75%
rename from pyrogram/client/types/bots_and_keyboards/game_high_score.py
rename to pyrogram/types/bots_and_keyboards/game_high_score.py
index 1e9b715764..a9af42ee27 100644
--- a/pyrogram/client/types/bots_and_keyboards/game_high_score.py
+++ b/pyrogram/types/bots_and_keyboards/game_high_score.py
@@ -17,17 +17,16 @@
# along with Pyrogram. If not, see .
import pyrogram
-
-from pyrogram.api import types
-from pyrogram.client.types.object import Object
-from pyrogram.client.types.user_and_chats import User
+from pyrogram import raw
+from pyrogram import types
+from ..object import Object
class GameHighScore(Object):
"""One row of the high scores table for a game.
Parameters:
- user (:obj:`User`):
+ user (:obj:`~pyrogram.types.User`):
User.
score (``int``):
@@ -40,8 +39,8 @@ class GameHighScore(Object):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
- user: User,
+ client: "pyrogram.Client" = None,
+ user: "types.User",
score: int,
position: int = None
):
@@ -52,20 +51,20 @@ def __init__(
self.position = position
@staticmethod
- def _parse(client, game_high_score: types.HighScore, users: dict) -> "GameHighScore":
+ def _parse(client, game_high_score: raw.types.HighScore, users: dict) -> "GameHighScore":
users = {i.id: i for i in users}
return GameHighScore(
- user=User._parse(client, users[game_high_score.user_id]),
+ user=types.User._parse(client, users[game_high_score.user_id]),
score=game_high_score.score,
position=game_high_score.pos,
client=client
)
@staticmethod
- def _parse_action(client, service: types.MessageService, users: dict):
+ def _parse_action(client, service: raw.types.MessageService, users: dict):
return GameHighScore(
- user=User._parse(client, users[service.from_id]),
+ user=types.User._parse(client, users[service.from_id]),
score=service.action.score,
client=client
)
diff --git a/pyrogram/client/types/bots_and_keyboards/inline_keyboard_button.py b/pyrogram/types/bots_and_keyboards/inline_keyboard_button.py
similarity index 85%
rename from pyrogram/client/types/bots_and_keyboards/inline_keyboard_button.py
rename to pyrogram/types/bots_and_keyboards/inline_keyboard_button.py
index 0b186b401f..2d5212d9d4 100644
--- a/pyrogram/client/types/bots_and_keyboards/inline_keyboard_button.py
+++ b/pyrogram/types/bots_and_keyboards/inline_keyboard_button.py
@@ -18,12 +18,8 @@
from typing import Union
-from pyrogram.api.types import (
- KeyboardButtonUrl, KeyboardButtonCallback,
- KeyboardButtonSwitchInline, KeyboardButtonGame
-)
-
-from .callback_game import CallbackGame
+from pyrogram import raw
+from pyrogram import types
from ..object import Object
@@ -66,7 +62,7 @@ def __init__(
url: str = None,
switch_inline_query: str = None,
switch_inline_query_current_chat: str = None,
- callback_game: CallbackGame = None
+ callback_game: "types.CallbackGame" = None
):
super().__init__()
@@ -80,13 +76,13 @@ def __init__(
@staticmethod
def read(o):
- if isinstance(o, KeyboardButtonUrl):
+ if isinstance(o, raw.types.KeyboardButtonUrl):
return InlineKeyboardButton(
text=o.text,
url=o.url
)
- if isinstance(o, KeyboardButtonCallback):
+ if isinstance(o, raw.types.KeyboardButtonCallback):
# Try decode data to keep it as string, but if fails, fallback to bytes so we don't lose any information,
# instead of decoding by ignoring/replacing errors.
try:
@@ -99,7 +95,7 @@ def read(o):
callback_data=data
)
- if isinstance(o, KeyboardButtonSwitchInline):
+ if isinstance(o, raw.types.KeyboardButtonSwitchInline):
if o.same_peer:
return InlineKeyboardButton(
text=o.text,
@@ -111,30 +107,30 @@ def read(o):
switch_inline_query=o.query
)
- if isinstance(o, KeyboardButtonGame):
+ if isinstance(o, raw.types.KeyboardButtonGame):
return InlineKeyboardButton(
text=o.text,
- callback_game=CallbackGame()
+ callback_game=types.CallbackGame()
)
def write(self):
if self.callback_data is not None:
# Telegram only wants bytes, but we are allowed to pass strings too, for convenience.
data = bytes(self.callback_data, "utf-8") if isinstance(self.callback_data, str) else self.callback_data
- return KeyboardButtonCallback(text=self.text, data=data)
+ return raw.types.KeyboardButtonCallback(text=self.text, data=data)
if self.url is not None:
- return KeyboardButtonUrl(text=self.text, url=self.url)
+ return raw.types.KeyboardButtonUrl(text=self.text, url=self.url)
if self.switch_inline_query is not None:
- return KeyboardButtonSwitchInline(text=self.text, query=self.switch_inline_query)
+ return raw.types.KeyboardButtonSwitchInline(text=self.text, query=self.switch_inline_query)
if self.switch_inline_query_current_chat is not None:
- return KeyboardButtonSwitchInline(
+ return raw.types.KeyboardButtonSwitchInline(
text=self.text,
query=self.switch_inline_query_current_chat,
same_peer=True
)
if self.callback_game is not None:
- return KeyboardButtonGame(text=self.text)
+ return raw.types.KeyboardButtonGame(text=self.text)
diff --git a/pyrogram/client/types/bots_and_keyboards/inline_keyboard_markup.py b/pyrogram/types/bots_and_keyboards/inline_keyboard_markup.py
similarity index 79%
rename from pyrogram/client/types/bots_and_keyboards/inline_keyboard_markup.py
rename to pyrogram/types/bots_and_keyboards/inline_keyboard_markup.py
index fb79b4db29..6332c7cfa7 100644
--- a/pyrogram/client/types/bots_and_keyboards/inline_keyboard_markup.py
+++ b/pyrogram/types/bots_and_keyboards/inline_keyboard_markup.py
@@ -18,9 +18,8 @@
from typing import List
-from pyrogram.api.types import ReplyInlineMarkup, KeyboardButtonRow
-
-from . import InlineKeyboardButton
+from pyrogram import raw
+from pyrogram import types
from ..object import Object
@@ -28,14 +27,11 @@ class InlineKeyboardMarkup(Object):
"""An inline keyboard that appears right next to the message it belongs to.
Parameters:
- inline_keyboard (List of List of :obj:`InlineKeyboardButton`):
+ inline_keyboard (List of List of :obj:`~pyrogram.types.InlineKeyboardButton`):
List of button rows, each represented by a List of InlineKeyboardButton objects.
"""
- def __init__(
- self,
- inline_keyboard: List[List[InlineKeyboardButton]]
- ):
+ def __init__(self, inline_keyboard: List[List["types.InlineKeyboardButton"]]):
super().__init__()
self.inline_keyboard = inline_keyboard
@@ -48,7 +44,7 @@ def read(o):
row = []
for j in i.buttons:
- row.append(InlineKeyboardButton.read(j))
+ row.append(types.InlineKeyboardButton.read(j))
inline_keyboard.append(row)
@@ -57,8 +53,8 @@ def read(o):
)
def write(self):
- return ReplyInlineMarkup(
- rows=[KeyboardButtonRow(
+ return raw.types.ReplyInlineMarkup(
+ rows=[raw.types.KeyboardButtonRow(
buttons=[j.write() for j in i]
) for i in self.inline_keyboard]
)
diff --git a/pyrogram/client/types/bots_and_keyboards/keyboard_button.py b/pyrogram/types/bots_and_keyboards/keyboard_button.py
similarity index 82%
rename from pyrogram/client/types/bots_and_keyboards/keyboard_button.py
rename to pyrogram/types/bots_and_keyboards/keyboard_button.py
index 022f19def1..855c11bd7e 100644
--- a/pyrogram/client/types/bots_and_keyboards/keyboard_button.py
+++ b/pyrogram/types/bots_and_keyboards/keyboard_button.py
@@ -16,9 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from pyrogram.api.types import KeyboardButton as RawKeyboardButton
-from pyrogram.api.types import KeyboardButtonRequestPhone, KeyboardButtonRequestGeoLocation
-
+from pyrogram import raw
from ..object import Object
@@ -55,16 +53,16 @@ def __init__(
@staticmethod
def read(o):
- if isinstance(o, RawKeyboardButton):
+ if isinstance(o, raw.types.KeyboardButton):
return o.text
- if isinstance(o, KeyboardButtonRequestPhone):
+ if isinstance(o, raw.types.KeyboardButtonRequestPhone):
return KeyboardButton(
text=o.text,
request_contact=True
)
- if isinstance(o, KeyboardButtonRequestGeoLocation):
+ if isinstance(o, raw.types.KeyboardButtonRequestGeoLocation):
return KeyboardButton(
text=o.text,
request_location=True
@@ -74,8 +72,8 @@ def write(self):
# TODO: Enforce optional args mutual exclusiveness
if self.request_contact:
- return KeyboardButtonRequestPhone(text=self.text)
+ return raw.types.KeyboardButtonRequestPhone(text=self.text)
elif self.request_location:
- return KeyboardButtonRequestGeoLocation(text=self.text)
+ return raw.types.KeyboardButtonRequestGeoLocation(text=self.text)
else:
- return RawKeyboardButton(text=self.text)
+ return raw.types.KeyboardButton(text=self.text)
diff --git a/pyrogram/client/types/bots_and_keyboards/reply_keyboard_markup.py b/pyrogram/types/bots_and_keyboards/reply_keyboard_markup.py
similarity index 88%
rename from pyrogram/client/types/bots_and_keyboards/reply_keyboard_markup.py
rename to pyrogram/types/bots_and_keyboards/reply_keyboard_markup.py
index f56087b95d..e4283c8bc4 100644
--- a/pyrogram/client/types/bots_and_keyboards/reply_keyboard_markup.py
+++ b/pyrogram/types/bots_and_keyboards/reply_keyboard_markup.py
@@ -18,10 +18,8 @@
from typing import List, Union
-from pyrogram.api.types import KeyboardButtonRow
-from pyrogram.api.types import ReplyKeyboardMarkup as RawReplyKeyboardMarkup
-
-from . import KeyboardButton
+from pyrogram import raw
+from pyrogram import types
from ..object import Object
@@ -29,7 +27,7 @@ class ReplyKeyboardMarkup(Object):
"""A custom keyboard with reply options.
Parameters:
- keyboard (List of List of :obj:`KeyboardButton`):
+ keyboard (List of List of :obj:`~pyrogram.types.KeyboardButton`):
List of button rows, each represented by a List of KeyboardButton objects.
resize_keyboard (``bool``, *optional*):
@@ -52,7 +50,7 @@ class ReplyKeyboardMarkup(Object):
def __init__(
self,
- keyboard: List[List[Union[KeyboardButton, str]]],
+ keyboard: List[List[Union["types.KeyboardButton", str]]],
resize_keyboard: bool = None,
one_time_keyboard: bool = None,
selective: bool = None
@@ -72,7 +70,7 @@ def read(kb):
row = []
for j in i.buttons:
- row.append(KeyboardButton.read(j))
+ row.append(types.KeyboardButton.read(j))
keyboard.append(row)
@@ -84,10 +82,10 @@ def read(kb):
)
def write(self):
- return RawReplyKeyboardMarkup(
- rows=[KeyboardButtonRow(
+ return raw.types.ReplyKeyboardMarkup(
+ rows=[raw.types.KeyboardButtonRow(
buttons=[
- KeyboardButton(j).write()
+ types.KeyboardButton(j).write()
if isinstance(j, str) else j.write()
for j in i
]
diff --git a/pyrogram/client/types/bots_and_keyboards/reply_keyboard_remove.py b/pyrogram/types/bots_and_keyboards/reply_keyboard_remove.py
similarity index 96%
rename from pyrogram/client/types/bots_and_keyboards/reply_keyboard_remove.py
rename to pyrogram/types/bots_and_keyboards/reply_keyboard_remove.py
index 2143870a0d..f595d06d5d 100644
--- a/pyrogram/client/types/bots_and_keyboards/reply_keyboard_remove.py
+++ b/pyrogram/types/bots_and_keyboards/reply_keyboard_remove.py
@@ -16,8 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from pyrogram.api.types import ReplyKeyboardHide
-
+from pyrogram import raw
from ..object import Object
@@ -53,6 +52,6 @@ def read(o):
)
def write(self):
- return ReplyKeyboardHide(
+ return raw.types.ReplyKeyboardHide(
selective=self.selective or None
)
diff --git a/pyrogram/client/types/inline_mode/__init__.py b/pyrogram/types/inline_mode/__init__.py
similarity index 100%
rename from pyrogram/client/types/inline_mode/__init__.py
rename to pyrogram/types/inline_mode/__init__.py
index 4980377d4f..b532c2e909 100644
--- a/pyrogram/client/types/inline_mode/__init__.py
+++ b/pyrogram/types/inline_mode/__init__.py
@@ -16,12 +16,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from .chosen_inline_result import ChosenInlineResult
from .inline_query import InlineQuery
from .inline_query_result import InlineQueryResult
from .inline_query_result_animation import InlineQueryResultAnimation
from .inline_query_result_article import InlineQueryResultArticle
from .inline_query_result_photo import InlineQueryResultPhoto
-from .chosen_inline_result import ChosenInlineResult
__all__ = [
"InlineQuery", "InlineQueryResult", "InlineQueryResultArticle", "InlineQueryResultPhoto",
diff --git a/pyrogram/client/types/inline_mode/chosen_inline_result.py b/pyrogram/types/inline_mode/chosen_inline_result.py
similarity index 67%
rename from pyrogram/client/types/inline_mode/chosen_inline_result.py
rename to pyrogram/types/inline_mode/chosen_inline_result.py
index b7180b0b59..11185d9b9e 100644
--- a/pyrogram/client/types/inline_mode/chosen_inline_result.py
+++ b/pyrogram/types/inline_mode/chosen_inline_result.py
@@ -15,31 +15,15 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-#
-# This file is part of Pyrogram.
-#
-# Pyrogram is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Pyrogram is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with Pyrogram. If not, see .
from base64 import b64encode
from struct import pack
import pyrogram
-from pyrogram.api import types
-from pyrogram.client.types.object import Object
-from pyrogram.client.types.update import Update
-from pyrogram.client.types.user_and_chats import User
-from pyrogram.client.types.messages_and_media import Location
+from pyrogram import raw
+from pyrogram import types
+from ..object import Object
+from ..update import Update
class ChosenInlineResult(Object, Update):
@@ -49,13 +33,13 @@ class ChosenInlineResult(Object, Update):
result_id (``str``):
The unique identifier for the result that was chosen.
- from_user (:obj:`User`):
+ from_user (:obj:`~pyrogram.types.User`):
The user that chose the result.
query (``str``):
The query that was used to obtain the result.
- location (:obj:`Location`, *optional*):
+ location (:obj:`~pyrogram.types.Location`, *optional*):
Sender location, only for bots that require user location.
inline_message_id (``str``, *optional*):
@@ -72,11 +56,11 @@ class ChosenInlineResult(Object, Update):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
result_id: str,
- from_user: User,
+ from_user: "types.User",
query: str,
- location: "pyrogram.Location" = None,
+ location: "types.Location" = None,
inline_message_id: str = None
):
super().__init__(client)
@@ -88,10 +72,10 @@ def __init__(
self.inline_message_id = inline_message_id
@staticmethod
- def _parse(client, chosen_inline_result: types.UpdateBotInlineSend, users) -> "ChosenInlineResult":
+ def _parse(client, chosen_inline_result: raw.types.UpdateBotInlineSend, users) -> "ChosenInlineResult":
inline_message_id = None
- if isinstance(chosen_inline_result.msg_id, types.InputBotInlineMessageID):
+ if isinstance(chosen_inline_result.msg_id, raw.types.InputBotInlineMessageID):
inline_message_id = b64encode(
pack(
" "C
return ChosenInlineResult(
result_id=str(chosen_inline_result.id),
- from_user=User._parse(client, users[chosen_inline_result.user_id]),
+ from_user=types.User._parse(client, users[chosen_inline_result.user_id]),
query=chosen_inline_result.query,
- location=Location(
+ location=types.Location(
longitude=chosen_inline_result.geo.long,
latitude=chosen_inline_result.geo.lat,
client=client
diff --git a/pyrogram/client/types/inline_mode/inline_query.py b/pyrogram/types/inline_mode/inline_query.py
similarity index 89%
rename from pyrogram/client/types/inline_mode/inline_query.py
rename to pyrogram/types/inline_mode/inline_query.py
index c48bb05383..57bdffa059 100644
--- a/pyrogram/client/types/inline_mode/inline_query.py
+++ b/pyrogram/types/inline_mode/inline_query.py
@@ -19,12 +19,10 @@
from typing import List, Match
import pyrogram
-from pyrogram.api import types
-from .inline_query_result import InlineQueryResult
-from ..messages_and_media import Location
+from pyrogram import raw
+from pyrogram import types
from ..object import Object
from ..update import Update
-from ..user_and_chats import User
class InlineQuery(Object, Update):
@@ -36,7 +34,7 @@ class InlineQuery(Object, Update):
id (``str``):
Unique identifier for this query.
- from_user (:obj:`User`):
+ from_user (:obj:`~pyrogram.types.User`):
Sender.
query (``str``):
@@ -45,7 +43,7 @@ class InlineQuery(Object, Update):
offset (``str``):
Offset of the results to be returned, can be controlled by the bot.
- location (:obj:`Location`. *optional*):
+ location (:obj:`~pyrogram.types.Location`. *optional*):
Sender location, only for bots that request user location.
matches (List of regex Matches, *optional*):
@@ -56,12 +54,12 @@ class InlineQuery(Object, Update):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
id: str,
- from_user: User,
+ from_user: "types.User",
query: str,
offset: str,
- location: Location = None,
+ location: "types.Location" = None,
matches: List[Match] = None
):
super().__init__(client)
@@ -74,13 +72,13 @@ def __init__(
self.matches = matches
@staticmethod
- def _parse(client, inline_query: types.UpdateBotInlineQuery, users: dict) -> "InlineQuery":
+ def _parse(client, inline_query: raw.types.UpdateBotInlineQuery, users: dict) -> "InlineQuery":
return InlineQuery(
id=str(inline_query.query_id),
- from_user=User._parse(client, users[inline_query.user_id]),
+ from_user=types.User._parse(client, users[inline_query.user_id]),
query=inline_query.query,
offset=inline_query.offset,
- location=Location(
+ location=types.Location(
longitude=inline_query.geo.long,
latitude=inline_query.geo.lat,
client=client
@@ -90,7 +88,7 @@ def _parse(client, inline_query: types.UpdateBotInlineQuery, users: dict) -> "In
async def answer(
self,
- results: List[InlineQueryResult],
+ results: List["types.InlineQueryResult"],
cache_time: int = 300,
is_gallery: bool = False,
is_personal: bool = False,
@@ -98,7 +96,7 @@ async def answer(
switch_pm_text: str = "",
switch_pm_parameter: str = ""
):
- """Bound method *answer* of :obj:`InlineQuery`.
+ """Bound method *answer* of :obj:`~pyrogram.types.InlineQuery`.
Use this method as a shortcut for:
@@ -115,7 +113,7 @@ async def answer(
inline_query.answer([...])
Parameters:
- results (List of :obj:`InlineQueryResult`):
+ results (List of :obj:`~pyrogram.types.InlineQueryResult`):
A list of results for the inline query.
cache_time (``int``, *optional*):
diff --git a/pyrogram/types/inline_mode/inline_query_result.py b/pyrogram/types/inline_mode/inline_query_result.py
new file mode 100644
index 0000000000..c70e52c0fd
--- /dev/null
+++ b/pyrogram/types/inline_mode/inline_query_result.py
@@ -0,0 +1,70 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+from uuid import uuid4
+
+from pyrogram import types
+from ..object import Object
+
+"""- :obj:`~pyrogram.types.InlineQueryResultCachedAudio`
+ - :obj:`~pyrogram.types.InlineQueryResultCachedDocument`
+ - :obj:`~pyrogram.types.InlineQueryResultCachedGif`
+ - :obj:`~pyrogram.types.InlineQueryResultCachedMpeg4Gif`
+ - :obj:`~pyrogram.types.InlineQueryResultCachedPhoto`
+ - :obj:`~pyrogram.types.InlineQueryResultCachedSticker`
+ - :obj:`~pyrogram.types.InlineQueryResultCachedVideo`
+ - :obj:`~pyrogram.types.InlineQueryResultCachedVoice`
+ - :obj:`~pyrogram.types.InlineQueryResultAudio`
+ - :obj:`~pyrogram.types.InlineQueryResultContact`
+ - :obj:`~pyrogram.types.InlineQueryResultGame`
+ - :obj:`~pyrogram.types.InlineQueryResultDocument`
+ - :obj:`~pyrogram.types.InlineQueryResultGif`
+ - :obj:`~pyrogram.types.InlineQueryResultLocation`
+ - :obj:`~pyrogram.types.InlineQueryResultMpeg4Gif`
+ - :obj:`~pyrogram.types.InlineQueryResultPhoto`
+ - :obj:`~pyrogram.types.InlineQueryResultVenue`
+ - :obj:`~pyrogram.types.InlineQueryResultVideo`
+ - :obj:`~pyrogram.types.InlineQueryResultVoice`"""
+
+
+class InlineQueryResult(Object):
+ """One result of an inline query.
+
+ Pyrogram currently supports results of the following types:
+
+ - :obj:`~pyrogram.types.InlineQueryResultArticle`
+ - :obj:`~pyrogram.types.InlineQueryResultPhoto`
+ - :obj:`~pyrogram.types.InlineQueryResultAnimation`
+ """
+
+ def __init__(
+ self,
+ type: str,
+ id: str,
+ input_message_content: "types.InputMessageContent",
+ reply_markup: "types.InlineKeyboardMarkup"
+ ):
+ super().__init__()
+
+ self.type = type
+ self.id = str(uuid4()) if id is None else str(id)
+ self.input_message_content = input_message_content
+ self.reply_markup = reply_markup
+
+ async def write(self):
+ pass
diff --git a/pyrogram/client/types/inline_mode/inline_query_result_animation.py b/pyrogram/types/inline_mode/inline_query_result_animation.py
similarity index 87%
rename from pyrogram/client/types/inline_mode/inline_query_result_animation.py
rename to pyrogram/types/inline_mode/inline_query_result_animation.py
index d53bbd594e..bd0e7037e7 100644
--- a/pyrogram/client/types/inline_mode/inline_query_result_animation.py
+++ b/pyrogram/types/inline_mode/inline_query_result_animation.py
@@ -18,11 +18,10 @@
from typing import Union
-from pyrogram.api import types
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.parser import Parser
from .inline_query_result import InlineQueryResult
-from ..bots_and_keyboards import InlineKeyboardMarkup
-from ..input_message_content import InputMessageContent
-from ...parser import Parser
class InlineQueryResultAnimation(InlineQueryResult):
@@ -61,10 +60,10 @@ class InlineQueryResultAnimation(InlineQueryResult):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
- input_message_content (:obj:`InputMessageContent`):
+ input_message_content (:obj:`~pyrogram.types.InputMessageContent`):
Content of the message to be sent instead of the photo.
"""
@@ -77,8 +76,8 @@ def __init__(
description: str = None,
caption: str = None,
parse_mode: Union[str, None] = object,
- reply_markup: InlineKeyboardMarkup = None,
- input_message_content: InputMessageContent = None
+ reply_markup: "types.InlineKeyboardMarkup" = None,
+ input_message_content: "types.InputMessageContent" = None
):
super().__init__("gif", id, input_message_content, reply_markup)
@@ -92,7 +91,7 @@ def __init__(
self.input_message_content = input_message_content
async def write(self):
- animation = types.InputWebDocument(
+ animation = raw.types.InputWebDocument(
url=self.animation_url,
size=0,
mime_type="image/gif",
@@ -102,14 +101,14 @@ async def write(self):
if self.thumb_url is None:
thumb = animation
else:
- thumb = types.InputWebDocument(
+ thumb = raw.types.InputWebDocument(
url=self.thumb_url,
size=0,
mime_type="image/gif",
attributes=[]
)
- return types.InputBotInlineResult(
+ return raw.types.InputBotInlineResult(
id=self.id,
type=self.type,
title=self.title,
@@ -119,7 +118,7 @@ async def write(self):
send_message=(
self.input_message_content.write(self.reply_markup)
if self.input_message_content
- else types.InputBotInlineMessageMediaAuto(
+ else raw.types.InputBotInlineMessageMediaAuto(
reply_markup=self.reply_markup.write() if self.reply_markup else None,
**await(Parser(None)).parse(self.caption, self.parse_mode)
)
diff --git a/pyrogram/client/types/inline_mode/inline_query_result_article.py b/pyrogram/types/inline_mode/inline_query_result_article.py
similarity index 83%
rename from pyrogram/client/types/inline_mode/inline_query_result_article.py
rename to pyrogram/types/inline_mode/inline_query_result_article.py
index 65e85a0fda..42bf6f0ab7 100644
--- a/pyrogram/client/types/inline_mode/inline_query_result_article.py
+++ b/pyrogram/types/inline_mode/inline_query_result_article.py
@@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from pyrogram.api import types
+from pyrogram import raw
+from pyrogram import types
+
from .inline_query_result import InlineQueryResult
-from ..bots_and_keyboards import InlineKeyboardMarkup
-from ..input_message_content import InputMessageContent
class InlineQueryResultArticle(InlineQueryResult):
@@ -29,7 +29,7 @@ class InlineQueryResultArticle(InlineQueryResult):
title (``str``):
Title for the result.
- input_message_content (:obj:`InputMessageContent`):
+ input_message_content (:obj:`~pyrogram.types.InputMessageContent`):
Content of the message to be sent.
id (``str``, *optional*):
@@ -45,16 +45,16 @@ class InlineQueryResultArticle(InlineQueryResult):
thumb_url (``str``, *optional*):
URL of the thumbnail for the result.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
Inline keyboard attached to the message.
"""
def __init__(
self,
title: str,
- input_message_content: InputMessageContent,
+ input_message_content: "types.InputMessageContent",
id: str = None,
- reply_markup: InlineKeyboardMarkup = None,
+ reply_markup: "types.InlineKeyboardMarkup" = None,
url: str = None,
description: str = None,
thumb_url: str = None
@@ -67,14 +67,14 @@ def __init__(
self.thumb_url = thumb_url
async def write(self):
- return types.InputBotInlineResult(
+ return raw.types.InputBotInlineResult(
id=self.id,
type=self.type,
send_message=await self.input_message_content.write(self.reply_markup),
title=self.title,
description=self.description,
url=self.url,
- thumb=types.InputWebDocument(
+ thumb=raw.types.InputWebDocument(
url=self.thumb_url,
size=0,
mime_type="image/jpeg",
diff --git a/pyrogram/client/types/inline_mode/inline_query_result_photo.py b/pyrogram/types/inline_mode/inline_query_result_photo.py
similarity index 86%
rename from pyrogram/client/types/inline_mode/inline_query_result_photo.py
rename to pyrogram/types/inline_mode/inline_query_result_photo.py
index e3890b9bae..7287abc017 100644
--- a/pyrogram/client/types/inline_mode/inline_query_result_photo.py
+++ b/pyrogram/types/inline_mode/inline_query_result_photo.py
@@ -18,11 +18,10 @@
from typing import Union
-from pyrogram.api import types
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.parser import Parser
from .inline_query_result import InlineQueryResult
-from ..bots_and_keyboards import InlineKeyboardMarkup
-from ..input_message_content import InputMessageContent
-from ...parser import Parser
class InlineQueryResultPhoto(InlineQueryResult):
@@ -61,10 +60,10 @@ class InlineQueryResultPhoto(InlineQueryResult):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
- input_message_content (:obj:`InputMessageContent`):
+ input_message_content (:obj:`~pyrogram.types.InputMessageContent`):
Content of the message to be sent instead of the photo.
"""
@@ -77,8 +76,8 @@ def __init__(
description: str = None,
caption: str = None,
parse_mode: Union[str, None] = object,
- reply_markup: InlineKeyboardMarkup = None,
- input_message_content: InputMessageContent = None
+ reply_markup: "types.InlineKeyboardMarkup" = None,
+ input_message_content: "types.InputMessageContent" = None
):
super().__init__("photo", id, input_message_content, reply_markup)
@@ -92,7 +91,7 @@ def __init__(
self.input_message_content = input_message_content
async def write(self):
- photo = types.InputWebDocument(
+ photo = raw.types.InputWebDocument(
url=self.photo_url,
size=0,
mime_type="image/jpeg",
@@ -102,14 +101,14 @@ async def write(self):
if self.thumb_url is None:
thumb = photo
else:
- thumb = types.InputWebDocument(
+ thumb = raw.types.InputWebDocument(
url=self.thumb_url,
size=0,
mime_type="image/jpeg",
attributes=[]
)
- return types.InputBotInlineResult(
+ return raw.types.InputBotInlineResult(
id=self.id,
type=self.type,
title=self.title,
@@ -119,7 +118,7 @@ async def write(self):
send_message=(
await self.input_message_content.write(self.reply_markup)
if self.input_message_content
- else types.InputBotInlineMessageMediaAuto(
+ else raw.types.InputBotInlineMessageMediaAuto(
reply_markup=self.reply_markup.write() if self.reply_markup else None,
**await(Parser(None)).parse(self.caption, self.parse_mode)
)
diff --git a/pyrogram/client/types/input_media/__init__.py b/pyrogram/types/input_media/__init__.py
similarity index 100%
rename from pyrogram/client/types/input_media/__init__.py
rename to pyrogram/types/input_media/__init__.py
diff --git a/pyrogram/client/types/input_media/input_media.py b/pyrogram/types/input_media/input_media.py
similarity index 83%
rename from pyrogram/client/types/input_media/input_media.py
rename to pyrogram/types/input_media/input_media.py
index 7d8497324c..f692cb8384 100644
--- a/pyrogram/client/types/input_media/input_media.py
+++ b/pyrogram/types/input_media/input_media.py
@@ -24,11 +24,11 @@ class InputMedia(Object):
It should be one of:
- - :obj:`InputMediaAnimation`
- - :obj:`InputMediaDocument`
- - :obj:`InputMediaAudio`
- - :obj:`InputMediaPhoto`
- - :obj:`InputMediaVideo`
+ - :obj:`~pyrogram.types.InputMediaAnimation`
+ - :obj:`~pyrogram.types.InputMediaDocument`
+ - :obj:`~pyrogram.types.InputMediaAudio`
+ - :obj:`~pyrogram.types.InputMediaPhoto`
+ - :obj:`~pyrogram.types.InputMediaVideo`
"""
def __init__(self, media: str, file_ref: str, caption: str, parse_mode: str):
diff --git a/pyrogram/client/types/input_media/input_media_animation.py b/pyrogram/types/input_media/input_media_animation.py
similarity index 98%
rename from pyrogram/client/types/input_media/input_media_animation.py
rename to pyrogram/types/input_media/input_media_animation.py
index ee74668996..786a4ee012 100644
--- a/pyrogram/client/types/input_media/input_media_animation.py
+++ b/pyrogram/types/input_media/input_media_animation.py
@@ -18,7 +18,7 @@
from typing import Union
-from . import InputMedia
+from .input_media import InputMedia
class InputMediaAnimation(InputMedia):
diff --git a/pyrogram/client/types/input_media/input_media_audio.py b/pyrogram/types/input_media/input_media_audio.py
similarity index 94%
rename from pyrogram/client/types/input_media/input_media_audio.py
rename to pyrogram/types/input_media/input_media_audio.py
index 66cd9e1fb4..a5ae9fca4b 100644
--- a/pyrogram/client/types/input_media/input_media_audio.py
+++ b/pyrogram/types/input_media/input_media_audio.py
@@ -18,13 +18,13 @@
from typing import Union
-from . import InputMedia
+from .input_media import InputMedia
class InputMediaAudio(InputMedia):
"""An audio to be sent inside an album.
- It is intended to be used with :obj:`send_media_group() `.
+ It is intended to be used with :meth:`~pyrogram.Client.send_media_group`.
Parameters:
media (``str``):
@@ -70,7 +70,7 @@ def __init__(
caption: str = "",
parse_mode: Union[str, None] = object,
duration: int = 0,
- performer: int = "",
+ performer: str = "",
title: str = ""
):
super().__init__(media, file_ref, caption, parse_mode)
diff --git a/pyrogram/client/types/input_media/input_media_document.py b/pyrogram/types/input_media/input_media_document.py
similarity index 98%
rename from pyrogram/client/types/input_media/input_media_document.py
rename to pyrogram/types/input_media/input_media_document.py
index 7ff3ca0b2e..1df2c3c329 100644
--- a/pyrogram/client/types/input_media/input_media_document.py
+++ b/pyrogram/types/input_media/input_media_document.py
@@ -18,7 +18,7 @@
from typing import Union
-from . import InputMedia
+from .input_media import InputMedia
class InputMediaDocument(InputMedia):
diff --git a/pyrogram/client/types/input_media/input_media_photo.py b/pyrogram/types/input_media/input_media_photo.py
similarity index 94%
rename from pyrogram/client/types/input_media/input_media_photo.py
rename to pyrogram/types/input_media/input_media_photo.py
index f40bdef76c..f4e5df8e45 100644
--- a/pyrogram/client/types/input_media/input_media_photo.py
+++ b/pyrogram/types/input_media/input_media_photo.py
@@ -18,12 +18,12 @@
from typing import Union
-from . import InputMedia
+from .input_media import InputMedia
class InputMediaPhoto(InputMedia):
"""A photo to be sent inside an album.
- It is intended to be used with :obj:`send_media_group() `.
+ It is intended to be used with :obj:`~pyrogram.Client.send_media_group`.
Parameters:
media (``str``):
diff --git a/pyrogram/client/types/input_media/input_media_video.py b/pyrogram/types/input_media/input_media_video.py
similarity index 96%
rename from pyrogram/client/types/input_media/input_media_video.py
rename to pyrogram/types/input_media/input_media_video.py
index 6b986a32e9..dc65d00296 100644
--- a/pyrogram/client/types/input_media/input_media_video.py
+++ b/pyrogram/types/input_media/input_media_video.py
@@ -18,12 +18,12 @@
from typing import Union
-from . import InputMedia
+from .input_media import InputMedia
class InputMediaVideo(InputMedia):
"""A video to be sent inside an album.
- It is intended to be used with :obj:`send_media_group() `.
+ It is intended to be used with :obj:`~pyrogram.Client.send_media_group`.
Parameters:
media (``str``):
diff --git a/pyrogram/client/types/input_media/input_phone_contact.py b/pyrogram/types/input_media/input_phone_contact.py
similarity index 93%
rename from pyrogram/client/types/input_media/input_phone_contact.py
rename to pyrogram/types/input_media/input_phone_contact.py
index e2c3aca142..58c73252c0 100644
--- a/pyrogram/client/types/input_media/input_phone_contact.py
+++ b/pyrogram/types/input_media/input_phone_contact.py
@@ -16,8 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from pyrogram.api.types import InputPhoneContact as RawInputPhoneContact
-
+from pyrogram import raw
from pyrogram.session.internals import MsgId
from ..object import Object
@@ -44,7 +43,7 @@ def __new__(cls,
phone: str,
first_name: str,
last_name: str = ""):
- return RawInputPhoneContact(
+ return raw.types.InputPhoneContact(
client_id=MsgId(),
phone="+" + phone.strip("+"),
first_name=first_name,
diff --git a/pyrogram/client/types/input_message_content/__init__.py b/pyrogram/types/input_message_content/__init__.py
similarity index 100%
rename from pyrogram/client/types/input_message_content/__init__.py
rename to pyrogram/types/input_message_content/__init__.py
diff --git a/pyrogram/client/types/input_message_content/input_message_content.py b/pyrogram/types/input_message_content/input_message_content.py
similarity index 83%
rename from pyrogram/client/types/input_message_content/input_message_content.py
rename to pyrogram/types/input_message_content/input_message_content.py
index f97e3cd9ad..4ecbc0a604 100644
--- a/pyrogram/client/types/input_message_content/input_message_content.py
+++ b/pyrogram/types/input_message_content/input_message_content.py
@@ -18,9 +18,9 @@
from ..object import Object
-"""- :obj:`InputLocationMessageContent`
- - :obj:`InputVenueMessageContent`
- - :obj:`InputContactMessageContent`"""
+"""- :obj:`~pyrogram.types.InputLocationMessageContent`
+ - :obj:`~pyrogram.types.InputVenueMessageContent`
+ - :obj:`~pyrogram.types.InputContactMessageContent`"""
class InputMessageContent(Object):
@@ -28,7 +28,7 @@ class InputMessageContent(Object):
Pyrogram currently supports the following types:
- - :obj:`InputTextMessageContent`
+ - :obj:`~pyrogram.types.InputTextMessageContent`
"""
def __init__(self):
diff --git a/pyrogram/client/types/input_message_content/input_text_message_content.py b/pyrogram/types/input_message_content/input_text_message_content.py
similarity index 95%
rename from pyrogram/client/types/input_message_content/input_text_message_content.py
rename to pyrogram/types/input_message_content/input_text_message_content.py
index 1247011ea2..ac584cc202 100644
--- a/pyrogram/client/types/input_message_content/input_text_message_content.py
+++ b/pyrogram/types/input_message_content/input_text_message_content.py
@@ -18,9 +18,9 @@
from typing import Union
-from pyrogram.api import types
+from pyrogram import raw
+from pyrogram.parser import Parser
from .input_message_content import InputMessageContent
-from ...parser import Parser
class InputTextMessageContent(InputMessageContent):
@@ -49,7 +49,7 @@ def __init__(self, message_text: str, parse_mode: Union[str, None] = object, dis
self.disable_web_page_preview = disable_web_page_preview
async def write(self, reply_markup):
- return types.InputBotInlineMessageText(
+ return raw.types.InputBotInlineMessageText(
no_webpage=self.disable_web_page_preview or None,
reply_markup=reply_markup.write() if reply_markup else None,
**await(Parser(None)).parse(self.message_text, self.parse_mode)
diff --git a/pyrogram/client/types/list.py b/pyrogram/types/list.py
similarity index 88%
rename from pyrogram/client/types/list.py
rename to pyrogram/types/list.py
index 118c4304f3..2bdc425b56 100644
--- a/pyrogram/client/types/list.py
+++ b/pyrogram/types/list.py
@@ -27,6 +27,4 @@ def __str__(self):
return Object.__str__(self)
def __repr__(self):
- return "pyrogram.client.types.list.List([{}])".format(
- ",".join(Object.__repr__(i) for i in self)
- )
+ return f"pyrogram.types.List([{','.join(Object.__repr__(i) for i in self)}])"
diff --git a/pyrogram/client/types/messages_and_media/__init__.py b/pyrogram/types/messages_and_media/__init__.py
similarity index 100%
rename from pyrogram/client/types/messages_and_media/__init__.py
rename to pyrogram/types/messages_and_media/__init__.py
index d24240436b..aeae6375fa 100644
--- a/pyrogram/client/types/messages_and_media/__init__.py
+++ b/pyrogram/types/messages_and_media/__init__.py
@@ -19,6 +19,7 @@
from .animation import Animation
from .audio import Audio
from .contact import Contact
+from .dice import Dice
from .document import Document
from .game import Game
from .location import Location
@@ -35,7 +36,6 @@
from .video_note import VideoNote
from .voice import Voice
from .webpage import WebPage
-from .dice import Dice
__all__ = [
"Animation", "Audio", "Contact", "Document", "Game", "Location", "Message", "MessageEntity", "Photo", "Thumbnail",
diff --git a/pyrogram/client/types/messages_and_media/animation.py b/pyrogram/types/messages_and_media/animation.py
similarity index 88%
rename from pyrogram/client/types/messages_and_media/animation.py
rename to pyrogram/types/messages_and_media/animation.py
index 497f943e2e..97f34e967d 100644
--- a/pyrogram/client/types/messages_and_media/animation.py
+++ b/pyrogram/types/messages_and_media/animation.py
@@ -20,10 +20,10 @@
from typing import List
import pyrogram
-from pyrogram.api import types
-from .thumbnail import Thumbnail
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.utils import encode_file_id, encode_file_ref
from ..object import Object
-from ...ext.utils import encode_file_id, encode_file_ref
class Animation(Object):
@@ -57,14 +57,14 @@ class Animation(Object):
date (``int``, *optional*):
Date the animation was sent in Unix time.
- thumbs (List of :obj:`Thumbnail`, *optional*):
+ thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*):
Animation thumbnails.
"""
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
width: int,
@@ -74,7 +74,7 @@ def __init__(
mime_type: str = None,
file_size: int = None,
date: int = None,
- thumbs: List[Thumbnail] = None
+ thumbs: List["types.Thumbnail"] = None
):
super().__init__(client)
@@ -92,8 +92,8 @@ def __init__(
@staticmethod
def _parse(
client,
- animation: types.Document,
- video_attributes: types.DocumentAttributeVideo,
+ animation: "raw.types.Document",
+ video_attributes: "raw.types.DocumentAttributeVideo",
file_name: str
) -> "Animation":
return Animation(
@@ -114,6 +114,6 @@ def _parse(
file_size=animation.size,
file_name=file_name,
date=animation.date,
- thumbs=Thumbnail._parse(client, animation),
+ thumbs=types.Thumbnail._parse(client, animation),
client=client
)
diff --git a/pyrogram/client/types/messages_and_media/audio.py b/pyrogram/types/messages_and_media/audio.py
similarity index 88%
rename from pyrogram/client/types/messages_and_media/audio.py
rename to pyrogram/types/messages_and_media/audio.py
index bd36012635..a54b6c9fb6 100644
--- a/pyrogram/client/types/messages_and_media/audio.py
+++ b/pyrogram/types/messages_and_media/audio.py
@@ -20,10 +20,10 @@
from typing import List
import pyrogram
-from pyrogram.api import types
-from .thumbnail import Thumbnail
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.utils import encode_file_id, encode_file_ref
from ..object import Object
-from ...ext.utils import encode_file_id, encode_file_ref
class Audio(Object):
@@ -57,14 +57,14 @@ class Audio(Object):
title (``str``, *optional*):
Title of the audio as defined by sender or by audio tags.
- thumbs (List of :obj:`Thumbnail`, *optional*):
+ thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*):
Thumbnails of the music file album cover.
"""
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
duration: int,
@@ -74,7 +74,7 @@ def __init__(
date: int = None,
performer: str = None,
title: str = None,
- thumbs: List[Thumbnail] = None
+ thumbs: List["types.Thumbnail"] = None
):
super().__init__(client)
@@ -92,8 +92,8 @@ def __init__(
@staticmethod
def _parse(
client,
- audio: types.Document,
- audio_attributes: types.DocumentAttributeAudio,
+ audio: "raw.types.Document",
+ audio_attributes: "raw.types.DocumentAttributeAudio",
file_name: str
) -> "Audio":
return Audio(
@@ -114,6 +114,6 @@ def _parse(
file_size=audio.size,
file_name=file_name,
date=audio.date,
- thumbs=Thumbnail._parse(client, audio),
+ thumbs=types.Thumbnail._parse(client, audio),
client=client
)
diff --git a/pyrogram/client/types/messages_and_media/contact.py b/pyrogram/types/messages_and_media/contact.py
similarity index 92%
rename from pyrogram/client/types/messages_and_media/contact.py
rename to pyrogram/types/messages_and_media/contact.py
index c2289ee144..8ce25d4033 100644
--- a/pyrogram/client/types/messages_and_media/contact.py
+++ b/pyrogram/types/messages_and_media/contact.py
@@ -17,8 +17,7 @@
# along with Pyrogram. If not, see .
import pyrogram
-
-from pyrogram.api import types
+from pyrogram import raw
from ..object import Object
@@ -45,7 +44,7 @@ class Contact(Object):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
phone_number: str,
first_name: str,
last_name: str = None,
@@ -61,7 +60,7 @@ def __init__(
self.vcard = vcard
@staticmethod
- def _parse(client, contact: types.MessageMediaContact) -> "Contact":
+ def _parse(client: "pyrogram.Client", contact: "raw.types.MessageMediaContact") -> "Contact":
return Contact(
phone_number=contact.phone_number,
first_name=contact.first_name,
diff --git a/pyrogram/client/types/messages_and_media/dice.py b/pyrogram/types/messages_and_media/dice.py
similarity index 88%
rename from pyrogram/client/types/messages_and_media/dice.py
rename to pyrogram/types/messages_and_media/dice.py
index e76cad1efc..e89fb38b40 100644
--- a/pyrogram/client/types/messages_and_media/dice.py
+++ b/pyrogram/types/messages_and_media/dice.py
@@ -17,7 +17,7 @@
# along with Pyrogram. If not, see .
import pyrogram
-from pyrogram.api import types
+from pyrogram import raw
from ..object import Object
@@ -32,14 +32,14 @@ class Dice(Object):
Value of the dice, 1-6 for currently supported base emoji.
"""
- def __init__(self, *, client: "pyrogram.BaseClient" = None, emoji: str, value: int):
+ def __init__(self, *, client: "pyrogram.Client" = None, emoji: str, value: int):
super().__init__(client)
self.emoji = emoji
self.value = value
@staticmethod
- def _parse(client, dice: types.MessageMediaDice) -> "Dice":
+ def _parse(client, dice: "raw.types.MessageMediaDice") -> "Dice":
return Dice(
emoji=dice.emoticon,
value=dice.value,
diff --git a/pyrogram/client/types/messages_and_media/document.py b/pyrogram/types/messages_and_media/document.py
similarity index 86%
rename from pyrogram/client/types/messages_and_media/document.py
rename to pyrogram/types/messages_and_media/document.py
index ec6a5edc07..19975b74ef 100644
--- a/pyrogram/client/types/messages_and_media/document.py
+++ b/pyrogram/types/messages_and_media/document.py
@@ -20,10 +20,10 @@
from typing import List
import pyrogram
-from pyrogram.api import types
-from .thumbnail import Thumbnail
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.utils import encode_file_id, encode_file_ref
from ..object import Object
-from ...ext.utils import encode_file_id, encode_file_ref
class Document(Object):
@@ -48,21 +48,21 @@ class Document(Object):
date (``int``, *optional*):
Date the document was sent in Unix time.
- thumbs (List of :obj:`Thumbnail`, *optional*):
+ thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*):
Document thumbnails as defined by sender.
"""
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
file_name: str = None,
mime_type: str = None,
file_size: int = None,
date: int = None,
- thumbs: List[Thumbnail] = None
+ thumbs: List["types.Thumbnail"] = None
):
super().__init__(client)
@@ -75,7 +75,7 @@ def __init__(
self.thumbs = thumbs
@staticmethod
- def _parse(client, document: types.Document, file_name: str) -> "Document":
+ def _parse(client, document: "raw.types.Document", file_name: str) -> "Document":
return Document(
file_id=encode_file_id(
pack(
@@ -91,6 +91,6 @@ def _parse(client, document: types.Document, file_name: str) -> "Document":
mime_type=document.mime_type,
file_size=document.size,
date=document.date,
- thumbs=Thumbnail._parse(client, document),
+ thumbs=types.Thumbnail._parse(client, document),
client=client
)
diff --git a/pyrogram/client/types/messages_and_media/game.py b/pyrogram/types/messages_and_media/game.py
similarity index 79%
rename from pyrogram/client/types/messages_and_media/game.py
rename to pyrogram/types/messages_and_media/game.py
index f828a2707e..a80888a2c5 100644
--- a/pyrogram/client/types/messages_and_media/game.py
+++ b/pyrogram/types/messages_and_media/game.py
@@ -17,9 +17,8 @@
# along with Pyrogram. If not, see .
import pyrogram
-from pyrogram.api import types
-from .animation import Animation
-from .photo import Photo
+from pyrogram import raw
+from pyrogram import types
from ..object import Object
@@ -40,10 +39,10 @@ class Game(Object):
description (``str``):
Description of the game.
- photo (:obj:`Photo`):
+ photo (:obj:`~pyrogram.types.Photo`):
Photo that will be displayed in the game message in chats.
- animation (:obj:`Animation`, *optional*):
+ animation (:obj:`~pyrogram.types.Animation`, *optional*):
Animation that will be displayed in the game message in chats.
Upload via BotFather.
"""
@@ -51,13 +50,13 @@ class Game(Object):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
id: int,
title: str,
short_name: str,
description: str,
- photo: Photo,
- animation: Animation = None
+ photo: "types.Photo",
+ animation: "types.Animation" = None
):
super().__init__(client)
@@ -69,8 +68,8 @@ def __init__(
self.animation = animation
@staticmethod
- def _parse(client, message: types.Message) -> "Game":
- game = message.media.game # type: types.Game
+ def _parse(client, message: "raw.types.Message") -> "Game":
+ game: "raw.types.Game" = message.media.game
animation = None
if game.document:
@@ -78,14 +77,14 @@ def _parse(client, message: types.Message) -> "Game":
file_name = getattr(
attributes.get(
- types.DocumentAttributeFilename, None
+ raw.types.DocumentAttributeFilename, None
), "file_name", None
)
- animation = Animation._parse(
+ animation = types.Animation._parse(
client,
game.document,
- attributes.get(types.DocumentAttributeVideo, None),
+ attributes.get(raw.types.DocumentAttributeVideo, None),
file_name
)
@@ -94,7 +93,7 @@ def _parse(client, message: types.Message) -> "Game":
title=game.title,
short_name=game.short_name,
description=game.description,
- photo=Photo._parse(client, game.photo),
+ photo=types.Photo._parse(client, game.photo),
animation=animation,
client=client
)
diff --git a/pyrogram/client/types/messages_and_media/location.py b/pyrogram/types/messages_and_media/location.py
similarity index 88%
rename from pyrogram/client/types/messages_and_media/location.py
rename to pyrogram/types/messages_and_media/location.py
index 38af642f83..ac122a6d0e 100644
--- a/pyrogram/client/types/messages_and_media/location.py
+++ b/pyrogram/types/messages_and_media/location.py
@@ -18,7 +18,7 @@
import pyrogram
-from pyrogram.api import types
+from pyrogram import raw
from ..object import Object
@@ -36,7 +36,7 @@ class Location(Object):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
longitude: float,
latitude: float
):
@@ -46,8 +46,8 @@ def __init__(
self.latitude = latitude
@staticmethod
- def _parse(client, geo_point: types.GeoPoint) -> "Location":
- if isinstance(geo_point, types.GeoPoint):
+ def _parse(client, geo_point: "raw.types.GeoPoint") -> "Location":
+ if isinstance(geo_point, raw.types.GeoPoint):
return Location(
longitude=geo_point.long,
latitude=geo_point.lat,
diff --git a/pyrogram/client/types/messages_and_media/message.py b/pyrogram/types/messages_and_media/message.py
similarity index 83%
rename from pyrogram/client/types/messages_and_media/message.py
rename to pyrogram/types/messages_and_media/message.py
index 8bf7cac4db..51bb4293d5 100644
--- a/pyrogram/client/types/messages_and_media/message.py
+++ b/pyrogram/types/messages_and_media/message.py
@@ -20,19 +20,13 @@
from typing import List, Match, Union, BinaryIO
import pyrogram
-from pyrogram.api import types
-from pyrogram.client.types.input_media import InputMedia
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
from pyrogram.errors import MessageIdsEmpty
-from .contact import Contact
-from .location import Location
-from .message_entity import MessageEntity
-from ..messages_and_media.photo import Photo
+from pyrogram.parser import utils as parser_utils, Parser
from ..object import Object
from ..update import Update
-from ..user_and_chats.chat import Chat
-from ..user_and_chats.user import User
-from ...ext import utils
-from ...parser import utils as parser_utils, Parser
class Str(str):
@@ -68,19 +62,19 @@ class Message(Object, Update):
date (``int``, *optional*):
Date the message was sent in Unix time.
- chat (:obj:`Chat`, *optional*):
+ chat (:obj:`~pyrogram.types.Chat`, *optional*):
Conversation the message belongs to.
- from_user (:obj:`User`, *optional*):
+ from_user (:obj:`~pyrogram.types.User`, *optional*):
Sender, empty for messages sent to channels.
- forward_from (:obj:`User`, *optional*):
+ forward_from (:obj:`~pyrogram.types.User`, *optional*):
For forwarded messages, sender of the original message.
forward_sender_name (``str``, *optional*):
For messages forwarded from users who have hidden their accounts, name of the user.
- forward_from_chat (:obj:`Chat`, *optional*):
+ forward_from_chat (:obj:`~pyrogram.types.Chat`, *optional*):
For messages forwarded from channels, information about the original channel.
forward_from_message_id (``int``, *optional*):
@@ -92,7 +86,7 @@ class Message(Object, Update):
forward_date (``int``, *optional*):
For forwarded messages, date the original message was sent in Unix time.
- reply_to_message (:obj:`Message`, *optional*):
+ reply_to_message (:obj:`~pyrogram.types.Message`, *optional*):
For replies, the original message. Note that the Message object in this field will not contain
further reply_to_message fields even if it itself is a reply.
@@ -129,38 +123,38 @@ class Message(Object, Update):
*text.html* to get the marked up message text. In case there is no entity, the fields
will contain the same text as *text*.
- entities (List of :obj:`MessageEntity`, *optional*):
+ entities (List of :obj:`~pyrogram.types.MessageEntity`, *optional*):
For text messages, special entities like usernames, URLs, bot commands, etc. that appear in the text.
- caption_entities (List of :obj:`MessageEntity`, *optional*):
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`, *optional*):
For messages with a caption, special entities like usernames, URLs, bot commands, etc. that appear
in the caption.
- audio (:obj:`Audio`, *optional*):
+ audio (:obj:`~pyrogram.types.Audio`, *optional*):
Message is an audio file, information about the file.
- document (:obj:`Document`, *optional*):
+ document (:obj:`~pyrogram.types.Document`, *optional*):
Message is a general file, information about the file.
- photo (:obj:`Photo`, *optional*):
+ photo (:obj:`~pyrogram.types.Photo`, *optional*):
Message is a photo, information about the photo.
- sticker (:obj:`Sticker`, *optional*):
+ sticker (:obj:`~pyrogram.types.Sticker`, *optional*):
Message is a sticker, information about the sticker.
- animation (:obj:`Animation`, *optional*):
+ animation (:obj:`~pyrogram.types.Animation`, *optional*):
Message is an animation, information about the animation.
- game (:obj:`Game`, *optional*):
+ game (:obj:`~pyrogram.types.Game`, *optional*):
Message is a game, information about the game.
- video (:obj:`Video`, *optional*):
+ video (:obj:`~pyrogram.types.Video`, *optional*):
Message is a video, information about the video.
- voice (:obj:`Voice`, *optional*):
+ voice (:obj:`~pyrogram.types.Voice`, *optional*):
Message is a voice message, information about the file.
- video_note (:obj:`VideoNote`, *optional*):
+ video_note (:obj:`~pyrogram.types.VideoNote`, *optional*):
Message is a video note, information about the video message.
caption (``str``, *optional*):
@@ -169,35 +163,35 @@ class Message(Object, Update):
*caption.html* to get the marked up caption text. In case there is no caption entity, the fields
will contain the same text as *caption*.
- contact (:obj:`Contact`, *optional*):
+ contact (:obj:`~pyrogram.types.Contact`, *optional*):
Message is a shared contact, information about the contact.
- location (:obj:`Location`, *optional*):
+ location (:obj:`~pyrogram.types.Location`, *optional*):
Message is a shared location, information about the location.
- venue (:obj:`Venue`, *optional*):
+ venue (:obj:`~pyrogram.types.Venue`, *optional*):
Message is a venue, information about the venue.
- web_page (:obj:`WebPage`, *optional*):
+ web_page (:obj:`~pyrogram.types.WebPage`, *optional*):
Message was sent with a webpage preview.
- poll (:obj:`Poll`, *optional*):
+ poll (:obj:`~pyrogram.types.Poll`, *optional*):
Message is a native poll, information about the poll.
- dice (:obj:`Dice`, *optional*):
+ dice (:obj:`~pyrogram.types.Dice`, *optional*):
A dice containing a value that is randomly generated by Telegram.
- new_chat_members (List of :obj:`User`, *optional*):
+ new_chat_members (List of :obj:`~pyrogram.types.User`, *optional*):
New members that were added to the group or supergroup and information about them
(the bot itself may be one of these members).
- left_chat_member (:obj:`User`, *optional*):
+ left_chat_member (:obj:`~pyrogram.types.User`, *optional*):
A member was removed from the group, information about them (this member may be the bot itself).
new_chat_title (``str``, *optional*):
A chat title was changed to this value.
- new_chat_photo (:obj:`Photo`, *optional*):
+ new_chat_photo (:obj:`~pyrogram.types.Photo`, *optional*):
A chat photo was change to this value.
delete_chat_photo (``bool``, *optional*):
@@ -230,19 +224,19 @@ class Message(Object, Update):
in interpreting it. But it is smaller than 52 bits, so a signed 64 bit integer or double-precision float
type are safe for storing this identifier.
- pinned_message (:obj:`Message`, *optional*):
+ pinned_message (:obj:`~pyrogram.types.Message`, *optional*):
Specified message was pinned.
Note that the Message object in this field will not contain further reply_to_message fields even if it
is itself a reply.
- game_high_score (:obj:`GameHighScore`, *optional*):
+ game_high_score (:obj:`~pyrogram.types.GameHighScore`, *optional*):
The game score for a user.
The reply_to_message field will contain the game Message.
views (``int``, *optional*):
Channel post views.
- via_bot (:obj:`User`):
+ via_bot (:obj:`~pyrogram.types.User`):
The information of the bot that generated the message from an inline query of a user.
outgoing (``bool``, *optional*):
@@ -261,9 +255,9 @@ class Message(Object, Update):
command (List of ``str``, *optional*):
A list containing the command and its arguments, if any.
E.g.: "/start 1 2 3" would produce ["start", "1", "2", "3"].
- Only applicable when using :obj:`Filters.command `.
+ Only applicable when using :obj:`~pyrogram.filters.command`.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
"""
@@ -273,14 +267,14 @@ class Message(Object, Update):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
message_id: int,
date: int = None,
- chat: Chat = None,
- from_user: User = None,
- forward_from: User = None,
+ chat: "types.Chat" = None,
+ from_user: "types.User" = None,
+ forward_from: "types.User" = None,
forward_sender_name: str = None,
- forward_from_chat: Chat = None,
+ forward_from_chat: "types.Chat" = None,
forward_from_message_id: int = None,
forward_signature: str = None,
forward_date: int = None,
@@ -295,28 +289,28 @@ def __init__(
media_group_id: str = None,
author_signature: str = None,
text: Str = None,
- entities: List["pyrogram.MessageEntity"] = None,
- caption_entities: List["pyrogram.MessageEntity"] = None,
- audio: "pyrogram.Audio" = None,
- document: "pyrogram.Document" = None,
- photo: "pyrogram.Photo" = None,
- sticker: "pyrogram.Sticker" = None,
- animation: "pyrogram.Animation" = None,
- game: "pyrogram.Game" = None,
- video: "pyrogram.Video" = None,
- voice: "pyrogram.Voice" = None,
- video_note: "pyrogram.VideoNote" = None,
+ entities: List["types.MessageEntity"] = None,
+ caption_entities: List["types.MessageEntity"] = None,
+ audio: "types.Audio" = None,
+ document: "types.Document" = None,
+ photo: "types.Photo" = None,
+ sticker: "types.Sticker" = None,
+ animation: "types.Animation" = None,
+ game: "types.Game" = None,
+ video: "types.Video" = None,
+ voice: "types.Voice" = None,
+ video_note: "types.VideoNote" = None,
caption: Str = None,
- contact: "pyrogram.Contact" = None,
- location: "pyrogram.Location" = None,
- venue: "pyrogram.Venue" = None,
- web_page: "pyrogram.WebPage" = None,
- poll: "pyrogram.Poll" = None,
- dice: "pyrogram.Dice" = None,
- new_chat_members: List[User] = None,
- left_chat_member: User = None,
+ contact: "types.Contact" = None,
+ location: "types.Location" = None,
+ venue: "types.Venue" = None,
+ web_page: "types.WebPage" = None,
+ poll: "types.Poll" = None,
+ dice: "types.Dice" = None,
+ new_chat_members: List["types.User"] = None,
+ left_chat_member: "types.User" = None,
new_chat_title: str = None,
- new_chat_photo: "pyrogram.Photo" = None,
+ new_chat_photo: "types.Photo" = None,
delete_chat_photo: bool = None,
group_chat_created: bool = None,
supergroup_chat_created: bool = None,
@@ -326,15 +320,15 @@ def __init__(
pinned_message: "Message" = None,
game_high_score: int = None,
views: int = None,
- via_bot: User = None,
+ via_bot: "types.User" = None,
outgoing: bool = None,
matches: List[Match] = None,
command: List[str] = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None
):
super().__init__(client)
@@ -398,12 +392,18 @@ def __init__(
self.reply_markup = reply_markup
@staticmethod
- async def _parse(client, message: types.Message or types.MessageService or types.MessageEmpty, users: dict,
- chats: dict, is_scheduled: bool = False, replies: int = 1):
- if isinstance(message, types.MessageEmpty):
+ async def _parse(
+ client,
+ message: raw.base.Message,
+ users: dict,
+ chats: dict,
+ is_scheduled: bool = False,
+ replies: int = 1
+ ):
+ if isinstance(message, raw.types.MessageEmpty):
return Message(message_id=message.id, empty=True, client=client)
- if isinstance(message, types.MessageService):
+ if isinstance(message, raw.types.MessageService):
action = message.action
new_chat_members = None
@@ -416,32 +416,32 @@ async def _parse(client, message: types.Message or types.MessageService or types
channel_chat_created = None
new_chat_photo = None
- if isinstance(action, types.MessageActionChatAddUser):
- new_chat_members = [User._parse(client, users[i]) for i in action.users]
- elif isinstance(action, types.MessageActionChatJoinedByLink):
- new_chat_members = [User._parse(client, users[message.from_id])]
- elif isinstance(action, types.MessageActionChatDeleteUser):
- left_chat_member = User._parse(client, users[action.user_id])
- elif isinstance(action, types.MessageActionChatEditTitle):
+ if isinstance(action, raw.types.MessageActionChatAddUser):
+ new_chat_members = [types.User._parse(client, users[i]) for i in action.users]
+ elif isinstance(action, raw.types.MessageActionChatJoinedByLink):
+ new_chat_members = [types.User._parse(client, users[message.from_id])]
+ elif isinstance(action, raw.types.MessageActionChatDeleteUser):
+ left_chat_member = types.User._parse(client, users[action.user_id])
+ elif isinstance(action, raw.types.MessageActionChatEditTitle):
new_chat_title = action.title
- elif isinstance(action, types.MessageActionChatDeletePhoto):
+ elif isinstance(action, raw.types.MessageActionChatDeletePhoto):
delete_chat_photo = True
- elif isinstance(action, types.MessageActionChatMigrateTo):
+ elif isinstance(action, raw.types.MessageActionChatMigrateTo):
migrate_to_chat_id = action.channel_id
- elif isinstance(action, types.MessageActionChannelMigrateFrom):
+ elif isinstance(action, raw.types.MessageActionChannelMigrateFrom):
migrate_from_chat_id = action.chat_id
- elif isinstance(action, types.MessageActionChatCreate):
+ elif isinstance(action, raw.types.MessageActionChatCreate):
group_chat_created = True
- elif isinstance(action, types.MessageActionChannelCreate):
+ elif isinstance(action, raw.types.MessageActionChannelCreate):
channel_chat_created = True
- elif isinstance(action, types.MessageActionChatEditPhoto):
- new_chat_photo = Photo._parse(client, action.photo)
+ elif isinstance(action, raw.types.MessageActionChatEditPhoto):
+ new_chat_photo = types.Photo._parse(client, action.photo)
parsed_message = Message(
message_id=message.id,
date=message.date,
- chat=Chat._parse(client, message, users, chats),
- from_user=User._parse(client, users.get(message.from_id, None)),
+ chat=types.Chat._parse(client, message, users, chats),
+ from_user=types.User._parse(client, users.get(message.from_id, None)),
service=True,
new_chat_members=new_chat_members,
left_chat_member=left_chat_member,
@@ -456,7 +456,7 @@ async def _parse(client, message: types.Message or types.MessageService or types
# TODO: supergroup_chat_created
)
- if isinstance(action, types.MessageActionPinMessage):
+ if isinstance(action, raw.types.MessageActionPinMessage):
try:
parsed_message.pinned_message = await client.get_messages(
parsed_message.chat.id,
@@ -466,8 +466,8 @@ async def _parse(client, message: types.Message or types.MessageService or types
except MessageIdsEmpty:
pass
- if isinstance(action, types.MessageActionGameScore):
- parsed_message.game_high_score = pyrogram.GameHighScore._parse_action(client, message, users)
+ if isinstance(action, raw.types.MessageActionGameScore):
+ parsed_message.game_high_score = types.GameHighScore._parse_action(client, message, users)
if message.reply_to_msg_id and replies:
try:
@@ -481,9 +481,9 @@ async def _parse(client, message: types.Message or types.MessageService or types
return parsed_message
- if isinstance(message, types.Message):
- entities = [MessageEntity._parse(client, entity, users) for entity in message.entities]
- entities = pyrogram.List(filter(lambda x: x is not None, entities))
+ if isinstance(message, raw.types.Message):
+ entities = [types.MessageEntity._parse(client, entity, users) for entity in message.entities]
+ entities = types.List(filter(lambda x: x is not None, entities))
forward_from = None
forward_sender_name = None
@@ -492,17 +492,17 @@ async def _parse(client, message: types.Message or types.MessageService or types
forward_signature = None
forward_date = None
- forward_header = message.fwd_from # type: types.MessageFwdHeader
+ forward_header = message.fwd_from # type: raw.types.MessageFwdHeader
if forward_header:
forward_date = forward_header.date
if forward_header.from_id:
- forward_from = User._parse(client, users[forward_header.from_id])
+ forward_from = types.User._parse(client, users[forward_header.from_id])
elif forward_header.from_name:
forward_sender_name = forward_header.from_name
else:
- forward_from_chat = Chat._parse_channel_chat(client, chats[forward_header.channel_id])
+ forward_from_chat = types.Chat._parse_channel_chat(client, chats[forward_header.channel_id])
forward_from_message_id = forward_header.channel_post
forward_signature = forward_header.post_author
@@ -525,87 +525,87 @@ async def _parse(client, message: types.Message or types.MessageService or types
media = message.media
if media:
- if isinstance(media, types.MessageMediaPhoto):
- photo = Photo._parse(client, media.photo, media.ttl_seconds)
- elif isinstance(media, types.MessageMediaGeo):
- location = Location._parse(client, media.geo)
- elif isinstance(media, types.MessageMediaContact):
- contact = Contact._parse(client, media)
- elif isinstance(media, types.MessageMediaVenue):
- venue = pyrogram.Venue._parse(client, media)
- elif isinstance(media, types.MessageMediaGame):
- game = pyrogram.Game._parse(client, message)
- elif isinstance(media, types.MessageMediaDocument):
+ if isinstance(media, raw.types.MessageMediaPhoto):
+ photo = types.Photo._parse(client, media.photo, media.ttl_seconds)
+ elif isinstance(media, raw.types.MessageMediaGeo):
+ location = types.Location._parse(client, media.geo)
+ elif isinstance(media, raw.types.MessageMediaContact):
+ contact = types.Contact._parse(client, media)
+ elif isinstance(media, raw.types.MessageMediaVenue):
+ venue = types.Venue._parse(client, media)
+ elif isinstance(media, raw.types.MessageMediaGame):
+ game = types.Game._parse(client, message)
+ elif isinstance(media, raw.types.MessageMediaDocument):
doc = media.document
- if isinstance(doc, types.Document):
+ if isinstance(doc, raw.types.Document):
attributes = {type(i): i for i in doc.attributes}
file_name = getattr(
attributes.get(
- types.DocumentAttributeFilename, None
+ raw.types.DocumentAttributeFilename, None
), "file_name", None
)
- if types.DocumentAttributeAudio in attributes:
- audio_attributes = attributes[types.DocumentAttributeAudio]
+ if raw.types.DocumentAttributeAudio in attributes:
+ audio_attributes = attributes[raw.types.DocumentAttributeAudio]
if audio_attributes.voice:
- voice = pyrogram.Voice._parse(client, doc, audio_attributes)
+ voice = types.Voice._parse(client, doc, audio_attributes)
else:
- audio = pyrogram.Audio._parse(client, doc, audio_attributes, file_name)
- elif types.DocumentAttributeAnimated in attributes:
- video_attributes = attributes.get(types.DocumentAttributeVideo, None)
+ audio = types.Audio._parse(client, doc, audio_attributes, file_name)
+ elif raw.types.DocumentAttributeAnimated in attributes:
+ video_attributes = attributes.get(raw.types.DocumentAttributeVideo, None)
- animation = pyrogram.Animation._parse(client, doc, video_attributes, file_name)
- elif types.DocumentAttributeVideo in attributes:
- video_attributes = attributes[types.DocumentAttributeVideo]
+ animation = types.Animation._parse(client, doc, video_attributes, file_name)
+ elif raw.types.DocumentAttributeVideo in attributes:
+ video_attributes = attributes[raw.types.DocumentAttributeVideo]
if video_attributes.round_message:
- video_note = pyrogram.VideoNote._parse(client, doc, video_attributes)
+ video_note = types.VideoNote._parse(client, doc, video_attributes)
else:
- video = pyrogram.Video._parse(client, doc, video_attributes, file_name,
- media.ttl_seconds)
- elif types.DocumentAttributeSticker in attributes:
- sticker = await pyrogram.Sticker._parse(
+ video = types.Video._parse(client, doc, video_attributes, file_name,
+ media.ttl_seconds)
+ elif raw.types.DocumentAttributeSticker in attributes:
+ sticker = await types.Sticker._parse(
client, doc,
- attributes.get(types.DocumentAttributeImageSize, None),
- attributes[types.DocumentAttributeSticker],
+ attributes.get(raw.types.DocumentAttributeImageSize, None),
+ attributes[raw.types.DocumentAttributeSticker],
file_name
)
else:
- document = pyrogram.Document._parse(client, doc, file_name)
- elif isinstance(media, types.MessageMediaWebPage):
- if isinstance(media.webpage, types.WebPage):
- web_page = pyrogram.WebPage._parse(client, media.webpage)
+ document = types.Document._parse(client, doc, file_name)
+ elif isinstance(media, raw.types.MessageMediaWebPage):
+ if isinstance(media.webpage, raw.types.WebPage):
+ web_page = types.WebPage._parse(client, media.webpage)
else:
media = None
- elif isinstance(media, types.MessageMediaPoll):
- poll = pyrogram.Poll._parse(client, media)
- elif isinstance(media, types.MessageMediaDice):
- dice = pyrogram.Dice._parse(client, media)
+ elif isinstance(media, raw.types.MessageMediaPoll):
+ poll = types.Poll._parse(client, media)
+ elif isinstance(media, raw.types.MessageMediaDice):
+ dice = types.Dice._parse(client, media)
else:
media = None
reply_markup = message.reply_markup
if reply_markup:
- if isinstance(reply_markup, types.ReplyKeyboardForceReply):
- reply_markup = pyrogram.ForceReply.read(reply_markup)
- elif isinstance(reply_markup, types.ReplyKeyboardMarkup):
- reply_markup = pyrogram.ReplyKeyboardMarkup.read(reply_markup)
- elif isinstance(reply_markup, types.ReplyInlineMarkup):
- reply_markup = pyrogram.InlineKeyboardMarkup.read(reply_markup)
- elif isinstance(reply_markup, types.ReplyKeyboardHide):
- reply_markup = pyrogram.ReplyKeyboardRemove.read(reply_markup)
+ if isinstance(reply_markup, raw.types.ReplyKeyboardForceReply):
+ reply_markup = types.ForceReply.read(reply_markup)
+ elif isinstance(reply_markup, raw.types.ReplyKeyboardMarkup):
+ reply_markup = types.ReplyKeyboardMarkup.read(reply_markup)
+ elif isinstance(reply_markup, raw.types.ReplyInlineMarkup):
+ reply_markup = types.InlineKeyboardMarkup.read(reply_markup)
+ elif isinstance(reply_markup, raw.types.ReplyKeyboardHide):
+ reply_markup = types.ReplyKeyboardRemove.read(reply_markup)
else:
reply_markup = None
parsed_message = Message(
message_id=message.id,
date=message.date,
- chat=Chat._parse(client, message, users, chats),
- from_user=User._parse(client, users.get(message.from_id, None)),
+ chat=types.Chat._parse(client, message, users, chats),
+ from_user=types.User._parse(client, users.get(message.from_id, None)),
text=(
Str(message.message).init(entities) or None
if media is None or web_page is not None
@@ -655,7 +655,7 @@ async def _parse(client, message: types.Message or types.MessageService or types
poll=poll,
dice=dice,
views=message.views,
- via_bot=User._parse(client, users.get(message.via_bot_id, None)),
+ via_bot=types.User._parse(client, users.get(message.via_bot_id, None)),
outgoing=message.out,
reply_markup=reply_markup,
client=client
@@ -676,9 +676,9 @@ async def _parse(client, message: types.Message or types.MessageService or types
@property
def link(self) -> str:
if self.chat.type in ("group", "supergroup", "channel") and self.chat.username:
- return "https://t.me/{}/{}".format(self.chat.username, self.message_id)
+ return f"https://t.me/{self.chat.username}/{self.message_id}"
else:
- return "https://t.me/c/{}/{}".format(utils.get_channel_id(self.chat.id), self.message_id)
+ return f"https://t.me/c/{utils.get_channel_id(self.chat.id)}/{self.message_id}"
async def reply_text(
self,
@@ -690,7 +690,7 @@ async def reply_text(
reply_to_message_id: int = None,
reply_markup=None
) -> "Message":
- """Bound method *reply_text* of :obj:`Message`.
+ """Bound method *reply_text* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -733,7 +733,7 @@ async def reply_text(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -774,16 +774,16 @@ async def reply_animation(
thumb: str = None,
disable_notification: bool = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
reply_to_message_id: int = None,
progress: callable = None,
progress_args: tuple = ()
) -> "Message":
- """Bound method *reply_animation* :obj:`Message`.
+ """Bound method *reply_animation* :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -847,7 +847,7 @@ async def reply_animation(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -874,8 +874,9 @@ async def reply_animation(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- On success, the sent :obj:`Message` is returned.
- In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead.
+ On success, the sent :obj:`~pyrogram.types.Message` is returned.
+ In case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned
+ instead.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -917,15 +918,15 @@ async def reply_audio(
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
progress: callable = None,
progress_args: tuple = ()
) -> "Message":
- """Bound method *reply_audio* of :obj:`Message`.
+ """Bound method *reply_audio* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -989,7 +990,7 @@ async def reply_audio(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -1016,8 +1017,9 @@ async def reply_audio(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- On success, the sent :obj:`Message` is returned.
- In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead.
+ On success, the sent :obj:`~pyrogram.types.Message` is returned.
+ In case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned
+ instead.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -1055,13 +1057,13 @@ async def reply_cached_media(
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None
) -> "Message":
- """Bound method *reply_cached_media* of :obj:`Message`.
+ """Bound method *reply_cached_media* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -1108,12 +1110,12 @@ async def reply_cached_media(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
Returns:
- On success, the sent :obj:`Message` is returned.
+ On success, the sent :obj:`~pyrogram.types.Message` is returned.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -1136,7 +1138,7 @@ async def reply_cached_media(
)
async def reply_chat_action(self, action: str) -> bool:
- """Bound method *reply_chat_action* of :obj:`Message`.
+ """Bound method *reply_chat_action* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -1183,13 +1185,13 @@ async def reply_contact(
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None
) -> "Message":
- """Bound method *reply_contact* of :obj:`Message`.
+ """Bound method *reply_contact* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -1231,12 +1233,12 @@ async def reply_contact(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
Returns:
- On success, the sent :obj:`Message` is returned.
+ On success, the sent :obj:`~pyrogram.types.Message` is returned.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -1269,15 +1271,15 @@ async def reply_document(
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
progress: callable = None,
progress_args: tuple = ()
) -> "Message":
- """Bound method *reply_document* of :obj:`Message`.
+ """Bound method *reply_document* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -1332,7 +1334,7 @@ async def reply_document(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -1359,8 +1361,9 @@ async def reply_document(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- On success, the sent :obj:`Message` is returned.
- In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead.
+ On success, the sent :obj:`~pyrogram.types.Message` is returned.
+ In case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned
+ instead.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -1392,13 +1395,13 @@ async def reply_game(
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None
) -> "Message":
- """Bound method *reply_game* of :obj:`Message`.
+ """Bound method *reply_game* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -1430,12 +1433,12 @@ async def reply_game(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An object for an inline keyboard. If empty, one ‘Play game_title’ button will be shown automatically.
If not empty, the first button must launch the game.
Returns:
- On success, the sent :obj:`Message` is returned.
+ On success, the sent :obj:`~pyrogram.types.Message` is returned.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -1463,7 +1466,7 @@ async def reply_inline_bot_result(
reply_to_message_id: int = None,
hide_via: bool = None
) -> "Message":
- """Bound method *reply_inline_bot_result* of :obj:`Message`.
+ """Bound method *reply_inline_bot_result* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -1531,13 +1534,13 @@ async def reply_location(
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None
) -> "Message":
- """Bound method *reply_location* of :obj:`Message`.
+ """Bound method *reply_location* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -1573,12 +1576,12 @@ async def reply_location(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
Returns:
- On success, the sent :obj:`Message` is returned.
+ On success, the sent :obj:`~pyrogram.types.Message` is returned.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -1600,12 +1603,12 @@ async def reply_location(
async def reply_media_group(
self,
- media: List[Union["pyrogram.InputMediaPhoto", "pyrogram.InputMediaVideo"]],
+ media: List[Union["types.InputMediaPhoto", "types.InputMediaVideo"]],
quote: bool = None,
disable_notification: bool = None,
reply_to_message_id: int = None
- ) -> "Message":
- """Bound method *reply_media_group* of :obj:`Message`.
+ ) -> List["types.Message"]:
+ """Bound method *reply_media_group* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -1623,8 +1626,8 @@ async def reply_media_group(
Parameters:
media (``list``):
- A list containing either :obj:`InputMediaPhoto ` or
- :obj:`InputMediaVideo ` objects
+ A list containing either :obj:`~pyrogram.types.InputMediaPhoto` or
+ :obj:`~pyrogram.types.InputMediaVideo` objects
describing photos and videos to be sent, must include 2–10 items.
quote (``bool``, *optional*):
@@ -1640,7 +1643,7 @@ async def reply_media_group(
If the message is a reply, ID of the original message.
Returns:
- On success, a :obj:`Messages` object is returned containing all the
+ On success, a :obj:`~pyrogram.types.Messages` object is returned containing all the
single messages sent.
Raises:
@@ -1670,15 +1673,15 @@ async def reply_photo(
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
progress: callable = None,
progress_args: tuple = ()
) -> "Message":
- """Bound method *reply_photo* of :obj:`Message`.
+ """Bound method *reply_photo* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -1732,7 +1735,7 @@ async def reply_photo(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -1759,8 +1762,9 @@ async def reply_photo(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- On success, the sent :obj:`Message` is returned.
- In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead.
+ On success, the sent :obj:`~pyrogram.types.Message` is returned.
+ In case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned
+ instead.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -1793,13 +1797,13 @@ async def reply_poll(
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None
) -> "Message":
- """Bound method *reply_poll* of :obj:`Message`.
+ """Bound method *reply_poll* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -1835,12 +1839,12 @@ async def reply_poll(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
Returns:
- On success, the sent :obj:`Message` is returned.
+ On success, the sent :obj:`~pyrogram.types.Message` is returned.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -1868,15 +1872,15 @@ async def reply_sticker(
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
progress: callable = None,
progress_args: tuple = ()
) -> "Message":
- """Bound method *reply_sticker* of :obj:`Message`.
+ """Bound method *reply_sticker* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -1915,7 +1919,7 @@ async def reply_sticker(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -1942,8 +1946,9 @@ async def reply_sticker(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- On success, the sent :obj:`Message` is returned.
- In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead.
+ On success, the sent :obj:`~pyrogram.types.Message` is returned.
+ In case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned
+ instead.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -1977,13 +1982,13 @@ async def reply_venue(
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None
) -> "Message":
- """Bound method *reply_venue* of :obj:`Message`.
+ """Bound method *reply_venue* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -2034,12 +2039,12 @@ async def reply_venue(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
Returns:
- On success, the sent :obj:`Message` is returned.
+ On success, the sent :obj:`~pyrogram.types.Message` is returned.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -2078,15 +2083,15 @@ async def reply_video(
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
progress: callable = None,
progress_args: tuple = ()
) -> "Message":
- """Bound method *reply_video* of :obj:`Message`.
+ """Bound method *reply_video* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -2153,7 +2158,7 @@ async def reply_video(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -2180,8 +2185,9 @@ async def reply_video(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- On success, the sent :obj:`Message` is returned.
- In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead.
+ On success, the sent :obj:`~pyrogram.types.Message` is returned.
+ In case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned
+ instead.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -2221,15 +2227,15 @@ async def reply_video_note(
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
progress: callable = None,
progress_args: tuple = ()
) -> "Message":
- """Bound method *reply_video_note* of :obj:`Message`.
+ """Bound method *reply_video_note* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -2280,7 +2286,7 @@ async def reply_video_note(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -2307,8 +2313,9 @@ async def reply_video_note(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- On success, the sent :obj:`Message` is returned.
- In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead.
+ On success, the sent :obj:`~pyrogram.types.Message` is returned.
+ In case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned
+ instead.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -2344,15 +2351,15 @@ async def reply_voice(
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
- "pyrogram.InlineKeyboardMarkup",
- "pyrogram.ReplyKeyboardMarkup",
- "pyrogram.ReplyKeyboardRemove",
- "pyrogram.ForceReply"
+ "types.InlineKeyboardMarkup",
+ "types.ReplyKeyboardMarkup",
+ "types.ReplyKeyboardRemove",
+ "types.ForceReply"
] = None,
progress: callable = None,
progress_args: tuple = ()
) -> "Message":
- """Bound method *reply_voice* of :obj:`Message`.
+ """Bound method *reply_voice* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -2404,7 +2411,7 @@ async def reply_voice(
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message
- reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
@@ -2431,8 +2438,9 @@ async def reply_voice(
You can either keep *\*args* or add every single extra argument in your function signature.
Returns:
- On success, the sent :obj:`Message` is returned.
- In case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned instead.
+ On success, the sent :obj:`~pyrogram.types.Message` is returned.
+ In case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned
+ instead.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -2462,9 +2470,9 @@ async def edit_text(
text: str,
parse_mode: Union[str, None] = object,
disable_web_page_preview: bool = None,
- reply_markup: "pyrogram.InlineKeyboardMarkup" = None
+ reply_markup: "types.InlineKeyboardMarkup" = None
) -> "Message":
- """Bound method *edit_text* of :obj:`Message`.
+ """Bound method *edit_text* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -2495,11 +2503,11 @@ async def edit_text(
disable_web_page_preview (``bool``, *optional*):
Disables link previews for links in this message.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
- On success, the edited :obj:`Message` is returned.
+ On success, the edited :obj:`~pyrogram.types.Message` is returned.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -2519,9 +2527,9 @@ async def edit_caption(
self,
caption: str,
parse_mode: Union[str, None] = object,
- reply_markup: "pyrogram.InlineKeyboardMarkup" = None
+ reply_markup: "types.InlineKeyboardMarkup" = None
) -> "Message":
- """Bound method *edit_caption* of :obj:`Message`.
+ """Bound method *edit_caption* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -2549,11 +2557,11 @@ async def edit_caption(
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
- On success, the edited :obj:`Message` is returned.
+ On success, the edited :obj:`~pyrogram.types.Message` is returned.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -2566,8 +2574,12 @@ async def edit_caption(
reply_markup=reply_markup
)
- async def edit_media(self, media: InputMedia, reply_markup: "pyrogram.InlineKeyboardMarkup" = None) -> "Message":
- """Bound method *edit_media* of :obj:`Message`.
+ async def edit_media(
+ self,
+ media: "types.InputMedia",
+ reply_markup: "types.InlineKeyboardMarkup" = None
+ ) -> "Message":
+ """Bound method *edit_media* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -2585,14 +2597,14 @@ async def edit_media(self, media: InputMedia, reply_markup: "pyrogram.InlineKeyb
message.edit_media(media)
Parameters:
- media (:obj:`InputMedia`):
+ media (:obj:`~pyrogram.types.InputMedia`):
One of the InputMedia objects describing an animation, audio, document, photo or video.
- reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
- On success, the edited :obj:`Message` is returned.
+ On success, the edited :obj:`~pyrogram.types.Message` is returned.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -2604,8 +2616,8 @@ async def edit_media(self, media: InputMedia, reply_markup: "pyrogram.InlineKeyb
reply_markup=reply_markup
)
- async def edit_reply_markup(self, reply_markup: "pyrogram.InlineKeyboardMarkup" = None) -> "Message":
- """Bound method *edit_reply_markup* of :obj:`Message`.
+ async def edit_reply_markup(self, reply_markup: "types.InlineKeyboardMarkup" = None) -> "Message":
+ """Bound method *edit_reply_markup* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -2623,12 +2635,12 @@ async def edit_reply_markup(self, reply_markup: "pyrogram.InlineKeyboardMarkup"
message.edit_reply_markup(inline_reply_markup)
Parameters:
- reply_markup (:obj:`InlineKeyboardMarkup`):
+ reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`):
An InlineKeyboardMarkup object.
Returns:
On success, if edited message is sent by the bot, the edited
- :obj:`Message` is returned, otherwise True is returned.
+ :obj:`~pyrogram.types.Message` is returned, otherwise True is returned.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -2646,8 +2658,8 @@ async def forward(
as_copy: bool = False,
remove_caption: bool = False,
schedule_date: int = None
- ) -> "Message":
- """Bound method *forward* of :obj:`Message`.
+ ) -> Union["types.Message", List["types.Message"]]:
+ """Bound method *forward* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -2696,7 +2708,7 @@ async def forward(
if self.service:
raise ValueError("Unable to copy service messages")
- if self.game and not self._client.is_bot:
+ if self.game and not await self._client.storage.is_bot():
raise ValueError("Users cannot send messages with Game media type")
if self.text:
@@ -2805,7 +2817,7 @@ async def forward(
)
async def delete(self, revoke: bool = True):
- """Bound method *delete* of :obj:`Message`.
+ """Bound method *delete* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -2841,7 +2853,7 @@ async def delete(self, revoke: bool = True):
)
async def click(self, x: int or str = 0, y: int = None, quote: bool = None, timeout: int = 10):
- """Bound method *click* of :obj:`Message`.
+ """Bound method *click* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for clicking a button attached to the message instead of:
@@ -2893,7 +2905,7 @@ async def click(self, x: int or str = 0, y: int = None, quote: bool = None, time
Timeout in seconds.
Returns:
- - The result of :meth:`~Client.request_callback_answer` in case of inline callback button clicks.
+ - The result of :meth:`~pyrogram.Client.request_callback_answer` in case of inline callback button clicks.
- The result of :meth:`~Message.reply()` in case of normal button clicks.
- A string in case the inline button is a URL, a *switch_inline_query* or a
*switch_inline_query_current_chat* button.
@@ -2904,10 +2916,10 @@ async def click(self, x: int or str = 0, y: int = None, quote: bool = None, time
TimeoutError: In case, after clicking an inline button, the bot fails to answer within the timeout.
"""
- if isinstance(self.reply_markup, pyrogram.ReplyKeyboardMarkup):
+ if isinstance(self.reply_markup, types.ReplyKeyboardMarkup):
keyboard = self.reply_markup.keyboard
is_inline = False
- elif isinstance(self.reply_markup, pyrogram.InlineKeyboardMarkup):
+ elif isinstance(self.reply_markup, types.InlineKeyboardMarkup):
keyboard = self.reply_markup.inline_keyboard
is_inline = True
else:
@@ -2921,12 +2933,12 @@ async def click(self, x: int or str = 0, y: int = None, quote: bool = None, time
for button in row
][x]
except IndexError:
- raise ValueError("The button at index {} doesn't exist".format(x))
+ raise ValueError(f"The button at index {x} doesn't exist")
elif isinstance(x, int) and isinstance(y, int):
try:
button = keyboard[y][x]
except IndexError:
- raise ValueError("The button at position ({}, {}) doesn't exist".format(x, y))
+ raise ValueError(f"The button at position ({x}, {y}) doesn't exist")
elif isinstance(x, str) and y is None:
label = x.encode("utf-16", "surrogatepass").decode("utf-16")
@@ -2938,7 +2950,7 @@ async def click(self, x: int or str = 0, y: int = None, quote: bool = None, time
if label == button.text
][0]
except IndexError:
- raise ValueError("The button with label '{}' doesn't exists".format(x))
+ raise ValueError(f"The button with label '{x}' doesn't exists")
else:
raise ValueError("Invalid arguments")
@@ -2963,8 +2975,8 @@ async def click(self, x: int or str = 0, y: int = None, quote: bool = None, time
async def retract_vote(
self,
- ) -> "pyrogram.Poll":
- """Bound method *retract_vote* of :obj:`Message`.
+ ) -> "types.Poll":
+ """Bound method *retract_vote* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -2981,7 +2993,7 @@ async def retract_vote(
message.retract_vote()
Returns:
- :obj:`Poll`: On success, the poll with the retracted vote is returned.
+ :obj:`~pyrogram.types.Poll`: On success, the poll with the retracted vote is returned.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -2999,7 +3011,7 @@ async def download(
progress: callable = None,
progress_args: tuple = ()
) -> str:
- """Bound method *download* of :obj:`Message`.
+ """Bound method *download* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -3063,8 +3075,8 @@ async def download(
async def vote(
self,
option: int,
- ) -> "pyrogram.Poll":
- """Bound method *vote* of :obj:`Message`.
+ ) -> "types.Poll":
+ """Bound method *vote* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
@@ -3086,7 +3098,7 @@ async def vote(
Index of the poll option you want to vote for (0 to 9).
Returns:
- :obj:`Poll`: On success, the poll with the chosen option is returned.
+ :obj:`~pyrogram.types.Poll`: On success, the poll with the chosen option is returned.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -3095,11 +3107,11 @@ async def vote(
return await self._client.vote_poll(
chat_id=self.chat.id,
message_id=self.message_id,
- option=option
+ options=option
)
- async def pin(self, disable_notification: bool = None) -> "Message":
- """Bound method *pin* of :obj:`Message`.
+ async def pin(self, disable_notification: bool = None) -> bool:
+ """Bound method *pin* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for:
diff --git a/pyrogram/client/types/messages_and_media/message_entity.py b/pyrogram/types/messages_and_media/message_entity.py
similarity index 68%
rename from pyrogram/client/types/messages_and_media/message_entity.py
rename to pyrogram/types/messages_and_media/message_entity.py
index a1e39a0f62..a88a91c859 100644
--- a/pyrogram/client/types/messages_and_media/message_entity.py
+++ b/pyrogram/types/messages_and_media/message_entity.py
@@ -17,10 +17,9 @@
# along with Pyrogram. If not, see .
import pyrogram
-
-from pyrogram.api import types
+from pyrogram import raw
+from pyrogram import types
from ..object import Object
-from ..user_and_chats.user import User
class MessageEntity(Object):
@@ -43,38 +42,38 @@ class MessageEntity(Object):
url (``str``, *optional*):
For "text_link" only, url that will be opened after user taps on the text.
- user (:obj:`User`, *optional*):
+ user (:obj:`~pyrogram.types.User`, *optional*):
For "text_mention" only, the mentioned user.
"""
ENTITIES = {
- types.MessageEntityMention.ID: "mention",
- types.MessageEntityHashtag.ID: "hashtag",
- types.MessageEntityCashtag.ID: "cashtag",
- types.MessageEntityBotCommand.ID: "bot_command",
- types.MessageEntityUrl.ID: "url",
- types.MessageEntityEmail.ID: "email",
- types.MessageEntityBold.ID: "bold",
- types.MessageEntityItalic.ID: "italic",
- types.MessageEntityCode.ID: "code",
- types.MessageEntityPre.ID: "pre",
- types.MessageEntityUnderline.ID: "underline",
- types.MessageEntityStrike.ID: "strike",
- types.MessageEntityBlockquote.ID: "blockquote",
- types.MessageEntityTextUrl.ID: "text_link",
- types.MessageEntityMentionName.ID: "text_mention",
- types.MessageEntityPhone.ID: "phone_number"
+ raw.types.MessageEntityMention.ID: "mention",
+ raw.types.MessageEntityHashtag.ID: "hashtag",
+ raw.types.MessageEntityCashtag.ID: "cashtag",
+ raw.types.MessageEntityBotCommand.ID: "bot_command",
+ raw.types.MessageEntityUrl.ID: "url",
+ raw.types.MessageEntityEmail.ID: "email",
+ raw.types.MessageEntityBold.ID: "bold",
+ raw.types.MessageEntityItalic.ID: "italic",
+ raw.types.MessageEntityCode.ID: "code",
+ raw.types.MessageEntityPre.ID: "pre",
+ raw.types.MessageEntityUnderline.ID: "underline",
+ raw.types.MessageEntityStrike.ID: "strike",
+ raw.types.MessageEntityBlockquote.ID: "blockquote",
+ raw.types.MessageEntityTextUrl.ID: "text_link",
+ raw.types.MessageEntityMentionName.ID: "text_mention",
+ raw.types.MessageEntityPhone.ID: "phone_number"
}
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
type: str,
offset: int,
length: int,
url: str = None,
- user: User = None
+ user: "types.User" = None
):
super().__init__(client)
@@ -96,6 +95,6 @@ def _parse(client, entity, users: dict) -> "MessageEntity" or None:
offset=entity.offset,
length=entity.length,
url=getattr(entity, "url", None),
- user=User._parse(client, users.get(getattr(entity, "user_id", None), None)),
+ user=types.User._parse(client, users.get(getattr(entity, "user_id", None), None)),
client=client
)
diff --git a/pyrogram/client/types/messages_and_media/photo.py b/pyrogram/types/messages_and_media/photo.py
similarity index 82%
rename from pyrogram/client/types/messages_and_media/photo.py
rename to pyrogram/types/messages_and_media/photo.py
index fe0678aba3..a6f572d43b 100644
--- a/pyrogram/client/types/messages_and_media/photo.py
+++ b/pyrogram/types/messages_and_media/photo.py
@@ -20,10 +20,10 @@
from typing import List
import pyrogram
-from pyrogram.api import types
-from .thumbnail import Thumbnail
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.utils import encode_file_id, encode_file_ref
from ..object import Object
-from ...ext.utils import encode_file_id, encode_file_ref
class Photo(Object):
@@ -51,14 +51,14 @@ class Photo(Object):
ttl_seconds (``int``, *optional*):
Time-to-live seconds, for secret photos.
- thumbs (List of :obj:`Thumbnail`, *optional*):
+ thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*):
Available thumbnails of this photo.
"""
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
width: int,
@@ -66,7 +66,7 @@ def __init__(
file_size: int,
date: int,
ttl_seconds: int = None,
- thumbs: List[Thumbnail] = None
+ thumbs: List["types.Thumbnail"] = None
):
super().__init__(client)
@@ -80,9 +80,9 @@ def __init__(
self.thumbs = thumbs
@staticmethod
- def _parse(client, photo: types.Photo, ttl_seconds: int = None) -> "Photo":
- if isinstance(photo, types.Photo):
- big = list(filter(lambda p: isinstance(p, types.PhotoSize), photo.sizes))[-1]
+ def _parse(client, photo: "raw.types.Photo", ttl_seconds: int = None) -> "Photo":
+ if isinstance(photo, raw.types.Photo):
+ big = list(filter(lambda p: isinstance(p, raw.types.PhotoSize), photo.sizes))[-1]
return Photo(
file_id=encode_file_id(
@@ -99,6 +99,6 @@ def _parse(client, photo: types.Photo, ttl_seconds: int = None) -> "Photo":
file_size=big.size,
date=photo.date,
ttl_seconds=ttl_seconds,
- thumbs=Thumbnail._parse(client, photo),
+ thumbs=types.Thumbnail._parse(client, photo),
client=client
)
diff --git a/pyrogram/client/types/messages_and_media/poll.py b/pyrogram/types/messages_and_media/poll.py
similarity index 88%
rename from pyrogram/client/types/messages_and_media/poll.py
rename to pyrogram/types/messages_and_media/poll.py
index d1dd2b219c..459c24bb3f 100644
--- a/pyrogram/client/types/messages_and_media/poll.py
+++ b/pyrogram/types/messages_and_media/poll.py
@@ -19,8 +19,8 @@
from typing import List, Union
import pyrogram
-from pyrogram.api import types
-from .poll_option import PollOption
+from pyrogram import raw
+from pyrogram import types
from ..object import Object
from ..update import Update
@@ -35,7 +35,7 @@ class Poll(Object, Update):
question (``str``):
Poll question, 1-255 characters.
- options (List of :obj:`PollOption`):
+ options (List of :obj:`~pyrogram.types.PollOption`):
List of poll options.
total_voter_count (``int``):
@@ -60,10 +60,10 @@ class Poll(Object, Update):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
id: str,
question: str,
- options: List[PollOption],
+ options: List["types.PollOption"],
total_voter_count: int,
is_closed: bool,
is_anonymous: bool = None,
@@ -86,9 +86,9 @@ def __init__(
self.chosen_option = chosen_option
@staticmethod
- def _parse(client, media_poll: Union[types.MessageMediaPoll, types.UpdateMessagePoll]) -> "Poll":
- poll = media_poll.poll # type: types.Poll
- results = media_poll.results.results # type: types.PollResults
+ def _parse(client, media_poll: Union["raw.types.MessageMediaPoll", "raw.types.UpdateMessagePoll"]) -> "Poll":
+ poll = media_poll.poll # type: raw.types.Poll
+ results = media_poll.results.results
chosen_option = None
options = []
@@ -103,7 +103,7 @@ def _parse(client, media_poll: Union[types.MessageMediaPoll, types.UpdateMessage
chosen_option = i
options.append(
- PollOption(
+ types.PollOption(
text=answer.text,
voter_count=voter_count,
data=answer.option,
@@ -125,7 +125,7 @@ def _parse(client, media_poll: Union[types.MessageMediaPoll, types.UpdateMessage
)
@staticmethod
- def _parse_update(client, update: types.UpdateMessagePoll):
+ def _parse_update(client, update: "raw.types.UpdateMessagePoll"):
if update.poll is not None:
return Poll._parse(client, update)
@@ -138,7 +138,7 @@ def _parse_update(client, update: types.UpdateMessagePoll):
chosen_option = i
options.append(
- PollOption(
+ types.PollOption(
text="",
voter_count=result.voters,
data=result.option,
diff --git a/pyrogram/client/types/messages_and_media/poll_option.py b/pyrogram/types/messages_and_media/poll_option.py
similarity index 96%
rename from pyrogram/client/types/messages_and_media/poll_option.py
rename to pyrogram/types/messages_and_media/poll_option.py
index da7daff327..93fda559ad 100644
--- a/pyrogram/client/types/messages_and_media/poll_option.py
+++ b/pyrogram/types/messages_and_media/poll_option.py
@@ -38,7 +38,7 @@ class PollOption(Object):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
text: str,
voter_count: int,
data: bytes
diff --git a/pyrogram/client/types/messages_and_media/sticker.py b/pyrogram/types/messages_and_media/sticker.py
similarity index 84%
rename from pyrogram/client/types/messages_and_media/sticker.py
rename to pyrogram/types/messages_and_media/sticker.py
index aca7d3a31b..76e7264fda 100644
--- a/pyrogram/client/types/messages_and_media/sticker.py
+++ b/pyrogram/types/messages_and_media/sticker.py
@@ -22,11 +22,11 @@
from async_lru import alru_cache
import pyrogram
-from pyrogram.api import types, functions
+from pyrogram import raw
+from pyrogram import types
from pyrogram.errors import StickersetInvalid
-from .thumbnail import Thumbnail
+from pyrogram.utils import encode_file_id, encode_file_ref
from ..object import Object
-from ...ext.utils import encode_file_id, encode_file_ref
class Sticker(Object):
@@ -66,7 +66,7 @@ class Sticker(Object):
set_name (``str``, *optional*):
Name of the sticker set to which the sticker belongs.
- thumbs (List of :obj:`Thumbnail`, *optional*):
+ thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*):
Sticker thumbnails in the .webp or .jpg format.
"""
@@ -75,7 +75,7 @@ class Sticker(Object):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
width: int,
@@ -87,7 +87,7 @@ def __init__(
date: int = None,
emoji: str = None,
set_name: str = None,
- thumbs: List[Thumbnail] = None
+ thumbs: List["types.Thumbnail"] = None
):
super().__init__(client)
@@ -110,8 +110,8 @@ def __init__(
async def _get_sticker_set_name(send, input_sticker_set_id):
try:
return (await send(
- functions.messages.GetStickerSet(
- stickerset=types.InputStickerSetID(
+ raw.functions.messages.GetStickerSet(
+ stickerset=raw.types.InputStickerSetID(
id=input_sticker_set_id[0],
access_hash=input_sticker_set_id[1]
)
@@ -121,11 +121,16 @@ async def _get_sticker_set_name(send, input_sticker_set_id):
return None
@staticmethod
- async def _parse(client, sticker: types.Document, image_size_attributes: types.DocumentAttributeImageSize,
- sticker_attributes: types.DocumentAttributeSticker, file_name: str) -> "Sticker":
+ async def _parse(
+ client,
+ sticker: "raw.types.Document",
+ image_size_attributes: "raw.types.DocumentAttributeImageSize",
+ sticker_attributes: "raw.types.DocumentAttributeSticker",
+ file_name: str
+ ) -> "Sticker":
sticker_set = sticker_attributes.stickerset
- if isinstance(sticker_set, types.InputStickerSetID):
+ if isinstance(sticker_set, raw.types.InputStickerSetID):
input_sticker_set_id = (sticker_set.id, sticker_set.access_hash)
set_name = await Sticker._get_sticker_set_name(client.send, input_sticker_set_id)
else:
@@ -152,6 +157,6 @@ async def _parse(client, sticker: types.Document, image_size_attributes: types.D
mime_type=sticker.mime_type,
file_name=file_name,
date=sticker.date,
- thumbs=Thumbnail._parse(client, sticker),
+ thumbs=types.Thumbnail._parse(client, sticker),
client=client
)
diff --git a/pyrogram/client/types/messages_and_media/stripped_thumbnail.py b/pyrogram/types/messages_and_media/stripped_thumbnail.py
similarity index 88%
rename from pyrogram/client/types/messages_and_media/stripped_thumbnail.py
rename to pyrogram/types/messages_and_media/stripped_thumbnail.py
index 546f9a486a..8f22dd80f7 100644
--- a/pyrogram/client/types/messages_and_media/stripped_thumbnail.py
+++ b/pyrogram/types/messages_and_media/stripped_thumbnail.py
@@ -17,7 +17,7 @@
# along with Pyrogram. If not, see .
import pyrogram
-from pyrogram.api import types
+from pyrogram import raw
from ..object import Object
@@ -32,7 +32,7 @@ class StrippedThumbnail(Object):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
data: bytes
):
super().__init__(client)
@@ -40,7 +40,7 @@ def __init__(
self.data = data
@staticmethod
- def _parse(client, stripped_thumbnail: types.PhotoStrippedSize) -> "StrippedThumbnail":
+ def _parse(client, stripped_thumbnail: "raw.types.PhotoStrippedSize") -> "StrippedThumbnail":
return StrippedThumbnail(
data=stripped_thumbnail.bytes,
client=client
diff --git a/pyrogram/client/types/messages_and_media/thumbnail.py b/pyrogram/types/messages_and_media/thumbnail.py
similarity index 86%
rename from pyrogram/client/types/messages_and_media/thumbnail.py
rename to pyrogram/types/messages_and_media/thumbnail.py
index c48b8fb572..cd9eeb5914 100644
--- a/pyrogram/client/types/messages_and_media/thumbnail.py
+++ b/pyrogram/types/messages_and_media/thumbnail.py
@@ -20,9 +20,9 @@
from typing import Union, List
import pyrogram
-from pyrogram.api import types
-from pyrogram.client.ext.utils import encode_file_id
-from .stripped_thumbnail import StrippedThumbnail
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.utils import encode_file_id
from ..object import Object
@@ -46,7 +46,7 @@ class Thumbnail(Object):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
file_id: str,
width: int,
height: int,
@@ -62,12 +62,12 @@ def __init__(
@staticmethod
def _parse(
client,
- media: Union[types.Photo, types.Document]
- ) -> Union[List[Union[StrippedThumbnail, "Thumbnail"]], None]:
- if isinstance(media, types.Photo):
+ media: Union["raw.types.Photo", "raw.types.Document"]
+ ) -> Union[List[Union["types.StrippedThumbnail", "Thumbnail"]], None]:
+ if isinstance(media, raw.types.Photo):
raw_thumbnails = media.sizes[:-1]
media_type = 2
- elif isinstance(media, types.Document):
+ elif isinstance(media, raw.types.Document):
raw_thumbnails = media.thumbs
media_type = 14
@@ -82,7 +82,7 @@ def _parse(
# TODO: Enable this
# if isinstance(thumbnail, types.PhotoStrippedSize):
# thumbnails.append(StrippedThumbnail._parse(client, thumbnail))
- if isinstance(thumbnail, types.PhotoSize):
+ if isinstance(thumbnail, raw.types.PhotoSize):
thumbnails.append(
Thumbnail(
file_id=encode_file_id(
diff --git a/pyrogram/client/types/messages_and_media/venue.py b/pyrogram/types/messages_and_media/venue.py
similarity index 86%
rename from pyrogram/client/types/messages_and_media/venue.py
rename to pyrogram/types/messages_and_media/venue.py
index a638bd4cdc..05f3e33e53 100644
--- a/pyrogram/client/types/messages_and_media/venue.py
+++ b/pyrogram/types/messages_and_media/venue.py
@@ -17,8 +17,8 @@
# along with Pyrogram. If not, see .
import pyrogram
-from pyrogram.api import types
-from .location import Location
+from pyrogram import raw
+from pyrogram import types
from ..object import Object
@@ -26,7 +26,7 @@ class Venue(Object):
"""A venue.
Parameters:
- location (:obj:`Location`):
+ location (:obj:`~pyrogram.types.Location`):
Venue location.
title (``str``):
@@ -47,8 +47,8 @@ class Venue(Object):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
- location: Location,
+ client: "pyrogram.Client" = None,
+ location: "types.Location",
title: str,
address: str,
foursquare_id: str = None,
@@ -63,9 +63,9 @@ def __init__(
self.foursquare_type = foursquare_type
@staticmethod
- def _parse(client, venue: types.MessageMediaVenue):
+ def _parse(client, venue: "raw.types.MessageMediaVenue"):
return Venue(
- location=Location._parse(client, venue.geo),
+ location=types.Location._parse(client, venue.geo),
title=venue.title,
address=venue.address,
foursquare_id=venue.venue_id or None,
diff --git a/pyrogram/client/types/messages_and_media/video.py b/pyrogram/types/messages_and_media/video.py
similarity index 89%
rename from pyrogram/client/types/messages_and_media/video.py
rename to pyrogram/types/messages_and_media/video.py
index 16388b181c..182ef94efa 100644
--- a/pyrogram/client/types/messages_and_media/video.py
+++ b/pyrogram/types/messages_and_media/video.py
@@ -20,10 +20,10 @@
from typing import List
import pyrogram
-from pyrogram.api import types
-from .thumbnail import Thumbnail
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.utils import encode_file_id, encode_file_ref
from ..object import Object
-from ...ext.utils import encode_file_id, encode_file_ref
class Video(Object):
@@ -63,14 +63,14 @@ class Video(Object):
ttl_seconds (``int``. *optional*):
Time-to-live seconds, for secret photos.
- thumbs (List of :obj:`Thumbnail`, *optional*):
+ thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*):
Video thumbnails.
"""
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
width: int,
@@ -82,7 +82,7 @@ def __init__(
file_size: int = None,
date: int = None,
ttl_seconds: int = None,
- thumbs: List[Thumbnail] = None
+ thumbs: List["types.Thumbnail"] = None
):
super().__init__(client)
@@ -102,8 +102,8 @@ def __init__(
@staticmethod
def _parse(
client,
- video: types.Document,
- video_attributes: types.DocumentAttributeVideo,
+ video: "raw.types.Document",
+ video_attributes: "raw.types.DocumentAttributeVideo",
file_name: str,
ttl_seconds: int = None
) -> "Video":
@@ -127,6 +127,6 @@ def _parse(
file_size=video.size,
date=video.date,
ttl_seconds=ttl_seconds,
- thumbs=Thumbnail._parse(client, video),
+ thumbs=types.Thumbnail._parse(client, video),
client=client
)
diff --git a/pyrogram/client/types/messages_and_media/video_note.py b/pyrogram/types/messages_and_media/video_note.py
similarity index 84%
rename from pyrogram/client/types/messages_and_media/video_note.py
rename to pyrogram/types/messages_and_media/video_note.py
index 1feb5a2d06..e12117eb68 100644
--- a/pyrogram/client/types/messages_and_media/video_note.py
+++ b/pyrogram/types/messages_and_media/video_note.py
@@ -20,10 +20,10 @@
from typing import List
import pyrogram
-from pyrogram.api import types
-from .thumbnail import Thumbnail
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.utils import encode_file_id, encode_file_ref
from ..object import Object
-from ...ext.utils import encode_file_id, encode_file_ref
class VideoNote(Object):
@@ -51,19 +51,19 @@ class VideoNote(Object):
date (``int``, *optional*):
Date the video note was sent in Unix time.
- thumbs (List of :obj:`Thumbnail`, *optional*):
+ thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*):
Video thumbnails.
"""
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
length: int,
duration: int,
- thumbs: List[Thumbnail] = None,
+ thumbs: List["types.Thumbnail"] = None,
mime_type: str = None,
file_size: int = None,
date: int = None
@@ -80,7 +80,11 @@ def __init__(
self.thumbs = thumbs
@staticmethod
- def _parse(client, video_note: types.Document, video_attributes: types.DocumentAttributeVideo) -> "VideoNote":
+ def _parse(
+ client,
+ video_note: "raw.types.Document",
+ video_attributes: "raw.types.DocumentAttributeVideo"
+ ) -> "VideoNote":
return VideoNote(
file_id=encode_file_id(
pack(
@@ -97,6 +101,6 @@ def _parse(client, video_note: types.Document, video_attributes: types.DocumentA
file_size=video_note.size,
mime_type=video_note.mime_type,
date=video_note.date,
- thumbs=Thumbnail._parse(client, video_note),
+ thumbs=types.Thumbnail._parse(client, video_note),
client=client
)
diff --git a/pyrogram/client/types/messages_and_media/voice.py b/pyrogram/types/messages_and_media/voice.py
similarity index 91%
rename from pyrogram/client/types/messages_and_media/voice.py
rename to pyrogram/types/messages_and_media/voice.py
index dec82af9a3..987d233f64 100644
--- a/pyrogram/client/types/messages_and_media/voice.py
+++ b/pyrogram/types/messages_and_media/voice.py
@@ -19,9 +19,9 @@
from struct import pack
import pyrogram
-from pyrogram.api import types
+from pyrogram import raw
+from pyrogram.utils import encode_file_id, encode_file_ref
from ..object import Object
-from ...ext.utils import encode_file_id, encode_file_ref
class Voice(Object):
@@ -53,7 +53,7 @@ class Voice(Object):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
duration: int,
@@ -73,7 +73,7 @@ def __init__(
self.date = date
@staticmethod
- def _parse(client, voice: types.Document, attributes: types.DocumentAttributeAudio) -> "Voice":
+ def _parse(client, voice: "raw.types.Document", attributes: "raw.types.DocumentAttributeAudio") -> "Voice":
return Voice(
file_id=encode_file_id(
pack(
diff --git a/pyrogram/client/types/messages_and_media/webpage.py b/pyrogram/types/messages_and_media/webpage.py
similarity index 73%
rename from pyrogram/client/types/messages_and_media/webpage.py
rename to pyrogram/types/messages_and_media/webpage.py
index ebebfc1c87..edd94934c1 100644
--- a/pyrogram/client/types/messages_and_media/webpage.py
+++ b/pyrogram/types/messages_and_media/webpage.py
@@ -17,7 +17,8 @@
# along with Pyrogram. If not, see .
import pyrogram
-from pyrogram.api import types
+from pyrogram import raw
+from pyrogram import types
from ..object import Object
@@ -49,19 +50,19 @@ class WebPage(Object):
description (``str``, *optional*):
Description of this webpage.
- audio (:obj:`Audio`, *optional*):
+ audio (:obj:`~pyrogram.types.Audio`, *optional*):
Webpage preview is an audio file, information about the file.
- document (:obj:`Document`, *optional*):
+ document (:obj:`~pyrogram.types.Document`, *optional*):
Webpage preview is a general file, information about the file.
- photo (:obj:`Photo`, *optional*):
+ photo (:obj:`~pyrogram.types.Photo`, *optional*):
Webpage preview is a photo, information about the photo.
- animation (:obj:`Animation`, *optional*):
+ animation (:obj:`~pyrogram.types.Animation`, *optional*):
Webpage preview is an animation, information about the animation.
- video (:obj:`Video`, *optional*):
+ video (:obj:`~pyrogram.types.Video`, *optional*):
Webpage preview is a video, information about the video.
embed_url (``str``, *optional*):
@@ -86,7 +87,7 @@ class WebPage(Object):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
id: str,
url: str,
display_url: str,
@@ -94,11 +95,11 @@ def __init__(
site_name: str = None,
title: str = None,
description: str = None,
- audio: "pyrogram.Audio" = None,
- document: "pyrogram.Document" = None,
- photo: "pyrogram.Photo" = None,
- animation: "pyrogram.Animation" = None,
- video: "pyrogram.Video" = None,
+ audio: "types.Audio" = None,
+ document: "types.Document" = None,
+ photo: "types.Photo" = None,
+ animation: "types.Animation" = None,
+ video: "types.Video" = None,
embed_url: str = None,
embed_type: str = None,
embed_width: int = None,
@@ -128,41 +129,41 @@ def __init__(
self.author = author
@staticmethod
- def _parse(client, webpage: types.WebPage) -> "WebPage":
+ def _parse(client, webpage: "raw.types.WebPage") -> "WebPage":
audio = None
document = None
photo = None
animation = None
video = None
- if isinstance(webpage.photo, types.Photo):
- photo = pyrogram.Photo._parse(client, webpage.photo)
+ if isinstance(webpage.photo, raw.types.Photo):
+ photo = types.Photo._parse(client, webpage.photo)
doc = webpage.document
- if isinstance(doc, types.Document):
+ if isinstance(doc, raw.types.Document):
attributes = {type(i): i for i in doc.attributes}
file_name = getattr(
attributes.get(
- types.DocumentAttributeFilename, None
+ raw.types.DocumentAttributeFilename, None
), "file_name", None
)
- if types.DocumentAttributeAudio in attributes:
- audio_attributes = attributes[types.DocumentAttributeAudio]
- audio = pyrogram.Audio._parse(client, doc, audio_attributes, file_name)
+ if raw.types.DocumentAttributeAudio in attributes:
+ audio_attributes = attributes[raw.types.DocumentAttributeAudio]
+ audio = types.Audio._parse(client, doc, audio_attributes, file_name)
- elif types.DocumentAttributeAnimated in attributes:
- video_attributes = attributes.get(types.DocumentAttributeVideo, None)
- animation = pyrogram.Animation._parse(client, doc, video_attributes, file_name)
+ elif raw.types.DocumentAttributeAnimated in attributes:
+ video_attributes = attributes.get(raw.types.DocumentAttributeVideo, None)
+ animation = types.Animation._parse(client, doc, video_attributes, file_name)
- elif types.DocumentAttributeVideo in attributes:
- video_attributes = attributes[types.DocumentAttributeVideo]
- video = pyrogram.Video._parse(client, doc, video_attributes, file_name)
+ elif raw.types.DocumentAttributeVideo in attributes:
+ video_attributes = attributes[raw.types.DocumentAttributeVideo]
+ video = types.Video._parse(client, doc, video_attributes, file_name)
else:
- document = pyrogram.Document._parse(client, doc, file_name)
+ document = types.Document._parse(client, doc, file_name)
return WebPage(
id=str(webpage.id),
diff --git a/pyrogram/client/types/object.py b/pyrogram/types/object.py
similarity index 77%
rename from pyrogram/client/types/object.py
rename to pyrogram/types/object.py
index 750e0be765..887b8e08a9 100644
--- a/pyrogram/client/types/object.py
+++ b/pyrogram/types/object.py
@@ -17,7 +17,6 @@
# along with Pyrogram. If not, see .
import typing
-from collections import OrderedDict
from datetime import datetime
from json import dumps
@@ -26,18 +25,18 @@
class Meta(type, metaclass=type("", (type,), {"__str__": lambda _: "~hi"})):
def __str__(self):
- return "".format(self.__name__)
+ return f""
class Object(metaclass=Meta):
- def __init__(self, client: "pyrogram.BaseClient" = None):
+ def __init__(self, client: "pyrogram.Client" = None):
self._client = client
- def bind(self, client: "pyrogram.BaseClient"):
+ def bind(self, client: "pyrogram.Client"):
"""Bind a Client instance to this Pyrogram Object
Parameters:
- client (:obj:`Client`):
+ client (:obj:`~pyrogram.types.Client`):
The Client instance to bind this object with. Useful to re-enable bound methods after serializing and
deserializing Pyrogram objects with ``repr`` and ``eval``.
"""
@@ -53,27 +52,29 @@ def default(obj: "Object"):
if isinstance(obj, typing.Match):
return repr(obj)
- return OrderedDict(
- [("_", "pyrogram." + obj.__class__.__name__)]
- + [
- (attr, "*" * len(getattr(obj, attr)))
- if attr == "phone_number"
- else (attr, str(datetime.fromtimestamp(getattr(obj, attr))))
- if attr.endswith("date")
- else (attr, getattr(obj, attr))
+ return {
+ "_": obj.__class__.__name__,
+ **{
+ attr: (
+ "*" * len(getattr(obj, attr))
+ if attr == "phone_number" else
+ str(datetime.fromtimestamp(getattr(obj, attr)))
+ if attr.endswith("date") else
+ getattr(obj, attr)
+ )
for attr in filter(lambda x: not x.startswith("_"), obj.__dict__)
if getattr(obj, attr) is not None
- ]
- )
+ }
+ }
def __str__(self) -> str:
return dumps(self, indent=4, default=Object.default, ensure_ascii=False)
def __repr__(self) -> str:
- return "pyrogram.{}({})".format(
+ return "pyrogram.types.{}({})".format(
self.__class__.__name__,
", ".join(
- "{}={}".format(attr, repr(getattr(self, attr)))
+ f"{attr}={repr(getattr(self, attr))}"
for attr in filter(lambda x: not x.startswith("_"), self.__dict__)
if getattr(self, attr) is not None
)
diff --git a/pyrogram/client/types/update.py b/pyrogram/types/update.py
similarity index 83%
rename from pyrogram/client/types/update.py
rename to pyrogram/types/update.py
index 3f70f58007..7231a92b04 100644
--- a/pyrogram/client/types/update.py
+++ b/pyrogram/types/update.py
@@ -16,17 +16,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-class StopPropagation(StopAsyncIteration):
- pass
-
-
-class ContinuePropagation(StopAsyncIteration):
- pass
+import pyrogram
class Update:
def stop_propagation(self):
- raise StopPropagation
+ raise pyrogram.StopPropagation
def continue_propagation(self):
- raise ContinuePropagation
+ raise pyrogram.ContinuePropagation
diff --git a/pyrogram/client/types/user_and_chats/__init__.py b/pyrogram/types/user_and_chats/__init__.py
similarity index 100%
rename from pyrogram/client/types/user_and_chats/__init__.py
rename to pyrogram/types/user_and_chats/__init__.py
diff --git a/pyrogram/client/types/user_and_chats/chat.py b/pyrogram/types/user_and_chats/chat.py
similarity index 81%
rename from pyrogram/client/types/user_and_chats/chat.py
rename to pyrogram/types/user_and_chats/chat.py
index 85ef0a1f87..a0f40eed58 100644
--- a/pyrogram/client/types/user_and_chats/chat.py
+++ b/pyrogram/types/user_and_chats/chat.py
@@ -19,12 +19,10 @@
from typing import Union, List, Generator, Optional
import pyrogram
-from pyrogram.api import types
-from .chat_permissions import ChatPermissions
-from .chat_photo import ChatPhoto
-from .restriction import Restriction
+from pyrogram import raw
+from pyrogram import types
+from pyrogram import utils
from ..object import Object
-from ...ext import utils
class Chat(Object):
@@ -65,51 +63,51 @@ class Chat(Object):
last_name (``str``, *optional*):
Last name of the other party in a private chat, for private chats.
- photo (:obj:`ChatPhoto`, *optional*):
+ photo (:obj:`~pyrogram.types.ChatPhoto`, *optional*):
Chat photo. Suitable for downloads only.
description (``str``, *optional*):
Bio, for private chats and bots or description for groups, supergroups and channels.
- Returned only in :meth:`~Client.get_chat`.
+ Returned only in :meth:`~pyrogram.Client.get_chat`.
invite_link (``str``, *optional*):
Chat invite link, for groups, supergroups and channels.
- Returned only in :meth:`~Client.get_chat`.
+ Returned only in :meth:`~pyrogram.Client.get_chat`.
- pinned_message (:obj:`Message`, *optional*):
+ pinned_message (:obj:`~pyrogram.types.Message`, *optional*):
Pinned message, for groups, supergroups channels and own chat.
- Returned only in :meth:`~Client.get_chat`.
+ Returned only in :meth:`~pyrogram.Client.get_chat`.
sticker_set_name (``str``, *optional*):
For supergroups, name of group sticker set.
- Returned only in :meth:`~Client.get_chat`.
+ Returned only in :meth:`~pyrogram.Client.get_chat`.
can_set_sticker_set (``bool``, *optional*):
True, if the group sticker set can be changed by you.
- Returned only in :meth:`~Client.get_chat`.
+ Returned only in :meth:`~pyrogram.Client.get_chat`.
members_count (``int``, *optional*):
Chat members count, for groups, supergroups and channels only.
- restrictions (List of :obj:`Restriction`, *optional*):
+ restrictions (List of :obj:`~pyrogram.types.Restriction`, *optional*):
The list of reasons why this chat might be unavailable to some users.
This field is available only in case *is_restricted* is True.
- permissions (:obj:`ChatPermissions` *optional*):
+ permissions (:obj:`~pyrogram.types.ChatPermissions` *optional*):
Default chat member permissions, for groups and supergroups.
distance (``int``, *optional*):
Distance in meters of this group chat from your location.
- Returned only in :meth:`~Client.get_nearby_chats`.
+ Returned only in :meth:`~pyrogram.Client.get_nearby_chats`.
- linked_chat (:obj:`Chat`, *optional*):
+ linked_chat (:obj:`~pyrogram.types.Chat`, *optional*):
The linked discussion group (in case of channels) or the linked channel (in case of supergroups).
"""
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
id: int,
type: str,
is_verified: bool = None,
@@ -121,17 +119,17 @@ def __init__(
username: str = None,
first_name: str = None,
last_name: str = None,
- photo: ChatPhoto = None,
+ photo: "types.ChatPhoto" = None,
description: str = None,
invite_link: str = None,
pinned_message=None,
sticker_set_name: str = None,
can_set_sticker_set: bool = None,
members_count: int = None,
- restrictions: List[Restriction] = None,
- permissions: "pyrogram.ChatPermissions" = None,
+ restrictions: List["types.Restriction"] = None,
+ permissions: "types.ChatPermissions" = None,
distance: int = None,
- linked_chat: "pyrogram.Chat" = None
+ linked_chat: "types.Chat" = None
):
super().__init__(client)
@@ -159,7 +157,7 @@ def __init__(
self.linked_chat = linked_chat
@staticmethod
- def _parse_user_chat(client, user: types.User) -> "Chat":
+ def _parse_user_chat(client, user: raw.types.User) -> "Chat":
peer_id = user.id
return Chat(
@@ -172,13 +170,13 @@ def _parse_user_chat(client, user: types.User) -> "Chat":
username=user.username,
first_name=user.first_name,
last_name=user.last_name,
- photo=ChatPhoto._parse(client, user.photo, peer_id, user.access_hash),
- restrictions=pyrogram.List([Restriction._parse(r) for r in user.restriction_reason]) or None,
+ photo=types.ChatPhoto._parse(client, user.photo, peer_id, user.access_hash),
+ restrictions=types.List([types.Restriction._parse(r) for r in user.restriction_reason]) or None,
client=client
)
@staticmethod
- def _parse_chat_chat(client, chat: types.Chat) -> "Chat":
+ def _parse_chat_chat(client, chat: raw.types.Chat) -> "Chat":
peer_id = -chat.id
return Chat(
@@ -186,14 +184,14 @@ def _parse_chat_chat(client, chat: types.Chat) -> "Chat":
type="group",
title=chat.title,
is_creator=getattr(chat, "creator", None),
- photo=ChatPhoto._parse(client, getattr(chat, "photo", None), peer_id, 0),
- permissions=ChatPermissions._parse(getattr(chat, "default_banned_rights", None)),
+ photo=types.ChatPhoto._parse(client, getattr(chat, "photo", None), peer_id, 0),
+ permissions=types.ChatPermissions._parse(getattr(chat, "default_banned_rights", None)),
members_count=getattr(chat, "participants_count", None),
client=client
)
@staticmethod
- def _parse_channel_chat(client, channel: types.Channel) -> "Chat":
+ def _parse_channel_chat(client, channel: raw.types.Channel) -> "Chat":
peer_id = utils.get_channel_id(channel.id)
restriction_reason = getattr(channel, "restriction_reason", [])
@@ -206,35 +204,35 @@ def _parse_channel_chat(client, channel: types.Channel) -> "Chat":
is_scam=getattr(channel, "scam", None),
title=channel.title,
username=getattr(channel, "username", None),
- photo=ChatPhoto._parse(client, getattr(channel, "photo", None), peer_id, channel.access_hash),
- restrictions=pyrogram.List([Restriction._parse(r) for r in restriction_reason]) or None,
- permissions=ChatPermissions._parse(getattr(channel, "default_banned_rights", None)),
+ photo=types.ChatPhoto._parse(client, getattr(channel, "photo", None), peer_id, channel.access_hash),
+ restrictions=types.List([types.Restriction._parse(r) for r in restriction_reason]) or None,
+ permissions=types.ChatPermissions._parse(getattr(channel, "default_banned_rights", None)),
members_count=getattr(channel, "participants_count", None),
client=client
)
@staticmethod
- def _parse(client, message: types.Message or types.MessageService, users: dict, chats: dict) -> "Chat":
- if isinstance(message.to_id, types.PeerUser):
+ def _parse(client, message: raw.types.Message or raw.types.MessageService, users: dict, chats: dict) -> "Chat":
+ if isinstance(message.to_id, raw.types.PeerUser):
return Chat._parse_user_chat(client, users[message.to_id.user_id if message.out else message.from_id])
- if isinstance(message.to_id, types.PeerChat):
+ if isinstance(message.to_id, raw.types.PeerChat):
return Chat._parse_chat_chat(client, chats[message.to_id.chat_id])
return Chat._parse_channel_chat(client, chats[message.to_id.channel_id])
@staticmethod
def _parse_dialog(client, peer, users: dict, chats: dict):
- if isinstance(peer, types.PeerUser):
+ if isinstance(peer, raw.types.PeerUser):
return Chat._parse_user_chat(client, users[peer.user_id])
- elif isinstance(peer, types.PeerChat):
+ elif isinstance(peer, raw.types.PeerChat):
return Chat._parse_chat_chat(client, chats[peer.chat_id])
else:
return Chat._parse_channel_chat(client, chats[peer.channel_id])
@staticmethod
- async def _parse_full(client, chat_full: types.messages.ChatFull or types.UserFull) -> "Chat":
- if isinstance(chat_full, types.UserFull):
+ async def _parse_full(client, chat_full: raw.types.messages.ChatFull or raw.types.UserFull) -> "Chat":
+ if isinstance(chat_full, raw.types.UserFull):
parsed_chat = Chat._parse_user_chat(client, chat_full.user)
parsed_chat.description = chat_full.about
@@ -252,15 +250,15 @@ async def _parse_full(client, chat_full: types.messages.ChatFull or types.UserFu
if full_chat.id == c.id:
chat = c
- if isinstance(full_chat, types.ChannelFull):
+ if isinstance(full_chat, raw.types.ChannelFull):
if full_chat.linked_chat_id == c.id:
linked_chat = c
- if isinstance(full_chat, types.ChatFull):
+ if isinstance(full_chat, raw.types.ChatFull):
parsed_chat = Chat._parse_chat_chat(client, chat)
parsed_chat.description = full_chat.about or None
- if isinstance(full_chat.participants, types.ChatParticipants):
+ if isinstance(full_chat.participants, raw.types.ChatParticipants):
parsed_chat.members_count = len(full_chat.participants.participants)
else:
parsed_chat = Chat._parse_channel_chat(client, chat)
@@ -278,22 +276,22 @@ async def _parse_full(client, chat_full: types.messages.ChatFull or types.UserFu
message_ids=full_chat.pinned_msg_id
)
- if isinstance(full_chat.exported_invite, types.ChatInviteExported):
+ if isinstance(full_chat.exported_invite, raw.types.ChatInviteExported):
parsed_chat.invite_link = full_chat.exported_invite.link
return parsed_chat
@staticmethod
- def _parse_chat(client, chat: Union[types.Chat, types.User, types.Channel]) -> "Chat":
- if isinstance(chat, types.Chat):
+ def _parse_chat(client, chat: Union[raw.types.Chat, raw.types.User, raw.types.Channel]) -> "Chat":
+ if isinstance(chat, raw.types.Chat):
return Chat._parse_chat_chat(client, chat)
- elif isinstance(chat, types.User):
+ elif isinstance(chat, raw.types.User):
return Chat._parse_user_chat(client, chat)
else:
return Chat._parse_channel_chat(client, chat)
async def archive(self):
- """Bound method *archive* of :obj:`Chat`.
+ """Bound method *archive* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
@@ -316,7 +314,7 @@ async def archive(self):
return await self._client.archive_chats(self.id)
async def unarchive(self):
- """Bound method *unarchive* of :obj:`Chat`.
+ """Bound method *unarchive* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
@@ -340,7 +338,7 @@ async def unarchive(self):
# TODO: Remove notes about "All Members Are Admins" for basic groups, the attribute doesn't exist anymore
async def set_title(self, title: str) -> bool:
- """Bound method *set_title* of :obj:`Chat`.
+ """Bound method *set_title* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
@@ -378,7 +376,7 @@ async def set_title(self, title: str) -> bool:
)
async def set_description(self, description: str) -> bool:
- """Bound method *set_description* of :obj:`Chat`.
+ """Bound method *set_description* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
@@ -412,7 +410,7 @@ async def set_description(self, description: str) -> bool:
)
async def set_photo(self, photo: str) -> bool:
- """Bound method *set_photo* of :obj:`Chat`.
+ """Bound method *set_photo* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
@@ -430,7 +428,7 @@ async def set_photo(self, photo: str) -> bool:
Parameters:
photo (``str``):
- New chat photo. You can pass a :obj:`Photo` id or a file path to upload a new photo.
+ New chat photo. You can pass a :obj:`~pyrogram.types.Photo` id or a file path to upload a new photo.
Returns:
``bool``: True on success.
@@ -449,8 +447,8 @@ async def kick_member(
self,
user_id: Union[int, str],
until_date: int = 0
- ) -> Union["pyrogram.Message", bool]:
- """Bound method *kick_member* of :obj:`Chat`.
+ ) -> Union["types.Message", bool]:
+ """Bound method *kick_member* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
@@ -482,7 +480,7 @@ async def kick_member(
considered to be banned forever. Defaults to 0 (ban forever).
Returns:
- :obj:`Message` | ``bool``: On success, a service message will be returned (when applicable), otherwise, in
+ :obj:`~pyrogram.types.Message` | ``bool``: On success, a service message will be returned (when applicable), otherwise, in
case a message object couldn't be returned, True is returned.
Raises:
@@ -499,7 +497,7 @@ async def unban_member(
self,
user_id: Union[int, str]
) -> bool:
- """Bound method *unban_member* of :obj:`Chat`.
+ """Bound method *unban_member* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
@@ -535,10 +533,10 @@ async def unban_member(
async def restrict_member(
self,
user_id: Union[int, str],
- permissions: ChatPermissions,
+ permissions: "types.ChatPermissions",
until_date: int = 0,
- ) -> "pyrogram.Chat":
- """Bound method *unban_member* of :obj:`Chat`.
+ ) -> "types.Chat":
+ """Bound method *unban_member* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
@@ -560,7 +558,7 @@ async def restrict_member(
Unique identifier (int) or username (str) of the target user.
For a contact that exists in your Telegram address book you can use his phone number (str).
- permissions (:obj:`ChatPermissions`):
+ permissions (:obj:`~pyrogram.types.ChatPermissions`):
New user permissions.
until_date (``int``, *optional*):
@@ -569,7 +567,7 @@ async def restrict_member(
considered to be banned forever. Defaults to 0 (ban forever).
Returns:
- :obj:`Chat`: On success, a chat object is returned.
+ :obj:`~pyrogram.types.Chat`: On success, a chat object is returned.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -594,7 +592,7 @@ async def promote_member(
can_pin_messages: bool = False,
can_promote_members: bool = False
) -> bool:
- """Bound method *promote_member* of :obj:`Chat`.
+ """Bound method *promote_member* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
@@ -663,7 +661,7 @@ async def promote_member(
)
async def join(self):
- """Bound method *join* of :obj:`Chat`.
+ """Bound method *join* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
@@ -680,7 +678,7 @@ async def join(self):
This only works for public groups, channels that have set a username or linked chats.
Returns:
- :obj:`Chat`: On success, a chat object is returned.
+ :obj:`~pyrogram.types.Chat`: On success, a chat object is returned.
Raises:
RPCError: In case of a Telegram RPC error.
@@ -689,7 +687,7 @@ async def join(self):
return await self._client.join_chat(self.username or self.id)
async def leave(self):
- """Bound method *leave* of :obj:`Chat`.
+ """Bound method *leave* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
@@ -709,7 +707,7 @@ async def leave(self):
return await self._client.leave_chat(self.id)
async def export_invite_link(self):
- """Bound method *export_invite_link* of :obj:`Chat`.
+ """Bound method *export_invite_link* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
@@ -734,8 +732,8 @@ async def export_invite_link(self):
async def get_member(
self,
user_id: Union[int, str],
- ) -> "pyrogram.ChatMember":
- """Bound method *get_member* of :obj:`Chat`.
+ ) -> "types.ChatMember":
+ """Bound method *get_member* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
@@ -752,7 +750,7 @@ async def get_member(
chat.get_member(user_id)
Returns:
- :obj:`ChatMember`: On success, a chat member is returned.
+ :obj:`~pyrogram.types.ChatMember`: On success, a chat member is returned.
"""
return await self._client.get_chat_member(
@@ -766,8 +764,8 @@ async def get_members(
limit: int = 200,
query: str = "",
filter: str = "all"
- ) -> List["pyrogram.ChatMember"]:
- """Bound method *get_members* of :obj:`Chat`.
+ ) -> List["types.ChatMember"]:
+ """Bound method *get_members* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
@@ -782,7 +780,7 @@ async def get_members(
chat.get_members()
Returns:
- List of :obj:`ChatMember`: On success, a list of chat members is returned.
+ List of :obj:`~pyrogram.types.ChatMember`: On success, a list of chat members is returned.
"""
return await self._client.get_chat_members(
@@ -798,8 +796,8 @@ def iter_members(
limit: int = 0,
query: str = "",
filter: str = "all"
- ) -> Optional[Generator["pyrogram.ChatMember", None, None]]:
- """Bound method *iter_members* of :obj:`Chat`.
+ ) -> Optional[Generator["types.ChatMember", None, None]]:
+ """Bound method *iter_members* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
@@ -815,7 +813,7 @@ def iter_members(
print(member.user.first_name)
Returns:
- ``Generator``: A generator yielding :obj:`ChatMember` objects.
+ ``Generator``: A generator yielding :obj:`~pyrogram.types.ChatMember` objects.
"""
return self._client.iter_chat_members(
@@ -830,7 +828,7 @@ async def add_members(
user_ids: Union[Union[int, str], List[Union[int, str]]],
forward_limit: int = 100
) -> bool:
- """Bound method *add_members* of :obj:`Chat`.
+ """Bound method *add_members* of :obj:`~pyrogram.types.Chat`.
Use as a shortcut for:
diff --git a/pyrogram/client/types/user_and_chats/chat_member.py b/pyrogram/types/user_and_chats/chat_member.py
similarity index 89%
rename from pyrogram/client/types/user_and_chats/chat_member.py
rename to pyrogram/types/user_and_chats/chat_member.py
index 203be137bf..31a27402c9 100644
--- a/pyrogram/client/types/user_and_chats/chat_member.py
+++ b/pyrogram/types/user_and_chats/chat_member.py
@@ -17,8 +17,8 @@
# along with Pyrogram. If not, see .
import pyrogram
-
-from pyrogram.api import types
+from pyrogram import raw
+from pyrogram import types
from ..object import Object
@@ -26,7 +26,7 @@ class ChatMember(Object):
"""Contains information about one member of a chat.
Parameters:
- user (:obj:`User`):
+ user (:obj:`~pyrogram.types.User`):
Information about the user.
status (``str``):
@@ -45,14 +45,14 @@ class ChatMember(Object):
Date when the user joined, unix time.
Not available for creator.
- invited_by (:obj:`User`, *optional*):
+ invited_by (:obj:`~pyrogram.types.User`, *optional*):
Administrators and self member only. Information about the user who invited this member.
In case the user joined by himself this will be the same as "user".
- promoted_by (:obj:`User`, *optional*):
+ promoted_by (:obj:`~pyrogram.types.User`, *optional*):
Administrators only. Information about the user who promoted this member as administrator.
- restricted_by (:obj:`User`, *optional*):
+ restricted_by (:obj:`~pyrogram.types.User`, *optional*):
Restricted and kicked only. Information about the user who restricted or kicked this member.
is_member (``bool``, *optional*):
@@ -128,15 +128,15 @@ class ChatMember(Object):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
- user: "pyrogram.User",
+ client: "pyrogram.Client" = None,
+ user: "types.User",
status: str,
title: str = None,
until_date: int = None,
joined_date: int = None,
- invited_by: "pyrogram.User" = None,
- promoted_by: "pyrogram.User" = None,
- restricted_by: "pyrogram.User" = None,
+ invited_by: "types.User" = None,
+ promoted_by: "types.User" = None,
+ restricted_by: "types.User" = None,
is_member: bool = None,
# Admin permissions
@@ -193,14 +193,16 @@ def __init__(
@staticmethod
def _parse(client, member, users) -> "ChatMember":
- user = pyrogram.User._parse(client, users[member.user_id])
+ user = types.User._parse(client, users[member.user_id])
invited_by = (
- pyrogram.User._parse(client, users[member.inviter_id])
+ types.User._parse(client, users[member.inviter_id])
if getattr(member, "inviter_id", None) else None
)
- if isinstance(member, (types.ChannelParticipant, types.ChannelParticipantSelf, types.ChatParticipant)):
+ if isinstance(member, (raw.types.ChannelParticipant,
+ raw.types.ChannelParticipantSelf,
+ raw.types.ChatParticipant)):
return ChatMember(
user=user,
status="member",
@@ -209,7 +211,7 @@ def _parse(client, member, users) -> "ChatMember":
client=client
)
- if isinstance(member, (types.ChannelParticipantCreator, types.ChatParticipantCreator)):
+ if isinstance(member, (raw.types.ChannelParticipantCreator, raw.types.ChatParticipantCreator)):
return ChatMember(
user=user,
status="creator",
@@ -217,7 +219,7 @@ def _parse(client, member, users) -> "ChatMember":
client=client
)
- if isinstance(member, types.ChatParticipantAdmin):
+ if isinstance(member, raw.types.ChatParticipantAdmin):
return ChatMember(
user=user,
status="administrator",
@@ -226,7 +228,7 @@ def _parse(client, member, users) -> "ChatMember":
client=client
)
- if isinstance(member, types.ChannelParticipantAdmin):
+ if isinstance(member, raw.types.ChannelParticipantAdmin):
permissions = member.admin_rights
return ChatMember(
@@ -235,7 +237,7 @@ def _parse(client, member, users) -> "ChatMember":
title=member.rank,
joined_date=member.date,
invited_by=invited_by,
- promoted_by=pyrogram.User._parse(client, users[member.promoted_by]),
+ promoted_by=types.User._parse(client, users[member.promoted_by]),
can_be_edited=member.can_edit,
can_change_info=permissions.change_info,
can_post_messages=permissions.post_messages,
@@ -248,7 +250,7 @@ def _parse(client, member, users) -> "ChatMember":
client=client
)
- if isinstance(member, types.ChannelParticipantBanned):
+ if isinstance(member, raw.types.ChannelParticipantBanned):
denied_permissions = member.banned_rights
return ChatMember(
@@ -257,7 +259,7 @@ def _parse(client, member, users) -> "ChatMember":
until_date=denied_permissions.until_date,
joined_date=member.date,
is_member=not member.left,
- restricted_by=pyrogram.User._parse(client, users[member.kicked_by]),
+ restricted_by=types.User._parse(client, users[member.kicked_by]),
can_send_messages=not denied_permissions.send_messages,
can_send_media_messages=not denied_permissions.send_media,
can_send_stickers=not denied_permissions.send_stickers,
diff --git a/pyrogram/client/types/user_and_chats/chat_permissions.py b/pyrogram/types/user_and_chats/chat_permissions.py
similarity index 96%
rename from pyrogram/client/types/user_and_chats/chat_permissions.py
rename to pyrogram/types/user_and_chats/chat_permissions.py
index 03d3e0721c..2d9306adde 100644
--- a/pyrogram/client/types/user_and_chats/chat_permissions.py
+++ b/pyrogram/types/user_and_chats/chat_permissions.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from pyrogram.api import types
+from pyrogram import raw
from ..object import Object
@@ -103,8 +103,8 @@ def __init__(
self.can_pin_messages = can_pin_messages
@staticmethod
- def _parse(denied_permissions: types.ChatBannedRights) -> "ChatPermissions":
- if isinstance(denied_permissions, types.ChatBannedRights):
+ def _parse(denied_permissions: "raw.types.ChatBannedRights") -> "ChatPermissions":
+ if isinstance(denied_permissions, raw.types.ChatBannedRights):
return ChatPermissions(
can_send_messages=not denied_permissions.send_messages,
can_send_media_messages=not denied_permissions.send_media,
diff --git a/pyrogram/client/types/user_and_chats/chat_photo.py b/pyrogram/types/user_and_chats/chat_photo.py
similarity index 86%
rename from pyrogram/client/types/user_and_chats/chat_photo.py
rename to pyrogram/types/user_and_chats/chat_photo.py
index 1966b1be60..58a9fcc1be 100644
--- a/pyrogram/client/types/user_and_chats/chat_photo.py
+++ b/pyrogram/types/user_and_chats/chat_photo.py
@@ -17,12 +17,13 @@
# along with Pyrogram. If not, see .
from struct import pack
+from typing import Union
import pyrogram
-from pyrogram.api import types
-from pyrogram.client.ext import utils
+from pyrogram import raw
+from pyrogram.utils import encode_file_id
from ..object import Object
-from ...ext.utils import encode_file_id
+from ... import utils
class ChatPhoto(Object):
@@ -41,7 +42,7 @@ class ChatPhoto(Object):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
small_file_id: str,
big_file_id: str
):
@@ -51,8 +52,13 @@ def __init__(
self.big_file_id = big_file_id
@staticmethod
- def _parse(client, chat_photo: types.UserProfilePhoto or types.ChatPhoto, peer_id: int, peer_access_hash: int):
- if not isinstance(chat_photo, (types.UserProfilePhoto, types.ChatPhoto)):
+ def _parse(
+ client,
+ chat_photo: Union["raw.types.UserProfilePhoto", "raw.types.ChatPhoto"],
+ peer_id: int,
+ peer_access_hash: int
+ ):
+ if not isinstance(chat_photo, (raw.types.UserProfilePhoto, raw.types.ChatPhoto)):
return None
if peer_access_hash is None:
diff --git a/pyrogram/client/types/user_and_chats/chat_preview.py b/pyrogram/types/user_and_chats/chat_preview.py
similarity index 79%
rename from pyrogram/client/types/user_and_chats/chat_preview.py
rename to pyrogram/types/user_and_chats/chat_preview.py
index fa48a319f3..1a0f9c94f9 100644
--- a/pyrogram/client/types/user_and_chats/chat_preview.py
+++ b/pyrogram/types/user_and_chats/chat_preview.py
@@ -19,10 +19,9 @@
from typing import List
import pyrogram
-from pyrogram.api import types
-from ..messages_and_media import Photo
+from pyrogram import raw
+from pyrogram import types
from ..object import Object
-from ..user_and_chats.user import User
class ChatPreview(Object):
@@ -38,22 +37,22 @@ class ChatPreview(Object):
members_count (``int``):
Chat members count.
- photo (:obj:`Photo`, *optional*):
+ photo (:obj:`~pyrogram.types.Photo`, *optional*):
Chat photo.
- members (List of :obj:`User`, *optional*):
+ members (List of :obj:`~pyrogram.types.User`, *optional*):
Preview of some of the chat members.
"""
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
title: str,
type: str,
members_count: int,
- photo: Photo = None,
- members: List[User] = None
+ photo: "types.Photo" = None,
+ members: List["types.User"] = None
):
super().__init__(client)
@@ -64,15 +63,15 @@ def __init__(
self.members = members
@staticmethod
- def _parse(client, chat_invite: types.ChatInvite) -> "ChatPreview":
+ def _parse(client, chat_invite: "raw.types.ChatInvite") -> "ChatPreview":
return ChatPreview(
title=chat_invite.title,
type=("group" if not chat_invite.channel else
"channel" if chat_invite.broadcast else
"supergroup"),
members_count=chat_invite.participants_count,
- photo=Photo._parse(client, chat_invite.photo),
- members=[User._parse(client, user) for user in chat_invite.participants] or None,
+ photo=types.Photo._parse(client, chat_invite.photo),
+ members=[types.User._parse(client, user) for user in chat_invite.participants] or None,
client=client
)
diff --git a/pyrogram/client/types/user_and_chats/dialog.py b/pyrogram/types/user_and_chats/dialog.py
similarity index 83%
rename from pyrogram/client/types/user_and_chats/dialog.py
rename to pyrogram/types/user_and_chats/dialog.py
index bbe06a2c69..b0212a2739 100644
--- a/pyrogram/client/types/user_and_chats/dialog.py
+++ b/pyrogram/types/user_and_chats/dialog.py
@@ -17,21 +17,20 @@
# along with Pyrogram. If not, see .
import pyrogram
-
-from pyrogram.api import types
+from pyrogram import raw
+from pyrogram import types
from ..object import Object
-from ..user_and_chats import Chat
-from ...ext import utils
+from ... import utils
class Dialog(Object):
"""A user's dialog.
Parameters:
- chat (:obj:`Chat `):
+ chat (:obj:`~pyrogram.types.Chat`):
Conversation the dialog belongs to.
- top_message (:obj:`Message`):
+ top_message (:obj:`~pyrogram.types.Message`):
The last message sent in the dialog at this time.
unread_messages_count (``int``):
@@ -50,9 +49,9 @@ class Dialog(Object):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
- chat: Chat,
- top_message: "pyrogram.Message",
+ client: "pyrogram.Client" = None,
+ chat: "types.Chat",
+ top_message: "types.Message",
unread_messages_count: int,
unread_mentions_count: int,
unread_mark: bool,
@@ -68,9 +67,9 @@ def __init__(
self.is_pinned = is_pinned
@staticmethod
- def _parse(client, dialog: types.Dialog, messages, users, chats) -> "Dialog":
+ def _parse(client, dialog: "raw.types.Dialog", messages, users, chats) -> "Dialog":
return Dialog(
- chat=Chat._parse_dialog(client, dialog.peer, users, chats),
+ chat=types.Chat._parse_dialog(client, dialog.peer, users, chats),
top_message=messages.get(utils.get_peer_id(dialog.peer)),
unread_messages_count=dialog.unread_count,
unread_mentions_count=dialog.unread_mentions_count,
diff --git a/pyrogram/client/types/user_and_chats/restriction.py b/pyrogram/types/user_and_chats/restriction.py
similarity index 93%
rename from pyrogram/client/types/user_and_chats/restriction.py
rename to pyrogram/types/user_and_chats/restriction.py
index abf04b7787..fd8b7a63fe 100644
--- a/pyrogram/client/types/user_and_chats/restriction.py
+++ b/pyrogram/types/user_and_chats/restriction.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from pyrogram.api import types
+from pyrogram import raw
from ..object import Object
@@ -42,7 +42,7 @@ def __init__(self, *, platform: str, reason: str, text: str):
self.text = text
@staticmethod
- def _parse(restriction: types.RestrictionReason) -> "Restriction":
+ def _parse(restriction: "raw.types.RestrictionReason") -> "Restriction":
return Restriction(
platform=restriction.platform,
reason=restriction.reason,
diff --git a/pyrogram/client/types/user_and_chats/user.py b/pyrogram/types/user_and_chats/user.py
similarity index 79%
rename from pyrogram/client/types/user_and_chats/user.py
rename to pyrogram/types/user_and_chats/user.py
index f386e1616b..e9a9518220 100644
--- a/pyrogram/client/types/user_and_chats/user.py
+++ b/pyrogram/types/user_and_chats/user.py
@@ -16,17 +16,49 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+import html
from typing import List
import pyrogram
-from pyrogram.api import types
-from pyrogram.client.ext import Link
-from .chat_photo import ChatPhoto
-from .restriction import Restriction
+from pyrogram import raw
+from pyrogram import types
from ..object import Object
from ..update import Update
+class Link(str):
+ HTML = "{text}"
+ MD = "[{text}]({url})"
+
+ def __init__(self, url: str, text: str, style: str):
+ super().__init__()
+
+ self.url = url
+ self.text = text
+ self.style = style
+
+ @staticmethod
+ def format(url: str, text: str, style: str):
+ if style in ["md", "markdown"]:
+ fmt = Link.MD
+ elif style in ["combined", "html", None]:
+ fmt = Link.HTML
+ else:
+ raise ValueError(f"{style} is not a valid style/parse mode")
+
+ return fmt.format(url=url, text=html.escape(text))
+
+ # noinspection PyArgumentList
+ def __new__(cls, url, text, style):
+ return str.__new__(cls, Link.format(url, text, style))
+
+ def __call__(self, other: str = None, *, style: str = None):
+ return Link.format(self.url, other or self.text, style or self.style)
+
+ def __str__(self):
+ return Link.format(self.url, self.text, self.style)
+
+
class User(Object, Update):
"""A Telegram user or bot.
@@ -100,10 +132,10 @@ class User(Object, Update):
phone_number (``str``, *optional*):
User's phone number.
- photo (:obj:`ChatPhoto `, *optional*):
+ photo (:obj:`~pyrogram.types.ChatPhoto`, *optional*):
User's or bot's current profile photo. Suitable for downloads only.
- restrictions (List of :obj:`Restriction`, *optional*):
+ restrictions (List of :obj:`~pyrogram.types.Restriction`, *optional*):
The list of reasons why this bot might be unavailable to some users.
This field is available only in case *is_restricted* is True.
"""
@@ -111,7 +143,7 @@ class User(Object, Update):
def __init__(
self,
*,
- client: "pyrogram.BaseClient" = None,
+ client: "pyrogram.Client" = None,
id: int,
is_self: bool = None,
is_contact: bool = None,
@@ -131,8 +163,8 @@ def __init__(
language_code: str = None,
dc_id: int = None,
phone_number: str = None,
- photo: ChatPhoto = None,
- restrictions: List[Restriction] = None
+ photo: "types.ChatPhoto" = None,
+ restrictions: List["types.Restriction"] = None
):
super().__init__(client)
@@ -160,10 +192,10 @@ def __init__(
@property
def mention(self):
- return Link("tg://user?id={}".format(self.id), self.first_name, self._client.parse_mode)
+ return Link(f"tg://user?id={self.id}", self.first_name, self._client.parse_mode)
@staticmethod
- def _parse(client, user: types.User) -> "User" or None:
+ def _parse(client, user: "raw.types.User") -> "User" or None:
if user is None:
return None
@@ -185,22 +217,22 @@ def _parse(client, user: types.User) -> "User" or None:
language_code=user.lang_code,
dc_id=getattr(user.photo, "dc_id", None),
phone_number=user.phone,
- photo=ChatPhoto._parse(client, user.photo, user.id, user.access_hash),
- restrictions=pyrogram.List([Restriction._parse(r) for r in user.restriction_reason]) or None,
+ photo=types.ChatPhoto._parse(client, user.photo, user.id, user.access_hash),
+ restrictions=types.List([types.Restriction._parse(r) for r in user.restriction_reason]) or None,
client=client
)
@staticmethod
- def _parse_status(user_status: types.UpdateUserStatus, is_bot: bool = False):
- if isinstance(user_status, types.UserStatusOnline):
+ def _parse_status(user_status: "raw.types.UpdateUserStatus", is_bot: bool = False):
+ if isinstance(user_status, raw.types.UserStatusOnline):
status, date = "online", user_status.expires
- elif isinstance(user_status, types.UserStatusOffline):
+ elif isinstance(user_status, raw.types.UserStatusOffline):
status, date = "offline", user_status.was_online
- elif isinstance(user_status, types.UserStatusRecently):
+ elif isinstance(user_status, raw.types.UserStatusRecently):
status, date = "recently", None
- elif isinstance(user_status, types.UserStatusLastWeek):
+ elif isinstance(user_status, raw.types.UserStatusLastWeek):
status, date = "within_week", None
- elif isinstance(user_status, types.UserStatusLastMonth):
+ elif isinstance(user_status, raw.types.UserStatusLastMonth):
status, date = "within_month", None
else:
status, date = "long_time_ago", None
@@ -224,7 +256,7 @@ def _parse_status(user_status: types.UpdateUserStatus, is_bot: bool = False):
}
@staticmethod
- def _parse_user_status(client, user_status: types.UpdateUserStatus):
+ def _parse_user_status(client, user_status: "raw.types.UpdateUserStatus"):
return User(
id=user_status.user_id,
**User._parse_status(user_status.status),
@@ -232,7 +264,7 @@ def _parse_user_status(client, user_status: types.UpdateUserStatus):
)
async def archive(self):
- """Bound method *archive* of :obj:`User`.
+ """Bound method *archive* of :obj:`~pyrogram.types.User`.
Use as a shortcut for:
@@ -255,7 +287,7 @@ async def archive(self):
return await self._client.archive_chats(self.id)
async def unarchive(self):
- """Bound method *unarchive* of :obj:`User`.
+ """Bound method *unarchive* of :obj:`~pyrogram.types.User`.
Use as a shortcut for:
@@ -278,7 +310,7 @@ async def unarchive(self):
return await self._client.unarchive_chats(self.id)
def block(self):
- """Bound method *block* of :obj:`User`.
+ """Bound method *block* of :obj:`~pyrogram.types.User`.
Use as a shortcut for:
@@ -301,7 +333,7 @@ def block(self):
return self._client.block_user(self.id)
def unblock(self):
- """Bound method *unblock* of :obj:`User`.
+ """Bound method *unblock* of :obj:`~pyrogram.types.User`.
Use as a shortcut for:
@@ -324,7 +356,7 @@ def unblock(self):
return self._client.unblock_user(self.id)
def get_common_chats(self):
- """Bound method *get_common_chats* of :obj:`User`.
+ """Bound method *get_common_chats* of :obj:`~pyrogram.types.User`.
Use as a shortcut for:
diff --git a/pyrogram/client/ext/utils.py b/pyrogram/utils.py
similarity index 58%
rename from pyrogram/client/ext/utils.py
rename to pyrogram/utils.py
index 9359ff0596..89ee7f6c79 100644
--- a/pyrogram/client/ext/utils.py
+++ b/pyrogram/utils.py
@@ -18,16 +18,18 @@
import asyncio
import base64
+import functools
+import hashlib
+import os
import struct
-import sys
from concurrent.futures.thread import ThreadPoolExecutor
+from getpass import getpass
from typing import List
from typing import Union
-import pyrogram
-from pyrogram.api.types import PeerUser, PeerChat, PeerChannel
-from . import BaseClient
-from ...api import types
+from pyrogram import raw
+from pyrogram import types
+from pyrogram.scaffold import Scaffold
def decode_file_id(s: str) -> bytes:
@@ -83,18 +85,15 @@ def decode_file_ref(file_ref: str) -> bytes:
return base64.urlsafe_b64decode(file_ref + "=" * (-len(file_ref) % 4))
-async def ainput(prompt: str = ""):
- print(prompt, end="", flush=True)
-
+async def ainput(prompt: str = "", *, hide: bool = False):
with ThreadPoolExecutor(1) as executor:
- return (await asyncio.get_event_loop().run_in_executor(
- executor, sys.stdin.readline
- )).rstrip()
+ func = functools.partial(getpass if hide else input, prompt)
+ return await asyncio.get_event_loop().run_in_executor(executor, func)
def get_offset_date(dialogs):
for m in reversed(dialogs.messages):
- if isinstance(m, types.MessageEmpty):
+ if isinstance(m, raw.types.MessageEmpty):
continue
else:
return m.date
@@ -106,32 +105,30 @@ def get_input_media_from_file_id(
file_id_str: str,
file_ref: str = None,
expected_media_type: int = None
-) -> Union[types.InputMediaPhoto, types.InputMediaDocument]:
+) -> Union["raw.types.InputMediaPhoto", "raw.types.InputMediaDocument"]:
try:
decoded = decode_file_id(file_id_str)
except Exception:
- raise ValueError("Failed to decode file_id: {}".format(file_id_str))
+ raise ValueError(f"Failed to decode file_id: {file_id_str}")
else:
media_type = decoded[0]
if expected_media_type is not None:
if media_type != expected_media_type:
- media_type_str = BaseClient.MEDIA_TYPE_ID.get(media_type, None)
- expected_media_type_str = BaseClient.MEDIA_TYPE_ID.get(expected_media_type, None)
+ media_type_str = Scaffold.MEDIA_TYPE_ID.get(media_type, None)
+ expected_media_type_str = Scaffold.MEDIA_TYPE_ID.get(expected_media_type, None)
- raise ValueError(
- 'Expected: "{}", got "{}" file_id instead'.format(expected_media_type_str, media_type_str)
- )
+ raise ValueError(f'Expected: "{expected_media_type_str}", got "{media_type_str}" file_id instead')
if media_type in (0, 1, 14):
- raise ValueError("This file_id can only be used for download: {}".format(file_id_str))
+ raise ValueError(f"This file_id can only be used for download: {file_id_str}")
if media_type == 2:
unpacked = struct.unpack(" List["pyrogram.Message"]:
+async def parse_messages(client, messages: "raw.types.messages.Messages", replies: int = 1) -> List["types.Message"]:
users = {i.id: i for i in messages.users}
chats = {i.id: i for i in messages.chats}
if not messages.messages:
- return pyrogram.List()
+ return types.List()
parsed_messages = []
for message in messages.messages:
- parsed_messages.append(await pyrogram.Message._parse(client, message, users, chats, replies=0))
+ parsed_messages.append(await types.Message._parse(client, message, users, chats, replies=0))
if replies:
messages_with_replies = {i.id: getattr(i, "reply_to_msg_id", None) for i in messages.messages}
@@ -183,10 +180,10 @@ async def parse_messages(client, messages: types.messages.Messages, replies: int
if reply.message_id == reply_id:
message.reply_to_message = reply
- return pyrogram.List(parsed_messages)
+ return types.List(parsed_messages)
-def parse_deleted_messages(client, update) -> List["pyrogram.Message"]:
+def parse_deleted_messages(client, update) -> List["types.Message"]:
messages = update.messages
channel_id = getattr(update, "channel_id", None)
@@ -194,9 +191,9 @@ def parse_deleted_messages(client, update) -> List["pyrogram.Message"]:
for message in messages:
parsed_messages.append(
- pyrogram.Message(
+ types.Message(
message_id=message,
- chat=pyrogram.Chat(
+ chat=types.Chat(
id=get_channel_id(channel_id),
type="channel",
client=client
@@ -205,14 +202,14 @@ def parse_deleted_messages(client, update) -> List["pyrogram.Message"]:
)
)
- return pyrogram.List(parsed_messages)
+ return types.List(parsed_messages)
-def unpack_inline_message_id(inline_message_id: str) -> types.InputBotInlineMessageID:
+def unpack_inline_message_id(inline_message_id: str) -> "raw.types.InputBotInlineMessageID":
r = inline_message_id + "=" * (-len(inline_message_id) % 4)
- r = struct.unpack(" types.InputBotInlineMess
MAX_USER_ID = 2147483647
-def get_peer_id(peer: Union[PeerUser, PeerChat, PeerChannel]) -> int:
- if isinstance(peer, PeerUser):
+def get_peer_id(peer: raw.base.Peer) -> int:
+ if isinstance(peer, raw.types.PeerUser):
return peer.user_id
- if isinstance(peer, PeerChat):
+ if isinstance(peer, raw.types.PeerChat):
return -peer.chat_id
- if isinstance(peer, PeerChannel):
+ if isinstance(peer, raw.types.PeerChannel):
return MAX_CHANNEL_ID - peer.channel_id
- raise ValueError("Peer type invalid: {}".format(peer))
+ raise ValueError(f"Peer type invalid: {peer}")
def get_peer_type(peer_id: int) -> str:
@@ -248,8 +245,91 @@ def get_peer_type(peer_id: int) -> str:
elif 0 < peer_id <= MAX_USER_ID:
return "user"
- raise ValueError("Peer id invalid: {}".format(peer_id))
+ raise ValueError(f"Peer id invalid: {peer_id}")
def get_channel_id(peer_id: int) -> int:
return MAX_CHANNEL_ID - peer_id
+
+
+def btoi(b: bytes) -> int:
+ return int.from_bytes(b, "big")
+
+
+def itob(i: int) -> bytes:
+ return i.to_bytes(256, "big")
+
+
+def sha256(data: bytes) -> bytes:
+ return hashlib.sha256(data).digest()
+
+
+def xor(a: bytes, b: bytes) -> bytes:
+ return bytes(i ^ j for i, j in zip(a, b))
+
+
+def compute_password_hash(algo: raw.types.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow,
+ password: str) -> bytes:
+ hash1 = sha256(algo.salt1 + password.encode() + algo.salt1)
+ hash2 = sha256(algo.salt2 + hash1 + algo.salt2)
+ hash3 = hashlib.pbkdf2_hmac("sha512", hash2, algo.salt1, 100000)
+
+ return sha256(algo.salt2 + hash3 + algo.salt2)
+
+
+# noinspection PyPep8Naming
+def compute_password_check(r: raw.types.account.Password, password: str) -> raw.types.InputCheckPasswordSRP:
+ algo = r.current_algo
+
+ p_bytes = algo.p
+ p = btoi(algo.p)
+
+ g_bytes = itob(algo.g)
+ g = algo.g
+
+ B_bytes = r.srp_B
+ B = btoi(B_bytes)
+
+ srp_id = r.srp_id
+
+ x_bytes = compute_password_hash(algo, password)
+ x = btoi(x_bytes)
+
+ g_x = pow(g, x, p)
+
+ k_bytes = sha256(p_bytes + g_bytes)
+ k = btoi(k_bytes)
+
+ kg_x = (k * g_x) % p
+
+ while True:
+ a_bytes = os.urandom(256)
+ a = btoi(a_bytes)
+
+ A = pow(g, a, p)
+ A_bytes = itob(A)
+
+ u = btoi(sha256(A_bytes + B_bytes))
+
+ if u > 0:
+ break
+
+ g_b = (B - kg_x) % p
+
+ ux = u * x
+ a_ux = a + ux
+ S = pow(g_b, a_ux, p)
+ S_bytes = itob(S)
+
+ K_bytes = sha256(S_bytes)
+
+ M1_bytes = sha256(
+ xor(sha256(p_bytes), sha256(g_bytes))
+ + sha256(algo.salt1)
+ + sha256(algo.salt2)
+ + A_bytes
+ + B_bytes
+ + K_bytes
+ )
+
+ return raw.types.InputCheckPasswordSRP(srp_id=srp_id, A=A_bytes, M1=M1_bytes)
diff --git a/requirements.txt b/requirements.txt
index 1af9706190..72ed1aa51a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,3 @@
pyaes==1.6.1
pysocks==1.7.1
-async_lru==1.0.1
-async_generator==1.10
\ No newline at end of file
+async_lru==1.0.2
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 0e9bb2dbfa..3b88bab70e 100644
--- a/setup.py
+++ b/setup.py
@@ -39,7 +39,7 @@
class Clean(Command):
DIST = ["./build", "./dist", "./Pyrogram.egg-info"]
- API = ["pyrogram/errors/exceptions", "pyrogram/api/functions", "pyrogram/api/types", "pyrogram/api/all.py"]
+ API = ["pyrogram/errors/exceptions", "pyrogram/raw/functions", "pyrogram/raw/types", "pyrogram/raw/all.py"]
DOCS = [
"docs/source/telegram", "docs/build", "docs/source/api/methods", "docs/source/api/types",
"docs/source/api/bound-methods"
@@ -139,17 +139,17 @@ def run(self):
author_email="dan@pyrogram.org",
license="LGPLv3+",
classifiers=[
- "Development Status :: 4 - Beta",
+ "Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Natural Language :: English",
"License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: Implementation",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
@@ -167,11 +167,11 @@ def run(self):
"Source": "https://github.com/pyrogram/pyrogram",
"Documentation": "https://docs.pyrogram.org",
},
- python_requires="~=3.5",
+ python_requires="~=3.6",
packages=find_packages(exclude=["compiler*"]),
package_data={
- "pyrogram.client.ext": ["mime.types"],
- "pyrogram.client.storage": ["schema.sql"]
+ "pyrogram": ["mime.types"],
+ "pyrogram.storage": ["schema.sql"]
},
zip_safe=False,
install_requires=requires,
From 23b1450f11b5b564f20b1f41934327d6c02fb20c Mon Sep 17 00:00:00 2001
From: Accipiter7 <64995687+Accipiter7@users.noreply.github.com>
Date: Sat, 22 Aug 2020 11:46:16 +0530
Subject: [PATCH 0167/1073] [Client] Fixed ImportError (#471)
---
pyrogram/client/client.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py
index 624c98c616..66201638c1 100644
--- a/pyrogram/client/client.py
+++ b/pyrogram/client/client.py
@@ -27,7 +27,7 @@
from configparser import ConfigParser
from hashlib import sha256, md5
from importlib import import_module
-from pathlib import Path, Pureapath
+from pathlib import Path, PurePath
from signal import signal, SIGINT, SIGTERM, SIGABRT
from typing import Union, List, BinaryIO
From fc07f8d5d1f31b46823c746eea210e0c647d5b0a Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 22 Aug 2020 08:17:51 +0200
Subject: [PATCH 0168/1073] Update README.md
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 61ece5685c..a6f0b6cf42 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@ app.run()
**Pyrogram** is a modern, elegant and easy-to-use [Telegram](https://telegram.org/) framework written from the ground up
in Python and C. It enables you to easily create custom apps for both user and bot identities (bot API alternative) via
-the [MTProto API](https://core.telegram.org/api#telegram-api).
+the [MTProto API](https://docs.pyrogram.org/topics/mtproto-vs-botapi).
### Features
@@ -44,7 +44,7 @@ the [MTProto API](https://core.telegram.org/api#telegram-api).
- **Elegant**: Low-level details are abstracted and re-presented in a much nicer and easier way.
- **Fast**: Crypto parts are boosted up by [TgCrypto](https://github.com/pyrogram/tgcrypto), a high-performance library
written in pure C.
-- **Asynchronous**: Allows both synchronous and asynchronous usages to fit all usage needs.
+- **Asynchronous**: Allows both synchronous and asynchronous models to fit all usage needs.
- **Documented**: API methods, types and public interfaces are all [well documented](https://docs.pyrogram.org).
- **Type-hinted**: Types and methods are all type-hinted, enabling excellent editor support.
- **Updated**, to make use of the latest Telegram API version and features.
From bc62b3f6aefdd491027d2c0de4de58e46370a741 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 22 Aug 2020 09:22:14 +0200
Subject: [PATCH 0169/1073] Implement a way to deal with failing inline
requests This is due to Telegram raising an error in case bots not in DC4 try
to communicate with chats that live in DC4.
---
.../methods/messages/edit_inline_media.py | 10 ++-
.../messages/edit_inline_reply_markup.py | 11 ++-
pyrogram/methods/messages/edit_inline_text.py | 10 ++-
pyrogram/methods/messages/inline_session.py | 75 +++++++++++++++++++
4 files changed, 100 insertions(+), 6 deletions(-)
create mode 100644 pyrogram/methods/messages/inline_session.py
diff --git a/pyrogram/methods/messages/edit_inline_media.py b/pyrogram/methods/messages/edit_inline_media.py
index 76b716f1ab..a6a893ae5e 100644
--- a/pyrogram/methods/messages/edit_inline_media.py
+++ b/pyrogram/methods/messages/edit_inline_media.py
@@ -22,6 +22,7 @@
from pyrogram import types
from pyrogram import utils
from pyrogram.scaffold import Scaffold
+from .inline_session import get_session
class EditInlineMedia(Scaffold):
@@ -105,9 +106,14 @@ async def edit_inline_media(
else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 5)
- return await self.send(
+ unpacked = utils.unpack_inline_message_id(inline_message_id)
+ dc_id = unpacked.dc_id
+
+ session = get_session(self, dc_id)
+
+ return await session.send(
raw.functions.messages.EditInlineBotMessage(
- id=utils.unpack_inline_message_id(inline_message_id),
+ id=unpacked,
media=media,
reply_markup=reply_markup.write() if reply_markup else None,
**await self.parser.parse(caption, parse_mode)
diff --git a/pyrogram/methods/messages/edit_inline_reply_markup.py b/pyrogram/methods/messages/edit_inline_reply_markup.py
index 5d1b24635b..9905bcf595 100644
--- a/pyrogram/methods/messages/edit_inline_reply_markup.py
+++ b/pyrogram/methods/messages/edit_inline_reply_markup.py
@@ -20,6 +20,7 @@
from pyrogram import types
from pyrogram import utils
from pyrogram.scaffold import Scaffold
+from .inline_session import get_session
class EditInlineReplyMarkup(Scaffold):
@@ -51,9 +52,15 @@ async def edit_inline_reply_markup(
InlineKeyboardMarkup([[
InlineKeyboardButton("New button", callback_data="new_data")]]))
"""
- return await self.send(
+
+ unpacked = utils.unpack_inline_message_id(inline_message_id)
+ dc_id = unpacked.dc_id
+
+ session = get_session(self, dc_id)
+
+ return await session.send(
raw.functions.messages.EditInlineBotMessage(
- id=utils.unpack_inline_message_id(inline_message_id),
+ id=unpacked,
reply_markup=reply_markup.write() if reply_markup else None,
)
)
diff --git a/pyrogram/methods/messages/edit_inline_text.py b/pyrogram/methods/messages/edit_inline_text.py
index ebb2f91a81..c1363181c7 100644
--- a/pyrogram/methods/messages/edit_inline_text.py
+++ b/pyrogram/methods/messages/edit_inline_text.py
@@ -22,6 +22,7 @@
from pyrogram import types
from pyrogram import utils
from pyrogram.scaffold import Scaffold
+from .inline_session import get_session
class EditInlineText(Scaffold):
@@ -72,9 +73,14 @@ async def edit_inline_text(
disable_web_page_preview=True)
"""
- return await self.send(
+ unpacked = utils.unpack_inline_message_id(inline_message_id)
+ dc_id = unpacked.dc_id
+
+ session = get_session(self, dc_id)
+
+ return await session.send(
raw.functions.messages.EditInlineBotMessage(
- id=utils.unpack_inline_message_id(inline_message_id),
+ id=unpacked,
no_webpage=disable_web_page_preview or None,
reply_markup=reply_markup.write() if reply_markup else None,
**await self.parser.parse(text, parse_mode)
diff --git a/pyrogram/methods/messages/inline_session.py b/pyrogram/methods/messages/inline_session.py
new file mode 100644
index 0000000000..681ea14fed
--- /dev/null
+++ b/pyrogram/methods/messages/inline_session.py
@@ -0,0 +1,75 @@
+# Pyrogram - Telegram MTProto API Client Library for Python
+# Copyright (C) 2017-2020 Dan
+#
+# This file is part of Pyrogram.
+#
+# Pyrogram is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pyrogram is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Pyrogram. If not, see .
+
+from asyncio import Lock
+
+import pyrogram
+from pyrogram import raw
+from pyrogram.errors import AuthBytesInvalid
+from pyrogram.session import Session
+from pyrogram.session.auth import Auth
+
+lock = Lock()
+session = None
+dest_dc_id = 4
+
+
+async def get_session(client: "pyrogram.Client", dc_id: int):
+ if dc_id != dest_dc_id:
+ return client
+
+ if dc_id == await client.storage.dc_id():
+ return client
+
+ async with lock:
+ global session
+
+ if session is not None:
+ return session
+
+ session = Session(
+ client, dest_dc_id,
+ await Auth(client, dest_dc_id, False).create(),
+ False, is_media=True
+ )
+
+ await session.start()
+
+ for _ in range(3):
+ exported_auth = await session.send(
+ raw.functions.auth.ExportAuthorization(
+ dc_id=dest_dc_id
+ )
+ )
+
+ try:
+ await session.send(
+ raw.functions.auth.ImportAuthorization(
+ id=exported_auth.id,
+ bytes=exported_auth.bytes
+ )
+ )
+ except AuthBytesInvalid:
+ continue
+ else:
+ break
+ else:
+ await session.stop()
+ raise AuthBytesInvalid
+
+ return session
From d7be2c90a152b4a2b225f4998e693aeb6dfd076f Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 22 Aug 2020 09:50:37 +0200
Subject: [PATCH 0170/1073] Fix run() not dealing properly with coroutines
---
pyrogram/methods/utilities/run.py | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/pyrogram/methods/utilities/run.py b/pyrogram/methods/utilities/run.py
index dc49a524a4..dccce0f22e 100644
--- a/pyrogram/methods/utilities/run.py
+++ b/pyrogram/methods/utilities/run.py
@@ -17,6 +17,7 @@
# along with Pyrogram. If not, see .
import asyncio
+import inspect
from pyrogram.methods.utilities.idle import idle
from pyrogram.scaffold import Scaffold
@@ -52,6 +53,11 @@ def run(self, coroutine=None):
if coroutine is not None:
run(coroutine)
else:
- self.start()
- run(idle())
- self.stop()
+ if inspect.iscoroutinefunction(self.start):
+ run(self.start())
+ run(idle())
+ run(self.stop())
+ else:
+ self.start()
+ run(idle())
+ self.stop()
From fbded4e23bafef1b42b95381e7e6abd640844840 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 22 Aug 2020 11:26:11 +0200
Subject: [PATCH 0171/1073] Fix time going out of sync when starting new
sessions
---
pyrogram/session/internals/msg_factory.py | 5 ++---
pyrogram/session/internals/msg_id.py | 15 +++++++++++++--
pyrogram/session/session.py | 7 +++----
3 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/pyrogram/session/internals/msg_factory.py b/pyrogram/session/internals/msg_factory.py
index bf44b7d3c4..98c88b3f89 100644
--- a/pyrogram/session/internals/msg_factory.py
+++ b/pyrogram/session/internals/msg_factory.py
@@ -26,14 +26,13 @@
class MsgFactory:
- def __init__(self, server_time: float = 0):
+ def __init__(self):
self.seq_no = SeqNo()
- self.server_time = server_time
def __call__(self, body: TLObject) -> Message:
return Message(
body,
- MsgId(self.server_time),
+ MsgId(),
self.seq_no(not isinstance(body, not_content_related)),
len(body)
)
diff --git a/pyrogram/session/internals/msg_id.py b/pyrogram/session/internals/msg_id.py
index 58474222c7..72b8e81f02 100644
--- a/pyrogram/session/internals/msg_id.py
+++ b/pyrogram/session/internals/msg_id.py
@@ -16,18 +16,29 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+import logging
+from datetime import datetime
from time import monotonic
+log = logging.getLogger(__name__)
+
class MsgId:
reference_clock = monotonic()
last_time = 0
msg_id_offset = 0
+ server_time = 0
- def __new__(cls, server_time: float = 0) -> int:
- now = monotonic() - cls.reference_clock + server_time
+ def __new__(cls) -> int:
+ now = monotonic() - cls.reference_clock + cls.server_time
cls.msg_id_offset = cls.msg_id_offset + 4 if now == cls.last_time else 0
msg_id = int(now * 2 ** 32) + cls.msg_id_offset
cls.last_time = now
return msg_id
+
+ @classmethod
+ def set_server_time(cls, server_time: int):
+ if not cls.server_time:
+ cls.server_time = server_time
+ log.info(f"Time synced: {datetime.utcfromtimestamp(server_time)} UTC")
diff --git a/pyrogram/session/session.py b/pyrogram/session/session.py
index 6c385199b4..b25b216689 100644
--- a/pyrogram/session/session.py
+++ b/pyrogram/session/session.py
@@ -23,6 +23,7 @@
from datetime import datetime, timedelta
from hashlib import sha1
from io import BytesIO
+import os
import pyrogram
from pyrogram import __copyright__, __license__, __version__
@@ -96,7 +97,7 @@ def __init__(
self.auth_key_id = sha1(auth_key).digest()[-8:]
- self.session_id = Long(MsgId(time.time()))
+ self.session_id = os.urandom(8)
self.msg_factory = MsgFactory()
self.current_salt = None
@@ -247,9 +248,7 @@ async def handle_packet(self, packet):
for msg in messages:
if msg.seq_no == 0:
- server_time = msg.msg_id / (2 ** 32)
- self.msg_factory.server_time = server_time
- log.info(f"Time synced: {datetime.utcfromtimestamp(server_time)} UTC")
+ MsgId.set_server_time(msg.msg_id / (2 ** 32))
if msg.seq_no % 2 != 0:
if msg.msg_id in self.pending_acks:
From 8f51f1597a6a7b04e2782869367ceff80b3eeb52 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 22 Aug 2020 11:30:27 +0200
Subject: [PATCH 0172/1073] Allow pruning the new generated files from
pyrogram.raw.base
---
MANIFEST.in | 1 +
setup.py | 5 ++++-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/MANIFEST.in b/MANIFEST.in
index 67900cba5e..100375d781 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -7,4 +7,5 @@ recursive-include pyrogram mime.types schema.sql
prune pyrogram/errors/exceptions
prune pyrogram/raw/functions
prune pyrogram/raw/types
+prune pyrogram/raw/base
exclude pyrogram/raw/all.py
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 3b88bab70e..28942b6b36 100644
--- a/setup.py
+++ b/setup.py
@@ -39,7 +39,10 @@
class Clean(Command):
DIST = ["./build", "./dist", "./Pyrogram.egg-info"]
- API = ["pyrogram/errors/exceptions", "pyrogram/raw/functions", "pyrogram/raw/types", "pyrogram/raw/all.py"]
+ API = [
+ "pyrogram/errors/exceptions", "pyrogram/raw/functions", "pyrogram/raw/types", "pyrogram/raw/base",
+ "pyrogram/raw/all.py"
+ ]
DOCS = [
"docs/source/telegram", "docs/build", "docs/source/api/methods", "docs/source/api/types",
"docs/source/api/bound-methods"
From a822c5126167552ea610b34eb8845a899afe3578 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 22 Aug 2020 11:30:42 +0200
Subject: [PATCH 0173/1073] Update beta version
---
pyrogram/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py
index 65ac3d7175..997dfdc9ed 100644
--- a/pyrogram/__init__.py
+++ b/pyrogram/__init__.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-__version__ = "1.0.0b1"
+__version__ = "1.0.0b2"
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__copyright__ = "Copyright (C) 2017-2020 Dan "
From 5f087e5f824cfb6c65446060f5168ec869e2912c Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 22 Aug 2020 14:05:54 +0200
Subject: [PATCH 0174/1073] Use create_task instead of ensure_future
---
pyrogram/dispatcher.py | 6 +++---
pyrogram/methods/advanced/save_file.py | 4 ++--
pyrogram/methods/utilities/restart.py | 2 +-
pyrogram/methods/utilities/stop.py | 2 +-
pyrogram/syncer.py | 2 +-
5 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/pyrogram/dispatcher.py b/pyrogram/dispatcher.py
index 40a6dcf48f..00c513496b 100644
--- a/pyrogram/dispatcher.py
+++ b/pyrogram/dispatcher.py
@@ -115,7 +115,7 @@ async def start(self):
self.locks_list.append(asyncio.Lock())
self.handler_worker_tasks.append(
- asyncio.ensure_future(self.handler_worker(self.locks_list[-1]))
+ self.loop.create_task(self.handler_worker(self.locks_list[-1]))
)
logging.info(f"Started {self.client.workers} HandlerTasks")
@@ -148,7 +148,7 @@ async def fn():
for lock in self.locks_list:
lock.release()
- asyncio.ensure_future(fn())
+ self.loop.create_task(fn())
def remove_handler(self, handler, group: int):
async def fn():
@@ -164,7 +164,7 @@ async def fn():
for lock in self.locks_list:
lock.release()
- asyncio.ensure_future(fn())
+ self.loop.create_task(fn())
async def handler_worker(self, lock):
while True:
diff --git a/pyrogram/methods/advanced/save_file.py b/pyrogram/methods/advanced/save_file.py
index 4e594b6485..4bdaedf5cb 100644
--- a/pyrogram/methods/advanced/save_file.py
+++ b/pyrogram/methods/advanced/save_file.py
@@ -101,7 +101,7 @@ async def worker(session):
return
try:
- await asyncio.ensure_future(session.send(data))
+ await self.loop.create_task(session.send(data))
except Exception as e:
log.error(e)
@@ -139,7 +139,7 @@ async def worker(session):
await self.storage.test_mode(), is_media=True
) for _ in range(pool_size)
]
- workers = [asyncio.ensure_future(worker(session)) for session in pool for _ in range(workers_count)]
+ workers = [self.loop.create_task(worker(session)) for session in pool for _ in range(workers_count)]
queue = asyncio.Queue(16)
try:
diff --git a/pyrogram/methods/utilities/restart.py b/pyrogram/methods/utilities/restart.py
index ad842bc4b3..22c145b536 100644
--- a/pyrogram/methods/utilities/restart.py
+++ b/pyrogram/methods/utilities/restart.py
@@ -65,6 +65,6 @@ async def do_it():
if block:
await do_it()
else:
- asyncio.ensure_future(do_it())
+ self.loop.create_task(do_it())
return self
diff --git a/pyrogram/methods/utilities/stop.py b/pyrogram/methods/utilities/stop.py
index b48a143142..b686211628 100644
--- a/pyrogram/methods/utilities/stop.py
+++ b/pyrogram/methods/utilities/stop.py
@@ -60,6 +60,6 @@ async def do_it():
if block:
await do_it()
else:
- asyncio.ensure_future(do_it())
+ self.loop.create_task(do_it())
return self
diff --git a/pyrogram/syncer.py b/pyrogram/syncer.py
index 1a9d77f30e..db46e9694c 100644
--- a/pyrogram/syncer.py
+++ b/pyrogram/syncer.py
@@ -59,7 +59,7 @@ async def remove(cls, client):
@classmethod
def start(cls):
cls.event.clear()
- asyncio.ensure_future(cls.worker())
+ asyncio.get_event_loop().create_task(cls.worker())
@classmethod
def stop(cls):
From 303712f599136c72e9ca3b8b7abfdde0c439a3c6 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 22 Aug 2020 16:09:38 +0200
Subject: [PATCH 0175/1073] Update docs
---
compiler/docs/template/bound-methods.rst | 2 +-
compiler/docs/template/types.rst | 4 +-
docs/source/api/handlers.rst | 2 +-
docs/source/intro/install.rst | 4 +-
docs/source/intro/quickstart.rst | 4 +-
docs/source/start/errors.rst | 2 +-
docs/source/start/examples/bot_keyboards.rst | 3 +-
docs/source/start/examples/echobot.rst | 10 +--
docs/source/start/examples/inline_queries.rst | 6 +-
docs/source/start/examples/welcomebot.rst | 14 ++--
docs/source/start/invoking.rst | 13 ++-
docs/source/start/updates.rst | 10 ++-
docs/source/topics/create-filters.rst | 83 ++++++++++++++++---
pyrogram/client.py | 2 +-
14 files changed, 110 insertions(+), 49 deletions(-)
diff --git a/compiler/docs/template/bound-methods.rst b/compiler/docs/template/bound-methods.rst
index 963b5251c9..13a51b047e 100644
--- a/compiler/docs/template/bound-methods.rst
+++ b/compiler/docs/template/bound-methods.rst
@@ -15,7 +15,7 @@ some of the required arguments.
@app.on_message()
def hello(client, message)
- message.reply("hi")
+ message.reply_text("hi")
app.run()
diff --git a/compiler/docs/template/types.rst b/compiler/docs/template/types.rst
index 4cc0cf924e..e6c9a5d7cc 100644
--- a/compiler/docs/template/types.rst
+++ b/compiler/docs/template/types.rst
@@ -1,12 +1,12 @@
Available Types
===============
-This page is about Pyrogram types. All types listed here are accessible through the main package directly.
+This page is about Pyrogram types. All types listed here are accessible through ``types`` package.
.. code-block:: python
:emphasize-lines: 1
- from pyrogram import User, Message, ...
+ from pyrogram.types import User, Message, ...
.. note::
diff --git a/docs/source/api/handlers.rst b/docs/source/api/handlers.rst
index 80d2cf73a9..4e79d139bc 100644
--- a/docs/source/api/handlers.rst
+++ b/docs/source/api/handlers.rst
@@ -5,7 +5,7 @@ Handlers are used to instruct Pyrogram about which kind of updates you'd like to
For a much more convenient way of registering callback functions have a look at :doc:`Decorators ` instead.
.. code-block:: python
- :emphasize-lines: 1, 10
+ :emphasize-lines: 2, 11
from pyrogram import Client
from pyrogram.handlers import MessageHandler
diff --git a/docs/source/intro/install.rst b/docs/source/intro/install.rst
index 9056d1f50f..813961dcac 100644
--- a/docs/source/intro/install.rst
+++ b/docs/source/intro/install.rst
@@ -40,12 +40,12 @@ Pyrogram is always evolving, although new releases on PyPI are published only wh
doesn't mean you can't try new features right now!
In case you'd like to try out the latest Pyrogram features, the `GitHub repo`_ is always kept updated with new changes;
-you can install the development version straight from the ``develop`` branch using this command (note "develop.zip" in
+you can install the development version straight from the ``master`` branch using this command (note "master.zip" in
the link):
.. code-block:: text
- $ pip3 install -U https://github.com/pyrogram/pyrogram/archive/develop.zip
+ $ pip3 install -U https://github.com/pyrogram/pyrogram/archive/master.zip
Verifying
---------
diff --git a/docs/source/intro/quickstart.rst b/docs/source/intro/quickstart.rst
index 593403b99c..eeb9848264 100644
--- a/docs/source/intro/quickstart.rst
+++ b/docs/source/intro/quickstart.rst
@@ -1,8 +1,8 @@
Quick Start
===========
-The next few steps serve as a quick start for all new Pyrogrammers that want to see Pyrogram in action as fast as
-possible. Let's go!
+The next few steps serve as a quick start for all new :term:`Pyrogrammers ` that want to see Pyrogram in
+action as fast as possible. Let's go!
Get Pyrogram Real Fast
----------------------
diff --git a/docs/source/start/errors.rst b/docs/source/start/errors.rst
index ff9ccf5b59..f5747d7741 100644
--- a/docs/source/start/errors.rst
+++ b/docs/source/start/errors.rst
@@ -1,7 +1,7 @@
Error Handling
==============
-Errors are inevitable when working with the API, and they must be correctly handled with ``try..except`` blocks in order
+Errors are inevitable when working with the API, and they can be correctly handled with ``try...except`` blocks in order
to control the behaviour of your application. Pyrogram errors all live inside the ``errors`` package:
.. code-block:: python
diff --git a/docs/source/start/examples/bot_keyboards.rst b/docs/source/start/examples/bot_keyboards.rst
index 343e22c927..6e288c4314 100644
--- a/docs/source/start/examples/bot_keyboards.rst
+++ b/docs/source/start/examples/bot_keyboards.rst
@@ -11,7 +11,8 @@ like send_audio(), send_document(), send_location(), etc...
.. code-block:: python
- from pyrogram import Client, ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton
+ from pyrogram import Client
+ from pyrogram.types import ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton
# Create a client using your bot token
app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
diff --git a/docs/source/start/examples/echobot.rst b/docs/source/start/examples/echobot.rst
index a751a2cddd..61dc9929da 100644
--- a/docs/source/start/examples/echobot.rst
+++ b/docs/source/start/examples/echobot.rst
@@ -3,19 +3,19 @@ echobot
This simple echo bot replies to every private text message.
-It uses the @on_message decorator to register a MessageHandler and applies two filters on it:
-Filters.text and Filters.private to make sure it will reply to private text messages only.
+It uses the ``@on_message`` decorator to register a ``MessageHandler`` and applies two filters on it:
+``filters.text`` and ``filters.private`` to make sure it will reply to private text messages only.
.. code-block:: python
- from pyrogram import Client, Filters
+ from pyrogram import Client, filters
app = Client("my_account")
- @app.on_message(Filters.text & Filters.private)
+ @app.on_message(filters.text & filters.private)
def echo(client, message):
- message.reply(message.text)
+ message.reply_text(message.text)
app.run() # Automatically start() and idle()
\ No newline at end of file
diff --git a/docs/source/start/examples/inline_queries.rst b/docs/source/start/examples/inline_queries.rst
index 158394e8d1..023b9c6ed1 100644
--- a/docs/source/start/examples/inline_queries.rst
+++ b/docs/source/start/examples/inline_queries.rst
@@ -8,9 +8,9 @@ It uses the @on_inline_query decorator to register an InlineQueryHandler.
.. code-block:: python
- from pyrogram import (
- Client, InlineQueryResultArticle, InputTextMessageContent, InlineKeyboardMarkup, InlineKeyboardButton
- )
+ from pyrogram import Client
+ from pyrogram.types import (InlineQueryResultArticle, InputTextMessageContent,
+ InlineKeyboardMarkup, InlineKeyboardButton)
app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
diff --git a/docs/source/start/examples/welcomebot.rst b/docs/source/start/examples/welcomebot.rst
index a3bb32998a..cdd7f022d7 100644
--- a/docs/source/start/examples/welcomebot.rst
+++ b/docs/source/start/examples/welcomebot.rst
@@ -1,14 +1,12 @@
welcomebot
==========
-This is the Welcome Bot in @PyrogramChat.
-
-It uses the Emoji module to easily add emojis in your text messages and Filters
+This example uses the ``emoji`` module to easily add emoji in your text messages and ``filters``
to make it only work for specific messages in a specific chat.
.. code-block:: python
- from pyrogram import Client, Emoji, Filters
+ from pyrogram import Client, emoji, filters
TARGET = "PyrogramChat" # Target chat. Can also be a list of multiple chat ids/usernames
MENTION = "[{}](tg://user?id={})" # User mention markup
@@ -18,16 +16,16 @@ to make it only work for specific messages in a specific chat.
# Filter in only new_chat_members updates generated in TARGET chat
- @app.on_message(Filters.chat(TARGET) & Filters.new_chat_members)
+ @app.on_message(filters.chat(TARGET) & filters.new_chat_members)
def welcome(client, message):
# Build the new members list (with mentions) by using their first_name
- new_members = [MENTION.format(i.first_name, i.id) for i in message.new_chat_members]
+ new_members = [u.mention for u in message.new_chat_members]
# Build the welcome message by using an emoji and the list we built above
- text = MESSAGE.format(Emoji.SPARKLES, ", ".join(new_members))
+ text = MESSAGE.format(emoji.SPARKLES, ", ".join(new_members))
# Send the welcome message, without the web page preview
- message.reply(text, disable_web_page_preview=True)
+ message.reply_text(text, disable_web_page_preview=True)
app.run() # Automatically start() and idle()
\ No newline at end of file
diff --git a/docs/source/start/invoking.rst b/docs/source/start/invoking.rst
index 0abea089e9..b8eddb9e62 100644
--- a/docs/source/start/invoking.rst
+++ b/docs/source/start/invoking.rst
@@ -14,8 +14,7 @@ account; we are now aiming towards the core of the library. It's time to start p
Basic Usage
-----------
-Making API method calls with Pyrogram is very simple. Here's a basic example we are going to examine step by step and
-then expand to explain what happens underneath:
+Making API method calls with Pyrogram is very simple. Here's a basic example we are going to examine step by step:
.. code-block:: python
@@ -56,9 +55,9 @@ Basic step-by-step
Context Manager
---------------
-The ``with`` statement starts a context manager, which is used as a shortcut to automatically call
-:meth:`~pyrogram.Client.start` and :meth:`~pyrogram.Client.stop`, which are methods required for Pyrogram to work
-properly. The context manager does also gracefully stop the client, even in case of unhandled exceptions in your code.
+The ``with`` statement starts a context manager used as a shortcut to automatically call :meth:`~pyrogram.Client.start`
+and :meth:`~pyrogram.Client.stop`, which are methods required for Pyrogram to work properly. The context manager does
+also gracefully stop the client, even in case of unhandled exceptions in your code.
This is how Pyrogram looks without the context manager:
@@ -111,8 +110,8 @@ Asynchronous step-by-step
async with app:
await app.send_message("me", "Hi!")
-#. Finally, we tell Python to schedule our ``main()`` async function, which in turn will execute Pyrogram's code. Using
- :meth:`~pyrogram.Client.run` this way is a friendly alternative for the much more verbose
+#. Finally, we tell Python to schedule our ``main()`` async function, which in turn will execute Pyrogram's methods.
+ Using :meth:`~pyrogram.Client.run` this way is a friendly alternative for the much more verbose
``asyncio.get_event_loop().run_until_complete(main())``:
.. code-block:: python
diff --git a/docs/source/start/updates.rst b/docs/source/start/updates.rst
index ef569bf903..a13d7fd771 100644
--- a/docs/source/start/updates.rst
+++ b/docs/source/start/updates.rst
@@ -26,8 +26,8 @@ Registering a Handler
---------------------
To explain how handlers work let's examine the one which will be in charge for handling :class:`~pyrogram.types.Message`
-updates coming from all around your chats. Every other handler shares the same setup logic; you should not have
-troubles settings them up once you learn from this section.
+updates coming from all around your chats. Every other kind of handler shares the same setup logic and you should not
+have troubles settings them up once you learn from this section.
Using Decorators
^^^^^^^^^^^^^^^^
@@ -98,3 +98,9 @@ The same about asynchronous handlers applies for :meth:`~pyrogram.Client.add_han
async def my_function(client, message):
await message.forward("me")
+
+.. note::
+
+ From now on, you'll see examples using synchronous code (i.e.: without ``async`` and ``await``, unless when actually
+ relevant). This is done to keep snippets concise and more readable. Once you get the idea behind a feature, you can
+ easily turn examples asynchronous later on.
diff --git a/docs/source/topics/create-filters.rst b/docs/source/topics/create-filters.rst
index 3e87a3deed..191eeb05b8 100644
--- a/docs/source/topics/create-filters.rst
+++ b/docs/source/topics/create-filters.rst
@@ -2,7 +2,8 @@ Creating Filters
================
Pyrogram already provides lots of built-in :class:`~pyrogram.filters` to work with, but in case you can't find a
-specific one for your needs or want to build a custom filter by yourself you can use :meth:`~pyrogram.filters.create`.
+specific one for your needs or want to build a custom filter by yourself you can use
+:meth:`filters.create() `.
.. contents:: Contents
:backlinks: none
@@ -37,29 +38,45 @@ Basic Filters
For this basic filter we will be using only the first parameter of :meth:`~pyrogram.filters.create`.
-The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries
-containing "pyrogram" as data, that is, the function *func* you pass returns True in case the callback query data
-equals to ``"pyrogram"``.
+The heart of a filter is its callback function, which accepts three arguments *(self, client, update)* and returns
+either ``True``, in case you want the update to pass the filter or ``False`` otherwise.
+
+In this example we are matching the query data to "pyrogram", which means that the filter will only allow callback
+queries containing "pyrogram" as data:
.. code-block:: python
from pyrogram import filters
- static_data_filter = filters.create(lambda _, query: query.data == "pyrogram")
+ static_data_filter = filters.create(lambda _, __, query: query.data == "pyrogram")
+
+The first two arguments of the callback function are unused here and because of this we named them using underscores.
-The ``lambda`` operator in python is used to create small anonymous functions and is perfect for this example, the same
-could be achieved with a normal function, but we don't really need it as it makes sense only inside the filter's scope:
+The ``lambda`` operator in python is used to create small anonymous functions and is perfect for this example. The same
+can be achieved with a normal function, but we don't really need it as it makes sense only inside the filter's scope:
.. code-block:: python
from pyrogram import filters
- def func(_, query):
+ def func(_, __, query):
return query.data == "pyrogram"
static_data_filter = filters.create(func)
-The filter usage remains the same:
+Asynchronous filters are also possible. Sadly, Python itself doesn't have an ``async lambda``, so we are left with
+using a named function:
+
+.. code-block:: python
+
+ from pyrogram import filters
+
+ async def func(_, __, query):
+ return query.data == "pyrogram"
+
+ static_data_filter = filters.create(func)
+
+Finally, the filter usage remains the same:
.. code-block:: python
@@ -70,8 +87,10 @@ The filter usage remains the same:
Filters with Arguments
----------------------
-A much cooler filter would be one that accepts "pyrogram" or any other data as argument at usage time.
-A dynamic filter like this will make use of named arguments for the :meth:`~pyrogram.filters.create` method.
+A much cooler filter would be one that accepts "pyrogram" or any other string as argument at usage time.
+A dynamic filter like this will make use of named arguments for the :meth:`~pyrogram.filters.create` method and the
+first argument of the callback function, which is a reference to the filter object itself holding the extra data passed
+via named arguments.
This is how a dynamic custom filter looks like:
@@ -81,14 +100,52 @@ This is how a dynamic custom filter looks like:
def dynamic_data_filter(data):
return filters.create(
- lambda flt, query: flt.data == query.data,
+ lambda flt, _, query: flt.data == query.data,
data=data # "data" kwarg is accessed with "flt.data" above
)
-And its usage:
+And its asynchronous variant:
+
+.. code-block:: python
+
+ from pyrogram import filters
+
+ def dynamic_data_filter(data):
+ async def func(flt, _, query):
+ return flt.data == query.data
+
+ # "data" kwarg is accessed with "flt.data" above
+ return filters.create(func, data=data)
+
+And finally its usage:
.. code-block:: python
@app.on_callback_query(dynamic_data_filter("pyrogram"))
def pyrogram_data(_, query):
query.answer("it works!")
+
+
+Method Calls Inside Filters
+---------------------------
+
+The missing piece we haven't covered yet is the second argument of a filter callback function, namely, the ``client``
+argument. This is a reference to the :obj:`~pyrogram.Client` instance that is running the filter and it is useful in
+case you would like to make some API calls before deciding whether the filter should allow the update or not:
+
+.. code-block:: python
+
+ def func(_, client, query):
+ # r = client.some_api_method()
+ # check response "r" and decide to return True or False
+ ...
+
+Asynchronous filters making API calls work fine as well. Just remember that you need to put ``async`` in front of
+function definitions and ``await`` in front of method calls:
+
+.. code-block:: python
+
+ async def func(_, client, query):
+ # r = await client.some_api_method()
+ # check response "r" and decide to return True or False
+ ...
\ No newline at end of file
diff --git a/pyrogram/client.py b/pyrogram/client.py
index a293efd544..ca0440aa50 100644
--- a/pyrogram/client.py
+++ b/pyrogram/client.py
@@ -58,7 +58,7 @@ class Client(Methods, Scaffold):
session_name (``str``):
Pass a string of your choice to give a name to the client session, e.g.: "*my_account*". This name will be
used to save a file on disk that stores details needed to reconnect without asking again for credentials.
- Alternatively, if you don't want a file to be saved on disk, pass the special name "**:memory:**" to start
+ Alternatively, if you don't want a file to be saved on disk, pass the special name ``":memory:"`` to start
an in-memory session that will be discarded as soon as you stop the Client. In order to reconnect again
using a memory storage without having to login again, you can use
:meth:`~pyrogram.Client.export_session_string` before stopping the client to get a session string you can
From 350ec152bccfd8529daf0d95449d09fc408c397d Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sun, 23 Aug 2020 07:35:07 +0200
Subject: [PATCH 0176/1073] .gitignore docs generated files
---
.gitignore | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/.gitignore b/.gitignore
index 357f483fbf..ff9ee02406 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,10 @@ pyrogram/raw/functions/
pyrogram/raw/types/
pyrogram/raw/base/
pyrogram/raw/all.py
+docs/source/telegram
+docs/source/api/methods/
+docs/source/api/bound-methods/
+docs/source/api/types/
# PyCharm stuff
.idea/
From 228828459cd09eb3d90952c33854927027030836 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Mon, 24 Aug 2020 09:16:25 +0200
Subject: [PATCH 0177/1073] Update FAQs
---
docs/source/faq.rst | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/docs/source/faq.rst b/docs/source/faq.rst
index a8386732ce..e3f92c1149 100644
--- a/docs/source/faq.rst
+++ b/docs/source/faq.rst
@@ -47,8 +47,9 @@ Why Pyrogram?
- **Easy**: You can install Pyrogram with pip and start building your applications right away.
- **Elegant**: Low-level details are abstracted and re-presented in a much nicer and easier way.
- **Fast**: Crypto parts are boosted up by TgCrypto_, a high-performance library written in pure C.
-- **Documented**: Pyrogram API methods, types and public interfaces are well documented.
-- **Type-hinted**: Exposed Pyrogram types and method parameters are all type-hinted.
+- **Asynchronous**: Allows both synchronous and asynchronous models to fit all usage needs.
+- **Documented**: API methods, types and public interfaces are all well documented.
+- **Type-hinted**: Types and methods are all type-hinted, enabling excellent editor support.
- **Updated**, to make use of the latest Telegram API version and features.
- **Bot API-like**: Similar to the Bot API in its simplicity, but much more powerful and detailed.
- **Pluggable**: The :doc:`Smart Plugin ` system allows to write components with minimal
From 3e3d77fdaff8874bdbcae32811af5de0f3602ac6 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Mon, 24 Aug 2020 09:20:10 +0200
Subject: [PATCH 0178/1073] Implement short-circuit evaluation for filters AND
and OR operations will not evaluate the second operand in case the first one
is, respectively, False and True.
---
pyrogram/filters.py | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/pyrogram/filters.py b/pyrogram/filters.py
index 45762aee7d..e9b177ae39 100644
--- a/pyrogram/filters.py
+++ b/pyrogram/filters.py
@@ -70,6 +70,10 @@ async def __call__(self, client: "pyrogram.Client", update: Update):
client, update
)
+ # short circuit
+ if not x:
+ return False
+
if inspect.iscoroutinefunction(self.other.__call__):
y = await self.other(client, update)
else:
@@ -97,6 +101,10 @@ async def __call__(self, client: "pyrogram.Client", update: Update):
client, update
)
+ # short circuit
+ if x:
+ return True
+
if inspect.iscoroutinefunction(self.other.__call__):
y = await self.other(client, update)
else:
From 01ec5d7f1d840e8de1a2448c6d97bebcdb1f463b Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Mon, 24 Aug 2020 09:51:21 +0200
Subject: [PATCH 0179/1073] Fix a bad docstring indentation in filters.regex
---
pyrogram/filters.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pyrogram/filters.py b/pyrogram/filters.py
index e9b177ae39..63628a60ad 100644
--- a/pyrogram/filters.py
+++ b/pyrogram/filters.py
@@ -781,8 +781,8 @@ def regex(pattern: Union[str, Pattern], flags: int = 0):
stored in the ``matches`` field of the update object itself.
Parameters:
- pattern (``str`` | ``Pattern``):
- The regex pattern as string or as pre-compiled pattern.
+ pattern (``str`` | ``Pattern``):
+ The regex pattern as string or as pre-compiled pattern.
flags (``int``, *optional*):
Regex flags.
From d86d8530ce11090e878e1c75d6225dbf3f4e1d93 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Mon, 24 Aug 2020 10:57:38 +0200
Subject: [PATCH 0180/1073] Add FAQ about PyInstaller FileNotFoundError
---
docs/source/faq.rst | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/docs/source/faq.rst b/docs/source/faq.rst
index e3f92c1149..5141b593d8 100644
--- a/docs/source/faq.rst
+++ b/docs/source/faq.rst
@@ -342,6 +342,17 @@ sqlite3.OperationalError: unable to open database file
Stackoverflow to the rescue: https://stackoverflow.com/questions/4636970
+FileNotFoundError when using PyInstaller
+----------------------------------------
+
+Pyrogram uses two files that are not Python files, which are not included automatically in the PyInstaller bundle:
+
+- ``pyrogram/mime.types``
+- ``pyrogram/storage/schema.sql``
+
+To fix the issue, you have to locate your local Pyrogram installation and pass those files to PyInstaller. More info in
+their docs https://pyinstaller.readthedocs.io/en/stable/spec-files.html#adding-files-to-the-bundle.
+
My verification code expires immediately!
-----------------------------------------
From b057dcb39db63b7fce8683aa8705dfcca02f16a9 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Mon, 24 Aug 2020 15:24:06 +0200
Subject: [PATCH 0181/1073] Small fixes around docs
---
docs/source/topics/debugging.rst | 6 +++---
pyrogram/types/object.py | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/docs/source/topics/debugging.rst b/docs/source/topics/debugging.rst
index 995ce9e5bb..ac0b396fd0 100644
--- a/docs/source/topics/debugging.rst
+++ b/docs/source/topics/debugging.rst
@@ -31,7 +31,7 @@ Consider the following code:
print(dan) # User
This will show a JSON representation of the object returned by :meth:`~pyrogram.Client.get_users`, which is a
-:class:`~pyrogram.User` instance, in this case. The output on your terminal will be something similar to this:
+:class:`~pyrogram.types.User` instance, in this case. The output on your terminal will be something similar to this:
.. code-block:: json
@@ -116,14 +116,14 @@ error. The correct way to get the object type is by using the built-in function
.. code-block:: text
-
+
And to check if an object is an instance of a given class, you use the built-in function ``isinstance()``:
.. code-block:: python
:name: this-py
- from pyrogram import UserStatus
+ from pyrogram.types import UserStatus
dan_status = dan.status
print(isinstance(dan_status, UserStatus))
diff --git a/pyrogram/types/object.py b/pyrogram/types/object.py
index 887b8e08a9..a447a0edcf 100644
--- a/pyrogram/types/object.py
+++ b/pyrogram/types/object.py
@@ -25,7 +25,7 @@
class Meta(type, metaclass=type("", (type,), {"__str__": lambda _: "~hi"})):
def __str__(self):
- return f""
+ return f""
class Object(metaclass=Meta):
From 65b5229fe8c94ea358a1d2d005a269fc5db7c7f0 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Tue, 25 Aug 2020 09:32:39 +0200
Subject: [PATCH 0182/1073] Use inspect's iscoroutinefunction, not asyncio's
---
pyrogram/client.py | 3 ++-
pyrogram/dispatcher.py | 3 ++-
pyrogram/methods/advanced/save_file.py | 3 ++-
3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/pyrogram/client.py b/pyrogram/client.py
index ca0440aa50..568496115a 100644
--- a/pyrogram/client.py
+++ b/pyrogram/client.py
@@ -18,6 +18,7 @@
import asyncio
import functools
+import inspect
import logging
import os
import re
@@ -1025,7 +1026,7 @@ async def get_file(
offset += limit
if progress:
- if asyncio.iscoroutinefunction(progress):
+ if inspect.iscoroutinefunction(progress):
await progress(
min(offset, file_size) if file_size != 0 else offset,
file_size,
diff --git a/pyrogram/dispatcher.py b/pyrogram/dispatcher.py
index 00c513496b..2541214e7b 100644
--- a/pyrogram/dispatcher.py
+++ b/pyrogram/dispatcher.py
@@ -17,6 +17,7 @@
# along with Pyrogram. If not, see .
import asyncio
+import inspect
import logging
from collections import OrderedDict
@@ -203,7 +204,7 @@ async def handler_worker(self, lock):
continue
try:
- if asyncio.iscoroutinefunction(handler.callback):
+ if inspect.iscoroutinefunction(handler.callback):
await handler.callback(self.client, *args)
else:
await self.loop.run_in_executor(
diff --git a/pyrogram/methods/advanced/save_file.py b/pyrogram/methods/advanced/save_file.py
index 4bdaedf5cb..a9bc5c79e6 100644
--- a/pyrogram/methods/advanced/save_file.py
+++ b/pyrogram/methods/advanced/save_file.py
@@ -18,6 +18,7 @@
import asyncio
import functools
+import inspect
import io
import logging
import math
@@ -182,7 +183,7 @@ async def worker(session):
file_part += 1
if progress:
- if asyncio.iscoroutinefunction(progress):
+ if inspect.iscoroutinefunction(progress):
await progress(min(file_part * part_size, file_size), file_size, *progress_args)
else:
func = functools.partial(
From 37edeb06b23b4806ee7e7fd7a88bbaaf316a1f62 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Tue, 25 Aug 2020 12:07:08 +0200
Subject: [PATCH 0183/1073] Update Pyrogram to v1.0.0
---
pyrogram/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py
index 997dfdc9ed..a0afc88f88 100644
--- a/pyrogram/__init__.py
+++ b/pyrogram/__init__.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-__version__ = "1.0.0b2"
+__version__ = "1.0.0"
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__copyright__ = "Copyright (C) 2017-2020 Dan "
From d44e92065570dfb42e5fb9599f5995d07b76db91 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Tue, 25 Aug 2020 14:08:03 +0200
Subject: [PATCH 0184/1073] Update robots.txt
---
docs/robots.txt | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/docs/robots.txt b/docs/robots.txt
index e7799fdd78..3e416f245f 100644
--- a/docs/robots.txt
+++ b/docs/robots.txt
@@ -2,7 +2,6 @@ User-agent: *
Allow: /
-Disallow: /dev*
-Disallow: /v0*
+Disallow: /old*
Sitemap: https://docs.pyrogram.org/sitemap.xml
\ No newline at end of file
From 093d1e0dcb15c931f8af7a96b095a08a44685ac0 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Tue, 25 Aug 2020 14:08:53 +0200
Subject: [PATCH 0185/1073] Fix filters.user and .chat breaking when no initial
collection is passed
---
pyrogram/handlers/handler.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyrogram/handlers/handler.py b/pyrogram/handlers/handler.py
index d4d41ea56c..1f3d2af612 100644
--- a/pyrogram/handlers/handler.py
+++ b/pyrogram/handlers/handler.py
@@ -30,7 +30,7 @@ def __init__(self, callback: Callable, filters: Filter = None):
self.filters = filters
async def check(self, client: "pyrogram.Client", update: Update):
- if self.filters:
+ if callable(self.filters):
if inspect.iscoroutinefunction(self.filters.__call__):
return await self.filters(client, update)
else:
From 1311974fde3e19addeaa80f8922536983c47356e Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Tue, 25 Aug 2020 14:17:39 +0200
Subject: [PATCH 0186/1073] Fix idle() not working in Windows - Remove
event-based idling - Add back while-true-based idling
---
pyrogram/methods/utilities/idle.py | 24 +++++++++++++-----------
1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/pyrogram/methods/utilities/idle.py b/pyrogram/methods/utilities/idle.py
index 86131ea218..044e41d11f 100644
--- a/pyrogram/methods/utilities/idle.py
+++ b/pyrogram/methods/utilities/idle.py
@@ -18,12 +18,11 @@
import asyncio
import logging
-import signal
+from signal import signal, SIGINT, SIGTERM, SIGABRT
log = logging.getLogger(__name__)
-loop = asyncio.get_event_loop()
-event = asyncio.Event()
+is_idling = False
async def idle():
@@ -64,15 +63,18 @@ async def idle():
app2.stop()
app3.stop()
"""
+ global is_idling
- def handler():
- log.info("Stop signal received")
- event.set()
+ def signal_handler(_, __):
+ global is_idling
- asyncio.get_event_loop().add_signal_handler(signal.SIGINT, handler)
+ logging.info("Stop signal received ({}). Exiting...".format(_))
+ is_idling = False
- log.info("Idle started")
- await event.wait()
+ for s in (SIGINT, SIGTERM, SIGABRT):
+ signal(s, signal_handler)
- log.info("Idle stopped")
- event.clear()
+ is_idling = True
+
+ while is_idling:
+ await asyncio.sleep(1)
From 1fbe88d4b281c19d9cb3e9ff1b50cbc23639060e Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Tue, 25 Aug 2020 14:18:29 +0200
Subject: [PATCH 0187/1073] Update Pyrogram to v1.0.1
---
pyrogram/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py
index a0afc88f88..4cfa3e5bb6 100644
--- a/pyrogram/__init__.py
+++ b/pyrogram/__init__.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-__version__ = "1.0.0"
+__version__ = "1.0.1"
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__copyright__ = "Copyright (C) 2017-2020 Dan "
From f06562b73da3bcd57da06bd68e0ea10820ab2293 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Wed, 26 Aug 2020 07:43:57 +0200
Subject: [PATCH 0188/1073] Add missing await keywords
---
pyrogram/methods/messages/edit_inline_media.py | 2 +-
pyrogram/methods/messages/edit_inline_reply_markup.py | 2 +-
pyrogram/methods/messages/edit_inline_text.py | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/pyrogram/methods/messages/edit_inline_media.py b/pyrogram/methods/messages/edit_inline_media.py
index a6a893ae5e..000a0660c3 100644
--- a/pyrogram/methods/messages/edit_inline_media.py
+++ b/pyrogram/methods/messages/edit_inline_media.py
@@ -109,7 +109,7 @@ async def edit_inline_media(
unpacked = utils.unpack_inline_message_id(inline_message_id)
dc_id = unpacked.dc_id
- session = get_session(self, dc_id)
+ session = await get_session(self, dc_id)
return await session.send(
raw.functions.messages.EditInlineBotMessage(
diff --git a/pyrogram/methods/messages/edit_inline_reply_markup.py b/pyrogram/methods/messages/edit_inline_reply_markup.py
index 9905bcf595..26fa22cf11 100644
--- a/pyrogram/methods/messages/edit_inline_reply_markup.py
+++ b/pyrogram/methods/messages/edit_inline_reply_markup.py
@@ -56,7 +56,7 @@ async def edit_inline_reply_markup(
unpacked = utils.unpack_inline_message_id(inline_message_id)
dc_id = unpacked.dc_id
- session = get_session(self, dc_id)
+ session = await get_session(self, dc_id)
return await session.send(
raw.functions.messages.EditInlineBotMessage(
diff --git a/pyrogram/methods/messages/edit_inline_text.py b/pyrogram/methods/messages/edit_inline_text.py
index c1363181c7..e6f5d11360 100644
--- a/pyrogram/methods/messages/edit_inline_text.py
+++ b/pyrogram/methods/messages/edit_inline_text.py
@@ -76,7 +76,7 @@ async def edit_inline_text(
unpacked = utils.unpack_inline_message_id(inline_message_id)
dc_id = unpacked.dc_id
- session = get_session(self, dc_id)
+ session = await get_session(self, dc_id)
return await session.send(
raw.functions.messages.EditInlineBotMessage(
From 15f504a91f87c7d911e7e63d33eb04c68708a57e Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Wed, 26 Aug 2020 08:09:12 +0200
Subject: [PATCH 0189/1073] Fix captions being "None" for inline media results
---
pyrogram/types/inline_mode/inline_query_result_animation.py | 2 +-
pyrogram/types/inline_mode/inline_query_result_photo.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/pyrogram/types/inline_mode/inline_query_result_animation.py b/pyrogram/types/inline_mode/inline_query_result_animation.py
index bd0e7037e7..72c290f007 100644
--- a/pyrogram/types/inline_mode/inline_query_result_animation.py
+++ b/pyrogram/types/inline_mode/inline_query_result_animation.py
@@ -74,7 +74,7 @@ def __init__(
id: str = None,
title: str = None,
description: str = None,
- caption: str = None,
+ caption: str = "",
parse_mode: Union[str, None] = object,
reply_markup: "types.InlineKeyboardMarkup" = None,
input_message_content: "types.InputMessageContent" = None
diff --git a/pyrogram/types/inline_mode/inline_query_result_photo.py b/pyrogram/types/inline_mode/inline_query_result_photo.py
index 7287abc017..6d6ae99d1c 100644
--- a/pyrogram/types/inline_mode/inline_query_result_photo.py
+++ b/pyrogram/types/inline_mode/inline_query_result_photo.py
@@ -74,7 +74,7 @@ def __init__(
id: str = None,
title: str = None,
description: str = None,
- caption: str = None,
+ caption: str = "",
parse_mode: Union[str, None] = object,
reply_markup: "types.InlineKeyboardMarkup" = None,
input_message_content: "types.InputMessageContent" = None
From c5dd474f935ff7df947a6a57be8ea3c8fe982c96 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Wed, 26 Aug 2020 08:10:34 +0200
Subject: [PATCH 0190/1073] Document undocumented properties
---
compiler/docs/compiler.py | 3 ++-
pyrogram/types/messages_and_media/message.py | 4 +---
pyrogram/types/user_and_chats/user.py | 5 +++++
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/compiler/docs/compiler.py b/compiler/docs/compiler.py
index 315c6b73a8..54fd9b9f13 100644
--- a/compiler/docs/compiler.py
+++ b/compiler/docs/compiler.py
@@ -416,7 +416,8 @@ def get_title_list(s: str) -> list:
title = "{}".format(type)
f2.write(title + "\n" + "=" * len(title) + "\n\n")
- f2.write(".. autoclass:: pyrogram.types.{}()".format(type))
+ f2.write(".. autoclass:: pyrogram.types.{}()\n".format(type))
+ f2.write(" :members:\n")
f.write(template.format(**fmt_keys))
diff --git a/pyrogram/types/messages_and_media/message.py b/pyrogram/types/messages_and_media/message.py
index 51bb4293d5..9950df4ac5 100644
--- a/pyrogram/types/messages_and_media/message.py
+++ b/pyrogram/types/messages_and_media/message.py
@@ -245,9 +245,6 @@ class Message(Object, Update):
Messages sent from yourself to other chats are outgoing (*outgoing* is True).
An exception is made for your own personal chat; messages sent there will be incoming.
- link (``str``):
- A link to the message, only for groups and channels.
-
matches (List of regex Matches, *optional*):
A list containing all `Match Objects `_ that match
the text of this message. Only applicable when using :obj:`Filters.regex `.
@@ -675,6 +672,7 @@ async def _parse(
@property
def link(self) -> str:
+ """Generate a link to this message, only for groups and channels."""
if self.chat.type in ("group", "supergroup", "channel") and self.chat.username:
return f"https://t.me/{self.chat.username}/{self.message_id}"
else:
diff --git a/pyrogram/types/user_and_chats/user.py b/pyrogram/types/user_and_chats/user.py
index e9a9518220..7174a3d4f6 100644
--- a/pyrogram/types/user_and_chats/user.py
+++ b/pyrogram/types/user_and_chats/user.py
@@ -192,6 +192,11 @@ def __init__(
@property
def mention(self):
+ """Generate a text mention for this user.
+
+ You can use ``user.mention()`` to mention the user using their first name (styled using html), or
+ ``user.mention("another name")`` for a custom name. To choose a different style
+ ("html" or "md"/"markdown") use ``user.mention(style="md")``."""
return Link(f"tg://user?id={self.id}", self.first_name, self._client.parse_mode)
@staticmethod
From ebf222bbb7d05abb1f8e6c229fe828e35fab2368 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Wed, 26 Aug 2020 08:12:11 +0200
Subject: [PATCH 0191/1073] Add the parameter hide_password to Client
---
pyrogram/client.py | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/pyrogram/client.py b/pyrogram/client.py
index 568496115a..688b1a5eb2 100644
--- a/pyrogram/client.py
+++ b/pyrogram/client.py
@@ -166,6 +166,11 @@ class Client(Methods, Scaffold):
request that raises a flood wait will be automatically invoked again after sleeping for the required amount
of time. Flood wait exceptions requiring higher waiting times will be raised.
Defaults to 60 (seconds).
+
+ hide_password (``bool``, *optional*):
+ Pass True to hide the password when typing it during the login.
+ Defaults to False, because ``getpass`` (the library used) is known to be problematic in some
+ terminal environments.
"""
def __init__(
@@ -192,7 +197,8 @@ def __init__(
parse_mode: str = Scaffold.PARSE_MODES[0],
no_updates: bool = None,
takeout: bool = None,
- sleep_threshold: int = Session.SLEEP_THRESHOLD
+ sleep_threshold: int = Session.SLEEP_THRESHOLD,
+ hide_password: bool = False
):
super().__init__()
@@ -220,6 +226,7 @@ def __init__(
self.no_updates = no_updates
self.takeout = takeout
self.sleep_threshold = sleep_threshold
+ self.hide_password = hide_password
self.executor = ThreadPoolExecutor(self.workers, thread_name_prefix="Handler")
@@ -328,7 +335,7 @@ async def authorize(self) -> User:
print("Password hint: {}".format(await self.get_password_hint()))
if not self.password:
- self.password = await ainput("Enter password (empty to recover): ", hide=True)
+ self.password = await ainput("Enter password (empty to recover): ", hide=self.hide_password)
try:
if not self.password:
From 7c987889f0742b5d3ed8512cdc37e4026a2ef300 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Wed, 26 Aug 2020 09:01:01 +0200
Subject: [PATCH 0192/1073] Add sleep_threshold parameter to send() method -
Decrease the default sleep threshold from 60 to 10 seconds - Use a higher
sleep threshold for generator methods
---
pyrogram/client.py | 2 +-
pyrogram/methods/advanced/send.py | 13 +++++++++++--
pyrogram/methods/chats/get_chat_members.py | 3 ++-
pyrogram/methods/chats/get_dialogs.py | 8 ++++++--
pyrogram/methods/messages/get_history.py | 5 +++--
pyrogram/methods/messages/get_messages.py | 2 +-
pyrogram/methods/messages/search_global.py | 3 ++-
pyrogram/methods/messages/search_messages.py | 3 ++-
pyrogram/methods/messages/send_media_group.py | 3 ++-
pyrogram/session/session.py | 9 ++++-----
10 files changed, 34 insertions(+), 17 deletions(-)
diff --git a/pyrogram/client.py b/pyrogram/client.py
index 688b1a5eb2..ba5cfb49ed 100644
--- a/pyrogram/client.py
+++ b/pyrogram/client.py
@@ -165,7 +165,7 @@ class Client(Methods, Scaffold):
Set a sleep threshold for flood wait exceptions happening globally in this client instance, below which any
request that raises a flood wait will be automatically invoked again after sleeping for the required amount
of time. Flood wait exceptions requiring higher waiting times will be raised.
- Defaults to 60 (seconds).
+ Defaults to 10 seconds.
hide_password (``bool``, *optional*):
Pass True to hide the password when typing it during the login.
diff --git a/pyrogram/methods/advanced/send.py b/pyrogram/methods/advanced/send.py
index fa6b9f44ce..a438a8be45 100644
--- a/pyrogram/methods/advanced/send.py
+++ b/pyrogram/methods/advanced/send.py
@@ -27,7 +27,13 @@
class Send(Scaffold):
- async def send(self, data: TLObject, retries: int = Session.MAX_RETRIES, timeout: float = Session.WAIT_TIMEOUT):
+ async def send(
+ self,
+ data: TLObject,
+ retries: int = Session.MAX_RETRIES,
+ timeout: float = Session.WAIT_TIMEOUT,
+ sleep_threshold: float = None
+ ):
"""Send raw Telegram queries.
This method makes it possible to manually call every single Telegram API method in a low-level manner.
@@ -50,6 +56,9 @@ async def send(self, data: TLObject, retries: int = Session.MAX_RETRIES, timeout
timeout (``float``):
Timeout in seconds.
+ sleep_threshold (``float``):
+ Sleep threshold in seconds.
+
Returns:
``RawType``: The raw type response generated by the query.
@@ -65,7 +74,7 @@ async def send(self, data: TLObject, retries: int = Session.MAX_RETRIES, timeout
if self.takeout_id:
data = raw.functions.InvokeWithTakeout(takeout_id=self.takeout_id, query=data)
- r = await self.session.send(data, retries, timeout, self.sleep_threshold)
+ r = await self.session.send(data, retries, timeout, sleep_threshold or self.sleep_threshold)
await self.fetch_peers(getattr(r, "users", []))
await self.fetch_peers(getattr(r, "chats", []))
diff --git a/pyrogram/methods/chats/get_chat_members.py b/pyrogram/methods/chats/get_chat_members.py
index e5a25f4191..d3e87c7d03 100644
--- a/pyrogram/methods/chats/get_chat_members.py
+++ b/pyrogram/methods/chats/get_chat_members.py
@@ -141,7 +141,8 @@ async def get_chat_members(
offset=offset,
limit=limit,
hash=0
- )
+ ),
+ sleep_threshold=60
)
members = r.participants
diff --git a/pyrogram/methods/chats/get_dialogs.py b/pyrogram/methods/chats/get_dialogs.py
index 8549fb139f..01bc0fd074 100644
--- a/pyrogram/methods/chats/get_dialogs.py
+++ b/pyrogram/methods/chats/get_dialogs.py
@@ -66,7 +66,10 @@ async def get_dialogs(
"""
if pinned_only:
- r = await self.send(raw.functions.messages.GetPinnedDialogs(folder_id=0))
+ r = await self.send(
+ raw.functions.messages.GetPinnedDialogs(folder_id=0),
+ sleep_threshold=60
+ )
else:
r = await self.send(
raw.functions.messages.GetDialogs(
@@ -76,7 +79,8 @@ async def get_dialogs(
limit=limit,
hash=0,
exclude_pinned=True
- )
+ ),
+ sleep_threshold=60
)
users = {i.id: i for i in r.users}
diff --git a/pyrogram/methods/messages/get_history.py b/pyrogram/methods/messages/get_history.py
index 00c9f435df..130c00bb12 100644
--- a/pyrogram/methods/messages/get_history.py
+++ b/pyrogram/methods/messages/get_history.py
@@ -20,7 +20,7 @@
from typing import Union, List
from pyrogram import raw
-# from pyrogram import types
+from pyrogram import types
from pyrogram import utils
from pyrogram.scaffold import Scaffold
@@ -95,7 +95,8 @@ async def get_history(
max_id=0,
min_id=0,
hash=0
- )
+ ),
+ sleep_threshold=60
)
)
diff --git a/pyrogram/methods/messages/get_messages.py b/pyrogram/methods/messages/get_messages.py
index d99bcb2f95..3503f16ade 100644
--- a/pyrogram/methods/messages/get_messages.py
+++ b/pyrogram/methods/messages/get_messages.py
@@ -111,7 +111,7 @@ async def get_messages(
else:
rpc = raw.functions.messages.GetMessages(id=ids)
- r = await self.send(rpc)
+ r = await self.send(rpc, sleep_threshold=-1)
messages = await utils.parse_messages(self, r, replies=replies)
diff --git a/pyrogram/methods/messages/search_global.py b/pyrogram/methods/messages/search_global.py
index 60c0c752ab..17f6d445cf 100644
--- a/pyrogram/methods/messages/search_global.py
+++ b/pyrogram/methods/messages/search_global.py
@@ -74,7 +74,8 @@ async def search_global(
offset_peer=offset_peer,
offset_id=offset_id,
limit=limit
- )
+ ),
+ sleep_threshold=60
),
replies=0
)
diff --git a/pyrogram/methods/messages/search_messages.py b/pyrogram/methods/messages/search_messages.py
index 44132dcef0..8744fe8118 100644
--- a/pyrogram/methods/messages/search_messages.py
+++ b/pyrogram/methods/messages/search_messages.py
@@ -80,7 +80,8 @@ async def get_chunk(
else None
),
hash=0
- )
+ ),
+ sleep_threshold=60
)
return await utils.parse_messages(client, r)
diff --git a/pyrogram/methods/messages/send_media_group.py b/pyrogram/methods/messages/send_media_group.py
index 6c9bd04d4f..e35984b868 100644
--- a/pyrogram/methods/messages/send_media_group.py
+++ b/pyrogram/methods/messages/send_media_group.py
@@ -176,7 +176,8 @@ async def send_media_group(
multi_media=multi_media,
silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id
- )
+ ),
+ sleep_threshold=60
)
return await utils.parse_messages(
diff --git a/pyrogram/session/session.py b/pyrogram/session/session.py
index b25b216689..bca1dc8f71 100644
--- a/pyrogram/session/session.py
+++ b/pyrogram/session/session.py
@@ -18,12 +18,11 @@
import asyncio
import logging
-import time
+import os
from concurrent.futures.thread import ThreadPoolExecutor
from datetime import datetime, timedelta
from hashlib import sha1
from io import BytesIO
-import os
import pyrogram
from pyrogram import __copyright__, __license__, __version__
@@ -32,7 +31,7 @@
from pyrogram.crypto import mtproto
from pyrogram.errors import RPCError, InternalServerError, AuthKeyDuplicated, FloodWait
from pyrogram.raw.all import layer
-from pyrogram.raw.core import TLObject, MsgContainer, Int, Long, FutureSalt, FutureSalts
+from pyrogram.raw.core import TLObject, MsgContainer, Int, FutureSalt, FutureSalts
from .internals import MsgId, MsgFactory
log = logging.getLogger(__name__)
@@ -48,7 +47,7 @@ class Session:
INITIAL_SALT = 0x616e67656c696361
START_TIMEOUT = 1
WAIT_TIMEOUT = 15
- SLEEP_THRESHOLD = 60
+ SLEEP_THRESHOLD = 10
MAX_RETRIES = 5
ACKS_THRESHOLD = 8
PING_INTERVAL = 5
@@ -443,7 +442,7 @@ async def send(
except FloodWait as e:
amount = e.x
- if amount > sleep_threshold:
+ if amount > sleep_threshold > 0:
raise
log.warning(f'[{self.client.session_name}] Sleeping for {amount}s (required by "{query}")')
From f909e1e4ea53126944b44b727011bc6c4f94885f Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Wed, 26 Aug 2020 09:07:26 +0200
Subject: [PATCH 0193/1073] Fix "invalid escape" warnings
---
pyrogram/methods/advanced/save_file.py | 4 ++--
pyrogram/methods/messages/download_media.py | 4 ++--
pyrogram/methods/messages/send_animation.py | 4 ++--
pyrogram/methods/messages/send_audio.py | 4 ++--
pyrogram/methods/messages/send_document.py | 4 ++--
pyrogram/methods/messages/send_photo.py | 4 ++--
pyrogram/methods/messages/send_sticker.py | 4 ++--
pyrogram/methods/messages/send_video.py | 4 ++--
pyrogram/methods/messages/send_video_note.py | 4 ++--
pyrogram/methods/messages/send_voice.py | 4 ++--
10 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/pyrogram/methods/advanced/save_file.py b/pyrogram/methods/advanced/save_file.py
index a9bc5c79e6..9d77073365 100644
--- a/pyrogram/methods/advanced/save_file.py
+++ b/pyrogram/methods/advanced/save_file.py
@@ -82,8 +82,8 @@ async def save_file(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
``InputFile``: On success, the uploaded file is returned in form of an InputFile object.
diff --git a/pyrogram/methods/messages/download_media.py b/pyrogram/methods/messages/download_media.py
index 24092caca7..cf63c74caa 100644
--- a/pyrogram/methods/messages/download_media.py
+++ b/pyrogram/methods/messages/download_media.py
@@ -107,8 +107,8 @@ async def download_media(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
``str`` | ``None``: On success, the absolute path of the downloaded file is returned, otherwise, in case
diff --git a/pyrogram/methods/messages/send_animation.py b/pyrogram/methods/messages/send_animation.py
index 9851c11bef..896ed5c593 100644
--- a/pyrogram/methods/messages/send_animation.py
+++ b/pyrogram/methods/messages/send_animation.py
@@ -139,8 +139,8 @@ async def send_animation(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
:obj:`~pyrogram.types.Message` | ``None``: On success, the sent animation message is returned, otherwise,
diff --git a/pyrogram/methods/messages/send_audio.py b/pyrogram/methods/messages/send_audio.py
index fc5213cc9a..45204716d9 100644
--- a/pyrogram/methods/messages/send_audio.py
+++ b/pyrogram/methods/messages/send_audio.py
@@ -135,8 +135,8 @@ async def send_audio(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
:obj:`~pyrogram.types.Message` | ``None``: On success, the sent audio message is returned, otherwise, in
diff --git a/pyrogram/methods/messages/send_document.py b/pyrogram/methods/messages/send_document.py
index 0c77a94086..0e5203da1b 100644
--- a/pyrogram/methods/messages/send_document.py
+++ b/pyrogram/methods/messages/send_document.py
@@ -122,8 +122,8 @@ async def send_document(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
:obj:`~pyrogram.types.Message` | ``None``: On success, the sent document message is returned, otherwise, in
diff --git a/pyrogram/methods/messages/send_photo.py b/pyrogram/methods/messages/send_photo.py
index 06a6688be1..d6e65acf90 100644
--- a/pyrogram/methods/messages/send_photo.py
+++ b/pyrogram/methods/messages/send_photo.py
@@ -116,8 +116,8 @@ async def send_photo(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
:obj:`~pyrogram.types.Message` | ``None``: On success, the sent photo message is returned, otherwise, in
diff --git a/pyrogram/methods/messages/send_sticker.py b/pyrogram/methods/messages/send_sticker.py
index 6ab211f894..565e3420da 100644
--- a/pyrogram/methods/messages/send_sticker.py
+++ b/pyrogram/methods/messages/send_sticker.py
@@ -98,8 +98,8 @@ async def send_sticker(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
:obj:`~pyrogram.types.Message` | ``None``: On success, the sent sticker message is returned, otherwise,
diff --git a/pyrogram/methods/messages/send_video.py b/pyrogram/methods/messages/send_video.py
index 3b2bc03eb2..9185d64bd1 100644
--- a/pyrogram/methods/messages/send_video.py
+++ b/pyrogram/methods/messages/send_video.py
@@ -139,8 +139,8 @@ async def send_video(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
:obj:`~pyrogram.types.Message` | ``None``: On success, the sent video message is returned, otherwise, in
diff --git a/pyrogram/methods/messages/send_video_note.py b/pyrogram/methods/messages/send_video_note.py
index 82a3688bd3..d40335afcf 100644
--- a/pyrogram/methods/messages/send_video_note.py
+++ b/pyrogram/methods/messages/send_video_note.py
@@ -112,8 +112,8 @@ async def send_video_note(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
:obj:`~pyrogram.types.Message` | ``None``: On success, the sent video note message is returned, otherwise,
diff --git a/pyrogram/methods/messages/send_voice.py b/pyrogram/methods/messages/send_voice.py
index 58d401d79d..0bbf72e671 100644
--- a/pyrogram/methods/messages/send_voice.py
+++ b/pyrogram/methods/messages/send_voice.py
@@ -114,8 +114,8 @@ async def send_voice(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
:obj:`~pyrogram.types.Message` | ``None``: On success, the sent voice message is returned, otherwise, in
From bab9359df843ceacf944e7e16571e575c8f77913 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Wed, 26 Aug 2020 09:07:54 +0200
Subject: [PATCH 0194/1073] Use a better way to document properties
---
compiler/docs/compiler.py | 1 -
pyrogram/types/messages_and_media/message.py | 40 ++++++++++----------
pyrogram/types/user_and_chats/user.py | 11 +++---
3 files changed, 27 insertions(+), 25 deletions(-)
diff --git a/compiler/docs/compiler.py b/compiler/docs/compiler.py
index 54fd9b9f13..fdb4972dab 100644
--- a/compiler/docs/compiler.py
+++ b/compiler/docs/compiler.py
@@ -417,7 +417,6 @@ def get_title_list(s: str) -> list:
f2.write(title + "\n" + "=" * len(title) + "\n\n")
f2.write(".. autoclass:: pyrogram.types.{}()\n".format(type))
- f2.write(" :members:\n")
f.write(template.format(**fmt_keys))
diff --git a/pyrogram/types/messages_and_media/message.py b/pyrogram/types/messages_and_media/message.py
index 9950df4ac5..0fad3f4175 100644
--- a/pyrogram/types/messages_and_media/message.py
+++ b/pyrogram/types/messages_and_media/message.py
@@ -257,6 +257,9 @@ class Message(Object, Update):
reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*):
Additional interface options. An object for an inline keyboard, custom reply keyboard,
instructions to remove reply keyboard or to force a reply from the user.
+
+ link (``str``, *property*):
+ Generate a link to this message, only for groups and channels.
"""
# TODO: Add game missing field. Also invoice, successful_payment, connected_website
@@ -672,7 +675,6 @@ async def _parse(
@property
def link(self) -> str:
- """Generate a link to this message, only for groups and channels."""
if self.chat.type in ("group", "supergroup", "channel") and self.chat.username:
return f"https://t.me/{self.chat.username}/{self.message_id}"
else:
@@ -868,8 +870,8 @@ async def reply_animation(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
On success, the sent :obj:`~pyrogram.types.Message` is returned.
@@ -1011,8 +1013,8 @@ async def reply_audio(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
On success, the sent :obj:`~pyrogram.types.Message` is returned.
@@ -1355,8 +1357,8 @@ async def reply_document(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
On success, the sent :obj:`~pyrogram.types.Message` is returned.
@@ -1756,8 +1758,8 @@ async def reply_photo(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
On success, the sent :obj:`~pyrogram.types.Message` is returned.
@@ -1940,8 +1942,8 @@ async def reply_sticker(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
On success, the sent :obj:`~pyrogram.types.Message` is returned.
@@ -2179,8 +2181,8 @@ async def reply_video(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
On success, the sent :obj:`~pyrogram.types.Message` is returned.
@@ -2307,8 +2309,8 @@ async def reply_video_note(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
On success, the sent :obj:`~pyrogram.types.Message` is returned.
@@ -2432,8 +2434,8 @@ async def reply_voice(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
On success, the sent :obj:`~pyrogram.types.Message` is returned.
@@ -3052,8 +3054,8 @@ async def download(
The total size of the file.
*args (``tuple``, *optional*):
- Extra custom arguments as defined in the *progress_args* parameter.
- You can either keep *\*args* or add every single extra argument in your function signature.
+ Extra custom arguments as defined in the ``progress_args`` parameter.
+ You can either keep ``*args`` or add every single extra argument in your function signature.
Returns:
On success, the absolute path of the downloaded file as string is returned, None otherwise.
diff --git a/pyrogram/types/user_and_chats/user.py b/pyrogram/types/user_and_chats/user.py
index 7174a3d4f6..f159576038 100644
--- a/pyrogram/types/user_and_chats/user.py
+++ b/pyrogram/types/user_and_chats/user.py
@@ -138,6 +138,12 @@ class User(Object, Update):
restrictions (List of :obj:`~pyrogram.types.Restriction`, *optional*):
The list of reasons why this bot might be unavailable to some users.
This field is available only in case *is_restricted* is True.
+
+ mention (``str``, *property*):
+ Generate a text mention for this user.
+ You can use ``user.mention()`` to mention the user using their first name (styled using html), or
+ ``user.mention("another name")`` for a custom name. To choose a different style
+ ("html" or "md"/"markdown") use ``user.mention(style="md")``.
"""
def __init__(
@@ -192,11 +198,6 @@ def __init__(
@property
def mention(self):
- """Generate a text mention for this user.
-
- You can use ``user.mention()`` to mention the user using their first name (styled using html), or
- ``user.mention("another name")`` for a custom name. To choose a different style
- ("html" or "md"/"markdown") use ``user.mention(style="md")``."""
return Link(f"tg://user?id={self.id}", self.first_name, self._client.parse_mode)
@staticmethod
From 7719c49062d50244409173c19eca7010a6e10ea5 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Wed, 26 Aug 2020 09:14:24 +0200
Subject: [PATCH 0195/1073] Update Pyrogram to v1.0.2
---
pyrogram/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py
index 4cfa3e5bb6..08003aeba2 100644
--- a/pyrogram/__init__.py
+++ b/pyrogram/__init__.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-__version__ = "1.0.1"
+__version__ = "1.0.2"
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__copyright__ = "Copyright (C) 2017-2020 Dan "
From eed3221ecb602f5c1c733b63942d1c0a9b1597e1 Mon Sep 17 00:00:00 2001
From: Mahesh0253 <44301650+Mahesh0253@users.noreply.github.com>
Date: Wed, 26 Aug 2020 23:16:19 +0530
Subject: [PATCH 0196/1073] Fixed bad f-string (#476)
---
pyrogram/parser/html.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyrogram/parser/html.py b/pyrogram/parser/html.py
index 7fa1d94d2e..7be5dc956c 100644
--- a/pyrogram/parser/html.py
+++ b/pyrogram/parser/html.py
@@ -155,7 +155,7 @@ def unparse(text: str, entities: list):
if entity_type in ("bold", "italic", "underline", "strike"):
start_tag = f"<{entity_type[0]}>"
- end_tag = "f{entity_type[0]}>"
+ end_tag = f"{entity_type[0]}>"
elif entity_type in ("code", "pre", "blockquote"):
start_tag = f"<{entity_type}>"
end_tag = f"{entity_type}>"
From 582e29dece1ae1a682e4311f8219db47f77de055 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 27 Aug 2020 10:59:28 +0200
Subject: [PATCH 0197/1073] Allow passing sleep_threshold=0 to always raise
flood waits
---
pyrogram/session/session.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyrogram/session/session.py b/pyrogram/session/session.py
index bca1dc8f71..3aecaab3af 100644
--- a/pyrogram/session/session.py
+++ b/pyrogram/session/session.py
@@ -442,7 +442,7 @@ async def send(
except FloodWait as e:
amount = e.x
- if amount > sleep_threshold > 0:
+ if amount > sleep_threshold >= 0:
raise
log.warning(f'[{self.client.session_name}] Sleeping for {amount}s (required by "{query}")')
From d489157f224bf5e5b20ad0f9c15eb5f42654aefc Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 27 Aug 2020 11:08:22 +0200
Subject: [PATCH 0198/1073] Update Pyrogram to v1.0.3
---
pyrogram/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py
index 08003aeba2..898a5f377d 100644
--- a/pyrogram/__init__.py
+++ b/pyrogram/__init__.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-__version__ = "1.0.2"
+__version__ = "1.0.3"
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__copyright__ = "Copyright (C) 2017-2020 Dan "
From c0049ba43b346e734e1916edc35068ce5627efff Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 27 Aug 2020 14:12:28 +0200
Subject: [PATCH 0199/1073] Strictly check if sleep_threshold is None
---
pyrogram/methods/advanced/send.py | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/pyrogram/methods/advanced/send.py b/pyrogram/methods/advanced/send.py
index a438a8be45..661d1be7e0 100644
--- a/pyrogram/methods/advanced/send.py
+++ b/pyrogram/methods/advanced/send.py
@@ -74,7 +74,12 @@ async def send(
if self.takeout_id:
data = raw.functions.InvokeWithTakeout(takeout_id=self.takeout_id, query=data)
- r = await self.session.send(data, retries, timeout, sleep_threshold or self.sleep_threshold)
+ r = await self.session.send(
+ data, retries, timeout,
+ (sleep_threshold
+ if sleep_threshold is not None
+ else self.sleep_threshold)
+ )
await self.fetch_peers(getattr(r, "users", []))
await self.fetch_peers(getattr(r, "chats", []))
From 50c620709923340cda8cc80a099cb45ea4dac6bf Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 27 Aug 2020 14:12:51 +0200
Subject: [PATCH 0200/1073] Actually fix inline callback queries coming from
different DCs
---
pyrogram/methods/messages/edit_inline_media.py | 3 ++-
pyrogram/methods/messages/edit_inline_reply_markup.py | 3 ++-
pyrogram/methods/messages/edit_inline_text.py | 3 ++-
pyrogram/methods/messages/inline_session.py | 2 +-
4 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/pyrogram/methods/messages/edit_inline_media.py b/pyrogram/methods/messages/edit_inline_media.py
index 000a0660c3..f607462d34 100644
--- a/pyrogram/methods/messages/edit_inline_media.py
+++ b/pyrogram/methods/messages/edit_inline_media.py
@@ -117,5 +117,6 @@ async def edit_inline_media(
media=media,
reply_markup=reply_markup.write() if reply_markup else None,
**await self.parser.parse(caption, parse_mode)
- )
+ ),
+ sleep_threshold=self.sleep_threshold
)
diff --git a/pyrogram/methods/messages/edit_inline_reply_markup.py b/pyrogram/methods/messages/edit_inline_reply_markup.py
index 26fa22cf11..8213c86e47 100644
--- a/pyrogram/methods/messages/edit_inline_reply_markup.py
+++ b/pyrogram/methods/messages/edit_inline_reply_markup.py
@@ -62,5 +62,6 @@ async def edit_inline_reply_markup(
raw.functions.messages.EditInlineBotMessage(
id=unpacked,
reply_markup=reply_markup.write() if reply_markup else None,
- )
+ ),
+ sleep_threshold=self.sleep_threshold
)
diff --git a/pyrogram/methods/messages/edit_inline_text.py b/pyrogram/methods/messages/edit_inline_text.py
index e6f5d11360..4558da57d6 100644
--- a/pyrogram/methods/messages/edit_inline_text.py
+++ b/pyrogram/methods/messages/edit_inline_text.py
@@ -84,5 +84,6 @@ async def edit_inline_text(
no_webpage=disable_web_page_preview or None,
reply_markup=reply_markup.write() if reply_markup else None,
**await self.parser.parse(text, parse_mode)
- )
+ ),
+ sleep_threshold=self.sleep_threshold
)
diff --git a/pyrogram/methods/messages/inline_session.py b/pyrogram/methods/messages/inline_session.py
index 681ea14fed..4ad7201068 100644
--- a/pyrogram/methods/messages/inline_session.py
+++ b/pyrogram/methods/messages/inline_session.py
@@ -51,7 +51,7 @@ async def get_session(client: "pyrogram.Client", dc_id: int):
await session.start()
for _ in range(3):
- exported_auth = await session.send(
+ exported_auth = await client.send(
raw.functions.auth.ExportAuthorization(
dc_id=dest_dc_id
)
From d385aae1d2571efaa0c7dbd6084c5dd656503f1d Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 27 Aug 2020 14:20:30 +0200
Subject: [PATCH 0201/1073] Types don't need to inherit from TLObject
---
compiler/api/template/type.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/compiler/api/template/type.txt b/compiler/api/template/type.txt
index 4dd6a2503b..3d327282fd 100644
--- a/compiler/api/template/type.txt
+++ b/compiler/api/template/type.txt
@@ -10,7 +10,7 @@ from pyrogram.raw.core import TLObject
# noinspection PyRedeclaration
-class {name}(TLObject): # type: ignore
+class {name}: # type: ignore
"""{docstring}
"""
From cecf5a19a4fad8daf66f9b1c5a53de0b9125c0b0 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 27 Aug 2020 14:32:25 +0200
Subject: [PATCH 0202/1073] Add dc_id to Chat objects
---
pyrogram/types/user_and_chats/chat.py | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/pyrogram/types/user_and_chats/chat.py b/pyrogram/types/user_and_chats/chat.py
index a0f40eed58..8ae130c6a2 100644
--- a/pyrogram/types/user_and_chats/chat.py
+++ b/pyrogram/types/user_and_chats/chat.py
@@ -70,6 +70,12 @@ class Chat(Object):
Bio, for private chats and bots or description for groups, supergroups and channels.
Returned only in :meth:`~pyrogram.Client.get_chat`.
+ dc_id (``int``, *optional*):
+ The chat assigned DC (data center). Available only in case the chat has a photo.
+ Note that this information is approximate; it is based on where Telegram stores the current chat photo.
+ It is accurate only in case the owner has set the chat photo, otherwise the dc_id will be the one assigned
+ to the administrator who set the current chat photo.
+
invite_link (``str``, *optional*):
Chat invite link, for groups, supergroups and channels.
Returned only in :meth:`~pyrogram.Client.get_chat`.
@@ -121,6 +127,7 @@ def __init__(
last_name: str = None,
photo: "types.ChatPhoto" = None,
description: str = None,
+ dc_id: int = None,
invite_link: str = None,
pinned_message=None,
sticker_set_name: str = None,
@@ -146,6 +153,7 @@ def __init__(
self.last_name = last_name
self.photo = photo
self.description = description
+ self.dc_id = dc_id
self.invite_link = invite_link
self.pinned_message = pinned_message
self.sticker_set_name = sticker_set_name
@@ -172,6 +180,7 @@ def _parse_user_chat(client, user: raw.types.User) -> "Chat":
last_name=user.last_name,
photo=types.ChatPhoto._parse(client, user.photo, peer_id, user.access_hash),
restrictions=types.List([types.Restriction._parse(r) for r in user.restriction_reason]) or None,
+ dc_id=getattr(user.photo, "dc_id", None),
client=client
)
@@ -187,6 +196,7 @@ def _parse_chat_chat(client, chat: raw.types.Chat) -> "Chat":
photo=types.ChatPhoto._parse(client, getattr(chat, "photo", None), peer_id, 0),
permissions=types.ChatPermissions._parse(getattr(chat, "default_banned_rights", None)),
members_count=getattr(chat, "participants_count", None),
+ dc_id=getattr(chat.photo, "dc_id", None),
client=client
)
@@ -208,6 +218,7 @@ def _parse_channel_chat(client, channel: raw.types.Channel) -> "Chat":
restrictions=types.List([types.Restriction._parse(r) for r in restriction_reason]) or None,
permissions=types.ChatPermissions._parse(getattr(channel, "default_banned_rights", None)),
members_count=getattr(channel, "participants_count", None),
+ dc_id=getattr(channel.photo, "dc_id", None),
client=client
)
From 899bd7bda3c9efc17c3c6336d3c433bd5aeed630 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 27 Aug 2020 14:33:04 +0200
Subject: [PATCH 0203/1073] Update Pyrogram to v1.0.4
---
pyrogram/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py
index 898a5f377d..194c38a3fd 100644
--- a/pyrogram/__init__.py
+++ b/pyrogram/__init__.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-__version__ = "1.0.3"
+__version__ = "1.0.4"
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__copyright__ = "Copyright (C) 2017-2020 Dan "
From 4dd068643da09642384483aab922787a61fa46c4 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 29 Aug 2020 15:11:21 +0200
Subject: [PATCH 0204/1073] Fix get_profile_photos not working properly in
channels
---
pyrogram/methods/users/get_profile_photos.py | 22 ++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/pyrogram/methods/users/get_profile_photos.py b/pyrogram/methods/users/get_profile_photos.py
index b27687a14f..8a222564f2 100644
--- a/pyrogram/methods/users/get_profile_photos.py
+++ b/pyrogram/methods/users/get_profile_photos.py
@@ -65,6 +65,14 @@ async def get_profile_photos(
peer_id = await self.resolve_peer(chat_id)
if isinstance(peer_id, raw.types.InputPeerChannel):
+ r = await self.send(
+ raw.functions.channels.GetFullChannel(
+ channel=peer_id
+ )
+ )
+
+ current = types.Photo._parse(self, r.full_chat.chat_photo) or []
+
r = await utils.parse_messages(
self,
await self.send(
@@ -75,7 +83,7 @@ async def get_profile_photos(
min_date=0,
max_date=0,
offset_id=0,
- add_offset=offset,
+ add_offset=0,
limit=limit,
max_id=0,
min_id=0,
@@ -84,7 +92,17 @@ async def get_profile_photos(
)
)
- return types.List([message.new_chat_photo for message in r][:limit])
+ extra = [message.new_chat_photo for message in r]
+
+ if extra:
+ if current:
+ photos = ([current] + extra) if current.file_id != extra[0].file_id else extra
+ else:
+ photos = extra
+ else:
+ photos = [current]
+
+ return types.List(photos[offset:limit])
else:
r = await self.send(
raw.functions.photos.GetUserPhotos(
From 22d9077e2bb11e350d9a408aedbe29b60e9c0373 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 29 Aug 2020 15:12:45 +0200
Subject: [PATCH 0205/1073] Warn users in case they try to use base types as
arguments
---
compiler/api/compiler.py | 3 ++-
compiler/api/template/type.txt | 6 ++++++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/compiler/api/compiler.py b/compiler/api/compiler.py
index e956085f32..6c3dcb27ec 100644
--- a/compiler/api/compiler.py
+++ b/compiler/api/compiler.py
@@ -336,7 +336,8 @@ def start(format: bool = False):
docstring=docstring,
name=type,
qualname=qualtype,
- types=", ".join([f"raw.types.{c}" for c in constructors])
+ types=", ".join([f"raw.types.{c}" for c in constructors]),
+ doc_name=snake(type).replace("_", "-")
)
)
diff --git a/compiler/api/template/type.txt b/compiler/api/template/type.txt
index 3d327282fd..99310359d5 100644
--- a/compiler/api/template/type.txt
+++ b/compiler/api/template/type.txt
@@ -15,3 +15,9 @@ class {name}: # type: ignore
"""
QUALNAME = "pyrogram.raw.base.{qualname}"
+
+ def __init__(self):
+ raise TypeError("Base types can only be used for type checking purposes: "
+ "you tried to use a base type instance as argument, "
+ "but you need to instantiate one of its constructors instead. "
+ "More info: https://docs.pyrogram.org/telegram/base/{doc_name}")
From 92bc59e688d46638fd609baf3dcbb20419c68022 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 29 Aug 2020 15:46:39 +0200
Subject: [PATCH 0206/1073] Fix dispatcher not obeying to the INFO logging
level
---
pyrogram/dispatcher.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pyrogram/dispatcher.py b/pyrogram/dispatcher.py
index 2541214e7b..db3344da93 100644
--- a/pyrogram/dispatcher.py
+++ b/pyrogram/dispatcher.py
@@ -119,7 +119,7 @@ async def start(self):
self.loop.create_task(self.handler_worker(self.locks_list[-1]))
)
- logging.info(f"Started {self.client.workers} HandlerTasks")
+ log.info(f"Started {self.client.workers} HandlerTasks")
async def stop(self):
if not self.client.no_updates:
@@ -132,7 +132,7 @@ async def stop(self):
self.handler_worker_tasks.clear()
self.groups.clear()
- logging.info(f"Stopped {self.client.workers} HandlerTasks")
+ log.info(f"Stopped {self.client.workers} HandlerTasks")
def add_handler(self, handler, group: int):
async def fn():
From c689273167d6cb23ba881edfd32ed12e2321bdb7 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 29 Aug 2020 15:50:36 +0200
Subject: [PATCH 0207/1073] Add force_document argument for send_document
---
pyrogram/methods/messages/send_document.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/pyrogram/methods/messages/send_document.py b/pyrogram/methods/messages/send_document.py
index 0e5203da1b..0ee814a587 100644
--- a/pyrogram/methods/messages/send_document.py
+++ b/pyrogram/methods/messages/send_document.py
@@ -38,6 +38,7 @@ async def send_document(
caption: str = "",
parse_mode: Union[str, None] = object,
file_name: str = None,
+ force_document: bool = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
schedule_date: int = None,
@@ -89,6 +90,11 @@ async def send_document(
File name of the document sent.
Defaults to file's path basename.
+ force_document (``bool``, *optional*):
+ Pass True to force sending files as document. Useful for video files that need to be sent as
+ document messages instead of video messages.
+ Defaults to False.
+
disable_notification (``bool``, *optional*):
Sends the message silently.
Users will receive a notification with no sound.
@@ -157,7 +163,7 @@ def progress(current, total):
media = raw.types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(document) or "application/zip",
file=file,
- force_file=True,
+ force_file=force_document or None,
thumb=thumb,
attributes=[
raw.types.DocumentAttributeFilename(file_name=file_name or os.path.basename(document))
From 5e3f2ab94795bacbad6b56febb1a6b16938f355c Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 29 Aug 2020 16:58:49 +0200
Subject: [PATCH 0208/1073] Replace monotonic() with perf_counter() It seems
like monotonic() goes out of sync after some time.
---
pyrogram/session/internals/msg_id.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/pyrogram/session/internals/msg_id.py b/pyrogram/session/internals/msg_id.py
index 72b8e81f02..95155d3c85 100644
--- a/pyrogram/session/internals/msg_id.py
+++ b/pyrogram/session/internals/msg_id.py
@@ -18,19 +18,19 @@
import logging
from datetime import datetime
-from time import monotonic
+from time import perf_counter
log = logging.getLogger(__name__)
class MsgId:
- reference_clock = monotonic()
+ reference_clock = perf_counter()
last_time = 0
msg_id_offset = 0
server_time = 0
def __new__(cls) -> int:
- now = monotonic() - cls.reference_clock + cls.server_time
+ now = perf_counter() - cls.reference_clock + cls.server_time
cls.msg_id_offset = cls.msg_id_offset + 4 if now == cls.last_time else 0
msg_id = int(now * 2 ** 32) + cls.msg_id_offset
cls.last_time = now
From 2c99926825bdc45f7808711efa4b155653f07339 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 29 Aug 2020 16:59:30 +0200
Subject: [PATCH 0209/1073] Update Pyrogram to v1.0.5
---
pyrogram/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py
index 194c38a3fd..32d4a5166c 100644
--- a/pyrogram/__init__.py
+++ b/pyrogram/__init__.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-__version__ = "1.0.4"
+__version__ = "1.0.5"
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__copyright__ = "Copyright (C) 2017-2020 Dan "
From 71bdfe6c407e0622cc337f51dc8383abc89880e4 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 29 Aug 2020 17:26:16 +0200
Subject: [PATCH 0210/1073] Fix get_profile_photos not working correctly in
case of no chat photos
---
pyrogram/methods/users/get_profile_photos.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/pyrogram/methods/users/get_profile_photos.py b/pyrogram/methods/users/get_profile_photos.py
index 8a222564f2..6ccfb8f8cf 100644
--- a/pyrogram/methods/users/get_profile_photos.py
+++ b/pyrogram/methods/users/get_profile_photos.py
@@ -100,7 +100,10 @@ async def get_profile_photos(
else:
photos = extra
else:
- photos = [current]
+ if current:
+ photos = [current]
+ else:
+ photos = []
return types.List(photos[offset:limit])
else:
From 15bdb3de4fdafc39ed88b4bad7732c1d7af8e40b Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 29 Aug 2020 17:28:39 +0200
Subject: [PATCH 0211/1073] Attempt to fix clock issues when running on AWS
Lambda
---
pyrogram/session/internals/msg_id.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/pyrogram/session/internals/msg_id.py b/pyrogram/session/internals/msg_id.py
index 95155d3c85..384a3e504f 100644
--- a/pyrogram/session/internals/msg_id.py
+++ b/pyrogram/session/internals/msg_id.py
@@ -24,7 +24,7 @@
class MsgId:
- reference_clock = perf_counter()
+ reference_clock = 0
last_time = 0
msg_id_offset = 0
server_time = 0
@@ -40,5 +40,6 @@ def __new__(cls) -> int:
@classmethod
def set_server_time(cls, server_time: int):
if not cls.server_time:
+ cls.reference_clock = perf_counter()
cls.server_time = server_time
log.info(f"Time synced: {datetime.utcfromtimestamp(server_time)} UTC")
From 84f6973bbb4693572510fdc4ea55d4386c68d0a5 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 29 Aug 2020 17:28:55 +0200
Subject: [PATCH 0212/1073] Update Pyrogram to v1.0.6
---
pyrogram/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py
index 32d4a5166c..f967dfc595 100644
--- a/pyrogram/__init__.py
+++ b/pyrogram/__init__.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-__version__ = "1.0.5"
+__version__ = "1.0.6"
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__copyright__ = "Copyright (C) 2017-2020 Dan "
From 352ea594834d12cafa8375047f9bc97f7f259992 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 29 Aug 2020 17:37:08 +0200
Subject: [PATCH 0213/1073] Update bug_report.md
---
.github/ISSUE_TEMPLATE/bug_report.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 6a2c6e7999..c46b935a5e 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -8,7 +8,7 @@ about: Create a bug report affecting the library
## Checklist
- [ ] I am sure the error is coming from Pyrogram's code and not elsewhere.
- [ ] I have searched in the issue tracker for similar bug reports, including closed ones.
-- [ ] I ran `pip3 install -U https://github.com/pyrogram/pyrogram/archive/develop.zip` and reproduced the issue using the latest development version.
+- [ ] I ran `pip3 install -U https://github.com/pyrogram/pyrogram/archive/master.zip` and reproduced the issue using the latest development version.
## Description
A clear and concise description of the problem.
From ecdba6be6f634354b13b5fac0f97205eb23fc705 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 29 Aug 2020 20:52:09 +0200
Subject: [PATCH 0214/1073] Add a new way to support Pyrogram - Add Hetzner
link for cloud credits.
---
docs/source/index.rst | 7 +++++++
docs/source/support-pyrogram.rst | 8 ++++++++
2 files changed, 15 insertions(+)
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 0fda6da652..18c69412b8 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -53,6 +53,13 @@ Contents are organized into sections composed of self-contained topics which can
following them in order using the :guilabel:`Next` button at the end of each page. Here below you can, instead, find a
list of the most relevant pages for a quick access.
+.. admonition :: Cloud Credits
+ :class: attention
+
+ If you need a cloud server to host your applications, we recommend using **Hetzner Cloud**. Sign up with
+ `this link `_ to get €20 in cloud credits and help support Pyrogram as
+ well.
+
First Steps
^^^^^^^^^^^
diff --git a/docs/source/support-pyrogram.rst b/docs/source/support-pyrogram.rst
index 2505585e96..aa662d49e8 100644
--- a/docs/source/support-pyrogram.rst
+++ b/docs/source/support-pyrogram.rst
@@ -11,6 +11,13 @@ found it to be useful, give Pyrogram a `Star on GitHub`_. Your appreciation mean
-----
+Cloud Credits
+-------------
+
+If you need a cloud server to host your applications, try **Hetzner Cloud**. You can sign up with
+`this link `_ to get €20 in cloud credits and help support Pyrogram and
+my `other projects`_.
+
Donate
------
@@ -25,5 +32,6 @@ PayPal button below. Thank you!
--- `Dan`_
.. _Star on GitHub: https://github.com/pyrogram/pyrogram
+.. _other projects: https://github.com/delivrance
.. _other works: https://github.com/delivrance
.. _Dan: https://t.me/haskell
From 6a5469edaf026a75b8b715d218439bbe60f84b43 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sun, 30 Aug 2020 10:57:31 +0200
Subject: [PATCH 0215/1073] Don't attempt to retrieve chat attributes from
empty messages Fixes #479
---
pyrogram/utils.py | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/pyrogram/utils.py b/pyrogram/utils.py
index 89ee7f6c79..807d98a024 100644
--- a/pyrogram/utils.py
+++ b/pyrogram/utils.py
@@ -167,8 +167,17 @@ async def parse_messages(client, messages: "raw.types.messages.Messages", replie
reply_message_ids = [i[0] for i in filter(lambda x: x[1] is not None, messages_with_replies.items())]
if reply_message_ids:
+ # We need a chat id, but some messages might be empty (no chat attribute available)
+ # Scan until we find a message with a chat available (there must be one, because we are fetching replies)
+ for m in parsed_messages:
+ if m.chat:
+ chat_id = m.chat.id
+ break
+ else:
+ chat_id = 0
+
reply_messages = await client.get_messages(
- parsed_messages[0].chat.id,
+ chat_id,
reply_to_message_ids=reply_message_ids,
replies=replies - 1
)
From 33d04b5916afbc312c84b7c0df334a2ad90b8f68 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sun, 30 Aug 2020 10:58:55 +0200
Subject: [PATCH 0216/1073] Change default get/iter_chat_members filter to
"recent"
---
pyrogram/methods/chats/get_chat_members.py | 4 ++--
pyrogram/methods/chats/iter_chat_members.py | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/pyrogram/methods/chats/get_chat_members.py b/pyrogram/methods/chats/get_chat_members.py
index d3e87c7d03..d55a741062 100644
--- a/pyrogram/methods/chats/get_chat_members.py
+++ b/pyrogram/methods/chats/get_chat_members.py
@@ -42,7 +42,7 @@ async def get_chat_members(
offset: int = 0,
limit: int = 200,
query: str = "",
- filter: str = Filters.ALL
+ filter: str = Filters.RECENT
) -> List["types.ChatMember"]:
"""Get a chunk of the members list of a chat.
@@ -78,7 +78,7 @@ async def get_chat_members(
*"recent"* - recent members only,
*"administrators"* - chat administrators only.
Only applicable to supergroups and channels.
- Defaults to *"all"*.
+ Defaults to *"recent"*.
.. [1] Server limit: on supergroups, you can get up to 10,000 members for a single query and up to 200 members
on channels.
diff --git a/pyrogram/methods/chats/iter_chat_members.py b/pyrogram/methods/chats/iter_chat_members.py
index 2954bcdba4..59def3c1da 100644
--- a/pyrogram/methods/chats/iter_chat_members.py
+++ b/pyrogram/methods/chats/iter_chat_members.py
@@ -43,7 +43,7 @@ async def iter_chat_members(
chat_id: Union[int, str],
limit: int = 0,
query: str = "",
- filter: str = Filters.ALL
+ filter: str = Filters.RECENT
) -> Optional[AsyncGenerator["types.ChatMember", None]]:
"""Iterate through the members of a chat sequentially.
@@ -72,7 +72,7 @@ async def iter_chat_members(
*"bots"* - bots only,
*"recent"* - recent members only,
*"administrators"* - chat administrators only.
- Defaults to *"all"*.
+ Defaults to *"recent"*.
Returns:
``Generator``: A generator yielding :obj:`~pyrogram.types.ChatMember` objects.
From a18e0242fa231a4fd29da310933c8ea5f15ba0c8 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sun, 30 Aug 2020 11:17:20 +0200
Subject: [PATCH 0217/1073] Fix raw API not being properly imported when using
repr/eval Fixes #423
---
compiler/api/compiler.py | 2 +-
pyrogram/__init__.py | 2 +-
pyrogram/raw/core/tl_object.py | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/compiler/api/compiler.py b/compiler/api/compiler.py
index 6c3dcb27ec..acaf9731c5 100644
--- a/compiler/api/compiler.py
+++ b/compiler/api/compiler.py
@@ -489,7 +489,7 @@ def start(format: bool = False):
docstring=docstring,
slots=slots,
id=c.id,
- qualname=f"pyrogram.raw.{c.section}.{c.qualname}",
+ qualname=f"{c.section}.{c.qualname}",
arguments=arguments,
fields=fields,
read_types=read_types,
diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py
index f967dfc595..af2c2ce996 100644
--- a/pyrogram/__init__.py
+++ b/pyrogram/__init__.py
@@ -33,6 +33,6 @@ class ContinuePropagation(StopAsyncIteration):
pass
-from . import types, filters, handlers, emoji
+from . import raw, types, filters, handlers, emoji
from .client import Client
from .sync import idle
diff --git a/pyrogram/raw/core/tl_object.py b/pyrogram/raw/core/tl_object.py
index 0391ab85f6..48b3ec9134 100644
--- a/pyrogram/raw/core/tl_object.py
+++ b/pyrogram/raw/core/tl_object.py
@@ -53,7 +53,7 @@ def __str__(self) -> str:
return dumps(self, indent=4, default=TLObject.default, ensure_ascii=False)
def __repr__(self) -> str:
- return "pyrogram.api.{}({})".format(
+ return "pyrogram.raw.{}({})".format(
self.QUALNAME,
", ".join(
f"{attr}={repr(getattr(self, attr))}"
From 35ec32891342998e1aff125873a80817b5567487 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sun, 30 Aug 2020 11:23:42 +0200
Subject: [PATCH 0218/1073] Update message.py
---
pyrogram/client/types/messages_and_media/message.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pyrogram/client/types/messages_and_media/message.py b/pyrogram/client/types/messages_and_media/message.py
index c6d58de39b..9a8d57a982 100644
--- a/pyrogram/client/types/messages_and_media/message.py
+++ b/pyrogram/client/types/messages_and_media/message.py
@@ -2687,9 +2687,9 @@ def forward(
"""
if as_copy:
if self.service:
- log.warning("Unable to copy service messages, message_id: {} from chat.id: {}".format(self.message_id, self.chat.id))
+ log.warning(f"Service messages cannot be copied. chat_id: {self.chat.id}, message_id: {self.message_id}")
elif self.game and not self._client.is_bot:
- log.warning("Users cannot send messages with Game media type, message_id: {} from chat.id: {}".format(self.message_id, self.chat.id))
+ log.warning(f"Users cannot send messages with Game media type. chat_id: {self.chat.id}, message_id: {self.message_id}")
elif self.text:
return self._client.send_message(
chat_id,
From 8f2e4f03b763a7edd4e107f731aa3fb5fc74fda4 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sun, 30 Aug 2020 13:18:10 +0200
Subject: [PATCH 0219/1073] Fix access to invalid attributes when parsing a
chat dc_id
---
pyrogram/types/user_and_chats/chat.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/pyrogram/types/user_and_chats/chat.py b/pyrogram/types/user_and_chats/chat.py
index 8ae130c6a2..44d6e156ae 100644
--- a/pyrogram/types/user_and_chats/chat.py
+++ b/pyrogram/types/user_and_chats/chat.py
@@ -180,7 +180,7 @@ def _parse_user_chat(client, user: raw.types.User) -> "Chat":
last_name=user.last_name,
photo=types.ChatPhoto._parse(client, user.photo, peer_id, user.access_hash),
restrictions=types.List([types.Restriction._parse(r) for r in user.restriction_reason]) or None,
- dc_id=getattr(user.photo, "dc_id", None),
+ dc_id=getattr(getattr(user, "photo", None), "dc_id", None),
client=client
)
@@ -196,7 +196,7 @@ def _parse_chat_chat(client, chat: raw.types.Chat) -> "Chat":
photo=types.ChatPhoto._parse(client, getattr(chat, "photo", None), peer_id, 0),
permissions=types.ChatPermissions._parse(getattr(chat, "default_banned_rights", None)),
members_count=getattr(chat, "participants_count", None),
- dc_id=getattr(chat.photo, "dc_id", None),
+ dc_id=getattr(getattr(chat, "photo", None), "dc_id", None),
client=client
)
@@ -218,7 +218,7 @@ def _parse_channel_chat(client, channel: raw.types.Channel) -> "Chat":
restrictions=types.List([types.Restriction._parse(r) for r in restriction_reason]) or None,
permissions=types.ChatPermissions._parse(getattr(channel, "default_banned_rights", None)),
members_count=getattr(channel, "participants_count", None),
- dc_id=getattr(channel.photo, "dc_id", None),
+ dc_id=getattr(getattr(channel, "photo", None), "dc_id", None),
client=client
)
From be62ac365f26ff2594c3f1d52c59dc623d29d634 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sun, 30 Aug 2020 22:19:55 +0200
Subject: [PATCH 0220/1073] Use a reasonable sleep threshold when downloading
files
---
pyrogram/client.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/pyrogram/client.py b/pyrogram/client.py
index ba5cfb49ed..e7683c26b4 100644
--- a/pyrogram/client.py
+++ b/pyrogram/client.py
@@ -930,7 +930,8 @@ async def get_file(
location=location,
offset=offset,
limit=limit
- )
+ ),
+ sleep_threshold=30
)
if isinstance(r, raw.types.upload.File):
@@ -961,7 +962,8 @@ async def get_file(
location=location,
offset=offset,
limit=limit
- )
+ ),
+ sleep_threshold=30
)
elif isinstance(r, raw.types.upload.FileCdnRedirect):
From 617f0c9b301015b841e8f8a22e9e0298db0a2567 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Mon, 31 Aug 2020 00:17:33 +0200
Subject: [PATCH 0221/1073] Set the main event loop in threads where there's no
event loop #480
---
pyrogram/__init__.py | 5 +++++
pyrogram/scaffold.py | 8 ++++++++
2 files changed, 13 insertions(+)
diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py
index af2c2ce996..5936ce7c22 100644
--- a/pyrogram/__init__.py
+++ b/pyrogram/__init__.py
@@ -33,6 +33,11 @@ class ContinuePropagation(StopAsyncIteration):
pass
+import asyncio
+
from . import raw, types, filters, handlers, emoji
from .client import Client
from .sync import idle
+
+# Save the main thread loop for future references
+main_event_loop = asyncio.get_event_loop()
diff --git a/pyrogram/scaffold.py b/pyrogram/scaffold.py
index 0b3bf02185..a118955c29 100644
--- a/pyrogram/scaffold.py
+++ b/pyrogram/scaffold.py
@@ -23,6 +23,7 @@
import sys
from pathlib import Path
+import pyrogram
from pyrogram import __version__
from pyrogram.parser import Parser
from pyrogram.session.internals import MsgId
@@ -73,6 +74,13 @@ class Scaffold:
mime_types_to_extensions[mime_type] = " ".join(extensions)
def __init__(self):
+ try:
+ asyncio.get_event_loop()
+ except RuntimeError:
+ # This happens when creating Client instances inside different threads that don't have an event loop.
+ # Set the main event loop in this thread.
+ asyncio.set_event_loop(pyrogram.main_event_loop)
+
self.session_name = None
self.api_id = None
self.api_hash = None
From 44880f7efe31f157f88b32779e160682ea8b500c Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Wed, 2 Sep 2020 13:07:30 +0200
Subject: [PATCH 0222/1073] Use the current loop instead of the main loop in
case there is one available #482
---
pyrogram/sync.py | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/pyrogram/sync.py b/pyrogram/sync.py
index 80288e68d0..2bca9700bb 100644
--- a/pyrogram/sync.py
+++ b/pyrogram/sync.py
@@ -28,7 +28,7 @@
def async_to_sync(obj, name):
function = getattr(obj, name)
- loop = asyncio.get_event_loop()
+ main_loop = asyncio.get_event_loop()
async def consume_generator(coroutine):
return [i async for i in coroutine]
@@ -37,6 +37,11 @@ async def consume_generator(coroutine):
def async_to_sync_wrap(*args, **kwargs):
coroutine = function(*args, **kwargs)
+ try:
+ loop = asyncio.get_event_loop()
+ except RuntimeError:
+ loop = main_loop
+
if loop.is_running():
if threading.current_thread() is threading.main_thread():
return coroutine
From 58667d2ae886518a9e93e82030935bebb2716c2f Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 5 Sep 2020 12:26:22 +0200
Subject: [PATCH 0223/1073] Update Pyrogram to v1.0.7
---
pyrogram/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py
index 5936ce7c22..39b83df745 100644
--- a/pyrogram/__init__.py
+++ b/pyrogram/__init__.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-__version__ = "1.0.6"
+__version__ = "1.0.7"
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__copyright__ = "Copyright (C) 2017-2020 Dan "
From ae88c851bbc98785abb829a748d68803f3a44c37 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 5 Sep 2020 12:44:48 +0200
Subject: [PATCH 0224/1073] Fix sync callback progress not working properly for
downloads - Reduce duplicated code - Fixes #484
---
pyrogram/client.py | 28 ++++++++++++++------------
pyrogram/methods/advanced/save_file.py | 16 +++++++--------
2 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/pyrogram/client.py b/pyrogram/client.py
index e7683c26b4..2577745a9c 100644
--- a/pyrogram/client.py
+++ b/pyrogram/client.py
@@ -949,7 +949,8 @@ async def get_file(
offset += limit
if progress:
- await progress(
+ func = functools.partial(
+ progress,
min(offset, file_size)
if file_size != 0
else offset,
@@ -957,6 +958,11 @@ async def get_file(
*progress_args
)
+ if inspect.iscoroutinefunction(progress):
+ await func()
+ else:
+ await self.loop.run_in_executor(self.executor, func)
+
r = await session.send(
raw.functions.upload.GetFile(
location=location,
@@ -1035,20 +1041,16 @@ async def get_file(
offset += limit
if progress:
+ func = functools.partial(
+ progress,
+ min(offset, file_size) if file_size != 0 else offset,
+ file_size,
+ *progress_args
+ )
+
if inspect.iscoroutinefunction(progress):
- await progress(
- min(offset, file_size) if file_size != 0 else offset,
- file_size,
- *progress_args
- )
+ await func()
else:
- func = functools.partial(
- progress,
- min(offset, file_size) if file_size != 0 else offset,
- file_size,
- *progress_args
- )
-
await self.loop.run_in_executor(self.executor, func)
if len(chunk) < limit:
diff --git a/pyrogram/methods/advanced/save_file.py b/pyrogram/methods/advanced/save_file.py
index 9d77073365..e97279515b 100644
--- a/pyrogram/methods/advanced/save_file.py
+++ b/pyrogram/methods/advanced/save_file.py
@@ -183,16 +183,16 @@ async def worker(session):
file_part += 1
if progress:
+ func = functools.partial(
+ progress,
+ min(file_part * part_size, file_size),
+ file_size,
+ *progress_args
+ )
+
if inspect.iscoroutinefunction(progress):
- await progress(min(file_part * part_size, file_size), file_size, *progress_args)
+ await func()
else:
- func = functools.partial(
- progress,
- min(file_part * part_size, file_size),
- file_size,
- *progress_args
- )
-
await self.loop.run_in_executor(self.executor, func)
except StopTransmission:
raise
From 3127edde6834813ee5117964d720753e259a1bb5 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Wed, 16 Sep 2020 09:16:31 +0200
Subject: [PATCH 0225/1073] Add missing method to the mixin
delete_user_history
---
pyrogram/methods/chats/__init__.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/pyrogram/methods/chats/__init__.py b/pyrogram/methods/chats/__init__.py
index 6e4a9228cf..b55d1be7ce 100644
--- a/pyrogram/methods/chats/__init__.py
+++ b/pyrogram/methods/chats/__init__.py
@@ -24,6 +24,7 @@
from .delete_channel import DeleteChannel
from .delete_chat_photo import DeleteChatPhoto
from .delete_supergroup import DeleteSupergroup
+from .delete_user_history import DeleteUserHistory
from .export_chat_invite_link import ExportChatInviteLink
from .get_chat import GetChat
from .get_chat_member import GetChatMember
@@ -86,6 +87,7 @@ class Chats(
DeleteSupergroup,
GetNearbyChats,
SetAdministratorTitle,
- SetSlowMode
+ SetSlowMode,
+ DeleteUserHistory
):
pass
From 5ee932b326b8baa1e5ff90b60a82904cfd702f93 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Wed, 30 Sep 2020 19:12:12 +0200
Subject: [PATCH 0226/1073] Update API Schema to Layer 119
---
compiler/api/source/main_api.tl | 83 ++++++++++++++++++++++-----------
1 file changed, 57 insertions(+), 26 deletions(-)
diff --git a/compiler/api/source/main_api.tl b/compiler/api/source/main_api.tl
index 9b50b802b7..9f65522874 100644
--- a/compiler/api/source/main_api.tl
+++ b/compiler/api/source/main_api.tl
@@ -106,7 +106,7 @@ channel#d31a961e flags:# creator:flags.0?true left:flags.2?true broadcast:flags.
channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat;
chatFull#1b7c9db3 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:int about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:flags.3?Vector pinned_msg_id:flags.6?int folder_id:flags.11?int = ChatFull;
-channelFull#f0e6672a flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?int location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int = ChatFull;
+channelFull#f0e6672a flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?int location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int = ChatFull;
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
chatParticipantCreator#da13538a user_id:int = ChatParticipant;
@@ -119,8 +119,8 @@ chatPhotoEmpty#37c1011c = ChatPhoto;
chatPhoto#d20b9f3c flags:# has_video:flags.0?true photo_small:FileLocation photo_big:FileLocation dc_id:int = ChatPhoto;
messageEmpty#83e5de54 id:int = Message;
-message#452c0e65 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector = Message;
-messageService#9e19a1f6 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?int to_id:Peer reply_to_msg_id:flags.3?int date:int action:MessageAction = Message;
+message#58ae39c9 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector = Message;
+messageService#286fa604 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?Peer peer_id:Peer reply_to:flags.3?MessageReplyHeader date:int action:MessageAction = Message;
messageMediaEmpty#3ded6320 = MessageMedia;
messageMediaPhoto#695150d7 flags:# photo:flags.0?Photo ttl_seconds:flags.2?int = MessageMedia;
@@ -170,6 +170,7 @@ photoSizeEmpty#e17e23c type:string = PhotoSize;
photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize;
photoStrippedSize#e0b0bc2e type:string bytes:bytes = PhotoSize;
+photoSizeProgressive#5aa86a51 type:string location:FileLocation w:int h:int sizes:Vector = PhotoSize;
geoPointEmpty#1117dd5f = GeoPoint;
geoPoint#296f104 long:double lat:double access_hash:long = GeoPoint;
@@ -209,8 +210,6 @@ contact#f911c994 user_id:int mutual:Bool = Contact;
importedContact#d0028438 user_id:int client_id:long = ImportedContact;
-contactBlocked#561bc879 user_id:int date:int = ContactBlocked;
-
contactStatus#d3680c61 user_id:int status:UserStatus = ContactStatus;
contacts.contactsNotModified#b74ba9d2 = contacts.Contacts;
@@ -218,8 +217,8 @@ contacts.contacts#eae87e42 contacts:Vector saved_count:int users:Vector
contacts.importedContacts#77d01c3b imported:Vector popular_invites:Vector retry_contacts:Vector users:Vector = contacts.ImportedContacts;
-contacts.blocked#1c138d15 blocked:Vector users:Vector = contacts.Blocked;
-contacts.blockedSlice#900802a1 count:int blocked:Vector users:Vector = contacts.Blocked;
+contacts.blocked#ade1591 blocked:Vector chats:Vector users:Vector = contacts.Blocked;
+contacts.blockedSlice#e1664194 count:int blocked:Vector chats:Vector users:Vector = contacts.Blocked;
messages.dialogs#15ba6c40 dialogs:Vector