From a17cb6ba63006da21a5c10109d51b1c2c1c6115d Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:28:00 +0545 Subject: [PATCH 001/103] Delete tox.ini --- tox.ini | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 tox.ini diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 1795b1f225..0000000000 --- a/tox.ini +++ /dev/null @@ -1,4 +0,0 @@ -[testenv] -deps = -rdev-requirements.txt -commands = coverage run -m pytest {posargs} -skip_install = true \ No newline at end of file From 6606ffa698dc84519941a71524dfccd3ec2ffb6e Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:28:11 +0545 Subject: [PATCH 002/103] Delete setup.py --- setup.py | 88 -------------------------------------------------------- 1 file changed, 88 deletions(-) delete mode 100644 setup.py diff --git a/setup.py b/setup.py deleted file mode 100644 index 2cb7d7f677..0000000000 --- a/setup.py +++ /dev/null @@ -1,88 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-present 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 sys import argv - -from setuptools import setup, find_packages - -from compiler.api import compiler as api_compiler -from compiler.errors import compiler as errors_compiler - -with open("requirements.txt", encoding="utf-8") as r: - requires = [i.strip() for i in r] - -with open("pyrogram/__init__.py", encoding="utf-8") as f: - version = re.findall(r"__version__ = \"(.+)\"", f.read())[0] - -with open("README.md", encoding="utf-8") as f: - readme = f.read() - -if len(argv) > 1 and argv[1] in ["bdist_wheel", "install", "develop"]: - api_compiler.start() - errors_compiler.start() - -setup( - name="Pyrogram", - version=version, - description="Elegant, modern and asynchronous Telegram MTProto API framework in Python for users and bots", - long_description=readme, - long_description_content_type="text/markdown", - url="https://github.com/pyrogram", - download_url="https://github.com/pyrogram/pyrogram/releases/latest", - author="Dan", - author_email="dan@pyrogram.org", - license="LGPLv3", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "Natural Language :: English", - "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: Implementation", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", - "Topic :: Internet", - "Topic :: Communications", - "Topic :: Communications :: Chat", - "Topic :: Software Development :: Libraries", - "Topic :: Software Development :: Libraries :: Python Modules", - "Topic :: Software Development :: Libraries :: Application Frameworks" - ], - keywords="telegram chat messenger mtproto api client library python", - project_urls={ - "Tracker": "https://github.com/pyrogram/pyrogram/issues", - "Community": "https://t.me/pyrogram", - "Source": "https://github.com/pyrogram/pyrogram", - "Documentation": "https://docs.pyrogram.org", - }, - python_requires="~=3.7", - package_data={ - "pyrogram": ["py.typed"], - }, - packages=find_packages(exclude=["compiler*", "tests*"]), - zip_safe=False, - install_requires=requires -) From eb4628000662afbfc9b286dd29fd890cf11efa43 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:28:22 +0545 Subject: [PATCH 003/103] Delete requirements.txt --- requirements.txt | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index bf6641539c..0000000000 --- a/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pyaes==1.6.1 -pysocks==1.7.1 From 53cdb6c31ae4561a84a549ea3b6b3e5b92e6ae5e Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:28:35 +0545 Subject: [PATCH 004/103] Delete dev-requirements.txt --- dev-requirements.txt | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 dev-requirements.txt diff --git a/dev-requirements.txt b/dev-requirements.txt deleted file mode 100644 index d8968085b3..0000000000 --- a/dev-requirements.txt +++ /dev/null @@ -1,6 +0,0 @@ --r requirements.txt - -pytest -pytest-asyncio -pytest-cov -twine \ No newline at end of file From 53edc8e41a59ad6c9697564d05d81fe1f2ba927f Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:28:49 +0545 Subject: [PATCH 005/103] Delete NOTICE --- NOTICE | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 NOTICE diff --git a/NOTICE b/NOTICE deleted file mode 100644 index 7a9aaab647..0000000000 --- a/NOTICE +++ /dev/null @@ -1,17 +0,0 @@ -Pyrogram - Telegram MTProto API Client Library for Python -Copyright (C) 2017-present 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 . \ No newline at end of file From 379d0c482cdcc1d9c4f220764c6db580e648b91e Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:29:24 +0545 Subject: [PATCH 006/103] Delete .gitignore --- .gitignore | 130 ----------------------------------------------------- 1 file changed, 130 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 7a99a5db85..0000000000 --- a/.gitignore +++ /dev/null @@ -1,130 +0,0 @@ -# Development -docs -*.session -config.ini -main.py -unknown_errors.txt -.DS_Store - -# Pyrogram generated code -pyrogram/errors/exceptions/ -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/ - -# VS Code -.vscode/ - -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -.hypothesis/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -.static_storage/ -.media/ -local_settings.py - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ -docs/source/_build - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# pyenv -.python-version - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ \ No newline at end of file From 53109b76eda66d083c5c4dd70644c1ae09eee3c9 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:29:37 +0545 Subject: [PATCH 007/103] Delete COPYING --- COPYING | 674 -------------------------------------------------------- 1 file changed, 674 deletions(-) delete mode 100644 COPYING diff --git a/COPYING b/COPYING deleted file mode 100644 index e72bfddabc..0000000000 --- a/COPYING +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file From 2b2938fc4310699d61b57e81b08974533bd2a847 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:29:49 +0545 Subject: [PATCH 008/103] Delete COPYING.lesser --- COPYING.lesser | 165 ------------------------------------------------- 1 file changed, 165 deletions(-) delete mode 100644 COPYING.lesser diff --git a/COPYING.lesser b/COPYING.lesser deleted file mode 100644 index 153d416dc8..0000000000 --- a/COPYING.lesser +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. \ No newline at end of file From e5dc85b5166984eda43a4d5356a2fee03d264b07 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:30:07 +0545 Subject: [PATCH 009/103] Delete Makefile --- Makefile | 42 ------------------------------------------ 1 file changed, 42 deletions(-) delete mode 100644 Makefile diff --git a/Makefile b/Makefile deleted file mode 100644 index 930d3be406..0000000000 --- a/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -VENV := venv -PYTHON := $(VENV)/bin/python -HOST = $(shell ifconfig | grep "inet " | tail -1 | cut -d\ -f2) -TAG = v$(shell grep -E '__version__ = ".*"' pyrogram/__init__.py | cut -d\" -f2) - -RM := rm -rf - -.PHONY: venv clean-build clean-api clean api build - -venv: - $(RM) $(VENV) - python3 -m venv $(VENV) - $(PYTHON) -m pip install -U pip wheel setuptools - $(PYTHON) -m pip install -U -r requirements.txt -r dev-requirements.txt - @echo "Created venv with $$($(PYTHON) --version)" - -clean-build: - $(RM) *.egg-info build dist - -clean-api: - $(RM) pyrogram/errors/exceptions pyrogram/raw/all.py pyrogram/raw/base pyrogram/raw/functions pyrogram/raw/types - -clean: - make clean-build - make clean-api - -api: - cd compiler/api && ../../$(PYTHON) compiler.py - cd compiler/errors && ../../$(PYTHON) compiler.py - -build: - make clean - $(PYTHON) setup.py sdist - $(PYTHON) setup.py bdist_wheel - -tag: - git tag $(TAG) - git push origin $(TAG) - -dtag: - git tag -d $(TAG) - git push origin -d $(TAG) \ No newline at end of file From 29e68739833248319fb66e0355470d23d2f23718 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:30:23 +0545 Subject: [PATCH 010/103] Delete MANIFEST.in --- MANIFEST.in | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index b1f5bc04f3..0000000000 --- a/MANIFEST.in +++ /dev/null @@ -1,11 +0,0 @@ -## Include -include README.md COPYING COPYING.lesser NOTICE requirements.txt -recursive-include compiler *.py *.tl *.tsv *.txt -recursive-include tests *.py - -## Exclude -prune pyrogram/errors/exceptions -prune pyrogram/raw/functions -prune pyrogram/raw/types -prune pyrogram/raw/base -exclude pyrogram/raw/all.py From faa0f97bae364b4dbb7dcd2601bb129b544504c3 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:30:39 +0545 Subject: [PATCH 011/103] Delete .github/FUNDING.yml --- .github/FUNDING.yml | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 19d0cd78d1..0000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,3 +0,0 @@ -github: delivrance -liberapay: delivrance -open_collective: pyrogram From b62a55bf00eb3f9d662027a726989b0e196a638f Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:31:58 +0545 Subject: [PATCH 012/103] Add files via upload --- .github/FUNDING.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..19d0cd78d1 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +github: delivrance +liberapay: delivrance +open_collective: pyrogram From 855fb64928afd0f94c007c485913f544fc637ad4 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:32:51 +0545 Subject: [PATCH 013/103] Add files via upload --- .gitignore | 130 +++++++++ COPYING | 674 +++++++++++++++++++++++++++++++++++++++++++ COPYING.lesser | 165 +++++++++++ MANIFEST.in | 11 + Makefile | 42 +++ NOTICE | 17 ++ dev-requirements.txt | 6 + requirements.txt | 2 + setup.py | 88 ++++++ tox.ini | 4 + 10 files changed, 1139 insertions(+) create mode 100644 .gitignore create mode 100644 COPYING create mode 100644 COPYING.lesser create mode 100644 MANIFEST.in create mode 100644 Makefile create mode 100644 NOTICE create mode 100644 dev-requirements.txt create mode 100644 requirements.txt create mode 100644 setup.py create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..7a99a5db85 --- /dev/null +++ b/.gitignore @@ -0,0 +1,130 @@ +# Development +docs +*.session +config.ini +main.py +unknown_errors.txt +.DS_Store + +# Pyrogram generated code +pyrogram/errors/exceptions/ +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/ + +# VS Code +.vscode/ + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +.static_storage/ +.media/ +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ +docs/source/_build + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ \ No newline at end of file diff --git a/COPYING b/COPYING new file mode 100644 index 0000000000..e72bfddabc --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/COPYING.lesser b/COPYING.lesser new file mode 100644 index 0000000000..153d416dc8 --- /dev/null +++ b/COPYING.lesser @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000000..b1f5bc04f3 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,11 @@ +## Include +include README.md COPYING COPYING.lesser NOTICE requirements.txt +recursive-include compiler *.py *.tl *.tsv *.txt +recursive-include tests *.py + +## Exclude +prune pyrogram/errors/exceptions +prune pyrogram/raw/functions +prune pyrogram/raw/types +prune pyrogram/raw/base +exclude pyrogram/raw/all.py diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..930d3be406 --- /dev/null +++ b/Makefile @@ -0,0 +1,42 @@ +VENV := venv +PYTHON := $(VENV)/bin/python +HOST = $(shell ifconfig | grep "inet " | tail -1 | cut -d\ -f2) +TAG = v$(shell grep -E '__version__ = ".*"' pyrogram/__init__.py | cut -d\" -f2) + +RM := rm -rf + +.PHONY: venv clean-build clean-api clean api build + +venv: + $(RM) $(VENV) + python3 -m venv $(VENV) + $(PYTHON) -m pip install -U pip wheel setuptools + $(PYTHON) -m pip install -U -r requirements.txt -r dev-requirements.txt + @echo "Created venv with $$($(PYTHON) --version)" + +clean-build: + $(RM) *.egg-info build dist + +clean-api: + $(RM) pyrogram/errors/exceptions pyrogram/raw/all.py pyrogram/raw/base pyrogram/raw/functions pyrogram/raw/types + +clean: + make clean-build + make clean-api + +api: + cd compiler/api && ../../$(PYTHON) compiler.py + cd compiler/errors && ../../$(PYTHON) compiler.py + +build: + make clean + $(PYTHON) setup.py sdist + $(PYTHON) setup.py bdist_wheel + +tag: + git tag $(TAG) + git push origin $(TAG) + +dtag: + git tag -d $(TAG) + git push origin -d $(TAG) \ No newline at end of file diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000000..7a9aaab647 --- /dev/null +++ b/NOTICE @@ -0,0 +1,17 @@ +Pyrogram - Telegram MTProto API Client Library for Python +Copyright (C) 2017-present 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 . \ No newline at end of file diff --git a/dev-requirements.txt b/dev-requirements.txt new file mode 100644 index 0000000000..d8968085b3 --- /dev/null +++ b/dev-requirements.txt @@ -0,0 +1,6 @@ +-r requirements.txt + +pytest +pytest-asyncio +pytest-cov +twine \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000..bf6641539c --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +pyaes==1.6.1 +pysocks==1.7.1 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000000..2cb7d7f677 --- /dev/null +++ b/setup.py @@ -0,0 +1,88 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present 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 sys import argv + +from setuptools import setup, find_packages + +from compiler.api import compiler as api_compiler +from compiler.errors import compiler as errors_compiler + +with open("requirements.txt", encoding="utf-8") as r: + requires = [i.strip() for i in r] + +with open("pyrogram/__init__.py", encoding="utf-8") as f: + version = re.findall(r"__version__ = \"(.+)\"", f.read())[0] + +with open("README.md", encoding="utf-8") as f: + readme = f.read() + +if len(argv) > 1 and argv[1] in ["bdist_wheel", "install", "develop"]: + api_compiler.start() + errors_compiler.start() + +setup( + name="Pyrogram", + version=version, + description="Elegant, modern and asynchronous Telegram MTProto API framework in Python for users and bots", + long_description=readme, + long_description_content_type="text/markdown", + url="https://github.com/pyrogram", + download_url="https://github.com/pyrogram/pyrogram/releases/latest", + author="Dan", + author_email="dan@pyrogram.org", + license="LGPLv3", + classifiers=[ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Natural Language :: English", + "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: Implementation", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", + "Topic :: Internet", + "Topic :: Communications", + "Topic :: Communications :: Chat", + "Topic :: Software Development :: Libraries", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Software Development :: Libraries :: Application Frameworks" + ], + keywords="telegram chat messenger mtproto api client library python", + project_urls={ + "Tracker": "https://github.com/pyrogram/pyrogram/issues", + "Community": "https://t.me/pyrogram", + "Source": "https://github.com/pyrogram/pyrogram", + "Documentation": "https://docs.pyrogram.org", + }, + python_requires="~=3.7", + package_data={ + "pyrogram": ["py.typed"], + }, + packages=find_packages(exclude=["compiler*", "tests*"]), + zip_safe=False, + install_requires=requires +) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000000..1795b1f225 --- /dev/null +++ b/tox.ini @@ -0,0 +1,4 @@ +[testenv] +deps = -rdev-requirements.txt +commands = coverage run -m pytest {posargs} +skip_install = true \ No newline at end of file From 2f01efc9a53f0e66c598b9704a9c0e298a15c4c1 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:26:41 +0545 Subject: [PATCH 014/103] Delete pyrogram/__init__.py --- pyrogram/__init__.py | 42 ------------------------------------------ 1 file changed, 42 deletions(-) delete mode 100644 pyrogram/__init__.py diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py deleted file mode 100644 index 9a6a44accb..0000000000 --- a/pyrogram/__init__.py +++ /dev/null @@ -1,42 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-present 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 . - -__version__ = "2.0.106" -__license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)" -__copyright__ = "Copyright (C) 2017-present Dan " - -from concurrent.futures.thread import ThreadPoolExecutor - - -class StopTransmission(Exception): - pass - - -class StopPropagation(StopAsyncIteration): - pass - - -class ContinuePropagation(StopAsyncIteration): - pass - - -from . import raw, types, filters, handlers, emoji, enums -from .client import Client -from .sync import idle, compose - -crypto_executor = ThreadPoolExecutor(1, thread_name_prefix="CryptoWorker") From fa9bf9b3d2090c5366f9afbb66e938a5eb4760f7 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:26:54 +0545 Subject: [PATCH 015/103] Delete pyrogram/client.py --- pyrogram/client.py | 1048 -------------------------------------------- 1 file changed, 1048 deletions(-) delete mode 100644 pyrogram/client.py diff --git a/pyrogram/client.py b/pyrogram/client.py deleted file mode 100644 index c74634ea8e..0000000000 --- a/pyrogram/client.py +++ /dev/null @@ -1,1048 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-present 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 logging -import os -import platform -import re -import shutil -import sys -from concurrent.futures.thread import ThreadPoolExecutor -from datetime import datetime, timedelta -from hashlib import sha256 -from importlib import import_module -from io import StringIO, BytesIO -from mimetypes import MimeTypes -from pathlib import Path -from typing import Union, List, Optional, Callable, AsyncGenerator - -import pyrogram -from pyrogram import __version__, __license__ -from pyrogram import enums -from pyrogram import raw -from pyrogram import utils -from pyrogram.crypto import aes -from pyrogram.errors import CDNFileHashMismatch -from pyrogram.errors import ( - SessionPasswordNeeded, - VolumeLocNotFound, ChannelPrivate, - BadRequest -) -from pyrogram.handlers.handler import Handler -from pyrogram.methods import Methods -from pyrogram.session import Auth, Session -from pyrogram.storage import FileStorage, MemoryStorage -from pyrogram.types import User, TermsOfService -from pyrogram.utils import ainput -from .dispatcher import Dispatcher -from .file_id import FileId, FileType, ThumbnailSource -from .mime_types import mime_types -from .parser import Parser -from .session.internals import MsgId - -log = logging.getLogger(__name__) - - -class Client(Methods): - """Pyrogram Client, the main means for interacting with Telegram. - - Parameters: - name (``str``): - A name for the client, e.g.: "my_account". - - api_id (``int`` | ``str``, *optional*): - The *api_id* part of the Telegram API key, as integer or string. - E.g.: 12345 or "12345". - - api_hash (``str``, *optional*): - The *api_hash* part of the Telegram API key, as string. - E.g.: "0123456789abcdef0123456789abcdef". - - app_version (``str``, *optional*): - Application version. - Defaults to "Pyrogram x.y.z". - - device_model (``str``, *optional*): - Device model. - Defaults to *platform.python_implementation() + " " + platform.python_version()*. - - system_version (``str``, *optional*): - Operating System version. - Defaults to *platform.system() + " " + platform.release()*. - - lang_code (``str``, *optional*): - Code of the language used on the client, in ISO 639-1 standard. - Defaults to "en". - - ipv6 (``bool``, *optional*): - Pass True to connect to Telegram using IPv6. - Defaults to False (IPv4). - - proxy (``dict``, *optional*): - The Proxy settings as dict. - E.g.: *dict(scheme="socks5", hostname="11.22.33.44", port=1234, username="user", password="pass")*. - The *username* and *password* can be omitted if the proxy doesn't require authorization. - - 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 the Bot API token to create a bot session, e.g.: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11" - Only applicable for new sessions. - - session_string (``str``, *optional*): - Pass a session string to load the session in-memory. - Implies ``in_memory=True``. - - in_memory (``bool``, *optional*): - Pass True to start an in-memory session that will be discarded as soon as the client stops. - In order to reconnect again using an in-memory session 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 to the ``session_string`` parameter. - Defaults to False. - - phone_number (``str``, *optional*): - Pass the phone number as string (with the 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 the Two-Step Verification password as string (if required) to avoid entering it manually. - Only applicable for new sessions. - - 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 the filesystem where Pyrogram will store the session files. - Defaults to the parent directory of the main script. - - plugins (``dict``, *optional*): - Smart Plugins settings as dict, e.g.: *dict(root="plugins")*. - - parse_mode (:obj:`~pyrogram.enums.ParseMode`, *optional*): - Set the global parse mode of the client. By default, texts are parsed using both Markdown and HTML styles. - You can combine both syntaxes together. - - no_updates (``bool``, *optional*): - Pass True to disable incoming updates. - When updates are disabled the client can't receive messages or other updates. - Useful for batch programs that don't need to deal with updates. - Defaults to False (updates enabled and 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 Telegram data. Methods invoked inside a takeout session (such as get_chat_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 10 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. - - max_concurrent_transmissions (``bool``, *optional*): - Set the maximum amount of concurrent transmissions (uploads & downloads). - A value that is too high may result in network related issues. - Defaults to 1. - """ - - 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-]+)$") - WORKERS = min(32, (os.cpu_count() or 0) + 4) # os.cpu_count() can be None - WORKDIR = PARENT_DIR - - # Interval of seconds in which the updates watchdog will kick in - UPDATES_WATCHDOG_INTERVAL = 5 * 60 - - MAX_CONCURRENT_TRANSMISSIONS = 1 - - mimetypes = MimeTypes() - mimetypes.readfp(StringIO(mime_types)) - - def __init__( - self, - name: str, - api_id: Union[int, str] = None, - api_hash: str = None, - app_version: str = APP_VERSION, - device_model: str = DEVICE_MODEL, - system_version: str = SYSTEM_VERSION, - lang_code: str = LANG_CODE, - ipv6: bool = False, - proxy: dict = None, - test_mode: bool = False, - bot_token: str = None, - session_string: str = None, - in_memory: bool = None, - phone_number: str = None, - phone_code: str = None, - password: str = None, - workers: int = WORKERS, - workdir: str = WORKDIR, - plugins: dict = None, - parse_mode: "enums.ParseMode" = enums.ParseMode.DEFAULT, - no_updates: bool = None, - takeout: bool = None, - sleep_threshold: int = Session.SLEEP_THRESHOLD, - hide_password: bool = False, - max_concurrent_transmissions: int = MAX_CONCURRENT_TRANSMISSIONS - ): - super().__init__() - - self.name = 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.lower() - self.ipv6 = ipv6 - self.proxy = proxy - self.test_mode = test_mode - self.bot_token = bot_token - self.session_string = session_string - self.in_memory = in_memory - self.phone_number = phone_number - self.phone_code = phone_code - self.password = password - self.workers = workers - self.workdir = Path(workdir) - self.plugins = plugins - self.parse_mode = parse_mode - self.no_updates = no_updates - self.takeout = takeout - self.sleep_threshold = sleep_threshold - self.hide_password = hide_password - self.max_concurrent_transmissions = max_concurrent_transmissions - - self.executor = ThreadPoolExecutor(self.workers, thread_name_prefix="Handler") - - if self.session_string: - self.storage = MemoryStorage(self.name, self.session_string) - elif self.in_memory: - self.storage = MemoryStorage(self.name) - else: - self.storage = FileStorage(self.name, self.workdir) - - self.dispatcher = Dispatcher(self) - - self.rnd_id = MsgId - - self.parser = Parser(self) - - self.session = None - - self.media_sessions = {} - self.media_sessions_lock = asyncio.Lock() - - self.save_file_semaphore = asyncio.Semaphore(self.max_concurrent_transmissions) - self.get_file_semaphore = asyncio.Semaphore(self.max_concurrent_transmissions) - - self.is_connected = None - self.is_initialized = None - - self.takeout_id = None - - self.disconnect_handler = None - - self.me: Optional[User] = None - - self.message_cache = Cache(10000) - - # Sometimes, for some reason, the server will stop sending updates and will only respond to pings. - # This watchdog will invoke updates.GetState in order to wake up the server and enable it sending updates again - # after some idle time has been detected. - self.updates_watchdog_task = None - self.updates_watchdog_event = asyncio.Event() - self.last_update_time = datetime.now() - - 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): - try: - await self.stop() - except ConnectionError: - pass - - async def updates_watchdog(self): - while True: - try: - await asyncio.wait_for(self.updates_watchdog_event.wait(), self.UPDATES_WATCHDOG_INTERVAL) - except asyncio.TimeoutError: - pass - else: - break - - if datetime.now() - self.last_update_time > timedelta(seconds=self.UPDATES_WATCHDOG_INTERVAL): - await self.invoke(raw.functions.updates.GetState()) - - async def authorize(self) -> User: - if self.bot_token: - return await self.sign_in_bot(self.bot_token) - - print(f"Welcome to Pyrogram (version {__version__})") - print(f"Pyrogram is free software and comes with ABSOLUTELY NO WARRANTY. Licensed\n" - f"under the terms of the {__license__}.\n") - - 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 - - sent_code_descriptions = { - enums.SentCodeType.APP: "Telegram app", - enums.SentCodeType.SMS: "SMS", - enums.SentCodeType.CALL: "phone call", - enums.SentCodeType.FLASH_CALL: "phone flash call", - enums.SentCodeType.FRAGMENT_SMS: "Fragment SMS", - enums.SentCodeType.EMAIL_CODE: "email code" - } - - print(f"The confirmation code has been sent via {sent_code_descriptions[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=self.hide_password) - - 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.exception(e) - 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 - - def set_parse_mode(self, parse_mode: Optional["enums.ParseMode"]): - """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. - - Parameters: - parse_mode (:obj:`~pyrogram.enums.ParseMode`): - By default, texts are parsed using both Markdown and HTML styles. - You can combine both syntaxes together. - - Example: - .. code-block:: python - - from pyrogram import enums - - # Default combined mode: Markdown + HTML - await app.send_message("me", "1. **markdown** and html") - - # Force Markdown-only, HTML is disabled - app.set_parse_mode(enums.ParseMode.MARKDOWN) - await app.send_message("me", "2. **markdown** and html") - - # Force HTML-only, Markdown is disabled - app.set_parse_mode(enums.ParseMode.HTML) - await app.send_message("me", "3. **markdown** and html") - - # Disable the parser completely - app.set_parse_mode(enums.ParseMode.DISABLED) - await app.send_message("me", "4. **markdown** and html") - - # Bring back the default combined mode - app.set_parse_mode(enums.ParseMode.DEFAULT) - await app.send_message("me", "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.lower() if peer.username - else peer.usernames[0].username.lower() if peer.usernames - else 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): - peer_id = utils.get_channel_id(peer.id) - access_hash = peer.access_hash - username = ( - peer.username.lower() if peer.username - else peer.usernames[0].username.lower() if peer.usernames - else None - ) - peer_type = "channel" if peer.broadcast else "supergroup" - elif isinstance(peer, raw.types.ChannelForbidden): - peer_id = utils.get_channel_id(peer.id) - access_hash = peer.access_hash - 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_updates(self, updates): - self.last_update_time = datetime.now() - - if isinstance(updates, (raw.types.Updates, raw.types.UpdatesCombined)): - is_min = any(( - await self.fetch_peers(updates.users), - 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 - ), "peer_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.info(update) - - if isinstance(update, raw.types.UpdateNewChannelMessage) and is_min: - message = update.message - - if not isinstance(message, raw.types.MessageEmpty): - try: - diff = await self.invoke( - 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.invoke( - 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: - if diff.other_updates: # The other_updates list can be empty - 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) - - 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: - if not self.api_id or not self.api_hash: - raise AttributeError("The API key is required for new authorizations. " - "More info: https://docs.pyrogram.org/start/auth") - - await self.storage.api_id(self.api_id) - - 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) - else: - # Needed for migration from storage v2 to v3 - if not await self.storage.api_id(): - if self.api_id: - await self.storage.api_id(self.api_id) - else: - while True: - try: - value = int(await ainput("Enter the api_id part of the API key: ")) - - if value <= 0: - print("Invalid value") - continue - - confirm = (await ainput(f'Is "{value}" correct? (y/N): ')).lower() - - if confirm == "y": - await self.storage.api_id(value) - break - except Exception as e: - print(e) - - def load_plugins(self): - if self.plugins: - plugins = self.plugins.copy() - - for option in ["include", "exclude"]: - if plugins.get(option, []): - plugins[option] = [ - (i.split()[0], i.split()[1:] or None) - for i in self.plugins[option] - ] - else: - return - - if plugins.get("enabled", True): - root = plugins["root"] - include = plugins.get("include", []) - exclude = plugins.get("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: - for handler, group in getattr(module, name).handlers: - if isinstance(handler, Handler) and isinstance(group, int): - self.add_handler(handler, group) - - log.info('[{}] [LOAD] {}("{}") in group {} from "{}"'.format( - self.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('[%s] [LOAD] Ignoring non-existent module "%s"', self.name, module_path) - continue - - if "__path__" in dir(module): - log.warning('[%s] [LOAD] Ignoring namespace "%s"', self.name, module_path) - continue - - if handlers is None: - handlers = vars(module).keys() - warn_non_existent_functions = False - - for name in handlers: - # noinspection PyBroadException - try: - for handler, group in getattr(module, name).handlers: - if isinstance(handler, Handler) and isinstance(group, int): - self.add_handler(handler, group) - - log.info('[{}] [LOAD] {}("{}") in group {} from "{}"'.format( - self.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.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('[%s] [UNLOAD] Ignoring non-existent module "%s"', self.name, module_path) - continue - - if "__path__" in dir(module): - log.warning('[%s] [UNLOAD] Ignoring namespace "%s"', self.name, module_path) - continue - - if handlers is None: - handlers = vars(module).keys() - warn_non_existent_functions = False - - for name in handlers: - # noinspection PyBroadException - try: - for handler, group in getattr(module, name).handlers: - if isinstance(handler, Handler) and isinstance(group, int): - self.remove_handler(handler, group) - - log.info('[{}] [UNLOAD] {}("{}") from group {} in "{}"'.format( - self.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.name, name, module_path)) - - if count > 0: - log.info('[{}] Successfully loaded {} plugin{} from "{}"'.format( - self.name, count, "s" if count > 1 else "", root)) - else: - log.warning('[%s] No plugin loaded from "%s"', self.name, root) - - async def handle_download(self, packet): - file_id, directory, file_name, in_memory, file_size, progress, progress_args = packet - - os.makedirs(directory, exist_ok=True) if not in_memory else None - temp_file_path = os.path.abspath(re.sub("\\\\", "/", os.path.join(directory, file_name))) + ".temp" - file = BytesIO() if in_memory else open(temp_file_path, "wb") - - try: - async for chunk in self.get_file(file_id, file_size, 0, 0, progress, progress_args): - file.write(chunk) - except BaseException as e: - if not in_memory: - file.close() - os.remove(temp_file_path) - - if isinstance(e, asyncio.CancelledError): - raise e - - return None - else: - if in_memory: - file.name = file_name - return file - else: - file.close() - file_path = os.path.splitext(temp_file_path)[0] - shutil.move(temp_file_path, file_path) - return file_path - - async def get_file( - self, - file_id: FileId, - file_size: int = 0, - limit: int = 0, - offset: int = 0, - progress: Callable = None, - progress_args: tuple = () - ) -> Optional[AsyncGenerator[bytes, None]]: - async with self.get_file_semaphore: - file_type = file_id.file_type - - if file_type == FileType.CHAT_PHOTO: - if file_id.chat_id > 0: - peer = raw.types.InputPeerUser( - user_id=file_id.chat_id, - access_hash=file_id.chat_access_hash - ) - else: - if file_id.chat_access_hash == 0: - peer = raw.types.InputPeerChat( - chat_id=-file_id.chat_id - ) - else: - peer = raw.types.InputPeerChannel( - channel_id=utils.get_channel_id(file_id.chat_id), - access_hash=file_id.chat_access_hash - ) - - location = raw.types.InputPeerPhotoFileLocation( - peer=peer, - photo_id=file_id.media_id, - big=file_id.thumbnail_source == ThumbnailSource.CHAT_PHOTO_BIG - ) - elif file_type == FileType.PHOTO: - location = raw.types.InputPhotoFileLocation( - id=file_id.media_id, - access_hash=file_id.access_hash, - file_reference=file_id.file_reference, - thumb_size=file_id.thumbnail_size - ) - else: - location = raw.types.InputDocumentFileLocation( - id=file_id.media_id, - access_hash=file_id.access_hash, - file_reference=file_id.file_reference, - thumb_size=file_id.thumbnail_size - ) - - current = 0 - total = abs(limit) or (1 << 31) - 1 - chunk_size = 1024 * 1024 - offset_bytes = abs(offset) * chunk_size - - dc_id = file_id.dc_id - - session = Session( - self, dc_id, - await Auth(self, dc_id, await self.storage.test_mode()).create() - if dc_id != await self.storage.dc_id() - else await self.storage.auth_key(), - await self.storage.test_mode(), - is_media=True - ) - - try: - await session.start() - - if dc_id != await self.storage.dc_id(): - exported_auth = await self.invoke( - raw.functions.auth.ExportAuthorization( - dc_id=dc_id - ) - ) - - await session.invoke( - raw.functions.auth.ImportAuthorization( - id=exported_auth.id, - bytes=exported_auth.bytes - ) - ) - - r = await session.invoke( - raw.functions.upload.GetFile( - location=location, - offset=offset_bytes, - limit=chunk_size - ), - sleep_threshold=30 - ) - - if isinstance(r, raw.types.upload.File): - while True: - chunk = r.bytes - - yield chunk - - current += 1 - offset_bytes += chunk_size - - if progress: - func = functools.partial( - progress, - min(offset_bytes, file_size) - if file_size != 0 - else offset_bytes, - file_size, - *progress_args - ) - - if inspect.iscoroutinefunction(progress): - await func() - else: - await self.loop.run_in_executor(self.executor, func) - - if len(chunk) < chunk_size or current >= total: - break - - r = await session.invoke( - raw.functions.upload.GetFile( - location=location, - offset=offset_bytes, - limit=chunk_size - ), - sleep_threshold=30 - ) - - elif isinstance(r, raw.types.upload.FileCdnRedirect): - 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 - ) - - try: - await cdn_session.start() - - while True: - r2 = await cdn_session.invoke( - raw.functions.upload.GetCdnFile( - file_token=r.file_token, - offset=offset_bytes, - limit=chunk_size - ) - ) - - if isinstance(r2, raw.types.upload.CdnFileReuploadNeeded): - try: - await session.invoke( - 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_bytes // 16).to_bytes(4, "big") - ) - ) - - hashes = await session.invoke( - raw.functions.upload.GetCdnFileHashes( - file_token=r.file_token, - offset=offset_bytes - ) - ) - - # https://core.telegram.org/cdn#verifying-files - for i, h in enumerate(hashes): - cdn_chunk = decrypted_chunk[h.limit * i: h.limit * (i + 1)] - CDNFileHashMismatch.check( - h.hash == sha256(cdn_chunk).digest(), - "h.hash == sha256(cdn_chunk).digest()" - ) - - yield decrypted_chunk - - current += 1 - offset_bytes += chunk_size - - if progress: - func = functools.partial( - progress, - min(offset_bytes, file_size) if file_size != 0 else offset_bytes, - file_size, - *progress_args - ) - - if inspect.iscoroutinefunction(progress): - await func() - else: - await self.loop.run_in_executor(self.executor, func) - - if len(chunk) < chunk_size or current >= total: - break - except Exception as e: - raise e - finally: - await cdn_session.stop() - except pyrogram.StopTransmission: - raise - except Exception as e: - log.exception(e) - finally: - await session.stop() - - def guess_mime_type(self, filename: str) -> Optional[str]: - return self.mimetypes.guess_type(filename)[0] - - def guess_extension(self, mime_type: str) -> Optional[str]: - return self.mimetypes.guess_extension(mime_type) - - -class Cache: - def __init__(self, capacity: int): - self.capacity = capacity - self.store = {} - - def __getitem__(self, key): - return self.store.get(key, None) - - def __setitem__(self, key, value): - if key in self.store: - del self.store[key] - - self.store[key] = value - - if len(self.store) > self.capacity: - for _ in range(self.capacity // 2 + 1): - del self.store[next(iter(self.store))] From 672a865e435a5e91a5b159c04a0b304391a796e2 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:27:07 +0545 Subject: [PATCH 016/103] Delete pyrogram/dispatcher.py --- pyrogram/dispatcher.py | 259 ----------------------------------------- 1 file changed, 259 deletions(-) delete mode 100644 pyrogram/dispatcher.py diff --git a/pyrogram/dispatcher.py b/pyrogram/dispatcher.py deleted file mode 100644 index 6e503cebb3..0000000000 --- a/pyrogram/dispatcher.py +++ /dev/null @@ -1,259 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-present 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 inspect -import logging -from collections import OrderedDict - -import pyrogram -from pyrogram import utils -from pyrogram.handlers import ( - CallbackQueryHandler, MessageHandler, EditedMessageHandler, DeletedMessagesHandler, - UserStatusHandler, RawUpdateHandler, InlineQueryHandler, PollHandler, - ChosenInlineResultHandler, ChatMemberUpdatedHandler, ChatJoinRequestHandler -) -from pyrogram.raw.types import ( - UpdateNewMessage, UpdateNewChannelMessage, UpdateNewScheduledMessage, - UpdateEditMessage, UpdateEditChannelMessage, - UpdateDeleteMessages, UpdateDeleteChannelMessages, - UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery, - UpdateUserStatus, UpdateBotInlineQuery, UpdateMessagePoll, - UpdateBotInlineSend, UpdateChatParticipant, UpdateChannelParticipant, - UpdateBotChatInviteRequester -) - -log = logging.getLogger(__name__) - - -class Dispatcher: - NEW_MESSAGE_UPDATES = (UpdateNewMessage, UpdateNewChannelMessage, UpdateNewScheduledMessage) - EDIT_MESSAGE_UPDATES = (UpdateEditMessage, UpdateEditChannelMessage) - DELETE_MESSAGES_UPDATES = (UpdateDeleteMessages, UpdateDeleteChannelMessages) - CALLBACK_QUERY_UPDATES = (UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery) - CHAT_MEMBER_UPDATES = (UpdateChatParticipant, UpdateChannelParticipant) - USER_STATUS_UPDATES = (UpdateUserStatus,) - BOT_INLINE_QUERY_UPDATES = (UpdateBotInlineQuery,) - POLL_UPDATES = (UpdateMessagePoll,) - CHOSEN_INLINE_RESULT_UPDATES = (UpdateBotInlineSend,) - CHAT_JOIN_REQUEST_UPDATES = (UpdateBotChatInviteRequester,) - - def __init__(self, client: "pyrogram.Client"): - self.client = client - self.loop = asyncio.get_event_loop() - - 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.types.Message._parse(self.client, update.message, users, chats, - isinstance(update, UpdateNewScheduledMessage)), - MessageHandler - ) - - async def edited_message_parser(update, users, chats): - # Edited messages are parsed the same way as new messages, but the handler is different - parsed, _ = await message_parser(update, users, chats) - - return ( - parsed, - EditedMessageHandler - ) - - 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.types.CallbackQuery._parse(self.client, update, users), - CallbackQueryHandler - ) - - async def user_status_parser(update, users, chats): - return ( - pyrogram.types.User._parse_user_status(self.client, update), - UserStatusHandler - ) - - async def inline_query_parser(update, users, chats): - return ( - pyrogram.types.InlineQuery._parse(self.client, update, users), - InlineQueryHandler - ) - - async def poll_parser(update, users, chats): - return ( - pyrogram.types.Poll._parse_update(self.client, update), - PollHandler - ) - - async def chosen_inline_result_parser(update, users, chats): - return ( - pyrogram.types.ChosenInlineResult._parse(self.client, update, users), - ChosenInlineResultHandler - ) - - async def chat_member_updated_parser(update, users, chats): - return ( - pyrogram.types.ChatMemberUpdated._parse(self.client, update, users, chats), - ChatMemberUpdatedHandler - ) - - async def chat_join_request_parser(update, users, chats): - return ( - pyrogram.types.ChatJoinRequest._parse(self.client, update, users, chats), - ChatJoinRequestHandler - ) - - self.update_parsers = { - Dispatcher.NEW_MESSAGE_UPDATES: message_parser, - Dispatcher.EDIT_MESSAGE_UPDATES: edited_message_parser, - Dispatcher.DELETE_MESSAGES_UPDATES: deleted_messages_parser, - Dispatcher.CALLBACK_QUERY_UPDATES: callback_query_parser, - Dispatcher.USER_STATUS_UPDATES: user_status_parser, - Dispatcher.BOT_INLINE_QUERY_UPDATES: inline_query_parser, - Dispatcher.POLL_UPDATES: poll_parser, - Dispatcher.CHOSEN_INLINE_RESULT_UPDATES: chosen_inline_result_parser, - Dispatcher.CHAT_MEMBER_UPDATES: chat_member_updated_parser, - Dispatcher.CHAT_JOIN_REQUEST_UPDATES: chat_join_request_parser - } - - self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple} - - async def start(self): - if not self.client.no_updates: - for i in range(self.client.workers): - self.locks_list.append(asyncio.Lock()) - - self.handler_worker_tasks.append( - self.loop.create_task(self.handler_worker(self.locks_list[-1])) - ) - - log.info("Started %s HandlerTasks", self.client.workers) - - async def stop(self): - if not self.client.no_updates: - for i in range(self.client.workers): - self.updates_queue.put_nowait(None) - - for i in self.handler_worker_tasks: - await i - - self.handler_worker_tasks.clear() - self.groups.clear() - - log.info("Stopped %s HandlerTasks", self.client.workers) - - def add_handler(self, handler, group: int): - async def fn(): - for lock in self.locks_list: - await lock.acquire() - - try: - if group not in self.groups: - self.groups[group] = [] - self.groups = OrderedDict(sorted(self.groups.items())) - - self.groups[group].append(handler) - finally: - for lock in self.locks_list: - lock.release() - - self.loop.create_task(fn()) - - def remove_handler(self, handler, group: int): - async def fn(): - for lock in self.locks_list: - await lock.acquire() - - try: - if group not in self.groups: - raise ValueError(f"Group {group} does not exist. Handler was not removed.") - - self.groups[group].remove(handler) - finally: - for lock in self.locks_list: - lock.release() - - self.loop.create_task(fn()) - - async def handler_worker(self, lock): - while True: - packet = await self.updates_queue.get() - - if packet is None: - break - - try: - update, users, chats = packet - parser = self.update_parsers.get(type(update), None) - - parsed_update, handler_type = ( - await parser(update, users, chats) - if parser is not None - else (None, type(None)) - ) - - async with lock: - for group in self.groups.values(): - for handler in group: - args = None - - if isinstance(handler, handler_type): - try: - if await handler.check(self.client, parsed_update): - args = (parsed_update,) - except Exception as e: - log.exception(e) - continue - - elif isinstance(handler, RawUpdateHandler): - args = (update, users, chats) - - if args is None: - continue - - try: - if inspect.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: - continue - except Exception as e: - log.exception(e) - - break - except pyrogram.StopPropagation: - pass - except Exception as e: - log.exception(e) From 85c90ddc742a55de1498c8ede5652d0f656c2c17 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:27:21 +0545 Subject: [PATCH 017/103] Delete pyrogram/emoji.py --- pyrogram/emoji.py | 4019 --------------------------------------------- 1 file changed, 4019 deletions(-) delete mode 100644 pyrogram/emoji.py diff --git a/pyrogram/emoji.py b/pyrogram/emoji.py deleted file mode 100644 index d135faf74d..0000000000 --- a/pyrogram/emoji.py +++ /dev/null @@ -1,4019 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-present 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" -MELTING_FACE = "\U0001fae0" -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" -SMILING_FACE_WITH_OPEN_HANDS = "\U0001f917" -FACE_WITH_HAND_OVER_MOUTH = "\U0001f92d" -FACE_WITH_OPEN_EYES_AND_HAND_OVER_MOUTH = "\U0001fae2" -FACE_WITH_PEEKING_EYE = "\U0001fae3" -SHUSHING_FACE = "\U0001f92b" -THINKING_FACE = "\U0001f914" -SALUTING_FACE = "\U0001fae1" -ZIPPER_MOUTH_FACE = "\U0001f910" -FACE_WITH_RAISED_EYEBROW = "\U0001f928" -NEUTRAL_FACE = "\U0001f610" -EXPRESSIONLESS_FACE = "\U0001f611" -FACE_WITHOUT_MOUTH = "\U0001f636" -DOTTED_LINE_FACE = "\U0001fae5" -FACE_IN_CLOUDS = "\U0001f636\u200d\U0001f32b\ufe0f" -SMIRKING_FACE = "\U0001f60f" -UNAMUSED_FACE = "\U0001f612" -FACE_WITH_ROLLING_EYES = "\U0001f644" -GRIMACING_FACE = "\U0001f62c" -FACE_EXHALING = "\U0001f62e\u200d\U0001f4a8" -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" -FACE_WITH_CROSSED_OUT_EYES = "\U0001f635" -FACE_WITH_SPIRAL_EYES = "\U0001f635\u200d\U0001f4ab" -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" -FACE_WITH_DIAGONAL_MOUTH = "\U0001fae4" -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" -FACE_HOLDING_BACK_TEARS = "\U0001f979" -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" -ENRAGED_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" -HEART_ON_FIRE = "\u2764\ufe0f\u200d\U0001f525" -MENDING_HEART = "\u2764\ufe0f\u200d\U0001fa79" -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" -RIGHTWARDS_HAND = "\U0001faf1" -RIGHTWARDS_HAND_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fb" -RIGHTWARDS_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fc" -RIGHTWARDS_HAND_MEDIUM_SKIN_TONE = "\U0001faf1\U0001f3fd" -RIGHTWARDS_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001faf1\U0001f3fe" -RIGHTWARDS_HAND_DARK_SKIN_TONE = "\U0001faf1\U0001f3ff" -LEFTWARDS_HAND = "\U0001faf2" -LEFTWARDS_HAND_LIGHT_SKIN_TONE = "\U0001faf2\U0001f3fb" -LEFTWARDS_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf2\U0001f3fc" -LEFTWARDS_HAND_MEDIUM_SKIN_TONE = "\U0001faf2\U0001f3fd" -LEFTWARDS_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001faf2\U0001f3fe" -LEFTWARDS_HAND_DARK_SKIN_TONE = "\U0001faf2\U0001f3ff" -PALM_DOWN_HAND = "\U0001faf3" -PALM_DOWN_HAND_LIGHT_SKIN_TONE = "\U0001faf3\U0001f3fb" -PALM_DOWN_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf3\U0001f3fc" -PALM_DOWN_HAND_MEDIUM_SKIN_TONE = "\U0001faf3\U0001f3fd" -PALM_DOWN_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001faf3\U0001f3fe" -PALM_DOWN_HAND_DARK_SKIN_TONE = "\U0001faf3\U0001f3ff" -PALM_UP_HAND = "\U0001faf4" -PALM_UP_HAND_LIGHT_SKIN_TONE = "\U0001faf4\U0001f3fb" -PALM_UP_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf4\U0001f3fc" -PALM_UP_HAND_MEDIUM_SKIN_TONE = "\U0001faf4\U0001f3fd" -PALM_UP_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001faf4\U0001f3fe" -PALM_UP_HAND_DARK_SKIN_TONE = "\U0001faf4\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" -HAND_WITH_INDEX_FINGER_AND_THUMB_CROSSED = "\U0001faf0" -HAND_WITH_INDEX_FINGER_AND_THUMB_CROSSED_LIGHT_SKIN_TONE = "\U0001faf0\U0001f3fb" -HAND_WITH_INDEX_FINGER_AND_THUMB_CROSSED_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf0\U0001f3fc" -HAND_WITH_INDEX_FINGER_AND_THUMB_CROSSED_MEDIUM_SKIN_TONE = "\U0001faf0\U0001f3fd" -HAND_WITH_INDEX_FINGER_AND_THUMB_CROSSED_MEDIUM_DARK_SKIN_TONE = "\U0001faf0\U0001f3fe" -HAND_WITH_INDEX_FINGER_AND_THUMB_CROSSED_DARK_SKIN_TONE = "\U0001faf0\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" -INDEX_POINTING_AT_THE_VIEWER = "\U0001faf5" -INDEX_POINTING_AT_THE_VIEWER_LIGHT_SKIN_TONE = "\U0001faf5\U0001f3fb" -INDEX_POINTING_AT_THE_VIEWER_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf5\U0001f3fc" -INDEX_POINTING_AT_THE_VIEWER_MEDIUM_SKIN_TONE = "\U0001faf5\U0001f3fd" -INDEX_POINTING_AT_THE_VIEWER_MEDIUM_DARK_SKIN_TONE = "\U0001faf5\U0001f3fe" -INDEX_POINTING_AT_THE_VIEWER_DARK_SKIN_TONE = "\U0001faf5\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" -HEART_HANDS = "\U0001faf6" -HEART_HANDS_LIGHT_SKIN_TONE = "\U0001faf6\U0001f3fb" -HEART_HANDS_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf6\U0001f3fc" -HEART_HANDS_MEDIUM_SKIN_TONE = "\U0001faf6\U0001f3fd" -HEART_HANDS_MEDIUM_DARK_SKIN_TONE = "\U0001faf6\U0001f3fe" -HEART_HANDS_DARK_SKIN_TONE = "\U0001faf6\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" -HANDSHAKE_LIGHT_SKIN_TONE = "\U0001f91d\U0001f3fb" -HANDSHAKE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f91d\U0001f3fc" -HANDSHAKE_MEDIUM_SKIN_TONE = "\U0001f91d\U0001f3fd" -HANDSHAKE_MEDIUM_DARK_SKIN_TONE = "\U0001f91d\U0001f3fe" -HANDSHAKE_DARK_SKIN_TONE = "\U0001f91d\U0001f3ff" -HANDSHAKE_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fb\u200d\U0001faf2\U0001f3fc" -HANDSHAKE_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = "\U0001faf1\U0001f3fb\u200d\U0001faf2\U0001f3fd" -HANDSHAKE_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = "\U0001faf1\U0001f3fb\u200d\U0001faf2\U0001f3fe" -HANDSHAKE_LIGHT_SKIN_TONE_DARK_SKIN_TONE = "\U0001faf1\U0001f3fb\u200d\U0001faf2\U0001f3ff" -HANDSHAKE_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fc\u200d\U0001faf2\U0001f3fb" -HANDSHAKE_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = "\U0001faf1\U0001f3fc\u200d\U0001faf2\U0001f3fd" -HANDSHAKE_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = "\U0001faf1\U0001f3fc\u200d\U0001faf2\U0001f3fe" -HANDSHAKE_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = "\U0001faf1\U0001f3fc\u200d\U0001faf2\U0001f3ff" -HANDSHAKE_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fd\u200d\U0001faf2\U0001f3fb" -HANDSHAKE_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fd\u200d\U0001faf2\U0001f3fc" -HANDSHAKE_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = "\U0001faf1\U0001f3fd\u200d\U0001faf2\U0001f3fe" -HANDSHAKE_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = "\U0001faf1\U0001f3fd\u200d\U0001faf2\U0001f3ff" -HANDSHAKE_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fe\u200d\U0001faf2\U0001f3fb" -HANDSHAKE_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fe\u200d\U0001faf2\U0001f3fc" -HANDSHAKE_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = "\U0001faf1\U0001f3fe\u200d\U0001faf2\U0001f3fd" -HANDSHAKE_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = "\U0001faf1\U0001f3fe\u200d\U0001faf2\U0001f3ff" -HANDSHAKE_DARK_SKIN_TONE_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3ff\u200d\U0001faf2\U0001f3fb" -HANDSHAKE_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3ff\u200d\U0001faf2\U0001f3fc" -HANDSHAKE_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = "\U0001faf1\U0001f3ff\u200d\U0001faf2\U0001f3fd" -HANDSHAKE_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = "\U0001faf1\U0001f3ff\u200d\U0001faf2\U0001f3fe" -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" -BITING_LIP = "\U0001fae6" -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" -PERSON_BEARD = "\U0001f9d4" -PERSON_LIGHT_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fb" -PERSON_MEDIUM_LIGHT_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fc" -PERSON_MEDIUM_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fd" -PERSON_MEDIUM_DARK_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fe" -PERSON_DARK_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3ff" -MAN_BEARD = "\U0001f9d4\u200d\u2642\ufe0f" -MAN_LIGHT_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fb\u200d\u2642\ufe0f" -MAN_MEDIUM_LIGHT_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fc\u200d\u2642\ufe0f" -MAN_MEDIUM_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fd\u200d\u2642\ufe0f" -MAN_MEDIUM_DARK_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fe\u200d\u2642\ufe0f" -MAN_DARK_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3ff\u200d\u2642\ufe0f" -WOMAN_BEARD = "\U0001f9d4\u200d\u2640\ufe0f" -WOMAN_LIGHT_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fb\u200d\u2640\ufe0f" -WOMAN_MEDIUM_LIGHT_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fc\u200d\u2640\ufe0f" -WOMAN_MEDIUM_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fd\u200d\u2640\ufe0f" -WOMAN_MEDIUM_DARK_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fe\u200d\u2640\ufe0f" -WOMAN_DARK_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3ff\u200d\u2640\ufe0f" -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" -PERSON_WITH_CROWN = "\U0001fac5" -PERSON_WITH_CROWN_LIGHT_SKIN_TONE = "\U0001fac5\U0001f3fb" -PERSON_WITH_CROWN_MEDIUM_LIGHT_SKIN_TONE = "\U0001fac5\U0001f3fc" -PERSON_WITH_CROWN_MEDIUM_SKIN_TONE = "\U0001fac5\U0001f3fd" -PERSON_WITH_CROWN_MEDIUM_DARK_SKIN_TONE = "\U0001fac5\U0001f3fe" -PERSON_WITH_CROWN_DARK_SKIN_TONE = "\U0001fac5\U0001f3ff" -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" -PREGNANT_MAN = "\U0001fac3" -PREGNANT_MAN_LIGHT_SKIN_TONE = "\U0001fac3\U0001f3fb" -PREGNANT_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001fac3\U0001f3fc" -PREGNANT_MAN_MEDIUM_SKIN_TONE = "\U0001fac3\U0001f3fd" -PREGNANT_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001fac3\U0001f3fe" -PREGNANT_MAN_DARK_SKIN_TONE = "\U0001fac3\U0001f3ff" -PREGNANT_PERSON = "\U0001fac4" -PREGNANT_PERSON_LIGHT_SKIN_TONE = "\U0001fac4\U0001f3fb" -PREGNANT_PERSON_MEDIUM_LIGHT_SKIN_TONE = "\U0001fac4\U0001f3fc" -PREGNANT_PERSON_MEDIUM_SKIN_TONE = "\U0001fac4\U0001f3fd" -PREGNANT_PERSON_MEDIUM_DARK_SKIN_TONE = "\U0001fac4\U0001f3fe" -PREGNANT_PERSON_DARK_SKIN_TONE = "\U0001fac4\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" -TROLL = "\U0001f9cc" -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" -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" -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_LIGHT_SKIN_TONE = "\U0001f48f\U0001f3fb" -KISS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f48f\U0001f3fc" -KISS_MEDIUM_SKIN_TONE = "\U0001f48f\U0001f3fd" -KISS_MEDIUM_DARK_SKIN_TONE = "\U0001f48f\U0001f3fe" -KISS_DARK_SKIN_TONE = "\U0001f48f\U0001f3ff" -KISS_PERSON_PERSON_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fc" -KISS_PERSON_PERSON_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fd" -KISS_PERSON_PERSON_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fe" -KISS_PERSON_PERSON_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3ff" -KISS_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fb" -KISS_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fd" -KISS_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fe" -KISS_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3ff" -KISS_PERSON_PERSON_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fb" -KISS_PERSON_PERSON_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fc" -KISS_PERSON_PERSON_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fe" -KISS_PERSON_PERSON_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3ff" -KISS_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fb" -KISS_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fc" -KISS_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fd" -KISS_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3ff" -KISS_PERSON_PERSON_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fb" -KISS_PERSON_PERSON_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fc" -KISS_PERSON_PERSON_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fd" -KISS_PERSON_PERSON_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fe" -KISS_WOMAN_MAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468" -KISS_WOMAN_MAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" -KISS_WOMAN_MAN_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" -KISS_WOMAN_MAN_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" -KISS_WOMAN_MAN_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" -KISS_WOMAN_MAN_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" -KISS_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" -KISS_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" -KISS_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" -KISS_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" -KISS_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" -KISS_WOMAN_MAN_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" -KISS_WOMAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" -KISS_WOMAN_MAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" -KISS_WOMAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" -KISS_WOMAN_MAN_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" -KISS_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" -KISS_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" -KISS_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" -KISS_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" -KISS_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" -KISS_WOMAN_MAN_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" -KISS_WOMAN_MAN_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" -KISS_WOMAN_MAN_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" -KISS_WOMAN_MAN_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" -KISS_WOMAN_MAN_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" -KISS_MAN_MAN = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468" -KISS_MAN_MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" -KISS_MAN_MAN_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" -KISS_MAN_MAN_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" -KISS_MAN_MAN_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" -KISS_MAN_MAN_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" -KISS_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" -KISS_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" -KISS_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" -KISS_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" -KISS_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" -KISS_MAN_MAN_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" -KISS_MAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" -KISS_MAN_MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" -KISS_MAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" -KISS_MAN_MAN_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" -KISS_MAN_MAN_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" -KISS_MAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" -KISS_MAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" -KISS_MAN_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" -KISS_MAN_MAN_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" -KISS_MAN_MAN_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" -KISS_MAN_MAN_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" -KISS_MAN_MAN_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" -KISS_MAN_MAN_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" -KISS_MAN_MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" -KISS_WOMAN_WOMAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469" -KISS_WOMAN_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb" -KISS_WOMAN_WOMAN_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc" -KISS_WOMAN_WOMAN_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd" -KISS_WOMAN_WOMAN_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe" -KISS_WOMAN_WOMAN_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff" -KISS_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb" -KISS_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc" -KISS_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd" -KISS_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe" -KISS_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff" -KISS_WOMAN_WOMAN_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb" -KISS_WOMAN_WOMAN_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc" -KISS_WOMAN_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd" -KISS_WOMAN_WOMAN_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe" -KISS_WOMAN_WOMAN_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff" -KISS_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb" -KISS_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc" -KISS_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd" -KISS_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe" -KISS_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff" -KISS_WOMAN_WOMAN_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb" -KISS_WOMAN_WOMAN_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc" -KISS_WOMAN_WOMAN_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd" -KISS_WOMAN_WOMAN_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe" -KISS_WOMAN_WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff" -COUPLE_WITH_HEART = "\U0001f491" -COUPLE_WITH_HEART_LIGHT_SKIN_TONE = "\U0001f491\U0001f3fb" -COUPLE_WITH_HEART_MEDIUM_LIGHT_SKIN_TONE = "\U0001f491\U0001f3fc" -COUPLE_WITH_HEART_MEDIUM_SKIN_TONE = "\U0001f491\U0001f3fd" -COUPLE_WITH_HEART_MEDIUM_DARK_SKIN_TONE = "\U0001f491\U0001f3fe" -COUPLE_WITH_HEART_DARK_SKIN_TONE = "\U0001f491\U0001f3ff" -COUPLE_WITH_HEART_PERSON_PERSON_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fc" -COUPLE_WITH_HEART_PERSON_PERSON_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fd" -COUPLE_WITH_HEART_PERSON_PERSON_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fe" -COUPLE_WITH_HEART_PERSON_PERSON_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3ff" -COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fb" -COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fd" -COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fe" -COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3ff" -COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fb" -COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fc" -COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fe" -COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3ff" -COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fb" -COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fc" -COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fd" -COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3ff" -COUPLE_WITH_HEART_PERSON_PERSON_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fb" -COUPLE_WITH_HEART_PERSON_PERSON_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fc" -COUPLE_WITH_HEART_PERSON_PERSON_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fd" -COUPLE_WITH_HEART_PERSON_PERSON_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fe" -COUPLE_WITH_HEART_WOMAN_MAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f468" -COUPLE_WITH_HEART_WOMAN_MAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" -COUPLE_WITH_HEART_WOMAN_MAN_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" -COUPLE_WITH_HEART_WOMAN_MAN_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" -COUPLE_WITH_HEART_WOMAN_MAN_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" -COUPLE_WITH_HEART_WOMAN_MAN_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" -COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" -COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" -COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" -COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" -COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" -COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" -COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" -COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" -COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" -COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" -COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" -COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" -COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" -COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" -COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" -COUPLE_WITH_HEART_WOMAN_MAN_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" -COUPLE_WITH_HEART_WOMAN_MAN_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" -COUPLE_WITH_HEART_WOMAN_MAN_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" -COUPLE_WITH_HEART_WOMAN_MAN_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" -COUPLE_WITH_HEART_WOMAN_MAN_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" -COUPLE_WITH_HEART_MAN_MAN = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f468" -COUPLE_WITH_HEART_MAN_MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" -COUPLE_WITH_HEART_MAN_MAN_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" -COUPLE_WITH_HEART_MAN_MAN_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" -COUPLE_WITH_HEART_MAN_MAN_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" -COUPLE_WITH_HEART_MAN_MAN_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" -COUPLE_WITH_HEART_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" -COUPLE_WITH_HEART_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" -COUPLE_WITH_HEART_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" -COUPLE_WITH_HEART_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" -COUPLE_WITH_HEART_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" -COUPLE_WITH_HEART_MAN_MAN_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" -COUPLE_WITH_HEART_MAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" -COUPLE_WITH_HEART_MAN_MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" -COUPLE_WITH_HEART_MAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" -COUPLE_WITH_HEART_MAN_MAN_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" -COUPLE_WITH_HEART_MAN_MAN_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" -COUPLE_WITH_HEART_MAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" -COUPLE_WITH_HEART_MAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" -COUPLE_WITH_HEART_MAN_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" -COUPLE_WITH_HEART_MAN_MAN_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" -COUPLE_WITH_HEART_MAN_MAN_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" -COUPLE_WITH_HEART_MAN_MAN_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" -COUPLE_WITH_HEART_MAN_MAN_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" -COUPLE_WITH_HEART_MAN_MAN_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" -COUPLE_WITH_HEART_MAN_MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" -COUPLE_WITH_HEART_WOMAN_WOMAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f469" -COUPLE_WITH_HEART_WOMAN_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb" -COUPLE_WITH_HEART_WOMAN_WOMAN_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc" -COUPLE_WITH_HEART_WOMAN_WOMAN_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd" -COUPLE_WITH_HEART_WOMAN_WOMAN_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe" -COUPLE_WITH_HEART_WOMAN_WOMAN_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff" -COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb" -COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc" -COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd" -COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe" -COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff" -COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb" -COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc" -COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd" -COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe" -COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff" -COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb" -COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc" -COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd" -COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe" -COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff" -COUPLE_WITH_HEART_WOMAN_WOMAN_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb" -COUPLE_WITH_HEART_WOMAN_WOMAN_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc" -COUPLE_WITH_HEART_WOMAN_WOMAN_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd" -COUPLE_WITH_HEART_WOMAN_WOMAN_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ - "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe" -COUPLE_WITH_HEART_WOMAN_WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff" -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" -CORAL = "\U0001fab8" -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" -LOTUS = "\U0001fab7" -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" -EMPTY_NEST = "\U0001fab9" -NEST_WITH_EGGS = "\U0001faba" -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" -BEANS = "\U0001fad8" -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" -POURING_LIQUID = "\U0001fad7" -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" -JAR = "\U0001fad9" -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" -PLAYGROUND_SLIDE = "\U0001f6dd" -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" -WHEEL = "\U0001f6de" -POLICE_CAR_LIGHT = "\U0001f6a8" -HORIZONTAL_TRAFFIC_LIGHT = "\U0001f6a5" -VERTICAL_TRAFFIC_LIGHT = "\U0001f6a6" -STOP_SIGN = "\U0001f6d1" -CONSTRUCTION = "\U0001f6a7" -ANCHOR = "\u2693" -RING_BUOY = "\U0001f6df" -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" -BULLSEYE = "\U0001f3af" -YO_YO = "\U0001fa80" -KITE = "\U0001fa81" -POOL_8_BALL = "\U0001f3b1" -CRYSTAL_BALL = "\U0001f52e" -MAGIC_WAND = "\U0001fa84" -NAZAR_AMULET = "\U0001f9ff" -HAMSA = "\U0001faac" -VIDEO_GAME = "\U0001f3ae" -JOYSTICK = "\U0001f579\ufe0f" -SLOT_MACHINE = "\U0001f3b0" -GAME_DIE = "\U0001f3b2" -PUZZLE_PIECE = "\U0001f9e9" -TEDDY_BEAR = "\U0001f9f8" -PINATA = "\U0001fa85" -MIRROR_BALL = "\U0001faa9" -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" -LOW_BATTERY = "\U0001faab" -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" -WATER_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" -CRUTCH = "\U0001fa7c" -STETHOSCOPE = "\U0001fa7a" -X_RAY = "\U0001fa7b" -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" -BUBBLES = "\U0001fae7" -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" -IDENTIFICATION_CARD = "\U0001faaa" -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" -HEAVY_EQUALS_SIGN = "\U0001f7f0" -INFINITY = "\u267e\ufe0f" -DOUBLE_EXCLAMATION_MARK = "\u203c\ufe0f" -EXCLAMATION_QUESTION_MARK = "\u2049\ufe0f" -RED_QUESTION_MARK = "\u2753" -WHITE_QUESTION_MARK = "\u2754" -WHITE_EXCLAMATION_MARK = "\u2755" -RED_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_RIGHT_CURLY_BRACKET = "\U000e007d" -DIGIT_FIVE = "5\ufe0f" -TAG_LATIN_CAPITAL_LETTER_U = "\U000e0055" -TAG_LATIN_CAPITAL_LETTER_Q = "\U000e0051" -TAG_LATIN_CAPITAL_LETTER_K = "\U000e004b" -COMBINING_ENCLOSING_KEYCAP = "\u20e3" -TAG_LATIN_CAPITAL_LETTER_C = "\U000e0043" -TAG_ASTERISK = "\U000e002a" -TAG_FULL_STOP = "\U000e002e" -TAG_CIRCUMFLEX_ACCENT = "\U000e005e" -DIGIT_ONE = "1\ufe0f" -TAG_COMMA = "\U000e002c" -DIGIT_ZERO = "0\ufe0f" -TAG_EQUALS_SIGN = "\U000e003d" -TAG_LATIN_CAPITAL_LETTER_O = "\U000e004f" -TAG_COMMERCIAL_AT = "\U000e0040" -DIGIT_EIGHT = "8\ufe0f" -TAG_NUMBER_SIGN = "\U000e0023" -TAG_LATIN_CAPITAL_LETTER_T = "\U000e0054" -TAG_LATIN_CAPITAL_LETTER_N = "\U000e004e" -DIGIT_SIX = "6\ufe0f" -TAG_PERCENT_SIGN = "\U000e0025" -VARIATION_SELECTOR_16 = "\ufe0f" -TAG_LATIN_CAPITAL_LETTER_W = "\U000e0057" -TAG_DOLLAR_SIGN = "\U000e0024" -TAG_LOW_LINE = "\U000e005f" -TAG_DIGIT_EIGHT = "\U000e0038" -TAG_LATIN_CAPITAL_LETTER_M = "\U000e004d" -TAG_LATIN_CAPITAL_LETTER_A = "\U000e0041" -TAG_REVERSE_SOLIDUS = "\U000e005c" -TAG_SOLIDUS = "\U000e002f" -TAG_LATIN_CAPITAL_LETTER_H = "\U000e0048" -TAG_DIGIT_NINE = "\U000e0039" -TAG_LEFT_CURLY_BRACKET = "\U000e007b" -TAG_LATIN_CAPITAL_LETTER_E = "\U000e0045" -TAG_LATIN_SMALL_LETTER_W = "\U000e0077" -TAG_DIGIT_ZERO = "\U000e0030" -TAG_LATIN_CAPITAL_LETTER_B = "\U000e0042" -TAG_LATIN_CAPITAL_LETTER_F = "\U000e0046" -TAG_LATIN_CAPITAL_LETTER_Y = "\U000e0059" -TAG_TILDE = "\U000e007e" -TAG_LATIN_SMALL_LETTER_P = "\U000e0070" -TAG_LATIN_CAPITAL_LETTER_Z = "\U000e005a" -TAG_GREATER_THAN_SIGN = "\U000e003e" -TAG_LATIN_SMALL_LETTER_S = "\U000e0073" -TAG_LATIN_SMALL_LETTER_G = "\U000e0067" -TAG_APOSTROPHE = "\U000e0027" -TAG_RIGHT_PARENTHESIS = "\U000e0029" -TAG_DIGIT_THREE = "\U000e0033" -TAG_LEFT_PARENTHESIS = "\U000e0028" -TAG_DIGIT_SEVEN = "\U000e0037" -TAG_LATIN_SMALL_LETTER_O = "\U000e006f" -TAG_DIGIT_SIX = "\U000e0036" -TAG_DIGIT_TWO = "\U000e0032" -TAG_LATIN_SMALL_LETTER_F = "\U000e0066" -TAG_LATIN_SMALL_LETTER_K = "\U000e006b" -TAG_LATIN_SMALL_LETTER_Y = "\U000e0079" -TAG_SPACE = "\U000e0020" -TAG_LATIN_SMALL_LETTER_I = "\U000e0069" -DIGIT_TWO = "2\ufe0f" -TAG_DIGIT_ONE = "\U000e0031" -TAG_RIGHT_SQUARE_BRACKET = "\U000e005d" -TAG_LATIN_SMALL_LETTER_R = "\U000e0072" -HASH_SIGN = "#\ufe0f" -TAG_SEMICOLON = "\U000e003b" -TAG_LATIN_CAPITAL_LETTER_L = "\U000e004c" -TAG_HYPHEN_MINUS = "\U000e002d" -ASTERISK = "*\ufe0f" -TAG_LATIN_SMALL_LETTER_A = "\U000e0061" -TAG_EXCLAMATION_MARK = "\U000e0021" -TAG_LATIN_CAPITAL_LETTER_V = "\U000e0056" -TAG_LATIN_SMALL_LETTER_C = "\U000e0063" -TAG_GRAVE_ACCENT = "\U000e0060" -ZERO_WIDTH_JOINER = "\u200d" -TAG_LATIN_CAPITAL_LETTER_G = "\U000e0047" -DIGIT_NINE = "9\ufe0f" -TAG_VERTICAL_LINE = "\U000e007c" -TAG_LATIN_SMALL_LETTER_Z = "\U000e007a" -TAG_LATIN_CAPITAL_LETTER_X = "\U000e0058" -TAG_LATIN_SMALL_LETTER_J = "\U000e006a" -TAG_LATIN_CAPITAL_LETTER_P = "\U000e0050" -TAG_AMPERSAND = "\U000e0026" -TAG_LATIN_SMALL_LETTER_L = "\U000e006c" -TAG_LATIN_SMALL_LETTER_X = "\U000e0078" -DIGIT_SEVEN = "7\ufe0f" -TAG_LATIN_CAPITAL_LETTER_J = "\U000e004a" -TAG_LATIN_SMALL_LETTER_T = "\U000e0074" -TAG_QUESTION_MARK = "\U000e003f" -TAG_LATIN_SMALL_LETTER_B = "\U000e0062" -TAG_LEFT_SQUARE_BRACKET = "\U000e005b" -TAG_LATIN_SMALL_LETTER_D = "\U000e0064" -TAG_LATIN_SMALL_LETTER_E = "\U000e0065" -TAG_LATIN_SMALL_LETTER_M = "\U000e006d" -TAG_LESS_THAN_SIGN = "\U000e003c" -TAG_DIGIT_FIVE = "\U000e0035" -TAG_LATIN_CAPITAL_LETTER_D = "\U000e0044" -TAG_LATIN_SMALL_LETTER_N = "\U000e006e" -TAG_PLUS_SIGN = "\U000e002b" -TAG_COLON = "\U000e003a" -DIGIT_THREE = "3\ufe0f" -TAG_LATIN_SMALL_LETTER_Q = "\U000e0071" -TAG_LATIN_CAPITAL_LETTER_R = "\U000e0052" -TAG_LATIN_CAPITAL_LETTER_S = "\U000e0053" -DIGIT_FOUR = "4\ufe0f" -TAG_LATIN_CAPITAL_LETTER_I = "\U000e0049" -TAG_QUOTATION_MARK = "\U000e0022" -CANCEL_TAG = "\U000e007f" -TAG_LATIN_SMALL_LETTER_V = "\U000e0076" -TAG_LATIN_SMALL_LETTER_H = "\U000e0068" -TAG_LATIN_SMALL_LETTER_U = "\U000e0075" -TAG_DIGIT_FOUR = "\U000e0034" From d84a818aaeec68e6c35154b7f56d70f269e5d22b Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:27:33 +0545 Subject: [PATCH 018/103] Delete pyrogram/utils.py --- pyrogram/utils.py | 371 ---------------------------------------------- 1 file changed, 371 deletions(-) delete mode 100644 pyrogram/utils.py diff --git a/pyrogram/utils.py b/pyrogram/utils.py deleted file mode 100644 index f7fe59706d..0000000000 --- a/pyrogram/utils.py +++ /dev/null @@ -1,371 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-present 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 base64 -import functools -import hashlib -import os -import struct -from concurrent.futures.thread import ThreadPoolExecutor -from datetime import datetime, timezone -from getpass import getpass -from typing import Union, List, Dict, Optional - -import pyrogram -from pyrogram import raw, enums -from pyrogram import types -from pyrogram.file_id import FileId, FileType, PHOTO_TYPES, DOCUMENT_TYPES - - -async def ainput(prompt: str = "", *, hide: bool = False): - """Just like the built-in input, but async""" - with ThreadPoolExecutor(1) as executor: - func = functools.partial(getpass if hide else input, prompt) - return await asyncio.get_event_loop().run_in_executor(executor, func) - - -def get_input_media_from_file_id( - file_id: str, - expected_file_type: FileType = None, - ttl_seconds: int = None -) -> Union["raw.types.InputMediaPhoto", "raw.types.InputMediaDocument"]: - try: - decoded = FileId.decode(file_id) - except Exception: - raise ValueError( - f'Failed to decode "{file_id}". The value does not represent an existing local file, ' - f"HTTP URL, or valid file id." - ) - - file_type = decoded.file_type - - if expected_file_type is not None and file_type != expected_file_type: - raise ValueError(f"Expected {expected_file_type.name}, got {file_type.name} file id instead") - - if file_type in (FileType.THUMBNAIL, FileType.CHAT_PHOTO): - raise ValueError(f"This file id can only be used for download: {file_id}") - - if file_type in PHOTO_TYPES: - return raw.types.InputMediaPhoto( - id=raw.types.InputPhoto( - id=decoded.media_id, - access_hash=decoded.access_hash, - file_reference=decoded.file_reference - ), - ttl_seconds=ttl_seconds - ) - - if file_type in DOCUMENT_TYPES: - return raw.types.InputMediaDocument( - id=raw.types.InputDocument( - id=decoded.media_id, - access_hash=decoded.access_hash, - file_reference=decoded.file_reference - ), - ttl_seconds=ttl_seconds - ) - - raise ValueError(f"Unknown file id: {file_id}") - - -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 types.List() - - parsed_messages = [] - - for message in messages.messages: - parsed_messages.append(await types.Message._parse(client, message, users, chats, replies=0)) - - if replies: - messages_with_replies = { - i.id: i.reply_to.reply_to_msg_id - for i in messages.messages - if not isinstance(i, raw.types.MessageEmpty) and i.reply_to - } - - if messages_with_replies: - # 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( - chat_id, - reply_to_message_ids=messages_with_replies.keys(), - replies=replies - 1 - ) - - for message in parsed_messages: - reply_id = messages_with_replies.get(message.id, None) - - for reply in reply_messages: - if reply.id == reply_id: - message.reply_to_message = reply - - return types.List(parsed_messages) - - -def parse_deleted_messages(client, update) -> List["types.Message"]: - messages = update.messages - channel_id = getattr(update, "channel_id", None) - - parsed_messages = [] - - for message in messages: - parsed_messages.append( - types.Message( - id=message, - chat=types.Chat( - id=get_channel_id(channel_id), - type=enums.ChatType.CHANNEL, - client=client - ) if channel_id is not None else None, - client=client - ) - ) - - return types.List(parsed_messages) - - -def pack_inline_message_id(msg_id: "raw.base.InputBotInlineMessageID"): - if isinstance(msg_id, raw.types.InputBotInlineMessageID): - inline_message_id_packed = struct.pack( - " Optional[int]: - """Get the raw peer id from a Peer object""" - if isinstance(peer, raw.types.PeerUser): - return peer.user_id - - if isinstance(peer, raw.types.PeerChat): - return peer.chat_id - - if isinstance(peer, raw.types.PeerChannel): - return peer.channel_id - - return None - - -def get_peer_id(peer: raw.base.Peer) -> int: - """Get the non-raw peer id from a Peer object""" - if isinstance(peer, raw.types.PeerUser): - return peer.user_id - - if isinstance(peer, raw.types.PeerChat): - return -peer.chat_id - - if isinstance(peer, raw.types.PeerChannel): - return MAX_CHANNEL_ID - peer.channel_id - - raise ValueError(f"Peer type invalid: {peer}") - - -def get_peer_type(peer_id: int) -> str: - if peer_id < 0: - if MIN_CHAT_ID <= peer_id: - return "chat" - - if MIN_CHANNEL_ID <= peer_id < MAX_CHANNEL_ID: - return "channel" - elif 0 < peer_id <= MAX_USER_ID: - return "user" - - 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) - - -async def parse_text_entities( - client: "pyrogram.Client", - text: str, - parse_mode: enums.ParseMode, - entities: List["types.MessageEntity"] -) -> Dict[str, Union[str, List[raw.base.MessageEntity]]]: - if entities: - # Inject the client instance because parsing user mentions requires it - for entity in entities: - entity._client = client - - text, entities = text, [await entity.write() for entity in entities] or None - else: - text, entities = (await client.parser.parse(text, parse_mode)).values() - - return { - "message": text, - "entities": entities - } - - -def zero_datetime() -> datetime: - return datetime.fromtimestamp(0, timezone.utc) - - -def timestamp_to_datetime(ts: Optional[int]) -> Optional[datetime]: - return datetime.fromtimestamp(ts) if ts else None - - -def datetime_to_timestamp(dt: Optional[datetime]) -> Optional[int]: - return int(dt.timestamp()) if dt else None From ec600fe3eaedcf33fe48fba59397178707385668 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:27:45 +0545 Subject: [PATCH 019/103] Delete pyrogram/sync.py --- pyrogram/sync.py | 113 ----------------------------------------------- 1 file changed, 113 deletions(-) delete mode 100644 pyrogram/sync.py diff --git a/pyrogram/sync.py b/pyrogram/sync.py deleted file mode 100644 index 94c82a3dd6..0000000000 --- a/pyrogram/sync.py +++ /dev/null @@ -1,113 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-present 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, compose as compose_module - - -def async_to_sync(obj, name): - function = getattr(obj, name) - main_loop = asyncio.get_event_loop() - - def async_to_sync_gen(agen, loop, is_main_thread): - async def anext(agen): - try: - return await agen.__anext__(), False - except StopAsyncIteration: - return None, True - - while True: - if is_main_thread: - item, done = loop.run_until_complete(anext(agen)) - else: - item, done = asyncio.run_coroutine_threadsafe(anext(agen), loop).result() - - if done: - break - - yield item - - @functools.wraps(function) - def async_to_sync_wrap(*args, **kwargs): - coroutine = function(*args, **kwargs) - - try: - loop = asyncio.get_event_loop() - except RuntimeError: - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - - if threading.current_thread() is threading.main_thread() or not main_loop.is_running(): - if loop.is_running(): - return coroutine - else: - if inspect.iscoroutine(coroutine): - return loop.run_until_complete(coroutine) - - if inspect.isasyncgen(coroutine): - return async_to_sync_gen(coroutine, loop, True) - else: - if inspect.iscoroutine(coroutine): - if loop.is_running(): - async def coro_wrapper(): - return await asyncio.wrap_future(asyncio.run_coroutine_threadsafe(coroutine, main_loop)) - - return coro_wrapper() - else: - return asyncio.run_coroutine_threadsafe(coroutine, main_loop).result() - - if inspect.isasyncgen(coroutine): - if loop.is_running(): - return coroutine - else: - return async_to_sync_gen(coroutine, main_loop, False) - - 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 and compose, because they are not inside Methods -async_to_sync(idle_module, "idle") -idle = getattr(idle_module, "idle") - -async_to_sync(compose_module, "compose") -compose = getattr(compose_module, "compose") From af51fba7ae30dc5c60c99bd8789fa8219b803991 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:27:57 +0545 Subject: [PATCH 020/103] Delete pyrogram/mime_types.py --- pyrogram/mime_types.py | 1881 ---------------------------------------- 1 file changed, 1881 deletions(-) delete mode 100644 pyrogram/mime_types.py diff --git a/pyrogram/mime_types.py b/pyrogram/mime_types.py deleted file mode 100644 index 2f6c86aa8b..0000000000 --- a/pyrogram/mime_types.py +++ /dev/null @@ -1,1881 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-present 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 https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types. -# Extended with extra mime types specific to Telegram. -mime_types = """ -# This file maps Internet media types to unique file extension(s). -# Although created for httpd, this file is used by many software systems -# and has been placed in the public domain for unlimited redistribution. -# -# The table below contains both registered and (common) unregistered types. -# A type that has no unique extension can be ignored -- they are listed -# here to guide configurations toward known types and to make it easier to -# identify "new" types. File extensions are also commonly used to indicate -# content languages and encodings, so choose them carefully. -# -# Internet media types should be registered as described in RFC 4288. -# The registry is at . -# -# MIME type (lowercased) Extensions -# ============================================ ========== -# application/1d-interleaved-parityfec -# application/3gpdash-qoe-report+xml -# application/3gpp-ims+xml -# application/a2l -# application/activemessage -# application/alto-costmap+json -# application/alto-costmapfilter+json -# application/alto-directory+json -# application/alto-endpointcost+json -# application/alto-endpointcostparams+json -# application/alto-endpointprop+json -# application/alto-endpointpropparams+json -# application/alto-error+json -# application/alto-networkmap+json -# application/alto-networkmapfilter+json -# application/aml -application/andrew-inset ez -# application/applefile -application/applixware aw -# application/atf -# application/atfx -application/atom+xml atom -application/atomcat+xml atomcat -# application/atomdeleted+xml -# application/atomicmail -application/atomsvc+xml atomsvc -# application/atxml -# application/auth-policy+xml -# application/bacnet-xdd+zip -# application/batch-smtp -# application/beep+xml -# application/calendar+json -# application/calendar+xml -# application/call-completion -# application/cals-1840 -# application/cbor -# application/ccmp+xml -application/ccxml+xml ccxml -# application/cdfx+xml -application/cdmi-capability cdmia -application/cdmi-container cdmic -application/cdmi-domain cdmid -application/cdmi-object cdmio -application/cdmi-queue cdmiq -# application/cdni -# application/cea -# application/cea-2018+xml -# application/cellml+xml -# application/cfw -# application/cms -# application/cnrp+xml -# application/coap-group+json -# application/commonground -# application/conference-info+xml -# application/cpl+xml -# application/csrattrs -# application/csta+xml -# application/cstadata+xml -# application/csvm+json -application/cu-seeme cu -# application/cybercash -# application/dash+xml -# application/dashdelta -application/davmount+xml davmount -# application/dca-rft -# application/dcd -# application/dec-dx -# application/dialog-info+xml -# application/dicom -# application/dii -# application/dit -# application/dns -application/docbook+xml dbk -# application/dskpp+xml -application/dssc+der dssc -application/dssc+xml xdssc -# application/dvcs -application/ecmascript ecma -# application/edi-consent -# application/edi-x12 -# application/edifact -# application/efi -# application/emergencycalldata.comment+xml -# application/emergencycalldata.deviceinfo+xml -# application/emergencycalldata.providerinfo+xml -# application/emergencycalldata.serviceinfo+xml -# application/emergencycalldata.subscriberinfo+xml -application/emma+xml emma -# application/emotionml+xml -# application/encaprtp -# application/epp+xml -application/epub+zip epub -# application/eshop -# application/example -application/exi exi -# application/fastinfoset -# application/fastsoap -# application/fdt+xml -# application/fits -application/font-tdpfr pfr -# application/framework-attributes+xml -# application/geo+json -application/gml+xml gml -application/gpx+xml gpx -application/gxf gxf -# application/gzip -# application/h224 -# application/held+xml -# application/http -application/hyperstudio stk -# application/ibe-key-request+xml -# application/ibe-pkg-reply+xml -# application/ibe-pp-data -# application/iges -# application/im-iscomposing+xml -# application/index -# application/index.cmd -# application/index.obj -# application/index.response -# application/index.vnd -application/inkml+xml ink inkml -# application/iotp -application/ipfix ipfix -# application/ipp -# application/isup -# application/its+xml -application/java-archive jar -application/java-serialized-object ser -application/java-vm class -application/javascript js -# application/jose -# application/jose+json -# application/jrd+json -application/json json -# application/json-patch+json -# application/json-seq -application/jsonml+json jsonml -# application/jwk+json -# application/jwk-set+json -# application/jwt -# application/kpml-request+xml -# application/kpml-response+xml -# application/ld+json -# application/lgr+xml -# application/link-format -# application/load-control+xml -application/lost+xml lostxml -# application/lostsync+xml -# application/lxf -application/mac-binhex40 hqx -application/mac-compactpro cpt -# application/macwriteii -application/mads+xml mads -application/marc mrc -application/marcxml+xml mrcx -application/mathematica ma nb mb -application/mathml+xml mathml -# application/mathml-content+xml -# application/mathml-presentation+xml -# application/mbms-associated-procedure-description+xml -# application/mbms-deregister+xml -# application/mbms-envelope+xml -# application/mbms-msk+xml -# application/mbms-msk-response+xml -# application/mbms-protection-description+xml -# application/mbms-reception-report+xml -# application/mbms-register+xml -# application/mbms-register-response+xml -# application/mbms-schedule+xml -# application/mbms-user-service-description+xml -application/mbox mbox -# application/media-policy-dataset+xml -# application/media_control+xml -application/mediaservercontrol+xml mscml -# application/merge-patch+json -application/metalink+xml metalink -application/metalink4+xml meta4 -application/mets+xml mets -# application/mf4 -# application/mikey -application/mods+xml mods -# application/moss-keys -# application/moss-signature -# application/mosskey-data -# application/mosskey-request -application/mp21 m21 mp21 -application/mp4 mp4s -# application/mpeg4-generic -# application/mpeg4-iod -# application/mpeg4-iod-xmt -# application/mrb-consumer+xml -# application/mrb-publish+xml -# application/msc-ivr+xml -# application/msc-mixer+xml -application/msword doc dot -application/mxf mxf -# application/nasdata -# application/news-checkgroups -# application/news-groupinfo -# application/news-transmission -# application/nlsml+xml -# application/nss -# application/ocsp-request -# application/ocsp-response -application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy -application/oda oda -# application/odx -application/oebps-package+xml opf -application/ogg ogx -application/omdoc+xml omdoc -application/onenote onetoc onetoc2 onetmp onepkg -application/oxps oxps -# application/p2p-overlay+xml -# application/parityfec -application/patch-ops-error+xml xer -application/pdf pdf -# application/pdx -application/pgp-encrypted pgp -# application/pgp-keys -application/pgp-signature asc sig -application/pics-rules prf -# application/pidf+xml -# application/pidf-diff+xml -application/pkcs10 p10 -# application/pkcs12 -application/pkcs7-mime p7m p7c -application/pkcs7-signature p7s -application/pkcs8 p8 -application/pkix-attr-cert ac -application/pkix-cert cer -application/pkix-crl crl -application/pkix-pkipath pkipath -application/pkixcmp pki -application/pls+xml pls -# application/poc-settings+xml -application/postscript ai eps ps -# application/ppsp-tracker+json -# application/problem+json -# application/problem+xml -# application/provenance+xml -# application/prs.alvestrand.titrax-sheet -application/prs.cww cww -# application/prs.hpub+zip -# application/prs.nprend -# application/prs.plucker -# application/prs.rdf-xml-crypt -# application/prs.xsf+xml -application/pskc+xml pskcxml -# application/qsig -# application/raptorfec -# application/rdap+json -application/rdf+xml rdf -application/reginfo+xml rif -application/relax-ng-compact-syntax rnc -# application/remote-printing -# application/reputon+json -application/resource-lists+xml rl -application/resource-lists-diff+xml rld -# application/rfc+xml -# application/riscos -# application/rlmi+xml -application/rls-services+xml rs -application/rpki-ghostbusters gbr -application/rpki-manifest mft -application/rpki-roa roa -# application/rpki-updown -application/rsd+xml rsd -application/rss+xml rss -application/rtf rtf -# application/rtploopback -# application/rtx -# application/samlassertion+xml -# application/samlmetadata+xml -application/sbml+xml sbml -# application/scaip+xml -# application/scim+json -application/scvp-cv-request scq -application/scvp-cv-response scs -application/scvp-vp-request spq -application/scvp-vp-response spp -application/sdp sdp -# application/sep+xml -# application/sep-exi -# application/session-info -# application/set-payment -application/set-payment-initiation setpay -# application/set-registration -application/set-registration-initiation setreg -# application/sgml -# application/sgml-open-catalog -application/shf+xml shf -# application/sieve -# application/simple-filter+xml -# application/simple-message-summary -# application/simplesymbolcontainer -# application/slate -# application/smil -application/smil+xml smi smil -# application/smpte336m -# application/soap+fastinfoset -# application/soap+xml -application/sparql-query rq -application/sparql-results+xml srx -# application/spirits-event+xml -# application/sql -application/srgs gram -application/srgs+xml grxml -application/sru+xml sru -application/ssdl+xml ssdl -application/ssml+xml ssml -# application/tamp-apex-update -# application/tamp-apex-update-confirm -# application/tamp-community-update -# application/tamp-community-update-confirm -# application/tamp-error -# application/tamp-sequence-adjust -# application/tamp-sequence-adjust-confirm -# application/tamp-status-query -# application/tamp-status-response -# application/tamp-update -# application/tamp-update-confirm -application/tei+xml tei teicorpus -application/thraud+xml tfi -# application/timestamp-query -# application/timestamp-reply -application/timestamped-data tsd -# application/ttml+xml -# application/tve-trigger -# application/ulpfec -# application/urc-grpsheet+xml -# application/urc-ressheet+xml -# application/urc-targetdesc+xml -# application/urc-uisocketdesc+xml -# application/vcard+json -# application/vcard+xml -# application/vemmi -# application/vividence.scriptfile -# application/vnd.3gpp-prose+xml -# application/vnd.3gpp-prose-pc3ch+xml -# application/vnd.3gpp.access-transfer-events+xml -# application/vnd.3gpp.bsf+xml -# application/vnd.3gpp.mid-call+xml -application/vnd.3gpp.pic-bw-large plb -application/vnd.3gpp.pic-bw-small psb -application/vnd.3gpp.pic-bw-var pvb -# application/vnd.3gpp.sms -# application/vnd.3gpp.sms+xml -# application/vnd.3gpp.srvcc-ext+xml -# application/vnd.3gpp.srvcc-info+xml -# application/vnd.3gpp.state-and-event-info+xml -# application/vnd.3gpp.ussd+xml -# application/vnd.3gpp2.bcmcsinfo+xml -# application/vnd.3gpp2.sms -application/vnd.3gpp2.tcap tcap -# application/vnd.3lightssoftware.imagescal -application/vnd.3m.post-it-notes pwn -application/vnd.accpac.simply.aso aso -application/vnd.accpac.simply.imp imp -application/vnd.acucobol acu -application/vnd.acucorp atc acutc -application/vnd.adobe.air-application-installer-package+zip air -# application/vnd.adobe.flash.movie -application/vnd.adobe.formscentral.fcdt fcdt -application/vnd.adobe.fxp fxp fxpl -# application/vnd.adobe.partial-upload -application/vnd.adobe.xdp+xml xdp -application/vnd.adobe.xfdf xfdf -# application/vnd.aether.imp -# application/vnd.ah-barcode -application/vnd.ahead.space ahead -application/vnd.airzip.filesecure.azf azf -application/vnd.airzip.filesecure.azs azs -application/vnd.amazon.ebook azw -# application/vnd.amazon.mobi8-ebook -application/vnd.americandynamics.acc acc -application/vnd.amiga.ami ami -# application/vnd.amundsen.maze+xml -application/vnd.android.package-archive apk -# application/vnd.anki -application/vnd.anser-web-certificate-issue-initiation cii -application/vnd.anser-web-funds-transfer-initiation fti -application/vnd.antix.game-component atx -# application/vnd.apache.thrift.binary -# application/vnd.apache.thrift.compact -# application/vnd.apache.thrift.json -# application/vnd.api+json -application/vnd.apple.installer+xml mpkg -application/vnd.apple.mpegurl m3u8 -# application/vnd.arastra.swi -application/vnd.aristanetworks.swi swi -# application/vnd.artsquare -application/vnd.astraea-software.iota iota -application/vnd.audiograph aep -# application/vnd.autopackage -# application/vnd.avistar+xml -# application/vnd.balsamiq.bmml+xml -# application/vnd.balsamiq.bmpr -# application/vnd.bekitzur-stech+json -# application/vnd.biopax.rdf+xml -application/vnd.blueice.multipass mpm -# application/vnd.bluetooth.ep.oob -# application/vnd.bluetooth.le.oob -application/vnd.bmi bmi -application/vnd.businessobjects rep -# application/vnd.cab-jscript -# application/vnd.canon-cpdl -# application/vnd.canon-lips -# application/vnd.cendio.thinlinc.clientconf -# application/vnd.century-systems.tcp_stream -application/vnd.chemdraw+xml cdxml -# application/vnd.chess-pgn -application/vnd.chipnuts.karaoke-mmd mmd -application/vnd.cinderella cdy -# application/vnd.cirpack.isdn-ext -# application/vnd.citationstyles.style+xml -application/vnd.claymore cla -application/vnd.cloanto.rp9 rp9 -application/vnd.clonk.c4group c4g c4d c4f c4p c4u -application/vnd.cluetrust.cartomobile-config c11amc -application/vnd.cluetrust.cartomobile-config-pkg c11amz -# application/vnd.coffeescript -# application/vnd.collection+json -# application/vnd.collection.doc+json -# application/vnd.collection.next+json -# application/vnd.comicbook+zip -# application/vnd.commerce-battelle -application/vnd.commonspace csp -application/vnd.contact.cmsg cdbcmsg -# application/vnd.coreos.ignition+json -application/vnd.cosmocaller cmc -application/vnd.crick.clicker clkx -application/vnd.crick.clicker.keyboard clkk -application/vnd.crick.clicker.palette clkp -application/vnd.crick.clicker.template clkt -application/vnd.crick.clicker.wordbank clkw -application/vnd.criticaltools.wbs+xml wbs -application/vnd.ctc-posml pml -# application/vnd.ctct.ws+xml -# application/vnd.cups-pdf -# application/vnd.cups-postscript -application/vnd.cups-ppd ppd -# application/vnd.cups-raster -# application/vnd.cups-raw -# application/vnd.curl -application/vnd.curl.car car -application/vnd.curl.pcurl pcurl -# application/vnd.cyan.dean.root+xml -# application/vnd.cybank -application/vnd.dart dart -application/vnd.data-vision.rdz rdz -# application/vnd.debian.binary-package -application/vnd.dece.data uvf uvvf uvd uvvd -application/vnd.dece.ttml+xml uvt uvvt -application/vnd.dece.unspecified uvx uvvx -application/vnd.dece.zip uvz uvvz -application/vnd.denovo.fcselayout-link fe_launch -# application/vnd.desmume.movie -# application/vnd.dir-bi.plate-dl-nosuffix -# application/vnd.dm.delegation+xml -application/vnd.dna dna -# application/vnd.document+json -application/vnd.dolby.mlp mlp -# application/vnd.dolby.mobile.1 -# application/vnd.dolby.mobile.2 -# application/vnd.doremir.scorecloud-binary-document -application/vnd.dpgraph dpg -application/vnd.dreamfactory dfac -# application/vnd.drive+json -application/vnd.ds-keypoint kpxx -# application/vnd.dtg.local -# application/vnd.dtg.local.flash -# application/vnd.dtg.local.html -application/vnd.dvb.ait ait -# application/vnd.dvb.dvbj -# application/vnd.dvb.esgcontainer -# application/vnd.dvb.ipdcdftnotifaccess -# application/vnd.dvb.ipdcesgaccess -# application/vnd.dvb.ipdcesgaccess2 -# application/vnd.dvb.ipdcesgpdd -# application/vnd.dvb.ipdcroaming -# application/vnd.dvb.iptv.alfec-base -# application/vnd.dvb.iptv.alfec-enhancement -# application/vnd.dvb.notif-aggregate-root+xml -# application/vnd.dvb.notif-container+xml -# application/vnd.dvb.notif-generic+xml -# application/vnd.dvb.notif-ia-msglist+xml -# application/vnd.dvb.notif-ia-registration-request+xml -# application/vnd.dvb.notif-ia-registration-response+xml -# application/vnd.dvb.notif-init+xml -# application/vnd.dvb.pfr -application/vnd.dvb.service svc -# application/vnd.dxr -application/vnd.dynageo geo -# application/vnd.dzr -# application/vnd.easykaraoke.cdgdownload -# application/vnd.ecdis-update -application/vnd.ecowin.chart mag -# application/vnd.ecowin.filerequest -# application/vnd.ecowin.fileupdate -# application/vnd.ecowin.series -# application/vnd.ecowin.seriesrequest -# application/vnd.ecowin.seriesupdate -# application/vnd.emclient.accessrequest+xml -application/vnd.enliven nml -# application/vnd.enphase.envoy -# application/vnd.eprints.data+xml -application/vnd.epson.esf esf -application/vnd.epson.msf msf -application/vnd.epson.quickanime qam -application/vnd.epson.salt slt -application/vnd.epson.ssf ssf -# application/vnd.ericsson.quickcall -application/vnd.eszigno3+xml es3 et3 -# application/vnd.etsi.aoc+xml -# application/vnd.etsi.asic-e+zip -# application/vnd.etsi.asic-s+zip -# application/vnd.etsi.cug+xml -# application/vnd.etsi.iptvcommand+xml -# application/vnd.etsi.iptvdiscovery+xml -# application/vnd.etsi.iptvprofile+xml -# application/vnd.etsi.iptvsad-bc+xml -# application/vnd.etsi.iptvsad-cod+xml -# application/vnd.etsi.iptvsad-npvr+xml -# application/vnd.etsi.iptvservice+xml -# application/vnd.etsi.iptvsync+xml -# application/vnd.etsi.iptvueprofile+xml -# application/vnd.etsi.mcid+xml -# application/vnd.etsi.mheg5 -# application/vnd.etsi.overload-control-policy-dataset+xml -# application/vnd.etsi.pstn+xml -# application/vnd.etsi.sci+xml -# application/vnd.etsi.simservs+xml -# application/vnd.etsi.timestamp-token -# application/vnd.etsi.tsl+xml -# application/vnd.etsi.tsl.der -# application/vnd.eudora.data -application/vnd.ezpix-album ez2 -application/vnd.ezpix-package ez3 -# application/vnd.f-secure.mobile -# application/vnd.fastcopy-disk-image -application/vnd.fdf fdf -application/vnd.fdsn.mseed mseed -application/vnd.fdsn.seed seed dataless -# application/vnd.ffsns -# application/vnd.filmit.zfc -# application/vnd.fints -# application/vnd.firemonkeys.cloudcell -application/vnd.flographit gph -application/vnd.fluxtime.clip ftc -# application/vnd.font-fontforge-sfd -application/vnd.framemaker fm frame maker book -application/vnd.frogans.fnc fnc -application/vnd.frogans.ltf ltf -application/vnd.fsc.weblaunch fsc -application/vnd.fujitsu.oasys oas -application/vnd.fujitsu.oasys2 oa2 -application/vnd.fujitsu.oasys3 oa3 -application/vnd.fujitsu.oasysgp fg5 -application/vnd.fujitsu.oasysprs bh2 -# application/vnd.fujixerox.art-ex -# application/vnd.fujixerox.art4 -application/vnd.fujixerox.ddd ddd -application/vnd.fujixerox.docuworks xdw -application/vnd.fujixerox.docuworks.binder xbd -# application/vnd.fujixerox.docuworks.container -# application/vnd.fujixerox.hbpl -# application/vnd.fut-misnet -application/vnd.fuzzysheet fzs -application/vnd.genomatix.tuxedo txd -# application/vnd.geo+json -# application/vnd.geocube+xml -application/vnd.geogebra.file ggb -application/vnd.geogebra.tool ggt -application/vnd.geometry-explorer gex gre -application/vnd.geonext gxt -application/vnd.geoplan g2w -application/vnd.geospace g3w -# application/vnd.gerber -# application/vnd.globalplatform.card-content-mgt -# application/vnd.globalplatform.card-content-mgt-response -application/vnd.gmx gmx -application/vnd.google-earth.kml+xml kml -application/vnd.google-earth.kmz kmz -# application/vnd.gov.sk.e-form+xml -# application/vnd.gov.sk.e-form+zip -# application/vnd.gov.sk.xmldatacontainer+xml -application/vnd.grafeq gqf gqs -# application/vnd.gridmp -application/vnd.groove-account gac -application/vnd.groove-help ghf -application/vnd.groove-identity-message gim -application/vnd.groove-injector grv -application/vnd.groove-tool-message gtm -application/vnd.groove-tool-template tpl -application/vnd.groove-vcard vcg -# application/vnd.hal+json -application/vnd.hal+xml hal -application/vnd.handheld-entertainment+xml zmm -application/vnd.hbci hbci -# application/vnd.hcl-bireports -# application/vnd.hdt -# application/vnd.heroku+json -application/vnd.hhe.lesson-player les -application/vnd.hp-hpgl hpgl -application/vnd.hp-hpid hpid -application/vnd.hp-hps hps -application/vnd.hp-jlyt jlt -application/vnd.hp-pcl pcl -application/vnd.hp-pclxl pclxl -# application/vnd.httphone -application/vnd.hydrostatix.sof-data sfd-hdstx -# application/vnd.hyperdrive+json -# application/vnd.hzn-3d-crossword -# application/vnd.ibm.afplinedata -# application/vnd.ibm.electronic-media -application/vnd.ibm.minipay mpy -application/vnd.ibm.modcap afp listafp list3820 -application/vnd.ibm.rights-management irm -application/vnd.ibm.secure-container sc -application/vnd.iccprofile icc icm -# application/vnd.ieee.1905 -application/vnd.igloader igl -application/vnd.immervision-ivp ivp -application/vnd.immervision-ivu ivu -# application/vnd.ims.imsccv1p1 -# application/vnd.ims.imsccv1p2 -# application/vnd.ims.imsccv1p3 -# application/vnd.ims.lis.v2.result+json -# application/vnd.ims.lti.v2.toolconsumerprofile+json -# application/vnd.ims.lti.v2.toolproxy+json -# application/vnd.ims.lti.v2.toolproxy.id+json -# application/vnd.ims.lti.v2.toolsettings+json -# application/vnd.ims.lti.v2.toolsettings.simple+json -# application/vnd.informedcontrol.rms+xml -# application/vnd.informix-visionary -# application/vnd.infotech.project -# application/vnd.infotech.project+xml -# application/vnd.innopath.wamp.notification -application/vnd.insors.igm igm -application/vnd.intercon.formnet xpw xpx -application/vnd.intergeo i2g -# application/vnd.intertrust.digibox -# application/vnd.intertrust.nncp -application/vnd.intu.qbo qbo -application/vnd.intu.qfx qfx -# application/vnd.iptc.g2.catalogitem+xml -# application/vnd.iptc.g2.conceptitem+xml -# application/vnd.iptc.g2.knowledgeitem+xml -# application/vnd.iptc.g2.newsitem+xml -# application/vnd.iptc.g2.newsmessage+xml -# application/vnd.iptc.g2.packageitem+xml -# application/vnd.iptc.g2.planningitem+xml -application/vnd.ipunplugged.rcprofile rcprofile -application/vnd.irepository.package+xml irp -application/vnd.is-xpr xpr -application/vnd.isac.fcs fcs -application/vnd.jam jam -# application/vnd.japannet-directory-service -# application/vnd.japannet-jpnstore-wakeup -# application/vnd.japannet-payment-wakeup -# application/vnd.japannet-registration -# application/vnd.japannet-registration-wakeup -# application/vnd.japannet-setstore-wakeup -# application/vnd.japannet-verification -# application/vnd.japannet-verification-wakeup -application/vnd.jcp.javame.midlet-rms rms -application/vnd.jisp jisp -application/vnd.joost.joda-archive joda -# application/vnd.jsk.isdn-ngn -application/vnd.kahootz ktz ktr -application/vnd.kde.karbon karbon -application/vnd.kde.kchart chrt -application/vnd.kde.kformula kfo -application/vnd.kde.kivio flw -application/vnd.kde.kontour kon -application/vnd.kde.kpresenter kpr kpt -application/vnd.kde.kspread ksp -application/vnd.kde.kword kwd kwt -application/vnd.kenameaapp htke -application/vnd.kidspiration kia -application/vnd.kinar kne knp -application/vnd.koan skp skd skt skm -application/vnd.kodak-descriptor sse -application/vnd.las.las+xml lasxml -# application/vnd.liberty-request+xml -application/vnd.llamagraphics.life-balance.desktop lbd -application/vnd.llamagraphics.life-balance.exchange+xml lbe -application/vnd.lotus-1-2-3 123 -application/vnd.lotus-approach apr -application/vnd.lotus-freelance pre -application/vnd.lotus-notes nsf -application/vnd.lotus-organizer org -application/vnd.lotus-screencam scm -application/vnd.lotus-wordpro lwp -application/vnd.macports.portpkg portpkg -# application/vnd.mapbox-vector-tile -# application/vnd.marlin.drm.actiontoken+xml -# application/vnd.marlin.drm.conftoken+xml -# application/vnd.marlin.drm.license+xml -# application/vnd.marlin.drm.mdcf -# application/vnd.mason+json -# application/vnd.maxmind.maxmind-db -application/vnd.mcd mcd -application/vnd.medcalcdata mc1 -application/vnd.mediastation.cdkey cdkey -# application/vnd.meridian-slingshot -application/vnd.mfer mwf -application/vnd.mfmp mfm -# application/vnd.micro+json -application/vnd.micrografx.flo flo -application/vnd.micrografx.igx igx -# application/vnd.microsoft.portable-executable -# application/vnd.miele+json -application/vnd.mif mif -# application/vnd.minisoft-hp3000-save -# application/vnd.mitsubishi.misty-guard.trustweb -application/vnd.mobius.daf daf -application/vnd.mobius.dis dis -application/vnd.mobius.mbk mbk -application/vnd.mobius.mqy mqy -application/vnd.mobius.msl msl -application/vnd.mobius.plc plc -application/vnd.mobius.txf txf -application/vnd.mophun.application mpn -application/vnd.mophun.certificate mpc -# application/vnd.motorola.flexsuite -# application/vnd.motorola.flexsuite.adsi -# application/vnd.motorola.flexsuite.fis -# application/vnd.motorola.flexsuite.gotap -# application/vnd.motorola.flexsuite.kmr -# application/vnd.motorola.flexsuite.ttc -# application/vnd.motorola.flexsuite.wem -# application/vnd.motorola.iprm -application/vnd.mozilla.xul+xml xul -# application/vnd.ms-3mfdocument -application/vnd.ms-artgalry cil -# application/vnd.ms-asf -application/vnd.ms-cab-compressed cab -# application/vnd.ms-color.iccprofile -application/vnd.ms-excel xls xlm xla xlc xlt xlw -application/vnd.ms-excel.addin.macroenabled.12 xlam -application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb -application/vnd.ms-excel.sheet.macroenabled.12 xlsm -application/vnd.ms-excel.template.macroenabled.12 xltm -application/vnd.ms-fontobject eot -application/vnd.ms-htmlhelp chm -application/vnd.ms-ims ims -application/vnd.ms-lrm lrm -# application/vnd.ms-office.activex+xml -application/vnd.ms-officetheme thmx -# application/vnd.ms-opentype -# application/vnd.ms-package.obfuscated-opentype -application/vnd.ms-pki.seccat cat -application/vnd.ms-pki.stl stl -# application/vnd.ms-playready.initiator+xml -application/vnd.ms-powerpoint ppt pps pot -application/vnd.ms-powerpoint.addin.macroenabled.12 ppam -application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm -application/vnd.ms-powerpoint.slide.macroenabled.12 sldm -application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm -application/vnd.ms-powerpoint.template.macroenabled.12 potm -# application/vnd.ms-printdevicecapabilities+xml -# application/vnd.ms-printing.printticket+xml -# application/vnd.ms-printschematicket+xml -application/vnd.ms-project mpp mpt -# application/vnd.ms-tnef -# application/vnd.ms-windows.devicepairing -# application/vnd.ms-windows.nwprinting.oob -# application/vnd.ms-windows.printerpairing -# application/vnd.ms-windows.wsd.oob -# application/vnd.ms-wmdrm.lic-chlg-req -# application/vnd.ms-wmdrm.lic-resp -# application/vnd.ms-wmdrm.meter-chlg-req -# application/vnd.ms-wmdrm.meter-resp -application/vnd.ms-word.document.macroenabled.12 docm -application/vnd.ms-word.template.macroenabled.12 dotm -application/vnd.ms-works wps wks wcm wdb -application/vnd.ms-wpl wpl -application/vnd.ms-xpsdocument xps -# application/vnd.msa-disk-image -application/vnd.mseq mseq -# application/vnd.msign -# application/vnd.multiad.creator -# application/vnd.multiad.creator.cif -# application/vnd.music-niff -application/vnd.musician mus -application/vnd.muvee.style msty -application/vnd.mynfc taglet -# application/vnd.ncd.control -# application/vnd.ncd.reference -# application/vnd.nervana -# application/vnd.netfpx -application/vnd.neurolanguage.nlu nlu -# application/vnd.nintendo.nitro.rom -# application/vnd.nintendo.snes.rom -application/vnd.nitf ntf nitf -application/vnd.noblenet-directory nnd -application/vnd.noblenet-sealer nns -application/vnd.noblenet-web nnw -# application/vnd.nokia.catalogs -# application/vnd.nokia.conml+wbxml -# application/vnd.nokia.conml+xml -# application/vnd.nokia.iptv.config+xml -# application/vnd.nokia.isds-radio-presets -# application/vnd.nokia.landmark+wbxml -# application/vnd.nokia.landmark+xml -# application/vnd.nokia.landmarkcollection+xml -# application/vnd.nokia.n-gage.ac+xml -application/vnd.nokia.n-gage.data ngdat -application/vnd.nokia.n-gage.symbian.install n-gage -# application/vnd.nokia.ncd -# application/vnd.nokia.pcd+wbxml -# application/vnd.nokia.pcd+xml -application/vnd.nokia.radio-preset rpst -application/vnd.nokia.radio-presets rpss -application/vnd.novadigm.edm edm -application/vnd.novadigm.edx edx -application/vnd.novadigm.ext ext -# application/vnd.ntt-local.content-share -# application/vnd.ntt-local.file-transfer -# application/vnd.ntt-local.ogw_remote-access -# application/vnd.ntt-local.sip-ta_remote -# application/vnd.ntt-local.sip-ta_tcp_stream -application/vnd.oasis.opendocument.chart odc -application/vnd.oasis.opendocument.chart-template otc -application/vnd.oasis.opendocument.database odb -application/vnd.oasis.opendocument.formula odf -application/vnd.oasis.opendocument.formula-template odft -application/vnd.oasis.opendocument.graphics odg -application/vnd.oasis.opendocument.graphics-template otg -application/vnd.oasis.opendocument.image odi -application/vnd.oasis.opendocument.image-template oti -application/vnd.oasis.opendocument.presentation odp -application/vnd.oasis.opendocument.presentation-template otp -application/vnd.oasis.opendocument.spreadsheet ods -application/vnd.oasis.opendocument.spreadsheet-template ots -application/vnd.oasis.opendocument.text odt -application/vnd.oasis.opendocument.text-master odm -application/vnd.oasis.opendocument.text-template ott -application/vnd.oasis.opendocument.text-web oth -# application/vnd.obn -# application/vnd.oftn.l10n+json -# application/vnd.oipf.contentaccessdownload+xml -# application/vnd.oipf.contentaccessstreaming+xml -# application/vnd.oipf.cspg-hexbinary -# application/vnd.oipf.dae.svg+xml -# application/vnd.oipf.dae.xhtml+xml -# application/vnd.oipf.mippvcontrolmessage+xml -# application/vnd.oipf.pae.gem -# application/vnd.oipf.spdiscovery+xml -# application/vnd.oipf.spdlist+xml -# application/vnd.oipf.ueprofile+xml -# application/vnd.oipf.userprofile+xml -application/vnd.olpc-sugar xo -# application/vnd.oma-scws-config -# application/vnd.oma-scws-http-request -# application/vnd.oma-scws-http-response -# application/vnd.oma.bcast.associated-procedure-parameter+xml -# application/vnd.oma.bcast.drm-trigger+xml -# application/vnd.oma.bcast.imd+xml -# application/vnd.oma.bcast.ltkm -# application/vnd.oma.bcast.notification+xml -# application/vnd.oma.bcast.provisioningtrigger -# application/vnd.oma.bcast.sgboot -# application/vnd.oma.bcast.sgdd+xml -# application/vnd.oma.bcast.sgdu -# application/vnd.oma.bcast.simple-symbol-container -# application/vnd.oma.bcast.smartcard-trigger+xml -# application/vnd.oma.bcast.sprov+xml -# application/vnd.oma.bcast.stkm -# application/vnd.oma.cab-address-book+xml -# application/vnd.oma.cab-feature-handler+xml -# application/vnd.oma.cab-pcc+xml -# application/vnd.oma.cab-subs-invite+xml -# application/vnd.oma.cab-user-prefs+xml -# application/vnd.oma.dcd -# application/vnd.oma.dcdc -application/vnd.oma.dd2+xml dd2 -# application/vnd.oma.drm.risd+xml -# application/vnd.oma.group-usage-list+xml -# application/vnd.oma.lwm2m+json -# application/vnd.oma.lwm2m+tlv -# application/vnd.oma.pal+xml -# application/vnd.oma.poc.detailed-progress-report+xml -# application/vnd.oma.poc.final-report+xml -# application/vnd.oma.poc.groups+xml -# application/vnd.oma.poc.invocation-descriptor+xml -# application/vnd.oma.poc.optimized-progress-report+xml -# application/vnd.oma.push -# application/vnd.oma.scidm.messages+xml -# application/vnd.oma.xcap-directory+xml -# application/vnd.omads-email+xml -# application/vnd.omads-file+xml -# application/vnd.omads-folder+xml -# application/vnd.omaloc-supl-init -# application/vnd.onepager -# application/vnd.openblox.game+xml -# application/vnd.openblox.game-binary -# application/vnd.openeye.oeb -application/vnd.openofficeorg.extension oxt -# application/vnd.openxmlformats-officedocument.custom-properties+xml -# application/vnd.openxmlformats-officedocument.customxmlproperties+xml -# application/vnd.openxmlformats-officedocument.drawing+xml -# application/vnd.openxmlformats-officedocument.drawingml.chart+xml -# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml -# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml -# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml -# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml -# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml -# application/vnd.openxmlformats-officedocument.extended-properties+xml -# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml -# application/vnd.openxmlformats-officedocument.presentationml.comments+xml -# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml -# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml -# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml -application/vnd.openxmlformats-officedocument.presentationml.presentation pptx -# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml -# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml -application/vnd.openxmlformats-officedocument.presentationml.slide sldx -# application/vnd.openxmlformats-officedocument.presentationml.slide+xml -# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml -# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml -application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx -# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml -# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml -# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml -# application/vnd.openxmlformats-officedocument.presentationml.tags+xml -application/vnd.openxmlformats-officedocument.presentationml.template potx -# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml -# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml -application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx -# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml -application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx -# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml -# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml -# application/vnd.openxmlformats-officedocument.theme+xml -# application/vnd.openxmlformats-officedocument.themeoverride+xml -# application/vnd.openxmlformats-officedocument.vmldrawing -# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml -application/vnd.openxmlformats-officedocument.wordprocessingml.document docx -# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml -# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml -# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml -# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml -# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml -# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml -# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml -# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml -# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml -application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx -# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml -# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml -# application/vnd.openxmlformats-package.core-properties+xml -# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml -# application/vnd.openxmlformats-package.relationships+xml -# application/vnd.oracle.resource+json -# application/vnd.orange.indata -# application/vnd.osa.netdeploy -application/vnd.osgeo.mapguide.package mgp -# application/vnd.osgi.bundle -application/vnd.osgi.dp dp -application/vnd.osgi.subsystem esa -# application/vnd.otps.ct-kip+xml -# application/vnd.oxli.countgraph -# application/vnd.pagerduty+json -application/vnd.palm pdb pqa oprc -# application/vnd.panoply -# application/vnd.paos.xml -application/vnd.pawaafile paw -# application/vnd.pcos -application/vnd.pg.format str -application/vnd.pg.osasli ei6 -# application/vnd.piaccess.application-licence -application/vnd.picsel efif -application/vnd.pmi.widget wg -# application/vnd.poc.group-advertisement+xml -application/vnd.pocketlearn plf -application/vnd.powerbuilder6 pbd -# application/vnd.powerbuilder6-s -# application/vnd.powerbuilder7 -# application/vnd.powerbuilder7-s -# application/vnd.powerbuilder75 -# application/vnd.powerbuilder75-s -# application/vnd.preminet -application/vnd.previewsystems.box box -application/vnd.proteus.magazine mgz -application/vnd.publishare-delta-tree qps -application/vnd.pvi.ptid1 ptid -# application/vnd.pwg-multiplexed -# application/vnd.pwg-xhtml-print+xml -# application/vnd.qualcomm.brew-app-res -# application/vnd.quarantainenet -application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb -# application/vnd.quobject-quoxdocument -# application/vnd.radisys.moml+xml -# application/vnd.radisys.msml+xml -# application/vnd.radisys.msml-audit+xml -# application/vnd.radisys.msml-audit-conf+xml -# application/vnd.radisys.msml-audit-conn+xml -# application/vnd.radisys.msml-audit-dialog+xml -# application/vnd.radisys.msml-audit-stream+xml -# application/vnd.radisys.msml-conf+xml -# application/vnd.radisys.msml-dialog+xml -# application/vnd.radisys.msml-dialog-base+xml -# application/vnd.radisys.msml-dialog-fax-detect+xml -# application/vnd.radisys.msml-dialog-fax-sendrecv+xml -# application/vnd.radisys.msml-dialog-group+xml -# application/vnd.radisys.msml-dialog-speech+xml -# application/vnd.radisys.msml-dialog-transform+xml -# application/vnd.rainstor.data -# application/vnd.rapid -# application/vnd.rar -application/vnd.realvnc.bed bed -application/vnd.recordare.musicxml mxl -application/vnd.recordare.musicxml+xml musicxml -# application/vnd.renlearn.rlprint -application/vnd.rig.cryptonote cryptonote -application/vnd.rim.cod cod -application/vnd.rn-realmedia rm -application/vnd.rn-realmedia-vbr rmvb -application/vnd.route66.link66+xml link66 -# application/vnd.rs-274x -# application/vnd.ruckus.download -# application/vnd.s3sms -application/vnd.sailingtracker.track st -# application/vnd.sbm.cid -# application/vnd.sbm.mid2 -# application/vnd.scribus -# application/vnd.sealed.3df -# application/vnd.sealed.csf -# application/vnd.sealed.doc -# application/vnd.sealed.eml -# application/vnd.sealed.mht -# application/vnd.sealed.net -# application/vnd.sealed.ppt -# application/vnd.sealed.tiff -# application/vnd.sealed.xls -# application/vnd.sealedmedia.softseal.html -# application/vnd.sealedmedia.softseal.pdf -application/vnd.seemail see -application/vnd.sema sema -application/vnd.semd semd -application/vnd.semf semf -application/vnd.shana.informed.formdata ifm -application/vnd.shana.informed.formtemplate itp -application/vnd.shana.informed.interchange iif -application/vnd.shana.informed.package ipk -application/vnd.simtech-mindmapper twd twds -# application/vnd.siren+json -application/vnd.smaf mmf -# application/vnd.smart.notebook -application/vnd.smart.teacher teacher -# application/vnd.software602.filler.form+xml -# application/vnd.software602.filler.form-xml-zip -application/vnd.solent.sdkm+xml sdkm sdkd -application/vnd.spotfire.dxp dxp -application/vnd.spotfire.sfs sfs -# application/vnd.sss-cod -# application/vnd.sss-dtf -# application/vnd.sss-ntf -application/vnd.stardivision.calc sdc -application/vnd.stardivision.draw sda -application/vnd.stardivision.impress sdd -application/vnd.stardivision.math smf -application/vnd.stardivision.writer sdw vor -application/vnd.stardivision.writer-global sgl -application/vnd.stepmania.package smzip -application/vnd.stepmania.stepchart sm -# application/vnd.street-stream -# application/vnd.sun.wadl+xml -application/vnd.sun.xml.calc sxc -application/vnd.sun.xml.calc.template stc -application/vnd.sun.xml.draw sxd -application/vnd.sun.xml.draw.template std -application/vnd.sun.xml.impress sxi -application/vnd.sun.xml.impress.template sti -application/vnd.sun.xml.math sxm -application/vnd.sun.xml.writer sxw -application/vnd.sun.xml.writer.global sxg -application/vnd.sun.xml.writer.template stw -application/vnd.sus-calendar sus susp -application/vnd.svd svd -# application/vnd.swiftview-ics -application/vnd.symbian.install sis sisx -application/vnd.syncml+xml xsm -application/vnd.syncml.dm+wbxml bdm -application/vnd.syncml.dm+xml xdm -# application/vnd.syncml.dm.notification -# application/vnd.syncml.dmddf+wbxml -# application/vnd.syncml.dmddf+xml -# application/vnd.syncml.dmtnds+wbxml -# application/vnd.syncml.dmtnds+xml -# application/vnd.syncml.ds.notification -application/vnd.tao.intent-module-archive tao -application/vnd.tcpdump.pcap pcap cap dmp -# application/vnd.tmd.mediaflex.api+xml -# application/vnd.tml -application/vnd.tmobile-livetv tmo -application/vnd.trid.tpt tpt -application/vnd.triscape.mxs mxs -application/vnd.trueapp tra -# application/vnd.truedoc -# application/vnd.ubisoft.webplayer -application/vnd.ufdl ufd ufdl -application/vnd.uiq.theme utz -application/vnd.umajin umj -application/vnd.unity unityweb -application/vnd.uoml+xml uoml -# application/vnd.uplanet.alert -# application/vnd.uplanet.alert-wbxml -# application/vnd.uplanet.bearer-choice -# application/vnd.uplanet.bearer-choice-wbxml -# application/vnd.uplanet.cacheop -# application/vnd.uplanet.cacheop-wbxml -# application/vnd.uplanet.channel -# application/vnd.uplanet.channel-wbxml -# application/vnd.uplanet.list -# application/vnd.uplanet.list-wbxml -# application/vnd.uplanet.listcmd -# application/vnd.uplanet.listcmd-wbxml -# application/vnd.uplanet.signal -# application/vnd.uri-map -# application/vnd.valve.source.material -application/vnd.vcx vcx -# application/vnd.vd-study -# application/vnd.vectorworks -# application/vnd.vel+json -# application/vnd.verimatrix.vcas -# application/vnd.vidsoft.vidconference -application/vnd.visio vsd vst vss vsw -application/vnd.visionary vis -# application/vnd.vividence.scriptfile -application/vnd.vsf vsf -# application/vnd.wap.sic -# application/vnd.wap.slc -application/vnd.wap.wbxml wbxml -application/vnd.wap.wmlc wmlc -application/vnd.wap.wmlscriptc wmlsc -application/vnd.webturbo wtb -# application/vnd.wfa.p2p -# application/vnd.wfa.wsc -# application/vnd.windows.devicepairing -# application/vnd.wmc -# application/vnd.wmf.bootstrap -# application/vnd.wolfram.mathematica -# application/vnd.wolfram.mathematica.package -application/vnd.wolfram.player nbp -application/vnd.wordperfect wpd -application/vnd.wqd wqd -# application/vnd.wrq-hp3000-labelled -application/vnd.wt.stf stf -# application/vnd.wv.csp+wbxml -# application/vnd.wv.csp+xml -# application/vnd.wv.ssp+xml -# application/vnd.xacml+json -application/vnd.xara xar -application/vnd.xfdl xfdl -# application/vnd.xfdl.webform -# application/vnd.xmi+xml -# application/vnd.xmpie.cpkg -# application/vnd.xmpie.dpkg -# application/vnd.xmpie.plan -# application/vnd.xmpie.ppkg -# application/vnd.xmpie.xlim -application/vnd.yamaha.hv-dic hvd -application/vnd.yamaha.hv-script hvs -application/vnd.yamaha.hv-voice hvp -application/vnd.yamaha.openscoreformat osf -application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg -# application/vnd.yamaha.remote-setup -application/vnd.yamaha.smaf-audio saf -application/vnd.yamaha.smaf-phrase spf -# application/vnd.yamaha.through-ngn -# application/vnd.yamaha.tunnel-udpencap -# application/vnd.yaoweme -application/vnd.yellowriver-custom-menu cmp -application/vnd.zul zir zirz -application/vnd.zzazz.deck+xml zaz -application/voicexml+xml vxml -# application/vq-rtcpxr -# application/watcherinfo+xml -# application/whoispp-query -# application/whoispp-response -application/widget wgt -application/winhlp hlp -# application/wita -# application/wordperfect5.1 -application/wsdl+xml wsdl -application/wspolicy+xml wspolicy -application/x-7z-compressed 7z -application/x-abiword abw -application/x-ace-compressed ace -# application/x-amf -application/x-apple-diskimage dmg -application/x-authorware-bin aab x32 u32 vox -application/x-authorware-map aam -application/x-authorware-seg aas -application/x-bcpio bcpio -application/x-bittorrent torrent -application/x-blorb blb blorb -application/x-bzip bz -application/x-bzip2 bz2 boz -application/x-cbr cbr cba cbt cbz cb7 -application/x-cdlink vcd -application/x-cfs-compressed cfs -application/x-chat chat -application/x-chess-pgn pgn -# application/x-compress -application/x-conference nsc -application/x-cpio cpio -application/x-csh csh -application/x-debian-package deb udeb -application/x-dgc-compressed dgc -application/x-director dir dcr dxr cst cct cxt w3d fgd swa -application/x-doom wad -application/x-dtbncx+xml ncx -application/x-dtbook+xml dtb -application/x-dtbresource+xml res -application/x-dvi dvi -application/x-envoy evy -application/x-eva eva -application/x-font-bdf bdf -# application/x-font-dos -# application/x-font-framemaker -application/x-font-ghostscript gsf -# application/x-font-libgrx -application/x-font-linux-psf psf -application/x-font-pcf pcf -application/x-font-snf snf -# application/x-font-speedo -# application/x-font-sunos-news -application/x-font-type1 pfa pfb pfm afm -# application/x-font-vfont -application/x-freearc arc -application/x-futuresplash spl -application/x-gca-compressed gca -application/x-glulx ulx -application/x-gnumeric gnumeric -application/x-gramps-xml gramps -application/x-gtar gtar -# application/x-gzip -application/x-hdf hdf -application/x-install-instructions install -application/x-iso9660-image iso -application/x-java-jnlp-file jnlp -application/x-latex latex -application/x-lzh-compressed lzh lha -application/x-mie mie -application/x-mobipocket-ebook prc mobi -application/x-ms-application application -application/x-ms-shortcut lnk -application/x-ms-wmd wmd -application/x-ms-wmz wmz -application/x-ms-xbap xbap -application/x-msaccess mdb -application/x-msbinder obd -application/x-mscardfile crd -application/x-msclip clp -application/x-msdownload exe dll com bat msi -application/x-msmediaview mvb m13 m14 -application/x-msmetafile wmf wmz emf emz -application/x-msmoney mny -application/x-mspublisher pub -application/x-msschedule scd -application/x-msterminal trm -application/x-mswrite wri -application/x-netcdf nc cdf -application/x-nzb nzb -application/x-pkcs12 p12 pfx -application/x-pkcs7-certificates p7b spc -application/x-pkcs7-certreqresp p7r -application/x-rar-compressed rar -application/x-research-info-systems ris -application/x-sh sh -application/x-shar shar -application/x-shockwave-flash swf -application/x-silverlight-app xap -application/x-sql sql -application/x-stuffit sit -application/x-stuffitx sitx -application/x-subrip srt -application/x-sv4cpio sv4cpio -application/x-sv4crc sv4crc -application/x-t3vm-image t3 -application/x-tads gam -application/x-tar tar -application/x-tcl tcl -application/x-tex tex -application/x-tex-tfm tfm -application/x-texinfo texinfo texi -application/x-tgif obj -application/x-ustar ustar -application/x-wais-source src -# application/x-www-form-urlencoded -application/x-x509-ca-cert der crt -application/x-xfig fig -application/x-xliff+xml xlf -application/x-xpinstall xpi -application/x-xz xz -application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8 -# application/x400-bp -# application/xacml+xml -application/xaml+xml xaml -# application/xcap-att+xml -# application/xcap-caps+xml -application/xcap-diff+xml xdf -# application/xcap-el+xml -# application/xcap-error+xml -# application/xcap-ns+xml -# application/xcon-conference-info+xml -# application/xcon-conference-info-diff+xml -application/xenc+xml xenc -application/xhtml+xml xhtml xht -# application/xhtml-voice+xml -application/xml xml xsl -application/xml-dtd dtd -# application/xml-external-parsed-entity -# application/xml-patch+xml -# application/xmpp+xml -application/xop+xml xop -application/xproc+xml xpl -application/xslt+xml xslt -application/xspf+xml xspf -application/xv+xml mxml xhvml xvml xvm -application/yang yang -application/yin+xml yin -application/zip zip -# application/zlib -# audio/1d-interleaved-parityfec -# audio/32kadpcm -# audio/3gpp -# audio/3gpp2 -# audio/ac3 -audio/adpcm adp -# audio/amr -# audio/amr-wb -# audio/amr-wb+ -# audio/aptx -# audio/asc -# audio/atrac-advanced-lossless -# audio/atrac-x -# audio/atrac3 -audio/basic au snd -# audio/bv16 -# audio/bv32 -# audio/clearmode -# audio/cn -# audio/dat12 -# audio/dls -# audio/dsr-es201108 -# audio/dsr-es202050 -# audio/dsr-es202211 -# audio/dsr-es202212 -# audio/dv -# audio/dvi4 -# audio/eac3 -# audio/encaprtp -# audio/evrc -# audio/evrc-qcp -# audio/evrc0 -# audio/evrc1 -# audio/evrcb -# audio/evrcb0 -# audio/evrcb1 -# audio/evrcnw -# audio/evrcnw0 -# audio/evrcnw1 -# audio/evrcwb -# audio/evrcwb0 -# audio/evrcwb1 -# audio/evs -# audio/example -# audio/fwdred -# audio/g711-0 -# audio/g719 -# audio/g722 -# audio/g7221 -# audio/g723 -# audio/g726-16 -# audio/g726-24 -# audio/g726-32 -# audio/g726-40 -# audio/g728 -# audio/g729 -# audio/g7291 -# audio/g729d -# audio/g729e -# audio/gsm -# audio/gsm-efr -# audio/gsm-hr-08 -# audio/ilbc -# audio/ip-mr_v2.5 -# audio/isac -# audio/l16 -# audio/l20 -# audio/l24 -# audio/l8 -# audio/lpc -audio/midi mid midi kar rmi -# audio/mobile-xmf -audio/mp4 m4a mp4a -# audio/mp4a-latm -# audio/mpa -# audio/mpa-robust -audio/mpeg mp3 mpga mp2 mp2a m2a m3a -# audio/mpeg4-generic -# audio/musepack -audio/ogg ogg oga spx -# audio/opus -# audio/parityfec -# audio/pcma -# audio/pcma-wb -# audio/pcmu -# audio/pcmu-wb -# audio/prs.sid -# audio/qcelp -# audio/raptorfec -# audio/red -# audio/rtp-enc-aescm128 -# audio/rtp-midi -# audio/rtploopback -# audio/rtx -audio/s3m s3m -audio/silk sil -# audio/smv -# audio/smv-qcp -# audio/smv0 -# audio/sp-midi -# audio/speex -# audio/t140c -# audio/t38 -# audio/telephone-event -# audio/tone -# audio/uemclip -# audio/ulpfec -# audio/vdvi -# audio/vmr-wb -# audio/vnd.3gpp.iufp -# audio/vnd.4sb -# audio/vnd.audiokoz -# audio/vnd.celp -# audio/vnd.cisco.nse -# audio/vnd.cmles.radio-events -# audio/vnd.cns.anp1 -# audio/vnd.cns.inf1 -audio/vnd.dece.audio uva uvva -audio/vnd.digital-winds eol -# audio/vnd.dlna.adts -# audio/vnd.dolby.heaac.1 -# audio/vnd.dolby.heaac.2 -# audio/vnd.dolby.mlp -# audio/vnd.dolby.mps -# audio/vnd.dolby.pl2 -# audio/vnd.dolby.pl2x -# audio/vnd.dolby.pl2z -# audio/vnd.dolby.pulse.1 -audio/vnd.dra dra -audio/vnd.dts dts -audio/vnd.dts.hd dtshd -# audio/vnd.dvb.file -# audio/vnd.everad.plj -# audio/vnd.hns.audio -audio/vnd.lucent.voice lvp -audio/vnd.ms-playready.media.pya pya -# audio/vnd.nokia.mobile-xmf -# audio/vnd.nortel.vbk -audio/vnd.nuera.ecelp4800 ecelp4800 -audio/vnd.nuera.ecelp7470 ecelp7470 -audio/vnd.nuera.ecelp9600 ecelp9600 -# audio/vnd.octel.sbc -# audio/vnd.qcelp -# audio/vnd.rhetorex.32kadpcm -audio/vnd.rip rip -# audio/vnd.sealedmedia.softseal.mpeg -# audio/vnd.vmx.cvsd -# audio/vorbis -# audio/vorbis-config -audio/webm weba -audio/x-aac aac -audio/x-aiff aif aiff aifc -audio/x-caf caf -audio/x-flac flac -audio/x-matroska mka -audio/x-mpegurl m3u -audio/x-ms-wax wax -audio/x-ms-wma wma -audio/x-pn-realaudio ram ra -audio/x-pn-realaudio-plugin rmp -# audio/x-tta -audio/x-wav wav -audio/xm xm -chemical/x-cdx cdx -chemical/x-cif cif -chemical/x-cmdf cmdf -chemical/x-cml cml -chemical/x-csml csml -# chemical/x-pdb -chemical/x-xyz xyz -font/collection ttc -font/otf otf -# font/sfnt -font/ttf ttf -font/woff woff -font/woff2 woff2 -image/bmp bmp -image/cgm cgm -# image/dicom-rle -# image/emf -# image/example -# image/fits -image/g3fax g3 -image/gif gif -image/ief ief -# image/jls -# image/jp2 -image/jpeg jpg jpeg jpe -# image/jpm -# image/jpx -image/ktx ktx -# image/naplps -image/png png -image/prs.btif btif -# image/prs.pti -# image/pwg-raster -image/sgi sgi -image/svg+xml svg svgz -# image/t38 -image/tiff tiff tif -# image/tiff-fx -image/vnd.adobe.photoshop psd -# image/vnd.airzip.accelerator.azv -# image/vnd.cns.inf2 -image/vnd.dece.graphic uvi uvvi uvg uvvg -image/vnd.djvu djvu djv -image/vnd.dvb.subtitle sub -image/vnd.dwg dwg -image/vnd.dxf dxf -image/vnd.fastbidsheet fbs -image/vnd.fpx fpx -image/vnd.fst fst -image/vnd.fujixerox.edmics-mmr mmr -image/vnd.fujixerox.edmics-rlc rlc -# image/vnd.globalgraphics.pgb -# image/vnd.microsoft.icon -# image/vnd.mix -# image/vnd.mozilla.apng -image/vnd.ms-modi mdi -image/vnd.ms-photo wdp -image/vnd.net-fpx npx -# image/vnd.radiance -# image/vnd.sealed.png -# image/vnd.sealedmedia.softseal.gif -# image/vnd.sealedmedia.softseal.jpg -# image/vnd.svf -# image/vnd.tencent.tap -# image/vnd.valve.source.texture -image/vnd.wap.wbmp wbmp -image/vnd.xiff xif -# image/vnd.zbrush.pcx -image/webp webp -# image/wmf -image/x-3ds 3ds -image/x-cmu-raster ras -image/x-cmx cmx -image/x-freehand fh fhc fh4 fh5 fh7 -image/x-icon ico -image/x-mrsid-image sid -image/x-pcx pcx -image/x-pict pic pct -image/x-portable-anymap pnm -image/x-portable-bitmap pbm -image/x-portable-graymap pgm -image/x-portable-pixmap ppm -image/x-rgb rgb -image/x-tga tga -image/x-xbitmap xbm -image/x-xpixmap xpm -image/x-xwindowdump xwd -# message/cpim -# message/delivery-status -# message/disposition-notification -# message/example -# message/external-body -# message/feedback-report -# message/global -# message/global-delivery-status -# message/global-disposition-notification -# message/global-headers -# message/http -# message/imdn+xml -# message/news -# message/partial -message/rfc822 eml mime -# message/s-http -# message/sip -# message/sipfrag -# message/tracking-status -# message/vnd.si.simp -# message/vnd.wfa.wsc -# model/example -# model/gltf+json -model/iges igs iges -model/mesh msh mesh silo -model/vnd.collada+xml dae -model/vnd.dwf dwf -# model/vnd.flatland.3dml -model/vnd.gdl gdl -# model/vnd.gs-gdl -# model/vnd.gs.gdl -model/vnd.gtw gtw -# model/vnd.moml+xml -model/vnd.mts mts -# model/vnd.opengex -# model/vnd.parasolid.transmit.binary -# model/vnd.parasolid.transmit.text -# model/vnd.rosette.annotated-data-model -# model/vnd.valve.source.compiled-map -model/vnd.vtu vtu -model/vrml wrl vrml -model/x3d+binary x3db x3dbz -# model/x3d+fastinfoset -model/x3d+vrml x3dv x3dvz -model/x3d+xml x3d x3dz -# model/x3d-vrml -# multipart/alternative -# multipart/appledouble -# multipart/byteranges -# multipart/digest -# multipart/encrypted -# multipart/example -# multipart/form-data -# multipart/header-set -# multipart/mixed -# multipart/parallel -# multipart/related -# multipart/report -# multipart/signed -# multipart/voice-message -# multipart/x-mixed-replace -# text/1d-interleaved-parityfec -text/cache-manifest appcache -text/calendar ics ifb -text/css css -text/csv csv -# text/csv-schema -# text/directory -# text/dns -# text/ecmascript -# text/encaprtp -# text/enriched -# text/example -# text/fwdred -# text/grammar-ref-list -text/html html htm -# text/javascript -# text/jcr-cnd -# text/markdown -# text/mizar -text/n3 n3 -# text/parameters -# text/parityfec -text/plain txt text conf def list log in -# text/provenance-notation -# text/prs.fallenstein.rst -text/prs.lines.tag dsc -# text/prs.prop.logic -# text/raptorfec -# text/red -# text/rfc822-headers -text/richtext rtx -# text/rtf -# text/rtp-enc-aescm128 -# text/rtploopback -# text/rtx -text/sgml sgml sgm -# text/t140 -text/tab-separated-values tsv -text/troff t tr roff man me ms -text/turtle ttl -# text/ulpfec -text/uri-list uri uris urls -text/vcard vcard -# text/vnd.a -# text/vnd.abc -text/vnd.curl curl -text/vnd.curl.dcurl dcurl -text/vnd.curl.mcurl mcurl -text/vnd.curl.scurl scurl -# text/vnd.debian.copyright -# text/vnd.dmclientscript -text/vnd.dvb.subtitle sub -# text/vnd.esmertec.theme-descriptor -text/vnd.fly fly -text/vnd.fmi.flexstor flx -text/vnd.graphviz gv -text/vnd.in3d.3dml 3dml -text/vnd.in3d.spot spot -# text/vnd.iptc.newsml -# text/vnd.iptc.nitf -# text/vnd.latex-z -# text/vnd.motorola.reflex -# text/vnd.ms-mediapackage -# text/vnd.net2phone.commcenter.command -# text/vnd.radisys.msml-basic-layout -# text/vnd.si.uricatalogue -text/vnd.sun.j2me.app-descriptor jad -# text/vnd.trolltech.linguist -# text/vnd.wap.si -# text/vnd.wap.sl -text/vnd.wap.wml wml -text/vnd.wap.wmlscript wmls -text/x-asm s asm -text/x-c c cc cxx cpp h hh dic -text/x-fortran f for f77 f90 -text/x-java-source java -text/x-nfo nfo -text/x-opml opml -text/x-pascal p pas -text/x-setext etx -text/x-sfv sfv -text/x-uuencode uu -text/x-vcalendar vcs -text/x-vcard vcf -# text/xml -# text/xml-external-parsed-entity -# video/1d-interleaved-parityfec -video/3gpp 3gp -# video/3gpp-tt -video/3gpp2 3g2 -# video/bmpeg -# video/bt656 -# video/celb -# video/dv -# video/encaprtp -# video/example -video/h261 h261 -video/h263 h263 -# video/h263-1998 -# video/h263-2000 -video/h264 h264 -# video/h264-rcdo -# video/h264-svc -# video/h265 -# video/iso.segment -video/jpeg jpgv -# video/jpeg2000 -video/jpm jpm jpgm -video/mj2 mj2 mjp2 -# video/mp1s -# video/mp2p -# video/mp2t -video/mp4 mp4 mp4v mpg4 -# video/mp4v-es -video/mpeg mpeg mpg mpe m1v m2v -# video/mpeg4-generic -# video/mpv -# video/nv -video/ogg ogv -# video/parityfec -# video/pointer -video/quicktime qt mov -# video/raptorfec -# video/raw -# video/rtp-enc-aescm128 -# video/rtploopback -# video/rtx -# video/smpte292m -# video/ulpfec -# video/vc1 -# video/vnd.cctv -video/vnd.dece.hd uvh uvvh -video/vnd.dece.mobile uvm uvvm -# video/vnd.dece.mp4 -video/vnd.dece.pd uvp uvvp -video/vnd.dece.sd uvs uvvs -video/vnd.dece.video uvv uvvv -# video/vnd.directv.mpeg -# video/vnd.directv.mpeg-tts -# video/vnd.dlna.mpeg-tts -video/vnd.dvb.file dvb -video/vnd.fvt fvt -# video/vnd.hns.video -# video/vnd.iptvforum.1dparityfec-1010 -# video/vnd.iptvforum.1dparityfec-2005 -# video/vnd.iptvforum.2dparityfec-1010 -# video/vnd.iptvforum.2dparityfec-2005 -# video/vnd.iptvforum.ttsavc -# video/vnd.iptvforum.ttsmpeg2 -# video/vnd.motorola.video -# video/vnd.motorola.videop -video/vnd.mpegurl mxu m4u -video/vnd.ms-playready.media.pyv pyv -# video/vnd.nokia.interleaved-multimedia -# video/vnd.nokia.videovoip -# video/vnd.objectvideo -# video/vnd.radgamettools.bink -# video/vnd.radgamettools.smacker -# video/vnd.sealed.mpeg1 -# video/vnd.sealed.mpeg4 -# video/vnd.sealed.swf -# video/vnd.sealedmedia.softseal.mov -video/vnd.uvvu.mp4 uvu uvvu -video/vnd.vivo viv -# video/vp8 -video/webm webm -video/x-f4v f4v -video/x-fli fli -video/x-flv flv -video/x-m4v m4v -video/x-matroska mkv mk3d mks -video/x-mng mng -video/x-ms-asf asf asx -video/x-ms-vob vob -video/x-ms-wm wm -video/x-ms-wmv wmv -video/x-ms-wmx wmx -video/x-ms-wvx wvx -video/x-msvideo avi -video/x-sgi-movie movie -video/x-smv smv -x-conference/x-cooltalk ice - -# Telegram animated stickers -application/x-bad-tgsticker tgs -application/x-tgsticker tgs -""" From 01ea086b9c3f88bc9a1b673b2dfc6bf9ed76d64d Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:28:08 +0545 Subject: [PATCH 021/103] Delete pyrogram/filters.py --- pyrogram/filters.py | 929 -------------------------------------------- 1 file changed, 929 deletions(-) delete mode 100644 pyrogram/filters.py diff --git a/pyrogram/filters.py b/pyrogram/filters.py deleted file mode 100644 index b52dfe601d..0000000000 --- a/pyrogram/filters.py +++ /dev/null @@ -1,929 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-present 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 import enums -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 - ) - - # short circuit - if not x: - return False - - 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 - ) - - # short circuit - if x: - return True - - 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 three positional arguments *(filter, client, 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 *client* argument refers to the :obj:`~pyrogram.Client` that received the update. - 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:`~pyrogram.filters.command` or :meth:`~pyrogram.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 or getattr(m, "outgoing", False)) - - -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_id) - - -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 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 bool(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 bool(m.poll) - - -poll = create(poll_filter) -"""Filter messages that contain :obj:`~pyrogram.types.Poll` objects.""" - - -# endregion - -# region dice_filter -async def dice_filter(_, __, m: Message): - return bool(m.dice) - - -dice = create(dice_filter) -"""Filter messages that contain :obj:`~pyrogram.types.Dice` objects.""" - - -# endregion - -# region media_spoiler -async def media_spoiler_filter(_, __, m: Message): - return bool(m.has_media_spoiler) - - -media_spoiler = create(media_spoiler_filter) -"""Filter media messages that contain a spoiler.""" - - -# endregion - -# region private_filter -async def private_filter(_, __, m: Message): - return bool(m.chat and m.chat.type in {enums.ChatType.PRIVATE, enums.ChatType.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 {enums.ChatType.GROUP, enums.ChatType.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 == enums.ChatType.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 video_chat_started_filter -async def video_chat_started_filter(_, __, m: Message): - return bool(m.video_chat_started) - - -video_chat_started = create(video_chat_started_filter) -"""Filter messages for started video chats""" - - -# endregion - -# region video_chat_ended_filter -async def video_chat_ended_filter(_, __, m: Message): - return bool(m.video_chat_ended) - - -video_chat_ended = create(video_chat_ended_filter) -"""Filter messages for ended video chats""" - - -# endregion - -# region video_chat_members_invited_filter -async def video_chat_members_invited_filter(_, __, m: Message): - return bool(m.video_chat_members_invited) - - -video_chat_members_invited = create(video_chat_members_invited_filter) -"""Filter messages for voice chat invited members""" - - -# 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*, -*video_chat_started*, *video_chat_ended*, *video_chat_members_invited*. -""" - - -# 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 - - -# region command_filter -def command(commands: Union[str, List[str]], prefixes: Union[str, 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: Union[int, str, List[Union[int, str]]] = 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: Union[int, str, List[Union[int, str]]] = 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))) From 0be5c8a881fa17f0b5c4bb9c3021c5eb7be5c086 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:28:18 +0545 Subject: [PATCH 022/103] Delete pyrogram/py.typed --- pyrogram/py.typed | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pyrogram/py.typed diff --git a/pyrogram/py.typed b/pyrogram/py.typed deleted file mode 100644 index e69de29bb2..0000000000 From 57244d5b6cd231564f61b611dd969070ec26bb53 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:28:28 +0545 Subject: [PATCH 023/103] Delete pyrogram/file_id.py --- pyrogram/file_id.py | 481 -------------------------------------------- 1 file changed, 481 deletions(-) delete mode 100644 pyrogram/file_id.py diff --git a/pyrogram/file_id.py b/pyrogram/file_id.py deleted file mode 100644 index 1a54a49d61..0000000000 --- a/pyrogram/file_id.py +++ /dev/null @@ -1,481 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-present 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 base64 -import logging -import struct -from enum import IntEnum -from io import BytesIO -from typing import List - -from pyrogram.raw.core import Bytes, String - -log = logging.getLogger(__name__) - - -def b64_encode(s: bytes) -> str: - """Encode bytes into a URL-safe Base64 string without padding - - Parameters: - s (``bytes``): - Bytes to encode - - Returns: - ``str``: The encoded bytes - """ - return base64.urlsafe_b64encode(s).decode().strip("=") - - -def b64_decode(s: str) -> bytes: - """Decode a URL-safe Base64 string without padding to bytes - - Parameters: - s (``str``): - String to decode - - Returns: - ``bytes``: The decoded string - """ - return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4)) - - -def rle_encode(s: bytes) -> bytes: - """Zero-value RLE encoder - - Parameters: - s (``bytes``): - Bytes to encode - - Returns: - ``bytes``: The encoded bytes - """ - r: List[int] = [] - n: int = 0 - - for b in s: - if not b: - n += 1 - else: - if n: - r.extend((0, n)) - n = 0 - - r.append(b) - - if n: - r.extend((0, n)) - - return bytes(r) - - -def rle_decode(s: bytes) -> bytes: - """Zero-value RLE decoder - - Parameters: - s (``bytes``): - Bytes to decode - - Returns: - ``bytes``: The decoded bytes - """ - r: List[int] = [] - z: bool = False - - for b in s: - if not b: - z = True - continue - - if z: - r.extend((0,) * b) - z = False - else: - r.append(b) - - return bytes(r) - - -class FileType(IntEnum): - """Known file types""" - THUMBNAIL = 0 - CHAT_PHOTO = 1 # ProfilePhoto - PHOTO = 2 - VOICE = 3 # VoiceNote - VIDEO = 4 - DOCUMENT = 5 - ENCRYPTED = 6 - TEMP = 7 - STICKER = 8 - AUDIO = 9 - ANIMATION = 10 - ENCRYPTED_THUMBNAIL = 11 - WALLPAPER = 12 - VIDEO_NOTE = 13 - SECURE_RAW = 14 - SECURE = 15 - BACKGROUND = 16 - DOCUMENT_AS_FILE = 17 - - -class ThumbnailSource(IntEnum): - """Known thumbnail sources""" - LEGACY = 0 - THUMBNAIL = 1 - CHAT_PHOTO_SMALL = 2 # DialogPhotoSmall - CHAT_PHOTO_BIG = 3 # DialogPhotoBig - STICKER_SET_THUMBNAIL = 4 - - -# Photo-like file ids are longer and contain extra info, the rest are all documents -PHOTO_TYPES = {FileType.THUMBNAIL, FileType.CHAT_PHOTO, FileType.PHOTO, FileType.WALLPAPER, - FileType.ENCRYPTED_THUMBNAIL} -DOCUMENT_TYPES = set(FileType) - PHOTO_TYPES - -# Since the file type values are small enough to fit them in few bits, Telegram thought it would be a good idea to -# encode extra information about web url and file reference existence as flag inside the 4 bytes allocated for the field -WEB_LOCATION_FLAG = 1 << 24 -FILE_REFERENCE_FLAG = 1 << 25 - - -class FileId: - MAJOR = 4 - MINOR = 30 - - def __init__( - self, *, - major: int = MAJOR, - minor: int = MINOR, - file_type: FileType, - dc_id: int, - file_reference: bytes = b"", - url: str = None, - media_id: int = None, - access_hash: int = None, - volume_id: int = None, - thumbnail_source: ThumbnailSource = None, - thumbnail_file_type: FileType = None, - thumbnail_size: str = "", - secret: int = None, - local_id: int = None, - chat_id: int = None, - chat_access_hash: int = None, - sticker_set_id: int = None, - sticker_set_access_hash: int = None - ): - self.major = major - self.minor = minor - self.file_type = file_type - self.dc_id = dc_id - self.file_reference = file_reference - self.url = url - self.media_id = media_id - self.access_hash = access_hash - self.volume_id = volume_id - self.thumbnail_source = thumbnail_source - self.thumbnail_file_type = thumbnail_file_type - self.thumbnail_size = thumbnail_size - self.secret = secret - self.local_id = local_id - self.chat_id = chat_id - self.chat_access_hash = chat_access_hash - self.sticker_set_id = sticker_set_id - self.sticker_set_access_hash = sticker_set_access_hash - - @staticmethod - def decode(file_id: str): - decoded = rle_decode(b64_decode(file_id)) - - # region read version - # File id versioning. Major versions lower than 4 don't have a minor version - major = decoded[-1] - - if major < 4: - minor = 0 - buffer = BytesIO(decoded[:-1]) - else: - minor = decoded[-2] - buffer = BytesIO(decoded[:-2]) - # endregion - - file_type, dc_id = struct.unpack("= 4: - buffer.write(struct.pack(" Date: Fri, 14 Jun 2024 09:29:36 +0545 Subject: [PATCH 024/103] =?UTF-8?q?Updated=20To=20Pyrogram=202.1.1=20?= =?UTF-8?q?=E2=9C=93=E2=9C=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyrogram/__init__.py | 42 + pyrogram/client.py | 1045 +++++++++++ pyrogram/dispatcher.py | 259 +++ pyrogram/emoji.py | 4019 ++++++++++++++++++++++++++++++++++++++++ pyrogram/file_id.py | 481 +++++ pyrogram/filters.py | 929 ++++++++++ pyrogram/mime_types.py | 1881 +++++++++++++++++++ pyrogram/py.typed | 0 pyrogram/sync.py | 113 ++ pyrogram/utils.py | 371 ++++ 10 files changed, 9140 insertions(+) create mode 100644 pyrogram/__init__.py create mode 100644 pyrogram/client.py create mode 100644 pyrogram/dispatcher.py create mode 100644 pyrogram/emoji.py create mode 100644 pyrogram/file_id.py create mode 100644 pyrogram/filters.py create mode 100644 pyrogram/mime_types.py create mode 100644 pyrogram/py.typed create mode 100644 pyrogram/sync.py create mode 100644 pyrogram/utils.py diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py new file mode 100644 index 0000000000..5b8f537c1d --- /dev/null +++ b/pyrogram/__init__.py @@ -0,0 +1,42 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present 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 . + +__version__ = "2.0.93" +__license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)" +__copyright__ = "Copyright (C) 2017-present Dan " + +from concurrent.futures.thread import ThreadPoolExecutor + + +class StopTransmission(Exception): + pass + + +class StopPropagation(StopAsyncIteration): + pass + + +class ContinuePropagation(StopAsyncIteration): + pass + + +from . import raw, types, filters, handlers, emoji, enums +from .client import Client +from .sync import idle, compose + +crypto_executor = ThreadPoolExecutor(1, thread_name_prefix="CryptoWorker") diff --git a/pyrogram/client.py b/pyrogram/client.py new file mode 100644 index 0000000000..7848c1f5b9 --- /dev/null +++ b/pyrogram/client.py @@ -0,0 +1,1045 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present 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 logging +import os +import platform +import re +import shutil +import sys +from concurrent.futures.thread import ThreadPoolExecutor +from datetime import datetime, timedelta +from hashlib import sha256 +from importlib import import_module +from io import StringIO, BytesIO +from mimetypes import MimeTypes +from pathlib import Path +from typing import Union, List, Optional, Callable, AsyncGenerator + +import pyrogram +from pyrogram import __version__, __license__ +from pyrogram import enums +from pyrogram import raw +from pyrogram import utils +from pyrogram.crypto import aes +from pyrogram.errors import CDNFileHashMismatch +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 FileStorage, MemoryStorage +from pyrogram.types import User, TermsOfService +from pyrogram.utils import ainput +from .dispatcher import Dispatcher +from .file_id import FileId, FileType, ThumbnailSource +from .mime_types import mime_types +from .parser import Parser +from .session.internals import MsgId + +log = logging.getLogger(__name__) + + +class Client(Methods): + """Pyrogram Client, the main means for interacting with Telegram. + + Parameters: + name (``str``): + A name for the client, e.g.: "my_account". + + api_id (``int`` | ``str``, *optional*): + The *api_id* part of the Telegram API key, as integer or string. + E.g.: 12345 or "12345". + + api_hash (``str``, *optional*): + The *api_hash* part of the Telegram API key, as string. + E.g.: "0123456789abcdef0123456789abcdef". + + app_version (``str``, *optional*): + Application version. + Defaults to "Pyrogram x.y.z". + + device_model (``str``, *optional*): + Device model. + Defaults to *platform.python_implementation() + " " + platform.python_version()*. + + system_version (``str``, *optional*): + Operating System version. + Defaults to *platform.system() + " " + platform.release()*. + + lang_code (``str``, *optional*): + Code of the language used on the client, in ISO 639-1 standard. + Defaults to "en". + + ipv6 (``bool``, *optional*): + Pass True to connect to Telegram using IPv6. + Defaults to False (IPv4). + + proxy (``dict``, *optional*): + The Proxy settings as dict. + E.g.: *dict(scheme="socks5", hostname="11.22.33.44", port=1234, username="user", password="pass")*. + The *username* and *password* can be omitted if the proxy doesn't require authorization. + + 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 the Bot API token to create a bot session, e.g.: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11" + Only applicable for new sessions. + + session_string (``str``, *optional*): + Pass a session string to load the session in-memory. + Implies ``in_memory=True``. + + in_memory (``bool``, *optional*): + Pass True to start an in-memory session that will be discarded as soon as the client stops. + In order to reconnect again using an in-memory session 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 to the ``session_string`` parameter. + Defaults to False. + + phone_number (``str``, *optional*): + Pass the phone number as string (with the 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 the Two-Step Verification password as string (if required) to avoid entering it manually. + Only applicable for new sessions. + + 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 the filesystem where Pyrogram will store the session files. + Defaults to the parent directory of the main script. + + plugins (``dict``, *optional*): + Smart Plugins settings as dict, e.g.: *dict(root="plugins")*. + + parse_mode (:obj:`~pyrogram.enums.ParseMode`, *optional*): + Set the global parse mode of the client. By default, texts are parsed using both Markdown and HTML styles. + You can combine both syntaxes together. + + no_updates (``bool``, *optional*): + Pass True to disable incoming updates. + When updates are disabled the client can't receive messages or other updates. + Useful for batch programs that don't need to deal with updates. + Defaults to False (updates enabled and 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 Telegram data. Methods invoked inside a takeout session (such as get_chat_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 10 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. + """ + + 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-]+)$") + WORKERS = min(32, (os.cpu_count() or 0) + 4) # os.cpu_count() can be None + WORKDIR = PARENT_DIR + + # Interval of seconds in which the updates watchdog will kick in + UPDATES_WATCHDOG_INTERVAL = 5 * 60 + + mimetypes = MimeTypes() + mimetypes.readfp(StringIO(mime_types)) + + def __init__( + self, + name: str, + api_id: Union[int, str] = None, + api_hash: str = None, + app_version: str = APP_VERSION, + device_model: str = DEVICE_MODEL, + system_version: str = SYSTEM_VERSION, + lang_code: str = LANG_CODE, + ipv6: bool = False, + proxy: dict = None, + test_mode: bool = False, + bot_token: str = None, + session_string: str = None, + in_memory: bool = None, + phone_number: str = None, + phone_code: str = None, + password: str = None, + workers: int = WORKERS, + workdir: str = WORKDIR, + plugins: dict = None, + parse_mode: "enums.ParseMode" = enums.ParseMode.DEFAULT, + no_updates: bool = None, + takeout: bool = None, + sleep_threshold: int = Session.SLEEP_THRESHOLD, + hide_password: bool = False + ): + super().__init__() + + self.name = 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.lower() + self.ipv6 = ipv6 + self.proxy = proxy + self.test_mode = test_mode + self.bot_token = bot_token + self.session_string = session_string + self.in_memory = in_memory + self.phone_number = phone_number + self.phone_code = phone_code + self.password = password + self.workers = workers + self.workdir = Path(workdir) + self.plugins = plugins + self.parse_mode = parse_mode + 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") + + if self.session_string: + self.storage = MemoryStorage(self.name, self.session_string) + elif self.in_memory: + self.storage = MemoryStorage(self.name) + else: + self.storage = FileStorage(self.name, self.workdir) + + self.dispatcher = Dispatcher(self) + + self.rnd_id = MsgId + + self.parser = Parser(self) + + self.session = None + + self.media_sessions = {} + self.media_sessions_lock = asyncio.Lock() + + self.is_connected = None + self.is_initialized = None + + self.takeout_id = None + + self.disconnect_handler = None + + self.me: Optional[User] = None + + self.message_cache = Cache(10000) + + # Sometimes, for some reason, the server will stop sending updates and will only respond to pings. + # This watchdog will invoke updates.GetState in order to wake up the server and enable it sending updates again + # after some idle time has been detected. + self.updates_watchdog_task = None + self.updates_watchdog_event = asyncio.Event() + self.last_update_time = datetime.now() + + 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): + try: + await self.stop() + except ConnectionError: + pass + + async def updates_watchdog(self): + while True: + try: + await asyncio.wait_for(self.updates_watchdog_event.wait(), self.UPDATES_WATCHDOG_INTERVAL) + except asyncio.TimeoutError: + pass + else: + break + + if datetime.now() - self.last_update_time > timedelta(seconds=self.UPDATES_WATCHDOG_INTERVAL): + await self.invoke(raw.functions.updates.GetState()) + + async def authorize(self) -> User: + if self.bot_token: + return await self.sign_in_bot(self.bot_token) + + print(f"Welcome to Pyrogram (version {__version__})") + print(f"Pyrogram is free software and comes with ABSOLUTELY NO WARRANTY. Licensed\n" + f"under the terms of the {__license__}.\n") + + 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 + + sent_code_descriptions = { + enums.SentCodeType.APP: "Telegram app", + enums.SentCodeType.SMS: "SMS", + enums.SentCodeType.CALL: "phone call", + enums.SentCodeType.FLASH_CALL: "phone flash call", + enums.SentCodeType.FRAGMENT_SMS: "Fragment SMS", + enums.SentCodeType.EMAIL_CODE: "email code" + } + + print(f"The confirmation code has been sent via {sent_code_descriptions[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=self.hide_password) + + 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.exception(e) + 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 + + def set_parse_mode(self, parse_mode: Optional["enums.ParseMode"]): + """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. + + Parameters: + parse_mode (:obj:`~pyrogram.enums.ParseMode`): + By default, texts are parsed using both Markdown and HTML styles. + You can combine both syntaxes together. + + Example: + .. code-block:: python + + from pyrogram import enums + + # Default combined mode: Markdown + HTML + await app.send_message("me", "1. **markdown** and html") + + # Force Markdown-only, HTML is disabled + app.set_parse_mode(enums.ParseMode.MARKDOWN) + await app.send_message("me", "2. **markdown** and html") + + # Force HTML-only, Markdown is disabled + app.set_parse_mode(enums.ParseMode.HTML) + await app.send_message("me", "3. **markdown** and html") + + # Disable the parser completely + app.set_parse_mode(enums.ParseMode.DISABLED) + await app.send_message("me", "4. **markdown** and html") + + # Bring back the default combined mode + app.set_parse_mode(enums.ParseMode.DEFAULT) + await app.send_message("me", "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.lower() if peer.username + else peer.usernames[0].username.lower() if peer.usernames + else 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_updates(self, updates): + self.last_update_time = datetime.now() + + if isinstance(updates, (raw.types.Updates, raw.types.UpdatesCombined)): + is_min = any(( + await self.fetch_peers(updates.users), + 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 + ), "peer_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.invoke( + 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.invoke( + 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: + if diff.other_updates: # The other_updates list can be empty + 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) + + 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: + if not self.api_id or not self.api_hash: + raise AttributeError("The API key is required for new authorizations. " + "More info: https://docs.pyrogram.org/start/auth") + + await self.storage.api_id(self.api_id) + + 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) + else: + # Needed for migration from storage v2 to v3 + if not await self.storage.api_id(): + if self.api_id: + await self.storage.api_id(self.api_id) + else: + while True: + try: + value = int(await ainput("Enter the api_id part of the API key: ")) + + if value <= 0: + print("Invalid value") + continue + + confirm = (await ainput(f'Is "{value}" correct? (y/N): ')).lower() + + if confirm == "y": + await self.storage.api_id(value) + break + except Exception as e: + print(e) + + def load_plugins(self): + if self.plugins: + plugins = self.plugins.copy() + + for option in ["include", "exclude"]: + if plugins.get(option, []): + plugins[option] = [ + (i.split()[0], i.split()[1:] or None) + for i in self.plugins[option] + ] + else: + return + + if plugins.get("enabled", True): + root = plugins["root"] + include = plugins.get("include", []) + exclude = plugins.get("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: + for handler, group in getattr(module, name).handlers: + if isinstance(handler, Handler) and isinstance(group, int): + self.add_handler(handler, group) + + log.info('[{}] [LOAD] {}("{}") in group {} from "{}"'.format( + self.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('[%s] [LOAD] Ignoring non-existent module "%s"', self.name, module_path) + continue + + if "__path__" in dir(module): + log.warning('[%s] [LOAD] Ignoring namespace "%s"', self.name, module_path) + continue + + if handlers is None: + handlers = vars(module).keys() + warn_non_existent_functions = False + + for name in handlers: + # noinspection PyBroadException + try: + for handler, group in getattr(module, name).handlers: + if isinstance(handler, Handler) and isinstance(group, int): + self.add_handler(handler, group) + + log.info('[{}] [LOAD] {}("{}") in group {} from "{}"'.format( + self.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.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('[%s] [UNLOAD] Ignoring non-existent module "%s"', self.name, module_path) + continue + + if "__path__" in dir(module): + log.warning('[%s] [UNLOAD] Ignoring namespace "%s"', self.name, module_path) + continue + + if handlers is None: + handlers = vars(module).keys() + warn_non_existent_functions = False + + for name in handlers: + # noinspection PyBroadException + try: + for handler, group in getattr(module, name).handlers: + if isinstance(handler, Handler) and isinstance(group, int): + self.remove_handler(handler, group) + + log.info('[{}] [UNLOAD] {}("{}") from group {} in "{}"'.format( + self.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.name, name, module_path)) + + if count > 0: + log.info('[{}] Successfully loaded {} plugin{} from "{}"'.format( + self.name, count, "s" if count > 1 else "", root)) + else: + log.warning('[%s] No plugin loaded from "%s"', self.name, root) + + async def handle_download(self, packet): + file_id, directory, file_name, in_memory, file_size, progress, progress_args = packet + + os.makedirs(directory, exist_ok=True) if not in_memory else None + temp_file_path = os.path.abspath(re.sub("\\\\", "/", os.path.join(directory, file_name))) + ".temp" + file = BytesIO() if in_memory else open(temp_file_path, "wb") + + try: + async for chunk in self.get_file(file_id, file_size, 0, 0, progress, progress_args): + file.write(chunk) + except BaseException as e: + if not in_memory: + file.close() + os.remove(temp_file_path) + + if isinstance(e, asyncio.CancelledError): + raise e + + return None + else: + if in_memory: + file.name = file_name + return file + else: + file.close() + file_path = os.path.splitext(temp_file_path)[0] + shutil.move(temp_file_path, file_path) + return file_path + + async def get_file( + self, + file_id: FileId, + file_size: int = 0, + limit: int = 0, + offset: int = 0, + progress: Callable = None, + progress_args: tuple = () + ) -> Optional[AsyncGenerator[bytes, None]]: + dc_id = file_id.dc_id + + 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.invoke( + raw.functions.auth.ExportAuthorization( + dc_id=dc_id + ) + ) + + try: + await session.invoke( + 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_type = file_id.file_type + + if file_type == FileType.CHAT_PHOTO: + if file_id.chat_id > 0: + peer = raw.types.InputPeerUser( + user_id=file_id.chat_id, + access_hash=file_id.chat_access_hash + ) + else: + if file_id.chat_access_hash == 0: + peer = raw.types.InputPeerChat( + chat_id=-file_id.chat_id + ) + else: + peer = raw.types.InputPeerChannel( + channel_id=utils.get_channel_id(file_id.chat_id), + access_hash=file_id.chat_access_hash + ) + + location = raw.types.InputPeerPhotoFileLocation( + peer=peer, + photo_id=file_id.media_id, + big=file_id.thumbnail_source == ThumbnailSource.CHAT_PHOTO_BIG + ) + elif file_type == FileType.PHOTO: + location = raw.types.InputPhotoFileLocation( + id=file_id.media_id, + access_hash=file_id.access_hash, + file_reference=file_id.file_reference, + thumb_size=file_id.thumbnail_size + ) + else: + location = raw.types.InputDocumentFileLocation( + id=file_id.media_id, + access_hash=file_id.access_hash, + file_reference=file_id.file_reference, + thumb_size=file_id.thumbnail_size + ) + + current = 0 + total = abs(limit) or (1 << 31) - 1 + chunk_size = 1024 * 1024 + offset_bytes = abs(offset) * chunk_size + + try: + r = await session.invoke( + raw.functions.upload.GetFile( + location=location, + offset=offset_bytes, + limit=chunk_size + ), + sleep_threshold=30 + ) + + if isinstance(r, raw.types.upload.File): + while True: + chunk = r.bytes + + yield chunk + + current += 1 + offset_bytes += chunk_size + + if progress: + func = functools.partial( + progress, + min(offset_bytes, file_size) + if file_size != 0 + else offset_bytes, + file_size, + *progress_args + ) + + if inspect.iscoroutinefunction(progress): + await func() + else: + await self.loop.run_in_executor(self.executor, func) + + if len(chunk) < chunk_size or current >= total: + break + + r = await session.invoke( + raw.functions.upload.GetFile( + location=location, + offset=offset_bytes, + limit=chunk_size + ), + sleep_threshold=30 + ) + + 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: + while True: + r2 = await cdn_session.invoke( + raw.functions.upload.GetCdnFile( + file_token=r.file_token, + offset=offset_bytes, + limit=chunk_size + ) + ) + + if isinstance(r2, raw.types.upload.CdnFileReuploadNeeded): + try: + await session.invoke( + 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_bytes // 16).to_bytes(4, "big") + ) + ) + + hashes = await session.invoke( + raw.functions.upload.GetCdnFileHashes( + file_token=r.file_token, + offset=offset_bytes + ) + ) + + # https://core.telegram.org/cdn#verifying-files + for i, h in enumerate(hashes): + cdn_chunk = decrypted_chunk[h.limit * i: h.limit * (i + 1)] + CDNFileHashMismatch.check( + h.hash == sha256(cdn_chunk).digest(), + "h.hash == sha256(cdn_chunk).digest()" + ) + + yield decrypted_chunk + + current += 1 + offset_bytes += chunk_size + + if progress: + func = functools.partial( + progress, + min(offset_bytes, file_size) if file_size != 0 else offset_bytes, + file_size, + *progress_args + ) + + if inspect.iscoroutinefunction(progress): + await func() + else: + await self.loop.run_in_executor(self.executor, func) + + if len(chunk) < chunk_size or current >= total: + break + except Exception as e: + raise e + except pyrogram.StopTransmission: + raise + except Exception as e: + log.exception(e) + + def guess_mime_type(self, filename: str) -> Optional[str]: + return self.mimetypes.guess_type(filename)[0] + + def guess_extension(self, mime_type: str) -> Optional[str]: + return self.mimetypes.guess_extension(mime_type) + + +class Cache: + def __init__(self, capacity: int): + self.capacity = capacity + self.store = {} + + def __getitem__(self, key): + return self.store.get(key, None) + + def __setitem__(self, key, value): + if key in self.store: + del self.store[key] + + self.store[key] = value + + if len(self.store) > self.capacity: + for _ in range(self.capacity // 2 + 1): + del self.store[next(iter(self.store))] diff --git a/pyrogram/dispatcher.py b/pyrogram/dispatcher.py new file mode 100644 index 0000000000..6e503cebb3 --- /dev/null +++ b/pyrogram/dispatcher.py @@ -0,0 +1,259 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present 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 inspect +import logging +from collections import OrderedDict + +import pyrogram +from pyrogram import utils +from pyrogram.handlers import ( + CallbackQueryHandler, MessageHandler, EditedMessageHandler, DeletedMessagesHandler, + UserStatusHandler, RawUpdateHandler, InlineQueryHandler, PollHandler, + ChosenInlineResultHandler, ChatMemberUpdatedHandler, ChatJoinRequestHandler +) +from pyrogram.raw.types import ( + UpdateNewMessage, UpdateNewChannelMessage, UpdateNewScheduledMessage, + UpdateEditMessage, UpdateEditChannelMessage, + UpdateDeleteMessages, UpdateDeleteChannelMessages, + UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery, + UpdateUserStatus, UpdateBotInlineQuery, UpdateMessagePoll, + UpdateBotInlineSend, UpdateChatParticipant, UpdateChannelParticipant, + UpdateBotChatInviteRequester +) + +log = logging.getLogger(__name__) + + +class Dispatcher: + NEW_MESSAGE_UPDATES = (UpdateNewMessage, UpdateNewChannelMessage, UpdateNewScheduledMessage) + EDIT_MESSAGE_UPDATES = (UpdateEditMessage, UpdateEditChannelMessage) + DELETE_MESSAGES_UPDATES = (UpdateDeleteMessages, UpdateDeleteChannelMessages) + CALLBACK_QUERY_UPDATES = (UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery) + CHAT_MEMBER_UPDATES = (UpdateChatParticipant, UpdateChannelParticipant) + USER_STATUS_UPDATES = (UpdateUserStatus,) + BOT_INLINE_QUERY_UPDATES = (UpdateBotInlineQuery,) + POLL_UPDATES = (UpdateMessagePoll,) + CHOSEN_INLINE_RESULT_UPDATES = (UpdateBotInlineSend,) + CHAT_JOIN_REQUEST_UPDATES = (UpdateBotChatInviteRequester,) + + def __init__(self, client: "pyrogram.Client"): + self.client = client + self.loop = asyncio.get_event_loop() + + 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.types.Message._parse(self.client, update.message, users, chats, + isinstance(update, UpdateNewScheduledMessage)), + MessageHandler + ) + + async def edited_message_parser(update, users, chats): + # Edited messages are parsed the same way as new messages, but the handler is different + parsed, _ = await message_parser(update, users, chats) + + return ( + parsed, + EditedMessageHandler + ) + + 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.types.CallbackQuery._parse(self.client, update, users), + CallbackQueryHandler + ) + + async def user_status_parser(update, users, chats): + return ( + pyrogram.types.User._parse_user_status(self.client, update), + UserStatusHandler + ) + + async def inline_query_parser(update, users, chats): + return ( + pyrogram.types.InlineQuery._parse(self.client, update, users), + InlineQueryHandler + ) + + async def poll_parser(update, users, chats): + return ( + pyrogram.types.Poll._parse_update(self.client, update), + PollHandler + ) + + async def chosen_inline_result_parser(update, users, chats): + return ( + pyrogram.types.ChosenInlineResult._parse(self.client, update, users), + ChosenInlineResultHandler + ) + + async def chat_member_updated_parser(update, users, chats): + return ( + pyrogram.types.ChatMemberUpdated._parse(self.client, update, users, chats), + ChatMemberUpdatedHandler + ) + + async def chat_join_request_parser(update, users, chats): + return ( + pyrogram.types.ChatJoinRequest._parse(self.client, update, users, chats), + ChatJoinRequestHandler + ) + + self.update_parsers = { + Dispatcher.NEW_MESSAGE_UPDATES: message_parser, + Dispatcher.EDIT_MESSAGE_UPDATES: edited_message_parser, + Dispatcher.DELETE_MESSAGES_UPDATES: deleted_messages_parser, + Dispatcher.CALLBACK_QUERY_UPDATES: callback_query_parser, + Dispatcher.USER_STATUS_UPDATES: user_status_parser, + Dispatcher.BOT_INLINE_QUERY_UPDATES: inline_query_parser, + Dispatcher.POLL_UPDATES: poll_parser, + Dispatcher.CHOSEN_INLINE_RESULT_UPDATES: chosen_inline_result_parser, + Dispatcher.CHAT_MEMBER_UPDATES: chat_member_updated_parser, + Dispatcher.CHAT_JOIN_REQUEST_UPDATES: chat_join_request_parser + } + + self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple} + + async def start(self): + if not self.client.no_updates: + for i in range(self.client.workers): + self.locks_list.append(asyncio.Lock()) + + self.handler_worker_tasks.append( + self.loop.create_task(self.handler_worker(self.locks_list[-1])) + ) + + log.info("Started %s HandlerTasks", self.client.workers) + + async def stop(self): + if not self.client.no_updates: + for i in range(self.client.workers): + self.updates_queue.put_nowait(None) + + for i in self.handler_worker_tasks: + await i + + self.handler_worker_tasks.clear() + self.groups.clear() + + log.info("Stopped %s HandlerTasks", self.client.workers) + + def add_handler(self, handler, group: int): + async def fn(): + for lock in self.locks_list: + await lock.acquire() + + try: + if group not in self.groups: + self.groups[group] = [] + self.groups = OrderedDict(sorted(self.groups.items())) + + self.groups[group].append(handler) + finally: + for lock in self.locks_list: + lock.release() + + self.loop.create_task(fn()) + + def remove_handler(self, handler, group: int): + async def fn(): + for lock in self.locks_list: + await lock.acquire() + + try: + if group not in self.groups: + raise ValueError(f"Group {group} does not exist. Handler was not removed.") + + self.groups[group].remove(handler) + finally: + for lock in self.locks_list: + lock.release() + + self.loop.create_task(fn()) + + async def handler_worker(self, lock): + while True: + packet = await self.updates_queue.get() + + if packet is None: + break + + try: + update, users, chats = packet + parser = self.update_parsers.get(type(update), None) + + parsed_update, handler_type = ( + await parser(update, users, chats) + if parser is not None + else (None, type(None)) + ) + + async with lock: + for group in self.groups.values(): + for handler in group: + args = None + + if isinstance(handler, handler_type): + try: + if await handler.check(self.client, parsed_update): + args = (parsed_update,) + except Exception as e: + log.exception(e) + continue + + elif isinstance(handler, RawUpdateHandler): + args = (update, users, chats) + + if args is None: + continue + + try: + if inspect.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: + continue + except Exception as e: + log.exception(e) + + break + except pyrogram.StopPropagation: + pass + except Exception as e: + log.exception(e) diff --git a/pyrogram/emoji.py b/pyrogram/emoji.py new file mode 100644 index 0000000000..d135faf74d --- /dev/null +++ b/pyrogram/emoji.py @@ -0,0 +1,4019 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present 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" +MELTING_FACE = "\U0001fae0" +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" +SMILING_FACE_WITH_OPEN_HANDS = "\U0001f917" +FACE_WITH_HAND_OVER_MOUTH = "\U0001f92d" +FACE_WITH_OPEN_EYES_AND_HAND_OVER_MOUTH = "\U0001fae2" +FACE_WITH_PEEKING_EYE = "\U0001fae3" +SHUSHING_FACE = "\U0001f92b" +THINKING_FACE = "\U0001f914" +SALUTING_FACE = "\U0001fae1" +ZIPPER_MOUTH_FACE = "\U0001f910" +FACE_WITH_RAISED_EYEBROW = "\U0001f928" +NEUTRAL_FACE = "\U0001f610" +EXPRESSIONLESS_FACE = "\U0001f611" +FACE_WITHOUT_MOUTH = "\U0001f636" +DOTTED_LINE_FACE = "\U0001fae5" +FACE_IN_CLOUDS = "\U0001f636\u200d\U0001f32b\ufe0f" +SMIRKING_FACE = "\U0001f60f" +UNAMUSED_FACE = "\U0001f612" +FACE_WITH_ROLLING_EYES = "\U0001f644" +GRIMACING_FACE = "\U0001f62c" +FACE_EXHALING = "\U0001f62e\u200d\U0001f4a8" +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" +FACE_WITH_CROSSED_OUT_EYES = "\U0001f635" +FACE_WITH_SPIRAL_EYES = "\U0001f635\u200d\U0001f4ab" +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" +FACE_WITH_DIAGONAL_MOUTH = "\U0001fae4" +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" +FACE_HOLDING_BACK_TEARS = "\U0001f979" +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" +ENRAGED_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" +HEART_ON_FIRE = "\u2764\ufe0f\u200d\U0001f525" +MENDING_HEART = "\u2764\ufe0f\u200d\U0001fa79" +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" +RIGHTWARDS_HAND = "\U0001faf1" +RIGHTWARDS_HAND_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fb" +RIGHTWARDS_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fc" +RIGHTWARDS_HAND_MEDIUM_SKIN_TONE = "\U0001faf1\U0001f3fd" +RIGHTWARDS_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001faf1\U0001f3fe" +RIGHTWARDS_HAND_DARK_SKIN_TONE = "\U0001faf1\U0001f3ff" +LEFTWARDS_HAND = "\U0001faf2" +LEFTWARDS_HAND_LIGHT_SKIN_TONE = "\U0001faf2\U0001f3fb" +LEFTWARDS_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf2\U0001f3fc" +LEFTWARDS_HAND_MEDIUM_SKIN_TONE = "\U0001faf2\U0001f3fd" +LEFTWARDS_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001faf2\U0001f3fe" +LEFTWARDS_HAND_DARK_SKIN_TONE = "\U0001faf2\U0001f3ff" +PALM_DOWN_HAND = "\U0001faf3" +PALM_DOWN_HAND_LIGHT_SKIN_TONE = "\U0001faf3\U0001f3fb" +PALM_DOWN_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf3\U0001f3fc" +PALM_DOWN_HAND_MEDIUM_SKIN_TONE = "\U0001faf3\U0001f3fd" +PALM_DOWN_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001faf3\U0001f3fe" +PALM_DOWN_HAND_DARK_SKIN_TONE = "\U0001faf3\U0001f3ff" +PALM_UP_HAND = "\U0001faf4" +PALM_UP_HAND_LIGHT_SKIN_TONE = "\U0001faf4\U0001f3fb" +PALM_UP_HAND_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf4\U0001f3fc" +PALM_UP_HAND_MEDIUM_SKIN_TONE = "\U0001faf4\U0001f3fd" +PALM_UP_HAND_MEDIUM_DARK_SKIN_TONE = "\U0001faf4\U0001f3fe" +PALM_UP_HAND_DARK_SKIN_TONE = "\U0001faf4\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" +HAND_WITH_INDEX_FINGER_AND_THUMB_CROSSED = "\U0001faf0" +HAND_WITH_INDEX_FINGER_AND_THUMB_CROSSED_LIGHT_SKIN_TONE = "\U0001faf0\U0001f3fb" +HAND_WITH_INDEX_FINGER_AND_THUMB_CROSSED_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf0\U0001f3fc" +HAND_WITH_INDEX_FINGER_AND_THUMB_CROSSED_MEDIUM_SKIN_TONE = "\U0001faf0\U0001f3fd" +HAND_WITH_INDEX_FINGER_AND_THUMB_CROSSED_MEDIUM_DARK_SKIN_TONE = "\U0001faf0\U0001f3fe" +HAND_WITH_INDEX_FINGER_AND_THUMB_CROSSED_DARK_SKIN_TONE = "\U0001faf0\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" +INDEX_POINTING_AT_THE_VIEWER = "\U0001faf5" +INDEX_POINTING_AT_THE_VIEWER_LIGHT_SKIN_TONE = "\U0001faf5\U0001f3fb" +INDEX_POINTING_AT_THE_VIEWER_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf5\U0001f3fc" +INDEX_POINTING_AT_THE_VIEWER_MEDIUM_SKIN_TONE = "\U0001faf5\U0001f3fd" +INDEX_POINTING_AT_THE_VIEWER_MEDIUM_DARK_SKIN_TONE = "\U0001faf5\U0001f3fe" +INDEX_POINTING_AT_THE_VIEWER_DARK_SKIN_TONE = "\U0001faf5\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" +HEART_HANDS = "\U0001faf6" +HEART_HANDS_LIGHT_SKIN_TONE = "\U0001faf6\U0001f3fb" +HEART_HANDS_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf6\U0001f3fc" +HEART_HANDS_MEDIUM_SKIN_TONE = "\U0001faf6\U0001f3fd" +HEART_HANDS_MEDIUM_DARK_SKIN_TONE = "\U0001faf6\U0001f3fe" +HEART_HANDS_DARK_SKIN_TONE = "\U0001faf6\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" +HANDSHAKE_LIGHT_SKIN_TONE = "\U0001f91d\U0001f3fb" +HANDSHAKE_MEDIUM_LIGHT_SKIN_TONE = "\U0001f91d\U0001f3fc" +HANDSHAKE_MEDIUM_SKIN_TONE = "\U0001f91d\U0001f3fd" +HANDSHAKE_MEDIUM_DARK_SKIN_TONE = "\U0001f91d\U0001f3fe" +HANDSHAKE_DARK_SKIN_TONE = "\U0001f91d\U0001f3ff" +HANDSHAKE_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fb\u200d\U0001faf2\U0001f3fc" +HANDSHAKE_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = "\U0001faf1\U0001f3fb\u200d\U0001faf2\U0001f3fd" +HANDSHAKE_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = "\U0001faf1\U0001f3fb\u200d\U0001faf2\U0001f3fe" +HANDSHAKE_LIGHT_SKIN_TONE_DARK_SKIN_TONE = "\U0001faf1\U0001f3fb\u200d\U0001faf2\U0001f3ff" +HANDSHAKE_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fc\u200d\U0001faf2\U0001f3fb" +HANDSHAKE_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = "\U0001faf1\U0001f3fc\u200d\U0001faf2\U0001f3fd" +HANDSHAKE_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = "\U0001faf1\U0001f3fc\u200d\U0001faf2\U0001f3fe" +HANDSHAKE_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = "\U0001faf1\U0001f3fc\u200d\U0001faf2\U0001f3ff" +HANDSHAKE_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fd\u200d\U0001faf2\U0001f3fb" +HANDSHAKE_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fd\u200d\U0001faf2\U0001f3fc" +HANDSHAKE_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = "\U0001faf1\U0001f3fd\u200d\U0001faf2\U0001f3fe" +HANDSHAKE_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = "\U0001faf1\U0001f3fd\u200d\U0001faf2\U0001f3ff" +HANDSHAKE_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fe\u200d\U0001faf2\U0001f3fb" +HANDSHAKE_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3fe\u200d\U0001faf2\U0001f3fc" +HANDSHAKE_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = "\U0001faf1\U0001f3fe\u200d\U0001faf2\U0001f3fd" +HANDSHAKE_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = "\U0001faf1\U0001f3fe\u200d\U0001faf2\U0001f3ff" +HANDSHAKE_DARK_SKIN_TONE_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3ff\u200d\U0001faf2\U0001f3fb" +HANDSHAKE_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = "\U0001faf1\U0001f3ff\u200d\U0001faf2\U0001f3fc" +HANDSHAKE_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = "\U0001faf1\U0001f3ff\u200d\U0001faf2\U0001f3fd" +HANDSHAKE_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = "\U0001faf1\U0001f3ff\u200d\U0001faf2\U0001f3fe" +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" +BITING_LIP = "\U0001fae6" +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" +PERSON_BEARD = "\U0001f9d4" +PERSON_LIGHT_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fb" +PERSON_MEDIUM_LIGHT_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fc" +PERSON_MEDIUM_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fd" +PERSON_MEDIUM_DARK_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fe" +PERSON_DARK_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3ff" +MAN_BEARD = "\U0001f9d4\u200d\u2642\ufe0f" +MAN_LIGHT_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fb\u200d\u2642\ufe0f" +MAN_MEDIUM_LIGHT_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fc\u200d\u2642\ufe0f" +MAN_MEDIUM_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fd\u200d\u2642\ufe0f" +MAN_MEDIUM_DARK_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fe\u200d\u2642\ufe0f" +MAN_DARK_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3ff\u200d\u2642\ufe0f" +WOMAN_BEARD = "\U0001f9d4\u200d\u2640\ufe0f" +WOMAN_LIGHT_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fb\u200d\u2640\ufe0f" +WOMAN_MEDIUM_LIGHT_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fc\u200d\u2640\ufe0f" +WOMAN_MEDIUM_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fd\u200d\u2640\ufe0f" +WOMAN_MEDIUM_DARK_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3fe\u200d\u2640\ufe0f" +WOMAN_DARK_SKIN_TONE_BEARD = "\U0001f9d4\U0001f3ff\u200d\u2640\ufe0f" +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" +PERSON_WITH_CROWN = "\U0001fac5" +PERSON_WITH_CROWN_LIGHT_SKIN_TONE = "\U0001fac5\U0001f3fb" +PERSON_WITH_CROWN_MEDIUM_LIGHT_SKIN_TONE = "\U0001fac5\U0001f3fc" +PERSON_WITH_CROWN_MEDIUM_SKIN_TONE = "\U0001fac5\U0001f3fd" +PERSON_WITH_CROWN_MEDIUM_DARK_SKIN_TONE = "\U0001fac5\U0001f3fe" +PERSON_WITH_CROWN_DARK_SKIN_TONE = "\U0001fac5\U0001f3ff" +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" +PREGNANT_MAN = "\U0001fac3" +PREGNANT_MAN_LIGHT_SKIN_TONE = "\U0001fac3\U0001f3fb" +PREGNANT_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001fac3\U0001f3fc" +PREGNANT_MAN_MEDIUM_SKIN_TONE = "\U0001fac3\U0001f3fd" +PREGNANT_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001fac3\U0001f3fe" +PREGNANT_MAN_DARK_SKIN_TONE = "\U0001fac3\U0001f3ff" +PREGNANT_PERSON = "\U0001fac4" +PREGNANT_PERSON_LIGHT_SKIN_TONE = "\U0001fac4\U0001f3fb" +PREGNANT_PERSON_MEDIUM_LIGHT_SKIN_TONE = "\U0001fac4\U0001f3fc" +PREGNANT_PERSON_MEDIUM_SKIN_TONE = "\U0001fac4\U0001f3fd" +PREGNANT_PERSON_MEDIUM_DARK_SKIN_TONE = "\U0001fac4\U0001f3fe" +PREGNANT_PERSON_DARK_SKIN_TONE = "\U0001fac4\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" +TROLL = "\U0001f9cc" +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" +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" +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_LIGHT_SKIN_TONE = "\U0001f48f\U0001f3fb" +KISS_MEDIUM_LIGHT_SKIN_TONE = "\U0001f48f\U0001f3fc" +KISS_MEDIUM_SKIN_TONE = "\U0001f48f\U0001f3fd" +KISS_MEDIUM_DARK_SKIN_TONE = "\U0001f48f\U0001f3fe" +KISS_DARK_SKIN_TONE = "\U0001f48f\U0001f3ff" +KISS_PERSON_PERSON_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fc" +KISS_PERSON_PERSON_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fd" +KISS_PERSON_PERSON_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fe" +KISS_PERSON_PERSON_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3ff" +KISS_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fb" +KISS_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fd" +KISS_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fe" +KISS_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3ff" +KISS_PERSON_PERSON_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fb" +KISS_PERSON_PERSON_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fc" +KISS_PERSON_PERSON_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fe" +KISS_PERSON_PERSON_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3ff" +KISS_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fb" +KISS_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fc" +KISS_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fd" +KISS_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3ff" +KISS_PERSON_PERSON_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fb" +KISS_PERSON_PERSON_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fc" +KISS_PERSON_PERSON_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fd" +KISS_PERSON_PERSON_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f9d1\U0001f3fe" +KISS_WOMAN_MAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468" +KISS_WOMAN_MAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" +KISS_WOMAN_MAN_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" +KISS_WOMAN_MAN_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" +KISS_WOMAN_MAN_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" +KISS_WOMAN_MAN_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" +KISS_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" +KISS_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" +KISS_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" +KISS_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" +KISS_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" +KISS_WOMAN_MAN_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" +KISS_WOMAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" +KISS_WOMAN_MAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" +KISS_WOMAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" +KISS_WOMAN_MAN_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" +KISS_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" +KISS_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" +KISS_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" +KISS_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" +KISS_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" +KISS_WOMAN_MAN_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" +KISS_WOMAN_MAN_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" +KISS_WOMAN_MAN_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" +KISS_WOMAN_MAN_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" +KISS_WOMAN_MAN_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" +KISS_MAN_MAN = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468" +KISS_MAN_MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" +KISS_MAN_MAN_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" +KISS_MAN_MAN_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" +KISS_MAN_MAN_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" +KISS_MAN_MAN_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" +KISS_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" +KISS_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" +KISS_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" +KISS_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" +KISS_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" +KISS_MAN_MAN_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" +KISS_MAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" +KISS_MAN_MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" +KISS_MAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" +KISS_MAN_MAN_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" +KISS_MAN_MAN_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" +KISS_MAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" +KISS_MAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" +KISS_MAN_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" +KISS_MAN_MAN_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" +KISS_MAN_MAN_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fb" +KISS_MAN_MAN_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fc" +KISS_MAN_MAN_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fd" +KISS_MAN_MAN_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3fe" +KISS_MAN_MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468\U0001f3ff" +KISS_WOMAN_WOMAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469" +KISS_WOMAN_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb" +KISS_WOMAN_WOMAN_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc" +KISS_WOMAN_WOMAN_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd" +KISS_WOMAN_WOMAN_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe" +KISS_WOMAN_WOMAN_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff" +KISS_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb" +KISS_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc" +KISS_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd" +KISS_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe" +KISS_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff" +KISS_WOMAN_WOMAN_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb" +KISS_WOMAN_WOMAN_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc" +KISS_WOMAN_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd" +KISS_WOMAN_WOMAN_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe" +KISS_WOMAN_WOMAN_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff" +KISS_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb" +KISS_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc" +KISS_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd" +KISS_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe" +KISS_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff" +KISS_WOMAN_WOMAN_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fb" +KISS_WOMAN_WOMAN_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fc" +KISS_WOMAN_WOMAN_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fd" +KISS_WOMAN_WOMAN_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3fe" +KISS_WOMAN_WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469\U0001f3ff" +COUPLE_WITH_HEART = "\U0001f491" +COUPLE_WITH_HEART_LIGHT_SKIN_TONE = "\U0001f491\U0001f3fb" +COUPLE_WITH_HEART_MEDIUM_LIGHT_SKIN_TONE = "\U0001f491\U0001f3fc" +COUPLE_WITH_HEART_MEDIUM_SKIN_TONE = "\U0001f491\U0001f3fd" +COUPLE_WITH_HEART_MEDIUM_DARK_SKIN_TONE = "\U0001f491\U0001f3fe" +COUPLE_WITH_HEART_DARK_SKIN_TONE = "\U0001f491\U0001f3ff" +COUPLE_WITH_HEART_PERSON_PERSON_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fc" +COUPLE_WITH_HEART_PERSON_PERSON_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fd" +COUPLE_WITH_HEART_PERSON_PERSON_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fe" +COUPLE_WITH_HEART_PERSON_PERSON_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3ff" +COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fb" +COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fd" +COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fe" +COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3ff" +COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fb" +COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fc" +COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fe" +COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3ff" +COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fb" +COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fc" +COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fd" +COUPLE_WITH_HEART_PERSON_PERSON_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3ff" +COUPLE_WITH_HEART_PERSON_PERSON_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fb" +COUPLE_WITH_HEART_PERSON_PERSON_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fc" +COUPLE_WITH_HEART_PERSON_PERSON_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fd" +COUPLE_WITH_HEART_PERSON_PERSON_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f9d1\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f9d1\U0001f3fe" +COUPLE_WITH_HEART_WOMAN_MAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f468" +COUPLE_WITH_HEART_WOMAN_MAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" +COUPLE_WITH_HEART_WOMAN_MAN_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" +COUPLE_WITH_HEART_WOMAN_MAN_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" +COUPLE_WITH_HEART_WOMAN_MAN_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" +COUPLE_WITH_HEART_WOMAN_MAN_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" +COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" +COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" +COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" +COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" +COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" +COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" +COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" +COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" +COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" +COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" +COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" +COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" +COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" +COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" +COUPLE_WITH_HEART_WOMAN_MAN_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" +COUPLE_WITH_HEART_WOMAN_MAN_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" +COUPLE_WITH_HEART_WOMAN_MAN_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" +COUPLE_WITH_HEART_WOMAN_MAN_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" +COUPLE_WITH_HEART_WOMAN_MAN_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" +COUPLE_WITH_HEART_WOMAN_MAN_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" +COUPLE_WITH_HEART_MAN_MAN = "\U0001f468\u200d\u2764\ufe0f\u200d\U0001f468" +COUPLE_WITH_HEART_MAN_MAN_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" +COUPLE_WITH_HEART_MAN_MAN_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" +COUPLE_WITH_HEART_MAN_MAN_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" +COUPLE_WITH_HEART_MAN_MAN_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" +COUPLE_WITH_HEART_MAN_MAN_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" +COUPLE_WITH_HEART_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" +COUPLE_WITH_HEART_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE = "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" +COUPLE_WITH_HEART_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" +COUPLE_WITH_HEART_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" +COUPLE_WITH_HEART_MAN_MAN_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" +COUPLE_WITH_HEART_MAN_MAN_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" +COUPLE_WITH_HEART_MAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" +COUPLE_WITH_HEART_MAN_MAN_MEDIUM_SKIN_TONE = "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" +COUPLE_WITH_HEART_MAN_MAN_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" +COUPLE_WITH_HEART_MAN_MAN_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" +COUPLE_WITH_HEART_MAN_MAN_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" +COUPLE_WITH_HEART_MAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" +COUPLE_WITH_HEART_MAN_MAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" +COUPLE_WITH_HEART_MAN_MAN_MEDIUM_DARK_SKIN_TONE = "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" +COUPLE_WITH_HEART_MAN_MAN_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" +COUPLE_WITH_HEART_MAN_MAN_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fb" +COUPLE_WITH_HEART_MAN_MAN_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fc" +COUPLE_WITH_HEART_MAN_MAN_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fd" +COUPLE_WITH_HEART_MAN_MAN_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3fe" +COUPLE_WITH_HEART_MAN_MAN_DARK_SKIN_TONE = "\U0001f468\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f468\U0001f3ff" +COUPLE_WITH_HEART_WOMAN_WOMAN = "\U0001f469\u200d\u2764\ufe0f\u200d\U0001f469" +COUPLE_WITH_HEART_WOMAN_WOMAN_LIGHT_SKIN_TONE = "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb" +COUPLE_WITH_HEART_WOMAN_WOMAN_LIGHT_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc" +COUPLE_WITH_HEART_WOMAN_WOMAN_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd" +COUPLE_WITH_HEART_WOMAN_WOMAN_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe" +COUPLE_WITH_HEART_WOMAN_WOMAN_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fb\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff" +COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb" +COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc" +COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd" +COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe" +COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_LIGHT_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fc\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff" +COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb" +COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc" +COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_SKIN_TONE = "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd" +COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe" +COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fd\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff" +COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb" +COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc" +COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd" +COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe" +COUPLE_WITH_HEART_WOMAN_WOMAN_MEDIUM_DARK_SKIN_TONE_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3fe\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff" +COUPLE_WITH_HEART_WOMAN_WOMAN_DARK_SKIN_TONE_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fb" +COUPLE_WITH_HEART_WOMAN_WOMAN_DARK_SKIN_TONE_MEDIUM_LIGHT_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fc" +COUPLE_WITH_HEART_WOMAN_WOMAN_DARK_SKIN_TONE_MEDIUM_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fd" +COUPLE_WITH_HEART_WOMAN_WOMAN_DARK_SKIN_TONE_MEDIUM_DARK_SKIN_TONE = \ + "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3fe" +COUPLE_WITH_HEART_WOMAN_WOMAN_DARK_SKIN_TONE = "\U0001f469\U0001f3ff\u200d\u2764\ufe0f\u200d\U0001f469\U0001f3ff" +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" +CORAL = "\U0001fab8" +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" +LOTUS = "\U0001fab7" +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" +EMPTY_NEST = "\U0001fab9" +NEST_WITH_EGGS = "\U0001faba" +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" +BEANS = "\U0001fad8" +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" +POURING_LIQUID = "\U0001fad7" +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" +JAR = "\U0001fad9" +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" +PLAYGROUND_SLIDE = "\U0001f6dd" +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" +WHEEL = "\U0001f6de" +POLICE_CAR_LIGHT = "\U0001f6a8" +HORIZONTAL_TRAFFIC_LIGHT = "\U0001f6a5" +VERTICAL_TRAFFIC_LIGHT = "\U0001f6a6" +STOP_SIGN = "\U0001f6d1" +CONSTRUCTION = "\U0001f6a7" +ANCHOR = "\u2693" +RING_BUOY = "\U0001f6df" +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" +BULLSEYE = "\U0001f3af" +YO_YO = "\U0001fa80" +KITE = "\U0001fa81" +POOL_8_BALL = "\U0001f3b1" +CRYSTAL_BALL = "\U0001f52e" +MAGIC_WAND = "\U0001fa84" +NAZAR_AMULET = "\U0001f9ff" +HAMSA = "\U0001faac" +VIDEO_GAME = "\U0001f3ae" +JOYSTICK = "\U0001f579\ufe0f" +SLOT_MACHINE = "\U0001f3b0" +GAME_DIE = "\U0001f3b2" +PUZZLE_PIECE = "\U0001f9e9" +TEDDY_BEAR = "\U0001f9f8" +PINATA = "\U0001fa85" +MIRROR_BALL = "\U0001faa9" +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" +LOW_BATTERY = "\U0001faab" +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" +WATER_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" +CRUTCH = "\U0001fa7c" +STETHOSCOPE = "\U0001fa7a" +X_RAY = "\U0001fa7b" +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" +BUBBLES = "\U0001fae7" +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" +IDENTIFICATION_CARD = "\U0001faaa" +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" +HEAVY_EQUALS_SIGN = "\U0001f7f0" +INFINITY = "\u267e\ufe0f" +DOUBLE_EXCLAMATION_MARK = "\u203c\ufe0f" +EXCLAMATION_QUESTION_MARK = "\u2049\ufe0f" +RED_QUESTION_MARK = "\u2753" +WHITE_QUESTION_MARK = "\u2754" +WHITE_EXCLAMATION_MARK = "\u2755" +RED_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_RIGHT_CURLY_BRACKET = "\U000e007d" +DIGIT_FIVE = "5\ufe0f" +TAG_LATIN_CAPITAL_LETTER_U = "\U000e0055" +TAG_LATIN_CAPITAL_LETTER_Q = "\U000e0051" +TAG_LATIN_CAPITAL_LETTER_K = "\U000e004b" +COMBINING_ENCLOSING_KEYCAP = "\u20e3" +TAG_LATIN_CAPITAL_LETTER_C = "\U000e0043" +TAG_ASTERISK = "\U000e002a" +TAG_FULL_STOP = "\U000e002e" +TAG_CIRCUMFLEX_ACCENT = "\U000e005e" +DIGIT_ONE = "1\ufe0f" +TAG_COMMA = "\U000e002c" +DIGIT_ZERO = "0\ufe0f" +TAG_EQUALS_SIGN = "\U000e003d" +TAG_LATIN_CAPITAL_LETTER_O = "\U000e004f" +TAG_COMMERCIAL_AT = "\U000e0040" +DIGIT_EIGHT = "8\ufe0f" +TAG_NUMBER_SIGN = "\U000e0023" +TAG_LATIN_CAPITAL_LETTER_T = "\U000e0054" +TAG_LATIN_CAPITAL_LETTER_N = "\U000e004e" +DIGIT_SIX = "6\ufe0f" +TAG_PERCENT_SIGN = "\U000e0025" +VARIATION_SELECTOR_16 = "\ufe0f" +TAG_LATIN_CAPITAL_LETTER_W = "\U000e0057" +TAG_DOLLAR_SIGN = "\U000e0024" +TAG_LOW_LINE = "\U000e005f" +TAG_DIGIT_EIGHT = "\U000e0038" +TAG_LATIN_CAPITAL_LETTER_M = "\U000e004d" +TAG_LATIN_CAPITAL_LETTER_A = "\U000e0041" +TAG_REVERSE_SOLIDUS = "\U000e005c" +TAG_SOLIDUS = "\U000e002f" +TAG_LATIN_CAPITAL_LETTER_H = "\U000e0048" +TAG_DIGIT_NINE = "\U000e0039" +TAG_LEFT_CURLY_BRACKET = "\U000e007b" +TAG_LATIN_CAPITAL_LETTER_E = "\U000e0045" +TAG_LATIN_SMALL_LETTER_W = "\U000e0077" +TAG_DIGIT_ZERO = "\U000e0030" +TAG_LATIN_CAPITAL_LETTER_B = "\U000e0042" +TAG_LATIN_CAPITAL_LETTER_F = "\U000e0046" +TAG_LATIN_CAPITAL_LETTER_Y = "\U000e0059" +TAG_TILDE = "\U000e007e" +TAG_LATIN_SMALL_LETTER_P = "\U000e0070" +TAG_LATIN_CAPITAL_LETTER_Z = "\U000e005a" +TAG_GREATER_THAN_SIGN = "\U000e003e" +TAG_LATIN_SMALL_LETTER_S = "\U000e0073" +TAG_LATIN_SMALL_LETTER_G = "\U000e0067" +TAG_APOSTROPHE = "\U000e0027" +TAG_RIGHT_PARENTHESIS = "\U000e0029" +TAG_DIGIT_THREE = "\U000e0033" +TAG_LEFT_PARENTHESIS = "\U000e0028" +TAG_DIGIT_SEVEN = "\U000e0037" +TAG_LATIN_SMALL_LETTER_O = "\U000e006f" +TAG_DIGIT_SIX = "\U000e0036" +TAG_DIGIT_TWO = "\U000e0032" +TAG_LATIN_SMALL_LETTER_F = "\U000e0066" +TAG_LATIN_SMALL_LETTER_K = "\U000e006b" +TAG_LATIN_SMALL_LETTER_Y = "\U000e0079" +TAG_SPACE = "\U000e0020" +TAG_LATIN_SMALL_LETTER_I = "\U000e0069" +DIGIT_TWO = "2\ufe0f" +TAG_DIGIT_ONE = "\U000e0031" +TAG_RIGHT_SQUARE_BRACKET = "\U000e005d" +TAG_LATIN_SMALL_LETTER_R = "\U000e0072" +HASH_SIGN = "#\ufe0f" +TAG_SEMICOLON = "\U000e003b" +TAG_LATIN_CAPITAL_LETTER_L = "\U000e004c" +TAG_HYPHEN_MINUS = "\U000e002d" +ASTERISK = "*\ufe0f" +TAG_LATIN_SMALL_LETTER_A = "\U000e0061" +TAG_EXCLAMATION_MARK = "\U000e0021" +TAG_LATIN_CAPITAL_LETTER_V = "\U000e0056" +TAG_LATIN_SMALL_LETTER_C = "\U000e0063" +TAG_GRAVE_ACCENT = "\U000e0060" +ZERO_WIDTH_JOINER = "\u200d" +TAG_LATIN_CAPITAL_LETTER_G = "\U000e0047" +DIGIT_NINE = "9\ufe0f" +TAG_VERTICAL_LINE = "\U000e007c" +TAG_LATIN_SMALL_LETTER_Z = "\U000e007a" +TAG_LATIN_CAPITAL_LETTER_X = "\U000e0058" +TAG_LATIN_SMALL_LETTER_J = "\U000e006a" +TAG_LATIN_CAPITAL_LETTER_P = "\U000e0050" +TAG_AMPERSAND = "\U000e0026" +TAG_LATIN_SMALL_LETTER_L = "\U000e006c" +TAG_LATIN_SMALL_LETTER_X = "\U000e0078" +DIGIT_SEVEN = "7\ufe0f" +TAG_LATIN_CAPITAL_LETTER_J = "\U000e004a" +TAG_LATIN_SMALL_LETTER_T = "\U000e0074" +TAG_QUESTION_MARK = "\U000e003f" +TAG_LATIN_SMALL_LETTER_B = "\U000e0062" +TAG_LEFT_SQUARE_BRACKET = "\U000e005b" +TAG_LATIN_SMALL_LETTER_D = "\U000e0064" +TAG_LATIN_SMALL_LETTER_E = "\U000e0065" +TAG_LATIN_SMALL_LETTER_M = "\U000e006d" +TAG_LESS_THAN_SIGN = "\U000e003c" +TAG_DIGIT_FIVE = "\U000e0035" +TAG_LATIN_CAPITAL_LETTER_D = "\U000e0044" +TAG_LATIN_SMALL_LETTER_N = "\U000e006e" +TAG_PLUS_SIGN = "\U000e002b" +TAG_COLON = "\U000e003a" +DIGIT_THREE = "3\ufe0f" +TAG_LATIN_SMALL_LETTER_Q = "\U000e0071" +TAG_LATIN_CAPITAL_LETTER_R = "\U000e0052" +TAG_LATIN_CAPITAL_LETTER_S = "\U000e0053" +DIGIT_FOUR = "4\ufe0f" +TAG_LATIN_CAPITAL_LETTER_I = "\U000e0049" +TAG_QUOTATION_MARK = "\U000e0022" +CANCEL_TAG = "\U000e007f" +TAG_LATIN_SMALL_LETTER_V = "\U000e0076" +TAG_LATIN_SMALL_LETTER_H = "\U000e0068" +TAG_LATIN_SMALL_LETTER_U = "\U000e0075" +TAG_DIGIT_FOUR = "\U000e0034" diff --git a/pyrogram/file_id.py b/pyrogram/file_id.py new file mode 100644 index 0000000000..1a54a49d61 --- /dev/null +++ b/pyrogram/file_id.py @@ -0,0 +1,481 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present 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 base64 +import logging +import struct +from enum import IntEnum +from io import BytesIO +from typing import List + +from pyrogram.raw.core import Bytes, String + +log = logging.getLogger(__name__) + + +def b64_encode(s: bytes) -> str: + """Encode bytes into a URL-safe Base64 string without padding + + Parameters: + s (``bytes``): + Bytes to encode + + Returns: + ``str``: The encoded bytes + """ + return base64.urlsafe_b64encode(s).decode().strip("=") + + +def b64_decode(s: str) -> bytes: + """Decode a URL-safe Base64 string without padding to bytes + + Parameters: + s (``str``): + String to decode + + Returns: + ``bytes``: The decoded string + """ + return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4)) + + +def rle_encode(s: bytes) -> bytes: + """Zero-value RLE encoder + + Parameters: + s (``bytes``): + Bytes to encode + + Returns: + ``bytes``: The encoded bytes + """ + r: List[int] = [] + n: int = 0 + + for b in s: + if not b: + n += 1 + else: + if n: + r.extend((0, n)) + n = 0 + + r.append(b) + + if n: + r.extend((0, n)) + + return bytes(r) + + +def rle_decode(s: bytes) -> bytes: + """Zero-value RLE decoder + + Parameters: + s (``bytes``): + Bytes to decode + + Returns: + ``bytes``: The decoded bytes + """ + r: List[int] = [] + z: bool = False + + for b in s: + if not b: + z = True + continue + + if z: + r.extend((0,) * b) + z = False + else: + r.append(b) + + return bytes(r) + + +class FileType(IntEnum): + """Known file types""" + THUMBNAIL = 0 + CHAT_PHOTO = 1 # ProfilePhoto + PHOTO = 2 + VOICE = 3 # VoiceNote + VIDEO = 4 + DOCUMENT = 5 + ENCRYPTED = 6 + TEMP = 7 + STICKER = 8 + AUDIO = 9 + ANIMATION = 10 + ENCRYPTED_THUMBNAIL = 11 + WALLPAPER = 12 + VIDEO_NOTE = 13 + SECURE_RAW = 14 + SECURE = 15 + BACKGROUND = 16 + DOCUMENT_AS_FILE = 17 + + +class ThumbnailSource(IntEnum): + """Known thumbnail sources""" + LEGACY = 0 + THUMBNAIL = 1 + CHAT_PHOTO_SMALL = 2 # DialogPhotoSmall + CHAT_PHOTO_BIG = 3 # DialogPhotoBig + STICKER_SET_THUMBNAIL = 4 + + +# Photo-like file ids are longer and contain extra info, the rest are all documents +PHOTO_TYPES = {FileType.THUMBNAIL, FileType.CHAT_PHOTO, FileType.PHOTO, FileType.WALLPAPER, + FileType.ENCRYPTED_THUMBNAIL} +DOCUMENT_TYPES = set(FileType) - PHOTO_TYPES + +# Since the file type values are small enough to fit them in few bits, Telegram thought it would be a good idea to +# encode extra information about web url and file reference existence as flag inside the 4 bytes allocated for the field +WEB_LOCATION_FLAG = 1 << 24 +FILE_REFERENCE_FLAG = 1 << 25 + + +class FileId: + MAJOR = 4 + MINOR = 30 + + def __init__( + self, *, + major: int = MAJOR, + minor: int = MINOR, + file_type: FileType, + dc_id: int, + file_reference: bytes = b"", + url: str = None, + media_id: int = None, + access_hash: int = None, + volume_id: int = None, + thumbnail_source: ThumbnailSource = None, + thumbnail_file_type: FileType = None, + thumbnail_size: str = "", + secret: int = None, + local_id: int = None, + chat_id: int = None, + chat_access_hash: int = None, + sticker_set_id: int = None, + sticker_set_access_hash: int = None + ): + self.major = major + self.minor = minor + self.file_type = file_type + self.dc_id = dc_id + self.file_reference = file_reference + self.url = url + self.media_id = media_id + self.access_hash = access_hash + self.volume_id = volume_id + self.thumbnail_source = thumbnail_source + self.thumbnail_file_type = thumbnail_file_type + self.thumbnail_size = thumbnail_size + self.secret = secret + self.local_id = local_id + self.chat_id = chat_id + self.chat_access_hash = chat_access_hash + self.sticker_set_id = sticker_set_id + self.sticker_set_access_hash = sticker_set_access_hash + + @staticmethod + def decode(file_id: str): + decoded = rle_decode(b64_decode(file_id)) + + # region read version + # File id versioning. Major versions lower than 4 don't have a minor version + major = decoded[-1] + + if major < 4: + minor = 0 + buffer = BytesIO(decoded[:-1]) + else: + minor = decoded[-2] + buffer = BytesIO(decoded[:-2]) + # endregion + + file_type, dc_id = struct.unpack("= 4: + buffer.write(struct.pack(" +# +# 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 import enums +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 + ) + + # short circuit + if not x: + return False + + 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 + ) + + # short circuit + if x: + return True + + 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 three positional arguments *(filter, client, 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 *client* argument refers to the :obj:`~pyrogram.Client` that received the update. + 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:`~pyrogram.filters.command` or :meth:`~pyrogram.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 or getattr(m, "outgoing", False)) + + +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_id) + + +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 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 bool(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 bool(m.poll) + + +poll = create(poll_filter) +"""Filter messages that contain :obj:`~pyrogram.types.Poll` objects.""" + + +# endregion + +# region dice_filter +async def dice_filter(_, __, m: Message): + return bool(m.dice) + + +dice = create(dice_filter) +"""Filter messages that contain :obj:`~pyrogram.types.Dice` objects.""" + + +# endregion + +# region media_spoiler +async def media_spoiler_filter(_, __, m: Message): + return bool(m.has_media_spoiler) + + +media_spoiler = create(media_spoiler_filter) +"""Filter media messages that contain a spoiler.""" + + +# endregion + +# region private_filter +async def private_filter(_, __, m: Message): + return bool(m.chat and m.chat.type in {enums.ChatType.PRIVATE, enums.ChatType.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 {enums.ChatType.GROUP, enums.ChatType.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 == enums.ChatType.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 video_chat_started_filter +async def video_chat_started_filter(_, __, m: Message): + return bool(m.video_chat_started) + + +video_chat_started = create(video_chat_started_filter) +"""Filter messages for started video chats""" + + +# endregion + +# region video_chat_ended_filter +async def video_chat_ended_filter(_, __, m: Message): + return bool(m.video_chat_ended) + + +video_chat_ended = create(video_chat_ended_filter) +"""Filter messages for ended video chats""" + + +# endregion + +# region video_chat_members_invited_filter +async def video_chat_members_invited_filter(_, __, m: Message): + return bool(m.video_chat_members_invited) + + +video_chat_members_invited = create(video_chat_members_invited_filter) +"""Filter messages for voice chat invited members""" + + +# 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*, +*video_chat_started*, *video_chat_ended*, *video_chat_members_invited*. +""" + + +# 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 + + +# region command_filter +def command(commands: Union[str, List[str]], prefixes: Union[str, 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: Union[int, str, List[Union[int, str]]] = 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: Union[int, str, List[Union[int, str]]] = 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))) diff --git a/pyrogram/mime_types.py b/pyrogram/mime_types.py new file mode 100644 index 0000000000..2f6c86aa8b --- /dev/null +++ b/pyrogram/mime_types.py @@ -0,0 +1,1881 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present 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 https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types. +# Extended with extra mime types specific to Telegram. +mime_types = """ +# This file maps Internet media types to unique file extension(s). +# Although created for httpd, this file is used by many software systems +# and has been placed in the public domain for unlimited redistribution. +# +# The table below contains both registered and (common) unregistered types. +# A type that has no unique extension can be ignored -- they are listed +# here to guide configurations toward known types and to make it easier to +# identify "new" types. File extensions are also commonly used to indicate +# content languages and encodings, so choose them carefully. +# +# Internet media types should be registered as described in RFC 4288. +# The registry is at . +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpdash-qoe-report+xml +# application/3gpp-ims+xml +# application/a2l +# application/activemessage +# application/alto-costmap+json +# application/alto-costmapfilter+json +# application/alto-directory+json +# application/alto-endpointcost+json +# application/alto-endpointcostparams+json +# application/alto-endpointprop+json +# application/alto-endpointpropparams+json +# application/alto-error+json +# application/alto-networkmap+json +# application/alto-networkmapfilter+json +# application/aml +application/andrew-inset ez +# application/applefile +application/applixware aw +# application/atf +# application/atfx +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomdeleted+xml +# application/atomicmail +application/atomsvc+xml atomsvc +# application/atxml +# application/auth-policy+xml +# application/bacnet-xdd+zip +# application/batch-smtp +# application/beep+xml +# application/calendar+json +# application/calendar+xml +# application/call-completion +# application/cals-1840 +# application/cbor +# application/ccmp+xml +application/ccxml+xml ccxml +# application/cdfx+xml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cdni +# application/cea +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +# application/cms +# application/cnrp+xml +# application/coap-group+json +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csrattrs +# application/csta+xml +# application/cstadata+xml +# application/csvm+json +application/cu-seeme cu +# application/cybercash +# application/dash+xml +# application/dashdelta +application/davmount+xml davmount +# application/dca-rft +# application/dcd +# application/dec-dx +# application/dialog-info+xml +# application/dicom +# application/dii +# application/dit +# application/dns +application/docbook+xml dbk +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +# application/efi +# application/emergencycalldata.comment+xml +# application/emergencycalldata.deviceinfo+xml +# application/emergencycalldata.providerinfo+xml +# application/emergencycalldata.serviceinfo+xml +# application/emergencycalldata.subscriberinfo+xml +application/emma+xml emma +# application/emotionml+xml +# application/encaprtp +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fdt+xml +# application/fits +application/font-tdpfr pfr +# application/framework-attributes+xml +# application/geo+json +application/gml+xml gml +application/gpx+xml gpx +application/gxf gxf +# application/gzip +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +application/inkml+xml ink inkml +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +# application/its+xml +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +# application/jose +# application/jose+json +# application/jrd+json +application/json json +# application/json-patch+json +# application/json-seq +application/jsonml+json jsonml +# application/jwk+json +# application/jwk-set+json +# application/jwt +# application/kpml-request+xml +# application/kpml-response+xml +# application/ld+json +# application/lgr+xml +# application/link-format +# application/load-control+xml +application/lost+xml lostxml +# application/lostsync+xml +# application/lxf +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica ma nb mb +application/mathml+xml mathml +# application/mathml-content+xml +# application/mathml-presentation+xml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-schedule+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media-policy-dataset+xml +# application/media_control+xml +application/mediaservercontrol+xml mscml +# application/merge-patch+json +application/metalink+xml metalink +application/metalink4+xml meta4 +application/mets+xml mets +# application/mf4 +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/mrb-consumer+xml +# application/mrb-publish+xml +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nlsml+xml +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy +application/oda oda +# application/odx +application/oebps-package+xml opf +application/ogg ogx +application/omdoc+xml omdoc +application/onenote onetoc onetoc2 onetmp onepkg +application/oxps oxps +# application/p2p-overlay+xml +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +# application/pdx +application/pgp-encrypted pgp +# application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +# application/pkcs12 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ai eps ps +# application/ppsp-tracker+json +# application/problem+json +# application/problem+xml +# application/provenance+xml +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.hpub+zip +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +# application/raptorfec +# application/rdap+json +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +# application/reputon+json +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/rfc+xml +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rpki-ghostbusters gbr +application/rpki-manifest mft +application/rpki-roa roa +# application/rpki-updown +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtploopback +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +# application/scaip+xml +# application/scim+json +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/sep+xml +# application/sep-exi +# application/session-info +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil+xml smi smil +# application/smpte336m +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +# application/sql +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssdl+xml ssdl +application/ssml+xml ssml +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/ttml+xml +# application/tve-trigger +# application/ulpfec +# application/urc-grpsheet+xml +# application/urc-ressheet+xml +# application/urc-targetdesc+xml +# application/urc-uisocketdesc+xml +# application/vcard+json +# application/vcard+xml +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp-prose+xml +# application/vnd.3gpp-prose-pc3ch+xml +# application/vnd.3gpp.access-transfer-events+xml +# application/vnd.3gpp.bsf+xml +# application/vnd.3gpp.mid-call+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp.sms+xml +# application/vnd.3gpp.srvcc-ext+xml +# application/vnd.3gpp.srvcc-info+xml +# application/vnd.3gpp.state-and-event-info+xml +# application/vnd.3gpp.ussd+xml +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +# application/vnd.3lightssoftware.imagescal +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +# application/vnd.adobe.flash.movie +application/vnd.adobe.formscentral.fcdt fcdt +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +# application/vnd.amazon.mobi8-ebook +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +# application/vnd.anki +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +# application/vnd.apache.thrift.binary +# application/vnd.apache.thrift.compact +# application/vnd.apache.thrift.json +# application/vnd.api+json +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +# application/vnd.artsquare +application/vnd.astraea-software.iota iota +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +# application/vnd.balsamiq.bmml+xml +# application/vnd.balsamiq.bmpr +# application/vnd.bekitzur-stech+json +# application/vnd.biopax.rdf+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +# application/vnd.bluetooth.le.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +# application/vnd.century-systems.tcp_stream +application/vnd.chemdraw+xml cdxml +# application/vnd.chess-pgn +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +# application/vnd.citationstyles.style+xml +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.coffeescript +# application/vnd.collection+json +# application/vnd.collection.doc+json +# application/vnd.collection.next+json +# application/vnd.comicbook+zip +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +# application/vnd.coreos.ignition+json +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +# application/vnd.curl +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cyan.dean.root+xml +# application/vnd.cybank +application/vnd.dart dart +application/vnd.data-vision.rdz rdz +# application/vnd.debian.binary-package +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.dece.zip uvz uvvz +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.desmume.movie +# application/vnd.dir-bi.plate-dl-nosuffix +# application/vnd.dm.delegation+xml +application/vnd.dna dna +# application/vnd.document+json +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +# application/vnd.doremir.scorecloud-binary-document +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +# application/vnd.drive+json +application/vnd.ds-keypoint kpxx +# application/vnd.dtg.local +# application/vnd.dtg.local.flash +# application/vnd.dtg.local.html +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.dzr +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +# application/vnd.enphase.envoy +# application/vnd.eprints.data+xml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.asic-e+zip +# application/vnd.etsi.asic-s+zip +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.mheg5 +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.pstn+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.timestamp-token +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +# application/vnd.fastcopy-disk-image +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.filmit.zfc +# application/vnd.fints +# application/vnd.firemonkeys.cloudcell +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fujixerox.docuworks.container +# application/vnd.fujixerox.hbpl +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geo+json +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.gerber +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +# application/vnd.gov.sk.e-form+xml +# application/vnd.gov.sk.e-form+zip +# application/vnd.gov.sk.xmldatacontainer+xml +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +# application/vnd.hal+json +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +# application/vnd.hdt +# application/vnd.heroku+json +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +# application/vnd.hyperdrive+json +# application/vnd.hzn-3d-crossword +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +# application/vnd.ieee.1905 +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.ims.imsccv1p1 +# application/vnd.ims.imsccv1p2 +# application/vnd.ims.imsccv1p3 +# application/vnd.ims.lis.v2.result+json +# application/vnd.ims.lti.v2.toolconsumerprofile+json +# application/vnd.ims.lti.v2.toolproxy+json +# application/vnd.ims.lti.v2.toolproxy.id+json +# application/vnd.ims.lti.v2.toolsettings+json +# application/vnd.ims.lti.v2.toolsettings.simple+json +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +# application/vnd.innopath.wamp.notification +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.catalogitem+xml +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.newsmessage+xml +# application/vnd.iptc.g2.packageitem+xml +# application/vnd.iptc.g2.planningitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +# application/vnd.jsk.isdn-ngn +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.mapbox-vector-tile +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +# application/vnd.mason+json +# application/vnd.maxmind.maxmind-db +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +# application/vnd.micro+json +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +# application/vnd.microsoft.portable-executable +# application/vnd.miele+json +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +# application/vnd.ms-3mfdocument +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +# application/vnd.ms-color.iccprofile +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +# application/vnd.ms-opentype +# application/vnd.ms-package.obfuscated-opentype +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +# application/vnd.ms-printdevicecapabilities+xml +# application/vnd.ms-printing.printticket+xml +# application/vnd.ms-printschematicket+xml +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-windows.devicepairing +# application/vnd.ms-windows.nwprinting.oob +# application/vnd.ms-windows.printerpairing +# application/vnd.ms-windows.wsd.oob +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +# application/vnd.msa-disk-image +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +application/vnd.mynfc taglet +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +# application/vnd.nintendo.nitro.rom +# application/vnd.nintendo.snes.rom +application/vnd.nitf ntf nitf +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.content-share +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.ogw_remote-access +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oftn.l10n+json +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-feature-handler+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.cab-subs-invite+xml +# application/vnd.oma.cab-user-prefs+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.lwm2m+json +# application/vnd.oma.lwm2m+tlv +# application/vnd.oma.pal+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +# application/vnd.onepager +# application/vnd.openblox.game+xml +# application/vnd.openblox.game-binary +# application/vnd.openeye.oeb +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.oracle.resource+json +# application/vnd.orange.indata +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +application/vnd.osgi.subsystem esa +# application/vnd.otps.ct-kip+xml +# application/vnd.oxli.countgraph +# application/vnd.pagerduty+json +application/vnd.palm pdb pqa oprc +# application/vnd.panoply +# application/vnd.paos.xml +application/vnd.pawaafile paw +# application/vnd.pcos +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +# application/vnd.quarantainenet +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.quobject-quoxdocument +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +# application/vnd.rar +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.rn-realmedia-vbr rmvb +application/vnd.route66.link66+xml link66 +# application/vnd.rs-274x +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +# application/vnd.siren+json +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.package smzip +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +# application/vnd.sun.wadl+xml +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.dmddf+wbxml +# application/vnd.syncml.dmddf+xml +# application/vnd.syncml.dmtnds+wbxml +# application/vnd.syncml.dmtnds+xml +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tcpdump.pcap pcap cap dmp +# application/vnd.tmd.mediaflex.api+xml +# application/vnd.tml +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +# application/vnd.uri-map +# application/vnd.valve.source.material +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.vel+json +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.p2p +# application/vnd.wfa.wsc +# application/vnd.windows.devicepairing +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +# application/vnd.xacml+json +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.through-ngn +# application/vnd.yamaha.tunnel-udpencap +# application/vnd.yaoweme +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw +application/x-ace-compressed ace +# application/x-amf +application/x-apple-diskimage dmg +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-blorb blb blorb +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cbr cbr cba cbt cbz cb7 +application/x-cdlink vcd +application/x-cfs-compressed cfs +application/x-chat chat +application/x-chess-pgn pgn +# application/x-compress +application/x-conference nsc +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-dgc-compressed dgc +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-envoy evy +application/x-eva eva +application/x-font-bdf bdf +# application/x-font-dos +# application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-pcf pcf +application/x-font-snf snf +# application/x-font-speedo +# application/x-font-sunos-news +application/x-font-type1 pfa pfb pfm afm +# application/x-font-vfont +application/x-freearc arc +application/x-futuresplash spl +application/x-gca-compressed gca +application/x-glulx ulx +application/x-gnumeric gnumeric +application/x-gramps-xml gramps +application/x-gtar gtar +# application/x-gzip +application/x-hdf hdf +application/x-install-instructions install +application/x-iso9660-image iso +application/x-java-jnlp-file jnlp +application/x-latex latex +application/x-lzh-compressed lzh lha +application/x-mie mie +application/x-mobipocket-ebook prc mobi +application/x-ms-application application +application/x-ms-shortcut lnk +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf wmz emf emz +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-nzb nzb +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-research-info-systems ris +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-silverlight-app xap +application/x-sql sql +application/x-stuffit sit +application/x-stuffitx sitx +application/x-subrip srt +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-t3vm-image t3 +application/x-tads gam +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-tgif obj +application/x-ustar ustar +application/x-wais-source src +# application/x-www-form-urlencoded +application/x-x509-ca-cert der crt +application/x-xfig fig +application/x-xliff+xml xlf +application/x-xpinstall xpi +application/x-xz xz +application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8 +# application/x400-bp +# application/xacml+xml +application/xaml+xml xaml +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info+xml +# application/xcon-conference-info-diff+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xml-patch+xml +# application/xmpp+xml +application/xop+xml xop +application/xproc+xml xpl +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# application/zlib +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/aptx +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dv +# audio/dvi4 +# audio/eac3 +# audio/encaprtp +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcnw +# audio/evrcnw0 +# audio/evrcnw1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/evs +# audio/example +# audio/fwdred +# audio/g711-0 +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/ip-mr_v2.5 +# audio/isac +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 m4a mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mp3 mpga mp2 mp2a m2a m3a +# audio/mpeg4-generic +# audio/musepack +audio/ogg ogg oga spx +# audio/opus +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu +# audio/pcmu-wb +# audio/prs.sid +# audio/qcelp +# audio/raptorfec +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtploopback +# audio/rtx +audio/s3m s3m +audio/silk sil +# audio/smv +# audio/smv-qcp +# audio/smv0 +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.dvb.file +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-aiff aif aiff aifc +audio/x-caf caf +audio/x-flac flac +audio/x-matroska mka +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +# audio/x-tta +audio/x-wav wav +audio/xm xm +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +font/collection ttc +font/otf otf +# font/sfnt +font/ttf ttf +font/woff woff +font/woff2 woff2 +image/bmp bmp +image/cgm cgm +# image/dicom-rle +# image/emf +# image/example +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jls +# image/jp2 +image/jpeg jpg jpeg jpe +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +# image/pwg-raster +image/sgi sgi +image/svg+xml svg svgz +# image/t38 +image/tiff tiff tif +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.airzip.accelerator.azv +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.djvu djvu djv +image/vnd.dvb.subtitle sub +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +# image/vnd.mozilla.apng +image/vnd.ms-modi mdi +image/vnd.ms-photo wdp +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +# image/vnd.tencent.tap +# image/vnd.valve.source.texture +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +# image/vnd.zbrush.pcx +image/webp webp +# image/wmf +image/x-3ds 3ds +image/x-cmu-raster ras +image/x-cmx cmx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icon ico +image/x-mrsid-image sid +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-tga tga +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +# message/cpim +# message/delivery-status +# message/disposition-notification +# message/example +# message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +# message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +# message/vnd.wfa.wsc +# model/example +# model/gltf+json +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.opengex +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +# model/vnd.rosette.annotated-data-model +# model/vnd.valve.source.compiled-map +model/vnd.vtu vtu +model/vrml wrl vrml +model/x3d+binary x3db x3dbz +# model/x3d+fastinfoset +model/x3d+vrml x3dv x3dvz +model/x3d+xml x3d x3dz +# model/x3d-vrml +# multipart/alternative +# multipart/appledouble +# multipart/byteranges +# multipart/digest +# multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +# multipart/parallel +# multipart/related +# multipart/report +# multipart/signed +# multipart/voice-message +# multipart/x-mixed-replace +# text/1d-interleaved-parityfec +text/cache-manifest appcache +text/calendar ics ifb +text/css css +text/csv csv +# text/csv-schema +# text/directory +# text/dns +# text/ecmascript +# text/encaprtp +# text/enriched +# text/example +# text/fwdred +# text/grammar-ref-list +text/html html htm +# text/javascript +# text/jcr-cnd +# text/markdown +# text/mizar +text/n3 n3 +# text/parameters +# text/parityfec +text/plain txt text conf def list log in +# text/provenance-notation +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +# text/prs.prop.logic +# text/raptorfec +# text/red +# text/rfc822-headers +text/richtext rtx +# text/rtf +# text/rtp-enc-aescm128 +# text/rtploopback +# text/rtx +text/sgml sgml sgm +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +text/vcard vcard +# text/vnd.a +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.mcurl mcurl +text/vnd.curl.scurl scurl +# text/vnd.debian.copyright +# text/vnd.dmclientscript +text/vnd.dvb.subtitle sub +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.radisys.msml-basic-layout +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-java-source java +text/x-nfo nfo +text/x-opml opml +text/x-pascal p pas +text/x-setext etx +text/x-sfv sfv +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +# text/xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +# video/encaprtp +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +# video/h265 +# video/iso.segment +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov +# video/raptorfec +# video/raw +# video/rtp-enc-aescm128 +# video/rtploopback +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.dvb.file dvb +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +# video/vnd.radgamettools.bink +# video/vnd.radgamettools.smacker +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +# video/vp8 +video/webm webm +video/x-f4v f4v +video/x-fli fli +video/x-flv flv +video/x-m4v m4v +video/x-matroska mkv mk3d mks +video/x-mng mng +video/x-ms-asf asf asx +video/x-ms-vob vob +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +video/x-smv smv +x-conference/x-cooltalk ice + +# Telegram animated stickers +application/x-bad-tgsticker tgs +application/x-tgsticker tgs +""" diff --git a/pyrogram/py.typed b/pyrogram/py.typed new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pyrogram/sync.py b/pyrogram/sync.py new file mode 100644 index 0000000000..94c82a3dd6 --- /dev/null +++ b/pyrogram/sync.py @@ -0,0 +1,113 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present 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, compose as compose_module + + +def async_to_sync(obj, name): + function = getattr(obj, name) + main_loop = asyncio.get_event_loop() + + def async_to_sync_gen(agen, loop, is_main_thread): + async def anext(agen): + try: + return await agen.__anext__(), False + except StopAsyncIteration: + return None, True + + while True: + if is_main_thread: + item, done = loop.run_until_complete(anext(agen)) + else: + item, done = asyncio.run_coroutine_threadsafe(anext(agen), loop).result() + + if done: + break + + yield item + + @functools.wraps(function) + def async_to_sync_wrap(*args, **kwargs): + coroutine = function(*args, **kwargs) + + try: + loop = asyncio.get_event_loop() + except RuntimeError: + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + + if threading.current_thread() is threading.main_thread() or not main_loop.is_running(): + if loop.is_running(): + return coroutine + else: + if inspect.iscoroutine(coroutine): + return loop.run_until_complete(coroutine) + + if inspect.isasyncgen(coroutine): + return async_to_sync_gen(coroutine, loop, True) + else: + if inspect.iscoroutine(coroutine): + if loop.is_running(): + async def coro_wrapper(): + return await asyncio.wrap_future(asyncio.run_coroutine_threadsafe(coroutine, main_loop)) + + return coro_wrapper() + else: + return asyncio.run_coroutine_threadsafe(coroutine, main_loop).result() + + if inspect.isasyncgen(coroutine): + if loop.is_running(): + return coroutine + else: + return async_to_sync_gen(coroutine, main_loop, False) + + 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 and compose, because they are not inside Methods +async_to_sync(idle_module, "idle") +idle = getattr(idle_module, "idle") + +async_to_sync(compose_module, "compose") +compose = getattr(compose_module, "compose") diff --git a/pyrogram/utils.py b/pyrogram/utils.py new file mode 100644 index 0000000000..f7fe59706d --- /dev/null +++ b/pyrogram/utils.py @@ -0,0 +1,371 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present 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 base64 +import functools +import hashlib +import os +import struct +from concurrent.futures.thread import ThreadPoolExecutor +from datetime import datetime, timezone +from getpass import getpass +from typing import Union, List, Dict, Optional + +import pyrogram +from pyrogram import raw, enums +from pyrogram import types +from pyrogram.file_id import FileId, FileType, PHOTO_TYPES, DOCUMENT_TYPES + + +async def ainput(prompt: str = "", *, hide: bool = False): + """Just like the built-in input, but async""" + with ThreadPoolExecutor(1) as executor: + func = functools.partial(getpass if hide else input, prompt) + return await asyncio.get_event_loop().run_in_executor(executor, func) + + +def get_input_media_from_file_id( + file_id: str, + expected_file_type: FileType = None, + ttl_seconds: int = None +) -> Union["raw.types.InputMediaPhoto", "raw.types.InputMediaDocument"]: + try: + decoded = FileId.decode(file_id) + except Exception: + raise ValueError( + f'Failed to decode "{file_id}". The value does not represent an existing local file, ' + f"HTTP URL, or valid file id." + ) + + file_type = decoded.file_type + + if expected_file_type is not None and file_type != expected_file_type: + raise ValueError(f"Expected {expected_file_type.name}, got {file_type.name} file id instead") + + if file_type in (FileType.THUMBNAIL, FileType.CHAT_PHOTO): + raise ValueError(f"This file id can only be used for download: {file_id}") + + if file_type in PHOTO_TYPES: + return raw.types.InputMediaPhoto( + id=raw.types.InputPhoto( + id=decoded.media_id, + access_hash=decoded.access_hash, + file_reference=decoded.file_reference + ), + ttl_seconds=ttl_seconds + ) + + if file_type in DOCUMENT_TYPES: + return raw.types.InputMediaDocument( + id=raw.types.InputDocument( + id=decoded.media_id, + access_hash=decoded.access_hash, + file_reference=decoded.file_reference + ), + ttl_seconds=ttl_seconds + ) + + raise ValueError(f"Unknown file id: {file_id}") + + +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 types.List() + + parsed_messages = [] + + for message in messages.messages: + parsed_messages.append(await types.Message._parse(client, message, users, chats, replies=0)) + + if replies: + messages_with_replies = { + i.id: i.reply_to.reply_to_msg_id + for i in messages.messages + if not isinstance(i, raw.types.MessageEmpty) and i.reply_to + } + + if messages_with_replies: + # 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( + chat_id, + reply_to_message_ids=messages_with_replies.keys(), + replies=replies - 1 + ) + + for message in parsed_messages: + reply_id = messages_with_replies.get(message.id, None) + + for reply in reply_messages: + if reply.id == reply_id: + message.reply_to_message = reply + + return types.List(parsed_messages) + + +def parse_deleted_messages(client, update) -> List["types.Message"]: + messages = update.messages + channel_id = getattr(update, "channel_id", None) + + parsed_messages = [] + + for message in messages: + parsed_messages.append( + types.Message( + id=message, + chat=types.Chat( + id=get_channel_id(channel_id), + type=enums.ChatType.CHANNEL, + client=client + ) if channel_id is not None else None, + client=client + ) + ) + + return types.List(parsed_messages) + + +def pack_inline_message_id(msg_id: "raw.base.InputBotInlineMessageID"): + if isinstance(msg_id, raw.types.InputBotInlineMessageID): + inline_message_id_packed = struct.pack( + " Optional[int]: + """Get the raw peer id from a Peer object""" + if isinstance(peer, raw.types.PeerUser): + return peer.user_id + + if isinstance(peer, raw.types.PeerChat): + return peer.chat_id + + if isinstance(peer, raw.types.PeerChannel): + return peer.channel_id + + return None + + +def get_peer_id(peer: raw.base.Peer) -> int: + """Get the non-raw peer id from a Peer object""" + if isinstance(peer, raw.types.PeerUser): + return peer.user_id + + if isinstance(peer, raw.types.PeerChat): + return -peer.chat_id + + if isinstance(peer, raw.types.PeerChannel): + return MAX_CHANNEL_ID - peer.channel_id + + raise ValueError(f"Peer type invalid: {peer}") + + +def get_peer_type(peer_id: int) -> str: + if peer_id < 0: + if MIN_CHAT_ID <= peer_id: + return "chat" + + if MIN_CHANNEL_ID <= peer_id < MAX_CHANNEL_ID: + return "channel" + elif 0 < peer_id <= MAX_USER_ID: + return "user" + + 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) + + +async def parse_text_entities( + client: "pyrogram.Client", + text: str, + parse_mode: enums.ParseMode, + entities: List["types.MessageEntity"] +) -> Dict[str, Union[str, List[raw.base.MessageEntity]]]: + if entities: + # Inject the client instance because parsing user mentions requires it + for entity in entities: + entity._client = client + + text, entities = text, [await entity.write() for entity in entities] or None + else: + text, entities = (await client.parser.parse(text, parse_mode)).values() + + return { + "message": text, + "entities": entities + } + + +def zero_datetime() -> datetime: + return datetime.fromtimestamp(0, timezone.utc) + + +def timestamp_to_datetime(ts: Optional[int]) -> Optional[datetime]: + return datetime.fromtimestamp(ts) if ts else None + + +def datetime_to_timestamp(dt: Optional[datetime]) -> Optional[int]: + return int(dt.timestamp()) if dt else None From 5968117debca5bf3b8ff9a9c53e73387180f9b2d Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:31:11 +0545 Subject: [PATCH 025/103] =?UTF-8?q?Updated=20To=20Pyrogram=202.1.1=20?= =?UTF-8?q?=E2=9C=93=E2=9C=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyrogram/connection/connection.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyrogram/connection/connection.py b/pyrogram/connection/connection.py index 1107673f1a..69cbb813a1 100644 --- a/pyrogram/connection/connection.py +++ b/pyrogram/connection/connection.py @@ -20,7 +20,7 @@ import logging from typing import Optional -from .transport import TCP, TCPAbridged +from .transport import TCP, TCPAbridgedO from ..session.internals import DataCenter log = logging.getLogger(__name__) @@ -41,7 +41,7 @@ def __init__(self, dc_id: int, test_mode: bool, ipv6: bool, proxy: dict, media: async def connect(self): for i in range(Connection.MAX_CONNECTION_ATTEMPTS): - self.protocol = TCPAbridged(self.ipv6, self.proxy) + self.protocol = TCPAbridgedO(self.ipv6, self.proxy) try: log.info("Connecting...") From 64dc0734477f3813dc02ea5414667dd87af81a27 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:32:14 +0545 Subject: [PATCH 026/103] Add files via upload --- pyrogram/connection/transport/tcp/tcp.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyrogram/connection/transport/tcp/tcp.py b/pyrogram/connection/transport/tcp/tcp.py index 82ef033be4..08a435cee9 100644 --- a/pyrogram/connection/transport/tcp/tcp.py +++ b/pyrogram/connection/transport/tcp/tcp.py @@ -91,7 +91,7 @@ async def close(self): self.writer.close() await asyncio.wait_for(self.writer.wait_closed(), TCP.TIMEOUT) except Exception as e: - log.info("Close exception: %s %s", type(e).__name__, e) + log.warning("Close exception: %s %s", type(e).__name__, e) async def send(self, data: bytes): async with self.lock: @@ -100,7 +100,7 @@ async def send(self, data: bytes): self.writer.write(data) await self.writer.drain() except Exception as e: - log.info("Send exception: %s %s", type(e).__name__, e) + log.warning("Send exception: %s %s", type(e).__name__, e) raise OSError(e) async def recv(self, length: int = 0): From eb5166eefd1c38191f0be6ad6e200af62319d32c Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:33:17 +0545 Subject: [PATCH 027/103] =?UTF-8?q?Updated=20To=20Pyrogram=202.1.1=20?= =?UTF-8?q?=E2=9C=93=E2=9C=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyrogram/crypto/rsa.py | 80 +++++++++--------------------------------- 1 file changed, 16 insertions(+), 64 deletions(-) diff --git a/pyrogram/crypto/rsa.py b/pyrogram/crypto/rsa.py index 25c2322957..3fd7d67ba3 100644 --- a/pyrogram/crypto/rsa.py +++ b/pyrogram/crypto/rsa.py @@ -153,25 +153,25 @@ int("010001", 16) # Exponent ), - # -7395192255793472640 - 0x995effd323b5db80 - (1 << 64): PublicKey( # CDN DC-121 + # 6427105915145367799 + 0x15931aac70e0d30f7 - (1 << 64): PublicKey( # CDN DC-121 # -----BEGIN RSA PUBLIC KEY----- - # MIIBCgKCAQEA4tWHcGJlElkxuxKQJwFjJaulmVHgdxNA3wgI2E8XbNnA88y51Xog - # V5m8BEYuTSP4llXZY4ZSJW5VlFXnmsJT/hmjyeFqqTajyAW6nb9vwZX291QvqD/1 - # ZCFBy7TLvCM0lbNIEhcLMf33ZV8AetLAd+uRLF6QHosys5w0iJ7x+UbGwDxyfeic - # 8EJJnsKaXrUOwRycMRN+V/zDySa0EYl1u1EB1MDX1/jIV1IQEbLvdBH4vsVTVEdW - # KHlzOcFzT9qX/g8XibCPiHLJvqQb8hVibvs9NaANyClcBEt3mOucG1/46Lilkc/K - # d4nlCcohk0jIHNp8symUzNWRPUGmTs3SPwIDAQAB + # MIIBCgKCAQEA+Lf3PvgE1yxbJUCMaEAkV0QySTVpnaDjiednB5RbtNWjCeqSVakY + # HbqqGMIIv5WCGdFdrqOfMNcNSstPtSU6R9UmRw6tquOIykpSuUOje9H+4XVIKquj + # yL2ISdK+4ZOMl4hCMkqauw4bP1Sbr03vZRQbU6qEA04V4j879BAyBVhr3WG9+Zi+ + # t5XfGSTgSExPYEl8rZNHYNV5RB+BuroVH2HLTOpT/mJVfikYpgjfWF5ldezV4Wo9 + # LSH0cZGSFIaeJl8d0A8Eiy5B9gtBO8mL+XfQRKOOmr7a4BM4Ro2de5rr2i2od7hY + # Xd3DO9FRSl4y1zA8Am48Rfd95WHF3N/OmQIDAQAB # -----END RSA PUBLIC KEY----- int( - "E2D587706265125931BB129027016325ABA59951E0771340DF0808D84F176CD9" - "C0F3CCB9D57A205799BC04462E4D23F89655D9638652256E559455E79AC253FE" - "19A3C9E16AA936A3C805BA9DBF6FC195F6F7542FA83FF5642141CBB4CBBC2334" - "95B34812170B31FDF7655F007AD2C077EB912C5E901E8B32B39C34889EF1F946" - "C6C03C727DE89CF042499EC29A5EB50EC11C9C31137E57FCC3C926B4118975BB" - "5101D4C0D7D7F8C857521011B2EF7411F8BEC55354475628797339C1734FDA97" - "FE0F1789B08F8872C9BEA41BF215626EFB3D35A00DC8295C044B7798EB9C1B5F" - "F8E8B8A591CFCA7789E509CA219348C81CDA7CB32994CCD5913D41A64ECDD23F", + "F8B7F73EF804D72C5B25408C6840245744324935699DA0E389E76707945BB4D5" + "A309EA9255A9181DBAAA18C208BF958219D15DAEA39F30D70D4ACB4FB5253A47" + "D526470EADAAE388CA4A52B943A37BD1FEE175482AABA3C8BD8849D2BEE1938C" + "978842324A9ABB0E1B3F549BAF4DEF65141B53AA84034E15E23F3BF410320558" + "6BDD61BDF998BEB795DF1924E0484C4F60497CAD934760D579441F81BABA151F" + "61CB4CEA53FE62557E2918A608DF585E6575ECD5E16A3D2D21F471919214869E" + "265F1DD00F048B2E41F60B413BC98BF977D044A38E9ABEDAE01338468D9D7B9A" + "EBDA2DA877B8585DDDC33BD1514A5E32D7303C026E3C45F77DE561C5DCDFCE99", 16 ), # Modulus int("010001", 16) # Exponent @@ -199,54 +199,6 @@ 16 ), # Modulus int("010001", 16) # Exponent - ), - - # -3997872768018684475 - 0xc884b3e62d09e5c5 - (1 << 64): PublicKey( # CDN DC-201 - # -----BEGIN RSA PUBLIC KEY----- - # MIIBCgKCAQEAug6fETVb7NkXYYu5ueZuM0pqw1heuqUrZNYomQN0lS0o7i6mAWwb - # 1/FiscFK+y4LQSSEx+oUzXAhjmll9fmb4e7PbUiXo8MuXO0Rj3e5416DXfTiOYGW - # XlFRV0aQzu8agy1epKwkFDidnmy7g5rJJV0q1+3eR+Jk2OEc/B6lMAOv3fBU6xhE - # ZByN9gqc6fvkNo13PQ8JYZUSGttzLlYy76uFmvFBhRsJU+LNQ2+bsTHwafSffVYl - # Z2boJOblvqbRWe453CzssaSWywGXOQmWvVbEe7F8q1ki/s7S8BxYWrhSLJ6bsu9V - # ZWnIHD9vB34QF8IABPRE93mhCOHBqJxSBQIDAQAB - # -----END RSA PUBLIC KEY----- - int( - "BA0E9F11355BECD917618BB9B9E66E334A6AC3585EBAA52B64D628990374952D" - "28EE2EA6016C1BD7F162B1C14AFB2E0B412484C7EA14CD70218E6965F5F99BE1" - "EECF6D4897A3C32E5CED118F77B9E35E835DF4E23981965E5151574690CEEF1A" - "832D5EA4AC2414389D9E6CBB839AC9255D2AD7EDDE47E264D8E11CFC1EA53003" - "AFDDF054EB1844641C8DF60A9CE9FBE4368D773D0F096195121ADB732E5632EF" - "AB859AF141851B0953E2CD436F9BB131F069F49F7D56256766E824E6E5BEA6D1" - "59EE39DC2CECB1A496CB0197390996BD56C47BB17CAB5922FECED2F01C585AB8" - "522C9E9BB2EF556569C81C3F6F077E1017C20004F444F779A108E1C1A89C5205", - 16 - ), # Modulus - int("010001", 16) # Exponent - ), - - # -4960899639492471258 - 0xbb27580fd5b01626 - (1 << 64): PublicKey( # CDN DC-203 - # -----BEGIN RSA PUBLIC KEY----- - # MIIBCgKCAQEAv/L6td+mj7Dl81NHfu+Xf1KNtvZPR1tS5xFqkiUson1u7D2ulK05 - # jM8HKvpV1o+1HPPqhaXhasvsX90u3TIHRQ0zuJKJxKAiZo3GK7phHozjAJ9VUFbO - # 7jKAa5BTE9tXgA5ZwJAiQWb3U6ykwRzk3fFRe5WaW7xfVUiepxyWGdr1eecoWCfB - # af1TCXfcS7vcyljNT03pwt2YyS5iXE5IB5wBB5yqSSm4GYtWWR67UjIsXBd77TRp - # foLGpfOdUHxBz4ZSj8D76m1zlpID5J2pF6bH4+ZCz0SUpv3j7bE8WFlvgMfwEPhw - # xMYidRGayq9YlLlYd4D+Yoq0U6jS3MWTRQIDAQAB - # -----END RSA PUBLIC KEY----- - int( - "BFF2FAB5DFA68FB0E5F353477EEF977F528DB6F64F475B52E7116A92252CA27D" - "6EEC3DAE94AD398CCF072AFA55D68FB51CF3EA85A5E16ACBEC5FDD2EDD320745" - "0D33B89289C4A022668DC62BBA611E8CE3009F555056CEEE32806B905313DB57" - "800E59C090224166F753ACA4C11CE4DDF1517B959A5BBC5F55489EA71C9619DA" - "F579E7285827C169FD530977DC4BBBDCCA58CD4F4DE9C2DD98C92E625C4E4807" - "9C01079CAA4929B8198B56591EBB52322C5C177BED34697E82C6A5F39D507C41" - "CF86528FC0FBEA6D73969203E49DA917A6C7E3E642CF4494A6FDE3EDB13C5859" - "6F80C7F010F870C4C62275119ACAAF5894B9587780FE628AB453A8D2DCC59345", - 16 - ), # Modulus - int("010001", 16) # Exponent ) } From e7da16c3d8583dc7d5877328e41094b67c3c4b4d Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:35:25 +0545 Subject: [PATCH 028/103] =?UTF-8?q?Updated=20To=20Pyrogram=202.1.1=20?= =?UTF-8?q?=E2=9C=93=E2=9C=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From 64a992f0ac09f878f2f04f2c039ccd0ed2f612fd Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:37:58 +0545 Subject: [PATCH 029/103] Add files via upload --- pyrogram/methods/advanced/save_file.py | 227 ++++++++++++------------- 1 file changed, 113 insertions(+), 114 deletions(-) diff --git a/pyrogram/methods/advanced/save_file.py b/pyrogram/methods/advanced/save_file.py index 453a62af17..5ecac6d80e 100644 --- a/pyrogram/methods/advanced/save_file.py +++ b/pyrogram/methods/advanced/save_file.py @@ -94,133 +94,132 @@ async def save_file( Raises: RPCError: In case of a Telegram RPC error. """ - async with self.save_file_semaphore: - if path is None: - return None + if path is None: + return None - async def worker(session): - while True: - data = await queue.get() + async def worker(session): + while True: + data = await queue.get() - if data is None: - return + if data is None: + return - try: - await session.invoke(data) - except Exception as e: - log.exception(e) + try: + await session.invoke(data) + except Exception as e: + log.exception(e) - part_size = 512 * 1024 + 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 = getattr(fp, "name", "file.jpg") - - 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") - - file_size_limit_mib = 4000 if self.me.is_premium else 2000 - - if file_size > file_size_limit_mib * 1024 * 1024: - raise ValueError(f"Can't upload files bigger than {file_size_limit_mib} MiB") - - file_total_parts = int(math.ceil(file_size / part_size)) - is_big = file_size > 10 * 1024 * 1024 - 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 - session = Session( - self, await self.storage.dc_id(), await self.storage.auth_key(), - await self.storage.test_mode(), is_media=True - ) - workers = [self.loop.create_task(worker(session)) for _ in range(workers_count)] - queue = asyncio.Queue(1) - - try: - await session.start() - - fp.seek(part_size * file_part) - - while True: - chunk = fp.read(part_size) - - if not chunk: - if not is_big and not is_missing_part: - 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 - ) + 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 = getattr(fp, "name", "file.jpg") + + 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") - await queue.put(rpc) + file_size_limit_mib = 4000 if self.me.is_premium else 2000 - if is_missing_part: - return + if file_size > file_size_limit_mib * 1024 * 1024: + raise ValueError(f"Can't upload files bigger than {file_size_limit_mib} MiB") + file_total_parts = int(math.ceil(file_size / part_size)) + is_big = file_size > 10 * 1024 * 1024 + 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 + session = Session( + self, await self.storage.dc_id(), await self.storage.auth_key(), + await self.storage.test_mode(), is_media=True + ) + workers = [self.loop.create_task(worker(session)) for _ in range(workers_count)] + queue = asyncio.Queue(1) + + try: + await session.start() + + fp.seek(part_size * file_part) + + while True: + chunk = fp.read(part_size) + + if not chunk: if not is_big and not is_missing_part: - md5_sum.update(chunk) - - 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 func() - else: - await self.loop.run_in_executor(self.executor, func) - except StopTransmission: - raise - except Exception as e: - log.exception(e) - else: - if is_big: - return raw.types.InputFileBig( - id=file_id, - parts=file_total_parts, - name=file_name, + 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: - return raw.types.InputFile( - id=file_id, - parts=file_total_parts, - name=file_name, - md5_checksum=md5_sum + rpc = raw.functions.upload.SaveFilePart( + file_id=file_id, + file_part=file_part, + bytes=chunk ) - finally: - for _ in workers: - await queue.put(None) - await asyncio.gather(*workers) + await queue.put(rpc) + + if is_missing_part: + return + + if not is_big and not is_missing_part: + md5_sum.update(chunk) - await session.stop() + file_part += 1 - if isinstance(path, (str, PurePath)): - fp.close() + if progress: + func = functools.partial( + progress, + min(file_part * part_size, file_size), + file_size, + *progress_args + ) + + if inspect.iscoroutinefunction(progress): + await func() + else: + await self.loop.run_in_executor(self.executor, func) + except StopTransmission: + raise + except Exception as e: + log.exception(e) + 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) + + await session.stop() + + if isinstance(path, (str, PurePath)): + fp.close() From 8690de8a83ad782d7f2f48da2a6a2ad9d06b78e7 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:39:05 +0545 Subject: [PATCH 030/103] Add files via upload --- 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 46722a8c40..7edb7f3c99 100644 --- a/pyrogram/parser/html.py +++ b/pyrogram/parser/html.py @@ -131,7 +131,7 @@ async def parse(self, text: str): for tag, entities in parser.tag_entities.items(): unclosed_tags.append(f"<{tag}> (x{len(entities)})") - log.info("Unclosed tags: %s", ", ".join(unclosed_tags)) + log.warning("Unclosed tags: %s", ", ".join(unclosed_tags)) entities = [] From 0a31599941d5defcaad1fb3ffaadb5af0c1921c1 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:40:00 +0545 Subject: [PATCH 031/103] Add files via upload --- pyrogram/session/session.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyrogram/session/session.py b/pyrogram/session/session.py index 0ed967a1a2..0dd3430539 100644 --- a/pyrogram/session/session.py +++ b/pyrogram/session/session.py @@ -45,7 +45,7 @@ def __init__(self): class Session: - START_TIMEOUT = 2 + START_TIMEOUT = 5 WAIT_TIMEOUT = 15 SLEEP_THRESHOLD = 10 MAX_RETRIES = 10 @@ -229,7 +229,7 @@ async def handle_packet(self, packet): raise SecurityCheckMismatch("The msg_id belongs to over 300 seconds in the past. " "Most likely the client time has to be synchronized.") except SecurityCheckMismatch as e: - log.info("Discarding packet: %s", e) + log.warning("Discarding packet: %s", e) await self.connection.close() return else: From 498562039ce89aa8073aba4be1e36565d79b6edc Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:47:29 +0545 Subject: [PATCH 032/103] =?UTF-8?q?Updated=20To=20Pyrogram=202.1.1=20?= =?UTF-8?q?=E2=9C=93=E2=9C=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyrogram/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyrogram/utils.py b/pyrogram/utils.py index f7fe59706d..f2daba2ba2 100644 --- a/pyrogram/utils.py +++ b/pyrogram/utils.py @@ -198,7 +198,8 @@ def unpack_inline_message_id(inline_message_id: str) -> "raw.base.InputBotInline ) -MIN_CHANNEL_ID = -1002147483647 +MIN_CHANNEL_ID_OLD = -1002147483647 +MIN_CHANNEL_ID = -1009999999999 MAX_CHANNEL_ID = -1000000000000 MIN_CHAT_ID = -2147483647 MAX_USER_ID_OLD = 2147483647 From 54ab89e8aca7e2d89c2a39114a41b63b22e24c20 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:48:18 +0545 Subject: [PATCH 033/103] =?UTF-8?q?Updated=20To=20Pyrogram=202.1.1=20?= =?UTF-8?q?=E2=9C=93=E2=9C=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyrogram/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py index 5b8f537c1d..7ab55c3397 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__ = "2.0.93" +__version__ = "2.1.1" __license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)" __copyright__ = "Copyright (C) 2017-present Dan " From d9efbcdc9764dcdd8525b40b203bd6c664e7365a Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 10:07:48 +0545 Subject: [PATCH 034/103] Update html.py --- pyrogram/parser/html.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pyrogram/parser/html.py b/pyrogram/parser/html.py index 7edb7f3c99..726a477226 100644 --- a/pyrogram/parser/html.py +++ b/pyrogram/parser/html.py @@ -57,6 +57,7 @@ def handle_starttag(self, tag, attrs): entity = raw.types.MessageEntityStrike elif tag == "blockquote": entity = raw.types.MessageEntityBlockquote + extra["collapsed"] = bool("expandable" in attrs.keys()) elif tag == "code": entity = raw.types.MessageEntityCode elif tag == "pre": @@ -131,7 +132,7 @@ async def parse(self, text: str): for tag, entities in parser.tag_entities.items(): unclosed_tags.append(f"<{tag}> (x{len(entities)})") - log.warning("Unclosed tags: %s", ", ".join(unclosed_tags)) + log.info("Unclosed tags: %s", ", ".join(unclosed_tags)) entities = [] @@ -177,6 +178,10 @@ def parse_one(entity): language = getattr(entity, "language", "") or "" start_tag = f'<{name} language="{language}">' if language else f"<{name}>" end_tag = f"" + elif entity_type == MessageEntityType.EXPANDABLE_BLOCKQUOTE: + name = "blockquote" + start_tag = f"<{name} expandable>" + end_tag = f"" elif entity_type in ( MessageEntityType.CODE, MessageEntityType.BLOCKQUOTE, From 281249d92d455d38014822ff12bd20bb9f95725c Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 10:09:29 +0545 Subject: [PATCH 035/103] Update markdown.py --- pyrogram/parser/markdown.py | 60 ++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/pyrogram/parser/markdown.py b/pyrogram/parser/markdown.py index 6219d9583d..417be7285a 100644 --- a/pyrogram/parser/markdown.py +++ b/pyrogram/parser/markdown.py @@ -17,6 +17,7 @@ # along with Pyrogram. If not, see . import html +import logging import re from typing import Optional @@ -32,6 +33,8 @@ SPOILER_DELIM = "||" CODE_DELIM = "`" PRE_DELIM = "```" +BLOCKQUOTE_DELIM = ">" +BLOCKQUOTE_EXPANDABLE_DELIM = "**>" MARKDOWN_RE = re.compile(r"({d})|\[(.+?)\]\((.+?)\)".format( d="|".join( @@ -59,9 +62,47 @@ class Markdown: def __init__(self, client: Optional["pyrogram.Client"]): self.html = HTML(client) + def blockquote_parser(self, text): + text = re.sub(r'\n>', '\n>', re.sub(r'^>', '>', text)) + lines = text.split('\n') + result = [] + + in_blockquote = False + + for line in lines: + if line.startswith(BLOCKQUOTE_DELIM): + if not in_blockquote: + line = re.sub(r'^> ', OPENING_TAG.format("blockquote"), line) + line = re.sub(r'^>', OPENING_TAG.format("blockquote"), line) + in_blockquote = True + result.append(line.strip()) + else: + result.append(line[1:].strip()) + elif line.startswith(BLOCKQUOTE_EXPANDABLE_DELIM): + if not in_blockquote: + line = re.sub(r'^\*\*> ', OPENING_TAG.format("blockquote expandable"), line) + line = re.sub(r'^\*\*>', OPENING_TAG.format("blockquote expandable"), line) + in_blockquote = True + result.append(line.strip()) + else: + result.append(line[3:].strip()) + else: + if in_blockquote: + line = CLOSING_TAG.format("blockquote") + line + in_blockquote = False + result.append(line) + + if in_blockquote: + line = result[len(result)-1] + CLOSING_TAG.format("blockquote") + result.pop(len(result)-1) + result.append(line) + + return '\n'.join(result) + async def parse(self, text: str, strict: bool = False): if strict: text = html.escape(text) + text = self.blockquote_parser(text) delims = set() is_fixed_width = False @@ -141,7 +182,24 @@ def unparse(text: str, entities: list): start_tag = f"{PRE_DELIM}{language}\n" end_tag = f"\n{PRE_DELIM}" elif entity_type == MessageEntityType.BLOCKQUOTE: - start_tag = end_tag = PRE_DELIM + if entity.collapsed: + start_tag = BLOCKQUOTE_EXPANDABLE_DELIM + " " + else: + start_tag = BLOCKQUOTE_DELIM + " " + end_tag = "" + blockquote_text = text[start:end] + lines = blockquote_text.split("\n") + last_length = 0 + for line in lines: + if len(line) == 0 and last_length == end: + continue + start_offset = start+last_length + last_length = last_length+len(line) + end_offset = start_offset+last_length + entities_offsets.append((start_tag, start_offset,)) + entities_offsets.append((end_tag, end_offset,)) + last_length = last_length+1 + continue elif entity_type == MessageEntityType.SPOILER: start_tag = end_tag = SPOILER_DELIM elif entity_type == MessageEntityType.TEXT_LINK: From c3aaffffb80311b11e03b8e33dcb5c2cb6600aa5 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 11:46:12 +0545 Subject: [PATCH 036/103] =?UTF-8?q?Updated=20To=20Pyrogram=202.1.2=20?= =?UTF-8?q?=E2=9C=93=E2=9C=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyrogram/client.py | 32 +------------------------------- pyrogram/filters.py | 12 ------------ 2 files changed, 1 insertion(+), 43 deletions(-) diff --git a/pyrogram/client.py b/pyrogram/client.py index 7848c1f5b9..63e4b47273 100644 --- a/pyrogram/client.py +++ b/pyrogram/client.py @@ -26,7 +26,6 @@ import shutil import sys from concurrent.futures.thread import ThreadPoolExecutor -from datetime import datetime, timedelta from hashlib import sha256 from importlib import import_module from io import StringIO, BytesIO @@ -186,9 +185,6 @@ class Client(Methods): WORKERS = min(32, (os.cpu_count() or 0) + 4) # os.cpu_count() can be None WORKDIR = PARENT_DIR - # Interval of seconds in which the updates watchdog will kick in - UPDATES_WATCHDOG_INTERVAL = 5 * 60 - mimetypes = MimeTypes() mimetypes.readfp(StringIO(mime_types)) @@ -277,13 +273,6 @@ def __init__( self.message_cache = Cache(10000) - # Sometimes, for some reason, the server will stop sending updates and will only respond to pings. - # This watchdog will invoke updates.GetState in order to wake up the server and enable it sending updates again - # after some idle time has been detected. - self.updates_watchdog_task = None - self.updates_watchdog_event = asyncio.Event() - self.last_update_time = datetime.now() - self.loop = asyncio.get_event_loop() def __enter__(self): @@ -304,18 +293,6 @@ async def __aexit__(self, *args): except ConnectionError: pass - async def updates_watchdog(self): - while True: - try: - await asyncio.wait_for(self.updates_watchdog_event.wait(), self.UPDATES_WATCHDOG_INTERVAL) - except asyncio.TimeoutError: - pass - else: - break - - if datetime.now() - self.last_update_time > timedelta(seconds=self.UPDATES_WATCHDOG_INTERVAL): - await self.invoke(raw.functions.updates.GetState()) - async def authorize(self) -> User: if self.bot_token: return await self.sign_in_bot(self.bot_token) @@ -358,7 +335,6 @@ async def authorize(self) -> User: enums.SentCodeType.CALL: "phone call", enums.SentCodeType.FLASH_CALL: "phone flash call", enums.SentCodeType.FRAGMENT_SMS: "Fragment SMS", - enums.SentCodeType.EMAIL_CODE: "email code" } print(f"The confirmation code has been sent via {sent_code_descriptions[sent_code.type]}") @@ -487,11 +463,7 @@ async def fetch_peers(self, peers: List[Union[raw.types.User, raw.types.Chat, ra if isinstance(peer, raw.types.User): peer_id = peer.id access_hash = peer.access_hash - username = ( - peer.username.lower() if peer.username - else peer.usernames[0].username.lower() if peer.usernames - else None - ) + 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)): @@ -513,8 +485,6 @@ async def fetch_peers(self, peers: List[Union[raw.types.User, raw.types.Chat, ra return is_min async def handle_updates(self, updates): - self.last_update_time = datetime.now() - if isinstance(updates, (raw.types.Updates, raw.types.UpdatesCombined)): is_min = any(( await self.fetch_peers(updates.users), diff --git a/pyrogram/filters.py b/pyrogram/filters.py index b52dfe601d..ac2dbf20fd 100644 --- a/pyrogram/filters.py +++ b/pyrogram/filters.py @@ -425,17 +425,6 @@ async def dice_filter(_, __, m: Message): """Filter messages that contain :obj:`~pyrogram.types.Dice` objects.""" -# endregion - -# region media_spoiler -async def media_spoiler_filter(_, __, m: Message): - return bool(m.has_media_spoiler) - - -media_spoiler = create(media_spoiler_filter) -"""Filter media messages that contain a spoiler.""" - - # endregion # region private_filter @@ -742,7 +731,6 @@ async def linked_channel_filter(_, __, m: Message): linked_channel = create(linked_channel_filter) """Filter messages that are automatically forwarded from the linked channel to the group chat.""" - # endregion From ebf87c8d95677afd5923881d903846d5be12c617 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 11:48:15 +0545 Subject: [PATCH 037/103] =?UTF-8?q?Updated=20To=20Pyrogram=202.1.2=20?= =?UTF-8?q?=E2=9C=93=E2=9C=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyrogram/session/auth.py | 2 +- pyrogram/session/session.py | 97 ++++++++++++------------------------- 2 files changed, 31 insertions(+), 68 deletions(-) diff --git a/pyrogram/session/auth.py b/pyrogram/session/auth.py index c5d9cd9a50..d51e18f843 100644 --- a/pyrogram/session/auth.py +++ b/pyrogram/session/auth.py @@ -278,4 +278,4 @@ async def create(self): else: return auth_key finally: - await self.connection.close() + self.connection.close() diff --git a/pyrogram/session/session.py b/pyrogram/session/session.py index 0dd3430539..5135af6987 100644 --- a/pyrogram/session/session.py +++ b/pyrogram/session/session.py @@ -17,7 +17,6 @@ # along with Pyrogram. If not, see . import asyncio -import bisect import logging import os from hashlib import sha1 @@ -33,7 +32,7 @@ ) from pyrogram.raw.all import layer from pyrogram.raw.core import TLObject, MsgContainer, Int, FutureSalts -from .internals import MsgId, MsgFactory +from .internals import MsgFactory log = logging.getLogger(__name__) @@ -45,19 +44,12 @@ def __init__(self): class Session: - START_TIMEOUT = 5 + START_TIMEOUT = 1 WAIT_TIMEOUT = 15 SLEEP_THRESHOLD = 10 - MAX_RETRIES = 10 - ACKS_THRESHOLD = 10 + MAX_RETRIES = 5 + ACKS_THRESHOLD = 8 PING_INTERVAL = 5 - STORED_MSG_IDS_MAX_SIZE = 1000 * 2 - - TRANSPORT_ERRORS = { - 404: "auth key not found", - 429: "transport flood", - 444: "invalid DC" - } def __init__( self, @@ -157,8 +149,6 @@ async def start(self): async def stop(self): self.is_started.clear() - self.stored_msg_ids.clear() - self.ping_task_event.set() if self.ping_task is not None: @@ -166,11 +156,14 @@ async def stop(self): self.ping_task_event.clear() - await self.connection.close() + self.connection.close() if self.recv_task: await self.recv_task + for i in self.results.values(): + i.event.set() + if not self.is_media and callable(self.client.disconnect_handler): try: await self.client.disconnect_handler(self.client) @@ -184,14 +177,19 @@ async def restart(self): await self.start() async def handle_packet(self, packet): - data = await self.loop.run_in_executor( - pyrogram.crypto_executor, - mtproto.unpack, - BytesIO(packet), - self.session_id, - self.auth_key, - self.auth_key_id - ) + try: + data = await self.loop.run_in_executor( + pyrogram.crypto_executor, + mtproto.unpack, + BytesIO(packet), + self.session_id, + self.auth_key, + self.auth_key_id, + self.stored_msg_ids + ) + except SecurityCheckMismatch as e: + log.warning("Discarding packet: %s", e) + return messages = ( data.body.messages @@ -208,33 +206,6 @@ async def handle_packet(self, packet): else: self.pending_acks.add(msg.msg_id) - try: - if len(self.stored_msg_ids) > Session.STORED_MSG_IDS_MAX_SIZE: - del self.stored_msg_ids[:Session.STORED_MSG_IDS_MAX_SIZE // 2] - - if self.stored_msg_ids: - if msg.msg_id < self.stored_msg_ids[0]: - raise SecurityCheckMismatch("The msg_id is lower than all the stored values") - - if msg.msg_id in self.stored_msg_ids: - raise SecurityCheckMismatch("The msg_id is equal to any of the stored values") - - time_diff = (msg.msg_id - MsgId()) / 2 ** 32 - - if time_diff > 30: - raise SecurityCheckMismatch("The msg_id belongs to over 30 seconds in the future. " - "Most likely the client time has to be synchronized.") - - if time_diff < -300: - raise SecurityCheckMismatch("The msg_id belongs to over 300 seconds in the past. " - "Most likely the client time has to be synchronized.") - except SecurityCheckMismatch as e: - log.warning("Discarding packet: %s", e) - await self.connection.close() - return - else: - bisect.insort(self.stored_msg_ids, msg.msg_id) - if isinstance(msg.body, (raw.types.MsgDetailedInfo, raw.types.MsgNewDetailedInfo)): self.pending_acks.add(msg.body.answer_msg_id) continue @@ -298,12 +269,7 @@ async def recv_worker(self): if packet is None or len(packet) == 4: if packet: - error_code = -Int.read(BytesIO(packet)) - - log.warning( - "Server sent transport error: %s (%s)", - error_code, Session.TRANSPORT_ERRORS.get(error_code, "unknown error") - ) + log.warning('Server sent "%s"', Int.read(BytesIO(packet))) if self.is_started.is_set(): self.loop.create_task(self.restart()) @@ -344,26 +310,23 @@ async def send(self, data: TLObject, wait_response: bool = True, timeout: float await asyncio.wait_for(self.results[msg_id].event.wait(), timeout) except asyncio.TimeoutError: pass - - result = self.results.pop(msg_id).value + finally: + result = self.results.pop(msg_id).value if result is None: raise TimeoutError("Request timed out") - - if isinstance(result, raw.types.RpcError): + elif isinstance(result, raw.types.RpcError): if isinstance(data, (raw.functions.InvokeWithoutUpdates, raw.functions.InvokeWithTakeout)): data = data.query RPCError.raise_it(result, type(data)) - - if isinstance(result, raw.types.BadMsgNotification): - log.warning("%s: %s", BadMsgNotification.__name__, BadMsgNotification(result.error_code)) - - if isinstance(result, raw.types.BadServerSalt): + elif isinstance(result, raw.types.BadMsgNotification): + raise BadMsgNotification(result.error_code) + elif isinstance(result, raw.types.BadServerSalt): self.salt = result.new_server_salt return await self.send(data, wait_response, timeout) - - return result + else: + return result async def invoke( self, From b80bb07891b86ce7705cc9d51a36b3f9d2723cae Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 11:51:24 +0545 Subject: [PATCH 038/103] =?UTF-8?q?Updated=20To=20Pyrogram=202.1.2=20?= =?UTF-8?q?=E2=9C=93=E2=9C=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../methods/messages/edit_inline_media.py | 77 +++++++++---------- .../methods/messages/edit_message_media.py | 49 +++++------- pyrogram/methods/messages/send_animation.py | 9 +-- pyrogram/methods/messages/send_media_group.py | 32 +++----- pyrogram/methods/messages/send_photo.py | 13 +--- pyrogram/methods/messages/send_video.py | 9 +-- 6 files changed, 72 insertions(+), 117 deletions(-) diff --git a/pyrogram/methods/messages/edit_inline_media.py b/pyrogram/methods/messages/edit_inline_media.py index 7ab424a4f2..77fa673ae6 100644 --- a/pyrogram/methods/messages/edit_inline_media.py +++ b/pyrogram/methods/messages/edit_inline_media.py @@ -16,10 +16,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -import asyncio -import io import os import re +import io +import asyncio +import io import pyrogram from pyrogram import raw @@ -79,6 +80,8 @@ async def edit_inline_media( caption = media.caption parse_mode = media.parse_mode + is_photo = isinstance(media, types.InputMediaPhoto) + is_bytes_io = isinstance(media.media, io.BytesIO) is_uploaded_file = is_bytes_io or os.path.isfile(media.media) @@ -96,16 +99,15 @@ async def edit_inline_media( else: filename_attribute = [] - if isinstance(media, types.InputMediaPhoto): + + if is_photo: if is_uploaded_file: media = raw.types.InputMediaUploadedPhoto( - file=await self.save_file(media.media), - spoiler=media.has_spoiler + file=await self.save_file(media.media) ) elif is_external_url: media = raw.types.InputMediaPhotoExternal( - url=media.media, - spoiler=media.has_spoiler + url=media.media ) else: media = utils.get_input_media_from_file_id(media.media, FileType.PHOTO) @@ -115,20 +117,18 @@ async def edit_inline_media( mime_type=(None if is_bytes_io else self.guess_mime_type(media.media)) or "video/mp4", thumb=await self.save_file(media.thumb), file=await self.save_file(media.media), - spoiler=media.has_spoiler, attributes=[ - raw.types.DocumentAttributeVideo( - supports_streaming=media.supports_streaming or None, - duration=media.duration, - w=media.width, - h=media.height - ) - ] + filename_attribute + raw.types.DocumentAttributeVideo( + supports_streaming=media.supports_streaming or None, + duration=media.duration, + w=media.width, + h=media.height + ) + ] + filename_attribute ) elif is_external_url: media = raw.types.InputMediaDocumentExternal( - url=media.media, - spoiler=media.has_spoiler + url=media.media ) else: media = utils.get_input_media_from_file_id(media.media, FileType.VIDEO) @@ -139,12 +139,12 @@ async def edit_inline_media( thumb=await self.save_file(media.thumb), file=await self.save_file(media.media), attributes=[ - raw.types.DocumentAttributeAudio( - duration=media.duration, - performer=media.performer, - title=media.title - ) - ] + filename_attribute + raw.types.DocumentAttributeAudio( + duration=media.duration, + performer=media.performer, + title=media.title + ) + ] + filename_attribute ) elif is_external_url: media = raw.types.InputMediaDocumentExternal( @@ -158,22 +158,20 @@ async def edit_inline_media( mime_type=(None if is_bytes_io else self.guess_mime_type(media.media)) or "video/mp4", thumb=await self.save_file(media.thumb), file=await self.save_file(media.media), - spoiler=media.has_spoiler, attributes=[ - raw.types.DocumentAttributeVideo( - supports_streaming=True, - duration=media.duration, - w=media.width, - h=media.height - ), - raw.types.DocumentAttributeAnimated() - ] + filename_attribute, + raw.types.DocumentAttributeVideo( + supports_streaming=True, + duration=media.duration, + w=media.width, + h=media.height + ), + raw.types.DocumentAttributeAnimated() + ] + filename_attribute, nosound_video=True ) elif is_external_url: media = raw.types.InputMediaDocumentExternal( - url=media.media, - spoiler=media.has_spoiler + url=media.media ) else: media = utils.get_input_media_from_file_id(media.media, FileType.ANIMATION) @@ -198,6 +196,7 @@ async def edit_inline_media( session = await get_session(self, dc_id) + if is_uploaded_file: uploaded_media = await self.invoke( raw.functions.messages.UploadMedia( @@ -211,15 +210,13 @@ async def edit_inline_media( id=uploaded_media.photo.id, access_hash=uploaded_media.photo.access_hash, file_reference=uploaded_media.photo.file_reference - ), - spoiler=getattr(media, "has_spoiler", None) - ) if isinstance(media, types.InputMediaPhoto) else raw.types.InputMediaDocument( + ) + ) if is_photo else raw.types.InputMediaDocument( id=raw.types.InputDocument( id=uploaded_media.document.id, access_hash=uploaded_media.document.access_hash, - file_reference=uploaded_media.document.file_reference - ), - spoiler=getattr(media, "has_spoiler", None) + file_reference=uploaded_media.document.file_reference + ) ) else: actual_media = media diff --git a/pyrogram/methods/messages/edit_message_media.py b/pyrogram/methods/messages/edit_message_media.py index 5a34f13875..16efb5b858 100644 --- a/pyrogram/methods/messages/edit_message_media.py +++ b/pyrogram/methods/messages/edit_message_media.py @@ -16,9 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -import io import os import re +import io from typing import Union import pyrogram @@ -93,40 +93,36 @@ async def edit_message_media( if isinstance(media, types.InputMediaPhoto): if isinstance(media.media, io.BytesIO) or os.path.isfile(media.media): - uploaded_media = await self.invoke( + media = await self.invoke( raw.functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=raw.types.InputMediaUploadedPhoto( - file=await self.save_file(media.media), - spoiler=media.has_spoiler + file=await self.save_file(media.media) ) ) ) media = raw.types.InputMediaPhoto( id=raw.types.InputPhoto( - id=uploaded_media.photo.id, - access_hash=uploaded_media.photo.access_hash, - file_reference=uploaded_media.photo.file_reference - ), - spoiler=media.has_spoiler + id=media.photo.id, + access_hash=media.photo.access_hash, + file_reference=media.photo.file_reference + ) ) elif re.match("^https?://", media.media): media = raw.types.InputMediaPhotoExternal( - url=media.media, - spoiler=media.has_spoiler + url=media.media ) else: media = utils.get_input_media_from_file_id(media.media, FileType.PHOTO) elif isinstance(media, types.InputMediaVideo): if isinstance(media.media, io.BytesIO) or os.path.isfile(media.media): - uploaded_media = await self.invoke( + media = await self.invoke( raw.functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=raw.types.InputMediaUploadedDocument( mime_type=self.guess_mime_type(media.media) or "video/mp4", thumb=await self.save_file(media.thumb), - spoiler=media.has_spoiler, file=await self.save_file(media.media), attributes=[ raw.types.DocumentAttributeVideo( @@ -145,16 +141,14 @@ async def edit_message_media( media = raw.types.InputMediaDocument( id=raw.types.InputDocument( - id=uploaded_media.document.id, - access_hash=uploaded_media.document.access_hash, - file_reference=uploaded_media.document.file_reference - ), - spoiler=media.has_spoiler + id=media.document.id, + access_hash=media.document.access_hash, + file_reference=media.document.file_reference + ) ) elif re.match("^https?://", media.media): media = raw.types.InputMediaDocumentExternal( - url=media.media, - spoiler=media.has_spoiler + url=media.media ) else: media = utils.get_input_media_from_file_id(media.media, FileType.VIDEO) @@ -196,13 +190,12 @@ async def edit_message_media( media = utils.get_input_media_from_file_id(media.media, FileType.AUDIO) elif isinstance(media, types.InputMediaAnimation): if isinstance(media.media, io.BytesIO) or os.path.isfile(media.media): - uploaded_media = await self.invoke( + media = await self.invoke( raw.functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=raw.types.InputMediaUploadedDocument( mime_type=self.guess_mime_type(media.media) or "video/mp4", thumb=await self.save_file(media.thumb), - spoiler=media.has_spoiler, file=await self.save_file(media.media), attributes=[ raw.types.DocumentAttributeVideo( @@ -222,16 +215,14 @@ async def edit_message_media( media = raw.types.InputMediaDocument( id=raw.types.InputDocument( - id=uploaded_media.document.id, - access_hash=uploaded_media.document.access_hash, - file_reference=uploaded_media.document.file_reference - ), - spoiler=media.has_spoiler + id=media.document.id, + access_hash=media.document.access_hash, + file_reference=media.document.file_reference + ) ) elif re.match("^https?://", media.media): media = raw.types.InputMediaDocumentExternal( - url=media.media, - spoiler=media.has_spoiler + url=media.media ) else: media = utils.get_input_media_from_file_id(media.media, FileType.ANIMATION) diff --git a/pyrogram/methods/messages/send_animation.py b/pyrogram/methods/messages/send_animation.py index bac16bac9f..ec85dc0569 100644 --- a/pyrogram/methods/messages/send_animation.py +++ b/pyrogram/methods/messages/send_animation.py @@ -39,7 +39,6 @@ async def send_animation( unsave: bool = False, parse_mode: Optional["enums.ParseMode"] = None, caption_entities: List["types.MessageEntity"] = None, - has_spoiler: bool = None, duration: int = 0, width: int = 0, height: int = 0, @@ -89,9 +88,6 @@ async def send_animation( caption_entities (List of :obj:`~pyrogram.types.MessageEntity`): List of special entities that appear in the caption, which can be specified instead of *parse_mode*. - has_spoiler (``bool``, *optional*): - Pass True if the animation needs to be covered with a spoiler animation. - duration (``int``, *optional*): Duration of sent animation in seconds. @@ -184,7 +180,6 @@ async def progress(current, total): mime_type=self.guess_mime_type(animation) or "video/mp4", file=file, thumb=thumb, - spoiler=has_spoiler, attributes=[ raw.types.DocumentAttributeVideo( supports_streaming=True, @@ -198,8 +193,7 @@ async def progress(current, total): ) elif re.match("^https?://", animation): media = raw.types.InputMediaDocumentExternal( - url=animation, - spoiler=has_spoiler + url=animation ) else: media = utils.get_input_media_from_file_id(animation, FileType.ANIMATION) @@ -210,7 +204,6 @@ async def progress(current, total): mime_type=self.guess_mime_type(file_name or animation.name) or "video/mp4", file=file, thumb=thumb, - spoiler=has_spoiler, attributes=[ raw.types.DocumentAttributeVideo( supports_streaming=True, diff --git a/pyrogram/methods/messages/send_media_group.py b/pyrogram/methods/messages/send_media_group.py index a8b905de23..0dfbbaa236 100644 --- a/pyrogram/methods/messages/send_media_group.py +++ b/pyrogram/methods/messages/send_media_group.py @@ -100,8 +100,7 @@ async def send_media_group( raw.functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=raw.types.InputMediaUploadedPhoto( - file=await self.save_file(i.media), - spoiler=i.has_spoiler + file=await self.save_file(i.media) ) ) ) @@ -111,16 +110,14 @@ async def send_media_group( id=media.photo.id, access_hash=media.photo.access_hash, file_reference=media.photo.file_reference - ), - spoiler=i.has_spoiler + ) ) elif re.match("^https?://", i.media): media = await self.invoke( raw.functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=raw.types.InputMediaPhotoExternal( - url=i.media, - spoiler=i.has_spoiler + url=i.media ) ) ) @@ -130,8 +127,7 @@ async def send_media_group( id=media.photo.id, access_hash=media.photo.access_hash, file_reference=media.photo.file_reference - ), - spoiler=i.has_spoiler + ) ) else: media = utils.get_input_media_from_file_id(i.media, FileType.PHOTO) @@ -140,8 +136,7 @@ async def send_media_group( raw.functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=raw.types.InputMediaUploadedPhoto( - file=await self.save_file(i.media), - spoiler=i.has_spoiler + file=await self.save_file(i.media) ) ) ) @@ -151,8 +146,7 @@ async def send_media_group( id=media.photo.id, access_hash=media.photo.access_hash, file_reference=media.photo.file_reference - ), - spoiler=i.has_spoiler + ) ) elif isinstance(i, types.InputMediaVideo): if isinstance(i.media, str): @@ -163,7 +157,6 @@ async def send_media_group( media=raw.types.InputMediaUploadedDocument( file=await self.save_file(i.media), thumb=await self.save_file(i.thumb), - spoiler=i.has_spoiler, mime_type=self.guess_mime_type(i.media) or "video/mp4", attributes=[ raw.types.DocumentAttributeVideo( @@ -183,16 +176,14 @@ async def send_media_group( id=media.document.id, access_hash=media.document.access_hash, file_reference=media.document.file_reference - ), - spoiler=i.has_spoiler + ) ) elif re.match("^https?://", i.media): media = await self.invoke( raw.functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=raw.types.InputMediaDocumentExternal( - url=i.media, - spoiler=i.has_spoiler + url=i.media ) ) ) @@ -202,8 +193,7 @@ async def send_media_group( id=media.document.id, access_hash=media.document.access_hash, file_reference=media.document.file_reference - ), - spoiler=i.has_spoiler + ) ) else: media = utils.get_input_media_from_file_id(i.media, FileType.VIDEO) @@ -214,7 +204,6 @@ async def send_media_group( media=raw.types.InputMediaUploadedDocument( file=await self.save_file(i.media), thumb=await self.save_file(i.thumb), - spoiler=i.has_spoiler, mime_type=self.guess_mime_type(getattr(i.media, "name", "video.mp4")) or "video/mp4", attributes=[ raw.types.DocumentAttributeVideo( @@ -234,8 +223,7 @@ async def send_media_group( id=media.document.id, access_hash=media.document.access_hash, file_reference=media.document.file_reference - ), - spoiler=i.has_spoiler + ) ) elif isinstance(i, types.InputMediaAudio): if isinstance(i.media, str): diff --git a/pyrogram/methods/messages/send_photo.py b/pyrogram/methods/messages/send_photo.py index 61298a5c68..994f0c9322 100644 --- a/pyrogram/methods/messages/send_photo.py +++ b/pyrogram/methods/messages/send_photo.py @@ -37,7 +37,6 @@ async def send_photo( caption: str = "", parse_mode: Optional["enums.ParseMode"] = None, caption_entities: List["types.MessageEntity"] = None, - has_spoiler: bool = None, ttl_seconds: int = None, disable_notification: bool = None, reply_to_message_id: int = None, @@ -79,9 +78,6 @@ async def send_photo( caption_entities (List of :obj:`~pyrogram.types.MessageEntity`): List of special entities that appear in the caption, which can be specified instead of *parse_mode*. - has_spoiler (``bool``, *optional*): - Pass True if the photo needs to be covered with a spoiler animation. - ttl_seconds (``int``, *optional*): Self-Destruct Timer. If you set a timer, the photo will self-destruct in *ttl_seconds* @@ -153,14 +149,12 @@ async def send_photo( file = await self.save_file(photo, progress=progress, progress_args=progress_args) media = raw.types.InputMediaUploadedPhoto( file=file, - ttl_seconds=ttl_seconds, - spoiler=has_spoiler, + ttl_seconds=ttl_seconds ) elif re.match("^https?://", photo): media = raw.types.InputMediaPhotoExternal( url=photo, - ttl_seconds=ttl_seconds, - spoiler=has_spoiler + ttl_seconds=ttl_seconds ) else: media = utils.get_input_media_from_file_id(photo, FileType.PHOTO, ttl_seconds=ttl_seconds) @@ -168,8 +162,7 @@ async def send_photo( file = await self.save_file(photo, progress=progress, progress_args=progress_args) media = raw.types.InputMediaUploadedPhoto( file=file, - ttl_seconds=ttl_seconds, - spoiler=has_spoiler + ttl_seconds=ttl_seconds ) while True: diff --git a/pyrogram/methods/messages/send_video.py b/pyrogram/methods/messages/send_video.py index e869dd172d..c20530641c 100644 --- a/pyrogram/methods/messages/send_video.py +++ b/pyrogram/methods/messages/send_video.py @@ -38,7 +38,6 @@ async def send_video( caption: str = "", parse_mode: Optional["enums.ParseMode"] = None, caption_entities: List["types.MessageEntity"] = None, - has_spoiler: bool = None, ttl_seconds: int = None, duration: int = 0, width: int = 0, @@ -86,9 +85,6 @@ async def send_video( caption_entities (List of :obj:`~pyrogram.types.MessageEntity`): List of special entities that appear in the caption, which can be specified instead of *parse_mode*. - has_spoiler (``bool``, *optional*): - Pass True if the video needs to be covered with a spoiler animation. - ttl_seconds (``int``, *optional*): Self-Destruct Timer. If you set a timer, the video will self-destruct in *ttl_seconds* @@ -189,7 +185,6 @@ async def progress(current, total): mime_type=self.guess_mime_type(video) or "video/mp4", file=file, ttl_seconds=ttl_seconds, - spoiler=has_spoiler, thumb=thumb, attributes=[ raw.types.DocumentAttributeVideo( @@ -204,8 +199,7 @@ async def progress(current, total): elif re.match("^https?://", video): media = raw.types.InputMediaDocumentExternal( url=video, - ttl_seconds=ttl_seconds, - spoiler=has_spoiler + ttl_seconds=ttl_seconds ) else: media = utils.get_input_media_from_file_id(video, FileType.VIDEO, ttl_seconds=ttl_seconds) @@ -216,7 +210,6 @@ async def progress(current, total): mime_type=self.guess_mime_type(file_name or video.name) or "video/mp4", file=file, ttl_seconds=ttl_seconds, - spoiler=has_spoiler, thumb=thumb, attributes=[ raw.types.DocumentAttributeVideo( From d21b9e599d669045b43b0697c933b2c40f62b8c2 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 11:53:19 +0545 Subject: [PATCH 039/103] =?UTF-8?q?Updated=20To=20Pyrogram=202.1.2=20?= =?UTF-8?q?=E2=9C=93=E2=9C=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyrogram/methods/advanced/save_file.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/pyrogram/methods/advanced/save_file.py b/pyrogram/methods/advanced/save_file.py index 5ecac6d80e..b99a3c43b5 100644 --- a/pyrogram/methods/advanced/save_file.py +++ b/pyrogram/methods/advanced/save_file.py @@ -134,19 +134,23 @@ async def worker(session): 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 - session = Session( - self, await self.storage.dc_id(), await self.storage.auth_key(), - await self.storage.test_mode(), is_media=True - ) - workers = [self.loop.create_task(worker(session)) for _ in range(workers_count)] - queue = asyncio.Queue(1) + 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 = [self.loop.create_task(worker(session)) for session in pool for _ in range(workers_count)] + queue = asyncio.Queue(16) try: - await session.start() + for session in pool: + await session.start() fp.seek(part_size * file_part) @@ -219,7 +223,8 @@ async def worker(session): await asyncio.gather(*workers) - await session.stop() + for session in pool: + await session.stop() if isinstance(path, (str, PurePath)): fp.close() From 9470edc364639149c38718ee4c397235eda04daa Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 11:55:05 +0545 Subject: [PATCH 040/103] =?UTF-8?q?Updated=20To=20Pyrogram=202.1.2=20?= =?UTF-8?q?=E2=9C=93=E2=9C=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyrogram/enums/sent_code_type.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pyrogram/enums/sent_code_type.py b/pyrogram/enums/sent_code_type.py index 474ed6b0f3..e3ec61120a 100644 --- a/pyrogram/enums/sent_code_type.py +++ b/pyrogram/enums/sent_code_type.py @@ -40,6 +40,3 @@ class SentCodeType(AutoName): FRAGMENT_SMS = raw.types.auth.SentCodeTypeFragmentSms "The code was sent via Fragment SMS." - - EMAIL_CODE = raw.types.auth.SentCodeTypeEmailCode - "The code was sent via email." From 2a2737afd969eb7a5dac871b44b59f518899ddcb Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 11:58:10 +0545 Subject: [PATCH 041/103] Add files via upload --- pyrogram/storage/file_storage.py | 9 ++++++--- pyrogram/storage/sqlite_storage.py | 26 ++++++++++++++++---------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/pyrogram/storage/file_storage.py b/pyrogram/storage/file_storage.py index aebe917671..986787cd95 100644 --- a/pyrogram/storage/file_storage.py +++ b/pyrogram/storage/file_storage.py @@ -38,13 +38,13 @@ def update(self): version = self.version() if version == 1: - with self.conn: + with self.lock, self.conn: self.conn.execute("DELETE FROM peers") version += 1 if version == 2: - with self.conn: + with self.lock, self.conn: self.conn.execute("ALTER TABLE sessions ADD api_id INTEGER") version += 1 @@ -63,7 +63,10 @@ async def open(self): self.update() with self.conn: - self.conn.execute("VACUUM") + try: # Python 3.6.0 (exactly this version) is bugged and won't successfully execute the vacuum + self.conn.execute("VACUUM") + except sqlite3.OperationalError: + pass async def delete(self): os.remove(self.database) diff --git a/pyrogram/storage/sqlite_storage.py b/pyrogram/storage/sqlite_storage.py index e28b9b746e..15e5ddc0c5 100644 --- a/pyrogram/storage/sqlite_storage.py +++ b/pyrogram/storage/sqlite_storage.py @@ -19,6 +19,7 @@ import inspect import sqlite3 import time +from threading import Lock from typing import List, Tuple, Any from pyrogram import raw @@ -97,9 +98,10 @@ def __init__(self, name: str): super().__init__(name) self.conn = None # type: sqlite3.Connection + self.lock = Lock() def create(self): - with self.conn: + with self.lock, self.conn: self.conn.executescript(SCHEMA) self.conn.execute( @@ -117,20 +119,24 @@ async def open(self): async def save(self): await self.date(int(time.time())) - self.conn.commit() + + with self.lock: + self.conn.commit() async def close(self): - self.conn.close() + with self.lock: + self.conn.close() async def delete(self): raise NotImplementedError async def update_peers(self, peers: List[Tuple[int, int, str, str, str]]): - self.conn.executemany( - "REPLACE INTO peers (id, access_hash, type, username, phone_number)" - "VALUES (?, ?, ?, ?, ?)", - peers - ) + with self.lock: + self.conn.executemany( + "REPLACE INTO peers (id, access_hash, type, username, phone_number)" + "VALUES (?, ?, ?, ?, ?)", + peers + ) async def get_peer_by_id(self, peer_id: int): r = self.conn.execute( @@ -179,7 +185,7 @@ def _get(self): def _set(self, value: Any): attr = inspect.stack()[2].function - with self.conn: + with self.lock, self.conn: self.conn.execute( f"UPDATE sessions SET {attr} = ?", (value,) @@ -215,7 +221,7 @@ def version(self, value: int = object): "SELECT number FROM version" ).fetchone()[0] else: - with self.conn: + with self.lock, self.conn: self.conn.execute( "UPDATE version SET number = ?", (value,) From fed8e3ba0f99a1363aa633f24dbdfe7ce3ac8290 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:26:00 +0545 Subject: [PATCH 042/103] Update message_entity_type.py --- pyrogram/enums/message_entity_type.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyrogram/enums/message_entity_type.py b/pyrogram/enums/message_entity_type.py index 4db75f93f7..5229d03917 100644 --- a/pyrogram/enums/message_entity_type.py +++ b/pyrogram/enums/message_entity_type.py @@ -68,6 +68,9 @@ class MessageEntityType(AutoName): BLOCKQUOTE = raw.types.MessageEntityBlockquote "Blockquote text" + EXPANDABLE_BLOCKQUOTE = raw.types.MessageEntityBlockquote + "collapsed-by-default block quotation" + TEXT_LINK = raw.types.MessageEntityTextUrl "For clickable text URLs" From 942bc1990d18c5b760b479876562ff999a5f4867 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:31:07 +0545 Subject: [PATCH 043/103] Update message_entity.py --- .../types/messages_and_media/message_entity.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pyrogram/types/messages_and_media/message_entity.py b/pyrogram/types/messages_and_media/message_entity.py index d2bf654dcd..281015c5ed 100644 --- a/pyrogram/types/messages_and_media/message_entity.py +++ b/pyrogram/types/messages_and_media/message_entity.py @@ -51,6 +51,9 @@ class MessageEntity(Object): custom_emoji_id (``int``, *optional*): For :obj:`~pyrogram.enums.MessageEntityType.CUSTOM_EMOJI` only, unique identifier of the custom emoji. Use :meth:`~pyrogram.Client.get_custom_emoji_stickers` to get full information about the sticker. + + collapsed (``bool``, *optional*): + For :obj:`~pyrogram.enums.MessageEntityType.BLOCKQUOTE` only, whether the blockquote expandable. """ def __init__( @@ -63,7 +66,8 @@ def __init__( url: str = None, user: "types.User" = None, language: str = None, - custom_emoji_id: int = None + custom_emoji_id: int = None, + collapsed: bool = None ): super().__init__(client) @@ -74,6 +78,7 @@ def __init__( self.user = user self.language = language self.custom_emoji_id = custom_emoji_id + self.collapsed = collapsed @staticmethod def _parse(client, entity: "raw.base.MessageEntity", users: dict) -> Optional["MessageEntity"]: @@ -94,6 +99,7 @@ def _parse(client, entity: "raw.base.MessageEntity", users: dict) -> Optional["M user=types.User._parse(client, users.get(user_id, None)), language=getattr(entity, "language", None), custom_emoji_id=getattr(entity, "document_id", None), + collapsed=getattr(entity, "collapsed", None), client=client ) @@ -116,6 +122,12 @@ async def write(self): if self.custom_emoji_id is not None: args["document_id"] = self.custom_emoji_id + if self.type not in [ + enums.MessageEntityType.BLOCKQUOTE, + enums.MessageEntityType.EXPANDABLE_BLOCKQUOTE + ]: + args.pop("collapsed") + entity = self.type.value if entity is raw.types.MessageEntityMentionName: From 756a99c24dc2f0f9e124a353127051ced654b198 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:39:16 +0545 Subject: [PATCH 044/103] Add files via upload From 36bdbc5052c0f49509bc665be2fd801290496209 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:39:53 +0545 Subject: [PATCH 045/103] Add files via upload From fa992088c3eafd800c35591e6b00963d9daf698e Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:41:08 +0545 Subject: [PATCH 046/103] Add files via upload From 1fef7e5b6e813c418fca2965682d07491522ec63 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:41:51 +0545 Subject: [PATCH 047/103] Add files via upload From f9b1a79dbfb52e7ffbc81d6f45ddd920525999ca Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:42:31 +0545 Subject: [PATCH 048/103] Add files via upload From bf4a907343663adba98d45255e243b99169ff4e9 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:43:51 +0545 Subject: [PATCH 049/103] Add files via upload From 2acf77d7b4aa9828c42b394972cb13ac667180f3 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:44:50 +0545 Subject: [PATCH 050/103] Add files via upload --- pyrogram/methods/auth/initialize.py | 3 --- pyrogram/methods/auth/terminate.py | 9 +-------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/pyrogram/methods/auth/initialize.py b/pyrogram/methods/auth/initialize.py index 7188b66817..1e7915e00e 100644 --- a/pyrogram/methods/auth/initialize.py +++ b/pyrogram/methods/auth/initialize.py @@ -16,7 +16,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -import asyncio import logging import pyrogram @@ -47,6 +46,4 @@ async def initialize( await self.dispatcher.start() - self.updates_watchdog_task = asyncio.create_task(self.updates_watchdog()) - self.is_initialized = True diff --git a/pyrogram/methods/auth/terminate.py b/pyrogram/methods/auth/terminate.py index d5fd949cba..5ecb6758ef 100644 --- a/pyrogram/methods/auth/terminate.py +++ b/pyrogram/methods/auth/terminate.py @@ -41,7 +41,7 @@ async def terminate( if self.takeout_id: await self.invoke(raw.functions.account.FinishTakeoutSession()) - log.info("Takeout session %s finished", self.takeout_id) + log.warning("Takeout session %s finished", self.takeout_id) await self.storage.save() await self.dispatcher.stop() @@ -51,11 +51,4 @@ async def terminate( self.media_sessions.clear() - self.updates_watchdog_event.set() - - if self.updates_watchdog_task is not None: - await self.updates_watchdog_task - - self.updates_watchdog_event.clear() - self.is_initialized = False From 47e6634a9b84e63521c38e3f0df419419ab064c4 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:45:50 +0545 Subject: [PATCH 051/103] Add files via upload --- pyrogram/methods/bots/send_inline_bot_result.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyrogram/methods/bots/send_inline_bot_result.py b/pyrogram/methods/bots/send_inline_bot_result.py index f29d8eb9cd..0f31880636 100644 --- a/pyrogram/methods/bots/send_inline_bot_result.py +++ b/pyrogram/methods/bots/send_inline_bot_result.py @@ -30,7 +30,7 @@ async def send_inline_bot_result( result_id: str, disable_notification: bool = None, reply_to_message_id: int = None - ) -> "raw.base.Updates": + ): """Send an inline bot result. Bot results can be retrieved using :meth:`~pyrogram.Client.get_inline_bot_results` @@ -56,7 +56,7 @@ async def send_inline_bot_result( If the message is a reply, ID of the original message. Returns: - :obj:`~pyrogram.raw.base.Updates`: Currently, on success, a raw result is returned. + :obj:`~pyrogram.types.Message`: On success, the sent inline result message is returned. Example: .. code-block:: python From 2e012a7c0d7a1bb7424506b1aedb6bb3fbf5de39 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:47:23 +0545 Subject: [PATCH 052/103] Add files via upload From b38ef42d6a92d6a85e2d7daea4694329b6e60aa5 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:48:13 +0545 Subject: [PATCH 053/103] Add files via upload From 589462317a6b2523c46efb851904d2ebe857bc9b Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:49:06 +0545 Subject: [PATCH 054/103] Add files via upload From 444f662dda54b253c3febcf24c8bf556297afe72 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:50:06 +0545 Subject: [PATCH 055/103] Add files via upload From c4f00b7c0fe19dffd5148a8e4b076e57c8b28fe1 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:52:33 +0545 Subject: [PATCH 056/103] Add files via upload From 7faa6ea32aaa1791bd30a79e1552733c9f5ea02a Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:53:20 +0545 Subject: [PATCH 057/103] Add files via upload From ca892a1218767547796ce70b02892c57454a321f Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:54:18 +0545 Subject: [PATCH 058/103] Add files via upload From cb5bf8601a16101e43b1a51352b6ac678c531f2d Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:55:12 +0545 Subject: [PATCH 059/103] Add files via upload --- pyrogram/methods/utilities/start.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/methods/utilities/start.py b/pyrogram/methods/utilities/start.py index d8314da182..19a7eb7cf3 100644 --- a/pyrogram/methods/utilities/start.py +++ b/pyrogram/methods/utilities/start.py @@ -63,7 +63,7 @@ async def main(): if not await self.storage.is_bot() and self.takeout: self.takeout_id = (await self.invoke(raw.functions.account.InitTakeoutSession())).id - log.info("Takeout session %s initiated", self.takeout_id) + log.warning("Takeout session %s initiated", self.takeout_id) await self.invoke(raw.functions.updates.GetState()) except (Exception, KeyboardInterrupt): From b4f38dd7504a18f3e958c4616a17bb648bdfab9d Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:59:20 +0545 Subject: [PATCH 060/103] Add files via upload From 2fe37de3b6a0665a4b9b79f6c639fac4ec69bf92 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:59:59 +0545 Subject: [PATCH 061/103] Add files via upload --- pyrogram/session/internals/data_center.py | 6 ++---- pyrogram/session/internals/msg_id.py | 4 ++-- pyrogram/session/internals/seq_no.py | 12 ++++++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/pyrogram/session/internals/data_center.py b/pyrogram/session/internals/data_center.py index d314626352..4fce19aa24 100644 --- a/pyrogram/session/internals/data_center.py +++ b/pyrogram/session/internals/data_center.py @@ -31,8 +31,7 @@ class DataCenter: 2: "149.154.167.51", 3: "149.154.175.100", 4: "149.154.167.91", - 5: "91.108.56.130", - 203: "91.105.192.100" + 5: "91.108.56.130" } PROD_MEDIA = { @@ -51,8 +50,7 @@ class DataCenter: 2: "2001:67c:4e8:f002::a", 3: "2001:b28:f23d:f003::a", 4: "2001:67c:4e8:f004::a", - 5: "2001:b28:f23f:f005::a", - 203: "2a0a:f280:0203:000a:5000:0000:0000:0100" + 5: "2001:b28:f23f:f005::a" } PROD_IPV6_MEDIA = { diff --git a/pyrogram/session/internals/msg_id.py b/pyrogram/session/internals/msg_id.py index da2e264ff6..58e3087c51 100644 --- a/pyrogram/session/internals/msg_id.py +++ b/pyrogram/session/internals/msg_id.py @@ -27,9 +27,9 @@ class MsgId: offset = 0 def __new__(cls) -> int: - now = int(time.time()) + now = time.time() cls.offset = (cls.offset + 4) if now == cls.last_time else 0 - msg_id = (now * 2 ** 32) + cls.offset + msg_id = int(now * 2 ** 32) + cls.offset cls.last_time = now return msg_id diff --git a/pyrogram/session/internals/seq_no.py b/pyrogram/session/internals/seq_no.py index 79501d9863..0abc4a2f72 100644 --- a/pyrogram/session/internals/seq_no.py +++ b/pyrogram/session/internals/seq_no.py @@ -16,15 +16,19 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from threading import Lock + class SeqNo: def __init__(self): self.content_related_messages_sent = 0 + self.lock = Lock() def __call__(self, is_content_related: bool) -> int: - seq_no = (self.content_related_messages_sent * 2) + (1 if is_content_related else 0) + with self.lock: + seq_no = (self.content_related_messages_sent * 2) + (1 if is_content_related else 0) - if is_content_related: - self.content_related_messages_sent += 1 + if is_content_related: + self.content_related_messages_sent += 1 - return seq_no + return seq_no From b6db0b30c2ae032281fa51f9d51943ac29e4ee38 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:03:28 +0545 Subject: [PATCH 062/103] Add files via upload From 1d167307a940fdbba57803104a47ff4e099d6fda Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:04:00 +0545 Subject: [PATCH 063/103] Add files via upload From e2c83ff3d2b0befcbcd261cba038ef265bc34ff2 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:04:56 +0545 Subject: [PATCH 064/103] Add files via upload --- compiler/api/source/main_api.tl | 205 ++++++++------------------------ 1 file changed, 52 insertions(+), 153 deletions(-) diff --git a/compiler/api/source/main_api.tl b/compiler/api/source/main_api.tl index 7fd74edb3d..e4f1ac0e9c 100644 --- a/compiler/api/source/main_api.tl +++ b/compiler/api/source/main_api.tl @@ -36,15 +36,15 @@ inputFile#f52ff27f id:long parts:int name:string md5_checksum:string = InputFile inputFileBig#fa4f0bb5 id:long parts:int name:string = InputFile; inputMediaEmpty#9664f57f = InputMedia; -inputMediaUploadedPhoto#1e287d04 flags:# spoiler:flags.2?true file:InputFile stickers:flags.0?Vector ttl_seconds:flags.1?int = InputMedia; -inputMediaPhoto#b3ba0635 flags:# spoiler:flags.1?true id:InputPhoto ttl_seconds:flags.0?int = InputMedia; +inputMediaUploadedPhoto#1e287d04 flags:# file:InputFile stickers:flags.0?Vector ttl_seconds:flags.1?int = InputMedia; +inputMediaPhoto#b3ba0635 flags:# id:InputPhoto ttl_seconds:flags.0?int = InputMedia; inputMediaGeoPoint#f9c44144 geo_point:InputGeoPoint = InputMedia; inputMediaContact#f8ab7dfb phone_number:string first_name:string last_name:string vcard:string = InputMedia; -inputMediaUploadedDocument#5b38c6c1 flags:# nosound_video:flags.3?true force_file:flags.4?true spoiler:flags.5?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector stickers:flags.0?Vector ttl_seconds:flags.1?int = InputMedia; -inputMediaDocument#33473058 flags:# spoiler:flags.2?true id:InputDocument ttl_seconds:flags.0?int query:flags.1?string = InputMedia; +inputMediaUploadedDocument#5b38c6c1 flags:# nosound_video:flags.3?true force_file:flags.4?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector stickers:flags.0?Vector ttl_seconds:flags.1?int = InputMedia; +inputMediaDocument#33473058 flags:# id:InputDocument ttl_seconds:flags.0?int query:flags.1?string = InputMedia; inputMediaVenue#c13d1c11 geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string = InputMedia; -inputMediaPhotoExternal#e5bbfe1a flags:# spoiler:flags.1?true url:string ttl_seconds:flags.0?int = InputMedia; -inputMediaDocumentExternal#fb52dc99 flags:# spoiler:flags.1?true url:string ttl_seconds:flags.0?int = InputMedia; +inputMediaPhotoExternal#e5bbfe1a flags:# url:string ttl_seconds:flags.0?int = InputMedia; +inputMediaDocumentExternal#fb52dc99 flags:# url:string ttl_seconds:flags.0?int = InputMedia; inputMediaGame#d33f43f3 id:InputGame = InputMedia; inputMediaInvoice#8eb5a6d5 flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:string provider_data:DataJSON start_param:flags.1?string extended_media:flags.2?InputMedia = InputMedia; inputMediaGeoLive#971fa843 flags:# stopped:flags.0?true geo_point:InputGeoPoint heading:flags.2?int period:flags.1?int proximity_notification_radius:flags.3?int = InputMedia; @@ -52,7 +52,7 @@ inputMediaPoll#f94e5f1 flags:# poll:Poll correct_answers:flags.0?Vector s inputMediaDice#e66fbf7b emoticon:string = InputMedia; inputChatPhotoEmpty#1ca48f57 = InputChatPhoto; -inputChatUploadedPhoto#bdcdaec0 flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double video_emoji_markup:flags.3?VideoSize = InputChatPhoto; +inputChatUploadedPhoto#c642724e flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double = InputChatPhoto; inputChatPhoto#8953ad37 id:InputPhoto = InputChatPhoto; inputGeoPointEmpty#e4c123d6 = InputGeoPoint; @@ -88,10 +88,10 @@ storage.fileMp4#b3cea0e4 = storage.FileType; storage.fileWebp#1081464c = storage.FileType; userEmpty#d3bc4b7a id:long = User; -user#8f97c628 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true flags2:# bot_can_edit:flags2.1?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus usernames:flags2.0?Vector = User; +user#8f97c628 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true flags2:# id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus usernames:flags2.0?Vector = User; userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto; -userProfilePhoto#82d1f706 flags:# has_video:flags.0?true personal:flags.2?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto; +userProfilePhoto#82d1f706 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto; userStatusEmpty#9d05049 = UserStatus; userStatusOnline#edb93949 expires:int = UserStatus; @@ -106,8 +106,8 @@ chatForbidden#6592a1a7 id:long title:string = Chat; channel#83259464 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector = Chat; channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat; -chatFull#c9d31138 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector available_reactions:flags.18?ChatReactions = ChatFull; -channelFull#f2355507 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 flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true id:long 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:flags.23?ExportedChatInvite bot_info:Vector migrated_from_chat_id:flags.4?long 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?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions = ChatFull; +chatFull#c9d31138 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector available_reactions:flags.18?ChatReactions = ChatFull; +channelFull#f2355507 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 flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true id:long 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:flags.23?ExportedChatInvite bot_info:Vector migrated_from_chat_id:flags.4?long 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?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions = ChatFull; chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant; chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant; @@ -124,11 +124,11 @@ message#38116ee0 flags:# out:flags.1?true mentioned:flags.4?true media_unread:fl messageService#2b085862 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 ttl_period:flags.25?int = Message; messageMediaEmpty#3ded6320 = MessageMedia; -messageMediaPhoto#695150d7 flags:# spoiler:flags.3?true photo:flags.0?Photo ttl_seconds:flags.2?int = MessageMedia; +messageMediaPhoto#695150d7 flags:# photo:flags.0?Photo ttl_seconds:flags.2?int = MessageMedia; messageMediaGeo#56e0d474 geo:GeoPoint = MessageMedia; messageMediaContact#70322949 phone_number:string first_name:string last_name:string vcard:string user_id:long = MessageMedia; messageMediaUnsupported#9f84f49e = MessageMedia; -messageMediaDocument#9cb070d7 flags:# nopremium:flags.3?true spoiler:flags.4?true document:flags.0?Document ttl_seconds:flags.2?int = MessageMedia; +messageMediaDocument#9cb070d7 flags:# nopremium:flags.3?true document:flags.0?Document ttl_seconds:flags.2?int = MessageMedia; messageMediaWebPage#a32dd600 webpage:WebPage = MessageMedia; messageMediaVenue#2ec0533f geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string = MessageMedia; messageMediaGame#fdb19008 game:Game = MessageMedia; @@ -156,7 +156,7 @@ messageActionPaymentSent#96163f56 flags:# recurring_init:flags.2?true recurring_ messageActionPhoneCall#80e11a7f flags:# video:flags.2?true call_id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = MessageAction; messageActionScreenshotTaken#4792929b = MessageAction; messageActionCustomAction#fae69f56 message:string = MessageAction; -messageActionBotAllowed#c516d679 flags:# attach_menu:flags.1?true domain:flags.0?string app:flags.2?BotApp = MessageAction; +messageActionBotAllowed#abe9affe domain:string = MessageAction; messageActionSecureValuesSentMe#1b287353 values:Vector credentials:SecureCredentialsEncrypted = MessageAction; messageActionSecureValuesSent#d95c6154 types:Vector = MessageAction; messageActionContactSignUp#f3f25f76 = MessageAction; @@ -169,13 +169,9 @@ messageActionSetChatTheme#aa786345 emoticon:string = MessageAction; messageActionChatJoinedByRequest#ebbca3cb = MessageAction; messageActionWebViewDataSentMe#47dd8079 text:string data:string = MessageAction; messageActionWebViewDataSent#b4c38cb5 text:string = MessageAction; -messageActionGiftPremium#c83d6aec flags:# currency:string amount:long months:int crypto_currency:flags.0?string crypto_amount:flags.0?long = MessageAction; +messageActionGiftPremium#aba0f5c6 currency:string amount:long months:int = MessageAction; messageActionTopicCreate#d999256 flags:# title:string icon_color:int icon_emoji_id:flags.0?long = MessageAction; messageActionTopicEdit#c0944820 flags:# title:flags.0?string icon_emoji_id:flags.1?long closed:flags.2?Bool hidden:flags.3?Bool = MessageAction; -messageActionSuggestProfilePhoto#57de635e photo:Photo = MessageAction; -messageActionRequestedPeer#fe77345d button_id:int peer:Peer = MessageAction; -messageActionSetChatWallPaper#bc44a927 wallpaper:WallPaper = MessageAction; -messageActionSetSameChatWallPaper#c0787d6d wallpaper:WallPaper = MessageAction; dialog#d58a08c6 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int ttl_period:flags.5?int = Dialog; dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog; @@ -194,9 +190,8 @@ geoPointEmpty#1117dd5f = GeoPoint; geoPoint#b2a2f663 flags:# long:double lat:double access_hash:long accuracy_radius:flags.0?int = GeoPoint; auth.sentCode#5e002502 flags:# type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode; -auth.sentCodeSuccess#2390fe44 authorization:auth.Authorization = auth.SentCode; -auth.authorization#2ea2c0d4 flags:# setup_password_required:flags.1?true otherwise_relogin_days:flags.1?int tmp_sessions:flags.0?int future_auth_token:flags.2?bytes user:User = auth.Authorization; +auth.authorization#33fb7bb8 flags:# setup_password_required:flags.1?true otherwise_relogin_days:flags.1?int tmp_sessions:flags.0?int user:User = auth.Authorization; auth.authorizationSignUpRequired#44747e9a flags:# terms_of_service:flags.0?help.TermsOfService = auth.Authorization; auth.exportedAuthorization#b434e2b8 id:long bytes:bytes = auth.ExportedAuthorization; @@ -227,7 +222,7 @@ inputReportReasonFake#f5ddd6e7 = ReportReason; inputReportReasonIllegalDrugs#a8eb2be = ReportReason; inputReportReasonPersonalDetails#9ec7863d = ReportReason; -userFull#93eadb53 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights premium_gifts:flags.19?Vector wallpaper:flags.24?WallPaper = UserFull; +userFull#c4b1fc3f flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true id:long about:flags.1?string settings:PeerSettings profile_photo:flags.2?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights premium_gifts:flags.19?Vector = UserFull; contact#145ade0b user_id:long mutual:Bool = Contact; @@ -285,6 +280,7 @@ updateChatUserTyping#83487af0 chat_id:long from_id:Peer action:SendMessageAction updateChatParticipants#7761198 participants:ChatParticipants = Update; updateUserStatus#e5bdf8de user_id:long status:UserStatus = Update; updateUserName#a7848924 user_id:long first_name:string last_name:string usernames:Vector = Update; +updateUserPhoto#f227868c user_id:long date:int photo:UserProfilePhoto previous:Bool = Update; updateNewEncryptedMessage#12bcbd9a message:EncryptedMessage qts:int = Update; updateEncryptedChatTyping#1710f156 chat_id:int = Update; updateEncryption#b4a2e88d chat:EncryptedChat date:int = Update; @@ -365,7 +361,7 @@ updateGroupCallParticipants#f2ebdb4e call:InputGroupCall participants:Vector = Update; @@ -385,9 +381,6 @@ updateMoveStickerSetToTop#86fccf85 flags:# masks:flags.0?true emojis:flags.1?tru updateMessageExtendedMedia#5a73a98c peer:Peer msg_id:int extended_media:MessageExtendedMedia = Update; updateChannelPinnedTopic#192efbe3 flags:# pinned:flags.0?true channel_id:long topic_id:int = Update; updateChannelPinnedTopics#fe198602 flags:# channel_id:long order:flags.0?Vector = Update; -updateUser#20529438 user_id:long = Update; -updateAutoSaveSettings#ec05b097 = Update; -updateGroupInvitePrivacyForbidden#ccf08ad6 user_id:long = Update; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; @@ -414,7 +407,7 @@ upload.fileCdnRedirect#f18cda44 dc_id:int file_token:bytes encryption_key:bytes dcOption#18b7a10d flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true this_port_only:flags.5?true id:int ip_address:string port:int secret:flags.10?bytes = DcOption; -config#cc1a241e flags:# default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true force_try_ipv6:flags.14?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int channels_read_media_period:int tmp_sessions:flags.0?int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int base_lang_pack_version:flags.2?int reactions_default:flags.15?Reaction autologin_token:flags.16?string = Config; +config#232566ac flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true pfs_enabled:flags.13?true force_try_ipv6:flags.14?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int pinned_infolder_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int base_lang_pack_version:flags.2?int reactions_default:flags.15?Reaction = Config; nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc; @@ -532,7 +525,7 @@ documentAttributeVideo#ef02ce6 flags:# round_message:flags.0?true supports_strea documentAttributeAudio#9852f9c6 flags:# voice:flags.10?true duration:int title:flags.0?string performer:flags.1?string waveform:flags.2?bytes = DocumentAttribute; documentAttributeFilename#15590068 file_name:string = DocumentAttribute; documentAttributeHasStickers#9801d2f7 = DocumentAttribute; -documentAttributeCustomEmoji#fd149899 flags:# free:flags.0?true text_color:flags.1?true alt:string stickerset:InputStickerSet = DocumentAttribute; +documentAttributeCustomEmoji#fd149899 flags:# free:flags.0?true alt:string stickerset:InputStickerSet = DocumentAttribute; messages.stickersNotModified#f1749a22 = messages.Stickers; messages.stickers#30a6ec7e hash:long stickers:Vector = messages.Stickers; @@ -595,7 +588,7 @@ keyboardButtonUrl#258aff05 text:string url:string = KeyboardButton; keyboardButtonCallback#35bbdb6b flags:# requires_password:flags.0?true text:string data:bytes = KeyboardButton; keyboardButtonRequestPhone#b16a6c29 text:string = KeyboardButton; keyboardButtonRequestGeoLocation#fc796b3f text:string = KeyboardButton; -keyboardButtonSwitchInline#93b9fbb5 flags:# same_peer:flags.0?true text:string query:string peer_types:flags.1?Vector = KeyboardButton; +keyboardButtonSwitchInline#568a748 flags:# same_peer:flags.0?true text:string query:string = KeyboardButton; keyboardButtonGame#50f41ccf text:string = KeyboardButton; keyboardButtonBuy#afd93fbb text:string = KeyboardButton; keyboardButtonUrlAuth#10b78d29 flags:# text:string fwd_text:flags.0?string url:string button_id:int = KeyboardButton; @@ -605,13 +598,12 @@ inputKeyboardButtonUserProfile#e988037b text:string user_id:InputUser = Keyboard keyboardButtonUserProfile#308660c1 text:string user_id:long = KeyboardButton; keyboardButtonWebView#13767230 text:string url:string = KeyboardButton; keyboardButtonSimpleWebView#a0c0505c text:string url:string = KeyboardButton; -keyboardButtonRequestPeer#d0b468c text:string button_id:int peer_type:RequestPeerType = KeyboardButton; keyboardButtonRow#77608b83 buttons:Vector = KeyboardButtonRow; replyKeyboardHide#a03e5b85 flags:# selective:flags.2?true = ReplyMarkup; replyKeyboardForceReply#86b40b08 flags:# single_use:flags.1?true selective:flags.2?true placeholder:flags.3?string = ReplyMarkup; -replyKeyboardMarkup#85dd99d1 flags:# resize:flags.0?true single_use:flags.1?true selective:flags.2?true persistent:flags.4?true rows:Vector placeholder:flags.3?string = ReplyMarkup; +replyKeyboardMarkup#85dd99d1 flags:# resize:flags.0?true single_use:flags.1?true selective:flags.2?true rows:Vector placeholder:flags.3?string = ReplyMarkup; replyInlineMarkup#48a30254 rows:Vector = ReplyMarkup; messageEntityUnknown#bb92ba95 offset:int length:int = MessageEntity; @@ -700,7 +692,7 @@ botInlineMessageMediaInvoice#354a9b09 flags:# shipping_address_requested:flags.1 botInlineResult#11965f3a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?WebDocument content:flags.5?WebDocument send_message:BotInlineMessage = BotInlineResult; botInlineMediaResult#17db940b flags:# id:string type:string photo:flags.0?Photo document:flags.1?Document title:flags.2?string description:flags.3?string send_message:BotInlineMessage = BotInlineResult; -messages.botResults#e021f2f6 flags:# gallery:flags.0?true query_id:long next_offset:flags.1?string switch_pm:flags.2?InlineBotSwitchPM switch_webview:flags.3?InlineBotWebView results:Vector cache_time:int users:Vector = messages.BotResults; +messages.botResults#947ca848 flags:# gallery:flags.0?true query_id:long next_offset:flags.1?string switch_pm:flags.2?InlineBotSwitchPM results:Vector cache_time:int users:Vector = messages.BotResults; exportedMessageLink#5dab1af4 link:string html:string = ExportedMessageLink; @@ -717,10 +709,9 @@ auth.sentCodeTypeSms#c000bba2 length:int = auth.SentCodeType; auth.sentCodeTypeCall#5353e5a7 length:int = auth.SentCodeType; auth.sentCodeTypeFlashCall#ab03c6d9 pattern:string = auth.SentCodeType; auth.sentCodeTypeMissedCall#82006484 prefix:string length:int = auth.SentCodeType; -auth.sentCodeTypeEmailCode#f450f59b flags:# apple_signin_allowed:flags.0?true google_signin_allowed:flags.1?true email_pattern:string length:int reset_available_period:flags.3?int reset_pending_date:flags.4?int = auth.SentCodeType; +auth.sentCodeTypeEmailCode#5a159841 flags:# apple_signin_allowed:flags.0?true google_signin_allowed:flags.1?true email_pattern:string length:int next_phone_login_date:flags.2?int = auth.SentCodeType; auth.sentCodeTypeSetUpEmailRequired#a5491dea flags:# apple_signin_allowed:flags.0?true google_signin_allowed:flags.1?true = auth.SentCodeType; auth.sentCodeTypeFragmentSms#d9565c39 url:string length:int = auth.SentCodeType; -auth.sentCodeTypeFirebaseSms#e57b1432 flags:# nonce:flags.0?bytes receipt:flags.1?string push_timeout:flags.1?int length:int = auth.SentCodeType; messages.botCallbackAnswer#36585ea4 flags:# alert:flags.1?true has_url:flags.3?true native_ui:flags.4?true message:flags.0?string url:flags.2?string cache_time:int = messages.BotCallbackAnswer; @@ -767,7 +758,6 @@ messages.stickerSetInstallResultArchive#35e410a8 sets:Vector stickerSetCovered#6410a5d2 set:StickerSet cover:Document = StickerSetCovered; stickerSetMultiCovered#3407e51b set:StickerSet covers:Vector = StickerSetCovered; stickerSetFullCovered#40d13c0e set:StickerSet packs:Vector keywords:Vector documents:Vector = StickerSetCovered; -stickerSetNoCovered#77b15d1c set:StickerSet = StickerSetCovered; maskCoords#aed6dbb2 n:int x:double y:double zoom:double = MaskCoords; @@ -880,7 +870,7 @@ account.tmpPassword#db64fd34 tmp_password:bytes valid_until:int = account.TmpPas shippingOption#b6213cdf id:string title:string prices:Vector = ShippingOption; -inputStickerSetItem#32da9e9c flags:# document:InputDocument emoji:string mask_coords:flags.0?MaskCoords keywords:flags.1?string = InputStickerSetItem; +inputStickerSetItem#ffa0a496 flags:# document:InputDocument emoji:string mask_coords:flags.0?MaskCoords = InputStickerSetItem; inputPhoneCall#1e36fded id:long access_hash:long = InputPhoneCall; @@ -939,7 +929,7 @@ channelAdminLogEventActionDiscardGroupCall#db9f9140 call:InputGroupCall = Channe channelAdminLogEventActionParticipantMute#f92424d2 participant:GroupCallParticipant = ChannelAdminLogEventAction; channelAdminLogEventActionParticipantUnmute#e64429c0 participant:GroupCallParticipant = ChannelAdminLogEventAction; channelAdminLogEventActionToggleGroupCallSetting#56d6a247 join_muted:Bool = ChannelAdminLogEventAction; -channelAdminLogEventActionParticipantJoinByInvite#fe9fc158 flags:# via_chatlist:flags.0?true invite:ExportedChatInvite = ChannelAdminLogEventAction; +channelAdminLogEventActionParticipantJoinByInvite#5cdada77 invite:ExportedChatInvite = ChannelAdminLogEventAction; channelAdminLogEventActionExportedInviteDelete#5a50fca4 invite:ExportedChatInvite = ChannelAdminLogEventAction; channelAdminLogEventActionExportedInviteRevoke#410a134e invite:ExportedChatInvite = ChannelAdminLogEventAction; channelAdminLogEventActionExportedInviteEdit#e90ebb59 prev_invite:ExportedChatInvite new_invite:ExportedChatInvite = ChannelAdminLogEventAction; @@ -1121,7 +1111,7 @@ statsURL#47a971e0 url:string = StatsURL; chatAdminRights#5fb224d5 flags:# change_info:flags.0?true post_messages:flags.1?true edit_messages:flags.2?true delete_messages:flags.3?true ban_users:flags.4?true invite_users:flags.5?true pin_messages:flags.7?true add_admins:flags.9?true anonymous:flags.10?true manage_call:flags.11?true other:flags.12?true manage_topics:flags.13?true = ChatAdminRights; -chatBannedRights#9f120418 flags:# view_messages:flags.0?true send_messages:flags.1?true send_media:flags.2?true send_stickers:flags.3?true send_gifs:flags.4?true send_games:flags.5?true send_inline:flags.6?true embed_links:flags.7?true send_polls:flags.8?true change_info:flags.10?true invite_users:flags.15?true pin_messages:flags.17?true manage_topics:flags.18?true send_photos:flags.19?true send_videos:flags.20?true send_roundvideos:flags.21?true send_audios:flags.22?true send_voices:flags.23?true send_docs:flags.24?true send_plain:flags.25?true until_date:int = ChatBannedRights; +chatBannedRights#9f120418 flags:# view_messages:flags.0?true send_messages:flags.1?true send_media:flags.2?true send_stickers:flags.3?true send_gifs:flags.4?true send_games:flags.5?true send_inline:flags.6?true embed_links:flags.7?true send_polls:flags.8?true change_info:flags.10?true invite_users:flags.15?true pin_messages:flags.17?true manage_topics:flags.18?true until_date:int = ChatBannedRights; inputWallPaper#e630b979 id:long access_hash:long = InputWallPaper; inputWallPaperSlug#72091c80 slug:string = InputWallPaper; @@ -1130,7 +1120,7 @@ inputWallPaperNoFile#967a462e id:long = InputWallPaper; account.wallPapersNotModified#1c199183 = account.WallPapers; account.wallPapers#cdc3858c hash:long wallpapers:Vector = account.WallPapers; -codeSettings#ad253d78 flags:# allow_flashcall:flags.0?true current_number:flags.1?true allow_app_hash:flags.4?true allow_missed_call:flags.5?true allow_firebase:flags.7?true logout_tokens:flags.6?Vector token:flags.8?string app_sandbox:flags.8?Bool = CodeSettings; +codeSettings#8a6469c2 flags:# allow_flashcall:flags.0?true current_number:flags.1?true allow_app_hash:flags.4?true allow_missed_call:flags.5?true logout_tokens:flags.6?Vector = CodeSettings; wallPaperSettings#1dc1bca4 flags:# blur:flags.1?true motion:flags.2?true background_color:flags.0?int second_background_color:flags.4?int third_background_color:flags.5?int fourth_background_color:flags.6?int intensity:flags.3?int rotation:flags.4?int = WallPaperSettings; @@ -1207,7 +1197,6 @@ payments.bankCardData#3e24e573 title:string open_urls:Vector = dialogFilter#7438f7e8 flags:# contacts:flags.0?true non_contacts:flags.1?true groups:flags.2?true broadcasts:flags.3?true bots:flags.4?true exclude_muted:flags.11?true exclude_read:flags.12?true exclude_archived:flags.13?true id:int title:string emoticon:flags.25?string pinned_peers:Vector include_peers:Vector exclude_peers:Vector = DialogFilter; dialogFilterDefault#363293ae = DialogFilter; -dialogFilterChatlist#d64a04a8 flags:# has_my_invites:flags.26?true id:int title:string emoticon:flags.25?string pinned_peers:Vector include_peers:Vector = DialogFilter; dialogFilterSuggested#77744d4a filter:DialogFilter description:string = DialogFilterSuggested; @@ -1229,8 +1218,6 @@ help.promoDataEmpty#98f6ac75 expires:int = help.PromoData; help.promoData#8c39793f flags:# proxy:flags.0?true expires:int peer:Peer chats:Vector users:Vector psa_type:flags.1?string psa_message:flags.2?string = help.PromoData; videoSize#de33b094 flags:# type:string w:int h:int size:int video_start_ts:flags.0?double = VideoSize; -videoSizeEmojiMarkup#f85c413c emoji_id:long background_colors:Vector = VideoSize; -videoSizeStickerMarkup#da082fe stickerset:InputStickerSet sticker_id:long background_colors:Vector = VideoSize; statsGroupTopPoster#9d04af9b user_id:long messages:int avg_chars:int = StatsGroupTopPoster; @@ -1279,7 +1266,6 @@ inlineQueryPeerTypePM#833c0fac = InlineQueryPeerType; inlineQueryPeerTypeChat#d766c50a = InlineQueryPeerType; inlineQueryPeerTypeMegagroup#5ec4be43 = InlineQueryPeerType; inlineQueryPeerTypeBroadcast#6334ee9a = InlineQueryPeerType; -inlineQueryPeerTypeBotPM#e3b2d0c = InlineQueryPeerType; messages.historyImport#1662af0b id:long = messages.HistoryImport; @@ -1287,7 +1273,7 @@ messages.historyImportParsed#5e0fb7b9 flags:# pm:flags.0?true group:flags.1?true messages.affectedFoundMessages#ef8d3e6c pts:int pts_count:int offset:int messages:Vector = messages.AffectedFoundMessages; -chatInviteImporter#8c5adfd9 flags:# requested:flags.0?true via_chatlist:flags.3?true user_id:long date:int about:flags.2?string approved_by:flags.1?long = ChatInviteImporter; +chatInviteImporter#8c5adfd9 flags:# requested:flags.0?true user_id:long date:int about:flags.2?string approved_by:flags.1?long = ChatInviteImporter; messages.exportedChatInvites#bdc62dcc count:int invites:Vector users:Vector = messages.ExportedChatInvites; @@ -1324,7 +1310,7 @@ account.resetPasswordFailedWait#e3779861 retry_date:int = account.ResetPasswordR account.resetPasswordRequestedWait#e9effc7d until_date:int = account.ResetPasswordResult; account.resetPasswordOk#e926d63e = account.ResetPasswordResult; -sponsoredMessage#fc25b828 flags:# recommended:flags.5?true show_peer_photo:flags.6?true random_id:bytes from_id:flags.3?Peer chat_invite:flags.4?ChatInvite chat_invite_hash:flags.4?string channel_post:flags.2?int start_param:flags.0?string message:string entities:flags.1?Vector sponsor_info:flags.7?string additional_info:flags.8?string = SponsoredMessage; +sponsoredMessage#3a836df8 flags:# recommended:flags.5?true show_peer_photo:flags.6?true random_id:bytes from_id:flags.3?Peer chat_invite:flags.4?ChatInvite chat_invite_hash:flags.4?string channel_post:flags.2?int start_param:flags.0?string message:string entities:flags.1?Vector = SponsoredMessage; messages.sponsoredMessages#c9ee1d87 flags:# posts_between:flags.0?int messages:Vector chats:Vector users:Vector = messages.SponsoredMessages; messages.sponsoredMessagesEmpty#1839490f = messages.SponsoredMessages; @@ -1356,7 +1342,10 @@ availableReaction#c077ec01 flags:# inactive:flags.0?true premium:flags.2?true re messages.availableReactionsNotModified#9f071957 = messages.AvailableReactions; messages.availableReactions#768e3aad hash:int reactions:Vector = messages.AvailableReactions; -messagePeerReaction#8c79b63c flags:# big:flags.0?true unread:flags.1?true peer_id:Peer date:int reaction:Reaction = MessagePeerReaction; +messages.translateNoResult#67ca4737 = messages.TranslatedText; +messages.translateResultText#a214f7d0 text:string = messages.TranslatedText; + +messagePeerReaction#b156fe9c flags:# big:flags.0?true unread:flags.1?true peer_id:Peer reaction:Reaction = MessagePeerReaction; groupCallStreamChannel#80eb48af channel:int scale:int last_timestamp_ms:long = GroupCallStreamChannel; @@ -1368,7 +1357,7 @@ attachMenuBotIconColor#4576f3f0 name:string color:int = AttachMenuBotIconColor; attachMenuBotIcon#b2a7386b flags:# name:string icon:Document colors:flags.0?Vector = AttachMenuBotIcon; -attachMenuBot#c8aa2cd2 flags:# inactive:flags.0?true has_settings:flags.1?true request_write_access:flags.2?true bot_id:long short_name:string peer_types:Vector icons:Vector = AttachMenuBot; +attachMenuBot#c8aa2cd2 flags:# inactive:flags.0?true has_settings:flags.1?true bot_id:long short_name:string peer_types:Vector icons:Vector = AttachMenuBot; attachMenuBotsNotModified#f1d88a5c = AttachMenuBots; attachMenuBots#3c4301c0 hash:long bots:Vector users:Vector = AttachMenuBots; @@ -1411,7 +1400,7 @@ messages.transcribedAudio#93752c52 flags:# pending:flags.0?true transcription_id help.premiumPromo#5334759c status_text:string status_entities:Vector video_sections:Vector videos:Vector period_options:Vector users:Vector = help.PremiumPromo; -inputStorePaymentPremiumSubscription#a6751e66 flags:# restore:flags.0?true upgrade:flags.1?true = InputStorePaymentPurpose; +inputStorePaymentPremiumSubscription#a6751e66 flags:# restore:flags.0?true = InputStorePaymentPurpose; inputStorePaymentGiftPremium#616f7fe8 user_id:InputUser currency:string amount:long = InputStorePaymentPurpose; premiumGiftOption#74c34319 flags:# months:int currency:string amount:long bot_url:string store_product:flags.0?string = PremiumGiftOption; @@ -1447,7 +1436,7 @@ emailVerificationApple#96d074fd token:string = EmailVerification; account.emailVerified#2b96cd1b email:string = account.EmailVerified; account.emailVerifiedLogin#e1bb0d61 email:string sent_code:auth.SentCode = account.EmailVerified; -premiumSubscriptionOption#5f2d1df2 flags:# current:flags.1?true can_purchase_upgrade:flags.2?true transaction:flags.3?string months:int currency:string amount:long bot_url:string store_product:flags.0?string = PremiumSubscriptionOption; +premiumSubscriptionOption#b6f11ebe flags:# current:flags.1?true can_purchase_upgrade:flags.2?true months:int currency:string amount:long bot_url:string store_product:flags.0?string = PremiumSubscriptionOption; sendAsPeer#b81c7034 flags:# premium_required:flags.0?true peer:Peer = SendAsPeer; @@ -1467,60 +1456,6 @@ defaultHistoryTTL#43b46b20 period:int = DefaultHistoryTTL; exportedContactToken#41bf109b url:string expires:int = ExportedContactToken; -requestPeerTypeUser#5f3b8a00 flags:# bot:flags.0?Bool premium:flags.1?Bool = RequestPeerType; -requestPeerTypeChat#c9f06e1b flags:# creator:flags.0?true bot_participant:flags.5?true has_username:flags.3?Bool forum:flags.4?Bool user_admin_rights:flags.1?ChatAdminRights bot_admin_rights:flags.2?ChatAdminRights = RequestPeerType; -requestPeerTypeBroadcast#339bef6c flags:# creator:flags.0?true has_username:flags.3?Bool user_admin_rights:flags.1?ChatAdminRights bot_admin_rights:flags.2?ChatAdminRights = RequestPeerType; - -emojiListNotModified#481eadfa = EmojiList; -emojiList#7a1e11d1 hash:long document_id:Vector = EmojiList; - -emojiGroup#7a9abda9 title:string icon_emoji_id:long emoticons:Vector = EmojiGroup; - -messages.emojiGroupsNotModified#6fb4ad87 = messages.EmojiGroups; -messages.emojiGroups#881fb94b hash:int groups:Vector = messages.EmojiGroups; - -textWithEntities#751f3146 text:string entities:Vector = TextWithEntities; - -messages.translateResult#33db32f8 result:Vector = messages.TranslatedText; - -autoSaveSettings#c84834ce flags:# photos:flags.0?true videos:flags.1?true video_max_size:flags.2?long = AutoSaveSettings; - -autoSaveException#81602d47 peer:Peer settings:AutoSaveSettings = AutoSaveException; - -account.autoSaveSettings#4c3e069d users_settings:AutoSaveSettings chats_settings:AutoSaveSettings broadcasts_settings:AutoSaveSettings exceptions:Vector chats:Vector users:Vector = account.AutoSaveSettings; - -help.appConfigNotModified#7cde641d = help.AppConfig; -help.appConfig#dd18782e hash:int config:JSONValue = help.AppConfig; - -inputBotAppID#a920bd7a id:long access_hash:long = InputBotApp; -inputBotAppShortName#908c0407 bot_id:InputUser short_name:string = InputBotApp; - -botAppNotModified#5da674b7 = BotApp; -botApp#95fcd1d6 flags:# id:long access_hash:long short_name:string title:string description:string photo:Photo document:flags.0?Document hash:long = BotApp; - -messages.botApp#eb50adf5 flags:# inactive:flags.0?true request_write_access:flags.1?true app:BotApp = messages.BotApp; - -appWebViewResultUrl#3c1b4f0d url:string = AppWebViewResult; - -inlineBotWebView#b57295d5 text:string url:string = InlineBotWebView; - -readParticipantDate#4a4ff172 user_id:long date:int = ReadParticipantDate; - -inputChatlistDialogFilter#f3e0da33 filter_id:int = InputChatlist; - -exportedChatlistInvite#c5181ac flags:# title:string url:string peers:Vector = ExportedChatlistInvite; - -chatlists.exportedChatlistInvite#10e6e3a6 filter:DialogFilter invite:ExportedChatlistInvite = chatlists.ExportedChatlistInvite; - -chatlists.exportedInvites#10ab6dc7 invites:Vector chats:Vector users:Vector = chatlists.ExportedInvites; - -chatlists.chatlistInviteAlready#fa87f659 filter_id:int missing_peers:Vector already_peers:Vector chats:Vector users:Vector = chatlists.ChatlistInvite; -chatlists.chatlistInvite#1dcd839d flags:# title:string emoticon:flags.0?string peers:Vector chats:Vector users:Vector = chatlists.ChatlistInvite; - -chatlists.chatlistUpdates#93bd878d missing_peers:Vector chats:Vector users:Vector = chatlists.ChatlistUpdates; - -bots.botInfo#e8a775b0 name:string about:string description:string = bots.BotInfo; - ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -1551,8 +1486,6 @@ auth.importLoginToken#95ac5ce4 token:bytes = auth.LoginToken; auth.acceptLoginToken#e894ad4d token:bytes = Authorization; auth.checkRecoveryPassword#d36bf79 code:string = Bool; auth.importWebTokenAuthorization#2db873a9 api_id:int api_hash:string web_auth_token:string = auth.Authorization; -auth.requestFirebaseSms#89464b50 flags:# phone_number:string phone_code_hash:string safety_net_token:flags.0?string ios_push_secret:flags.1?string = Bool; -auth.resetLoginEmail#7e960193 phone_number:string phone_code_hash:string = auth.SentCode; account.registerDevice#ec86017a flags:# no_muted:flags.0?true token_type:int token:string app_sandbox:Bool secret:bytes other_uids:Vector = Bool; account.unregisterDevice#6a0d3206 token_type:int token:string other_uids:Vector = Bool; @@ -1603,7 +1536,7 @@ account.getContactSignUpNotification#9f07c728 = Bool; account.setContactSignUpNotification#cff43f61 silent:Bool = Bool; account.getNotifyExceptions#53577479 flags:# compare_sound:flags.1?true peer:flags.0?InputNotifyPeer = Updates; account.getWallPaper#fc8ddbea wallpaper:InputWallPaper = WallPaper; -account.uploadWallPaper#e39a8f03 flags:# for_chat:flags.0?true file:InputFile mime_type:string settings:WallPaperSettings = WallPaper; +account.uploadWallPaper#dd853661 file:InputFile mime_type:string settings:WallPaperSettings = WallPaper; account.saveWallPaper#6c5a5b37 wallpaper:InputWallPaper unsave:Bool settings:WallPaperSettings = Bool; account.installWallPaper#feed5769 wallpaper:InputWallPaper settings:WallPaperSettings = Bool; account.resetWallPapers#bb3b9804 = Bool; @@ -1636,11 +1569,6 @@ account.getRecentEmojiStatuses#f578105 hash:long = account.EmojiStatuses; account.clearRecentEmojiStatuses#18201aae = Bool; account.reorderUsernames#ef500eab order:Vector = Bool; account.toggleUsername#58d6b376 username:string active:Bool = Bool; -account.getDefaultProfilePhotoEmojis#e2750328 hash:long = EmojiList; -account.getDefaultGroupPhotoEmojis#915860ae hash:long = EmojiList; -account.getAutoSaveSettings#adcbbcda = account.AutoSaveSettings; -account.saveAutoSaveSettings#d69b8361 flags:# users:flags.0?true chats:flags.1?true broadcasts:flags.2?true peer:flags.3?InputPeer settings:AutoSaveSettings = Bool; -account.deleteAutoSaveExceptions#53bc0020 = Bool; users.getUsers#d91a548 id:Vector = Vector; users.getFullUser#b60f5918 id:InputUser = users.UserFull; @@ -1723,7 +1651,7 @@ messages.getDocumentByHash#b1f2061f sha256:bytes size:long mime_type:string = Do messages.getSavedGifs#5cf09635 hash:long = messages.SavedGifs; messages.saveGif#327a30cb id:InputDocument unsave:Bool = Bool; messages.getInlineBotResults#514e999d flags:# bot:InputUser peer:InputPeer geo_point:flags.0?InputGeoPoint query:string offset:string = messages.BotResults; -messages.setInlineBotResults#bb12a419 flags:# gallery:flags.0?true private:flags.1?true query_id:long results:Vector cache_time:int next_offset:flags.2?string switch_pm:flags.3?InlineBotSwitchPM switch_webview:flags.4?InlineBotWebView = Bool; +messages.setInlineBotResults#eb5ea206 flags:# gallery:flags.0?true private:flags.1?true query_id:long results:Vector cache_time:int next_offset:flags.2?string switch_pm:flags.3?InlineBotSwitchPM = Bool; messages.sendInlineBotResult#d3fbdccb flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true hide_via:flags.11?true peer:InputPeer reply_to_msg_id:flags.0?int top_msg_id:flags.9?int random_id:long query_id:long id:string schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; messages.getMessageEditData#fda68d36 peer:InputPeer id:int = messages.MessageEditData; messages.editMessage#48f71778 flags:# no_webpage:flags.1?true peer:InputPeer id:int message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector schedule_date:flags.15?int = Updates; @@ -1812,7 +1740,7 @@ messages.getChatInviteImporters#df04dd4e flags:# requested:flags.0?true peer:Inp messages.setHistoryTTL#b80e5fe4 peer:InputPeer period:int = Updates; messages.checkHistoryImportPeer#5dc60f03 peer:InputPeer = messages.CheckedHistoryImportPeer; messages.setChatTheme#e63be13f peer:InputPeer emoticon:string = Updates; -messages.getMessageReadParticipants#31c1c44f peer:InputPeer msg_id:int = Vector; +messages.getMessageReadParticipants#2c6f97b7 peer:InputPeer msg_id:int = Vector; messages.getSearchResultsCalendar#49f0bde9 peer:InputPeer filter:MessagesFilter offset_id:int offset_date:int = messages.SearchResultsCalendar; messages.getSearchResultsPositions#6e9583a3 peer:InputPeer filter:MessagesFilter offset_id:int limit:int = messages.SearchResultsPositions; messages.hideChatJoinRequest#7fe7e815 flags:# approved:flags.0?true peer:InputPeer user_id:InputUser = Updates; @@ -1825,16 +1753,16 @@ messages.getMessageReactionsList#461b3f48 flags:# peer:InputPeer id:int reaction messages.setChatAvailableReactions#feb16771 peer:InputPeer available_reactions:ChatReactions = Updates; messages.getAvailableReactions#18dea0ac hash:int = messages.AvailableReactions; messages.setDefaultReaction#4f47a016 reaction:Reaction = Bool; -messages.translateText#63183030 flags:# peer:flags.0?InputPeer id:flags.0?Vector text:flags.1?Vector to_lang:string = messages.TranslatedText; +messages.translateText#24ce6dee flags:# peer:flags.0?InputPeer msg_id:flags.0?int text:flags.1?string from_lang:flags.2?string to_lang:string = messages.TranslatedText; messages.getUnreadReactions#3223495b flags:# peer:InputPeer top_msg_id:flags.0?int offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages; messages.readReactions#54aa7f8e flags:# peer:InputPeer top_msg_id:flags.0?int = messages.AffectedHistory; messages.searchSentMedia#107e31a0 q:string filter:MessagesFilter limit:int = messages.Messages; messages.getAttachMenuBots#16fcc2cb hash:long = AttachMenuBots; messages.getAttachMenuBot#77216192 bot:InputUser = AttachMenuBotsBot; -messages.toggleBotInAttachMenu#69f59d69 flags:# write_allowed:flags.0?true bot:InputUser enabled:Bool = Bool; +messages.toggleBotInAttachMenu#1aee33af bot:InputUser enabled:Bool = Bool; messages.requestWebView#178b480b flags:# from_bot_menu:flags.4?true silent:flags.5?true peer:InputPeer bot:InputUser url:flags.1?string start_param:flags.3?string theme_params:flags.2?DataJSON platform:string reply_to_msg_id:flags.0?int top_msg_id:flags.9?int send_as:flags.13?InputPeer = WebViewResult; messages.prolongWebView#7ff34309 flags:# silent:flags.5?true peer:InputPeer bot:InputUser query_id:long reply_to_msg_id:flags.0?int top_msg_id:flags.9?int send_as:flags.13?InputPeer = Bool; -messages.requestSimpleWebView#299bec8e flags:# from_switch_webview:flags.1?true bot:InputUser url:string theme_params:flags.0?DataJSON platform:string = SimpleWebViewResult; +messages.requestSimpleWebView#299bec8e flags:# bot:InputUser url:string theme_params:flags.0?DataJSON platform:string = SimpleWebViewResult; messages.sendWebViewResultMessage#a4314f5 bot_query_id:string result:InputBotInlineResult = WebViewMessageSent; messages.sendWebViewData#dc0242c8 bot:InputUser random_id:long button_text:string data:string = Updates; messages.transcribeAudio#269e9a49 peer:InputPeer msg_id:int = messages.TranscribedAudio; @@ -1849,25 +1777,15 @@ messages.clearRecentReactions#9dfeefb4 = Bool; messages.getExtendedMedia#84f80814 peer:InputPeer id:Vector = Updates; messages.setDefaultHistoryTTL#9eb51445 period:int = Bool; messages.getDefaultHistoryTTL#658b7188 = DefaultHistoryTTL; -messages.sendBotRequestedPeer#fe38d01b peer:InputPeer msg_id:int button_id:int requested_peer:InputPeer = Updates; -messages.getEmojiGroups#7488ce5b hash:int = messages.EmojiGroups; -messages.getEmojiStatusGroups#2ecd56cd hash:int = messages.EmojiGroups; -messages.getEmojiProfilePhotoGroups#21a548f3 hash:int = messages.EmojiGroups; -messages.searchCustomEmoji#2c11c0d7 emoticon:string hash:long = EmojiList; -messages.togglePeerTranslations#e47cb579 flags:# disabled:flags.0?true peer:InputPeer = Bool; -messages.getBotApp#34fdc5c3 app:InputBotApp hash:long = messages.BotApp; -messages.requestAppWebView#8c5a3b3c flags:# write_allowed:flags.0?true peer:InputPeer app:InputBotApp start_param:flags.1?string theme_params:flags.2?DataJSON platform:string = AppWebViewResult; -messages.setChatWallPaper#8ffacae1 flags:# peer:InputPeer wallpaper:flags.0?InputWallPaper settings:flags.2?WallPaperSettings id:flags.1?int = Updates; updates.getState#edd4882a = updates.State; updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference; updates.getChannelDifference#3173d78 flags:# force:flags.0?true channel:InputChannel filter:ChannelMessagesFilter pts:int limit:int = updates.ChannelDifference; -photos.updateProfilePhoto#9e82039 flags:# fallback:flags.0?true bot:flags.1?InputUser id:InputPhoto = photos.Photo; -photos.uploadProfilePhoto#388a3b5 flags:# fallback:flags.3?true bot:flags.5?InputUser file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double video_emoji_markup:flags.4?VideoSize = photos.Photo; +photos.updateProfilePhoto#72d4742c id:InputPhoto = photos.Photo; +photos.uploadProfilePhoto#89f30f69 flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double = photos.Photo; photos.deletePhotos#87cf7f2f id:Vector = Vector; photos.getUserPhotos#91cd32a8 user_id:InputUser offset:int max_id:long limit:int = photos.Photos; -photos.uploadContactProfilePhoto#e14c4a71 flags:# suggest:flags.3?true save:flags.4?true user_id:InputUser file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double video_emoji_markup:flags.5?VideoSize = photos.Photo; upload.saveFilePart#b304a621 file_id:long file_part:int bytes:bytes = Bool; upload.getFile#be5335be flags:# precise:flags.0?true cdn_supported:flags.1?true location:InputFileLocation offset:long limit:int = upload.File; @@ -1890,7 +1808,7 @@ help.getRecentMeUrls#3dc0f114 referer:string = help.RecentMeUrls; help.getTermsOfServiceUpdate#2ca51fd1 = help.TermsOfServiceUpdate; help.acceptTermsOfService#ee72f79a id:DataJSON = Bool; help.getDeepLinkInfo#3fedc75f path:string = help.DeepLinkInfo; -help.getAppConfig#61e3f854 hash:int = help.AppConfig; +help.getAppConfig#98914110 = JSONValue; help.saveAppLog#6f02f748 events:Vector = Bool; help.getPassportConfig#c661ad08 hash:int = help.PassportConfig; help.getSupportName#d360e72c = help.SupportName; @@ -1910,7 +1828,7 @@ channels.getParticipants#77ced9d0 channel:InputChannel filter:ChannelParticipant channels.getParticipant#a0ab6cc6 channel:InputChannel participant:InputPeer = channels.ChannelParticipant; channels.getChannels#a7f6bbb id:Vector = messages.Chats; channels.getFullChannel#8736a09 channel:InputChannel = messages.ChatFull; -channels.createChannel#91006707 flags:# broadcast:flags.0?true megagroup:flags.1?true for_import:flags.3?true forum:flags.5?true title:string about:string geo_point:flags.2?InputGeoPoint address:flags.2?string ttl_period:flags.4?int = Updates; +channels.createChannel#91006707 flags:# broadcast:flags.0?true megagroup:flags.1?true for_import:flags.3?true title:string about:string geo_point:flags.2?InputGeoPoint address:flags.2?string ttl_period:flags.4?int = Updates; channels.editAdmin#d33c8902 channel:InputChannel user_id:InputUser admin_rights:ChatAdminRights rank:string = Updates; channels.editTitle#566decd0 channel:InputChannel title:string = Updates; channels.editPhoto#f12e57c9 channel:InputChannel photo:InputChatPhoto = Updates; @@ -1956,7 +1874,6 @@ channels.deleteTopicHistory#34435f2d channel:InputChannel top_msg_id:int = messa channels.reorderPinnedForumTopics#2950a18f flags:# force:flags.0?true channel:InputChannel order:Vector = Updates; channels.toggleAntiSpam#68f3e4eb channel:InputChannel enabled:Bool = Updates; channels.reportAntiSpamFalsePositive#a850a693 channel:InputChannel msg_id:int = Bool; -channels.toggleParticipantsHidden#6a6e7854 channel:InputChannel enabled:Bool = Updates; bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON; bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool; @@ -1967,10 +1884,6 @@ bots.setBotMenuButton#4504d54f user_id:InputUser button:BotMenuButton = Bool; bots.getBotMenuButton#9c60eb28 user_id:InputUser = BotMenuButton; bots.setBotBroadcastDefaultAdminRights#788464e1 admin_rights:ChatAdminRights = Bool; bots.setBotGroupDefaultAdminRights#925ec9ea admin_rights:ChatAdminRights = Bool; -bots.setBotInfo#10cf3123 flags:# bot:flags.2?InputUser lang_code:string name:flags.3?string about:flags.0?string description:flags.1?string = Bool; -bots.getBotInfo#dcd914fd flags:# bot:flags.0?InputUser lang_code:string = bots.BotInfo; -bots.reorderUsernames#9709b1c2 bot:InputUser order:Vector = Bool; -bots.toggleUsername#53ca973 bot:InputUser username:string active:Bool = Bool; payments.getPaymentForm#37148dbb flags:# invoice:InputInvoice theme_params:flags.0?DataJSON = payments.PaymentForm; payments.getPaymentReceipt#2478d1cc peer:InputPeer msg_id:int = payments.PaymentReceipt; @@ -1984,16 +1897,13 @@ payments.assignAppStoreTransaction#80ed747d receipt:bytes purpose:InputStorePaym payments.assignPlayMarketTransaction#dffd50d3 receipt:DataJSON purpose:InputStorePaymentPurpose = Updates; payments.canPurchasePremium#9fc19eb6 purpose:InputStorePaymentPurpose = Bool; -stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true animated:flags.1?true videos:flags.4?true emojis:flags.5?true text_color:flags.6?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector software:flags.3?string = messages.StickerSet; +stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true animated:flags.1?true videos:flags.4?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector software:flags.3?string = messages.StickerSet; stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet; stickers.changeStickerPosition#ffb6d4ca sticker:InputDocument position:int = messages.StickerSet; stickers.addStickerToSet#8653febe stickerset:InputStickerSet sticker:InputStickerSetItem = messages.StickerSet; -stickers.setStickerSetThumb#a76a5392 flags:# stickerset:InputStickerSet thumb:flags.0?InputDocument thumb_document_id:flags.1?long = messages.StickerSet; +stickers.setStickerSetThumb#9a364e30 stickerset:InputStickerSet thumb:InputDocument = messages.StickerSet; stickers.checkShortName#284b3639 short_name:string = Bool; stickers.suggestShortName#4dafc503 title:string = stickers.SuggestedShortName; -stickers.changeSticker#f5537ebc flags:# sticker:InputDocument emoji:flags.0?string mask_coords:flags.1?MaskCoords keywords:flags.2?string = messages.StickerSet; -stickers.renameStickerSet#124b1c00 stickerset:InputStickerSet title:string = messages.StickerSet; -stickers.deleteStickerSet#87704394 stickerset:InputStickerSet = Bool; phone.getCallConfig#55451fa9 = DataJSON; phone.requestCall#42ff96ed flags:# video:flags.0?true user_id:InputUser random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall; @@ -2034,6 +1944,7 @@ langpack.getLanguages#42c6978f lang_pack:string = Vector; langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLanguage; folders.editPeerFolders#6847d0ab folder_peers:Vector = Updates; +folders.deleteFolder#1c295881 folder_id:int = Updates; stats.getBroadcastStats#ab42441a flags:# dark:flags.0?true channel:InputChannel = stats.BroadcastStats; stats.loadAsyncGraph#621d5fa0 flags:# token:string x:flags.0?long = StatsGraph; @@ -2041,16 +1952,4 @@ stats.getMegagroupStats#dcdf8607 flags:# dark:flags.0?true channel:InputChannel stats.getMessagePublicForwards#5630281b channel:InputChannel msg_id:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages; stats.getMessageStats#b6e0a3f5 flags:# dark:flags.0?true channel:InputChannel msg_id:int = stats.MessageStats; -chatlists.exportChatlistInvite#8472478e chatlist:InputChatlist title:string peers:Vector = chatlists.ExportedChatlistInvite; -chatlists.deleteExportedInvite#719c5c5e chatlist:InputChatlist slug:string = Bool; -chatlists.editExportedInvite#653db63d flags:# chatlist:InputChatlist slug:string title:flags.1?string peers:flags.2?Vector = ExportedChatlistInvite; -chatlists.getExportedInvites#ce03da83 chatlist:InputChatlist = chatlists.ExportedInvites; -chatlists.checkChatlistInvite#41c10fff slug:string = chatlists.ChatlistInvite; -chatlists.joinChatlistInvite#a6b1e39a slug:string peers:Vector = Updates; -chatlists.getChatlistUpdates#89419521 chatlist:InputChatlist = chatlists.ChatlistUpdates; -chatlists.joinChatlistUpdates#e089f8f5 chatlist:InputChatlist peers:Vector = Updates; -chatlists.hideChatlistUpdates#66e486fb chatlist:InputChatlist = Bool; -chatlists.getLeaveChatlistSuggestions#fdbcd714 chatlist:InputChatlist = Vector; -chatlists.leaveChatlist#74fae13a chatlist:InputChatlist peers:Vector = Updates; - -// LAYER 158 +// LAYER 150 \ No newline at end of file From 0bf29381393f64be8ca186472707e3bbdfab54a1 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:05:32 +0545 Subject: [PATCH 065/103] Add files via upload From 7fb8efc231763620057bd4950c0bbc71009c172e Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:06:08 +0545 Subject: [PATCH 066/103] Add files via upload From 7d2946a64813f41d74d7e729034538f42f65b5ce Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:06:56 +0545 Subject: [PATCH 067/103] Add files via upload --- compiler/errors/source/400_BAD_REQUEST.tsv | 9 +++------ compiler/errors/source/403_FORBIDDEN.tsv | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/errors/source/400_BAD_REQUEST.tsv b/compiler/errors/source/400_BAD_REQUEST.tsv index 08ecb7a676..1ad4c6a593 100644 --- a/compiler/errors/source/400_BAD_REQUEST.tsv +++ b/compiler/errors/source/400_BAD_REQUEST.tsv @@ -28,7 +28,6 @@ BOT_INLINE_DISABLED The inline feature of the bot is disabled BOT_INVALID This is not a valid bot BOT_METHOD_INVALID The method can't be used by bots BOT_MISSING This method can only be run by a bot -BOT_ONESIDE_NOT_AVAIL Bots can't pin messages for one side only in private chats BOT_PAYMENTS_DISABLED This method can only be run by a bot BOT_POLLS_DISABLED Sending polls by bots has been disabled BOT_RESPONSE_TIMEOUT The bot did not answer to the callback query in time @@ -39,7 +38,6 @@ BROADCAST_REQUIRED The request can only be used with a channel BUTTON_DATA_INVALID The button callback data is invalid or too large BUTTON_TYPE_INVALID The type of one of the buttons you provided is invalid BUTTON_URL_INVALID The button url is invalid -BUTTON_USER_PRIVACY_RESTRICTED The privacy settings of the user specified in a keyboard button do not allow creating such button CALL_ALREADY_ACCEPTED The call is already accepted CALL_ALREADY_DECLINED The call is already declined CALL_PEER_INVALID The provided call peer object is invalid @@ -102,7 +100,6 @@ ENCRYPTION_ALREADY_DECLINED The secret chat is already declined ENCRYPTION_DECLINED The secret chat was declined ENCRYPTION_ID_INVALID The provided secret chat id is invalid ENTITIES_TOO_LONG The entity provided contains data that is too long, or you passed too many entities to this message -ENTITY_BOUNDS_INVALID The message entity bounds are invalid ENTITY_MENTION_USER_INVALID The mentioned entity is not an user ERROR_TEXT_EMPTY The provided error message is empty EXPIRE_DATE_INVALID The expiration date is invalid @@ -156,7 +153,6 @@ INPUT_USER_DEACTIVATED The target user has been deleted/deactivated INVITE_HASH_EMPTY The invite hash is empty INVITE_HASH_EXPIRED The chat invite link is no longer valid INVITE_HASH_INVALID The invite link hash is invalid -INVITE_REQUEST_SENT The request to join this chat or channel has been successfully sent INVITE_REVOKED_MISSING The action required a chat invite link to be revoked first LANG_PACK_INVALID The provided language pack is invalid LASTNAME_INVALID The last name is invalid @@ -300,8 +296,8 @@ STICKER_INVALID The provided sticker is invalid STICKER_PNG_DIMENSIONS The sticker png dimensions are invalid STICKER_PNG_NOPNG Stickers must be png files but the provided image was not a png STICKER_TGS_NOTGS A tgs sticker file was expected, but something else was provided -STICKER_THUMB_PNG_NOPNG A png sticker thumbnail file was expected, but something else was provided STICKER_VIDEO_NOWEBM A webm video file was expected, but something else was provided +STICKER_THUMB_PNG_NOPNG A png sticker thumbnail file was expected, but something else was provided TAKEOUT_INVALID The takeout id is invalid TAKEOUT_REQUIRED The method must be invoked inside a takeout session TEMP_AUTH_KEY_EMPTY The temporary auth key provided is empty @@ -357,4 +353,5 @@ WEBDOCUMENT_URL_EMPTY The web document URL is empty WEBDOCUMENT_URL_INVALID The web document URL is invalid WEBPAGE_CURL_FAILED Telegram server could not fetch the provided URL WEBPAGE_MEDIA_EMPTY The URL doesn't contain any valid media -YOU_BLOCKED_USER You blocked this user \ No newline at end of file +YOU_BLOCKED_USER You blocked this user +ENTITY_BOUNDS_INVALID The message entity bounds are invalid diff --git a/compiler/errors/source/403_FORBIDDEN.tsv b/compiler/errors/source/403_FORBIDDEN.tsv index 027f2e852e..69777cd249 100644 --- a/compiler/errors/source/403_FORBIDDEN.tsv +++ b/compiler/errors/source/403_FORBIDDEN.tsv @@ -15,7 +15,6 @@ INLINE_BOT_REQUIRED The action must be performed through an inline bot callback MESSAGE_AUTHOR_REQUIRED You are not the author of this message MESSAGE_DELETE_FORBIDDEN You don't have rights to delete messages in this chat, most likely because you are not the author of them POLL_VOTE_REQUIRED Cast a vote in the poll before calling this method -PREMIUM_ACCOUNT_REQUIRED This action requires a premium account RIGHT_FORBIDDEN You don't have enough rights for this action, or you tried to set one or more admin rights that can't be applied to this kind of chat (channel or supergroup) SENSITIVE_CHANGE_FORBIDDEN Your sensitive content settings can't be changed at this time TAKEOUT_REQUIRED The method must be invoked inside a takeout session @@ -25,4 +24,5 @@ USER_INVALID The provided user is invalid USER_IS_BLOCKED The user is blocked USER_NOT_MUTUAL_CONTACT The provided user is not a mutual contact USER_PRIVACY_RESTRICTED The user's privacy settings is preventing you to perform this action -USER_RESTRICTED You are limited/restricted. You can't perform this action \ No newline at end of file +USER_RESTRICTED You are limited/restricted. You can't perform this action +PREMIUM_ACCOUNT_REQUIRED This action requires a premium account \ No newline at end of file From 97d0fb8c34f0f1a1ec31d425bf9028346e58e1c6 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:07:30 +0545 Subject: [PATCH 068/103] Add files via upload From c4193c2fc8f8d1f2cc694e2697f1d8d0ca45c9bb Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:08:15 +0545 Subject: [PATCH 069/103] Add files via upload --- pyrogram/__init__.py | 2 +- pyrogram/utils.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py index 7ab55c3397..a1accaf2ee 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__ = "2.1.1" +__version__ = "2.0.83" __license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)" __copyright__ = "Copyright (C) 2017-present Dan " diff --git a/pyrogram/utils.py b/pyrogram/utils.py index f2daba2ba2..f7fe59706d 100644 --- a/pyrogram/utils.py +++ b/pyrogram/utils.py @@ -198,8 +198,7 @@ def unpack_inline_message_id(inline_message_id: str) -> "raw.base.InputBotInline ) -MIN_CHANNEL_ID_OLD = -1002147483647 -MIN_CHANNEL_ID = -1009999999999 +MIN_CHANNEL_ID = -1002147483647 MAX_CHANNEL_ID = -1000000000000 MIN_CHAT_ID = -2147483647 MAX_USER_ID_OLD = 2147483647 From ff5c18507408fc318a438b43b0e0fc8546f63efa Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:09:04 +0545 Subject: [PATCH 070/103] Add files via upload --- pyrogram/connection/connection.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pyrogram/connection/connection.py b/pyrogram/connection/connection.py index 69cbb813a1..051d3c526b 100644 --- a/pyrogram/connection/connection.py +++ b/pyrogram/connection/connection.py @@ -48,7 +48,7 @@ async def connect(self): await self.protocol.connect(self.address) except OSError as e: log.warning("Unable to connect due to network issues: %s", e) - await self.protocol.close() + self.protocol.close() await asyncio.sleep(1) else: log.info("Connected! %s DC%s%s - IPv%s", @@ -59,14 +59,17 @@ async def connect(self): break else: log.warning("Connection failed! Trying again...") - raise ConnectionError + raise TimeoutError - async def close(self): - await self.protocol.close() + def close(self): + self.protocol.close() log.info("Disconnected") async def send(self, data: bytes): - await self.protocol.send(data) + try: + await self.protocol.send(data) + except Exception as e: + raise OSError(e) async def recv(self) -> Optional[bytes]: return await self.protocol.recv() From 424b765348153753a2f573d69ca89427d3c08f32 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:10:07 +0545 Subject: [PATCH 071/103] Add files via upload --- pyrogram/connection/transport/tcp/tcp.py | 52 +++++++++++------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/pyrogram/connection/transport/tcp/tcp.py b/pyrogram/connection/transport/tcp/tcp.py index 08a435cee9..beb2e58a2a 100644 --- a/pyrogram/connection/transport/tcp/tcp.py +++ b/pyrogram/connection/transport/tcp/tcp.py @@ -20,6 +20,7 @@ import ipaddress import logging import socket +import time from concurrent.futures import ThreadPoolExecutor import socks @@ -33,14 +34,12 @@ class TCP: def __init__(self, ipv6: bool, proxy: dict): self.socket = None - self.reader = None - self.writer = None + self.reader = None # type: asyncio.StreamReader + self.writer = None # type: asyncio.StreamWriter self.lock = asyncio.Lock() self.loop = asyncio.get_event_loop() - self.proxy = proxy - if proxy: hostname = proxy.get("hostname") @@ -62,46 +61,41 @@ def __init__(self, ipv6: bool, proxy: dict): password=proxy.get("password", None) ) - self.socket.settimeout(TCP.TIMEOUT) - log.info("Using proxy %s", hostname) else: - self.socket = socket.socket( + self.socket = socks.socksocket( socket.AF_INET6 if ipv6 else socket.AF_INET ) - self.socket.setblocking(False) + self.socket.settimeout(TCP.TIMEOUT) async def connect(self, address: tuple): - if self.proxy: - with ThreadPoolExecutor(1) as executor: - await self.loop.run_in_executor(executor, self.socket.connect, address) - else: - try: - await asyncio.wait_for(asyncio.get_event_loop().sock_connect(self.socket, address), TCP.TIMEOUT) - except asyncio.TimeoutError: # Re-raise as TimeoutError. asyncio.TimeoutError is deprecated in 3.11 - raise TimeoutError("Connection timed out") + # The socket used by the whole logic is blocking and thus it blocks when connecting. + # Offload the task to a thread executor to avoid blocking the main event loop. + with ThreadPoolExecutor(1) as executor: + await self.loop.run_in_executor(executor, self.socket.connect, address) self.reader, self.writer = await asyncio.open_connection(sock=self.socket) - async def close(self): + def close(self): try: - if self.writer is not None: - self.writer.close() - await asyncio.wait_for(self.writer.wait_closed(), TCP.TIMEOUT) - except Exception as e: - log.warning("Close exception: %s %s", type(e).__name__, e) + self.writer.close() + except AttributeError: + try: + self.socket.shutdown(socket.SHUT_RDWR) + except OSError: + pass + finally: + # A tiny sleep placed here helps avoiding .recv(n) hanging until the timeout. + # This is a workaround that seems to fix the occasional delayed stop of a client. + time.sleep(0.001) + self.socket.close() async def send(self, data: bytes): async with self.lock: - try: - if self.writer is not None: - self.writer.write(data) - await self.writer.drain() - except Exception as e: - log.warning("Send exception: %s %s", type(e).__name__, e) - raise OSError(e) + self.writer.write(data) + await self.writer.drain() async def recv(self, length: int = 0): data = b"" From 820c66c1596ee7fab32379b9491140b918e0d63f Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:11:24 +0545 Subject: [PATCH 072/103] Update utils.py --- pyrogram/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyrogram/utils.py b/pyrogram/utils.py index f7fe59706d..f2daba2ba2 100644 --- a/pyrogram/utils.py +++ b/pyrogram/utils.py @@ -198,7 +198,8 @@ def unpack_inline_message_id(inline_message_id: str) -> "raw.base.InputBotInline ) -MIN_CHANNEL_ID = -1002147483647 +MIN_CHANNEL_ID_OLD = -1002147483647 +MIN_CHANNEL_ID = -1009999999999 MAX_CHANNEL_ID = -1000000000000 MIN_CHAT_ID = -2147483647 MAX_USER_ID_OLD = 2147483647 From da7f7b162f70c958d8e8ce93e1c8842aaf403ac2 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:12:27 +0545 Subject: [PATCH 073/103] Add files via upload --- pyrogram/crypto/mtproto.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/pyrogram/crypto/mtproto.py b/pyrogram/crypto/mtproto.py index 6d1521a47b..e147c22a3e 100644 --- a/pyrogram/crypto/mtproto.py +++ b/pyrogram/crypto/mtproto.py @@ -16,13 +16,18 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +import bisect from hashlib import sha256 from io import BytesIO from os import urandom +from typing import List from pyrogram.errors import SecurityCheckMismatch from pyrogram.raw.core import Message, Long from . import aes +from ..session.internals import MsgId + +STORED_MSG_IDS_MAX_SIZE = 1000 * 2 def kdf(auth_key: bytes, msg_key: bytes, outgoing: bool) -> tuple: @@ -54,7 +59,8 @@ def unpack( b: BytesIO, session_id: bytes, auth_key: bytes, - auth_key_id: bytes + auth_key_id: bytes, + stored_msg_ids: List[int] ) -> Message: SecurityCheckMismatch.check(b.read(8) == auth_key_id, "b.read(8) == auth_key_id") @@ -97,4 +103,26 @@ def unpack( # https://core.telegram.org/mtproto/security_guidelines#checking-msg-id SecurityCheckMismatch.check(message.msg_id % 2 != 0, "message.msg_id % 2 != 0") + if len(stored_msg_ids) > STORED_MSG_IDS_MAX_SIZE: + del stored_msg_ids[:STORED_MSG_IDS_MAX_SIZE // 2] + + if stored_msg_ids: + if message.msg_id < stored_msg_ids[0]: + raise SecurityCheckMismatch("The msg_id is lower than all the stored values") + + if message.msg_id in stored_msg_ids: + raise SecurityCheckMismatch("The msg_id is equal to any of the stored values") + + time_diff = (message.msg_id - MsgId()) / 2 ** 32 + + if time_diff > 30: + raise SecurityCheckMismatch("The msg_id belongs to over 30 seconds in the future. " + "Most likely the client time has to be synchronized.") + + if time_diff < -300: + raise SecurityCheckMismatch("The msg_id belongs to over 300 seconds in the past. " + "Most likely the client time has to be synchronized.") + + bisect.insort(stored_msg_ids, message.msg_id) + return message From b321fe6ba4ca1f7265d9efe90b6f5abde7669938 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:14:48 +0545 Subject: [PATCH 074/103] =?UTF-8?q?Update=20Pyrogram=202.2.1=20?= =?UTF-8?q?=F0=9F=94=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyrogram/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py index a1accaf2ee..63db62ead1 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__ = "2.0.83" +__version__ = "2.2.1" __license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)" __copyright__ = "Copyright (C) 2017-present Dan " From 3de4d15ff53b3067914806db246d44d29862fada Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:19:33 +0545 Subject: [PATCH 075/103] Add files via upload --- pyrogram/types/messages_and_media/message.py | 25 -------------------- 1 file changed, 25 deletions(-) diff --git a/pyrogram/types/messages_and_media/message.py b/pyrogram/types/messages_and_media/message.py index 62a85b7593..ef249771fd 100644 --- a/pyrogram/types/messages_and_media/message.py +++ b/pyrogram/types/messages_and_media/message.py @@ -136,9 +136,6 @@ class Message(Object, Update): has_protected_content (``bool``, *optional*): True, if the message can't be forwarded. - has_media_spoiler (``bool``, *optional*): - True, if the message media is covered by a spoiler animation. - text (``str``, *optional*): For text messages, the actual UTF-8 text of the message, 0-4096 characters. If the message contains entities (bold, italic, ...) you can access *text.markdown* or @@ -335,7 +332,6 @@ def __init__( media_group_id: str = None, author_signature: str = None, has_protected_content: bool = None, - has_media_spoiler: bool = None, text: Str = None, entities: List["types.MessageEntity"] = None, caption_entities: List["types.MessageEntity"] = None, @@ -412,7 +408,6 @@ def __init__( self.media_group_id = media_group_id self.author_signature = author_signature self.has_protected_content = has_protected_content - self.has_media_spoiler = has_media_spoiler self.text = text self.entities = entities self.caption_entities = caption_entities @@ -663,13 +658,11 @@ async def _parse( media = message.media media_type = None - has_media_spoiler = None if media: if isinstance(media, raw.types.MessageMediaPhoto): photo = types.Photo._parse(client, media.photo, media.ttl_seconds) media_type = enums.MessageMediaType.PHOTO - has_media_spoiler = media.spoiler elif isinstance(media, raw.types.MessageMediaGeo): location = types.Location._parse(client, media.geo) media_type = enums.MessageMediaType.LOCATION @@ -698,7 +691,6 @@ async def _parse( video_attributes = attributes.get(raw.types.DocumentAttributeVideo, None) animation = types.Animation._parse(client, doc, video_attributes, file_name) media_type = enums.MessageMediaType.ANIMATION - has_media_spoiler = media.spoiler elif raw.types.DocumentAttributeSticker in attributes: sticker = await types.Sticker._parse(client, doc, attributes) media_type = enums.MessageMediaType.STICKER @@ -711,7 +703,6 @@ async def _parse( else: video = types.Video._parse(client, doc, video_attributes, file_name, media.ttl_seconds) media_type = enums.MessageMediaType.VIDEO - has_media_spoiler = media.spoiler elif raw.types.DocumentAttributeAudio in attributes: audio_attributes = attributes[raw.types.DocumentAttributeAudio] @@ -786,7 +777,6 @@ async def _parse( ), author_signature=message.post_author, has_protected_content=message.noforwards, - has_media_spoiler=has_media_spoiler, forward_from=forward_from, forward_sender_name=forward_sender_name, forward_from_chat=forward_from_chat, @@ -989,7 +979,6 @@ async def reply_animation( caption: str = "", parse_mode: Optional["enums.ParseMode"] = None, caption_entities: List["types.MessageEntity"] = None, - has_spoiler: bool = None, duration: int = 0, width: int = 0, height: int = 0, @@ -1043,9 +1032,6 @@ async def reply_animation( caption_entities (List of :obj:`~pyrogram.types.MessageEntity`): List of special entities that appear in the caption, which can be specified instead of *parse_mode*. - has_spoiler (``bool``, *optional*): - Pass True if the animation needs to be covered with a spoiler animation. - duration (``int``, *optional*): Duration of sent animation in seconds. @@ -1114,7 +1100,6 @@ async def reply_animation( caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, - has_spoiler=has_spoiler, duration=duration, width=width, height=height, @@ -1891,7 +1876,6 @@ async def reply_photo( caption: str = "", parse_mode: Optional["enums.ParseMode"] = None, caption_entities: List["types.MessageEntity"] = None, - has_spoiler: bool = None, ttl_seconds: int = None, disable_notification: bool = None, reply_to_message_id: int = None, @@ -1942,9 +1926,6 @@ async def reply_photo( caption_entities (List of :obj:`~pyrogram.types.MessageEntity`): List of special entities that appear in the caption, which can be specified instead of *parse_mode*. - has_spoiler (``bool``, *optional*): - Pass True if the photo needs to be covered with a spoiler animation. - ttl_seconds (``int``, *optional*): Self-Destruct Timer. If you set a timer, the photo will self-destruct in *ttl_seconds* @@ -2003,7 +1984,6 @@ async def reply_photo( caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, - has_spoiler=has_spoiler, ttl_seconds=ttl_seconds, disable_notification=disable_notification, reply_to_message_id=reply_to_message_id, @@ -2362,7 +2342,6 @@ async def reply_video( caption: str = "", parse_mode: Optional["enums.ParseMode"] = None, caption_entities: List["types.MessageEntity"] = None, - has_spoiler: bool = None, ttl_seconds: int = None, duration: int = 0, width: int = 0, @@ -2418,9 +2397,6 @@ async def reply_video( caption_entities (List of :obj:`~pyrogram.types.MessageEntity`): List of special entities that appear in the caption, which can be specified instead of *parse_mode*. - has_spoiler (``bool``, *optional*): - Pass True if the video needs to be covered with a spoiler animation. - ttl_seconds (``int``, *optional*): Self-Destruct Timer. If you set a timer, the video will self-destruct in *ttl_seconds* @@ -2497,7 +2473,6 @@ async def reply_video( caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, - has_spoiler=has_spoiler, ttl_seconds=ttl_seconds, duration=duration, width=width, From 8459e54b24365ef97451e2ca7396000c3ad16d10 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:21:35 +0545 Subject: [PATCH 076/103] Add files via upload From 1a0216a9468e83727685f6fc2b163eff95cec392 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:25:52 +0545 Subject: [PATCH 077/103] Add files via upload --- .../types/messages_and_media/message_entity.py | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/pyrogram/types/messages_and_media/message_entity.py b/pyrogram/types/messages_and_media/message_entity.py index 281015c5ed..d2bf654dcd 100644 --- a/pyrogram/types/messages_and_media/message_entity.py +++ b/pyrogram/types/messages_and_media/message_entity.py @@ -51,9 +51,6 @@ class MessageEntity(Object): custom_emoji_id (``int``, *optional*): For :obj:`~pyrogram.enums.MessageEntityType.CUSTOM_EMOJI` only, unique identifier of the custom emoji. Use :meth:`~pyrogram.Client.get_custom_emoji_stickers` to get full information about the sticker. - - collapsed (``bool``, *optional*): - For :obj:`~pyrogram.enums.MessageEntityType.BLOCKQUOTE` only, whether the blockquote expandable. """ def __init__( @@ -66,8 +63,7 @@ def __init__( url: str = None, user: "types.User" = None, language: str = None, - custom_emoji_id: int = None, - collapsed: bool = None + custom_emoji_id: int = None ): super().__init__(client) @@ -78,7 +74,6 @@ def __init__( self.user = user self.language = language self.custom_emoji_id = custom_emoji_id - self.collapsed = collapsed @staticmethod def _parse(client, entity: "raw.base.MessageEntity", users: dict) -> Optional["MessageEntity"]: @@ -99,7 +94,6 @@ def _parse(client, entity: "raw.base.MessageEntity", users: dict) -> Optional["M user=types.User._parse(client, users.get(user_id, None)), language=getattr(entity, "language", None), custom_emoji_id=getattr(entity, "document_id", None), - collapsed=getattr(entity, "collapsed", None), client=client ) @@ -122,12 +116,6 @@ async def write(self): if self.custom_emoji_id is not None: args["document_id"] = self.custom_emoji_id - if self.type not in [ - enums.MessageEntityType.BLOCKQUOTE, - enums.MessageEntityType.EXPANDABLE_BLOCKQUOTE - ]: - args.pop("collapsed") - entity = self.type.value if entity is raw.types.MessageEntityMentionName: From 0550899ff5baf8481aa21e3527653269cf90dbb5 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:26:40 +0545 Subject: [PATCH 078/103] Add files via upload --- pyrogram/parser/html.py | 7 +---- pyrogram/parser/markdown.py | 60 +------------------------------------ 2 files changed, 2 insertions(+), 65 deletions(-) diff --git a/pyrogram/parser/html.py b/pyrogram/parser/html.py index 726a477226..7edb7f3c99 100644 --- a/pyrogram/parser/html.py +++ b/pyrogram/parser/html.py @@ -57,7 +57,6 @@ def handle_starttag(self, tag, attrs): entity = raw.types.MessageEntityStrike elif tag == "blockquote": entity = raw.types.MessageEntityBlockquote - extra["collapsed"] = bool("expandable" in attrs.keys()) elif tag == "code": entity = raw.types.MessageEntityCode elif tag == "pre": @@ -132,7 +131,7 @@ async def parse(self, text: str): for tag, entities in parser.tag_entities.items(): unclosed_tags.append(f"<{tag}> (x{len(entities)})") - log.info("Unclosed tags: %s", ", ".join(unclosed_tags)) + log.warning("Unclosed tags: %s", ", ".join(unclosed_tags)) entities = [] @@ -178,10 +177,6 @@ def parse_one(entity): language = getattr(entity, "language", "") or "" start_tag = f'<{name} language="{language}">' if language else f"<{name}>" end_tag = f"" - elif entity_type == MessageEntityType.EXPANDABLE_BLOCKQUOTE: - name = "blockquote" - start_tag = f"<{name} expandable>" - end_tag = f"" elif entity_type in ( MessageEntityType.CODE, MessageEntityType.BLOCKQUOTE, diff --git a/pyrogram/parser/markdown.py b/pyrogram/parser/markdown.py index 417be7285a..6219d9583d 100644 --- a/pyrogram/parser/markdown.py +++ b/pyrogram/parser/markdown.py @@ -17,7 +17,6 @@ # along with Pyrogram. If not, see . import html -import logging import re from typing import Optional @@ -33,8 +32,6 @@ SPOILER_DELIM = "||" CODE_DELIM = "`" PRE_DELIM = "```" -BLOCKQUOTE_DELIM = ">" -BLOCKQUOTE_EXPANDABLE_DELIM = "**>" MARKDOWN_RE = re.compile(r"({d})|\[(.+?)\]\((.+?)\)".format( d="|".join( @@ -62,47 +59,9 @@ class Markdown: def __init__(self, client: Optional["pyrogram.Client"]): self.html = HTML(client) - def blockquote_parser(self, text): - text = re.sub(r'\n>', '\n>', re.sub(r'^>', '>', text)) - lines = text.split('\n') - result = [] - - in_blockquote = False - - for line in lines: - if line.startswith(BLOCKQUOTE_DELIM): - if not in_blockquote: - line = re.sub(r'^> ', OPENING_TAG.format("blockquote"), line) - line = re.sub(r'^>', OPENING_TAG.format("blockquote"), line) - in_blockquote = True - result.append(line.strip()) - else: - result.append(line[1:].strip()) - elif line.startswith(BLOCKQUOTE_EXPANDABLE_DELIM): - if not in_blockquote: - line = re.sub(r'^\*\*> ', OPENING_TAG.format("blockquote expandable"), line) - line = re.sub(r'^\*\*>', OPENING_TAG.format("blockquote expandable"), line) - in_blockquote = True - result.append(line.strip()) - else: - result.append(line[3:].strip()) - else: - if in_blockquote: - line = CLOSING_TAG.format("blockquote") + line - in_blockquote = False - result.append(line) - - if in_blockquote: - line = result[len(result)-1] + CLOSING_TAG.format("blockquote") - result.pop(len(result)-1) - result.append(line) - - return '\n'.join(result) - async def parse(self, text: str, strict: bool = False): if strict: text = html.escape(text) - text = self.blockquote_parser(text) delims = set() is_fixed_width = False @@ -182,24 +141,7 @@ def unparse(text: str, entities: list): start_tag = f"{PRE_DELIM}{language}\n" end_tag = f"\n{PRE_DELIM}" elif entity_type == MessageEntityType.BLOCKQUOTE: - if entity.collapsed: - start_tag = BLOCKQUOTE_EXPANDABLE_DELIM + " " - else: - start_tag = BLOCKQUOTE_DELIM + " " - end_tag = "" - blockquote_text = text[start:end] - lines = blockquote_text.split("\n") - last_length = 0 - for line in lines: - if len(line) == 0 and last_length == end: - continue - start_offset = start+last_length - last_length = last_length+len(line) - end_offset = start_offset+last_length - entities_offsets.append((start_tag, start_offset,)) - entities_offsets.append((end_tag, end_offset,)) - last_length = last_length+1 - continue + start_tag = end_tag = PRE_DELIM elif entity_type == MessageEntityType.SPOILER: start_tag = end_tag = SPOILER_DELIM elif entity_type == MessageEntityType.TEXT_LINK: From 15a2423e4b9787e665df7336e0ba5b6f751826eb Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:27:42 +0545 Subject: [PATCH 079/103] Add files via upload --- pyrogram/enums/message_entity_type.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pyrogram/enums/message_entity_type.py b/pyrogram/enums/message_entity_type.py index 5229d03917..4db75f93f7 100644 --- a/pyrogram/enums/message_entity_type.py +++ b/pyrogram/enums/message_entity_type.py @@ -68,9 +68,6 @@ class MessageEntityType(AutoName): BLOCKQUOTE = raw.types.MessageEntityBlockquote "Blockquote text" - EXPANDABLE_BLOCKQUOTE = raw.types.MessageEntityBlockquote - "collapsed-by-default block quotation" - TEXT_LINK = raw.types.MessageEntityTextUrl "For clickable text URLs" From 7c9b351f62d407b94ec54ebf2a72aea19c2ec84d Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:35:08 +0545 Subject: [PATCH 080/103] Delete pyrogram/parser/html.py --- pyrogram/parser/html.py | 243 ---------------------------------------- 1 file changed, 243 deletions(-) delete mode 100644 pyrogram/parser/html.py diff --git a/pyrogram/parser/html.py b/pyrogram/parser/html.py deleted file mode 100644 index 7edb7f3c99..0000000000 --- a/pyrogram/parser/html.py +++ /dev/null @@ -1,243 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-present 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 -import logging -import re -from html.parser import HTMLParser -from typing import Optional - -import pyrogram -from pyrogram import raw -from pyrogram.enums import MessageEntityType -from pyrogram.errors import PeerIdInvalid -from . import utils - -log = logging.getLogger(__name__) - - -class Parser(HTMLParser): - MENTION_RE = re.compile(r"tg://user\?id=(\d+)") - - def __init__(self, client: "pyrogram.Client"): - super().__init__() - - self.client = client - - self.text = "" - self.entities = [] - self.tag_entities = {} - - def handle_starttag(self, tag, attrs): - attrs = dict(attrs) - extra = {} - - if tag in ["b", "strong"]: - entity = raw.types.MessageEntityBold - elif tag in ["i", "em"]: - entity = raw.types.MessageEntityItalic - elif tag == "u": - entity = raw.types.MessageEntityUnderline - elif tag in ["s", "del", "strike"]: - entity = raw.types.MessageEntityStrike - elif tag == "blockquote": - entity = raw.types.MessageEntityBlockquote - elif tag == "code": - entity = raw.types.MessageEntityCode - elif tag == "pre": - entity = raw.types.MessageEntityPre - extra["language"] = attrs.get("language", "") - elif tag == "spoiler": - entity = raw.types.MessageEntitySpoiler - elif tag == "a": - url = attrs.get("href", "") - - mention = Parser.MENTION_RE.match(url) - - if mention: - entity = raw.types.InputMessageEntityMentionName - extra["user_id"] = int(mention.group(1)) - else: - entity = raw.types.MessageEntityTextUrl - extra["url"] = url - elif tag == "emoji": - entity = raw.types.MessageEntityCustomEmoji - custom_emoji_id = int(attrs.get("id")) - extra["document_id"] = custom_emoji_id - else: - return - - if tag not in self.tag_entities: - self.tag_entities[tag] = [] - - self.tag_entities[tag].append(entity(offset=len(self.text), length=0, **extra)) - - def handle_data(self, data): - data = html.unescape(data) - - for entities in self.tag_entities.values(): - for entity in entities: - entity.length += len(data) - - self.text += data - - def handle_endtag(self, tag): - try: - self.entities.append(self.tag_entities[tag].pop()) - except (KeyError, IndexError): - line, offset = self.getpos() - offset += 1 - - log.debug("Unmatched closing tag at line %s:%s", tag, line, offset) - else: - if not self.tag_entities[tag]: - self.tag_entities.pop(tag) - - def error(self, message): - pass - - -class HTML: - def __init__(self, client: Optional["pyrogram.Client"]): - self.client = client - - async def parse(self, text: str): - # Strip whitespaces from the beginning and the end, but preserve closing tags - text = re.sub(r"^\s*(<[\w<>=\s\"]*>)\s*", r"\1", text) - text = re.sub(r"\s*(]*>)\s*$", r"\1", text) - - parser = Parser(self.client) - parser.feed(utils.add_surrogates(text)) - parser.close() - - if parser.tag_entities: - unclosed_tags = [] - - for tag, entities in parser.tag_entities.items(): - unclosed_tags.append(f"<{tag}> (x{len(entities)})") - - log.warning("Unclosed tags: %s", ", ".join(unclosed_tags)) - - entities = [] - - for entity in parser.entities: - if isinstance(entity, raw.types.InputMessageEntityMentionName): - try: - if self.client is not None: - entity.user_id = await self.client.resolve_peer(entity.user_id) - except PeerIdInvalid: - continue - - entities.append(entity) - - # Remove zero-length entities - entities = list(filter(lambda x: x.length > 0, entities)) - - return { - "message": utils.remove_surrogates(parser.text), - "entities": sorted(entities, key=lambda e: e.offset) or None - } - - @staticmethod - def unparse(text: str, entities: list): - def parse_one(entity): - """ - Parses a single entity and returns (start_tag, start), (end_tag, end) - """ - entity_type = entity.type - start = entity.offset - end = start + entity.length - - if entity_type in ( - MessageEntityType.BOLD, - MessageEntityType.ITALIC, - MessageEntityType.UNDERLINE, - MessageEntityType.STRIKETHROUGH, - ): - name = entity_type.name[0].lower() - start_tag = f"<{name}>" - end_tag = f"" - elif entity_type == MessageEntityType.PRE: - name = entity_type.name.lower() - language = getattr(entity, "language", "") or "" - start_tag = f'<{name} language="{language}">' if language else f"<{name}>" - end_tag = f"" - elif entity_type in ( - MessageEntityType.CODE, - MessageEntityType.BLOCKQUOTE, - MessageEntityType.SPOILER, - ): - name = entity_type.name.lower() - start_tag = f"<{name}>" - end_tag = f"" - elif entity_type == MessageEntityType.TEXT_LINK: - url = entity.url - start_tag = f'' - end_tag = "" - elif entity_type == MessageEntityType.TEXT_MENTION: - user = entity.user - start_tag = f'' - end_tag = "" - elif entity_type == MessageEntityType.CUSTOM_EMOJI: - custom_emoji_id = entity.custom_emoji_id - start_tag = f'' - end_tag = "" - else: - return - - return (start_tag, start), (end_tag, end) - - def recursive(entity_i: int) -> int: - """ - Takes the index of the entity to start parsing from, returns the number of parsed entities inside it. - Uses entities_offsets as a stack, pushing (start_tag, start) first, then parsing nested entities, - and finally pushing (end_tag, end) to the stack. - No need to sort at the end. - """ - this = parse_one(entities[entity_i]) - if this is None: - return 1 - (start_tag, start), (end_tag, end) = this - entities_offsets.append((start_tag, start)) - internal_i = entity_i + 1 - # while the next entity is inside the current one, keep parsing - while internal_i < len(entities) and entities[internal_i].offset < end: - internal_i += recursive(internal_i) - entities_offsets.append((end_tag, end)) - return internal_i - entity_i - - text = utils.add_surrogates(text) - - entities_offsets = [] - - # probably useless because entities are already sorted by telegram - entities.sort(key=lambda e: (e.offset, -e.length)) - - # main loop for first-level entities - i = 0 - while i < len(entities): - i += recursive(i) - - if entities_offsets: - last_offset = entities_offsets[-1][1] - # no need to sort, but still add entities starting from the end - for entity, offset in reversed(entities_offsets): - text = text[:offset] + entity + html.escape(text[offset:last_offset]) + text[last_offset:] - last_offset = offset - - return utils.remove_surrogates(text) From 6778cdc8d1c58bb22074dc0720ea3abd77c1d214 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:35:35 +0545 Subject: [PATCH 081/103] Add files via upload --- pyrogram/parser/html.py | 243 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 pyrogram/parser/html.py diff --git a/pyrogram/parser/html.py b/pyrogram/parser/html.py new file mode 100644 index 0000000000..7edb7f3c99 --- /dev/null +++ b/pyrogram/parser/html.py @@ -0,0 +1,243 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present 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 +import logging +import re +from html.parser import HTMLParser +from typing import Optional + +import pyrogram +from pyrogram import raw +from pyrogram.enums import MessageEntityType +from pyrogram.errors import PeerIdInvalid +from . import utils + +log = logging.getLogger(__name__) + + +class Parser(HTMLParser): + MENTION_RE = re.compile(r"tg://user\?id=(\d+)") + + def __init__(self, client: "pyrogram.Client"): + super().__init__() + + self.client = client + + self.text = "" + self.entities = [] + self.tag_entities = {} + + def handle_starttag(self, tag, attrs): + attrs = dict(attrs) + extra = {} + + if tag in ["b", "strong"]: + entity = raw.types.MessageEntityBold + elif tag in ["i", "em"]: + entity = raw.types.MessageEntityItalic + elif tag == "u": + entity = raw.types.MessageEntityUnderline + elif tag in ["s", "del", "strike"]: + entity = raw.types.MessageEntityStrike + elif tag == "blockquote": + entity = raw.types.MessageEntityBlockquote + elif tag == "code": + entity = raw.types.MessageEntityCode + elif tag == "pre": + entity = raw.types.MessageEntityPre + extra["language"] = attrs.get("language", "") + elif tag == "spoiler": + entity = raw.types.MessageEntitySpoiler + elif tag == "a": + url = attrs.get("href", "") + + mention = Parser.MENTION_RE.match(url) + + if mention: + entity = raw.types.InputMessageEntityMentionName + extra["user_id"] = int(mention.group(1)) + else: + entity = raw.types.MessageEntityTextUrl + extra["url"] = url + elif tag == "emoji": + entity = raw.types.MessageEntityCustomEmoji + custom_emoji_id = int(attrs.get("id")) + extra["document_id"] = custom_emoji_id + else: + return + + if tag not in self.tag_entities: + self.tag_entities[tag] = [] + + self.tag_entities[tag].append(entity(offset=len(self.text), length=0, **extra)) + + def handle_data(self, data): + data = html.unescape(data) + + for entities in self.tag_entities.values(): + for entity in entities: + entity.length += len(data) + + self.text += data + + def handle_endtag(self, tag): + try: + self.entities.append(self.tag_entities[tag].pop()) + except (KeyError, IndexError): + line, offset = self.getpos() + offset += 1 + + log.debug("Unmatched closing tag at line %s:%s", tag, line, offset) + else: + if not self.tag_entities[tag]: + self.tag_entities.pop(tag) + + def error(self, message): + pass + + +class HTML: + def __init__(self, client: Optional["pyrogram.Client"]): + self.client = client + + async def parse(self, text: str): + # Strip whitespaces from the beginning and the end, but preserve closing tags + text = re.sub(r"^\s*(<[\w<>=\s\"]*>)\s*", r"\1", text) + text = re.sub(r"\s*(]*>)\s*$", r"\1", text) + + parser = Parser(self.client) + parser.feed(utils.add_surrogates(text)) + parser.close() + + if parser.tag_entities: + unclosed_tags = [] + + for tag, entities in parser.tag_entities.items(): + unclosed_tags.append(f"<{tag}> (x{len(entities)})") + + log.warning("Unclosed tags: %s", ", ".join(unclosed_tags)) + + entities = [] + + for entity in parser.entities: + if isinstance(entity, raw.types.InputMessageEntityMentionName): + try: + if self.client is not None: + entity.user_id = await self.client.resolve_peer(entity.user_id) + except PeerIdInvalid: + continue + + entities.append(entity) + + # Remove zero-length entities + entities = list(filter(lambda x: x.length > 0, entities)) + + return { + "message": utils.remove_surrogates(parser.text), + "entities": sorted(entities, key=lambda e: e.offset) or None + } + + @staticmethod + def unparse(text: str, entities: list): + def parse_one(entity): + """ + Parses a single entity and returns (start_tag, start), (end_tag, end) + """ + entity_type = entity.type + start = entity.offset + end = start + entity.length + + if entity_type in ( + MessageEntityType.BOLD, + MessageEntityType.ITALIC, + MessageEntityType.UNDERLINE, + MessageEntityType.STRIKETHROUGH, + ): + name = entity_type.name[0].lower() + start_tag = f"<{name}>" + end_tag = f"" + elif entity_type == MessageEntityType.PRE: + name = entity_type.name.lower() + language = getattr(entity, "language", "") or "" + start_tag = f'<{name} language="{language}">' if language else f"<{name}>" + end_tag = f"" + elif entity_type in ( + MessageEntityType.CODE, + MessageEntityType.BLOCKQUOTE, + MessageEntityType.SPOILER, + ): + name = entity_type.name.lower() + start_tag = f"<{name}>" + end_tag = f"" + elif entity_type == MessageEntityType.TEXT_LINK: + url = entity.url + start_tag = f'' + end_tag = "" + elif entity_type == MessageEntityType.TEXT_MENTION: + user = entity.user + start_tag = f'' + end_tag = "" + elif entity_type == MessageEntityType.CUSTOM_EMOJI: + custom_emoji_id = entity.custom_emoji_id + start_tag = f'' + end_tag = "" + else: + return + + return (start_tag, start), (end_tag, end) + + def recursive(entity_i: int) -> int: + """ + Takes the index of the entity to start parsing from, returns the number of parsed entities inside it. + Uses entities_offsets as a stack, pushing (start_tag, start) first, then parsing nested entities, + and finally pushing (end_tag, end) to the stack. + No need to sort at the end. + """ + this = parse_one(entities[entity_i]) + if this is None: + return 1 + (start_tag, start), (end_tag, end) = this + entities_offsets.append((start_tag, start)) + internal_i = entity_i + 1 + # while the next entity is inside the current one, keep parsing + while internal_i < len(entities) and entities[internal_i].offset < end: + internal_i += recursive(internal_i) + entities_offsets.append((end_tag, end)) + return internal_i - entity_i + + text = utils.add_surrogates(text) + + entities_offsets = [] + + # probably useless because entities are already sorted by telegram + entities.sort(key=lambda e: (e.offset, -e.length)) + + # main loop for first-level entities + i = 0 + while i < len(entities): + i += recursive(i) + + if entities_offsets: + last_offset = entities_offsets[-1][1] + # no need to sort, but still add entities starting from the end + for entity, offset in reversed(entities_offsets): + text = text[:offset] + entity + html.escape(text[offset:last_offset]) + text[last_offset:] + last_offset = offset + + return utils.remove_surrogates(text) From 636f286d6ec95f699d8494ba41169825fe3bc0a5 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:37:01 +0545 Subject: [PATCH 082/103] Add files via upload From cf5f39b4f505cfc333dc0e8fc281f825c42a3258 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:37:41 +0545 Subject: [PATCH 083/103] Add files via upload From 87d5f57bc391c112ece0e6060efb42ff0b1eaac4 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:38:28 +0545 Subject: [PATCH 084/103] Add files via upload From 1739ae4b9e0a35fd7160ade2e6d4e840c6712340 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 18:59:39 +0545 Subject: [PATCH 085/103] Add files via upload From bedca3462ee6aa170fe9ae5da9a5bdd91ab7b777 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Fri, 14 Jun 2024 19:00:47 +0545 Subject: [PATCH 086/103] Add files via upload From d2f3cd998a90bff89a3915648fb2a1805af95bf1 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Wed, 26 Jun 2024 10:02:48 +0545 Subject: [PATCH 087/103] Implement non-blocking TCP connection ( --- pyrogram/connection/connection.py | 40 ++++++++++++++++++------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/pyrogram/connection/connection.py b/pyrogram/connection/connection.py index 051d3c526b..05d2e07af1 100644 --- a/pyrogram/connection/connection.py +++ b/pyrogram/connection/connection.py @@ -18,9 +18,9 @@ import asyncio import logging -from typing import Optional +from typing import Optional, Type -from .transport import TCP, TCPAbridgedO +from .transport import TCP, TCPAbridged from ..session.internals import DataCenter log = logging.getLogger(__name__) @@ -29,26 +29,37 @@ class Connection: MAX_CONNECTION_ATTEMPTS = 3 - def __init__(self, dc_id: int, test_mode: bool, ipv6: bool, proxy: dict, media: bool = False): + def __init__( + self, + dc_id: int, + test_mode: bool, + ipv6: bool, + alt_port: bool, + proxy: dict, + media: bool = False, + protocol_factory: Type[TCP] = TCPAbridged + ) -> None: self.dc_id = dc_id self.test_mode = test_mode self.ipv6 = ipv6 + self.alt_port = alt_port self.proxy = proxy self.media = media + self.protocol_factory = protocol_factory - self.address = DataCenter(dc_id, test_mode, ipv6, media) - self.protocol: TCP = None + self.address = DataCenter(dc_id, test_mode, ipv6, alt_port, media) + self.protocol: Optional[TCP] = None - async def connect(self): + async def connect(self) -> None: for i in range(Connection.MAX_CONNECTION_ATTEMPTS): - self.protocol = TCPAbridgedO(self.ipv6, self.proxy) + self.protocol = self.protocol_factory(ipv6=self.ipv6, proxy=self.proxy) try: log.info("Connecting...") await self.protocol.connect(self.address) except OSError as e: log.warning("Unable to connect due to network issues: %s", e) - self.protocol.close() + await self.protocol.close() await asyncio.sleep(1) else: log.info("Connected! %s DC%s%s - IPv%s", @@ -59,17 +70,14 @@ async def connect(self): break else: log.warning("Connection failed! Trying again...") - raise TimeoutError + raise ConnectionError - def close(self): - self.protocol.close() + async def close(self) -> None: + await self.protocol.close() log.info("Disconnected") - async def send(self, data: bytes): - try: - await self.protocol.send(data) - except Exception as e: - raise OSError(e) + async def send(self, data: bytes) -> None: + await self.protocol.send(data) async def recv(self) -> Optional[bytes]: return await self.protocol.recv() From e96daec359591e4457eb86f637e5cd9c50a0f9b3 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Wed, 26 Jun 2024 10:05:40 +0545 Subject: [PATCH 088/103] Implement non-blocking TCP connection ( --- pyrogram/connection/transport/tcp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/connection/transport/tcp/__init__.py b/pyrogram/connection/transport/tcp/__init__.py index 3e23a88379..bae35e8825 100644 --- a/pyrogram/connection/transport/tcp/__init__.py +++ b/pyrogram/connection/transport/tcp/__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 .tcp import TCP +from .tcp import TCP, Proxy from .tcp_abridged import TCPAbridged from .tcp_abridged_o import TCPAbridgedO from .tcp_full import TCPFull From c4d427fa2e2d6c614cadb50eb67d8f46904f60a3 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Wed, 26 Jun 2024 10:07:07 +0545 Subject: [PATCH 089/103] Implement non-blocking TCP connection ( --- pyrogram/connection/transport/tcp/tcp.py | 155 +++++++++++++++-------- 1 file changed, 103 insertions(+), 52 deletions(-) diff --git a/pyrogram/connection/transport/tcp/tcp.py b/pyrogram/connection/transport/tcp/tcp.py index beb2e58a2a..8913123628 100644 --- a/pyrogram/connection/transport/tcp/tcp.py +++ b/pyrogram/connection/transport/tcp/tcp.py @@ -20,84 +20,135 @@ import ipaddress import logging import socket -import time from concurrent.futures import ThreadPoolExecutor +from typing import Tuple, Dict, TypedDict, Optional import socks log = logging.getLogger(__name__) +proxy_type_by_scheme: Dict[str, int] = { + "SOCKS4": socks.SOCKS4, + "SOCKS5": socks.SOCKS5, + "HTTP": socks.HTTP, +} + + +class Proxy(TypedDict): + scheme: str + hostname: str + port: int + username: Optional[str] + password: Optional[str] + class TCP: TIMEOUT = 10 - def __init__(self, ipv6: bool, proxy: dict): - self.socket = None + def __init__(self, ipv6: bool, proxy: Proxy) -> None: + self.ipv6 = ipv6 + self.proxy = proxy - self.reader = None # type: asyncio.StreamReader - self.writer = None # type: asyncio.StreamWriter + self.reader: Optional[asyncio.StreamReader] = None + self.writer: Optional[asyncio.StreamWriter] = None self.lock = asyncio.Lock() self.loop = asyncio.get_event_loop() - if proxy: - hostname = proxy.get("hostname") + async def _connect_via_proxy( + self, + destination: Tuple[str, int] + ) -> None: + scheme = self.proxy.get("scheme") + if scheme is None: + raise ValueError("No scheme specified") - try: - ip_address = ipaddress.ip_address(hostname) - except ValueError: - self.socket = socks.socksocket(socket.AF_INET) - else: - if isinstance(ip_address, ipaddress.IPv6Address): - self.socket = socks.socksocket(socket.AF_INET6) - else: - self.socket = socks.socksocket(socket.AF_INET) + proxy_type = proxy_type_by_scheme.get(scheme.upper()) + if proxy_type is None: + raise ValueError(f"Unknown proxy type {scheme}") - self.socket.set_proxy( - proxy_type=getattr(socks, proxy.get("scheme").upper()), - addr=hostname, - port=proxy.get("port", None), - username=proxy.get("username", None), - password=proxy.get("password", None) - ) + hostname = self.proxy.get("hostname") + port = self.proxy.get("port") + username = self.proxy.get("username") + password = self.proxy.get("password") - log.info("Using proxy %s", hostname) + try: + ip_address = ipaddress.ip_address(hostname) + except ValueError: + is_proxy_ipv6 = False else: - self.socket = socks.socksocket( - socket.AF_INET6 if ipv6 - else socket.AF_INET - ) - - self.socket.settimeout(TCP.TIMEOUT) + is_proxy_ipv6 = isinstance(ip_address, ipaddress.IPv6Address) + + proxy_family = socket.AF_INET6 if is_proxy_ipv6 else socket.AF_INET + sock = socks.socksocket(proxy_family) + + sock.set_proxy( + proxy_type=proxy_type, + addr=hostname, + port=port, + username=username, + password=password + ) + sock.settimeout(TCP.TIMEOUT) + + await self.loop.sock_connect( + sock=sock, + address=destination + ) + + sock.setblocking(False) + + self.reader, self.writer = await asyncio.open_connection( + sock=sock + ) + + async def _connect_via_direct( + self, + destination: Tuple[str, int] + ) -> None: + host, port = destination + family = socket.AF_INET6 if self.ipv6 else socket.AF_INET + self.reader, self.writer = await asyncio.open_connection( + host=host, + port=port, + family=family + ) + + async def _connect(self, destination: Tuple[str, int]) -> None: + if self.proxy: + await self._connect_via_proxy(destination) + else: + await self._connect_via_direct(destination) - async def connect(self, address: tuple): - # The socket used by the whole logic is blocking and thus it blocks when connecting. - # Offload the task to a thread executor to avoid blocking the main event loop. - with ThreadPoolExecutor(1) as executor: - await self.loop.run_in_executor(executor, self.socket.connect, address) + async def connect(self, address: Tuple[str, int]) -> None: + try: + await asyncio.wait_for(self._connect(address), TCP.TIMEOUT) + except asyncio.TimeoutError: # Re-raise as TimeoutError. asyncio.TimeoutError is deprecated in 3.11 + raise TimeoutError("Connection timed out") - self.reader, self.writer = await asyncio.open_connection(sock=self.socket) + async def close(self) -> None: + if self.writer is None: + return None - def close(self): try: self.writer.close() - except AttributeError: - try: - self.socket.shutdown(socket.SHUT_RDWR) - except OSError: - pass - finally: - # A tiny sleep placed here helps avoiding .recv(n) hanging until the timeout. - # This is a workaround that seems to fix the occasional delayed stop of a client. - time.sleep(0.001) - self.socket.close() - - async def send(self, data: bytes): + await asyncio.wait_for(self.writer.wait_closed(), TCP.TIMEOUT) + except Exception as e: + log.info("Close exception: %s %s", type(e).__name__, e) + + async def send(self, data: bytes) -> None: + if self.writer is None: + return None + async with self.lock: - self.writer.write(data) - await self.writer.drain() + try: + self.writer.write(data) + await self.writer.drain() + except Exception as e: + log.info("Send exception: %s %s", type(e).__name__, e) + raise OSError(e) - async def recv(self, length: int = 0): + async def recv(self, length: int = 0) -> Optional[bytes]: data = b"" while len(data) < length: From c7108baa87cfc2342446e97311e515efd0ef042c Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Wed, 26 Jun 2024 10:08:28 +0545 Subject: [PATCH 090/103] Implement non-blocking TCP connection ( --- pyrogram/connection/transport/tcp/tcp_abridged.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyrogram/connection/transport/tcp/tcp_abridged.py b/pyrogram/connection/transport/tcp/tcp_abridged.py index 77d44cf41c..4cb4c1b2a3 100644 --- a/pyrogram/connection/transport/tcp/tcp_abridged.py +++ b/pyrogram/connection/transport/tcp/tcp_abridged.py @@ -17,22 +17,22 @@ # along with Pyrogram. If not, see . import logging -from typing import Optional +from typing import Optional, Tuple -from .tcp import TCP +from .tcp import TCP, Proxy log = logging.getLogger(__name__) class TCPAbridged(TCP): - def __init__(self, ipv6: bool, proxy: dict): + def __init__(self, ipv6: bool, proxy: Proxy) -> None: super().__init__(ipv6, proxy) - async def connect(self, address: tuple): + async def connect(self, address: Tuple[str, int]) -> None: await super().connect(address) await super().send(b"\xef") - async def send(self, data: bytes, *args): + async def send(self, data: bytes, *args) -> None: length = len(data) // 4 await super().send( From 00d4508d805c5fbaf3e892eb0a5800d321a04c72 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Wed, 26 Jun 2024 10:10:44 +0545 Subject: [PATCH 091/103] Implement non-blocking TCP connection ( --- pyrogram/connection/transport/tcp/tcp_abridged_o.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyrogram/connection/transport/tcp/tcp_abridged_o.py b/pyrogram/connection/transport/tcp/tcp_abridged_o.py index 6f57ab1154..20efb5ec3f 100644 --- a/pyrogram/connection/transport/tcp/tcp_abridged_o.py +++ b/pyrogram/connection/transport/tcp/tcp_abridged_o.py @@ -18,11 +18,11 @@ import logging import os -from typing import Optional +from typing import Optional, Tuple import pyrogram from pyrogram.crypto import aes -from .tcp import TCP +from .tcp import TCP, Proxy log = logging.getLogger(__name__) @@ -30,13 +30,13 @@ class TCPAbridgedO(TCP): RESERVED = (b"HEAD", b"POST", b"GET ", b"OPTI", b"\xee" * 4) - def __init__(self, ipv6: bool, proxy: dict): + def __init__(self, ipv6: bool, proxy: Proxy) -> None: super().__init__(ipv6, proxy) self.encrypt = None self.decrypt = None - async def connect(self, address: tuple): + async def connect(self, address: Tuple[str, int]) -> None: await super().connect(address) while True: @@ -55,7 +55,7 @@ async def connect(self, address: tuple): await super().send(nonce) - async def send(self, data: bytes, *args): + async def send(self, data: bytes, *args) -> None: length = len(data) // 4 data = (bytes([length]) if length <= 126 else b"\x7f" + length.to_bytes(3, "little")) + data payload = await self.loop.run_in_executor(pyrogram.crypto_executor, aes.ctr256_encrypt, data, *self.encrypt) From b84f6690d13ef981508e9c12c539168b147a2ccd Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Wed, 26 Jun 2024 10:11:49 +0545 Subject: [PATCH 092/103] Implement non-blocking TCP connection ( --- pyrogram/connection/transport/tcp/tcp_full.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyrogram/connection/transport/tcp/tcp_full.py b/pyrogram/connection/transport/tcp/tcp_full.py index 8bd89000c8..ad9d981718 100644 --- a/pyrogram/connection/transport/tcp/tcp_full.py +++ b/pyrogram/connection/transport/tcp/tcp_full.py @@ -19,24 +19,24 @@ import logging from binascii import crc32 from struct import pack, unpack -from typing import Optional +from typing import Optional, Tuple -from .tcp import TCP +from .tcp import TCP, Proxy log = logging.getLogger(__name__) class TCPFull(TCP): - def __init__(self, ipv6: bool, proxy: dict): + def __init__(self, ipv6: bool, proxy: Proxy) -> None: super().__init__(ipv6, proxy) - self.seq_no = None + self.seq_no: Optional[int] = None - async def connect(self, address: tuple): + async def connect(self, address: Tuple[str, int]) -> None: await super().connect(address) self.seq_no = 0 - async def send(self, data: bytes, *args): + async def send(self, data: bytes, *args) -> None: data = pack(" Date: Wed, 26 Jun 2024 10:12:48 +0545 Subject: [PATCH 093/103] Implement non-blocking TCP connection ( --- pyrogram/connection/transport/tcp/tcp_intermediate.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyrogram/connection/transport/tcp/tcp_intermediate.py b/pyrogram/connection/transport/tcp/tcp_intermediate.py index b6aef335a9..6823d88ce9 100644 --- a/pyrogram/connection/transport/tcp/tcp_intermediate.py +++ b/pyrogram/connection/transport/tcp/tcp_intermediate.py @@ -18,22 +18,22 @@ import logging from struct import pack, unpack -from typing import Optional +from typing import Optional, Tuple -from .tcp import TCP +from .tcp import TCP, Proxy log = logging.getLogger(__name__) class TCPIntermediate(TCP): - def __init__(self, ipv6: bool, proxy: dict): + def __init__(self, ipv6: bool, proxy: Proxy) -> None: super().__init__(ipv6, proxy) - async def connect(self, address: tuple): + async def connect(self, address: Tuple[str, int]) -> None: await super().connect(address) await super().send(b"\xee" * 4) - async def send(self, data: bytes, *args): + async def send(self, data: bytes, *args) -> None: await super().send(pack(" Optional[bytes]: From 64ea7f5f71a41e2c06058d339e64680b2cd410d5 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Wed, 26 Jun 2024 10:13:41 +0545 Subject: [PATCH 094/103] Update tcp_intermediate_o.py --- .../connection/transport/tcp/tcp_intermediate_o.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyrogram/connection/transport/tcp/tcp_intermediate_o.py b/pyrogram/connection/transport/tcp/tcp_intermediate_o.py index 48b2d44520..3f47bdfe0a 100644 --- a/pyrogram/connection/transport/tcp/tcp_intermediate_o.py +++ b/pyrogram/connection/transport/tcp/tcp_intermediate_o.py @@ -19,10 +19,10 @@ import logging import os from struct import pack, unpack -from typing import Optional +from typing import Optional, Tuple from pyrogram.crypto import aes -from .tcp import TCP +from .tcp import TCP, Proxy log = logging.getLogger(__name__) @@ -30,13 +30,13 @@ class TCPIntermediateO(TCP): RESERVED = (b"HEAD", b"POST", b"GET ", b"OPTI", b"\xee" * 4) - def __init__(self, ipv6: bool, proxy: dict): + def __init__(self, ipv6: bool, proxy: Proxy) -> None: super().__init__(ipv6, proxy) self.encrypt = None self.decrypt = None - async def connect(self, address: tuple): + async def connect(self, address: Tuple[str, int]) -> None: await super().connect(address) while True: @@ -55,7 +55,7 @@ async def connect(self, address: tuple): await super().send(nonce) - async def send(self, data: bytes, *args): + async def send(self, data: bytes, *args) -> None: await super().send( aes.ctr256_encrypt( pack(" Date: Wed, 26 Jun 2024 10:16:49 +0545 Subject: [PATCH 095/103] Implement non-blocking TCP connection ( --- pyrogram/session/auth.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/pyrogram/session/auth.py b/pyrogram/session/auth.py index d51e18f843..f91f9b6377 100644 --- a/pyrogram/session/auth.py +++ b/pyrogram/session/auth.py @@ -22,6 +22,7 @@ from hashlib import sha1 from io import BytesIO from os import urandom +from typing import Optional import pyrogram from pyrogram import raw @@ -37,13 +38,21 @@ class Auth: MAX_RETRIES = 5 - def __init__(self, client: "pyrogram.Client", dc_id: int, test_mode: bool): + def __init__( + self, + client: "pyrogram.Client", + dc_id: int, + test_mode: bool + ): self.dc_id = dc_id self.test_mode = test_mode self.ipv6 = client.ipv6 + self.alt_port = client.alt_port self.proxy = client.proxy + self.connection_factory = client.connection_factory + self.protocol_factory = client.protocol_factory - self.connection = None + self.connection: Optional[Connection] = None @staticmethod def pack(data: TLObject) -> bytes: @@ -76,7 +85,15 @@ async def create(self): # The server may close the connection at any time, causing the auth key creation to fail. # If that happens, just try again up to MAX_RETRIES times. while True: - self.connection = Connection(self.dc_id, self.test_mode, self.ipv6, self.proxy) + self.connection = self.connection_factory( + dc_id=self.dc_id, + test_mode=self.test_mode, + ipv6=self.ipv6, + alt_port=self.alt_port, + proxy=self.proxy, + media=False, + protocol_factory=self.protocol_factory + ) try: log.info("Start creating a new auth key on DC%s", self.dc_id) @@ -278,4 +295,4 @@ async def create(self): else: return auth_key finally: - self.connection.close() + await self.connection.close() From 7532b1f6333d2e5b6bcd1cda6e49bc136ee8709c Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Wed, 26 Jun 2024 10:19:28 +0545 Subject: [PATCH 096/103] Implement non-blocking TCP connection ( --- pyrogram/session/session.py | 139 +++++++++++++++++++++++++----------- 1 file changed, 98 insertions(+), 41 deletions(-) diff --git a/pyrogram/session/session.py b/pyrogram/session/session.py index 5135af6987..abca955eab 100644 --- a/pyrogram/session/session.py +++ b/pyrogram/session/session.py @@ -16,23 +16,28 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . + import asyncio +import bisect import logging import os from hashlib import sha1 from io import BytesIO +from typing import Optional import pyrogram from pyrogram import raw from pyrogram.connection import Connection from pyrogram.crypto import mtproto from pyrogram.errors import ( - RPCError, InternalServerError, AuthKeyDuplicated, FloodWait, ServiceUnavailable, BadMsgNotification, + RPCError, InternalServerError, AuthKeyDuplicated, + FloodWait, FloodPremiumWait, + ServiceUnavailable, BadMsgNotification, SecurityCheckMismatch ) from pyrogram.raw.all import layer from pyrogram.raw.core import TLObject, MsgContainer, Int, FutureSalts -from .internals import MsgFactory +from .internals import MsgId, MsgFactory log = logging.getLogger(__name__) @@ -44,12 +49,19 @@ def __init__(self): class Session: - START_TIMEOUT = 1 + START_TIMEOUT = 2 WAIT_TIMEOUT = 15 SLEEP_THRESHOLD = 10 - MAX_RETRIES = 5 - ACKS_THRESHOLD = 8 + MAX_RETRIES = 10 + ACKS_THRESHOLD = 10 PING_INTERVAL = 5 + STORED_MSG_IDS_MAX_SIZE = 500 + + TRANSPORT_ERRORS = { + 404: "auth key not found", + 429: "transport flood", + 444: "invalid DC" + } def __init__( self, @@ -67,7 +79,7 @@ def __init__( self.is_media = is_media self.is_cdn = is_cdn - self.connection = None + self.connection: Optional[Connection] = None self.auth_key_id = sha1(auth_key).digest()[-8:] @@ -93,12 +105,14 @@ def __init__( async def start(self): while True: - self.connection = Connection( - self.dc_id, - self.test_mode, - self.client.ipv6, - self.client.proxy, - self.is_media + self.connection = self.client.connection_factory( + dc_id=self.dc_id, + test_mode=self.test_mode, + ipv6=self.client.ipv6, + alt_port=self.client.alt_port, + proxy=self.client.proxy, + media=self.is_media, + protocol_factory=self.client.protocol_factory ) try: @@ -149,6 +163,8 @@ async def start(self): async def stop(self): self.is_started.clear() + self.stored_msg_ids.clear() + self.ping_task_event.set() if self.ping_task is not None: @@ -156,14 +172,11 @@ async def stop(self): self.ping_task_event.clear() - self.connection.close() + await self.connection.close() if self.recv_task: await self.recv_task - for i in self.results.values(): - i.event.set() - if not self.is_media and callable(self.client.disconnect_handler): try: await self.client.disconnect_handler(self.client) @@ -177,19 +190,14 @@ async def restart(self): await self.start() async def handle_packet(self, packet): - try: - data = await self.loop.run_in_executor( - pyrogram.crypto_executor, - mtproto.unpack, - BytesIO(packet), - self.session_id, - self.auth_key, - self.auth_key_id, - self.stored_msg_ids - ) - except SecurityCheckMismatch as e: - log.warning("Discarding packet: %s", e) - return + data = await self.loop.run_in_executor( + pyrogram.crypto_executor, + mtproto.unpack, + BytesIO(packet), + self.session_id, + self.auth_key, + self.auth_key_id + ) messages = ( data.body.messages @@ -206,6 +214,33 @@ async def handle_packet(self, packet): else: self.pending_acks.add(msg.msg_id) + try: + if len(self.stored_msg_ids) > Session.STORED_MSG_IDS_MAX_SIZE: + del self.stored_msg_ids[:Session.STORED_MSG_IDS_MAX_SIZE // 2] + + if self.stored_msg_ids: + if msg.msg_id < self.stored_msg_ids[0]: + raise SecurityCheckMismatch("The msg_id is lower than all the stored values") + + if msg.msg_id in self.stored_msg_ids: + raise SecurityCheckMismatch("The msg_id is equal to any of the stored values") + + time_diff = (msg.msg_id - MsgId()) / 2 ** 32 + + if time_diff > 30: + raise SecurityCheckMismatch("The msg_id belongs to over 30 seconds in the future. " + "Most likely the client time has to be synchronized.") + + if time_diff < -300: + raise SecurityCheckMismatch("The msg_id belongs to over 300 seconds in the past. " + "Most likely the client time has to be synchronized.") + except SecurityCheckMismatch as e: + log.info("Discarding packet: %s", e) + await self.connection.close() + return + else: + bisect.insort(self.stored_msg_ids, msg.msg_id) + if isinstance(msg.body, (raw.types.MsgDetailedInfo, raw.types.MsgNewDetailedInfo)): self.pending_acks.add(msg.body.answer_msg_id) continue @@ -256,7 +291,10 @@ async def ping_worker(self): ping_id=0, disconnect_delay=self.WAIT_TIMEOUT + 10 ), False ) - except (OSError, RPCError): + except OSError: + self.loop.create_task(self.restart()) + break + except RPCError: pass log.info("PingTask stopped") @@ -269,7 +307,12 @@ async def recv_worker(self): if packet is None or len(packet) == 4: if packet: - log.warning('Server sent "%s"', Int.read(BytesIO(packet))) + error_code = -Int.read(BytesIO(packet)) + + log.warning( + "Server sent transport error: %s (%s)", + error_code, Session.TRANSPORT_ERRORS.get(error_code, "unknown error") + ) if self.is_started.is_set(): self.loop.create_task(self.restart()) @@ -280,7 +323,7 @@ async def recv_worker(self): log.info("NetworkTask stopped") - async def send(self, data: TLObject, wait_response: bool = True, timeout: float = WAIT_TIMEOUT): + async def send(self, data: TLObject, wait_response: bool = True, timeout: float = WAIT_TIMEOUT, retry: int = 0): message = self.msg_factory(data) msg_id = message.msg_id @@ -310,23 +353,37 @@ async def send(self, data: TLObject, wait_response: bool = True, timeout: float await asyncio.wait_for(self.results[msg_id].event.wait(), timeout) except asyncio.TimeoutError: pass - finally: - result = self.results.pop(msg_id).value + + result = self.results.pop(msg_id).value if result is None: raise TimeoutError("Request timed out") - elif isinstance(result, raw.types.RpcError): + + if 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, raw.types.BadMsgNotification): - raise BadMsgNotification(result.error_code) - elif isinstance(result, raw.types.BadServerSalt): + + if isinstance(result, raw.types.BadMsgNotification): + if retry > 1: + raise BadMsgNotification(result.error_code) + + self._handle_bad_notification() + await self.send(data, wait_response, timeout, retry + 1) + + if isinstance(result, raw.types.BadServerSalt): self.salt = result.new_server_salt return await self.send(data, wait_response, timeout) - else: - return result + + return result + + def _handle_bad_notification(self): + new_msg_id = MsgId() + if self.stored_msg_ids[len(self.stored_msg_ids)-1] >= new_msg_id: + new_msg_id = self.stored_msg_ids[len(self.stored_msg_ids)-1] + 4 + log.debug("Changing msg_id old=%s new=%s", self.stored_msg_ids[len(self.stored_msg_ids)-1], new_msg_id) + self.stored_msg_ids[len(self.stored_msg_ids)-1] = new_msg_id async def invoke( self, @@ -350,7 +407,7 @@ async def invoke( while True: try: return await self.send(query, timeout=timeout) - except FloodWait as e: + except (FloodWait, FloodPremiumWait) as e: amount = e.value if amount > sleep_threshold >= 0: From 7b4101c999ac273589056831fee0748d0d837a8e Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Wed, 26 Jun 2024 10:25:33 +0545 Subject: [PATCH 097/103] Implement non-blocking TCP connection ( --- pyrogram/client.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pyrogram/client.py b/pyrogram/client.py index 63e4b47273..f60ad63fb8 100644 --- a/pyrogram/client.py +++ b/pyrogram/client.py @@ -31,7 +31,7 @@ from io import StringIO, BytesIO from mimetypes import MimeTypes from pathlib import Path -from typing import Union, List, Optional, Callable, AsyncGenerator +from typing import Union, List, Optional, Callable, AsyncGenerator, Type import pyrogram from pyrogram import __version__, __license__ @@ -51,6 +51,8 @@ from pyrogram.storage import FileStorage, MemoryStorage from pyrogram.types import User, TermsOfService from pyrogram.utils import ainput +from .connection import Connection +from .connection.transport import TCP, TCPAbridged from .dispatcher import Dispatcher from .file_id import FileId, FileType, ThumbnailSource from .mime_types import mime_types @@ -251,6 +253,9 @@ def __init__( else: self.storage = FileStorage(self.name, self.workdir) + self.connection_factory = Connection + self.protocol_factory = TCPAbridged + self.dispatcher = Dispatcher(self) self.rnd_id = MsgId From 70620a18a046848422cb9ddf1b3b2ab3d5b98fda Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Wed, 26 Jun 2024 10:27:38 +0545 Subject: [PATCH 098/103] =?UTF-8?q?Update=20Pyrogram=202.2.2=20?= =?UTF-8?q?=F0=9F=94=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyrogram/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py index 63db62ead1..a0d9ce7848 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__ = "2.2.1" +__version__ = "2.2.2" __license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)" __copyright__ = "Copyright (C) 2017-present Dan " From eea9f125e6082206eb524598857d71a1bc5bb14a Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:10:40 +0545 Subject: [PATCH 099/103] Implement non-blocking TCP connection ( --- pyrogram/session/session.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyrogram/session/session.py b/pyrogram/session/session.py index abca955eab..3aaadf563d 100644 --- a/pyrogram/session/session.py +++ b/pyrogram/session/session.py @@ -31,7 +31,7 @@ from pyrogram.crypto import mtproto from pyrogram.errors import ( RPCError, InternalServerError, AuthKeyDuplicated, - FloodWait, FloodPremiumWait, + FloodWait, ServiceUnavailable, BadMsgNotification, SecurityCheckMismatch ) @@ -407,7 +407,7 @@ async def invoke( while True: try: return await self.send(query, timeout=timeout) - except (FloodWait, FloodPremiumWait) as e: + except (FloodWait) as e: amount = e.value if amount > sleep_threshold >= 0: From 32bf0f2e296c1b03c3cf20bbc81e5497f7bb3470 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:28:42 +0545 Subject: [PATCH 100/103] Update session.py --- pyrogram/session/session.py | 139 +++++++++++------------------------- 1 file changed, 41 insertions(+), 98 deletions(-) diff --git a/pyrogram/session/session.py b/pyrogram/session/session.py index 3aaadf563d..5135af6987 100644 --- a/pyrogram/session/session.py +++ b/pyrogram/session/session.py @@ -16,28 +16,23 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . - import asyncio -import bisect import logging import os from hashlib import sha1 from io import BytesIO -from typing import Optional import pyrogram from pyrogram import raw from pyrogram.connection import Connection from pyrogram.crypto import mtproto from pyrogram.errors import ( - RPCError, InternalServerError, AuthKeyDuplicated, - FloodWait, - ServiceUnavailable, BadMsgNotification, + RPCError, InternalServerError, AuthKeyDuplicated, FloodWait, ServiceUnavailable, BadMsgNotification, SecurityCheckMismatch ) from pyrogram.raw.all import layer from pyrogram.raw.core import TLObject, MsgContainer, Int, FutureSalts -from .internals import MsgId, MsgFactory +from .internals import MsgFactory log = logging.getLogger(__name__) @@ -49,19 +44,12 @@ def __init__(self): class Session: - START_TIMEOUT = 2 + START_TIMEOUT = 1 WAIT_TIMEOUT = 15 SLEEP_THRESHOLD = 10 - MAX_RETRIES = 10 - ACKS_THRESHOLD = 10 + MAX_RETRIES = 5 + ACKS_THRESHOLD = 8 PING_INTERVAL = 5 - STORED_MSG_IDS_MAX_SIZE = 500 - - TRANSPORT_ERRORS = { - 404: "auth key not found", - 429: "transport flood", - 444: "invalid DC" - } def __init__( self, @@ -79,7 +67,7 @@ def __init__( self.is_media = is_media self.is_cdn = is_cdn - self.connection: Optional[Connection] = None + self.connection = None self.auth_key_id = sha1(auth_key).digest()[-8:] @@ -105,14 +93,12 @@ def __init__( async def start(self): while True: - self.connection = self.client.connection_factory( - dc_id=self.dc_id, - test_mode=self.test_mode, - ipv6=self.client.ipv6, - alt_port=self.client.alt_port, - proxy=self.client.proxy, - media=self.is_media, - protocol_factory=self.client.protocol_factory + self.connection = Connection( + self.dc_id, + self.test_mode, + self.client.ipv6, + self.client.proxy, + self.is_media ) try: @@ -163,8 +149,6 @@ async def start(self): async def stop(self): self.is_started.clear() - self.stored_msg_ids.clear() - self.ping_task_event.set() if self.ping_task is not None: @@ -172,11 +156,14 @@ async def stop(self): self.ping_task_event.clear() - await self.connection.close() + self.connection.close() if self.recv_task: await self.recv_task + for i in self.results.values(): + i.event.set() + if not self.is_media and callable(self.client.disconnect_handler): try: await self.client.disconnect_handler(self.client) @@ -190,14 +177,19 @@ async def restart(self): await self.start() async def handle_packet(self, packet): - data = await self.loop.run_in_executor( - pyrogram.crypto_executor, - mtproto.unpack, - BytesIO(packet), - self.session_id, - self.auth_key, - self.auth_key_id - ) + try: + data = await self.loop.run_in_executor( + pyrogram.crypto_executor, + mtproto.unpack, + BytesIO(packet), + self.session_id, + self.auth_key, + self.auth_key_id, + self.stored_msg_ids + ) + except SecurityCheckMismatch as e: + log.warning("Discarding packet: %s", e) + return messages = ( data.body.messages @@ -214,33 +206,6 @@ async def handle_packet(self, packet): else: self.pending_acks.add(msg.msg_id) - try: - if len(self.stored_msg_ids) > Session.STORED_MSG_IDS_MAX_SIZE: - del self.stored_msg_ids[:Session.STORED_MSG_IDS_MAX_SIZE // 2] - - if self.stored_msg_ids: - if msg.msg_id < self.stored_msg_ids[0]: - raise SecurityCheckMismatch("The msg_id is lower than all the stored values") - - if msg.msg_id in self.stored_msg_ids: - raise SecurityCheckMismatch("The msg_id is equal to any of the stored values") - - time_diff = (msg.msg_id - MsgId()) / 2 ** 32 - - if time_diff > 30: - raise SecurityCheckMismatch("The msg_id belongs to over 30 seconds in the future. " - "Most likely the client time has to be synchronized.") - - if time_diff < -300: - raise SecurityCheckMismatch("The msg_id belongs to over 300 seconds in the past. " - "Most likely the client time has to be synchronized.") - except SecurityCheckMismatch as e: - log.info("Discarding packet: %s", e) - await self.connection.close() - return - else: - bisect.insort(self.stored_msg_ids, msg.msg_id) - if isinstance(msg.body, (raw.types.MsgDetailedInfo, raw.types.MsgNewDetailedInfo)): self.pending_acks.add(msg.body.answer_msg_id) continue @@ -291,10 +256,7 @@ async def ping_worker(self): ping_id=0, disconnect_delay=self.WAIT_TIMEOUT + 10 ), False ) - except OSError: - self.loop.create_task(self.restart()) - break - except RPCError: + except (OSError, RPCError): pass log.info("PingTask stopped") @@ -307,12 +269,7 @@ async def recv_worker(self): if packet is None or len(packet) == 4: if packet: - error_code = -Int.read(BytesIO(packet)) - - log.warning( - "Server sent transport error: %s (%s)", - error_code, Session.TRANSPORT_ERRORS.get(error_code, "unknown error") - ) + log.warning('Server sent "%s"', Int.read(BytesIO(packet))) if self.is_started.is_set(): self.loop.create_task(self.restart()) @@ -323,7 +280,7 @@ async def recv_worker(self): log.info("NetworkTask stopped") - async def send(self, data: TLObject, wait_response: bool = True, timeout: float = WAIT_TIMEOUT, retry: int = 0): + async def send(self, data: TLObject, wait_response: bool = True, timeout: float = WAIT_TIMEOUT): message = self.msg_factory(data) msg_id = message.msg_id @@ -353,37 +310,23 @@ async def send(self, data: TLObject, wait_response: bool = True, timeout: float await asyncio.wait_for(self.results[msg_id].event.wait(), timeout) except asyncio.TimeoutError: pass - - result = self.results.pop(msg_id).value + finally: + result = self.results.pop(msg_id).value if result is None: raise TimeoutError("Request timed out") - - if isinstance(result, raw.types.RpcError): + elif isinstance(result, raw.types.RpcError): if isinstance(data, (raw.functions.InvokeWithoutUpdates, raw.functions.InvokeWithTakeout)): data = data.query RPCError.raise_it(result, type(data)) - - if isinstance(result, raw.types.BadMsgNotification): - if retry > 1: - raise BadMsgNotification(result.error_code) - - self._handle_bad_notification() - await self.send(data, wait_response, timeout, retry + 1) - - if isinstance(result, raw.types.BadServerSalt): + elif isinstance(result, raw.types.BadMsgNotification): + raise BadMsgNotification(result.error_code) + elif isinstance(result, raw.types.BadServerSalt): self.salt = result.new_server_salt return await self.send(data, wait_response, timeout) - - return result - - def _handle_bad_notification(self): - new_msg_id = MsgId() - if self.stored_msg_ids[len(self.stored_msg_ids)-1] >= new_msg_id: - new_msg_id = self.stored_msg_ids[len(self.stored_msg_ids)-1] + 4 - log.debug("Changing msg_id old=%s new=%s", self.stored_msg_ids[len(self.stored_msg_ids)-1], new_msg_id) - self.stored_msg_ids[len(self.stored_msg_ids)-1] = new_msg_id + else: + return result async def invoke( self, @@ -407,7 +350,7 @@ async def invoke( while True: try: return await self.send(query, timeout=timeout) - except (FloodWait) as e: + except FloodWait as e: amount = e.value if amount > sleep_threshold >= 0: From 5a4d5cf028c2fea3600010fb1bac362b9ed5030b Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:29:16 +0545 Subject: [PATCH 101/103] Update auth.py --- pyrogram/session/auth.py | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/pyrogram/session/auth.py b/pyrogram/session/auth.py index f91f9b6377..d51e18f843 100644 --- a/pyrogram/session/auth.py +++ b/pyrogram/session/auth.py @@ -22,7 +22,6 @@ from hashlib import sha1 from io import BytesIO from os import urandom -from typing import Optional import pyrogram from pyrogram import raw @@ -38,21 +37,13 @@ class Auth: MAX_RETRIES = 5 - def __init__( - self, - client: "pyrogram.Client", - dc_id: int, - test_mode: bool - ): + def __init__(self, client: "pyrogram.Client", dc_id: int, test_mode: bool): self.dc_id = dc_id self.test_mode = test_mode self.ipv6 = client.ipv6 - self.alt_port = client.alt_port self.proxy = client.proxy - self.connection_factory = client.connection_factory - self.protocol_factory = client.protocol_factory - self.connection: Optional[Connection] = None + self.connection = None @staticmethod def pack(data: TLObject) -> bytes: @@ -85,15 +76,7 @@ async def create(self): # The server may close the connection at any time, causing the auth key creation to fail. # If that happens, just try again up to MAX_RETRIES times. while True: - self.connection = self.connection_factory( - dc_id=self.dc_id, - test_mode=self.test_mode, - ipv6=self.ipv6, - alt_port=self.alt_port, - proxy=self.proxy, - media=False, - protocol_factory=self.protocol_factory - ) + self.connection = Connection(self.dc_id, self.test_mode, self.ipv6, self.proxy) try: log.info("Start creating a new auth key on DC%s", self.dc_id) @@ -295,4 +278,4 @@ async def create(self): else: return auth_key finally: - await self.connection.close() + self.connection.close() From 833e960a64173b35e412d4f830d58cd76204b843 Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:38:47 +0545 Subject: [PATCH 102/103] Implement non-blocking TCP connection ( --- pyrogram/session/session.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/pyrogram/session/session.py b/pyrogram/session/session.py index 5135af6987..c345f39512 100644 --- a/pyrogram/session/session.py +++ b/pyrogram/session/session.py @@ -21,7 +21,7 @@ import os from hashlib import sha1 from io import BytesIO - +from typing import Optional import pyrogram from pyrogram import raw from pyrogram.connection import Connection @@ -67,7 +67,7 @@ def __init__( self.is_media = is_media self.is_cdn = is_cdn - self.connection = None + self.connection: Optional[Connection] = None self.auth_key_id = sha1(auth_key).digest()[-8:] @@ -93,12 +93,14 @@ def __init__( async def start(self): while True: - self.connection = Connection( - self.dc_id, - self.test_mode, - self.client.ipv6, - self.client.proxy, - self.is_media + self.connection = self.client.connection_factory( + dc_id=self.dc_id, + test_mode=self.test_mode, + ipv6=self.client.ipv6, + alt_port=self.client.alt_port, + proxy=self.client.proxy, + media=self.is_media, + protocol_factory=self.client.protocol_factory ) try: From 725a64f31a86ea102aaee49cc93c6dc293c5f42f Mon Sep 17 00:00:00 2001 From: Rkn Developer <138338185+RknDeveloper@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:56:03 +0545 Subject: [PATCH 103/103] Implement non-blocking TCP connection ( --- pyrogram/session/auth.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/pyrogram/session/auth.py b/pyrogram/session/auth.py index d51e18f843..8c01211926 100644 --- a/pyrogram/session/auth.py +++ b/pyrogram/session/auth.py @@ -22,6 +22,7 @@ from hashlib import sha1 from io import BytesIO from os import urandom +from typing import Optional import pyrogram from pyrogram import raw @@ -37,13 +38,21 @@ class Auth: MAX_RETRIES = 5 - def __init__(self, client: "pyrogram.Client", dc_id: int, test_mode: bool): + def __init__( + self, + client: "pyrogram.Client", + dc_id: int, + test_mode: bool + ): self.dc_id = dc_id self.test_mode = test_mode self.ipv6 = client.ipv6 + self.alt_port = client.alt_port self.proxy = client.proxy + self.connection_factory = client.connection_factory + self.protocol_factory = client.protocol_factory - self.connection = None + self.connection: Optional[Connection] = None @staticmethod def pack(data: TLObject) -> bytes: @@ -76,7 +85,15 @@ async def create(self): # The server may close the connection at any time, causing the auth key creation to fail. # If that happens, just try again up to MAX_RETRIES times. while True: - self.connection = Connection(self.dc_id, self.test_mode, self.ipv6, self.proxy) + self.connection = self.connection_factory( + dc_id=self.dc_id, + test_mode=self.test_mode, + ipv6=self.ipv6, + alt_port=self.alt_port, + proxy=self.proxy, + media=False, + protocol_factory=self.protocol_factory + ) try: log.info("Start creating a new auth key on DC%s", self.dc_id)